Skip to content

Commit

Permalink
Support SDT deployment via CSV
Browse files Browse the repository at this point in the history
- Add SDT related structs
- Add RenewInstallationCookie to get valid cookie that can be used
  during cluster deployment
- Replace cookie dir `/home` to user's home directory to avoid the case
  that user doesn't have write permission to `/home` or OS is Windows
  • Loading branch information
baoy1 committed Sep 16, 2024
1 parent fc34c46 commit 1487736
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 7 deletions.
68 changes: 65 additions & 3 deletions deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"net/http"
"net/url"
"os"
"path/filepath"
path "path/filepath"
"regexp"
"strconv"
Expand Down Expand Up @@ -286,6 +287,14 @@ func (gc *GatewayClient) UploadPackages(filePaths []string) (*types.GatewayRespo

gatewayResponse.StatusCode = 200

// store cookie for successive deployment requests
if gc.version == "4.0" {
err := storeCookie(response.Header, gc.host)
if err != nil {
return &gatewayResponse, fmt.Errorf("Error While Storing cookie: %s", err)
}
}

return &gatewayResponse, nil
}

Expand Down Expand Up @@ -978,6 +987,47 @@ func (gc *GatewayClient) MoveToIdlePhase() (*types.GatewayResponse, error) {
return &gatewayResponse, nil
}

// RenewInstallationCookie is used to renew the installation cookie, i.e. LEGACYGWCOOKIE.
// Using the same LEGACYGWCOOKIE ensures that the REST requests are sent to the same GW pod.
// That would help to get the correct response from the GW pod that stores installation packages.
func (gc *GatewayClient) RenewInstallationCookie(retryCount int) error {
var packageParam []*types.PackageDetails

req, httpError := http.NewRequest(http.MethodGet, gc.host+"/im/types/installationPackages/instances?onlyLatest=false&_search=false", nil)
if httpError != nil {
return httpError
}

if gc.version == "4.0" {
req.Header.Set("Authorization", "Bearer "+gc.token)
} else {
req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(gc.username+":"+gc.password)))
}
req.Header.Set("Content-Type", "application/json")

for i := 0; i < retryCount; i++ {
httpResp, httpRespError := gc.http.Do(req)
if httpRespError != nil {
continue
}

responseString, err := extractString(httpResp)
if err != nil {
continue
}

if httpResp.StatusCode == 200 {
err := json.Unmarshal([]byte(responseString), &packageParam)
// No packages found. Retry to find the cookie that can return packages info
if err != nil || len(packageParam) == 0 || storeCookie(httpResp.Header, gc.host) != nil {
continue
}
return nil
}
}
return fmt.Errorf("Failed to renew installation cookie %d times", retryCount)
}

