From 12ba707be6a4df6712797dca48eabd655e11e3a8 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 23 Jan 2024 03:06:19 -0500 Subject: [PATCH 01/21] Template Datasource --- inttests/template_test.go | 47 ++++++++++ template.go | 68 +++++++++++++++ template_test.go | 119 +++++++++++++++++++++++++ types/v1/templateTypes.go | 177 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 411 insertions(+) create mode 100644 inttests/template_test.go create mode 100644 template.go create mode 100644 template_test.go create mode 100644 types/v1/templateTypes.go diff --git a/inttests/template_test.go b/inttests/template_test.go new file mode 100644 index 0000000..41e24ed --- /dev/null +++ b/inttests/template_test.go @@ -0,0 +1,47 @@ +// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package inttests + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetTemplates(t *testing.T) { + templates, err := C.GetAllTemplates() + assert.Nil(t, err) + assert.NotNil(t, templates) +} + +func TestGetTemplateByID(t *testing.T) { + templates, err := C.GetAllTemplates() + assert.Nil(t, err) + assert.NotNil(t, templates) + + if len(templates) > 0 { + template, err := C.GetTemplateByID(templates[0].ID) + assert.Nil(t, err) + assert.NotNil(t, template) + } + + template, err := C.GetTemplateByID(invalidIdentifier) + assert.NotNil(t, err) + assert.Nil(t, template) +} + +func TestGetTemplateByFilters(t *testing.T) { + templates, err := C.GetTemplateByFilters("invalid", "invalid") + assert.NotNil(t, err) + assert.Nil(t, templates) +} diff --git a/template.go b/template.go new file mode 100644 index 0000000..edd6f2e --- /dev/null +++ b/template.go @@ -0,0 +1,68 @@ +// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package goscaleio + +import ( + "errors" + "fmt" + "net/http" + "time" + + types "github.com/dell/goscaleio/types/v1" +) + +// GetTemplateByID gets the node details based on ID +func (c *Client) GetTemplateByID(id string) (*types.TemplateDetails, error) { + defer TimeSpent("GetTemplateByID", time.Now()) + + path := fmt.Sprintf("/Api/V1/template/%v", id) + + var template types.TemplateDetails + err := c.getJSONWithRetry(http.MethodGet, path, nil, &template) + if err != nil { + return nil, err + } + return &template, nil +} + +// GetAllTemplates gets all the Template details +func (c *Client) GetAllTemplates() ([]types.TemplateDetails, error) { + defer TimeSpent("GetAllTemplates", time.Now()) + + path := fmt.Sprintf("/Api/V1/template") + + var templates types.TemplateDetailsFilter + err := c.getJSONWithRetry(http.MethodGet, path, nil, &templates) + if err != nil { + return nil, err + } + return templates.TemplateDetails, nil +} + +// GetTemplateByFilters gets the Template details based on the provided filter +func (c *Client) GetTemplateByFilters(key string, value string) ([]types.TemplateDetails, error) { + defer TimeSpent("GetTemplateByFilters", time.Now()) + + path := fmt.Sprintf("/Api/V1/template?filter=eq,%v,%v", key, value) + + var templates types.TemplateDetailsFilter + err := c.getJSONWithRetry(http.MethodGet, path, nil, &templates) + if err != nil { + return nil, err + } + + if len(templates.TemplateDetails) == 0 { + return nil, errors.New("Couldn't find templates with the given filter") + } + return templates.TemplateDetails, nil +} diff --git a/template_test.go b/template_test.go new file mode 100644 index 0000000..962004d --- /dev/null +++ b/template_test.go @@ -0,0 +1,119 @@ +// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package goscaleio + +import ( + "errors" + "fmt" + "math" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetTemplates(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNoContent) + })) + defer svr.Close() + + client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) + client.configConnect.Version = "4.5" + if err != nil { + t.Fatal(err) + } + + templateDetails, err := client.GetAllTemplates() + assert.Equal(t, len(templateDetails), 0) + assert.Nil(t, err) +} + +func TestGetTemplateByID(t *testing.T) { + type testCase struct { + id string + expected error + } + + cases := []testCase{ + { + id: "sdnasgw", + expected: nil, + }, + { + id: "sdnasgw1", + expected: errors.New("The template cannot be found"), + }, + } + + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + })) + defer svr.Close() + + for _, tc := range cases { + tc := tc + t.Run("", func(ts *testing.T) { + client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) + if err != nil { + t.Fatal(err) + } + + _, err = client.GetTemplateByID(tc.id) + if err != nil { + if tc.expected == nil { + t.Errorf("Getting template by ID did not work as expected, \n\tgot: %s \n\twant: %v", err, tc.expected) + } else { + if err.Error() != tc.expected.Error() { + t.Errorf("Getting template by ID did not work as expected, \n\tgot: %s \n\twant: %s", err, tc.expected) + } + } + } + }) + } +} + +func TestGetTemplateByFilters(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNoContent) + })) + defer svr.Close() + + client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) + client.configConnect.Version = "4.5" + if err != nil { + t.Fatal(err) + } + + templates, err := client.GetTemplateByFilters("Name", "Test") + assert.Equal(t, len(templates), 0) + assert.NotNil(t, err) +} + +func TestGetAllTemplatesNegative(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintln(w, `{"error":"Internal Server Error"}`) + })) + defer svr.Close() + + client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) + client.configConnect.Version = "4.5" + if err != nil { + t.Fatal(err) + } + + nodes, err := client.GetAllTemplates() + assert.Nil(t, nodes) + assert.NotNil(t, err) +} diff --git a/types/v1/templateTypes.go b/types/v1/templateTypes.go new file mode 100644 index 0000000..0f38b73 --- /dev/null +++ b/types/v1/templateTypes.go @@ -0,0 +1,177 @@ +// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package goscaleio + +import "time" + +// TemplateDetails defines struct for Template +type TemplateDetails struct { + ID string `json:"id,omitempty"` + TemplateName string `json:"templateName,omitempty"` + TemplateDescription string `json:"templateDescription,omitempty"` + TemplateType string `json:"templateType,omitempty"` + TemplateVersion string `json:"templateVersion,omitempty"` + TemplateValid TemplateValid `json:"templateValid,omitempty"` + OriginalTemplateID any `json:"originalTemplateId,omitempty"` + TemplateLocked bool `json:"templateLocked,omitempty"` + Draft bool `json:"draft,omitempty"` + InConfiguration bool `json:"inConfiguration,omitempty"` + CreatedDate time.Time `json:"createdDate,omitempty"` + CreatedBy string `json:"createdBy,omitempty"` + UpdatedDate time.Time `json:"updatedDate,omitempty"` + LastDeployedDate time.Time `json:"lastDeployedDate,omitempty"` + UpdatedBy string `json:"updatedBy,omitempty"` + Components []Components `json:"components,omitempty"` + Category string `json:"category,omitempty"` + AllUsersAllowed bool `json:"allUsersAllowed,omitempty"` + AssignedUsers []any `json:"assignedUsers,omitempty"` + ManageFirmware bool `json:"manageFirmware,omitempty"` + UseDefaultCatalog bool `json:"useDefaultCatalog,omitempty"` + FirmwareRepository FirmwareRepository `json:"firmwareRepository,omitempty"` + LicenseRepository any `json:"licenseRepository,omitempty"` + Configuration any `json:"configuration,omitempty"` + ServerCount int `json:"serverCount,omitempty"` + StorageCount int `json:"storageCount,omitempty"` + ClusterCount int `json:"clusterCount,omitempty"` + ServiceCount int `json:"serviceCount,omitempty"` + SwitchCount int `json:"switchCount,omitempty"` + VMCount int `json:"vmCount,omitempty"` + SdnasCount int `json:"sdnasCount,omitempty"` + BrownfieldTemplateType string `json:"brownfieldTemplateType,omitempty"` + Networks []Networks `json:"networks,omitempty"` + BlockServiceOperationsMap BlockServiceOperationsMap `json:"blockServiceOperationsMap,omitempty"` +} + +// TemplateValid defines struct for TemplateValid +type TemplateValid struct { + Valid bool `json:"valid,omitempty"` + Messages []string `json:"messages,omitempty"` +} + +// ComponentValid defines struct for ComponentValid +type ComponentValid struct { + Valid bool `json:"valid,omitempty"` + Messages []string `json:"messages,omitempty"` +} + +// RelatedComponents defines struct for RelatedComponents +type RelatedComponents struct { + NAMING_FAILED string `json:",omitempty"` +} + +// Components defines struct for RelatedComponents +type Components struct { + ID string `json:"id,omitempty"` + ComponentID string `json:"componentID,omitempty"` + Identifier string `json:"identifier,omitempty"` + ComponentValid ComponentValid `json:"componentValid,omitempty"` + PuppetCertName string `json:"puppetCertName,omitempty"` + OsPuppetCertName string `json:"osPuppetCertName,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + SubType string `json:"subType,omitempty"` + Teardown bool `json:"teardown,omitempty"` + HelpText any `json:"helpText,omitempty"` + ManagementIPAddress string `json:"managementIpAddress,omitempty"` + ConfigFile any `json:"configFile,omitempty"` + SerialNumber string `json:"serialNumber,omitempty"` + AsmGUID string `json:"asmGUID,omitempty"` + RelatedComponents RelatedComponents `json:"relatedComponents,omitempty"` + Resources []any `json:"resources,omitempty"` + RefID string `json:"refId,omitempty"` + Cloned bool `json:"cloned,omitempty"` + ClonedFromID any `json:"clonedFromId,omitempty"` + ManageFirmware bool `json:"manageFirmware,omitempty"` + Brownfield bool `json:"brownfield,omitempty"` + Instances int `json:"instances,omitempty"` + ClonedFromAsmGUID string `json:"clonedFromAsmGuid,omitempty"` + IP string `json:"ip,omitempty"` +} + +// FirmwareRepository defines struct for FirmwareRepository +type FirmwareRepository struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + SourceLocation any `json:"sourceLocation,omitempty"` + SourceType any `json:"sourceType,omitempty"` + DiskLocation any `json:"diskLocation,omitempty"` + Filename any `json:"filename,omitempty"` + Md5Hash any `json:"md5Hash,omitempty"` + Username any `json:"username,omitempty"` + Password any `json:"password,omitempty"` + DownloadStatus any `json:"downloadStatus,omitempty"` + CreatedDate any `json:"createdDate,omitempty"` + CreatedBy any `json:"createdBy,omitempty"` + UpdatedDate any `json:"updatedDate,omitempty"` + UpdatedBy any `json:"updatedBy,omitempty"` + DefaultCatalog bool `json:"defaultCatalog,omitempty"` + Embedded bool `json:"embedded,omitempty"` + State any `json:"state,omitempty"` + SoftwareComponents []any `json:"softwareComponents,omitempty"` + SoftwareBundles []any `json:"softwareBundles,omitempty"` + Deployments []any `json:"deployments,omitempty"` + BundleCount int `json:"bundleCount,omitempty"` + ComponentCount int `json:"componentCount,omitempty"` + UserBundleCount int `json:"userBundleCount,omitempty"` + Minimal bool `json:"minimal,omitempty"` + DownloadProgress int `json:"downloadProgress,omitempty"` + ExtractProgress int `json:"extractProgress,omitempty"` + FileSizeInGigabytes any `json:"fileSizeInGigabytes,omitempty"` + SignedKeySourceLocation any `json:"signedKeySourceLocation,omitempty"` + Signature any `json:"signature,omitempty"` + Custom bool `json:"custom,omitempty"` + NeedsAttention bool `json:"needsAttention,omitempty"` + JobID any `json:"jobId,omitempty"` + Rcmapproved bool `json:"rcmapproved,omitempty"` +} + +// StaticNetworkConfiguration defines struct for StaticNetworkConfiguration +type StaticNetworkConfiguration struct { + Gateway string `json:"gateway,omitempty"` + Subnet string `json:"subnet,omitempty"` + PrimaryDNS string `json:"primaryDns,omitempty"` + SecondaryDNS string `json:"secondaryDns,omitempty"` + DNSSuffix string `json:"dnsSuffix,omitempty"` + IPRange []IPRange `json:"ipRange,omitempty"` + IPAddress string `json:"ipAddress,omitempty"` + StaticRoute string `json:"staticRoute,omitempty"` +} + +// Networks defines struct for Networks +type Networks struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Type string `json:"type,omitempty"` + VlanID int `json:"vlanId,omitempty"` + Static bool `json:"static,omitempty"` + StaticNetworkConfiguration StaticNetworkConfiguration `json:"staticNetworkConfiguration,omitempty"` + DestinationIPAddress string `json:"destinationIpAddress,omitempty"` +} + +// IPRange defines struct for IPRange +type IPRange struct { + ID string `json:"id"` + StartingIP string `json:"startingIp"` + EndingIP string `json:"endingIp"` + Role any `json:"role"` +} + +// BlockServiceOperationsMap defines struct for BlockServiceOperationsMap +type BlockServiceOperationsMap struct { +} + +// TemplateDetailsFilter defines struct for nodepools +type TemplateDetailsFilter struct { + TemplateDetails []TemplateDetails `json:"serviceTemplate"` +} From 236a554122a09ce31146bf53666be95c9b06be3b Mon Sep 17 00:00:00 2001 From: root Date: Wed, 24 Jan 2024 03:43:48 -0500 Subject: [PATCH 02/21] Template Datasource --- types/v1/templateTypes.go | 940 ++++++++++++++++++++++++++++++++++---- types/v1/types.go | 6 +- 2 files changed, 853 insertions(+), 93 deletions(-) diff --git a/types/v1/templateTypes.go b/types/v1/templateTypes.go index 0f38b73..1d3a5a0 100644 --- a/types/v1/templateTypes.go +++ b/types/v1/templateTypes.go @@ -12,34 +12,30 @@ package goscaleio -import "time" - -// TemplateDetails defines struct for Template type TemplateDetails struct { ID string `json:"id,omitempty"` TemplateName string `json:"templateName,omitempty"` TemplateDescription string `json:"templateDescription,omitempty"` TemplateType string `json:"templateType,omitempty"` TemplateVersion string `json:"templateVersion,omitempty"` + OriginalTemplateID string `json:"originalTemplateId,omitempty"` TemplateValid TemplateValid `json:"templateValid,omitempty"` - OriginalTemplateID any `json:"originalTemplateId,omitempty"` TemplateLocked bool `json:"templateLocked,omitempty"` - Draft bool `json:"draft,omitempty"` InConfiguration bool `json:"inConfiguration,omitempty"` - CreatedDate time.Time `json:"createdDate,omitempty"` + CreatedDate string `json:"createdDate,omitempty"` CreatedBy string `json:"createdBy,omitempty"` - UpdatedDate time.Time `json:"updatedDate,omitempty"` - LastDeployedDate time.Time `json:"lastDeployedDate,omitempty"` + UpdatedDate string `json:"updatedDate,omitempty"` + LastDeployedDate string `json:"lastDeployedDate,omitempty"` UpdatedBy string `json:"updatedBy,omitempty"` - Components []Components `json:"components,omitempty"` - Category string `json:"category,omitempty"` - AllUsersAllowed bool `json:"allUsersAllowed,omitempty"` - AssignedUsers []any `json:"assignedUsers,omitempty"` ManageFirmware bool `json:"manageFirmware,omitempty"` UseDefaultCatalog bool `json:"useDefaultCatalog,omitempty"` FirmwareRepository FirmwareRepository `json:"firmwareRepository,omitempty"` - LicenseRepository any `json:"licenseRepository,omitempty"` - Configuration any `json:"configuration,omitempty"` + LicenseRepository LicenseRepository `json:"licenseRepository,omitempty"` + AssignedUsers []AssignedUsers `json:"assignedUsers,omitempty"` + AllUsersAllowed bool `json:"allUsersAllowed,omitempty"` + Category string `json:"category,omitempty"` + Components []Components `json:"components,omitempty"` + Configuration ConfigurationDetails `json:"configuration,omitempty"` ServerCount int `json:"serverCount,omitempty"` StorageCount int `json:"storageCount,omitempty"` ClusterCount int `json:"clusterCount,omitempty"` @@ -50,125 +46,887 @@ type TemplateDetails struct { BrownfieldTemplateType string `json:"brownfieldTemplateType,omitempty"` Networks []Networks `json:"networks,omitempty"` BlockServiceOperationsMap BlockServiceOperationsMap `json:"blockServiceOperationsMap,omitempty"` + Draft bool `json:"draft,omitempty"` +} + +type Messages struct { + ID string `json:"id,omitempty"` + MessageCode string `json:"messageCode,omitempty"` + MessageBundle string `json:"messageBundle,omitempty"` + Severity string `json:"severity,omitempty"` + Category string `json:"category,omitempty"` + DisplayMessage string `json:"displayMessage,omitempty"` + ResponseAction string `json:"responseAction,omitempty"` + DetailedMessage string `json:"detailedMessage,omitempty"` + CorrelationID string `json:"correlationId,omitempty"` + AgentID string `json:"agentId,omitempty"` + TimeStamp string `json:"timeStamp,omitempty"` + SequenceNumber int `json:"sequenceNumber,omitempty"` } -// TemplateValid defines struct for TemplateValid type TemplateValid struct { - Valid bool `json:"valid,omitempty"` - Messages []string `json:"messages,omitempty"` + Valid bool `json:"valid,omitempty"` + Messages []Messages `json:"messages,omitempty"` +} + +type SoftwareComponents struct { + ID string `json:"id,omitempty"` + PackageID string `json:"packageId,omitempty"` + DellVersion string `json:"dellVersion,omitempty"` + VendorVersion string `json:"vendorVersion,omitempty"` + ComponentID string `json:"componentId,omitempty"` + DeviceID string `json:"deviceId,omitempty"` + SubDeviceID string `json:"subDeviceId,omitempty"` + VendorID string `json:"vendorId,omitempty"` + SubVendorID string `json:"subVendorId,omitempty"` + CreatedDate string `json:"createdDate,omitempty"` + CreatedBy string `json:"createdBy,omitempty"` + UpdatedDate string `json:"updatedDate,omitempty"` + UpdatedBy string `json:"updatedBy,omitempty"` + Path string `json:"path,omitempty"` + HashMd5 string `json:"hashMd5,omitempty"` + Name string `json:"name,omitempty"` + Category string `json:"category,omitempty"` + ComponentType string `json:"componentType,omitempty"` + OperatingSystem string `json:"operatingSystem,omitempty"` + SystemIDs []string `json:"systemIDs,omitempty"` + Custom bool `json:"custom,omitempty"` + NeedsAttention bool `json:"needsAttention,omitempty"` + Ignore bool `json:"ignore,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + OriginalComponentID string `json:"originalComponentId,omitempty"` + FirmwareRepoName string `json:"firmwareRepoName,omitempty"` +} + +type SoftwareBundles struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Version string `json:"version,omitempty"` + BundleDate string `json:"bundleDate,omitempty"` + CreatedDate string `json:"createdDate,omitempty"` + CreatedBy string `json:"createdBy,omitempty"` + UpdatedDate string `json:"updatedDate,omitempty"` + UpdatedBy string `json:"updatedBy,omitempty"` + Description string `json:"description,omitempty"` + UserBundle bool `json:"userBundle,omitempty"` + UserBundlePath string `json:"userBundlePath,omitempty"` + UserBundleHashMd5 string `json:"userBundleHashMd5,omitempty"` + DeviceType string `json:"deviceType,omitempty"` + DeviceModel string `json:"deviceModel,omitempty"` + Criticality string `json:"criticality,omitempty"` + FwRepositoryID string `json:"fwRepositoryId,omitempty"` + Link Link `json:"link,omitempty"` + BundleType string `json:"bundleType,omitempty"` + Custom bool `json:"custom,omitempty"` + NeedsAttention bool `json:"needsAttention,omitempty"` + SoftwareComponents []SoftwareComponents `json:"softwareComponents,omitempty"` +} + +type DeploymentValid struct { + Valid bool `json:"valid,omitempty"` + Messages []Messages `json:"messages,omitempty"` +} + +type DeploymentDevice struct { + RefID string `json:"refId,omitempty"` + RefType string `json:"refType,omitempty"` + LogDump string `json:"logDump,omitempty"` + Status string `json:"status,omitempty"` + StatusEndTime string `json:"statusEndTime,omitempty"` + StatusStartTime string `json:"statusStartTime,omitempty"` + DeviceHealth string `json:"deviceHealth,omitempty"` + HealthMessage string `json:"healthMessage,omitempty"` + CompliantState string `json:"compliantState,omitempty"` + BrownfieldStatus string `json:"brownfieldStatus,omitempty"` + DeviceType string `json:"deviceType,omitempty"` + DeviceGroupName string `json:"deviceGroupName,omitempty"` + IPAddress string `json:"ipAddress,omitempty"` + CurrentIPAddress string `json:"currentIpAddress,omitempty"` + ServiceTag string `json:"serviceTag,omitempty"` + ComponentID string `json:"componentId,omitempty"` + StatusMessage string `json:"statusMessage,omitempty"` + Model string `json:"model,omitempty"` + CloudLink bool `json:"cloudLink,omitempty"` + DasCache bool `json:"dasCache,omitempty"` + DeviceState string `json:"deviceState,omitempty"` + PuppetCertName string `json:"puppetCertName,omitempty"` + Brownfield bool `json:"brownfield,omitempty"` +} + +type Vms struct { + CertificateName string `json:"certificateName,omitempty"` + VMModel string `json:"vmModel,omitempty"` + VMIpaddress string `json:"vmIpaddress,omitempty"` + VMManufacturer string `json:"vmManufacturer,omitempty"` + VMServiceTag string `json:"vmServiceTag,omitempty"` +} + +type LicenseRepository struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + DiskLocation string `json:"diskLocation,omitempty"` + Filename string `json:"filename,omitempty"` + State string `json:"state,omitempty"` + CreatedDate string `json:"createdDate,omitempty"` + CreatedBy string `json:"createdBy,omitempty"` + UpdatedDate string `json:"updatedDate,omitempty"` + UpdatedBy string `json:"updatedBy,omitempty"` + Templates []any `json:"templates,omitempty"` + LicenseData string `json:"licenseData,omitempty"` +} + +type AssignedUsers struct { + UserSeqID int `json:"userSeqId,omitempty"` + UserName string `json:"userName,omitempty"` + Password string `json:"password,omitempty"` + UpdatePassword bool `json:"updatePassword,omitempty"` + DomainName string `json:"domainName,omitempty"` + GroupDN string `json:"groupDN,omitempty"` + GroupName string `json:"groupName,omitempty"` + FirstName string `json:"firstName,omitempty"` + LastName string `json:"lastName,omitempty"` + Email string `json:"email,omitempty"` + PhoneNumber string `json:"phoneNumber,omitempty"` + Enabled bool `json:"enabled,omitempty"` + SystemUser bool `json:"systemUser,omitempty"` + CreatedDate string `json:"createdDate,omitempty"` + CreatedBy string `json:"createdBy,omitempty"` + UpdatedDate string `json:"updatedDate,omitempty"` + UpdatedBy string `json:"updatedBy,omitempty"` + Link Link `json:"link,omitempty"` + Role string `json:"role,omitempty"` + UserPreference string `json:"userPreference,omitempty"` + ID string `json:"id,omitempty"` + Roles []string `json:"roles,omitempty"` +} + +type JobDetails struct { + Level string `json:"level,omitempty"` + Message string `json:"message,omitempty"` + Timestamp string `json:"timestamp,omitempty"` + ExecutionID string `json:"executionId,omitempty"` + ComponentID string `json:"componentId,omitempty"` +} + +type DeploymentValidationResponse struct { + Nodes int `json:"nodes,omitempty"` + StoragePools int `json:"storagePools,omitempty"` + DrivesPerStoragePool int `json:"drivesPerStoragePool,omitempty"` + MaxScalability int `json:"maxScalability,omitempty"` + VirtualMachines int `json:"virtualMachines,omitempty"` + NumberOfServiceVolumes int `json:"numberOfServiceVolumes,omitempty"` + CanDeploy bool `json:"canDeploy,omitempty"` + WarningMessages []string `json:"warningMessages,omitempty"` + StoragePoolDiskType []string `json:"storagePoolDiskType,omitempty"` + Hostnames []string `json:"hostnames,omitempty"` + NewNodeDiskTypes []string `json:"newNodeDiskTypes,omitempty"` + NoOfFaultSets int `json:"noOfFaultSets,omitempty"` + NodesPerFaultSet int `json:"nodesPerFaultSet,omitempty"` + ProtectionDomain string `json:"protectionDomain,omitempty"` + DiskTypeMismatch bool `json:"diskTypeMismatch,omitempty"` +} + +type Deployments struct { + ID string `json:"id,omitempty"` + DeploymentName string `json:"deploymentName,omitempty"` + DeploymentDescription string `json:"deploymentDescription,omitempty"` + DeploymentValid DeploymentValid `json:"deploymentValid,omitempty"` + Retry bool `json:"retry,omitempty"` + Teardown bool `json:"teardown,omitempty"` + TeardownAfterCancel bool `json:"teardownAfterCancel,omitempty"` + RemoveService bool `json:"removeService,omitempty"` + CreatedDate string `json:"createdDate,omitempty"` + CreatedBy string `json:"createdBy,omitempty"` + UpdatedDate string `json:"updatedDate,omitempty"` + UpdatedBy string `json:"updatedBy,omitempty"` + DeploymentScheduledDate string `json:"deploymentScheduledDate,omitempty"` + DeploymentStartedDate string `json:"deploymentStartedDate,omitempty"` + DeploymentFinishedDate string `json:"deploymentFinishedDate,omitempty"` + ScheduleDate string `json:"scheduleDate,omitempty"` + Status string `json:"status,omitempty"` + Compliant bool `json:"compliant,omitempty"` + DeploymentDevice []DeploymentDevice `json:"deploymentDevice,omitempty"` + Vms []Vms `json:"vms,omitempty"` + UpdateServerFirmware bool `json:"updateServerFirmware,omitempty"` + UseDefaultCatalog bool `json:"useDefaultCatalog,omitempty"` + FirmwareRepositoryID string `json:"firmwareRepositoryId,omitempty"` + LicenseRepository LicenseRepository `json:"licenseRepository,omitempty"` + LicenseRepositoryID string `json:"licenseRepositoryId,omitempty"` + IndividualTeardown bool `json:"individualTeardown,omitempty"` + DeploymentHealthStatusType string `json:"deploymentHealthStatusType,omitempty"` + AssignedUsers []AssignedUsers `json:"assignedUsers,omitempty"` + AllUsersAllowed bool `json:"allUsersAllowed,omitempty"` + Owner string `json:"owner,omitempty"` + NoOp bool `json:"noOp,omitempty"` + FirmwareInit bool `json:"firmwareInit,omitempty"` + DisruptiveFirmware bool `json:"disruptiveFirmware,omitempty"` + PreconfigureSVM bool `json:"preconfigureSVM,omitempty"` + PreconfigureSVMAndUpdate bool `json:"preconfigureSVMAndUpdate,omitempty"` + ServicesDeployed string `json:"servicesDeployed,omitempty"` + PrecalculatedDeviceHealth string `json:"precalculatedDeviceHealth,omitempty"` + LifecycleModeReasons []string `json:"lifecycleModeReasons,omitempty"` + JobDetails []JobDetails `json:"jobDetails,omitempty"` + NumberOfDeployments int `json:"numberOfDeployments,omitempty"` + OperationType string `json:"operationType,omitempty"` + OperationStatus string `json:"operationStatus,omitempty"` + OperationData string `json:"operationData,omitempty"` + DeploymentValidationResponse DeploymentValidationResponse `json:"deploymentValidationResponse,omitempty"` + CurrentStepCount string `json:"currentStepCount,omitempty"` + TotalNumOfSteps string `json:"totalNumOfSteps,omitempty"` + CurrentStepMessage string `json:"currentStepMessage,omitempty"` + CustomImage string `json:"customImage,omitempty"` + OriginalDeploymentID string `json:"originalDeploymentId,omitempty"` + CurrentBatchCount string `json:"currentBatchCount,omitempty"` + TotalBatchCount string `json:"totalBatchCount,omitempty"` + Brownfield bool `json:"brownfield,omitempty"` + ScaleUp bool `json:"scaleUp,omitempty"` + LifecycleMode bool `json:"lifecycleMode,omitempty"` + OverallDeviceHealth string `json:"overallDeviceHealth,omitempty"` + Vds bool `json:"vds,omitempty"` + TemplateValid bool `json:"templateValid,omitempty"` + ConfigurationChange bool `json:"configurationChange,omitempty"` + CanMigratevCLSVMs bool `json:"canMigratevCLSVMs,omitempty"` +} + +type FirmwareRepository struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + SourceLocation string `json:"sourceLocation,omitempty"` + SourceType string `json:"sourceType,omitempty"` + DiskLocation string `json:"diskLocation,omitempty"` + Filename string `json:"filename,omitempty"` + Md5Hash string `json:"md5Hash,omitempty"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + DownloadStatus string `json:"downloadStatus,omitempty"` + CreatedDate string `json:"createdDate,omitempty"` + CreatedBy string `json:"createdBy,omitempty"` + UpdatedDate string `json:"updatedDate,omitempty"` + UpdatedBy string `json:"updatedBy,omitempty"` + DefaultCatalog bool `json:"defaultCatalog,omitempty"` + Embedded bool `json:"embedded,omitempty"` + State string `json:"state,omitempty"` + SoftwareComponents []SoftwareComponents `json:"softwareComponents,omitempty"` + SoftwareBundles []SoftwareBundles `json:"softwareBundles,omitempty"` + Deployments []Deployments `json:"deployments,omitempty"` + BundleCount int `json:"bundleCount,omitempty"` + ComponentCount int `json:"componentCount,omitempty"` + UserBundleCount int `json:"userBundleCount,omitempty"` + Minimal bool `json:"minimal,omitempty"` + DownloadProgress int `json:"downloadProgress,omitempty"` + ExtractProgress int `json:"extractProgress,omitempty"` + FileSizeInGigabytes int `json:"fileSizeInGigabytes,omitempty"` + SignedKeySourceLocation string `json:"signedKeySourceLocation,omitempty"` + Signature string `json:"signature,omitempty"` + Custom bool `json:"custom,omitempty"` + NeedsAttention bool `json:"needsAttention,omitempty"` + JobID string `json:"jobId,omitempty"` + Rcmapproved bool `json:"rcmapproved,omitempty"` } -// ComponentValid defines struct for ComponentValid type ComponentValid struct { - Valid bool `json:"valid,omitempty"` - Messages []string `json:"messages,omitempty"` + Valid bool `json:"valid,omitempty"` + Messages []Messages `json:"messages,omitempty"` } -// RelatedComponents defines struct for RelatedComponents type RelatedComponents struct { - NAMING_FAILED string `json:",omitempty"` + AdditionalProp1 string `json:"additionalProp1,omitempty"` + AdditionalProp2 string `json:"additionalProp2,omitempty"` + AdditionalProp3 string `json:"additionalProp3,omitempty"` +} + +type DependenciesDetails struct { + ID string `json:"id,omitempty"` + DependencyTarget string `json:"dependencyTarget,omitempty"` + DependencyValue string `json:"dependencyValue,omitempty"` +} + +type NetworkIPAddressList struct { + ID string `json:"id,omitempty"` + IPAddress string `json:"ipAddress,omitempty"` +} + +type Partitions struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Networks []string `json:"networks,omitempty"` + NetworkIPAddressList []NetworkIPAddressList `json:"networkIpAddressList,omitempty"` + Minimum int `json:"minimum,omitempty"` + Maximum int `json:"maximum,omitempty"` + LanMacAddress string `json:"lanMacAddress,omitempty"` + IscsiMacAddress string `json:"iscsiMacAddress,omitempty"` + IscsiIQN string `json:"iscsiIQN,omitempty"` + Wwnn string `json:"wwnn,omitempty"` + Wwpn string `json:"wwpn,omitempty"` + Fqdd string `json:"fqdd,omitempty"` + MirroredPort string `json:"mirroredPort,omitempty"` + MacAddress string `json:"mac_address,omitempty"` + PortNo int `json:"port_no,omitempty"` + PartitionNo int `json:"partition_no,omitempty"` + PartitionIndex int `json:"partition_index,omitempty"` +} + +type Interfaces struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Partitioned bool `json:"partitioned,omitempty"` + Partitions []Partitions `json:"partitions,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Redundancy bool `json:"redundancy,omitempty"` + Nictype string `json:"nictype,omitempty"` + Fqdd string `json:"fqdd,omitempty"` + MaxPartitions int `json:"maxPartitions,omitempty"` + AllNetworks []string `json:"allNetworks,omitempty"` +} + +type InterfacesDetails struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Redundancy bool `json:"redundancy,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Partitioned bool `json:"partitioned,omitempty"` + Interfaces []Interfaces `json:"interfaces,omitempty"` + Nictype string `json:"nictype,omitempty"` + Fabrictype string `json:"fabrictype,omitempty"` + MaxPartitions int `json:"maxPartitions,omitempty"` + Nports int `json:"nports,omitempty"` + CardIndex int `json:"card_index,omitempty"` + NictypeSource string `json:"nictypeSource,omitempty"` +} + +type NetworkConfiguration struct { + ID string `json:"id,omitempty"` + Interfaces []InterfacesDetails `json:"interfaces,omitempty"` + SoftwareOnly bool `json:"softwareOnly,omitempty"` +} + +type ConfigurationDetails struct { + ID string `json:"id,omitempty"` + Disktype string `json:"disktype,omitempty"` + Comparator string `json:"comparator,omitempty"` + Numberofdisks int `json:"numberofdisks,omitempty"` + Raidlevel string `json:"raidlevel,omitempty"` + VirtualDiskFqdd string `json:"virtualDiskFqdd,omitempty"` + ControllerFqdd string `json:"controllerFqdd,omitempty"` + Categories []Categories `json:"categories,omitempty"` + CategoriesMap CategoriesMap `json:"categoriesMap,omitempty"` + SettingsMap SettingsMap `json:"settingsMap,omitempty"` +} + +type VirtualDisks struct { + PhysicalDisks []string `json:"physicalDisks,omitempty"` + VirtualDiskFqdd string `json:"virtualDiskFqdd,omitempty"` + RaidLevel string `json:"raidLevel,omitempty"` + RollUpStatus string `json:"rollUpStatus,omitempty"` + Controller string `json:"controller,omitempty"` + ControllerProductName string `json:"controllerProductName,omitempty"` + Configuration ConfigurationDetails `json:"configuration,omitempty"` + MediaType string `json:"mediaType,omitempty"` + EncryptionType string `json:"encryptionType,omitempty"` } -// Components defines struct for RelatedComponents +type ExternalVirtualDisks struct { + PhysicalDisks []string `json:"physicalDisks,omitempty"` + VirtualDiskFqdd string `json:"virtualDiskFqdd,omitempty"` + RaidLevel string `json:"raidLevel,omitempty"` + RollUpStatus string `json:"rollUpStatus,omitempty"` + Controller string `json:"controller,omitempty"` + ControllerProductName string `json:"controllerProductName,omitempty"` + Configuration ConfigurationDetails `json:"configuration,omitempty"` + MediaType string `json:"mediaType,omitempty"` + EncryptionType string `json:"encryptionType,omitempty"` +} + +type SizeToDiskMap struct { + AdditionalProp1 int `json:"additionalProp1,omitempty"` + AdditionalProp2 int `json:"additionalProp2,omitempty"` + AdditionalProp3 int `json:"additionalProp3,omitempty"` +} + +type RaidConfiguration struct { + VirtualDisks []VirtualDisks `json:"virtualDisks,omitempty"` + ExternalVirtualDisks []ExternalVirtualDisks `json:"externalVirtualDisks,omitempty"` + HddHotSpares []string `json:"hddHotSpares,omitempty"` + SsdHotSpares []string `json:"ssdHotSpares,omitempty"` + ExternalHddHotSpares []string `json:"externalHddHotSpares,omitempty"` + ExternalSsdHotSpares []string `json:"externalSsdHotSpares,omitempty"` + SizeToDiskMap SizeToDiskMap `json:"sizeToDiskMap,omitempty"` +} + +type Attributes struct { + AdditionalProp1 string `json:"additionalProp1,omitempty"` + AdditionalProp2 string `json:"additionalProp2,omitempty"` + AdditionalProp3 string `json:"additionalProp3,omitempty"` +} + +type OptionsDetails struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Value string `json:"value,omitempty"` + Dependencies []DependenciesDetails `json:"dependencies,omitempty"` + Attributes Attributes `json:"attributes,omitempty"` +} +type ScaleIOStoragePoolDisks struct { + ProtectionDomainID string `json:"protectionDomainId,omitempty"` + ProtectionDomainName string `json:"protectionDomainName,omitempty"` + StoragePoolID string `json:"storagePoolId,omitempty"` + StoragePoolName string `json:"storagePoolName,omitempty"` + DiskType string `json:"diskType,omitempty"` + PhysicalDiskFqdds []string `json:"physicalDiskFqdds,omitempty"` + VirtualDiskFqdds []string `json:"virtualDiskFqdds,omitempty"` + SoftwareOnlyDisks []string `json:"softwareOnlyDisks,omitempty"` +} +type ScaleIODiskConfiguration struct { + ScaleIOStoragePoolDisks []ScaleIOStoragePoolDisks `json:"scaleIOStoragePoolDisks,omitempty"` +} +type ShortWindow struct { + Threshold int `json:"threshold,omitempty"` + WindowSizeInSec int `json:"windowSizeInSec,omitempty"` +} +type MediumWindow struct { + Threshold int `json:"threshold,omitempty"` + WindowSizeInSec int `json:"windowSizeInSec,omitempty"` +} +type LongWindow struct { + Threshold int `json:"threshold,omitempty"` + WindowSizeInSec int `json:"windowSizeInSec,omitempty"` +} +type SdsDecoupledCounterParameters struct { + ShortWindow ShortWindow `json:"shortWindow,omitempty"` + MediumWindow MediumWindow `json:"mediumWindow,omitempty"` + LongWindow LongWindow `json:"longWindow,omitempty"` +} +type SdsConfigurationFailureCounterParameters struct { + ShortWindow ShortWindow `json:"shortWindow,omitempty"` + MediumWindow MediumWindow `json:"mediumWindow,omitempty"` + LongWindow LongWindow `json:"longWindow,omitempty"` +} +type MdmSdsCounterParameters struct { + ShortWindow ShortWindow `json:"shortWindow,omitempty"` + MediumWindow MediumWindow `json:"mediumWindow,omitempty"` + LongWindow LongWindow `json:"longWindow,omitempty"` +} +type SdsSdsCounterParameters struct { + ShortWindow ShortWindow `json:"shortWindow,omitempty"` + MediumWindow MediumWindow `json:"mediumWindow,omitempty"` + LongWindow LongWindow `json:"longWindow,omitempty"` +} +type SdsReceiveBufferAllocationFailuresCounterParameters struct { + ShortWindow ShortWindow `json:"shortWindow,omitempty"` + MediumWindow MediumWindow `json:"mediumWindow,omitempty"` + LongWindow LongWindow `json:"longWindow,omitempty"` +} +type General struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + SystemID string `json:"systemId,omitempty"` + ProtectionDomainState string `json:"protectionDomainState,omitempty"` + RebuildNetworkThrottlingInKbps int `json:"rebuildNetworkThrottlingInKbps,omitempty"` + RebalanceNetworkThrottlingInKbps int `json:"rebalanceNetworkThrottlingInKbps,omitempty"` + OverallIoNetworkThrottlingInKbps int `json:"overallIoNetworkThrottlingInKbps,omitempty"` + SdsDecoupledCounterParameters SdsDecoupledCounterParameters `json:"sdsDecoupledCounterParameters,omitempty"` + SdsConfigurationFailureCounterParameters SdsConfigurationFailureCounterParameters `json:"sdsConfigurationFailureCounterParameters,omitempty"` + MdmSdsCounterParameters MdmSdsCounterParameters `json:"mdmSdsCounterParameters,omitempty"` + SdsSdsCounterParameters SdsSdsCounterParameters `json:"sdsSdsCounterParameters,omitempty"` + RfcacheOpertionalMode string `json:"rfcacheOpertionalMode,omitempty"` + RfcachePageSizeKb int `json:"rfcachePageSizeKb,omitempty"` + RfcacheMaxIoSizeKb int `json:"rfcacheMaxIoSizeKb,omitempty"` + SdsReceiveBufferAllocationFailuresCounterParameters SdsReceiveBufferAllocationFailuresCounterParameters `json:"sdsReceiveBufferAllocationFailuresCounterParameters,omitempty"` + RebuildNetworkThrottlingEnabled bool `json:"rebuildNetworkThrottlingEnabled,omitempty"` + RebalanceNetworkThrottlingEnabled bool `json:"rebalanceNetworkThrottlingEnabled,omitempty"` + OverallIoNetworkThrottlingEnabled bool `json:"overallIoNetworkThrottlingEnabled,omitempty"` + RfcacheEnabled bool `json:"rfcacheEnabled,omitempty"` +} + +type StatisticsDetails struct { + NumOfDevices int `json:"numOfDevices,omitempty"` + UnusedCapacityInKb int `json:"unusedCapacityInKb,omitempty"` + NumOfVolumes int `json:"numOfVolumes,omitempty"` + NumOfMappedToAllVolumes int `json:"numOfMappedToAllVolumes,omitempty"` + CapacityAvailableForVolumeAllocationInKb int `json:"capacityAvailableForVolumeAllocationInKb,omitempty"` + VolumeAllocationLimitInKb int `json:"volumeAllocationLimitInKb,omitempty"` + CapacityLimitInKb int `json:"capacityLimitInKb,omitempty"` + NumOfUnmappedVolumes int `json:"numOfUnmappedVolumes,omitempty"` + SpareCapacityInKb int `json:"spareCapacityInKb,omitempty"` + CapacityInUseInKb int `json:"capacityInUseInKb,omitempty"` + MaxCapacityInKb int `json:"maxCapacityInKb,omitempty"` + + NumOfSds int `json:"numOfSds,omitempty"` + + NumOfStoragePools int `json:"numOfStoragePools,omitempty"` + NumOfFaultSets int `json:"numOfFaultSets,omitempty"` + + ThinCapacityInUseInKb int `json:"thinCapacityInUseInKb,omitempty"` + ThickCapacityInUseInKb int `json:"thickCapacityInUseInKb,omitempty"` +} +type DiskList struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + ErrorState string `json:"errorState,omitempty"` + SdsID string `json:"sdsId,omitempty"` + DeviceState string `json:"deviceState,omitempty"` + CapacityLimitInKb int `json:"capacityLimitInKb,omitempty"` + MaxCapacityInKb int `json:"maxCapacityInKb,omitempty"` + StoragePoolID string `json:"storagePoolId,omitempty"` + DeviceCurrentPathName string `json:"deviceCurrentPathName,omitempty"` + DeviceOriginalPathName string `json:"deviceOriginalPathName,omitempty"` + SerialNumber string `json:"serialNumber,omitempty"` + VendorName string `json:"vendorName,omitempty"` + ModelName string `json:"modelName,omitempty"` +} + +type MappedSdcInfoDetails struct { + SdcIP string `json:"sdcIp,omitempty"` + SdcID string `json:"sdcId,omitempty"` + LimitBwInMbps int `json:"limitBwInMbps,omitempty"` + LimitIops int `json:"limitIops,omitempty"` +} + +type VolumeList struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + VolumeType string `json:"volumeType,omitempty"` + StoragePoolID string `json:"storagePoolId,omitempty"` + DataLayout string `json:"dataLayout,omitempty"` + CompressionMethod string `json:"compressionMethod,omitempty"` + SizeInKb int `json:"sizeInKb,omitempty"` + MappedSdcInfo []MappedSdcInfoDetails `json:"mappedSdcInfo,omitempty"` + VolumeClass string `json:"volumeClass,omitempty"` +} + +type StoragePoolList struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + RebuildIoPriorityPolicy string `json:"rebuildIoPriorityPolicy,omitempty"` + RebalanceIoPriorityPolicy string `json:"rebalanceIoPriorityPolicy,omitempty"` + RebuildIoPriorityNumOfConcurrentIosPerDevice int `json:"rebuildIoPriorityNumOfConcurrentIosPerDevice,omitempty"` + RebalanceIoPriorityNumOfConcurrentIosPerDevice int `json:"rebalanceIoPriorityNumOfConcurrentIosPerDevice,omitempty"` + RebuildIoPriorityBwLimitPerDeviceInKbps int `json:"rebuildIoPriorityBwLimitPerDeviceInKbps,omitempty"` + RebalanceIoPriorityBwLimitPerDeviceInKbps int `json:"rebalanceIoPriorityBwLimitPerDeviceInKbps,omitempty"` + RebuildIoPriorityAppIopsPerDeviceThreshold string `json:"rebuildIoPriorityAppIopsPerDeviceThreshold,omitempty"` + RebalanceIoPriorityAppIopsPerDeviceThreshold string `json:"rebalanceIoPriorityAppIopsPerDeviceThreshold,omitempty"` + RebuildIoPriorityAppBwPerDeviceThresholdInKbps int `json:"rebuildIoPriorityAppBwPerDeviceThresholdInKbps,omitempty"` + RebalanceIoPriorityAppBwPerDeviceThresholdInKbps int `json:"rebalanceIoPriorityAppBwPerDeviceThresholdInKbps,omitempty"` + RebuildIoPriorityQuietPeriodInMsec int `json:"rebuildIoPriorityQuietPeriodInMsec,omitempty"` + RebalanceIoPriorityQuietPeriodInMsec int `json:"rebalanceIoPriorityQuietPeriodInMsec,omitempty"` + ZeroPaddingEnabled bool `json:"zeroPaddingEnabled,omitempty"` + BackgroundScannerMode string `json:"backgroundScannerMode,omitempty"` + BackgroundScannerBWLimitKBps int `json:"backgroundScannerBWLimitKBps,omitempty"` + UseRmcache bool `json:"useRmcache,omitempty"` + ProtectionDomainID string `json:"protectionDomainId,omitempty"` + SpClass string `json:"spClass,omitempty"` + UseRfcache bool `json:"useRfcache,omitempty"` + SparePercentage int `json:"sparePercentage,omitempty"` + RmcacheWriteHandlingMode string `json:"rmcacheWriteHandlingMode,omitempty"` + ChecksumEnabled bool `json:"checksumEnabled,omitempty"` + RebuildEnabled bool `json:"rebuildEnabled,omitempty"` + RebalanceEnabled bool `json:"rebalanceEnabled,omitempty"` + NumOfParallelRebuildRebalanceJobsPerDevice int `json:"numOfParallelRebuildRebalanceJobsPerDevice,omitempty"` + CapacityAlertHighThreshold int `json:"capacityAlertHighThreshold,omitempty"` + CapacityAlertCriticalThreshold int `json:"capacityAlertCriticalThreshold,omitempty"` + Statistics StatisticsDetails `json:"statistics,omitempty"` + DataLayout string `json:"dataLayout,omitempty"` + ReplicationCapacityMaxRatio string `json:"replicationCapacityMaxRatio,omitempty"` + MediaType string `json:"mediaType,omitempty"` + DiskList []DiskList `json:"disk_list,omitempty"` + VolumeList []VolumeList `json:"volume_list,omitempty"` + FglAccpID string `json:"fglAccpId,omitempty"` +} + +type IPList struct { + IP string `json:"ip,omitempty"` + Role string `json:"role,omitempty"` +} + +type SdsListDetails struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Port int `json:"port,omitempty"` + ProtectionDomainID string `json:"protectionDomainId,omitempty"` + FaultSetID string `json:"faultSetId,omitempty"` + SoftwareVersionInfo string `json:"softwareVersionInfo,omitempty"` + SdsState string `json:"sdsState,omitempty"` + MembershipState string `json:"membershipState,omitempty"` + MdmConnectionState string `json:"mdmConnectionState,omitempty"` + DrlMode string `json:"drlMode,omitempty"` + MaintenanceState string `json:"maintenanceState,omitempty"` + PerfProfile string `json:"perfProfile,omitempty"` + OnVMWare bool `json:"onVmWare,omitempty"` + IPList []IPList `json:"ipList,omitempty"` +} +type SdrListDetails struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Port int `json:"port,omitempty"` + ProtectionDomainID string `json:"protectionDomainId,omitempty"` + SoftwareVersionInfo string `json:"softwareVersionInfo,omitempty"` + SdrState string `json:"sdrState,omitempty"` + MembershipState string `json:"membershipState,omitempty"` + MdmConnectionState string `json:"mdmConnectionState,omitempty"` + MaintenanceState string `json:"maintenanceState,omitempty"` + PerfProfile string `json:"perfProfile,omitempty"` + IPList []IPList `json:"ipList,omitempty"` +} +type AccelerationPool struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + ProtectionDomainID string `json:"protectionDomainId,omitempty"` + MediaType string `json:"mediaType,omitempty"` + Rfcache bool `json:"rfcache,omitempty"` +} +type ProtectionDomainSettings struct { + General General `json:"general,omitempty"` + Statistics Statistics `json:"statistics,omitempty"` + StoragePoolList []StoragePoolList `json:"storage_pool_list,omitempty"` + SdsList []SdsListDetails `json:"sds_list,omitempty"` + SdrList []SdsListDetails `json:"sdr_list,omitempty"` + AccelerationPool []AccelerationPool `json:"acceleration_pool,omitempty"` +} +type FaultSetSettings struct { + ProtectionDomainID string `json:"protectionDomainId,omitempty"` + Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` +} +type Datacenter struct { + VcenterID string `json:"vcenterId,omitempty"` + DatacenterID string `json:"datacenterId,omitempty"` + DatacenterName string `json:"datacenterName,omitempty"` +} +type PortGroupOptions struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} +type PortGroups struct { + ID string `json:"id,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Vlan int `json:"vlan,omitempty"` + Name string `json:"name,omitempty"` + Value string `json:"value,omitempty"` + PortGroupOptions []PortGroupOptions `json:"portGroupOptions,omitempty"` +} +type VdsSettings struct { + ID string `json:"id,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Name string `json:"name,omitempty"` + Value string `json:"value,omitempty"` + PortGroups []PortGroups `json:"portGroups,omitempty"` +} +type VdsNetworkMtuSizeConfiguration struct { + ID string `json:"id,omitempty"` + Value string `json:"value,omitempty"` +} +type VdsNetworkMTUSizeConfiguration struct { + ID string `json:"id,omitempty"` + Value string `json:"value,omitempty"` +} +type VdsConfiguration struct { + Datacenter Datacenter `json:"datacenter,omitempty"` + PortGroupOption string `json:"portGroupOption,omitempty"` + PortGroupCreationOption string `json:"portGroupCreationOption,omitempty"` + VdsSettings []VdsSettings `json:"vdsSettings,omitempty"` + VdsNetworkMtuSizeConfiguration []VdsNetworkMtuSizeConfiguration `json:"vdsNetworkMtuSizeConfiguration,omitempty"` + VdsNetworkMTUSizeConfiguration []VdsNetworkMTUSizeConfiguration `json:"vdsNetworkMTUSizeConfiguration,omitempty"` +} +type NodeSelection struct { + ID string `json:"id,omitempty"` + ServiceTag string `json:"serviceTag,omitempty"` + MgmtIPAddress string `json:"mgmtIpAddress,omitempty"` +} +type ParametersDetails struct { + GUID string `json:"guid,omitempty"` + ID string `json:"id,omitempty"` + Type string `json:"type,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Value string `json:"value,omitempty"` + ToolTip string `json:"toolTip,omitempty"` + Required bool `json:"required,omitempty"` + RequiredAtDeployment bool `json:"requiredAtDeployment,omitempty"` + HideFromTemplate bool `json:"hideFromTemplate,omitempty"` + Dependencies []DependenciesDetails `json:"dependencies,omitempty"` + Group string `json:"group,omitempty"` + ReadOnly bool `json:"readOnly,omitempty"` + Generated bool `json:"generated,omitempty"` + InfoIcon bool `json:"infoIcon,omitempty"` + Step int `json:"step,omitempty"` + MaxLength int `json:"maxLength,omitempty"` + Min int `json:"min,omitempty"` + Max int `json:"max,omitempty"` + NetworkIPAddressList []NetworkIPAddressList `json:"networkIpAddressList,omitempty"` + NetworkConfiguration NetworkConfiguration `json:"networkConfiguration,omitempty"` + RaidConfiguration RaidConfiguration `json:"raidConfiguration,omitempty"` + Options []OptionsDetails `json:"options,omitempty"` + OptionsSortable bool `json:"optionsSortable,omitempty"` + PreservedForDeployment bool `json:"preservedForDeployment,omitempty"` + ScaleIODiskConfiguration ScaleIODiskConfiguration `json:"scaleIODiskConfiguration,omitempty"` + ProtectionDomainSettings []ProtectionDomainSettings `json:"protectionDomainSettings,omitempty"` + FaultSetSettings []FaultSetSettings `json:"faultSetSettings,omitempty"` + Attributes Attributes `json:"attributes,omitempty"` + VdsConfiguration VdsConfiguration `json:"vdsConfiguration,omitempty"` + NodeSelection NodeSelection `json:"nodeSelection,omitempty"` +} +type AdditionalPropDetails struct { + GUID string `json:"guid,omitempty"` + ID string `json:"id,omitempty"` + Type string `json:"type,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Value string `json:"value,omitempty"` + ToolTip string `json:"toolTip,omitempty"` + Required bool `json:"required,omitempty"` + RequiredAtDeployment bool `json:"requiredAtDeployment,omitempty"` + HideFromTemplate bool `json:"hideFromTemplate,omitempty"` + Dependencies []DependenciesDetails `json:"dependencies,omitempty"` + Group string `json:"group,omitempty"` + ReadOnly bool `json:"readOnly,omitempty"` + Generated bool `json:"generated,omitempty"` + InfoIcon bool `json:"infoIcon,omitempty"` + Step int `json:"step,omitempty"` + MaxLength int `json:"maxLength,omitempty"` + Min int `json:"min,omitempty"` + Max int `json:"max,omitempty"` + NetworkIPAddressList []NetworkIPAddressList `json:"networkIpAddressList,omitempty"` + NetworkConfiguration NetworkConfiguration `json:"networkConfiguration,omitempty"` + RaidConfiguration RaidConfiguration `json:"raidConfiguration,omitempty"` + Options []Options `json:"options,omitempty"` + OptionsSortable bool `json:"optionsSortable,omitempty"` + PreservedForDeployment bool `json:"preservedForDeployment,omitempty"` + ScaleIODiskConfiguration ScaleIODiskConfiguration `json:"scaleIODiskConfiguration,omitempty"` + ProtectionDomainSettings []ProtectionDomainSettings `json:"protectionDomainSettings,omitempty"` + FaultSetSettings []FaultSetSettings `json:"faultSetSettings,omitempty"` + Attributes Attributes `json:"attributes,omitempty"` + VdsConfiguration VdsConfiguration `json:"vdsConfiguration,omitempty"` + NodeSelection NodeSelection `json:"nodeSelection,omitempty"` +} +type ParametersMap struct { + AdditionalProp1 AdditionalPropDetails `json:"additionalProp1,omitempty"` + AdditionalProp2 AdditionalPropDetails `json:"additionalProp2,omitempty"` + AdditionalProp3 AdditionalPropDetails `json:"additionalProp3,omitempty"` +} +type Resources struct { + GUID string `json:"guid,omitempty"` + ID string `json:"id,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Parameters []ParametersDetails `json:"parameters,omitempty"` + ParametersMap ParametersMap `json:"parametersMap,omitempty"` +} type Components struct { ID string `json:"id,omitempty"` ComponentID string `json:"componentID,omitempty"` Identifier string `json:"identifier,omitempty"` ComponentValid ComponentValid `json:"componentValid,omitempty"` - PuppetCertName string `json:"puppetCertName,omitempty"` - OsPuppetCertName string `json:"osPuppetCertName,omitempty"` Name string `json:"name,omitempty"` + HelpText string `json:"helpText,omitempty"` + ClonedFromID string `json:"clonedFromId,omitempty"` + Teardown bool `json:"teardown,omitempty"` Type string `json:"type,omitempty"` SubType string `json:"subType,omitempty"` - Teardown bool `json:"teardown,omitempty"` - HelpText any `json:"helpText,omitempty"` + RelatedComponents RelatedComponents `json:"relatedComponents,omitempty"` + Resources []Resources `json:"resources,omitempty"` + Brownfield bool `json:"brownfield,omitempty"` + PuppetCertName string `json:"puppetCertName,omitempty"` + OsPuppetCertName string `json:"osPuppetCertName,omitempty"` ManagementIPAddress string `json:"managementIpAddress,omitempty"` - ConfigFile any `json:"configFile,omitempty"` SerialNumber string `json:"serialNumber,omitempty"` AsmGUID string `json:"asmGUID,omitempty"` - RelatedComponents RelatedComponents `json:"relatedComponents,omitempty"` - Resources []any `json:"resources,omitempty"` - RefID string `json:"refId,omitempty"` Cloned bool `json:"cloned,omitempty"` - ClonedFromID any `json:"clonedFromId,omitempty"` + ConfigFile string `json:"configFile,omitempty"` ManageFirmware bool `json:"manageFirmware,omitempty"` - Brownfield bool `json:"brownfield,omitempty"` Instances int `json:"instances,omitempty"` + RefID string `json:"refId,omitempty"` ClonedFromAsmGUID string `json:"clonedFromAsmGuid,omitempty"` + Changed bool `json:"changed,omitempty"` IP string `json:"ip,omitempty"` } - -// FirmwareRepository defines struct for FirmwareRepository -type FirmwareRepository struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - SourceLocation any `json:"sourceLocation,omitempty"` - SourceType any `json:"sourceType,omitempty"` - DiskLocation any `json:"diskLocation,omitempty"` - Filename any `json:"filename,omitempty"` - Md5Hash any `json:"md5Hash,omitempty"` - Username any `json:"username,omitempty"` - Password any `json:"password,omitempty"` - DownloadStatus any `json:"downloadStatus,omitempty"` - CreatedDate any `json:"createdDate,omitempty"` - CreatedBy any `json:"createdBy,omitempty"` - UpdatedDate any `json:"updatedDate,omitempty"` - UpdatedBy any `json:"updatedBy,omitempty"` - DefaultCatalog bool `json:"defaultCatalog,omitempty"` - Embedded bool `json:"embedded,omitempty"` - State any `json:"state,omitempty"` - SoftwareComponents []any `json:"softwareComponents,omitempty"` - SoftwareBundles []any `json:"softwareBundles,omitempty"` - Deployments []any `json:"deployments,omitempty"` - BundleCount int `json:"bundleCount,omitempty"` - ComponentCount int `json:"componentCount,omitempty"` - UserBundleCount int `json:"userBundleCount,omitempty"` - Minimal bool `json:"minimal,omitempty"` - DownloadProgress int `json:"downloadProgress,omitempty"` - ExtractProgress int `json:"extractProgress,omitempty"` - FileSizeInGigabytes any `json:"fileSizeInGigabytes,omitempty"` - SignedKeySourceLocation any `json:"signedKeySourceLocation,omitempty"` - Signature any `json:"signature,omitempty"` - Custom bool `json:"custom,omitempty"` - NeedsAttention bool `json:"needsAttention,omitempty"` - JobID any `json:"jobId,omitempty"` - Rcmapproved bool `json:"rcmapproved,omitempty"` -} - -// StaticNetworkConfiguration defines struct for StaticNetworkConfiguration +type IPRange struct { + ID string `json:"id,omitempty"` + StartingIP string `json:"startingIp,omitempty"` + EndingIP string `json:"endingIp,omitempty"` + Role string `json:"role,omitempty"` +} +type StaticRoute struct { + StaticRouteSourceNetworkID string `json:"staticRouteSourceNetworkId,omitempty"` + StaticRouteDestinationNetworkID string `json:"staticRouteDestinationNetworkId,omitempty"` + StaticRouteGateway string `json:"staticRouteGateway,omitempty"` + SubnetMask string `json:"subnetMask,omitempty"` + DestinationIPAddress string `json:"destinationIpAddress,omitempty"` +} type StaticNetworkConfiguration struct { - Gateway string `json:"gateway,omitempty"` - Subnet string `json:"subnet,omitempty"` - PrimaryDNS string `json:"primaryDns,omitempty"` - SecondaryDNS string `json:"secondaryDns,omitempty"` - DNSSuffix string `json:"dnsSuffix,omitempty"` - IPRange []IPRange `json:"ipRange,omitempty"` - IPAddress string `json:"ipAddress,omitempty"` - StaticRoute string `json:"staticRoute,omitempty"` + Gateway string `json:"gateway,omitempty"` + Subnet string `json:"subnet,omitempty"` + PrimaryDNS string `json:"primaryDns,omitempty"` + SecondaryDNS string `json:"secondaryDns,omitempty"` + DNSSuffix string `json:"dnsSuffix,omitempty"` + IPRange []IPRange `json:"ipRange,omitempty"` + IPAddress string `json:"ipAddress,omitempty"` + StaticRoute []StaticRoute `json:"staticRoute,omitempty"` } - -// Networks defines struct for Networks type Networks struct { ID string `json:"id,omitempty"` Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` - Type string `json:"type,omitempty"` VlanID int `json:"vlanId,omitempty"` - Static bool `json:"static,omitempty"` StaticNetworkConfiguration StaticNetworkConfiguration `json:"staticNetworkConfiguration,omitempty"` DestinationIPAddress string `json:"destinationIpAddress,omitempty"` + Static bool `json:"static,omitempty"` + Type string `json:"type,omitempty"` +} +type Options struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Dependencies []DependenciesDetails `json:"dependencies,omitempty"` + Attributes Attributes `json:"attributes,omitempty"` +} +type Parameters struct { + ID string `json:"id,omitempty"` + Value string `json:"value,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Type string `json:"type,omitempty"` + ToolTip string `json:"toolTip,omitempty"` + Required bool `json:"required,omitempty"` + HideFromTemplate bool `json:"hideFromTemplate,omitempty"` + DeviceType string `json:"deviceType,omitempty"` + Dependencies []DependenciesDetails `json:"dependencies,omitempty"` + Group string `json:"group,omitempty"` + ReadOnly bool `json:"readOnly,omitempty"` + Generated bool `json:"generated,omitempty"` + InfoIcon bool `json:"infoIcon,omitempty"` + Step int `json:"step,omitempty"` + MaxLength int `json:"maxLength,omitempty"` + Min int `json:"min,omitempty"` + Max int `json:"max,omitempty"` + Networks []Networks `json:"networks,omitempty"` + Options []Options `json:"options,omitempty"` + OptionsSortable bool `json:"optionsSortable,omitempty"` } -// IPRange defines struct for IPRange -type IPRange struct { - ID string `json:"id"` - StartingIP string `json:"startingIp"` - EndingIP string `json:"endingIp"` - Role any `json:"role"` +type ParameterMap struct { + AdditionalProp1 AdditionalPropDetails `json:"additionalProp1,omitempty"` + AdditionalProp2 AdditionalPropDetails `json:"additionalProp2,omitempty"` + AdditionalProp3 AdditionalPropDetails `json:"additionalProp3,omitempty"` +} +type Categories struct { + ID string `json:"id,omitempty"` + DisplayName string `json:"displayName,omitempty"` + DeviceType string `json:"deviceType,omitempty"` + Parameters []Parameters `json:"parameters,omitempty"` + ParameterMap ParameterMap `json:"parameterMap,omitempty"` +} + +type CategoriesMap struct { + AdditionalProp1 AdditionalPropDetails `json:"additionalProp1,omitempty"` + AdditionalProp2 AdditionalPropDetails `json:"additionalProp2,omitempty"` + AdditionalProp3 AdditionalPropDetails `json:"additionalProp3,omitempty"` +} +type SettingsMap struct { + AdditionalProp1 AdditionalPropDetails `json:"additionalProp1,omitempty"` + AdditionalProp2 AdditionalPropDetails `json:"additionalProp2,omitempty"` + AdditionalProp3 AdditionalPropDetails `json:"additionalProp3,omitempty"` } -// BlockServiceOperationsMap defines struct for BlockServiceOperationsMap type BlockServiceOperationsMap struct { + AdditionalProp1 AdditionalPropDetails `json:"additionalProp1,omitempty"` + AdditionalProp2 AdditionalPropDetails `json:"additionalProp2,omitempty"` + AdditionalProp3 AdditionalPropDetails `json:"additionalProp3,omitempty"` } // TemplateDetailsFilter defines struct for nodepools diff --git a/types/v1/types.go b/types/v1/types.go index caa42fe5..3ac2ac1 100644 --- a/types/v1/types.go +++ b/types/v1/types.go @@ -187,8 +187,10 @@ type RenameMdm struct { // Link defines struct of Link type Link struct { - Rel string `json:"rel"` - HREF string `json:"href"` + Rel string `json:"rel"` + HREF string `json:"href"` + Title string `json:"title,omitempty"` + Type string `json:"type,omitempty"` } // BWC defines struct of BWC From ae2bf32d887b3160b7ce00cd595aad9bc704f98f Mon Sep 17 00:00:00 2001 From: root Date: Wed, 24 Jan 2024 03:47:49 -0500 Subject: [PATCH 03/21] Template Datasource --- types/v1/templateTypes.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/v1/templateTypes.go b/types/v1/templateTypes.go index 1d3a5a0..ed87085 100644 --- a/types/v1/templateTypes.go +++ b/types/v1/templateTypes.go @@ -677,10 +677,10 @@ type AccelerationPool struct { } type ProtectionDomainSettings struct { General General `json:"general,omitempty"` - Statistics Statistics `json:"statistics,omitempty"` + Statistics StatisticsDetails `json:"statistics,omitempty"` StoragePoolList []StoragePoolList `json:"storage_pool_list,omitempty"` SdsList []SdsListDetails `json:"sds_list,omitempty"` - SdrList []SdsListDetails `json:"sdr_list,omitempty"` + SdrList []SdrListDetails `json:"sdr_list,omitempty"` AccelerationPool []AccelerationPool `json:"acceleration_pool,omitempty"` } type FaultSetSettings struct { From 0fe44aa5ec477b953612af10d8838ca22fcd6177 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 24 Jan 2024 04:09:34 -0500 Subject: [PATCH 04/21] Template Datasource --- template.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template.go b/template.go index edd6f2e..3e88c00 100644 --- a/template.go +++ b/template.go @@ -53,7 +53,7 @@ func (c *Client) GetAllTemplates() ([]types.TemplateDetails, error) { func (c *Client) GetTemplateByFilters(key string, value string) ([]types.TemplateDetails, error) { defer TimeSpent("GetTemplateByFilters", time.Now()) - path := fmt.Sprintf("/Api/V1/template?filter=eq,%v,%v", key, value) + path := `/Api/V1/template?filter=`+key+`%20eq%20%22`+value+`%22` var templates types.TemplateDetailsFilter err := c.getJSONWithRetry(http.MethodGet, path, nil, &templates) From 41e978e9d8838c8991132b617089a656998f9d50 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 25 Jan 2024 06:15:57 -0500 Subject: [PATCH 05/21] Template Datasource --- template.go | 5 ++++- types/v1/types.go | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/template.go b/template.go index 3e88c00..02e98ea 100644 --- a/template.go +++ b/template.go @@ -16,6 +16,7 @@ import ( "errors" "fmt" "net/http" + "net/url" "time" types "github.com/dell/goscaleio/types/v1" @@ -53,7 +54,9 @@ func (c *Client) GetAllTemplates() ([]types.TemplateDetails, error) { func (c *Client) GetTemplateByFilters(key string, value string) ([]types.TemplateDetails, error) { defer TimeSpent("GetTemplateByFilters", time.Now()) - path := `/Api/V1/template?filter=`+key+`%20eq%20%22`+value+`%22` + encodedValue := url.QueryEscape(value) + + path := `/Api/V1/template?filter=` + key + `%20eq%20%22` + encodedValue + `%22` var templates types.TemplateDetailsFilter err := c.getJSONWithRetry(http.MethodGet, path, nil, &templates) diff --git a/types/v1/types.go b/types/v1/types.go index 3ac2ac1..0a9fbfa 100644 --- a/types/v1/types.go +++ b/types/v1/types.go @@ -1,4 +1,4 @@ -// Copyright © 2019 - 2023 Dell Inc. or its subsidiaries. All Rights Reserved. +// Copyright © 2019 - 2024 Dell Inc. or its subsidiaries. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From e7fb9725a74abeaad93e8eb28474f2472500feec Mon Sep 17 00:00:00 2001 From: root Date: Mon, 29 Jan 2024 04:53:52 -0500 Subject: [PATCH 06/21] Template Datasource --- template_test.go | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/template_test.go b/template_test.go index 962004d..eb3a73f 100644 --- a/template_test.go +++ b/template_test.go @@ -100,6 +100,43 @@ func TestGetTemplateByFilters(t *testing.T) { assert.NotNil(t, err) } +func TestGetTemplateByIDNegative(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintln(w, `{"error":"Internal Server Error"}`) + })) + defer svr.Close() + + client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) + client.configConnect.Version = "4.5" + if err != nil { + t.Fatal(err) + } + + templates, err := client.GetTemplateByID("Test") + assert.Nil(t, templates) + assert.NotNil(t, err) +} + + +func TestGetTemplateByFiltersNegative(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintln(w, `{"error":"Internal Server Error"}`) + })) + defer svr.Close() + + client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) + client.configConnect.Version = "4.5" + if err != nil { + t.Fatal(err) + } + + templates, err := client.GetTemplateByFilters("Name", "Test") + assert.Nil(t, templates) + assert.NotNil(t, err) +} + func TestGetAllTemplatesNegative(t *testing.T) { svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) @@ -113,7 +150,7 @@ func TestGetAllTemplatesNegative(t *testing.T) { t.Fatal(err) } - nodes, err := client.GetAllTemplates() - assert.Nil(t, nodes) + templates, err := client.GetAllTemplates() + assert.Nil(t, templates) assert.NotNil(t, err) } From 0410c307cdc823cdf907790faed8c05471ed3c42 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 2 Feb 2024 05:38:40 -0500 Subject: [PATCH 07/21] Service Resource and Datasource --- inttests/service_test.go | 57 ++++++++ service.go | 292 ++++++++++++++++++++++++++++++++++++++ types/v1/serviceTypes.go | 87 ++++++++++++ types/v1/templateTypes.go | 117 ++++++--------- 4 files changed, 482 insertions(+), 71 deletions(-) create mode 100644 inttests/service_test.go create mode 100644 service.go create mode 100644 types/v1/serviceTypes.go diff --git a/inttests/service_test.go b/inttests/service_test.go new file mode 100644 index 0000000..05d2912 --- /dev/null +++ b/inttests/service_test.go @@ -0,0 +1,57 @@ +// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package inttests + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDeployeService(t *testing.T) { + templates, err := GC.DeployService("Test-Create", "Test", "8150d563-639d-464e-80c4-a435ed10f132", "8aaaee208c8c467e018cd37813250614") + assert.Nil(t, err) + assert.NotNil(t, templates) +} + +func TestGetAllDeployeService(t *testing.T) { + templates, err := GC.GetAllServiceDetails() + assert.Nil(t, err) + assert.NotNil(t, templates) + + if len(templates) > 0 { + template, err := GC.GetServiceDetailsByID(templates[0].ID) + assert.Nil(t, err) + assert.NotNil(t, template) + } + + template, err := GC.GetServiceDetailsByID(invalidIdentifier) + assert.NotNil(t, err) + assert.Nil(t, template) +} + +func TestGetDeployeServiceByName(t *testing.T) { + templates, err := GC.GetAllServiceDetails() + assert.Nil(t, err) + assert.NotNil(t, templates) + + if len(templates) > 0 { + template, err := GC.GetServiceDetailsByName(templates[0].DeploymentName, "name") + assert.Nil(t, err) + assert.NotNil(t, template) + } + + template, err := GC.GetServiceDetailsByName("invalid", "invalid") + assert.NotNil(t, err) + assert.Nil(t, template) +} diff --git a/service.go b/service.go new file mode 100644 index 0000000..579dea4 --- /dev/null +++ b/service.go @@ -0,0 +1,292 @@ +// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package goscaleio + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "fmt" + "net/http" + "net/url" + "time" + + types "github.com/dell/goscaleio/types/v1" +) + +// DeployService used to deploy service +func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTemplateID, firmwareRepositoryId string) (*types.ServiceResponse, error) { + defer TimeSpent("DeployService", time.Now()) + + path := fmt.Sprintf("/Api/V1/ServiceTemplate/%v?forDeployment=true", serviceTemplateID) + + req, httpError := http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError + } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + setCookie(req.Header, gc.host) + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 { + var templateData map[string]interface{} + + parseError := json.Unmarshal([]byte(responseString), &templateData) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Template: %s", parseError) + } + + deploymentPayload := map[string]interface{}{ + "deploymentName": deploymentName, + "deploymentDesc": deploymentDesc, + "serviceTemplate": templateData, + "updateServerFirmware": true, + "firmwareRepositoryId": firmwareRepositoryId, //TODO + } + + deploymentPayloadJson, _ := json.Marshal(deploymentPayload) + + req, httpError := http.NewRequest("POST", gc.host+"/Api/V1/Deployment", bytes.NewBuffer(deploymentPayloadJson)) + if httpError != nil { + return nil, httpError + } + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + setCookie(req.Header, gc.host) + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, error := extractString(httpResp) + if error != nil { + return nil, fmt.Errorf("Error Extracting Response: %s", error) + } + + if httpResp.StatusCode == 200 { + + var deploymentResponse types.ServiceResponse + + parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + return &deploymentResponse, nil + + } else { + var deploymentResponse types.ServiceFailedResponse + + parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", deploymentResponse.Messages[0].DisplayMessage) + } + + } + + return nil, nil +} + +func (gc *GatewayClient) GetServiceDetailsByID(deploymentID string) (*types.ServiceResponse, error) { + + defer TimeSpent("GetServiceDetailsByID", time.Now()) + + path := fmt.Sprintf("/Api/V1/Deployment/%v", deploymentID) + + req, httpError := http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError + } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + setCookie(req.Header, gc.host) + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 { + + var deploymentResponse types.ServiceResponse + + parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + return &deploymentResponse, nil + + } else { + var deploymentResponse types.ServiceFailedResponse + + parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", deploymentResponse.Messages[0].DisplayMessage) + } +} + +func (gc *GatewayClient) GetServiceDetailsByName(value, filter string) (*types.ServiceResponse, error) { + + defer TimeSpent("GetServiceDetailsByName", time.Now()) + + encodedValue := url.QueryEscape(value) + + path := fmt.Sprintf("/Api/V1/Deployment?filter=eq,%v,%v", filter, encodedValue) + + req, httpError := http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError + } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + setCookie(req.Header, gc.host) + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 { + + var deploymentResponse []types.ServiceResponse + + parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + return &deploymentResponse[0], nil + + } else { + var deploymentResponse types.ServiceFailedResponse + + parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", deploymentResponse.Messages[0].DisplayMessage) + } +} + +func (gc *GatewayClient) GetAllServiceDetails() ([]types.ServiceResponse, error) { + + defer TimeSpent("DeploGetServiceDetailsByIDyService", time.Now()) + + req, httpError := http.NewRequest("GET", gc.host+"/Api/V1/Deployment/", nil) + if httpError != nil { + return nil, httpError + } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + setCookie(req.Header, gc.host) + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 { + + var deploymentResponse []types.ServiceResponse + + parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + return deploymentResponse, nil + + } else { + var deploymentResponse types.ServiceFailedResponse + + parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", deploymentResponse.Messages[0].DisplayMessage) + } +} diff --git a/types/v1/serviceTypes.go b/types/v1/serviceTypes.go new file mode 100644 index 0000000..5dbe01e --- /dev/null +++ b/types/v1/serviceTypes.go @@ -0,0 +1,87 @@ +package goscaleio + +type ServiceFailedResponse struct { + DetailMessage string `json:"detailMessage,omitempty"` + Status int `json:"status,omitempty"` + Timestamp string `json:"timestamp,omitempty"` + Error string `json:"error,omitempty"` + Path string `json:"path,omitempty"` + Messages []Messages `json:"messages,omitempty"` +} + +type DeploymentPayload struct { + DeploymentName string `json:"deploymentName,omitempty"` + DeploymentDescription string `json:"deploymentDescription,omitempty"` + ServiceTemplate TemplateDetails `json:"serviceTemplate,omitempty"` + UpdateServerFirmware bool `json:"updateServerFirmware,omitempty"` + FirmwareRepositoryID string `json:"firmwareRepositoryId,omitempty"` + Status string `json:"status,omitempty"` +} + +type ServiceResponse struct { + ID string `json:"id,omitempty"` + DeploymentName string `json:"deploymentName,omitempty"` + DeploymentDescription string `json:"deploymentDescription,omitempty"` + DeploymentValid DeploymentValid `json:"deploymentValid,omitempty"` + Retry bool `json:"retry,omitempty"` + Teardown bool `json:"teardown,omitempty"` + TeardownAfterCancel bool `json:"teardownAfterCancel,omitempty"` + RemoveService bool `json:"removeService,omitempty"` + CreatedDate string `json:"createdDate,omitempty"` + CreatedBy string `json:"createdBy,omitempty"` + UpdatedDate string `json:"updatedDate,omitempty"` + UpdatedBy string `json:"updatedBy,omitempty"` + DeploymentScheduledDate string `json:"deploymentScheduledDate,omitempty"` + DeploymentStartedDate string `json:"deploymentStartedDate,omitempty"` + DeploymentFinishedDate string `json:"deploymentFinishedDate,omitempty"` + ScheduleDate string `json:"scheduleDate,omitempty"` + Status string `json:"status,omitempty"` + Compliant bool `json:"compliant,omitempty"` + DeploymentDevice []DeploymentDevice `json:"deploymentDevice,omitempty"` + Vms []Vms `json:"vms,omitempty"` + UpdateServerFirmware bool `json:"updateServerFirmware,omitempty"` + UseDefaultCatalog bool `json:"useDefaultCatalog,omitempty"` + FirmwareRepository FirmwareRepository `json:"firmwareRepository,omitempty"` + FirmwareRepositoryID string `json:"firmwareRepositoryId,omitempty"` + LicenseRepository LicenseRepository `json:"licenseRepository,omitempty"` + LicenseRepositoryID string `json:"licenseRepositoryId,omitempty"` + IndividualTeardown bool `json:"individualTeardown,omitempty"` + DeploymentHealthStatusType string `json:"deploymentHealthStatusType,omitempty"` + AssignedUsers []AssignedUsers `json:"assignedUsers,omitempty"` + AllUsersAllowed bool `json:"allUsersAllowed,omitempty"` + Owner string `json:"owner,omitempty"` + NoOp bool `json:"noOp,omitempty"` + FirmwareInit bool `json:"firmwareInit,omitempty"` + DisruptiveFirmware bool `json:"disruptiveFirmware,omitempty"` + PreconfigureSVM bool `json:"preconfigureSVM,omitempty"` + PreconfigureSVMAndUpdate bool `json:"preconfigureSVMAndUpdate,omitempty"` + ServicesDeployed string `json:"servicesDeployed,omitempty"` + PrecalculatedDeviceHealth string `json:"precalculatedDeviceHealth,omitempty"` + LifecycleModeReasons []string `json:"lifecycleModeReasons,omitempty"` + JobDetails []JobDetails `json:"jobDetails,omitempty"` + NumberOfDeployments int `json:"numberOfDeployments,omitempty"` + OperationType string `json:"operationType,omitempty"` + OperationStatus string `json:"operationStatus,omitempty"` + OperationData string `json:"operationData,omitempty"` + DeploymentValidationResponse DeploymentValidationResponse `json:"deploymentValidationResponse,omitempty"` + CurrentStepCount string `json:"currentStepCount,omitempty"` + TotalNumOfSteps string `json:"totalNumOfSteps,omitempty"` + CurrentStepMessage string `json:"currentStepMessage,omitempty"` + CustomImage string `json:"customImage,omitempty"` + OriginalDeploymentID string `json:"originalDeploymentId,omitempty"` + CurrentBatchCount string `json:"currentBatchCount,omitempty"` + TotalBatchCount string `json:"totalBatchCount,omitempty"` + Brownfield bool `json:"brownfield,omitempty"` + OverallDeviceHealth string `json:"overallDeviceHealth,omitempty"` + Vds bool `json:"vds,omitempty"` + ScaleUp bool `json:"scaleUp,omitempty"` + LifecycleMode bool `json:"lifecycleMode,omitempty"` + CanMigratevCLSVMs bool `json:"canMigratevCLSVMs,omitempty"` + TemplateValid bool `json:"templateValid,omitempty"` + ConfigurationChange bool `json:"configurationChange,omitempty"` + DetailMessage string `json:"detailMessage,omitempty"` + Timestamp string `json:"timestamp,omitempty"` + Error string `json:"error,omitempty"` + Path string `json:"path,omitempty"` + Messages []Messages `json:"messages,omitempty"` +} diff --git a/types/v1/templateTypes.go b/types/v1/templateTypes.go index ed87085..86e1f2d 100644 --- a/types/v1/templateTypes.go +++ b/types/v1/templateTypes.go @@ -13,40 +13,40 @@ package goscaleio type TemplateDetails struct { - ID string `json:"id,omitempty"` - TemplateName string `json:"templateName,omitempty"` - TemplateDescription string `json:"templateDescription,omitempty"` - TemplateType string `json:"templateType,omitempty"` - TemplateVersion string `json:"templateVersion,omitempty"` - OriginalTemplateID string `json:"originalTemplateId,omitempty"` - TemplateValid TemplateValid `json:"templateValid,omitempty"` - TemplateLocked bool `json:"templateLocked,omitempty"` - InConfiguration bool `json:"inConfiguration,omitempty"` - CreatedDate string `json:"createdDate,omitempty"` - CreatedBy string `json:"createdBy,omitempty"` - UpdatedDate string `json:"updatedDate,omitempty"` - LastDeployedDate string `json:"lastDeployedDate,omitempty"` - UpdatedBy string `json:"updatedBy,omitempty"` - ManageFirmware bool `json:"manageFirmware,omitempty"` - UseDefaultCatalog bool `json:"useDefaultCatalog,omitempty"` - FirmwareRepository FirmwareRepository `json:"firmwareRepository,omitempty"` - LicenseRepository LicenseRepository `json:"licenseRepository,omitempty"` - AssignedUsers []AssignedUsers `json:"assignedUsers,omitempty"` - AllUsersAllowed bool `json:"allUsersAllowed,omitempty"` - Category string `json:"category,omitempty"` - Components []Components `json:"components,omitempty"` - Configuration ConfigurationDetails `json:"configuration,omitempty"` - ServerCount int `json:"serverCount,omitempty"` - StorageCount int `json:"storageCount,omitempty"` - ClusterCount int `json:"clusterCount,omitempty"` - ServiceCount int `json:"serviceCount,omitempty"` - SwitchCount int `json:"switchCount,omitempty"` - VMCount int `json:"vmCount,omitempty"` - SdnasCount int `json:"sdnasCount,omitempty"` - BrownfieldTemplateType string `json:"brownfieldTemplateType,omitempty"` - Networks []Networks `json:"networks,omitempty"` - BlockServiceOperationsMap BlockServiceOperationsMap `json:"blockServiceOperationsMap,omitempty"` - Draft bool `json:"draft,omitempty"` + ID string `json:"id,omitempty"` + TemplateName string `json:"templateName,omitempty"` + TemplateDescription string `json:"templateDescription,omitempty"` + TemplateType string `json:"templateType,omitempty"` + TemplateVersion string `json:"templateVersion,omitempty"` + OriginalTemplateID string `json:"originalTemplateId,omitempty"` + TemplateValid TemplateValid `json:"templateValid,omitempty"` + TemplateLocked bool `json:"templateLocked,omitempty"` + InConfiguration bool `json:"inConfiguration,omitempty"` + CreatedDate string `json:"createdDate,omitempty"` + CreatedBy string `json:"createdBy,omitempty"` + UpdatedDate string `json:"updatedDate,omitempty"` + LastDeployedDate string `json:"lastDeployedDate,omitempty"` + UpdatedBy string `json:"updatedBy,omitempty"` + ManageFirmware bool `json:"manageFirmware,omitempty"` + UseDefaultCatalog bool `json:"useDefaultCatalog,omitempty"` + FirmwareRepository FirmwareRepository `json:"firmwareRepository,omitempty"` + LicenseRepository LicenseRepository `json:"licenseRepository,omitempty"` + AssignedUsers []AssignedUsers `json:"assignedUsers,omitempty"` + AllUsersAllowed bool `json:"allUsersAllowed,omitempty"` + Category string `json:"category,omitempty"` + Components []Components `json:"components,omitempty"` + Configuration ConfigurationDetails `json:"configuration,omitempty"` + ServerCount int `json:"serverCount,omitempty"` + StorageCount int `json:"storageCount,omitempty"` + ClusterCount int `json:"clusterCount,omitempty"` + ServiceCount int `json:"serviceCount,omitempty"` + SwitchCount int `json:"switchCount,omitempty"` + VMCount int `json:"vmCount,omitempty"` + SdnasCount int `json:"sdnasCount,omitempty"` + BrownfieldTemplateType string `json:"brownfieldTemplateType,omitempty"` + Networks []Networks `json:"networks,omitempty"` + NetworksMap map[string]Networks `json:"networksMap,omitempty"` + Draft bool `json:"draft,omitempty"` } type Messages struct { @@ -402,16 +402,14 @@ type NetworkConfiguration struct { } type ConfigurationDetails struct { - ID string `json:"id,omitempty"` - Disktype string `json:"disktype,omitempty"` - Comparator string `json:"comparator,omitempty"` - Numberofdisks int `json:"numberofdisks,omitempty"` - Raidlevel string `json:"raidlevel,omitempty"` - VirtualDiskFqdd string `json:"virtualDiskFqdd,omitempty"` - ControllerFqdd string `json:"controllerFqdd,omitempty"` - Categories []Categories `json:"categories,omitempty"` - CategoriesMap CategoriesMap `json:"categoriesMap,omitempty"` - SettingsMap SettingsMap `json:"settingsMap,omitempty"` + ID string `json:"id,omitempty"` + Disktype string `json:"disktype,omitempty"` + Comparator string `json:"comparator,omitempty"` + Numberofdisks int `json:"numberofdisks,omitempty"` + Raidlevel string `json:"raidlevel,omitempty"` + VirtualDiskFqdd string `json:"virtualDiskFqdd,omitempty"` + ControllerFqdd string `json:"controllerFqdd,omitempty"` + Categories []Categories `json:"categories,omitempty"` } type VirtualDisks struct { @@ -899,34 +897,11 @@ type Parameters struct { OptionsSortable bool `json:"optionsSortable,omitempty"` } -type ParameterMap struct { - AdditionalProp1 AdditionalPropDetails `json:"additionalProp1,omitempty"` - AdditionalProp2 AdditionalPropDetails `json:"additionalProp2,omitempty"` - AdditionalProp3 AdditionalPropDetails `json:"additionalProp3,omitempty"` -} type Categories struct { - ID string `json:"id,omitempty"` - DisplayName string `json:"displayName,omitempty"` - DeviceType string `json:"deviceType,omitempty"` - Parameters []Parameters `json:"parameters,omitempty"` - ParameterMap ParameterMap `json:"parameterMap,omitempty"` -} - -type CategoriesMap struct { - AdditionalProp1 AdditionalPropDetails `json:"additionalProp1,omitempty"` - AdditionalProp2 AdditionalPropDetails `json:"additionalProp2,omitempty"` - AdditionalProp3 AdditionalPropDetails `json:"additionalProp3,omitempty"` -} -type SettingsMap struct { - AdditionalProp1 AdditionalPropDetails `json:"additionalProp1,omitempty"` - AdditionalProp2 AdditionalPropDetails `json:"additionalProp2,omitempty"` - AdditionalProp3 AdditionalPropDetails `json:"additionalProp3,omitempty"` -} - -type BlockServiceOperationsMap struct { - AdditionalProp1 AdditionalPropDetails `json:"additionalProp1,omitempty"` - AdditionalProp2 AdditionalPropDetails `json:"additionalProp2,omitempty"` - AdditionalProp3 AdditionalPropDetails `json:"additionalProp3,omitempty"` + ID string `json:"id,omitempty"` + DisplayName string `json:"displayName,omitempty"` + DeviceType string `json:"deviceType,omitempty"` + Parameters []Parameters `json:"parameters,omitempty"` } // TemplateDetailsFilter defines struct for nodepools From 7dc118aa99aec928e57cc7f4a58d7eed97fff56b Mon Sep 17 00:00:00 2001 From: root Date: Sun, 4 Feb 2024 11:23:07 -0500 Subject: [PATCH 08/21] Service Resource and Datasource --- inttests/service_test.go | 4 +- service.go | 6 +- service_test.go | 149 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 service_test.go diff --git a/inttests/service_test.go b/inttests/service_test.go index 05d2912..86e5f81 100644 --- a/inttests/service_test.go +++ b/inttests/service_test.go @@ -46,12 +46,12 @@ func TestGetDeployeServiceByName(t *testing.T) { assert.NotNil(t, templates) if len(templates) > 0 { - template, err := GC.GetServiceDetailsByName(templates[0].DeploymentName, "name") + template, err := GC.GetServiceDetailsByFilter(templates[0].DeploymentName, "name") assert.Nil(t, err) assert.NotNil(t, template) } - template, err := GC.GetServiceDetailsByName("invalid", "invalid") + template, err := GC.GetServiceDetailsByFilter("invalid", "invalid") assert.NotNil(t, err) assert.Nil(t, template) } diff --git a/service.go b/service.go index 579dea4..1fccad1 100644 --- a/service.go +++ b/service.go @@ -181,9 +181,9 @@ func (gc *GatewayClient) GetServiceDetailsByID(deploymentID string) (*types.Serv } } -func (gc *GatewayClient) GetServiceDetailsByName(value, filter string) (*types.ServiceResponse, error) { +func (gc *GatewayClient) GetServiceDetailsByFilter(value, filter string) ([]types.ServiceResponse, error) { - defer TimeSpent("GetServiceDetailsByName", time.Now()) + defer TimeSpent("GetServiceDetailsByFilter", time.Now()) encodedValue := url.QueryEscape(value) @@ -223,7 +223,7 @@ func (gc *GatewayClient) GetServiceDetailsByName(value, filter string) (*types.S return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) } - return &deploymentResponse[0], nil + return deploymentResponse, nil } else { var deploymentResponse types.ServiceFailedResponse diff --git a/service_test.go b/service_test.go new file mode 100644 index 0000000..2e5f2dc --- /dev/null +++ b/service_test.go @@ -0,0 +1,149 @@ +// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package goscaleio + +import ( + "errors" + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetAllDeployeService(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNoContent) + })) + defer svr.Close() + + GC, err := NewGateway(svr.URL, "", "", true, true) + if err != nil { + t.Fatal(err) + } + + templateDetails, err := GC.GetAllServiceDetails() + assert.Equal(t, len(templateDetails), 0) + assert.Nil(t, err) +} + +func TestGetDeployeServiceByID(t *testing.T) { + type testCase struct { + id string + expected error + } + + cases := []testCase{ + { + id: "sdnasgw", + expected: nil, + }, + { + id: "sdnasgw1", + expected: errors.New("The template cannot be found"), + }, + } + + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + })) + defer svr.Close() + + for _, tc := range cases { + tc := tc + t.Run("", func(ts *testing.T) { + GC, err := NewGateway(svr.URL, "", "", true, true) + if err != nil { + t.Fatal(err) + } + + _, err = GC.GetServiceDetailsByID(tc.id) + if err != nil { + if tc.expected == nil { + t.Errorf("Getting template by ID did not work as expected, \n\tgot: %s \n\twant: %v", err, tc.expected) + } else { + if err.Error() != tc.expected.Error() { + t.Errorf("Getting template by ID did not work as expected, \n\tgot: %s \n\twant: %s", err, tc.expected) + } + } + } + }) + } +} + +func TestGetDeployeServiceByFilters(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNoContent) + })) + defer svr.Close() + + client, err := NewGateway(svr.URL, "", "", true, true) + if err != nil { + t.Fatal(err) + } + + templates, err := client.GetServiceDetailsByFilter("Name", "Test") + assert.Equal(t, len(templates), 0) + assert.NotNil(t, err) +} + +func TestGetDeployeServiceByIDNegative(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintln(w, `{"error":"Internal Server Error"}`) + })) + defer svr.Close() + + client, err := NewGateway(svr.URL, "", "", true, true) + if err != nil { + t.Fatal(err) + } + + templates, err := client.GetServiceDetailsByID("Test") + assert.Nil(t, templates) + assert.NotNil(t, err) +} + +func TestGetDeployeServiceByFiltersNegative(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintln(w, `{"error":"Internal Server Error"}`) + })) + defer svr.Close() + + client, err := NewGateway(svr.URL, "", "", true, true) + if err != nil { + t.Fatal(err) + } + + templates, err := client.GetServiceDetailsByFilter("Name", "Test") + assert.Nil(t, templates) + assert.NotNil(t, err) +} + +func TestGetAllDeployeServiceNegative(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintln(w, `{"error":"Internal Server Error"}`) + })) + defer svr.Close() + + client, err := NewGateway(svr.URL, "", "", true, true) + if err != nil { + t.Fatal(err) + } + + templates, err := client.GetAllServiceDetails() + assert.Nil(t, templates) + assert.NotNil(t, err) +} From a441d424b2600a918a4530c897d1e8d64ac76360 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Feb 2024 07:20:29 -0500 Subject: [PATCH 09/21] Service Resource and Datasource --- service.go | 102 ++++++++++++++++++++++++++++++++++++++- service_test.go | 4 +- types/v1/serviceTypes.go | 3 ++ 3 files changed, 105 insertions(+), 4 deletions(-) diff --git a/service.go b/service.go index 1fccad1..2b915e8 100644 --- a/service.go +++ b/service.go @@ -17,11 +17,13 @@ import ( "encoding/base64" "encoding/json" "fmt" + "io" "net/http" "net/url" "time" types "github.com/dell/goscaleio/types/v1" + log "github.com/sirupsen/logrus" ) // DeployService used to deploy service @@ -103,6 +105,8 @@ func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTe parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + deploymentResponse.StatusCode = 200 + if parseError != nil { return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) } @@ -114,6 +118,8 @@ func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTe parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + deploymentResponse.StatusCode = 400 + if parseError != nil { return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) } @@ -126,10 +132,62 @@ func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTe return nil, nil } -func (gc *GatewayClient) GetServiceDetailsByID(deploymentID string) (*types.ServiceResponse, error) { +func (gc *GatewayClient) GetServiceDetailsByID(deploymentID string, newToken bool) (*types.ServiceResponse, error) { defer TimeSpent("GetServiceDetailsByID", time.Now()) + if newToken { + bodyData := map[string]interface{}{ + "username": gc.username, + "password": gc.password, + } + + body, _ := json.Marshal(bodyData) + + req, err := http.NewRequest("POST", gc.host+"/rest/auth/login", bytes.NewBuffer(body)) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", "application/json") + + resp, err := gc.http.Do(req) + if err != nil { + return nil, err + } + + defer func() { + if err := resp.Body.Close(); err != nil { + doLog(log.WithError(err).Error, "") + } + }() + + // parse the response + switch { + case resp == nil: + return nil, errNilReponse + case !(resp.StatusCode >= 200 && resp.StatusCode <= 299): + return nil, gc.api.ParseJSONError(resp) + } + + bs, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + responseBody := string(bs) + + result := make(map[string]interface{}) + jsonErr := json.Unmarshal([]byte(responseBody), &result) + if err != nil { + return nil, fmt.Errorf("Error For Uploading Package: %s", jsonErr) + } + + token := result["access_token"].(string) + + gc.token = token + } + path := fmt.Sprintf("/Api/V1/Deployment/%v", deploymentID) req, httpError := http.NewRequest("GET", gc.host+path, nil) @@ -181,7 +239,7 @@ func (gc *GatewayClient) GetServiceDetailsByID(deploymentID string) (*types.Serv } } -func (gc *GatewayClient) GetServiceDetailsByFilter(value, filter string) ([]types.ServiceResponse, error) { +func (gc *GatewayClient) GetServiceDetailsByFilter(filter, value string) ([]types.ServiceResponse, error) { defer TimeSpent("GetServiceDetailsByFilter", time.Now()) @@ -290,3 +348,43 @@ func (gc *GatewayClient) GetAllServiceDetails() ([]types.ServiceResponse, error) return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", deploymentResponse.Messages[0].DisplayMessage) } } + +func (gc *GatewayClient) DeleteService(serviceId string) (*types.ServiceResponse, error) { + + var deploymentResponse types.ServiceResponse + + deploymentResponse.StatusCode = 400 + + defer TimeSpent("DeleteService", time.Now()) + + req, httpError := http.NewRequest("DELETE", gc.host+"/Api/V1/Deployment/"+serviceId, nil) + if httpError != nil { + return nil, httpError + } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + setCookie(req.Header, gc.host) + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + if httpResp.StatusCode == 204 { + + deploymentResponse.StatusCode = 200 + + return &deploymentResponse, nil + } + + return &deploymentResponse, nil +} diff --git a/service_test.go b/service_test.go index 2e5f2dc..38ed2ae 100644 --- a/service_test.go +++ b/service_test.go @@ -67,7 +67,7 @@ func TestGetDeployeServiceByID(t *testing.T) { t.Fatal(err) } - _, err = GC.GetServiceDetailsByID(tc.id) + _, err = GC.GetServiceDetailsByID(tc.id,false) if err != nil { if tc.expected == nil { t.Errorf("Getting template by ID did not work as expected, \n\tgot: %s \n\twant: %v", err, tc.expected) @@ -109,7 +109,7 @@ func TestGetDeployeServiceByIDNegative(t *testing.T) { t.Fatal(err) } - templates, err := client.GetServiceDetailsByID("Test") + templates, err := client.GetServiceDetailsByID("Test",false) assert.Nil(t, templates) assert.NotNil(t, err) } diff --git a/types/v1/serviceTypes.go b/types/v1/serviceTypes.go index 5dbe01e..3a23b2d 100644 --- a/types/v1/serviceTypes.go +++ b/types/v1/serviceTypes.go @@ -3,6 +3,7 @@ package goscaleio type ServiceFailedResponse struct { DetailMessage string `json:"detailMessage,omitempty"` Status int `json:"status,omitempty"` + StatusCode int `json:"statusCode,omitempty"` Timestamp string `json:"timestamp,omitempty"` Error string `json:"error,omitempty"` Path string `json:"path,omitempty"` @@ -34,6 +35,7 @@ type ServiceResponse struct { DeploymentScheduledDate string `json:"deploymentScheduledDate,omitempty"` DeploymentStartedDate string `json:"deploymentStartedDate,omitempty"` DeploymentFinishedDate string `json:"deploymentFinishedDate,omitempty"` + ServiceTemplate TemplateDetails `json:"serviceTemplate"` ScheduleDate string `json:"scheduleDate,omitempty"` Status string `json:"status,omitempty"` Compliant bool `json:"compliant,omitempty"` @@ -84,4 +86,5 @@ type ServiceResponse struct { Error string `json:"error,omitempty"` Path string `json:"path,omitempty"` Messages []Messages `json:"messages,omitempty"` + StatusCode int `json:"statusCode,omitempty"` } From 64e808c109262d6f36e9a4150880db188f0a55d5 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Feb 2024 12:03:43 -0500 Subject: [PATCH 10/21] Service Resource and Datasource --- service.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/service.go b/service.go index 2b915e8..a780819 100644 --- a/service.go +++ b/service.go @@ -66,11 +66,11 @@ func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTe } deploymentPayload := map[string]interface{}{ - "deploymentName": deploymentName, - "deploymentDesc": deploymentDesc, - "serviceTemplate": templateData, - "updateServerFirmware": true, - "firmwareRepositoryId": firmwareRepositoryId, //TODO + "deploymentName": deploymentName, + "deploymentDescription": deploymentDesc, + "serviceTemplate": templateData, + "updateServerFirmware": true, + "firmwareRepositoryId": firmwareRepositoryId, //TODO } deploymentPayloadJson, _ := json.Marshal(deploymentPayload) @@ -357,7 +357,7 @@ func (gc *GatewayClient) DeleteService(serviceId string) (*types.ServiceResponse defer TimeSpent("DeleteService", time.Now()) - req, httpError := http.NewRequest("DELETE", gc.host+"/Api/V1/Deployment/"+serviceId, nil) + req, httpError := http.NewRequest("DELETE", gc.host+"/Api/V1/Deployment/"+serviceId+"?serversInInventory=remove&resourceState=managed", nil) if httpError != nil { return nil, httpError } From 0fba0de15312d7d87fd0ad328eeafb88fb73b2f5 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 19 Feb 2024 04:55:56 -0500 Subject: [PATCH 11/21] Service Resource --- inttests/service_test.go | 7 +- service.go | 225 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 228 insertions(+), 4 deletions(-) diff --git a/inttests/service_test.go b/inttests/service_test.go index 86e5f81..0b13eef 100644 --- a/inttests/service_test.go +++ b/inttests/service_test.go @@ -30,12 +30,15 @@ func TestGetAllDeployeService(t *testing.T) { assert.NotNil(t, templates) if len(templates) > 0 { - template, err := GC.GetServiceDetailsByID(templates[0].ID) + template, err := GC.GetServiceDetailsByID(templates[0].ID, false) assert.Nil(t, err) assert.NotNil(t, template) + + _, err = GC.UpdateService(templates[0].ID, "Test-Update - Krunal", "Test-Update - Krunal", 1) + assert.Nil(t, err) } - template, err := GC.GetServiceDetailsByID(invalidIdentifier) + template, err := GC.GetServiceDetailsByID(invalidIdentifier, false) assert.NotNil(t, err) assert.Nil(t, template) } diff --git a/service.go b/service.go index a780819..6e91760 100644 --- a/service.go +++ b/service.go @@ -23,11 +23,12 @@ import ( "time" types "github.com/dell/goscaleio/types/v1" + "github.com/google/uuid" log "github.com/sirupsen/logrus" ) // DeployService used to deploy service -func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTemplateID, firmwareRepositoryId string) (*types.ServiceResponse, error) { +func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTemplateID, firmwareRepositoryID string) (*types.ServiceResponse, error) { defer TimeSpent("DeployService", time.Now()) path := fmt.Sprintf("/Api/V1/ServiceTemplate/%v?forDeployment=true", serviceTemplateID) @@ -70,7 +71,7 @@ func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTe "deploymentDescription": deploymentDesc, "serviceTemplate": templateData, "updateServerFirmware": true, - "firmwareRepositoryId": firmwareRepositoryId, //TODO + "firmwareRepositoryId": firmwareRepositoryID, //TODO } deploymentPayloadJson, _ := json.Marshal(deploymentPayload) @@ -132,6 +133,226 @@ func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTe return nil, nil } +func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentDesc string, nodes int) (*types.ServiceResponse, error) { + defer TimeSpent("UpdateService", time.Now()) + + path := fmt.Sprintf("/Api/V1/Deployment/%v", deploymentID) + + req, httpError := http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError + } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + setCookie(req.Header, gc.host) + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 { + + var deploymentPayloadJson []byte + + if nodes > 0 { + + var deploymentData map[string]interface{} + + uuid := uuid.New().String() + + parseError := json.Unmarshal([]byte(responseString), &deploymentData) + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + deploymentData["deploymentName"] = deploymentName + + deploymentData["deploymentDescription"] = deploymentDesc + + // Access the "components" field + serviceTemplate, ok := deploymentData["serviceTemplate"].(map[string]interface{}) + if !ok { + fmt.Println("Error: serviceTemplate field not found or not a map[string]interface{}") + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", ok) + } + + components, ok := serviceTemplate["components"].([]interface{}) + if !ok { + fmt.Println("Error: components field not found or not a []interface{}") + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", ok) + } + + // Find the component with type "SERVER" + var clonedComponent map[string]interface{} + + for _, comp := range components { + comp := comp.(map[string]interface{}) + if comp["type"].(string) == "SERVER" { + clonedComponent = comp + break + } + } + + // Modify ID and GUID of the cloned component + clonedComponent["id"] = uuid + clonedComponent["name"] = uuid + clonedComponent["brownfield"] = false + + clonedComponent["identifier"] = nil + clonedComponent["asmGUID"] = nil + clonedComponent["puppetCertName"] = nil + clonedComponent["osPuppetCertName"] = nil + clonedComponent["managementIpAddress"] = nil + + resources, ok := clonedComponent["resources"].([]interface{}) + if !ok { + fmt.Println("Error: components field not found or not a []interface{}") + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", ok) + } + + excludeList := map[string]bool{ + "razor_image": true, + "scaleio_enabled": true, + "scaleio_role": true, + "compression_enabled": true, + "replication_enabled": true, + } + + for _, comp := range resources { + comp := comp.(map[string]interface{}) + if comp["id"].(string) == "asm::server" { + + parameters, ok := comp["parameters"].([]interface{}) + if !ok { + fmt.Println("Error: components field not found or not a []interface{}") + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", ok) + } + + for _, parameter := range parameters { + parameter := parameter.(map[string]interface{}) + if !excludeList[parameter["id"].(string)] { + parameter["guid"] = nil + parameter["value"] = nil + } + } + } + } + + clonedComponent["resources"] = resources + + // Append the cloned component back to the components array + components = append(components, clonedComponent) + + serviceTemplate["components"] = components + + deploymentData["scaleUp"] = true + deploymentData["retry"] = true + + deploymentPayloadJson, _ = json.Marshal(deploymentData) + + } else { + + deploymentResponse, jsonParseError := jsonToMap(responseString) + if jsonParseError != nil { + return nil, jsonParseError + } + + deploymentResponse["deploymentName"] = deploymentName + + deploymentResponse["deploymentDescription"] = deploymentDesc + + deploymentPayloadJson, _ = json.Marshal(deploymentResponse) + } + + req, httpError := http.NewRequest("PUT", gc.host+"/Api/V1/Deployment/"+deploymentID, bytes.NewBuffer(deploymentPayloadJson)) + if httpError != nil { + return nil, httpError + } + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + setCookie(req.Header, gc.host) + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, error := extractString(httpResp) + if error != nil { + return nil, fmt.Errorf("Error Extracting Response: %s", error) + } + + if httpResp.StatusCode == 200 { + + var deploymentResponse types.ServiceResponse + + parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + + deploymentResponse.StatusCode = 200 + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + return &deploymentResponse, nil + + } else { + var deploymentResponse types.ServiceFailedResponse + + parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + + deploymentResponse.StatusCode = 400 + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", deploymentResponse.Messages[0].DisplayMessage) + } + + //return nil, fmt.Errorf("Error While Parsing Response Data For Deployment:") + + } else { + var deploymentResponse types.ServiceFailedResponse + + parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", deploymentResponse.Messages[0].DisplayMessage) + } +} + +// Function to check if string is not present in list +func contains(list []string, str string) bool { + for _, s := range list { + if s == str { + return true + } + } + return false +} + func (gc *GatewayClient) GetServiceDetailsByID(deploymentID string, newToken bool) (*types.ServiceResponse, error) { defer TimeSpent("GetServiceDetailsByID", time.Now()) From 4a71c8001ed109e2a54752ea730fbb1ab1800a6f Mon Sep 17 00:00:00 2001 From: root Date: Mon, 19 Feb 2024 05:03:59 -0500 Subject: [PATCH 12/21] Service Resource --- template_test.go | 158 +---------------------------------------------- 1 file changed, 1 insertion(+), 157 deletions(-) diff --git a/template_test.go b/template_test.go index 144115f..bc79acf 100644 --- a/template_test.go +++ b/template_test.go @@ -152,160 +152,4 @@ func TestGetAllTemplatesNegative(t *testing.T) { templates, err := client.GetAllTemplates() assert.Nil(t, templates) assert.NotNil(t, err) -} -// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package goscaleio - -import ( - "errors" - "fmt" - "math" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestGetTemplates(t *testing.T) { - svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNoContent) - })) - defer svr.Close() - - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" - if err != nil { - t.Fatal(err) - } - - templateDetails, err := client.GetAllTemplates() - assert.Equal(t, len(templateDetails), 0) - assert.Nil(t, err) -} - -func TestGetTemplateByID(t *testing.T) { - type testCase struct { - id string - expected error - } - - cases := []testCase{ - { - id: "sdnasgw", - expected: nil, - }, - { - id: "sdnasgw1", - expected: errors.New("The template cannot be found"), - }, - } - - svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - })) - defer svr.Close() - - for _, tc := range cases { - tc := tc - t.Run("", func(ts *testing.T) { - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - if err != nil { - t.Fatal(err) - } - - _, err = client.GetTemplateByID(tc.id) - if err != nil { - if tc.expected == nil { - t.Errorf("Getting template by ID did not work as expected, \n\tgot: %s \n\twant: %v", err, tc.expected) - } else { - if err.Error() != tc.expected.Error() { - t.Errorf("Getting template by ID did not work as expected, \n\tgot: %s \n\twant: %s", err, tc.expected) - } - } - } - }) - } -} - -func TestGetTemplateByFilters(t *testing.T) { - svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNoContent) - })) - defer svr.Close() - - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" - if err != nil { - t.Fatal(err) - } - - templates, err := client.GetTemplateByFilters("Name", "Test") - assert.Equal(t, len(templates), 0) - assert.NotNil(t, err) -} - -func TestGetTemplateByIDNegative(t *testing.T) { - svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintln(w, `{"error":"Internal Server Error"}`) - })) - defer svr.Close() - - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" - if err != nil { - t.Fatal(err) - } - - templates, err := client.GetTemplateByID("Test") - assert.Nil(t, templates) - assert.NotNil(t, err) -} - - -func TestGetTemplateByFiltersNegative(t *testing.T) { - svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintln(w, `{"error":"Internal Server Error"}`) - })) - defer svr.Close() - - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" - if err != nil { - t.Fatal(err) - } - - templates, err := client.GetTemplateByFilters("Name", "Test") - assert.Nil(t, templates) - assert.NotNil(t, err) -} - -func TestGetAllTemplatesNegative(t *testing.T) { - svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintln(w, `{"error":"Internal Server Error"}`) - })) - defer svr.Close() - - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" - if err != nil { - t.Fatal(err) - } - - templates, err := client.GetAllTemplates() - assert.Nil(t, templates) - assert.NotNil(t, err) -} +} \ No newline at end of file From 9229ae9c100e5aec4c46a9c4773ce25d70b9279f Mon Sep 17 00:00:00 2001 From: root Date: Mon, 19 Feb 2024 23:52:30 -0500 Subject: [PATCH 13/21] Service Resource --- service.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/service.go b/service.go index 6e91760..6c0224f 100644 --- a/service.go +++ b/service.go @@ -195,16 +195,22 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD } // Find the component with type "SERVER" - var clonedComponent map[string]interface{} + var serverComponent map[string]interface{} for _, comp := range components { comp := comp.(map[string]interface{}) if comp["type"].(string) == "SERVER" { - clonedComponent = comp + serverComponent = comp break } } + // Deep copy the component + clonedComponent := make(map[string]interface{}) + for key, value := range serverComponent { + clonedComponent[key] = value + } + // Modify ID and GUID of the cloned component clonedComponent["id"] = uuid clonedComponent["name"] = uuid @@ -216,12 +222,24 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD clonedComponent["osPuppetCertName"] = nil clonedComponent["managementIpAddress"] = nil + // Deep copy resources resources, ok := clonedComponent["resources"].([]interface{}) if !ok { - fmt.Println("Error: components field not found or not a []interface{}") + fmt.Println("Error: resources field not found or not a []interface{}") return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", ok) } + clonedResources := make([]interface{}, len(resources)) + for i, res := range resources { + resCopy := make(map[string]interface{}) + for k, v := range res.(map[string]interface{}) { + resCopy[k] = v + } + clonedResources[i] = resCopy + } + clonedComponent["resources"] = clonedResources + + // Exclude list of parameters to skip excludeList := map[string]bool{ "razor_image": true, "scaleio_enabled": true, @@ -230,36 +248,62 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD "replication_enabled": true, } - for _, comp := range resources { + // Iterate over resources to modify parameters + for _, comp := range clonedResources { comp := comp.(map[string]interface{}) if comp["id"].(string) == "asm::server" { + comp["guid"] = nil + parameters, ok := comp["parameters"].([]interface{}) if !ok { fmt.Println("Error: components field not found or not a []interface{}") return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", ok) } - for _, parameter := range parameters { + clonedParams := make([]interface{}, len(parameters)) + for i, param := range parameters { + paramCopy := make(map[string]interface{}) + for k, v := range param.(map[string]interface{}) { + paramCopy[k] = v + } + clonedParams[i] = paramCopy + } + + for _, parameter := range clonedParams { parameter := parameter.(map[string]interface{}) if !excludeList[parameter["id"].(string)] { - parameter["guid"] = nil - parameter["value"] = nil + + if parameter["id"].(string) == "scaleio_mdm_role" { + parameter["guid"] = nil + parameter["value"] = "standby_mdm" + } else { + parameter["guid"] = nil + parameter["value"] = nil + } + } } + + // Update parameters in the component + comp["parameters"] = clonedParams } } - clonedComponent["resources"] = resources - // Append the cloned component back to the components array components = append(components, clonedComponent) + // Update serviceTemplate with modified components serviceTemplate["components"] = components + // Update deploymentData with modified serviceTemplate + deploymentData["serviceTemplate"] = serviceTemplate + + // Update other fields as needed deploymentData["scaleUp"] = true deploymentData["retry"] = true + // Marshal deploymentData to JSON deploymentPayloadJson, _ = json.Marshal(deploymentData) } else { @@ -276,6 +320,10 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD deploymentPayloadJson, _ = json.Marshal(deploymentResponse) } + fmt.Println("==================================") + + fmt.Println(string(deploymentPayloadJson)) + req, httpError := http.NewRequest("PUT", gc.host+"/Api/V1/Deployment/"+deploymentID, bytes.NewBuffer(deploymentPayloadJson)) if httpError != nil { return nil, httpError From cde5ee8e76dad35ee8f7ab2b71d1a039d56548d2 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 20 Feb 2024 04:08:30 -0500 Subject: [PATCH 14/21] Service Resource --- inttests/service_test.go | 24 ++++++++++++------------ service.go | 35 +++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/inttests/service_test.go b/inttests/service_test.go index 0b13eef..306a64f 100644 --- a/inttests/service_test.go +++ b/inttests/service_test.go @@ -19,22 +19,22 @@ import ( ) func TestDeployeService(t *testing.T) { - templates, err := GC.DeployService("Test-Create", "Test", "8150d563-639d-464e-80c4-a435ed10f132", "8aaaee208c8c467e018cd37813250614") - assert.Nil(t, err) - assert.NotNil(t, templates) + deployments, err := GC.DeployService("Test-Create", "Test", "8150d563-639d-464e-80c4-a435ed10f132", "8aaaee208c8c467e018cd37813250614") + assert.NotNil(t, err) + assert.Nil(t, deployments) } func TestGetAllDeployeService(t *testing.T) { - templates, err := GC.GetAllServiceDetails() + deployments, err := GC.GetAllServiceDetails() assert.Nil(t, err) - assert.NotNil(t, templates) + assert.NotNil(t, deployments) - if len(templates) > 0 { - template, err := GC.GetServiceDetailsByID(templates[0].ID, false) + if len(deployments) > 0 { + template, err := GC.GetServiceDetailsByID(deployments[0].ID, false) assert.Nil(t, err) assert.NotNil(t, template) - _, err = GC.UpdateService(templates[0].ID, "Test-Update - Krunal", "Test-Update - Krunal", 1) + _, err = GC.UpdateService(deployments[0].ID, "Test-Update-K", "Test-Update-K", 1) assert.Nil(t, err) } @@ -44,12 +44,12 @@ func TestGetAllDeployeService(t *testing.T) { } func TestGetDeployeServiceByName(t *testing.T) { - templates, err := GC.GetAllServiceDetails() + deployments, err := GC.GetAllServiceDetails() assert.Nil(t, err) - assert.NotNil(t, templates) + assert.NotNil(t, deployments) - if len(templates) > 0 { - template, err := GC.GetServiceDetailsByFilter(templates[0].DeploymentName, "name") + if len(deployments) > 0 { + template, err := GC.GetServiceDetailsByFilter(deployments[0].DeploymentName, "name") assert.Nil(t, err) assert.NotNil(t, template) } diff --git a/service.go b/service.go index 6c0224f..a48edbc 100644 --- a/service.go +++ b/service.go @@ -164,9 +164,20 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD if httpResp.StatusCode == 200 { + var deploymentResponse types.ServiceResponse + + parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) + } + + deployedNodes := deploymentResponse.ServiceTemplate.ServerCount + var deploymentPayloadJson []byte - if nodes > 0 { + nodeDiff := nodes - deployedNodes + + if nodeDiff > 0 && nodeDiff == 1 { var deploymentData map[string]interface{} @@ -184,14 +195,12 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD // Access the "components" field serviceTemplate, ok := deploymentData["serviceTemplate"].(map[string]interface{}) if !ok { - fmt.Println("Error: serviceTemplate field not found or not a map[string]interface{}") - return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", ok) + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment") } components, ok := serviceTemplate["components"].([]interface{}) if !ok { - fmt.Println("Error: components field not found or not a []interface{}") - return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", ok) + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment") } // Find the component with type "SERVER" @@ -225,8 +234,7 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD // Deep copy resources resources, ok := clonedComponent["resources"].([]interface{}) if !ok { - fmt.Println("Error: resources field not found or not a []interface{}") - return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", ok) + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment") } clonedResources := make([]interface{}, len(resources)) @@ -257,8 +265,7 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD parameters, ok := comp["parameters"].([]interface{}) if !ok { - fmt.Println("Error: components field not found or not a []interface{}") - return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", ok) + return nil, fmt.Errorf("Error While Parsing Response Data For Deployment") } clonedParams := make([]interface{}, len(parameters)) @@ -306,7 +313,7 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD // Marshal deploymentData to JSON deploymentPayloadJson, _ = json.Marshal(deploymentData) - } else { + } else if nodeDiff == 0 { deploymentResponse, jsonParseError := jsonToMap(responseString) if jsonParseError != nil { @@ -318,12 +325,10 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD deploymentResponse["deploymentDescription"] = deploymentDesc deploymentPayloadJson, _ = json.Marshal(deploymentResponse) + } else if nodeDiff > 1 || nodeDiff < 0 { + return nil, fmt.Errorf("node difference is more than 1") } - fmt.Println("==================================") - - fmt.Println(string(deploymentPayloadJson)) - req, httpError := http.NewRequest("PUT", gc.host+"/Api/V1/Deployment/"+deploymentID, bytes.NewBuffer(deploymentPayloadJson)) if httpError != nil { return nil, httpError @@ -376,8 +381,6 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", deploymentResponse.Messages[0].DisplayMessage) } - //return nil, fmt.Errorf("Error While Parsing Response Data For Deployment:") - } else { var deploymentResponse types.ServiceFailedResponse From f03178a0cd36a9b8d039789f8ca9068f346e73d7 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 20 Feb 2024 06:48:06 -0500 Subject: [PATCH 15/21] Service Resource --- inttests/service_test.go | 9 ++++----- service.go | 11 +++++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/inttests/service_test.go b/inttests/service_test.go index 306a64f..5636eb9 100644 --- a/inttests/service_test.go +++ b/inttests/service_test.go @@ -19,9 +19,8 @@ import ( ) func TestDeployeService(t *testing.T) { - deployments, err := GC.DeployService("Test-Create", "Test", "8150d563-639d-464e-80c4-a435ed10f132", "8aaaee208c8c467e018cd37813250614") + _, err := GC.DeployService("Test-Create", "Test", "8150d563-639d-464e-80c4-a435ed10f132", "8aaaee208c8c467e018cd37813250614") assert.NotNil(t, err) - assert.Nil(t, deployments) } func TestGetAllDeployeService(t *testing.T) { @@ -34,8 +33,8 @@ func TestGetAllDeployeService(t *testing.T) { assert.Nil(t, err) assert.NotNil(t, template) - _, err = GC.UpdateService(deployments[0].ID, "Test-Update-K", "Test-Update-K", 1) - assert.Nil(t, err) + _, err = GC.UpdateService("ABC", "Test-Update-K", "Test-Update-K", "4") + assert.NotNil(t, err) } template, err := GC.GetServiceDetailsByID(invalidIdentifier, false) @@ -49,7 +48,7 @@ func TestGetDeployeServiceByName(t *testing.T) { assert.NotNil(t, deployments) if len(deployments) > 0 { - template, err := GC.GetServiceDetailsByFilter(deployments[0].DeploymentName, "name") + template, err := GC.GetServiceDetailsByFilter("name",deployments[0].DeploymentName) assert.Nil(t, err) assert.NotNil(t, template) } diff --git a/service.go b/service.go index a48edbc..3d67b42 100644 --- a/service.go +++ b/service.go @@ -20,6 +20,7 @@ import ( "io" "net/http" "net/url" + "strconv" "time" types "github.com/dell/goscaleio/types/v1" @@ -128,12 +129,12 @@ func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTe return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", deploymentResponse.Messages[0].DisplayMessage) } + } else { + return nil, fmt.Errorf("Service Template Not Found") } - - return nil, nil } -func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentDesc string, nodes int) (*types.ServiceResponse, error) { +func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentDesc, nodes string) (*types.ServiceResponse, error) { defer TimeSpent("UpdateService", time.Now()) path := fmt.Sprintf("/Api/V1/Deployment/%v", deploymentID) @@ -175,6 +176,8 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD var deploymentPayloadJson []byte + nodes, _ := strconv.Atoi(nodes) + nodeDiff := nodes - deployedNodes if nodeDiff > 0 && nodeDiff == 1 { @@ -326,7 +329,7 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD deploymentPayloadJson, _ = json.Marshal(deploymentResponse) } else if nodeDiff > 1 || nodeDiff < 0 { - return nil, fmt.Errorf("node difference is more than 1") + return nil, fmt.Errorf("node difference is more than 1 ::" + string(nodeDiff)) } req, httpError := http.NewRequest("PUT", gc.host+"/Api/V1/Deployment/"+deploymentID, bytes.NewBuffer(deploymentPayloadJson)) From cb49292748ef2bc6287c156d6aa19a2bb50dfe69 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 20 Feb 2024 07:37:37 -0500 Subject: [PATCH 16/21] Service Resource --- service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service.go b/service.go index 3d67b42..dfb09fa 100644 --- a/service.go +++ b/service.go @@ -329,7 +329,7 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD deploymentPayloadJson, _ = json.Marshal(deploymentResponse) } else if nodeDiff > 1 || nodeDiff < 0 { - return nil, fmt.Errorf("node difference is more than 1 ::" + string(nodeDiff)) + return nil, fmt.Errorf("node difference is more than 1") } req, httpError := http.NewRequest("PUT", gc.host+"/Api/V1/Deployment/"+deploymentID, bytes.NewBuffer(deploymentPayloadJson)) From 75e1ec250bd5dc982433116adb06f3a62deee435 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 20 Feb 2024 11:48:29 -0500 Subject: [PATCH 17/21] Service Resource --- deploy.go | 70 ++++++++++++++++----- inttests/service_test.go | 4 +- inttests/template_test.go | 10 +-- service.go | 55 ++++++++++++++--- template.go | 127 +++++++++++++++++++++++++++++++++----- template_test.go | 26 ++++---- 6 files changed, 232 insertions(+), 60 deletions(-) diff --git a/deploy.go b/deploy.go index cdc0e1d..f1f08ba 100644 --- a/deploy.go +++ b/deploy.go @@ -236,7 +236,10 @@ func (gc *GatewayClient) UploadPackages(filePaths []string) (*types.GatewayRespo if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -304,7 +307,10 @@ func (gc *GatewayClient) ParseCSV(filePath string) (*types.GatewayResponse, erro if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -363,7 +369,10 @@ func (gc *GatewayClient) GetPackageDetails() ([]*types.PackageDetails, error) { if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) @@ -411,7 +420,10 @@ func (gc *GatewayClient) ValidateMDMDetails(mdmTopologyParam []byte) (*types.Gat if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -473,7 +485,10 @@ func (gc *GatewayClient) GetClusterDetails(mdmTopologyParam []byte, requireJSONO if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -544,7 +559,10 @@ func (gc *GatewayClient) DeletePackage(packageName string) (*types.GatewayRespon if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -631,7 +649,10 @@ func (gc *GatewayClient) BeginInstallation(jsonStr, mdmUsername, mdmPassword, li if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -677,7 +698,10 @@ func (gc *GatewayClient) MoveToNextPhase() (*types.GatewayResponse, error) { if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -727,7 +751,10 @@ func (gc *GatewayClient) RetryPhase() (*types.GatewayResponse, error) { if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -777,7 +804,10 @@ func (gc *GatewayClient) AbortOperation() (*types.GatewayResponse, error) { if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -827,7 +857,10 @@ func (gc *GatewayClient) ClearQueueCommand() (*types.GatewayResponse, error) { if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -877,7 +910,10 @@ func (gc *GatewayClient) MoveToIdlePhase() (*types.GatewayResponse, error) { if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -927,7 +963,10 @@ func (gc *GatewayClient) GetInQueueCommand() ([]types.MDMQueueCommandDetails, er if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -1047,7 +1086,10 @@ func (gc *GatewayClient) UninstallCluster(jsonStr, mdmUsername, mdmPassword, lia if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } diff --git a/inttests/service_test.go b/inttests/service_test.go index 5636eb9..66c6f34 100644 --- a/inttests/service_test.go +++ b/inttests/service_test.go @@ -19,7 +19,7 @@ import ( ) func TestDeployeService(t *testing.T) { - _, err := GC.DeployService("Test-Create", "Test", "8150d563-639d-464e-80c4-a435ed10f132", "8aaaee208c8c467e018cd37813250614") + _, err := GC.DeployService("Test-Create", "Test", "453c41eb-d72a-4ed1-ad16-bacdffbdd766", "8aaaee208c8c467e018cd37813250614", "3") assert.NotNil(t, err) } @@ -48,7 +48,7 @@ func TestGetDeployeServiceByName(t *testing.T) { assert.NotNil(t, deployments) if len(deployments) > 0 { - template, err := GC.GetServiceDetailsByFilter("name",deployments[0].DeploymentName) + template, err := GC.GetServiceDetailsByFilter("name", deployments[0].DeploymentName) assert.Nil(t, err) assert.NotNil(t, template) } diff --git a/inttests/template_test.go b/inttests/template_test.go index 41e24ed..229b5bd 100644 --- a/inttests/template_test.go +++ b/inttests/template_test.go @@ -19,29 +19,29 @@ import ( ) func TestGetTemplates(t *testing.T) { - templates, err := C.GetAllTemplates() + templates, err := GC.GetAllTemplates() assert.Nil(t, err) assert.NotNil(t, templates) } func TestGetTemplateByID(t *testing.T) { - templates, err := C.GetAllTemplates() + templates, err := GC.GetAllTemplates() assert.Nil(t, err) assert.NotNil(t, templates) if len(templates) > 0 { - template, err := C.GetTemplateByID(templates[0].ID) + template, err := GC.GetTemplateByID(templates[0].ID) assert.Nil(t, err) assert.NotNil(t, template) } - template, err := C.GetTemplateByID(invalidIdentifier) + template, err := GC.GetTemplateByID(invalidIdentifier) assert.NotNil(t, err) assert.Nil(t, template) } func TestGetTemplateByFilters(t *testing.T) { - templates, err := C.GetTemplateByFilters("invalid", "invalid") + templates, err := GC.GetTemplateByFilters("invalid", "invalid") assert.NotNil(t, err) assert.Nil(t, templates) } diff --git a/service.go b/service.go index dfb09fa..12a81b1 100644 --- a/service.go +++ b/service.go @@ -29,7 +29,7 @@ import ( ) // DeployService used to deploy service -func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTemplateID, firmwareRepositoryID string) (*types.ServiceResponse, error) { +func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTemplateID, firmwareRepositoryID, nodes string) (*types.ServiceResponse, error) { defer TimeSpent("DeployService", time.Now()) path := fmt.Sprintf("/Api/V1/ServiceTemplate/%v?forDeployment=true", serviceTemplateID) @@ -42,7 +42,10 @@ func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTe if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) @@ -62,11 +65,22 @@ func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTe var templateData map[string]interface{} parseError := json.Unmarshal([]byte(responseString), &templateData) - if parseError != nil { return nil, fmt.Errorf("Error While Parsing Response Data For Template: %s", parseError) } + configuredNode, _ := templateData["serverCount"].(int) + + nodes, _ := strconv.Atoi(nodes) + + if nodes > 0 { + nodeDiff := nodes - configuredNode + + if nodeDiff != 0 { + return nil, fmt.Errorf("Node count is not matching with Service Template") + } + } + deploymentPayload := map[string]interface{}{ "deploymentName": deploymentName, "deploymentDescription": deploymentDesc, @@ -84,7 +98,10 @@ func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTe if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -147,7 +164,10 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) @@ -339,7 +359,10 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } @@ -473,7 +496,10 @@ func (gc *GatewayClient) GetServiceDetailsByID(deploymentID string, newToken boo if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) @@ -530,7 +556,10 @@ func (gc *GatewayClient) GetServiceDetailsByFilter(filter, value string) ([]type if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) @@ -583,7 +612,10 @@ func (gc *GatewayClient) GetAllServiceDetails() ([]types.ServiceResponse, error) if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) @@ -640,7 +672,10 @@ func (gc *GatewayClient) DeleteService(serviceId string) (*types.ServiceResponse if gc.version == "4.0" { req.Header.Set("Authorization", "Bearer "+gc.token) - setCookie(req.Header, gc.host) + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } } else { req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) diff --git a/template.go b/template.go index 02e98ea..d7db753 100644 --- a/template.go +++ b/template.go @@ -13,7 +13,8 @@ package goscaleio import ( - "errors" + "encoding/base64" + "encoding/json" "fmt" "net/http" "net/url" @@ -23,35 +24,99 @@ import ( ) // GetTemplateByID gets the node details based on ID -func (c *Client) GetTemplateByID(id string) (*types.TemplateDetails, error) { +func (gc *GatewayClient) GetTemplateByID(id string) (*types.TemplateDetails, error) { defer TimeSpent("GetTemplateByID", time.Now()) path := fmt.Sprintf("/Api/V1/template/%v", id) var template types.TemplateDetails - err := c.getJSONWithRetry(http.MethodGet, path, nil, &template) - if err != nil { - return nil, err + req, httpError := http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError + } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 { + parseError := json.Unmarshal([]byte(responseString), &template) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Template: %s", parseError) + } + + return &template, nil + } else { + return nil, fmt.Errorf("Template not found") } - return &template, nil } // GetAllTemplates gets all the Template details -func (c *Client) GetAllTemplates() ([]types.TemplateDetails, error) { +func (gc *GatewayClient) GetAllTemplates() ([]types.TemplateDetails, error) { defer TimeSpent("GetAllTemplates", time.Now()) path := fmt.Sprintf("/Api/V1/template") var templates types.TemplateDetailsFilter - err := c.getJSONWithRetry(http.MethodGet, path, nil, &templates) - if err != nil { - return nil, err + req, httpError := http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 { + parseError := json.Unmarshal([]byte(responseString), &templates) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Template: %s", parseError) + } + } + return templates.TemplateDetails, nil } // GetTemplateByFilters gets the Template details based on the provided filter -func (c *Client) GetTemplateByFilters(key string, value string) ([]types.TemplateDetails, error) { +func (gc *GatewayClient) GetTemplateByFilters(key string, value string) ([]types.TemplateDetails, error) { defer TimeSpent("GetTemplateByFilters", time.Now()) encodedValue := url.QueryEscape(value) @@ -59,13 +124,43 @@ func (c *Client) GetTemplateByFilters(key string, value string) ([]types.Templat path := `/Api/V1/template?filter=` + key + `%20eq%20%22` + encodedValue + `%22` var templates types.TemplateDetailsFilter - err := c.getJSONWithRetry(http.MethodGet, path, nil, &templates) - if err != nil { - return nil, err + req, httpError := http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError } - if len(templates.TemplateDetails) == 0 { - return nil, errors.New("Couldn't find templates with the given filter") + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 { + parseError := json.Unmarshal([]byte(responseString), &templates) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Template: %s", parseError) + } + + } else { + return nil, fmt.Errorf("Template not found") + } + return templates.TemplateDetails, nil } diff --git a/template_test.go b/template_test.go index bc79acf..0578605 100644 --- a/template_test.go +++ b/template_test.go @@ -15,7 +15,6 @@ package goscaleio import ( "errors" "fmt" - "math" "net/http" "net/http/httptest" "testing" @@ -29,8 +28,8 @@ func TestGetTemplates(t *testing.T) { })) defer svr.Close() - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -64,7 +63,8 @@ func TestGetTemplateByID(t *testing.T) { for _, tc := range cases { tc := tc t.Run("", func(ts *testing.T) { - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -89,8 +89,8 @@ func TestGetTemplateByFilters(t *testing.T) { })) defer svr.Close() - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -107,8 +107,8 @@ func TestGetTemplateByIDNegative(t *testing.T) { })) defer svr.Close() - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -125,8 +125,8 @@ func TestGetTemplateByFiltersNegative(t *testing.T) { })) defer svr.Close() - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -143,8 +143,8 @@ func TestGetAllTemplatesNegative(t *testing.T) { })) defer svr.Close() - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -152,4 +152,4 @@ func TestGetAllTemplatesNegative(t *testing.T) { templates, err := client.GetAllTemplates() assert.Nil(t, templates) assert.NotNil(t, err) -} \ No newline at end of file +} From 57e4cf0b1b53f1be15edee0614b8eb26f0c3388c Mon Sep 17 00:00:00 2001 From: root Date: Tue, 20 Feb 2024 11:59:53 -0500 Subject: [PATCH 18/21] Service Resource --- deploy.go | 50 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/deploy.go b/deploy.go index f1f08ba..db6bb1d 100644 --- a/deploy.go +++ b/deploy.go @@ -394,7 +394,10 @@ func (gc *GatewayClient) GetPackageDetails() ([]*types.PackageDetails, error) { if httpResp.StatusCode == 200 { if gc.version == "4.0" { - storeCookie(httpResp.Header, gc.host) + err := storeCookie(httpResp.Header, gc.host) + if err != nil { + return packageParam, fmt.Errorf("Error While Storing cookie: %s", err) + } } err := json.Unmarshal([]byte(responseString), &packageParam) @@ -456,7 +459,10 @@ func (gc *GatewayClient) ValidateMDMDetails(mdmTopologyParam []byte) (*types.Gat } if gc.version == "4.0" { - storeCookie(httpResp.Header, gc.host) + err := storeCookie(httpResp.Header, gc.host) + if err != nil { + return &gatewayResponse, fmt.Errorf("Error While Storing cookie: %s", err) + } } var mdmTopologyDetails types.MDMTopologyDetails @@ -521,7 +527,10 @@ func (gc *GatewayClient) GetClusterDetails(mdmTopologyParam []byte, requireJSONO } if gc.version == "4.0" { - storeCookie(httpResp.Header, gc.host) + err := storeCookie(httpResp.Header, gc.host) + if err != nil { + return &gatewayResponse, fmt.Errorf("Error While Storing cookie: %s", err) + } } if requireJSONOutput { @@ -591,7 +600,10 @@ func (gc *GatewayClient) DeletePackage(packageName string) (*types.GatewayRespon } if gc.version == "4.0" { - storeCookie(httpResp.Header, gc.host) + err := storeCookie(httpResp.Header, gc.host) + if err != nil { + return &gatewayResponse, fmt.Errorf("Error While Storing cookie: %s", err) + } } gatewayResponse.StatusCode = 200 @@ -731,7 +743,10 @@ func (gc *GatewayClient) MoveToNextPhase() (*types.GatewayResponse, error) { } if gc.version == "4.0" { - storeCookie(httpResp.Header, gc.host) + err := storeCookie(httpResp.Header, gc.host) + if err != nil { + return &gatewayResponse, fmt.Errorf("Error While Storing cookie: %s", err) + } } gatewayResponse.StatusCode = 200 @@ -784,7 +799,10 @@ func (gc *GatewayClient) RetryPhase() (*types.GatewayResponse, error) { } if gc.version == "4.0" { - storeCookie(httpResp.Header, gc.host) + err := storeCookie(httpResp.Header, gc.host) + if err != nil { + return &gatewayResponse, fmt.Errorf("Error While Storing cookie: %s", err) + } } gatewayResponse.StatusCode = 200 @@ -837,7 +855,10 @@ func (gc *GatewayClient) AbortOperation() (*types.GatewayResponse, error) { } if gc.version == "4.0" { - storeCookie(httpResp.Header, gc.host) + err := storeCookie(httpResp.Header, gc.host) + if err != nil { + return &gatewayResponse, fmt.Errorf("Error While Storing cookie: %s", err) + } } gatewayResponse.StatusCode = 200 @@ -890,7 +911,10 @@ func (gc *GatewayClient) ClearQueueCommand() (*types.GatewayResponse, error) { } if gc.version == "4.0" { - storeCookie(httpResp.Header, gc.host) + err := storeCookie(httpResp.Header, gc.host) + if err != nil { + return &gatewayResponse, fmt.Errorf("Error While Storing cookie: %s", err) + } } gatewayResponse.StatusCode = 200 @@ -943,7 +967,10 @@ func (gc *GatewayClient) MoveToIdlePhase() (*types.GatewayResponse, error) { } if gc.version == "4.0" { - storeCookie(httpResp.Header, gc.host) + err := storeCookie(httpResp.Header, gc.host) + if err != nil { + return &gatewayResponse, fmt.Errorf("Error While Storing cookie: %s", err) + } } gatewayResponse.StatusCode = 200 @@ -986,7 +1013,10 @@ func (gc *GatewayClient) GetInQueueCommand() ([]types.MDMQueueCommandDetails, er if httpResp.StatusCode == 200 { if gc.version == "4.0" { - storeCookie(httpResp.Header, gc.host) + err := storeCookie(httpResp.Header, gc.host) + if err != nil { + return mdmQueueCommandDetails, fmt.Errorf("Error While Storing cookie: %s", err) + } } var queueCommandDetails map[string][]interface{} From 49dcfe7cb7a3206e6380ac88cd1b06a03b9cc68b Mon Sep 17 00:00:00 2001 From: root Date: Wed, 21 Feb 2024 00:36:05 -0500 Subject: [PATCH 19/21] Client Change for Node and Template --- inttests/node_test.go | 21 ++-- inttests/template_test.go | 2 +- node.go | 210 +++++++++++++++++++++++++++++++++----- node_test.go | 35 ++++--- service.go | 39 ++++++- template.go | 4 + 6 files changed, 254 insertions(+), 57 deletions(-) diff --git a/inttests/node_test.go b/inttests/node_test.go index 6be1888..89b24ac 100644 --- a/inttests/node_test.go +++ b/inttests/node_test.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved. +// Copyright © 2024 Dell InGC. or its subsidiaries. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,47 +19,46 @@ import ( ) func TestGetNodes(t *testing.T) { - allNodes, err := C.GetAllNodes() + allNodes, err := GC.GetAllNodes() assert.Nil(t, err) assert.NotNil(t, allNodes) } func TestGetNodeByID(t *testing.T) { - allNodes, err := C.GetAllNodes() + allNodes, err := GC.GetAllNodes() assert.Nil(t, err) assert.NotNil(t, allNodes) if len(allNodes) > 0 { - node, err := C.GetNodeByID(allNodes[0].RefID) + node, err := GC.GetNodeByID(allNodes[0].RefID) assert.Nil(t, err) assert.NotNil(t, node) } - node, err := C.GetNodeByID(invalidIdentifier) + node, err := GC.GetNodeByID(invalidIdentifier) assert.NotNil(t, err) assert.Nil(t, node) } func TestGetNodeByFilters(t *testing.T) { - allNodes, err := C.GetNodeByFilters("invalid", "invalid") + allNodes, err := GC.GetNodeByFilters("invalid", "invalid") assert.NotNil(t, err) assert.Nil(t, allNodes) } func TestGetNodePoolByID(t *testing.T) { - nodePool, err := C.GetNodePoolByID(-2) - assert.Nil(t, err) - assert.Equal(t, nodePool.DeviceGroup.GroupName, "") + _, err := GC.GetNodePoolByID(-2) + assert.NotNil(t, err) } func TestGetNodePoolByName(t *testing.T) { - nodePool, err := C.GetNodePoolByName(invalidIdentifier) + nodePool, err := GC.GetNodePoolByName(invalidIdentifier) assert.NotNil(t, err) assert.Nil(t, nodePool) } func TestGetAllNodePools(t *testing.T) { - allNodePools, err := C.GetAllNodePools() + allNodePools, err := GC.GetAllNodePools() assert.Nil(t, err) assert.NotNil(t, allNodePools) } diff --git a/inttests/template_test.go b/inttests/template_test.go index 229b5bd..5d5cecc 100644 --- a/inttests/template_test.go +++ b/inttests/template_test.go @@ -41,7 +41,7 @@ func TestGetTemplateByID(t *testing.T) { } func TestGetTemplateByFilters(t *testing.T) { - templates, err := GC.GetTemplateByFilters("invalid", "invalid") + templates, err := GC.GetTemplateByFilters("name", "invalid") assert.NotNil(t, err) assert.Nil(t, templates) } diff --git a/node.go b/node.go index 4c6762d..3be704b 100644 --- a/node.go +++ b/node.go @@ -13,6 +13,8 @@ package goscaleio import ( + "encoding/base64" + "encoding/json" "errors" "fmt" "net/http" @@ -22,94 +24,252 @@ import ( ) // GetNodeByID gets the node details based on ID -func (c *Client) GetNodeByID(id string) (*types.NodeDetails, error) { +func (gc *GatewayClient) GetNodeByID(id string) (*types.NodeDetails, error) { defer TimeSpent("GetNodeByID", time.Now()) path := fmt.Sprintf("/Api/V1/ManagedDevice/%v", id) var node types.NodeDetails - err := c.getJSONWithRetry(http.MethodGet, path, nil, &node) - if err != nil { - return nil, err + req, httpError := http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError + } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 { + parseError := json.Unmarshal([]byte(responseString), &node) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Node: %s", parseError) + } + } else { + return nil, fmt.Errorf("Couldn't find nodes with the given filter") } return &node, nil } // GetAllNodes gets all the node details -func (c *Client) GetAllNodes() ([]types.NodeDetails, error) { +func (gc *GatewayClient) GetAllNodes() ([]types.NodeDetails, error) { defer TimeSpent("GetNodeByID", time.Now()) path := fmt.Sprintf("/Api/V1/ManagedDevice") var nodes []types.NodeDetails - err := c.getJSONWithRetry(http.MethodGet, path, nil, &nodes) - if err != nil { - return nil, err + req, httpError := http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError + } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 { + parseError := json.Unmarshal([]byte(responseString), &nodes) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Node: %s", parseError) + } + } else { + return nil, fmt.Errorf("Couldn't find nodes with the given filter") } return nodes, nil } // GetNodeByFilters gets the node details based on the provided filter -func (c *Client) GetNodeByFilters(key string, value string) ([]types.NodeDetails, error) { +func (gc *GatewayClient) GetNodeByFilters(key string, value string) ([]types.NodeDetails, error) { defer TimeSpent("GetNodeByFilters", time.Now()) path := fmt.Sprintf("/Api/V1/ManagedDevice?filter=eq,%v,%v", key, value) var nodes []types.NodeDetails - err := c.getJSONWithRetry(http.MethodGet, path, nil, &nodes) - if err != nil { - return nil, err + req, httpError := http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError } - if len(nodes) == 0 { - return nil, errors.New("Couldn't find nodes with the given filter") + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 { + parseError := json.Unmarshal([]byte(responseString), &nodes) + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Node: %s", parseError) + } + + if len(nodes) == 0 { + return nil, errors.New("Couldn't find nodes with the given filter") + } + } else { + return nil, fmt.Errorf("Couldn't find nodes with the given filter") } return nodes, nil } // GetNodePoolByID gets the nodepool details based on ID -func (c *Client) GetNodePoolByID(id int) (*types.NodePoolDetails, error) { +func (gc *GatewayClient) GetNodePoolByID(id int) (*types.NodePoolDetails, error) { defer TimeSpent("GetNodePoolByID", time.Now()) path := fmt.Sprintf("/Api/V1/nodepool/%v", id) var nodePool types.NodePoolDetails - err := c.getJSONWithRetry(http.MethodGet, path, nil, &nodePool) - if err != nil { - return nil, err + req, httpError := http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError + } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 && responseString != "" { + parseError := json.Unmarshal([]byte(responseString), &nodePool) + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Nodepool: %s", parseError) + } + + } else { + return nil, fmt.Errorf("Couldn't find nodes with the given filter") } return &nodePool, nil } // GetNodePoolByName gets the nodepool details based on name -func (c *Client) GetNodePoolByName(name string) (*types.NodePoolDetails, error) { +func (gc *GatewayClient) GetNodePoolByName(name string) (*types.NodePoolDetails, error) { defer TimeSpent("GetNodePoolByName", time.Now()) - nodePools, err := c.GetAllNodePools() + nodePools, err := gc.GetAllNodePools() if err != nil { return nil, err } for _, nodePool := range nodePools.NodePoolDetails { if nodePool.GroupName == name { - return c.GetNodePoolByID(nodePool.GroupSeqID) + return gc.GetNodePoolByID(nodePool.GroupSeqID) } } return nil, errors.New("no node pool found with name " + name) } // GetAllNodePools gets all the nodepool details -func (c *Client) GetAllNodePools() (*types.NodePoolDetailsFilter, error) { +func (gc *GatewayClient) GetAllNodePools() (*types.NodePoolDetailsFilter, error) { defer TimeSpent("GetAllNodePools", time.Now()) path := fmt.Sprintf("/Api/V1/nodepool") var nodePools types.NodePoolDetailsFilter - err := c.getJSONWithRetry(http.MethodGet, path, nil, &nodePools) - if err != nil { - return nil, err + req, httpError := http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError + } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client := gc.http + httpResp, httpRespError := client.Do(req) + if httpRespError != nil { + return nil, httpRespError } + responseString, _ := extractString(httpResp) + + if httpResp.StatusCode == 200 { + parseError := json.Unmarshal([]byte(responseString), &nodePools) + + if parseError != nil { + return nil, fmt.Errorf("Error While Parsing Response Data For Nodepool: %s", parseError) + } + } else { + return nil, fmt.Errorf("Couldn't find nodes with the given filter") + } return &nodePools, nil } diff --git a/node_test.go b/node_test.go index 77a8916..99755b7 100644 --- a/node_test.go +++ b/node_test.go @@ -15,7 +15,6 @@ package goscaleio import ( "errors" "fmt" - "math" "net/http" "net/http/httptest" "testing" @@ -29,8 +28,8 @@ func TestGetNodes(t *testing.T) { })) defer svr.Close() - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -64,7 +63,8 @@ func TestGetNodeByID(t *testing.T) { for _, tc := range cases { tc := tc t.Run("", func(ts *testing.T) { - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -107,7 +107,8 @@ func TestGetNodePoolByID(t *testing.T) { for _, tc := range cases { tc := tc t.Run("", func(ts *testing.T) { - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -132,8 +133,8 @@ func TestGetNodeByFilters(t *testing.T) { })) defer svr.Close() - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -149,8 +150,8 @@ func TestGetNodePoolByName(t *testing.T) { })) defer svr.Close() - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -167,8 +168,8 @@ func TestGetNodePoolByNameError(t *testing.T) { })) defer svr.Close() - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -185,8 +186,8 @@ func TestGetNodePoolByIDNegative(t *testing.T) { })) defer svr.Close() - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -203,8 +204,8 @@ func TestGetNodeByIDNegative(t *testing.T) { })) defer svr.Close() - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } @@ -221,8 +222,8 @@ func TestGetAllNodesNegative(t *testing.T) { })) defer svr.Close() - client, err := NewClientWithArgs(svr.URL, "", math.MaxInt64, true, false) - client.configConnect.Version = "4.5" + client, err := NewGateway(svr.URL, "", "", true, false) + client.version = "4.5" if err != nil { t.Fatal(err) } diff --git a/service.go b/service.go index 12a81b1..ba1c237 100644 --- a/service.go +++ b/service.go @@ -32,7 +32,7 @@ import ( func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTemplateID, firmwareRepositoryID, nodes string) (*types.ServiceResponse, error) { defer TimeSpent("DeployService", time.Now()) - path := fmt.Sprintf("/Api/V1/ServiceTemplate/%v?forDeployment=true", serviceTemplateID) + path := fmt.Sprintf("/Api/V1/FirmwareRepository/%v", firmwareRepositoryID) req, httpError := http.NewRequest("GET", gc.host+path, nil) if httpError != nil { @@ -61,7 +61,40 @@ func (gc *GatewayClient) DeployService(deploymentName, deploymentDesc, serviceTe responseString, _ := extractString(httpResp) - if httpResp.StatusCode == 200 { + if httpResp.StatusCode == 200 && responseString == "" { + return nil, fmt.Errorf("Firmware Repository Not Found") + } + + path = fmt.Sprintf("/Api/V1/ServiceTemplate/%v?forDeployment=true", serviceTemplateID) + + req, httpError = http.NewRequest("GET", gc.host+path, nil) + if httpError != nil { + return nil, httpError + } + + if gc.version == "4.0" { + req.Header.Set("Authorization", "Bearer "+gc.token) + + err := setCookie(req.Header, gc.host) + if err != nil { + return nil, fmt.Errorf("Error While Handling Cookie: %s", err) + } + + } else { + req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password))) + } + + req.Header.Set("Content-Type", "application/json") + + client = gc.http + httpResp, httpRespError = client.Do(req) + if httpRespError != nil { + return nil, httpRespError + } + + responseString, _ = extractString(httpResp) + + if httpResp.StatusCode == 200 && responseString != "" { var templateData map[string]interface{} parseError := json.Unmarshal([]byte(responseString), &templateData) @@ -183,7 +216,7 @@ func (gc *GatewayClient) UpdateService(deploymentID, deploymentName, deploymentD responseString, _ := extractString(httpResp) - if httpResp.StatusCode == 200 { + if httpResp.StatusCode == 200 && responseString != "" { var deploymentResponse types.ServiceResponse diff --git a/template.go b/template.go index d7db753..df9d4cb 100644 --- a/template.go +++ b/template.go @@ -158,6 +158,10 @@ func (gc *GatewayClient) GetTemplateByFilters(key string, value string) ([]types return nil, fmt.Errorf("Error While Parsing Response Data For Template: %s", parseError) } + if len(templates.TemplateDetails) == 0 { + return nil, fmt.Errorf("Template not found") + } + } else { return nil, fmt.Errorf("Template not found") } From 9d40fa5b118c45b8503aa53fcdc8527fa1d842d6 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 21 Feb 2024 01:13:49 -0500 Subject: [PATCH 20/21] Service Resource --- service.go | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/service.go b/service.go index ba1c237..5c3bee8 100644 --- a/service.go +++ b/service.go @@ -561,15 +561,7 @@ func (gc *GatewayClient) GetServiceDetailsByID(deploymentID string, newToken boo return &deploymentResponse, nil } else { - var deploymentResponse types.ServiceFailedResponse - - parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) - - if parseError != nil { - return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) - } - - return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", deploymentResponse.Messages[0].DisplayMessage) + return nil, fmt.Errorf("Couldn't find service with the given filter") } } @@ -618,18 +610,14 @@ func (gc *GatewayClient) GetServiceDetailsByFilter(filter, value string) ([]type return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) } + if len(deploymentResponse) == 0 { + return nil, fmt.Errorf("Couldn't find service with the given filter") + } + return deploymentResponse, nil } else { - var deploymentResponse types.ServiceFailedResponse - - parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) - - if parseError != nil { - return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) - } - - return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", deploymentResponse.Messages[0].DisplayMessage) + return nil, fmt.Errorf("Couldn't find service with the given filter") } } @@ -677,15 +665,7 @@ func (gc *GatewayClient) GetAllServiceDetails() ([]types.ServiceResponse, error) return deploymentResponse, nil } else { - var deploymentResponse types.ServiceFailedResponse - - parseError := json.Unmarshal([]byte(responseString), &deploymentResponse) - - if parseError != nil { - return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", parseError) - } - - return nil, fmt.Errorf("Error While Parsing Response Data For Deployment: %s", deploymentResponse.Messages[0].DisplayMessage) + return nil, fmt.Errorf("Couldn't find service with the given filter") } } @@ -729,5 +709,5 @@ func (gc *GatewayClient) DeleteService(serviceId string) (*types.ServiceResponse return &deploymentResponse, nil } - return &deploymentResponse, nil + return nil, fmt.Errorf("Couldn't delete service") } From 8a9f9e5dc5d1288896db5e9d5dc50503f2d5acb2 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 21 Feb 2024 03:41:22 -0500 Subject: [PATCH 21/21] Fixing typo --- inttests/node_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inttests/node_test.go b/inttests/node_test.go index 89b24ac..e874f66 100644 --- a/inttests/node_test.go +++ b/inttests/node_test.go @@ -1,4 +1,4 @@ -// Copyright © 2024 Dell InGC. or its subsidiaries. All Rights Reserved. +// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.