diff --git a/Dockerfile b/Dockerfile index c40b9f6..6fb7677 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # 빌드 및 실행 단계 -FROM golang:1.23 +FROM golang:1.24 # 필수 패키지 설치 (libvirt 개발 패키지 포함) RUN apt-get update && apt-get install -y \ diff --git a/client/rustfs.go b/client/rustfs.go new file mode 100644 index 0000000..50de646 --- /dev/null +++ b/client/rustfs.go @@ -0,0 +1,113 @@ +package client + +import ( + "context" + "os" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/s3" +) + +type RustFSClient struct { + client *s3.Client +} + +// Currently RustFSClient has solid s3.Client as its field, +// when logic get complex and needs for mocking arise, replace it with interface + +func NewRustFSClient() (*RustFSClient, error) { + endpoint := os.Getenv("RUSTFS_ENDPOINT") + if endpoint == "" { + endpoint = "http://localhost:9001" + } + accessKey := os.Getenv("RUSTFS_ACCESS_KEY") + if accessKey == "" { + accessKey = "minioadmin" + } + secretKey := os.Getenv("RUSTFS_SECRET_KEY") + if secretKey == "" { + secretKey = "minioadmin" + } + //TODO: replace unstable accesskey override when testing with proper method + + cfg, err := config.LoadDefaultConfig(context.Background(), + config.WithRegion("us-east-1"), + config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")), + ) + if err != nil { + return nil, err + } + + client := s3.NewFromConfig(cfg, func(o *s3.Options) { + o.BaseEndpoint = aws.String(endpoint) + o.UsePathStyle = true + }) + + return &RustFSClient{client: client}, nil +} + +func (c *RustFSClient) ListBuckets(ctx context.Context) ([]string, error) { + out, err := c.client.ListBuckets(ctx, &s3.ListBucketsInput{}) + if err != nil { + return nil, err + } + names := make([]string, len(out.Buckets)) + for i, b := range out.Buckets { + names[i] = aws.ToString(b.Name) + } + return names, nil +} + +func (c *RustFSClient) CreateBucket(ctx context.Context, bucket string) error { + _, err := c.client.CreateBucket(ctx, &s3.CreateBucketInput{ + Bucket: aws.String(bucket), + }) + return err +} + +// / Refer: https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#NewPresignClient +// Direct listing, generating bucket and presigned URL is the role for RustFSClient(control) +// This Presigned url should be passed to Core client, and core should use this url to upload/download file. +// This Presigend related functions are yet not fully tested, so there might be some issues. Please refer to AWS SDK for Go v2 documentation +// +// for more details and examples on how to use the PresignClient. +func (c *RustFSClient) PresignPutObject(ctx context.Context, bucket, key string, expires time.Duration) (string, error) { + presignClient := s3.NewPresignClient(c.client) + req, err := presignClient.PresignPutObject(ctx, &s3.PutObjectInput{ + Bucket: aws.String(bucket), + Key: aws.String(key), + }, s3.WithPresignExpires(expires)) + if err != nil { + return "", err + } + return req.URL, nil +} + +func (c *RustFSClient) PresignGetObject(ctx context.Context, bucket, key string, expires time.Duration) (string, error) { + presignClient := s3.NewPresignClient(c.client) + req, err := presignClient.PresignGetObject(ctx, &s3.GetObjectInput{ + Bucket: aws.String(bucket), + Key: aws.String(key), + }, s3.WithPresignExpires(expires)) + if err != nil { + return "", err + } + return req.URL, nil +} + +// newCLI := &RustFSClient{client: client} +// ctx, cancel := context.WithTimeout(context.Background(), time.Duration(20)*time.Second) +// defer cancel() +// err = newCLI.CreateBucket(ctx, "adsfasdfds") +// err = newCLI.CreateBucket(ctx, "asdfaifdsfn") +// err = newCLI.CreateBucket(ctx, "asdf") +// err = newCLI.CreateBucket(ctx, "zxvc") +// err = newCLI.CreateBucket(ctx, "asdfs") +// bucks, err := newCLI.ListBuckets(ctx) +// fmt.Println(bucks) +// if err != nil { +// fmt.Println(err) +// } diff --git a/go.mod b/go.mod index 43c1b96..014ef18 100755 --- a/go.mod +++ b/go.mod @@ -1,10 +1,14 @@ module github.com/easy-cloud-Knet/KWS_Control -go 1.23.0 +go 1.24 -toolchain go1.23.4 +toolchain go1.24.3 require ( + github.com/aws/aws-sdk-go-v2 v1.41.7 + github.com/aws/aws-sdk-go-v2/config v1.32.18 + github.com/aws/aws-sdk-go-v2/credentials v1.19.17 + github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0 github.com/go-sql-driver/mysql v1.9.2 github.com/redis/go-redis/v9 v9.11.0 github.com/sirupsen/logrus v1.9.3 @@ -15,6 +19,20 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 // indirect + github.com/aws/smithy-go v1.25.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect golang.org/x/sys v0.33.0 // indirect diff --git a/go.sum b/go.sum index d3fa9de..ec267f9 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,41 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/aws/aws-sdk-go-v2 v1.41.7 h1:DWpAJt66FmnnaRIOT/8ASTucrvuDPZASqhhLey6tLY8= +github.com/aws/aws-sdk-go-v2 v1.41.7/go.mod h1:4LAfZOPHNVNQEckOACQx60Y8pSRjIkNZQz1w92xpMJc= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10 h1:gx1AwW1Iyk9Z9dD9F4akX5gnN3QZwUB20GGKH/I+Rho= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10/go.mod h1:qqY157uZoqm5OXq/amuaBJyC9hgBCBQnsaWnPe905GY= +github.com/aws/aws-sdk-go-v2/config v1.32.18 h1:Hcia46bxhGgF3BaSnG8nSNCWmqTK6bj9xN9/FJ3WK6Q= +github.com/aws/aws-sdk-go-v2/config v1.32.18/go.mod h1:zEjCAYmxqDadH1WX8CdBvmLKhUEUVFgKRQG38zjDmrY= +github.com/aws/aws-sdk-go-v2/credentials v1.19.17 h1:gP2nkGsS+KMvF/jfFz2Vv2qiiOqWKyPACSzPsqHgoW8= +github.com/aws/aws-sdk-go-v2/credentials v1.19.17/go.mod h1:Bsew3S/moG5iT77giPj1q8wb/s0RE5/QfH+ASjYtuQc= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 h1:UuSfcORqNSz/ey3VPRS8TcVH2Ikf0/sC+Hdj400QI6U= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23/go.mod h1:+G/OSGiOFnSOkYloKj/9M35s74LgVAdJBSD5lsFfqKg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 h1:GpT/TrnBYuE5gan2cZbTtvP+JlHsutdmlV2YfEyNde0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23/go.mod h1:xYWD6BS9ywC5bS3sz9Xh04whO/hzK2plt2Zkyrp4JuA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 h1:bpd8vxhlQi2r1hiueOw02f/duEPTMK59Q4QMAoTTtTo= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23/go.mod h1:15DfR2nw+CRHIk0tqNyifu3G1YdAOy68RftkhMDDwYk= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 h1:OQqn11BtaYv1WLUowvcA30MpzIu8Ti4pcLPIIyoKZrA= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24/go.mod h1:X5ZJyfwVrWA96GzPmUCWFQaEARPR7gCrpq2E92PJwAE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 h1:FLudkZLt5ci0ozzgkVo8BJGwvqNaZbTWb3UcucAateA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9/go.mod h1:w7wZ/s9qK7c8g4al+UyoF1Sp/Z45UwMGcqIzLWVQHWk= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15 h1:ieLCO1JxUWuxTZ1cRd0GAaeX7O6cIxnwk7tc1LsQhC4= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15/go.mod h1:e3IzZvQ3kAWNykvE0Tr0RDZCMFInMvhku3qNpcIQXhM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 h1:pbrxO/kuIwgEsOPLkaHu0O+m4fNgLU8B3vxQ+72jTPw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23/go.mod h1:/CMNUqoj46HpS3MNRDEDIwcgEnrtZlKRaHNaHxIFpNA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23 h1:03xatSQO4+AM1lTAbnRg5OK528EUg744nW7F73U8DKw= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23/go.mod h1:M8l3mwgx5ToK7wot2sBBce/ojzgnPzZXUV445gTSyE8= +github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0 h1:etqBTKY581iwLL/H/S2sVgk3C9lAsTJFeXWFDsDcWOU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0/go.mod h1:L2dcoOgS2VSgbPLvpak2NyUPsO1TBN7M45Z4H7DlRc4= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 h1:TdJ+HdzOBhU8+iVAOGUTU63VXopcumCOF1paFulHWZc= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.11/go.mod h1:R82ZRExE/nheo0N+T8zHPcLRTcH8MGsnR3BiVGX0TwI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 h1:7byT8HUWrgoRp6sXjxtZwgOKfhss5fW6SkLBtqzgRoE= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.17/go.mod h1:xNWknVi4Ezm1vg1QsB/5EWpAJURq22uqd38U8qKvOJc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.0 h1:nDARhv/oF55bcxF7rCI/4PDxOKnVXVWwDuDwCs2I2SQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.36.0/go.mod h1:4vIRDq+CJB2xFAXZ+YgGUTiEft7oAQlhIs71xcSeuVg= +github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 h1:F/M5Y9I3nwr2IEpshZgh1GeHpOItExNM9L1euNuh/fk= +github.com/aws/aws-sdk-go-v2/service/sts v1.42.1/go.mod h1:mTNxImtovCOEEuD65mKW7DCsL+2gjEH+RPEAexAzAio= +github.com/aws/smithy-go v1.25.1 h1:J8ERsGSU7d+aCmdQur5Txg6bVoYelvQJgtZehD12GkI= +github.com/aws/smithy-go v1.25.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= diff --git a/tests/docker-compose.test.yml b/tests/docker-compose.test.yml index 04348a2..38a6ace 100644 --- a/tests/docker-compose.test.yml +++ b/tests/docker-compose.test.yml @@ -35,6 +35,27 @@ services: timeout: 3s retries: 10 + rustfs-test: + image: rustfs/rustfs:latest + container_name: kws-test-rustfs + ports: + - "19000:9000" + - "19001:9001" + environment: + RUSTFS_ACCESS_KEY: minioadmin + RUSTFS_SECRET_KEY: minioadmin + RUSTFS_VOLUMES: /data/rustfs0 + RUSTFS_OBS_LOG_DIRECTORY: /logs + RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS: "*" + RUSTFS_OBS_LOGGER_LEVEL: warn + RUSTFS_OBS_ENVIRONMENT: production + healthcheck: + test: ["CMD", "nc", "-z", "127.0.0.1", "9000"] + interval: 3s + timeout: 5s + retries: 15 + start_period: 15s + control-test: build: context: .. @@ -58,6 +79,9 @@ services: CORES: mock-core:8080 GUACAMOLE_BASE_URL: http://mock-core:8080/guacamole CMS_HOST: mock-core:8080 + RUSTFS_ENDPOINT: http://rustfs-test:9000 + RUSTFS_ACCESS_KEY: minioadmin + RUSTFS_SECRET_KEY: minioadmin depends_on: mysql-test: condition: service_healthy @@ -65,3 +89,5 @@ services: condition: service_healthy mock-core: condition: service_healthy + rustfs-test: + condition: service_healthy