// GetInQueueCommand used for get in queue commands
func (gc *GatewayClient) GetInQueueCommand() ([]types.MDMQueueCommandDetails, error) {
var mdmQueueCommandDetails []types.MDMQueueCommandDetails
Expand Down Expand Up @@ -1156,7 +1206,17 @@ func jsonToMap(jsonStr string) (map[string]interface{}, error) {
return result, nil
}

const configFile = "/home/.cookie_config.yaml"
// getConfigPath returns the path to the cookie configuration file in the user's home directory.
func getConfigPath() (string, error) {
homeDir, err := os.UserHomeDir()
if err != nil {
return "/home/.cookie_config.yaml", err
}

configPath := filepath.Join(homeDir, ".cookie_config.yaml")

return configPath, nil
}

var globalCookie string

Expand Down Expand Up @@ -1233,7 +1293,8 @@ func setCookie(header http.Header, host string) error {
}

func loadConfig() (*CookieConfig, error) {
if _, err := os.Stat(configFile); err == nil {
configFile, _ := getConfigPath()
if _, err := os.Stat(filepath.Clean(configFile)); err == nil {
data, err := ioutil.ReadFile(configFile)
if err != nil {
return nil, err
Expand All @@ -1257,7 +1318,8 @@ func writeConfig(config *CookieConfig) error {
return err
}
// #nosec G306
err = ioutil.WriteFile(configFile, data, 0o644)
configFile, _ := getConfigPath()
err = ioutil.WriteFile(configFile, data, 0o600)
if err != nil {
return err
}
Expand Down
46 changes: 46 additions & 0 deletions deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,3 +421,49 @@ func TestUninstallCluster(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, gatewayResponse.StatusCode)
}

func TestRenewInstallationCookie(t *testing.T) {
responseJSON := `[
{
"version": "4.5-0.287",
"sioPatchNumber": 0,
"type": "mdm",
"size": 72378708,
"label": "0.287.sles15.3.x86_64",
"operatingSystem": "linux",
"linuxFlavour": "sles15_3",
"activemqPackage": false,
"filename": "EMC-ScaleIO-mdm-4.5-0.287.sles15.3.x86_64.rpm",
"activemqRpmPackage": false,
"activemqUbuntuPackage": false,
"latest": true
}]`
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet && strings.Contains(r.URL.Path, "/im/types/installationPackages/instances") {
cookie := &http.Cookie{
Name: "LEGACYGWCOOKIE",
Value: "123456789",
Path: "/",
}
http.SetCookie(w, cookie)
w.WriteHeader(http.StatusOK)
_, err := w.Write([]byte(responseJSON))
if err != nil {
t.Fatalf("Error writing response: %v", err)
}
return
}
http.NotFound(w, r)
}))
defer server.Close()

gc := &GatewayClient{
http: &http.Client{},
host: server.URL,
username: "test_username",
password: "test_password",
}

err := gc.RenewInstallationCookie(5)
assert.NoError(t, err)
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.2.0 // indirect
golang.org/x/sys v0.25.0 // indirect
)

go 1.22
go 1.22.0
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
6 changes: 6 additions & 0 deletions inttests/deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,9 @@ func TestDeployCheckForCompletionQueueCommands(t *testing.T) {
assert.NotNil(t, res)
assert.Nil(t, err)
}

// TestRenewInstallationCookie function to test Renew Installation Cookie
func TestRenewInstallationCookie(t *testing.T) {
err := GC.RenewInstallationCookie(5)
assert.Nil(t, err)
}
17 changes: 17 additions & 0 deletions types/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1658,6 +1658,7 @@ type MDMTopologyDetails struct {
SystemVersionName string `json:"systemVersionName,omitempty"`
SdsList []SdsList `json:"sdsList,omitempty"`
SdcList []SdcList `json:"sdcList,omitempty"`
SdtList []SdtList `json:"sdtList,omitempty"`
ProtectionDomains []ProtectionDomains `json:"protectionDomains,omitempty"`
SdrList []SdrList `json:"sdrList,omitempty"`
VasaProviderList []any `json:"vasaProviderList,omitempty"`
Expand Down Expand Up @@ -1759,6 +1760,22 @@ type SdsList struct {
ID string `json:"id,omitempty"`
}

// SdtList defines struct for SDT Details
type SdtList struct {
Node Node `json:"node,omitempty"`
SdtName string `json:"sdtName,omitempty"`
ProtectionDomain string `json:"protectionDomain,omitempty"`
ProtectionDomainID string `json:"protectionDomainId,omitempty"`
AllIPs []string `json:"allIPs,omitempty"`
StorageOnlyIPs []string `json:"storageOnlyIPs,omitempty"`
HostOnlyIPs []string `json:"hostOnlyIPs,omitempty"`
StoragePort int `json:"storagePort,omitempty"`
NvmePort int `json:"nvmePort,omitempty"`
DiscoveryPort int `json:"discoveryPort,omitempty"`
Optimized bool `json:"optimized,omitempty"`
ID string `json:"id,omitempty"`
}

// SdcList defines struct for SDC Details
type SdcList struct {
Node Node `json:"node,omitempty"`
Expand Down

0 comments on commit 1487736

Please sign in to comment.