diff --git a/blr/blobs_service.go b/blr/blobs_service.go index 401fc97e..d3151c49 100644 --- a/blr/blobs_service.go +++ b/blr/blobs_service.go @@ -24,21 +24,22 @@ type Blob struct { ID string `json:"id,omitempty"` DataType string `json:"dataType" validate:"required"` Guid string `json:"guid,omitempty"` - Tags *[]Tag `json:"tags,omitempty" validate:"max=10"` + Tags *[]Tag `json:"tags,omitempty" validate:"omitempty,max=10"` AutoGenerateBlobPathName bool `json:"autoGenerateBlobPathName"` - BlobPath string `json:"blobPath" validate:"required"` - BlobName string `json:"blobName" validate:"required"` - VirtualPath string `json:"virtualPath" validate:"required"` - VirtualName string `json:"virtualName" validate:"required"` + BlobPath string `json:"blobPath,omitempty" validate:"omitempty"` + BlobName string `json:"blobName,omitempty" validate:"omitempty"` + VirtualPath string `json:"virtualPath,omitempty" validate:"omitempty"` + VirtualName string `json:"virtualName,omitempty" validate:"omitempty"` Bucket string `json:"bucket,omitempty"` - Creation string `json:"creation,omitempty"` + Creation *string `json:"creation,omitempty"` CreatedBy string `json:"createdBy,omitempty"` Attachment *Attachment `json:"attachment,omitempty"` UploadOnBehalf bool `json:"uploadOnBehalf"` ManagingOrganization string `json:"managingOrganization,omitempty"` PropositionGuid string `json:"propositionGuid,omitempty"` MultipartEnabled bool `json:"multipartEnabled"` - NoOfParts int `json:"noOfParts"` + NoOfParts *int `json:"noOfParts,omitempty"` + State *string `json:"state,omitempty"` Meta *Meta `json:"meta,omitempty"` } @@ -79,7 +80,8 @@ type GetBlobOptions struct { } func (b *BlobsService) Create(blob Blob) (*Blob, *Response, error) { - blob.ResourceType = "Bucket" + blob.ResourceType = "Blob" + blob.AutoGenerateBlobPathName = true if err := b.validate.Struct(blob); err != nil { return nil, nil, err } diff --git a/blr/blobs_service_test.go b/blr/blobs_service_test.go new file mode 100644 index 00000000..c551c2b8 --- /dev/null +++ b/blr/blobs_service_test.go @@ -0,0 +1,92 @@ +package blr_test + +import ( + "fmt" + "io" + "net/http" + "testing" + + "github.com/philips-software/go-hsdp-api/blr" + "github.com/stretchr/testify/assert" +) + +func blobBody(id, dataType, state string) string { + return fmt.Sprintf(`{ + "resourceType": "Blob", + "meta": { + "lastUpdated": "2022-05-25T19:36:10Z", + "versionId": "1" + }, + "id": "%s", + "dataType": "%s", + "autoGenerateBlobPathName": true, + "bucket": "bucket-exact-moose", + "blobPath": "dae89cf0-888d-4a26-8c1d-578e97365efc/64e403e6-d215-457a-bf12-2a4f49038208/tf-exact-moose/9b6f1d8a-0967-42d8-9622-d30c877c9da4/2022/05/25", + "blobName": "74f78808-10d2-4199-92cf-e112bd9ff4de-19_36_10.bin", + "createdBy": "9b6f1d8a-0967-42d8-9622-d30c877c9da4", + "dataAccessUrl": "https://pre-signed.upload.url.com/something?x-amz-server-side-encryption=AES256", + "dataAccessUrlExpiry": "2022-05-25T19:41:10.677Z", + "creation": "2022-05-25T19:36:10Z", + "multipartEnabled": false, + "uploadOnBehalf": false, + "managingOrganization": "dae89cf0-888d-4a26-8c1d-578e97365efc", + "propositionGuid": "64e403e6-d215-457a-bf12-2a4f49038208", + "state": "%s" +}`, id, dataType, state) +} + +func TestBlobCRUD(t *testing.T) { + teardown := setup(t) + defer teardown() + + blobID := "dbf1d779-ab9f-4c27-b4aa-ea75f9efbbc1" + dataType := "tf-exact-moose" + muxBLR.HandleFunc("/connect/blobrepository/Blob", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + switch r.Method { + case "POST": + w.Header().Set("Etag", "1") + w.WriteHeader(http.StatusCreated) + _, _ = io.WriteString(w, blobBody(blobID, dataType, "uploading")) + } + }) + muxBLR.HandleFunc("/connect/blobrepository/Blob/"+blobID, func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + switch r.Method { + case "GET": + w.WriteHeader(http.StatusOK) + _, _ = io.WriteString(w, blobBody(blobID, dataType, "uploading")) + case "PUT": + w.WriteHeader(http.StatusOK) + _, _ = io.WriteString(w, blobBody(blobID, dataType, "uploading")) + case "DELETE": + w.WriteHeader(http.StatusNoContent) + } + }) + + created, resp, err := blrClient.Blobs.Create(blr.Blob{ + DataType: dataType, + }) + if !assert.Nil(t, err) { + return + } + if !assert.NotNil(t, resp) { + return + } + if !assert.NotNil(t, created) { + return + } + assert.Equal(t, dataType, created.DataType) + assert.Equal(t, blobID, created.ID) + assert.NotNil(t, created.State) + + res, resp, err := blrClient.Blobs.Delete(*created) + if !assert.Nil(t, err) { + return + } + if !assert.NotNil(t, resp) { + return + } + assert.True(t, res) + assert.Equal(t, http.StatusNoContent, resp.StatusCode) +} diff --git a/blr/client.go b/blr/client.go index e6d1ce23..fa016927 100644 --- a/blr/client.go +++ b/blr/client.go @@ -4,6 +4,7 @@ package blr import ( "bytes" "encoding/json" + "fmt" "io" "io/ioutil" "net/http" @@ -43,24 +44,24 @@ type Client struct { config *Config baseURL *url.URL - // User agent used when communicating with the HSDP Notification API + // User agent used when communicating with the HSDP Blob Repository API UserAgent string - systemIDM string - systemIAM string - debugFile *os.File validate *validator.Validate Blobs *BlobsService } -// NewClient returns a new Discovery client +// NewClient returns a new BLR client func NewClient(iamClient *iam.Client, config *Config) (*Client, error) { validate := validator.New() if err := validate.Struct(config); err != nil { return nil, err } + if iamClient == nil { + return nil, fmt.Errorf("iamClient cannot be nil") + } doAutoconf(config) c := &Client{Client: iamClient, config: config, UserAgent: userAgent, validate: validator.New()} @@ -68,13 +69,6 @@ func NewClient(iamClient *iam.Client, config *Config) (*Client, error) { return nil, err } - if baseIDM := c.BaseIDMURL(); baseIDM != nil { - c.systemIDM = baseIDM.String() + "/authorize/identity" - } - if baseIAM := c.BaseIAMURL(); baseIAM != nil { - c.systemIAM = baseIAM.String() - } - c.Blobs = &BlobsService{Client: c, validate: validator.New()} return c, nil @@ -184,8 +178,8 @@ func (c *Client) NewRequest(method, requestPath string, opt interface{}, options return req, nil } -// Response is a HSDP IAM API response. This wraps the standard http.Response -// returned from HSDP IAM and provides convenient access to things like errors +// Response is a HSDP BLR API response. This wraps the standard http.Response +// returned from HSDP BLR and provides convenient access to things like errors type Response struct { *http.Response } @@ -215,7 +209,9 @@ func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) { } if v != nil { - defer resp.Body.Close() // Only close if we plan to read it + defer func() { + _ = resp.Body.Close() + }() // Only close if we plan to read it if w, ok := v.(io.Writer); ok { _, err = io.Copy(w, resp.Body) } else { diff --git a/blr/client_test.go b/blr/client_test.go index 213ff2f5..95502d34 100644 --- a/blr/client_test.go +++ b/blr/client_test.go @@ -8,7 +8,7 @@ import ( _ "os" "testing" - "github.com/philips-software/go-hsdp-api/connect/mdm" + "github.com/philips-software/go-hsdp-api/blr" "github.com/philips-software/go-hsdp-api/iam" "github.com/stretchr/testify/assert" ) @@ -16,18 +16,18 @@ import ( var ( muxIAM *http.ServeMux serverIAM *httptest.Server - muxMDM *http.ServeMux - serverMDM *httptest.Server + muxBLR *http.ServeMux + serverBLR *httptest.Server iamClient *iam.Client - mdmClient *mdm.Client + blrClient *blr.Client ) func setup(t *testing.T) func() { muxIAM = http.NewServeMux() serverIAM = httptest.NewServer(muxIAM) - muxMDM = http.NewServeMux() - serverMDM = httptest.NewServer(muxMDM) + muxBLR = http.NewServeMux() + serverBLR = httptest.NewServer(muxBLR) var err error @@ -37,13 +37,13 @@ func setup(t *testing.T) func() { SharedKey: "SharedKey", SecretKey: "SecretKey", IAMURL: serverIAM.URL, - IDMURL: serverMDM.URL, + IDMURL: serverBLR.URL, }) if err != nil { - t.Fatalf("Failed to create iamCleitn: %v", err) + t.Fatalf("Failed to create iamClient: %v", err) } - mdmClient, err = mdm.NewClient(iamClient, &mdm.Config{ - BaseURL: serverMDM.URL + "/connect/mdm", + blrClient, err = blr.NewClient(iamClient, &blr.Config{ + BaseURL: serverBLR.URL + "/connect/blobrepository", }) if err != nil { t.Fatalf("Failed to create mdmClient: %v", err) @@ -132,7 +132,7 @@ func setup(t *testing.T) func() { return func() { serverIAM.Close() - serverMDM.Close() + serverBLR.Close() } }