From 2a6f810f0eca5de908e202496b8016370539da9f Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Sun, 20 Mar 2022 18:41:29 +0200 Subject: [PATCH 01/17] MGMT-9451: Moving to new service-agent protocol Moving new commands : stop and logs Adding new step type for stop and logs --- internal/host/hostcommands/logs_cmd.go | 93 +++----- .../hostcommands/stop_installation_cmd.go | 10 +- models/logs_gather_cmd_request.go | 215 ++++++++++++++++++ models/next_step_cmd_request.go | 115 ++++++++++ models/step_type.go | 11 +- restapi/embedded_spec.go | 176 +++++++++++++- swagger.yaml | 69 ++++++ 7 files changed, 616 insertions(+), 73 deletions(-) create mode 100644 models/logs_gather_cmd_request.go create mode 100644 models/next_step_cmd_request.go diff --git a/internal/host/hostcommands/logs_cmd.go b/internal/host/hostcommands/logs_cmd.go index b81b8d826a2..2407b8f7c35 100644 --- a/internal/host/hostcommands/logs_cmd.go +++ b/internal/host/hostcommands/logs_cmd.go @@ -1,13 +1,10 @@ package hostcommands import ( - "bytes" "context" "encoding/json" "net" - "strconv" "strings" - "text/template" "time" "github.com/go-openapi/swag" @@ -32,87 +29,57 @@ func NewLogsCmd(log logrus.FieldLogger, db *gorm.DB, instructionConfig Instructi } } -func (i *logsCmd) GetSteps(ctx context.Context, host *models.Host) ([]*models.Step, error) { - // added to run upload logs if install command fails - if !time.Time(host.LogsCollectedAt).Equal(time.Time{}) { - return nil, nil - } - +func (i *logsCmd) prepareParam(ctx context.Context, host *models.Host) (string, error) { var mastersIPs []string var err error if host.Bootstrap { mastersIPs, err = i.getNonBootstrapMastersIPsInHostCluster(ctx, host) if err != nil { i.log.WithError(err).Errorf("Failed to get non-bootstrap masters IPs from cluster %s", host.ClusterID) - return nil, err + return "", err } } - logsCommand, err := i.createUploadLogsCmd(host, i.instructionConfig.ServiceBaseURL, - i.instructionConfig.AgentImage, strings.Join(mastersIPs, ","), - i.instructionConfig.SkipCertVerification, false, true) - if err != nil { - return nil, err - } - logsCommandAsArgs := strings.Fields(logsCommand) - step := &models.Step{ - StepType: models.StepTypeExecute, - Command: logsCommandAsArgs[0], - Args: logsCommandAsArgs[1:], - } - - return []*models.Step{step}, nil -} - -func (i *logsCmd) createUploadLogsCmd(host *models.Host, baseURL, agentImage, mastersIPs string, skipCertVerification, preservePreviousCommandReturnCode, - withInstallerGatherLogging bool) (string, error) { - - cmdArgsTmpl := "" - if preservePreviousCommandReturnCode { - cmdArgsTmpl = "( returnCode=$?; " + request := models.LogsGatherCmdRequest{ + BaseURL: swag.String(strings.TrimSpace(i.instructionConfig.ServiceBaseURL)), + ClusterID: host.ClusterID, + HostID: host.ID, + InfraEnvID: &host.InfraEnvID, + Insecure: swag.Bool(i.instructionConfig.SkipCertVerification), + Bootstrap: swag.Bool(host.Bootstrap), + InstallerGather: true, + MasterIps: mastersIPs, } - data := map[string]string{ - "BASE_URL": strings.TrimSpace(baseURL), - "CLUSTER_ID": host.ClusterID.String(), - "HOST_ID": host.ID.String(), - "INFRA_ENV_ID": host.InfraEnvID.String(), - "AGENT_IMAGE": strings.TrimSpace(agentImage), - "SKIP_CERT_VERIFICATION": strconv.FormatBool(skipCertVerification), - "BOOTSTRAP": strconv.FormatBool(host.Bootstrap), - "INSTALLER_GATHER": strconv.FormatBool(withInstallerGatherLogging), - "MASTERS_IPS": mastersIPs, + if i.instructionConfig.ServiceCACertPath != "" { + request.CaCertPath = common.HostCACertPath } - if i.instructionConfig.ServiceCACertPath != "" { - data["CACERTPATH"] = common.HostCACertPath + b, err := json.Marshal(&request) + if err != nil { + i.log.WithError(err).Warn("Json marshal") + return "", err } + return string(b), nil +} - cmdArgsTmpl += "timeout 1h podman run --rm --privileged --net=host " + - "-v /run/systemd/journal/socket:/run/systemd/journal/socket -v /var/log:/var/log -v /etc/pki:/etc/pki " + - "{{if .CACERTPATH}} -v {{.CACERTPATH}}:{{.CACERTPATH}} {{end}}" + - "{{if eq .BOOTSTRAP `true`}} -v /root/.ssh:/root/.ssh -v /tmp:/tmp {{end}}" + - "--env PULL_SECRET_TOKEN --name logs-sender --pid=host {{.AGENT_IMAGE}} logs_sender " + - "-url {{.BASE_URL}} -cluster-id {{.CLUSTER_ID}} -host-id {{.HOST_ID}} -infra-env-id {{.INFRA_ENV_ID}} " + - "--insecure={{.SKIP_CERT_VERIFICATION}} -bootstrap={{.BOOTSTRAP}} -with-installer-gather-logging={{.INSTALLER_GATHER}}" + - "{{if .MASTERS_IPS}} -masters-ips={{.MASTERS_IPS}} {{end}}" + - "{{if .CACERTPATH}} --cacert {{.CACERTPATH}} {{end}}" - - if preservePreviousCommandReturnCode { - cmdArgsTmpl = cmdArgsTmpl + "; exit $returnCode; )" +func (i *logsCmd) GetSteps(ctx context.Context, host *models.Host) ([]*models.Step, error) { + // added to run upload logs if install command fails + if !time.Time(host.LogsCollectedAt).Equal(time.Time{}) { + return nil, nil } - t, err := template.New("cmd").Parse(cmdArgsTmpl) + logsCommandAsArgs, err := i.prepareParam(ctx, host) if err != nil { - return "", err + return nil, err } - - buf := &bytes.Buffer{} - if err := t.Execute(buf, data); err != nil { - return "", err + step := &models.Step{ + StepType: models.StepTypeLogsGather, + Command: "", + Args: []string{logsCommandAsArgs}, } - return buf.String(), nil + return []*models.Step{step}, nil } func (i *logsCmd) getNonBootstrapMastersIPsInHostCluster(ctx context.Context, host *models.Host) ([]string, error) { diff --git a/internal/host/hostcommands/stop_installation_cmd.go b/internal/host/hostcommands/stop_installation_cmd.go index 5c31cc08dce..bd316794b7a 100644 --- a/internal/host/hostcommands/stop_installation_cmd.go +++ b/internal/host/hostcommands/stop_installation_cmd.go @@ -18,14 +18,10 @@ func NewStopInstallationCmd(log logrus.FieldLogger) *stopInstallationCmd { } func (h *stopInstallationCmd) GetSteps(ctx context.Context, host *models.Host) ([]*models.Step, error) { - command := "/usr/bin/podman" - step := &models.Step{ - StepType: models.StepTypeExecute, - Command: command, - Args: []string{ - "stop", "-i", "-t", "5", "assisted-installer", - }, + StepType: models.StepTypeStopInstallation, + Command: "", + Args: []string{}, } return []*models.Step{step}, nil diff --git a/models/logs_gather_cmd_request.go b/models/logs_gather_cmd_request.go new file mode 100644 index 00000000000..538b3817d36 --- /dev/null +++ b/models/logs_gather_cmd_request.go @@ -0,0 +1,215 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// LogsGatherCmdRequest logs gather cmd request +// +// swagger:model logs_gather_cmd_request +type LogsGatherCmdRequest struct { + + // Service base url to send logs to + // Required: true + BaseURL *string `json:"base_url"` + + // Host is bootstrap or not + // Required: true + Bootstrap *bool `json:"bootstrap"` + + // Path to certificate on the nodes + CaCertPath string `json:"ca_cert_path,omitempty"` + + // Cluster id + // Required: true + // Format: uuid + ClusterID *strfmt.UUID `json:"cluster_id"` + + // Host id + // Required: true + // Format: uuid + HostID *strfmt.UUID `json:"host_id"` + + // Infra env id + // Required: true + // Format: uuid + InfraEnvID *strfmt.UUID `json:"infra_env_id"` + + // Skip ceritifacate verification + // Required: true + Insecure *bool `json:"insecure"` + + // Run installer gather logs + // Required: true + InstallerGather bool `json:"installer_gather"` + + // List of master ips + MasterIps []string `json:"master_ips"` +} + +// Validate validates this logs gather cmd request +func (m *LogsGatherCmdRequest) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateBaseURL(formats); err != nil { + res = append(res, err) + } + + if err := m.validateBootstrap(formats); err != nil { + res = append(res, err) + } + + if err := m.validateClusterID(formats); err != nil { + res = append(res, err) + } + + if err := m.validateHostID(formats); err != nil { + res = append(res, err) + } + + if err := m.validateInfraEnvID(formats); err != nil { + res = append(res, err) + } + + if err := m.validateInsecure(formats); err != nil { + res = append(res, err) + } + + if err := m.validateInstallerGather(formats); err != nil { + res = append(res, err) + } + + if err := m.validateMasterIps(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *LogsGatherCmdRequest) validateBaseURL(formats strfmt.Registry) error { + + if err := validate.Required("base_url", "body", m.BaseURL); err != nil { + return err + } + + return nil +} + +func (m *LogsGatherCmdRequest) validateBootstrap(formats strfmt.Registry) error { + + if err := validate.Required("bootstrap", "body", m.Bootstrap); err != nil { + return err + } + + return nil +} + +func (m *LogsGatherCmdRequest) validateClusterID(formats strfmt.Registry) error { + + if err := validate.Required("cluster_id", "body", m.ClusterID); err != nil { + return err + } + + if err := validate.FormatOf("cluster_id", "body", "uuid", m.ClusterID.String(), formats); err != nil { + return err + } + + return nil +} + +func (m *LogsGatherCmdRequest) validateHostID(formats strfmt.Registry) error { + + if err := validate.Required("host_id", "body", m.HostID); err != nil { + return err + } + + if err := validate.FormatOf("host_id", "body", "uuid", m.HostID.String(), formats); err != nil { + return err + } + + return nil +} + +func (m *LogsGatherCmdRequest) validateInfraEnvID(formats strfmt.Registry) error { + + if err := validate.Required("infra_env_id", "body", m.InfraEnvID); err != nil { + return err + } + + if err := validate.FormatOf("infra_env_id", "body", "uuid", m.InfraEnvID.String(), formats); err != nil { + return err + } + + return nil +} + +func (m *LogsGatherCmdRequest) validateInsecure(formats strfmt.Registry) error { + + if err := validate.Required("insecure", "body", m.Insecure); err != nil { + return err + } + + return nil +} + +func (m *LogsGatherCmdRequest) validateInstallerGather(formats strfmt.Registry) error { + + if err := validate.Required("installer_gather", "body", bool(m.InstallerGather)); err != nil { + return err + } + + return nil +} + +func (m *LogsGatherCmdRequest) validateMasterIps(formats strfmt.Registry) error { + if swag.IsZero(m.MasterIps) { // not required + return nil + } + + for i := 0; i < len(m.MasterIps); i++ { + + if err := validate.Pattern("master_ips"+"."+strconv.Itoa(i), "body", m.MasterIps[i], `^(?:(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:(?:[0-9a-fA-F]*:[0-9a-fA-F]*){2,}))$`); err != nil { + return err + } + + } + + return nil +} + +// ContextValidate validates this logs gather cmd request based on context it is used +func (m *LogsGatherCmdRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *LogsGatherCmdRequest) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *LogsGatherCmdRequest) UnmarshalBinary(b []byte) error { + var res LogsGatherCmdRequest + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/models/next_step_cmd_request.go b/models/next_step_cmd_request.go new file mode 100644 index 00000000000..270e6fc4e1c --- /dev/null +++ b/models/next_step_cmd_request.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// NextStepCmdRequest next step cmd request +// +// swagger:model next_step_cmd_request +type NextStepCmdRequest struct { + + // Host id + // Required: true + // Format: uuid + HostID *strfmt.UUID `json:"host_id"` + + // Infra env id + // Required: true + // Format: uuid + InfraEnvID *strfmt.UUID `json:"infra_env_id"` + + // Skip ceritifacate verification + // Required: true + Insecure *bool `json:"insecure"` +} + +// Validate validates this next step cmd request +func (m *NextStepCmdRequest) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateHostID(formats); err != nil { + res = append(res, err) + } + + if err := m.validateInfraEnvID(formats); err != nil { + res = append(res, err) + } + + if err := m.validateInsecure(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NextStepCmdRequest) validateHostID(formats strfmt.Registry) error { + + if err := validate.Required("host_id", "body", m.HostID); err != nil { + return err + } + + if err := validate.FormatOf("host_id", "body", "uuid", m.HostID.String(), formats); err != nil { + return err + } + + return nil +} + +func (m *NextStepCmdRequest) validateInfraEnvID(formats strfmt.Registry) error { + + if err := validate.Required("infra_env_id", "body", m.InfraEnvID); err != nil { + return err + } + + if err := validate.FormatOf("infra_env_id", "body", "uuid", m.InfraEnvID.String(), formats); err != nil { + return err + } + + return nil +} + +func (m *NextStepCmdRequest) validateInsecure(formats strfmt.Registry) error { + + if err := validate.Required("insecure", "body", m.Insecure); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this next step cmd request based on context it is used +func (m *NextStepCmdRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *NextStepCmdRequest) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *NextStepCmdRequest) UnmarshalBinary(b []byte) error { + var res NextStepCmdRequest + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/models/step_type.go b/models/step_type.go index f332e90cfd5..dd76dbcf6e0 100644 --- a/models/step_type.go +++ b/models/step_type.go @@ -61,6 +61,15 @@ const ( // StepTypeDomainResolution captures enum value "domain-resolution" StepTypeDomainResolution StepType = "domain-resolution" + + // StepTypeStopInstallation captures enum value "stop-installation" + StepTypeStopInstallation StepType = "stop-installation" + + // StepTypeLogsGather captures enum value "logs-gather" + StepTypeLogsGather StepType = "logs-gather" + + // StepTypeNextStepRunner captures enum value "next-step-runner" + StepTypeNextStepRunner StepType = "next-step-runner" ) // for schema @@ -68,7 +77,7 @@ var stepTypeEnum []interface{} func init() { var res []StepType - if err := json.Unmarshal([]byte(`["connectivity-check","execute","inventory","install","free-network-addresses","reset-installation","dhcp-lease-allocate","api-vip-connectivity-check","ntp-synchronizer","installation-disk-speed-check","container-image-availability","domain-resolution"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["connectivity-check","execute","inventory","install","free-network-addresses","reset-installation","dhcp-lease-allocate","api-vip-connectivity-check","ntp-synchronizer","installation-disk-speed-check","container-image-availability","domain-resolution","stop-installation","logs-gather","next-step-runner"]`), &res); err != nil { panic(err) } for _, v := range res { diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index 6161760b514..da2dbc3fbde 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -7696,6 +7696,65 @@ func init() { } } }, + "logs_gather_cmd_request": { + "type": "object", + "required": [ + "cluster_id", + "infra_env_id", + "host_id", + "insecure", + "base_url", + "bootstrap", + "installer_gather" + ], + "properties": { + "base_url": { + "description": "Service base url to send logs to", + "type": "string" + }, + "bootstrap": { + "description": "Host is bootstrap or not", + "type": "boolean" + }, + "ca_cert_path": { + "description": "Path to certificate on the nodes", + "type": "string" + }, + "cluster_id": { + "description": "Cluster id", + "type": "string", + "format": "uuid" + }, + "host_id": { + "description": "Host id", + "type": "string", + "format": "uuid" + }, + "infra_env_id": { + "description": "Infra env id", + "type": "string", + "format": "uuid" + }, + "insecure": { + "description": "Skip ceritifacate verification", + "type": "boolean" + }, + "installer_gather": { + "description": "Run installer gather logs", + "type": "boolean", + "default": true + }, + "master_ips": { + "description": "List of master ips", + "type": "array", + "items": { + "description": "Master ip.", + "type": "string", + "pattern": "^(?:(?:(?:[0-9]{1,3}\\.){3}[0-9]{1,3})|(?:(?:[0-9a-fA-F]*:[0-9a-fA-F]*){2,}))$" + } + } + } + }, "logs_state": { "type": "string", "enum": [ @@ -7858,6 +7917,30 @@ func init() { "$ref": "#/definitions/monitored-operator" } }, + "next_step_cmd_request": { + "type": "object", + "required": [ + "infra_env_id", + "host_id", + "insecure" + ], + "properties": { + "host_id": { + "description": "Host id", + "type": "string", + "format": "uuid" + }, + "infra_env_id": { + "description": "Infra env id", + "type": "string", + "format": "uuid" + }, + "insecure": { + "description": "Skip ceritifacate verification", + "type": "boolean" + } + } + }, "ntp_source": { "type": "object", "properties": { @@ -8386,7 +8469,10 @@ func init() { "ntp-synchronizer", "installation-disk-speed-check", "container-image-availability", - "domain-resolution" + "domain-resolution", + "stop-installation", + "logs-gather", + "next-step-runner" ] }, "steps": { @@ -16470,6 +16556,65 @@ func init() { } } }, + "logs_gather_cmd_request": { + "type": "object", + "required": [ + "cluster_id", + "infra_env_id", + "host_id", + "insecure", + "base_url", + "bootstrap", + "installer_gather" + ], + "properties": { + "base_url": { + "description": "Service base url to send logs to", + "type": "string" + }, + "bootstrap": { + "description": "Host is bootstrap or not", + "type": "boolean" + }, + "ca_cert_path": { + "description": "Path to certificate on the nodes", + "type": "string" + }, + "cluster_id": { + "description": "Cluster id", + "type": "string", + "format": "uuid" + }, + "host_id": { + "description": "Host id", + "type": "string", + "format": "uuid" + }, + "infra_env_id": { + "description": "Infra env id", + "type": "string", + "format": "uuid" + }, + "insecure": { + "description": "Skip ceritifacate verification", + "type": "boolean" + }, + "installer_gather": { + "description": "Run installer gather logs", + "type": "boolean", + "default": true + }, + "master_ips": { + "description": "List of master ips", + "type": "array", + "items": { + "description": "Master ip.", + "type": "string", + "pattern": "^(?:(?:(?:[0-9]{1,3}\\.){3}[0-9]{1,3})|(?:(?:[0-9a-fA-F]*:[0-9a-fA-F]*){2,}))$" + } + } + } + }, "logs_state": { "type": "string", "enum": [ @@ -16621,6 +16766,30 @@ func init() { "$ref": "#/definitions/monitored-operator" } }, + "next_step_cmd_request": { + "type": "object", + "required": [ + "infra_env_id", + "host_id", + "insecure" + ], + "properties": { + "host_id": { + "description": "Host id", + "type": "string", + "format": "uuid" + }, + "infra_env_id": { + "description": "Infra env id", + "type": "string", + "format": "uuid" + }, + "insecure": { + "description": "Skip ceritifacate verification", + "type": "boolean" + } + } + }, "ntp_source": { "type": "object", "properties": { @@ -17149,7 +17318,10 @@ func init() { "ntp-synchronizer", "installation-disk-speed-check", "container-image-availability", - "domain-resolution" + "domain-resolution", + "stop-installation", + "logs-gather", + "next-step-runner" ] }, "steps": { diff --git a/swagger.yaml b/swagger.yaml index 404d04916e9..df375e328c2 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -4012,6 +4012,9 @@ definitions: - installation-disk-speed-check - container-image-availability - domain-resolution + - stop-installation + - logs-gather + - next-step-runner step: type: object @@ -5526,6 +5529,72 @@ definitions: type: string description: Contents of last acquired lease for Ingress virtual IP. + next_step_cmd_request: + type: object + required: + - infra_env_id + - host_id + - insecure + properties: + infra_env_id: + type: string + format: uuid + description: Infra env id + host_id: + type: string + format: uuid + description: Host id + insecure: + type: boolean + description: Skip ceritifacate verification + + logs_gather_cmd_request: + type: object + required: + - cluster_id + - infra_env_id + - host_id + - insecure + - base_url + - bootstrap + - installer_gather + properties: + cluster_id: + type: string + format: uuid + description: Cluster id + infra_env_id: + type: string + format: uuid + description: Infra env id + host_id: + type: string + format: uuid + description: Host id + base_url: + type: string + description: Service base url to send logs to + insecure: + type: boolean + description: Skip ceritifacate verification + bootstrap: + type: boolean + description: Host is bootstrap or not + installer_gather: + type: boolean + description: Run installer gather logs + default: true + ca_cert_path: + type: string + description: Path to certificate on the nodes + master_ips: + type: array + description: List of master ips + items: + type: string + description: Master ip. + pattern: '^(?:(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:(?:[0-9a-fA-F]*:[0-9a-fA-F]*){2,}))$' + ntp_synchronization_request: type: object required: From 4813e7801b2552ef1e541c6bdc60bc533fe5c225 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Tue, 22 Mar 2022 13:07:59 +0200 Subject: [PATCH 02/17] MGMT-9451: adding --- models/cluster.go | 68 +++--- models/cluster_create_params.go | 68 +++--- models/high_availability_mode.go | 76 +++++++ models/install_cmd_request.go | 361 +++++++++++++++++++++++++++++++ restapi/embedded_spec.go | 220 ++++++++++++++++--- swagger.yaml | 91 +++++++- 6 files changed, 770 insertions(+), 114 deletions(-) create mode 100644 models/high_availability_mode.go create mode 100644 models/install_cmd_request.go diff --git a/models/cluster.go b/models/cluster.go index 038990eceeb..957b31318dd 100644 --- a/models/cluster.go +++ b/models/cluster.go @@ -85,11 +85,8 @@ type Cluster struct { // JSON-formatted string containing the usage information by feature name FeatureUsage string `json:"feature_usage,omitempty" gorm:"type:text"` - // Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster - // over multiple master nodes whereas 'None' installs a full cluster over one node. - // - // Enum: [Full None] - HighAvailabilityMode *string `json:"high_availability_mode,omitempty"` + // high availability mode + HighAvailabilityMode *HighAvailabilityMode `json:"high_availability_mode,omitempty"` // List of host networks to be filled during query. HostNetworks []*HostNetwork `json:"host_networks" gorm:"-"` @@ -531,43 +528,20 @@ func (m *Cluster) validateDiskEncryption(formats strfmt.Registry) error { return nil } -var clusterTypeHighAvailabilityModePropEnum []interface{} - -func init() { - var res []string - if err := json.Unmarshal([]byte(`["Full","None"]`), &res); err != nil { - panic(err) - } - for _, v := range res { - clusterTypeHighAvailabilityModePropEnum = append(clusterTypeHighAvailabilityModePropEnum, v) - } -} - -const ( - - // ClusterHighAvailabilityModeFull captures enum value "Full" - ClusterHighAvailabilityModeFull string = "Full" - - // ClusterHighAvailabilityModeNone captures enum value "None" - ClusterHighAvailabilityModeNone string = "None" -) - -// prop value enum -func (m *Cluster) validateHighAvailabilityModeEnum(path, location string, value string) error { - if err := validate.EnumCase(path, location, value, clusterTypeHighAvailabilityModePropEnum, true); err != nil { - return err - } - return nil -} - func (m *Cluster) validateHighAvailabilityMode(formats strfmt.Registry) error { if swag.IsZero(m.HighAvailabilityMode) { // not required return nil } - // value enum - if err := m.validateHighAvailabilityModeEnum("high_availability_mode", "body", *m.HighAvailabilityMode); err != nil { - return err + if m.HighAvailabilityMode != nil { + if err := m.HighAvailabilityMode.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("high_availability_mode") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("high_availability_mode") + } + return err + } } return nil @@ -1139,6 +1113,10 @@ func (m *Cluster) ContextValidate(ctx context.Context, formats strfmt.Registry) res = append(res, err) } + if err := m.contextValidateHighAvailabilityMode(ctx, formats); err != nil { + res = append(res, err) + } + if err := m.contextValidateHostNetworks(ctx, formats); err != nil { res = append(res, err) } @@ -1221,6 +1199,22 @@ func (m *Cluster) contextValidateDiskEncryption(ctx context.Context, formats str return nil } +func (m *Cluster) contextValidateHighAvailabilityMode(ctx context.Context, formats strfmt.Registry) error { + + if m.HighAvailabilityMode != nil { + if err := m.HighAvailabilityMode.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("high_availability_mode") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("high_availability_mode") + } + return err + } + } + + return nil +} + func (m *Cluster) contextValidateHostNetworks(ctx context.Context, formats strfmt.Registry) error { for i := 0; i < len(m.HostNetworks); i++ { diff --git a/models/cluster_create_params.go b/models/cluster_create_params.go index 7c3b8947961..8818c0f10d0 100644 --- a/models/cluster_create_params.go +++ b/models/cluster_create_params.go @@ -45,11 +45,8 @@ type ClusterCreateParams struct { // Installation disks encryption mode and host roles to be applied. DiskEncryption *DiskEncryption `json:"disk_encryption,omitempty" gorm:"embedded;embeddedPrefix:disk_encryption_"` - // Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster - // over multiple master nodes whereas 'None' installs a full cluster over one node. - // - // Enum: [Full None] - HighAvailabilityMode *string `json:"high_availability_mode,omitempty"` + // high availability mode + HighAvailabilityMode *HighAvailabilityMode `json:"high_availability_mode,omitempty"` // A proxy URL to use for creating HTTP connections outside the cluster. // http://\:\@\:\ @@ -276,43 +273,20 @@ func (m *ClusterCreateParams) validateDiskEncryption(formats strfmt.Registry) er return nil } -var clusterCreateParamsTypeHighAvailabilityModePropEnum []interface{} - -func init() { - var res []string - if err := json.Unmarshal([]byte(`["Full","None"]`), &res); err != nil { - panic(err) - } - for _, v := range res { - clusterCreateParamsTypeHighAvailabilityModePropEnum = append(clusterCreateParamsTypeHighAvailabilityModePropEnum, v) - } -} - -const ( - - // ClusterCreateParamsHighAvailabilityModeFull captures enum value "Full" - ClusterCreateParamsHighAvailabilityModeFull string = "Full" - - // ClusterCreateParamsHighAvailabilityModeNone captures enum value "None" - ClusterCreateParamsHighAvailabilityModeNone string = "None" -) - -// prop value enum -func (m *ClusterCreateParams) validateHighAvailabilityModeEnum(path, location string, value string) error { - if err := validate.EnumCase(path, location, value, clusterCreateParamsTypeHighAvailabilityModePropEnum, true); err != nil { - return err - } - return nil -} - func (m *ClusterCreateParams) validateHighAvailabilityMode(formats strfmt.Registry) error { if swag.IsZero(m.HighAvailabilityMode) { // not required return nil } - // value enum - if err := m.validateHighAvailabilityModeEnum("high_availability_mode", "body", *m.HighAvailabilityMode); err != nil { - return err + if m.HighAvailabilityMode != nil { + if err := m.HighAvailabilityMode.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("high_availability_mode") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("high_availability_mode") + } + return err + } } return nil @@ -595,6 +569,10 @@ func (m *ClusterCreateParams) ContextValidate(ctx context.Context, formats strfm res = append(res, err) } + if err := m.contextValidateHighAvailabilityMode(ctx, formats); err != nil { + res = append(res, err) + } + if err := m.contextValidateIgnitionEndpoint(ctx, formats); err != nil { res = append(res, err) } @@ -657,6 +635,22 @@ func (m *ClusterCreateParams) contextValidateDiskEncryption(ctx context.Context, return nil } +func (m *ClusterCreateParams) contextValidateHighAvailabilityMode(ctx context.Context, formats strfmt.Registry) error { + + if m.HighAvailabilityMode != nil { + if err := m.HighAvailabilityMode.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("high_availability_mode") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("high_availability_mode") + } + return err + } + } + + return nil +} + func (m *ClusterCreateParams) contextValidateIgnitionEndpoint(ctx context.Context, formats strfmt.Registry) error { if m.IgnitionEndpoint != nil { diff --git a/models/high_availability_mode.go b/models/high_availability_mode.go new file mode 100644 index 00000000000..d4323406137 --- /dev/null +++ b/models/high_availability_mode.go @@ -0,0 +1,76 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" +) + +// HighAvailabilityMode Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster +// over multiple master nodes whereas 'None' installs a full cluster over one node. +// +// +// swagger:model high_availability_mode +type HighAvailabilityMode string + +func NewHighAvailabilityMode(value HighAvailabilityMode) *HighAvailabilityMode { + v := value + return &v +} + +const ( + + // HighAvailabilityModeFull captures enum value "Full" + HighAvailabilityModeFull HighAvailabilityMode = "Full" + + // HighAvailabilityModeNone captures enum value "None" + HighAvailabilityModeNone HighAvailabilityMode = "None" +) + +// for schema +var highAvailabilityModeEnum []interface{} + +func init() { + var res []HighAvailabilityMode + if err := json.Unmarshal([]byte(`["Full","None"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + highAvailabilityModeEnum = append(highAvailabilityModeEnum, v) + } +} + +func (m HighAvailabilityMode) validateHighAvailabilityModeEnum(path, location string, value HighAvailabilityMode) error { + if err := validate.EnumCase(path, location, value, highAvailabilityModeEnum, true); err != nil { + return err + } + return nil +} + +// Validate validates this high availability mode +func (m HighAvailabilityMode) Validate(formats strfmt.Registry) error { + var res []error + + // value enum + if err := m.validateHighAvailabilityModeEnum("", "body", m); err != nil { + return err + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// ContextValidate validates this high availability mode based on context it is used +func (m HighAvailabilityMode) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} diff --git a/models/install_cmd_request.go b/models/install_cmd_request.go new file mode 100644 index 00000000000..2a3bfcd1ec5 --- /dev/null +++ b/models/install_cmd_request.go @@ -0,0 +1,361 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// InstallCmdRequest install cmd request +// +// swagger:model install_cmd_request +type InstallCmdRequest struct { + + // Service base url to send logs to + // Required: true + BaseURL *string `json:"base_url"` + + // Boot device to write image on + // Required: true + Bootdevice *string `json:"bootdevice"` + + // Path to certificate on the nodes + CaCertPath string `json:"ca_cert_path,omitempty"` + + // Check CVO status if needed + CheckCvo *bool `json:"check_cvo,omitempty"` + + // Cluster id + // Required: true + // Format: uuid + ClusterID *strfmt.UUID `json:"cluster_id"` + + // Assisted installer controller image + // Required: true + ControllerImage *string `json:"controller_image"` + + // List of disks to format + DiskToFormat []string `json:"disk_to_format"` + + // high availability mode + // Required: true + HighAvailabilityMode *HighAvailabilityMode `json:"high_availability_mode"` + + // Host id + // Required: true + // Format: uuid + HostID *strfmt.UUID `json:"host_id"` + + // Infra env id + // Required: true + // Format: uuid + InfraEnvID *strfmt.UUID `json:"infra_env_id"` + + // Skip ceritifacate verification + // Required: true + Insecure *bool `json:"insecure"` + + // Machine config operator image + McoImage string `json:"mco_image,omitempty"` + + // Must-gather images to use + MustGatherImage string `json:"must_gather_image,omitempty"` + + // Version of the OpenShift cluster. + OpenshiftVersion string `json:"openshift_version,omitempty"` + + // proxy + Proxy *Proxy `json:"proxy,omitempty" gorm:"embedded;embeddedPrefix:proxy_"` + + // role + // Required: true + Role *HostRole `json:"role"` +} + +// Validate validates this install cmd request +func (m *InstallCmdRequest) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateBaseURL(formats); err != nil { + res = append(res, err) + } + + if err := m.validateBootdevice(formats); err != nil { + res = append(res, err) + } + + if err := m.validateClusterID(formats); err != nil { + res = append(res, err) + } + + if err := m.validateControllerImage(formats); err != nil { + res = append(res, err) + } + + if err := m.validateHighAvailabilityMode(formats); err != nil { + res = append(res, err) + } + + if err := m.validateHostID(formats); err != nil { + res = append(res, err) + } + + if err := m.validateInfraEnvID(formats); err != nil { + res = append(res, err) + } + + if err := m.validateInsecure(formats); err != nil { + res = append(res, err) + } + + if err := m.validateProxy(formats); err != nil { + res = append(res, err) + } + + if err := m.validateRole(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *InstallCmdRequest) validateBaseURL(formats strfmt.Registry) error { + + if err := validate.Required("base_url", "body", m.BaseURL); err != nil { + return err + } + + return nil +} + +func (m *InstallCmdRequest) validateBootdevice(formats strfmt.Registry) error { + + if err := validate.Required("bootdevice", "body", m.Bootdevice); err != nil { + return err + } + + return nil +} + +func (m *InstallCmdRequest) validateClusterID(formats strfmt.Registry) error { + + if err := validate.Required("cluster_id", "body", m.ClusterID); err != nil { + return err + } + + if err := validate.FormatOf("cluster_id", "body", "uuid", m.ClusterID.String(), formats); err != nil { + return err + } + + return nil +} + +func (m *InstallCmdRequest) validateControllerImage(formats strfmt.Registry) error { + + if err := validate.Required("controller_image", "body", m.ControllerImage); err != nil { + return err + } + + return nil +} + +func (m *InstallCmdRequest) validateHighAvailabilityMode(formats strfmt.Registry) error { + + if err := validate.Required("high_availability_mode", "body", m.HighAvailabilityMode); err != nil { + return err + } + + if err := validate.Required("high_availability_mode", "body", m.HighAvailabilityMode); err != nil { + return err + } + + if m.HighAvailabilityMode != nil { + if err := m.HighAvailabilityMode.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("high_availability_mode") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("high_availability_mode") + } + return err + } + } + + return nil +} + +func (m *InstallCmdRequest) validateHostID(formats strfmt.Registry) error { + + if err := validate.Required("host_id", "body", m.HostID); err != nil { + return err + } + + if err := validate.FormatOf("host_id", "body", "uuid", m.HostID.String(), formats); err != nil { + return err + } + + return nil +} + +func (m *InstallCmdRequest) validateInfraEnvID(formats strfmt.Registry) error { + + if err := validate.Required("infra_env_id", "body", m.InfraEnvID); err != nil { + return err + } + + if err := validate.FormatOf("infra_env_id", "body", "uuid", m.InfraEnvID.String(), formats); err != nil { + return err + } + + return nil +} + +func (m *InstallCmdRequest) validateInsecure(formats strfmt.Registry) error { + + if err := validate.Required("insecure", "body", m.Insecure); err != nil { + return err + } + + return nil +} + +func (m *InstallCmdRequest) validateProxy(formats strfmt.Registry) error { + if swag.IsZero(m.Proxy) { // not required + return nil + } + + if m.Proxy != nil { + if err := m.Proxy.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("proxy") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("proxy") + } + return err + } + } + + return nil +} + +func (m *InstallCmdRequest) validateRole(formats strfmt.Registry) error { + + if err := validate.Required("role", "body", m.Role); err != nil { + return err + } + + if err := validate.Required("role", "body", m.Role); err != nil { + return err + } + + if m.Role != nil { + if err := m.Role.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("role") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("role") + } + return err + } + } + + return nil +} + +// ContextValidate validate this install cmd request based on the context it is used +func (m *InstallCmdRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateHighAvailabilityMode(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateProxy(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateRole(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *InstallCmdRequest) contextValidateHighAvailabilityMode(ctx context.Context, formats strfmt.Registry) error { + + if m.HighAvailabilityMode != nil { + if err := m.HighAvailabilityMode.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("high_availability_mode") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("high_availability_mode") + } + return err + } + } + + return nil +} + +func (m *InstallCmdRequest) contextValidateProxy(ctx context.Context, formats strfmt.Registry) error { + + if m.Proxy != nil { + if err := m.Proxy.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("proxy") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("proxy") + } + return err + } + } + + return nil +} + +func (m *InstallCmdRequest) contextValidateRole(ctx context.Context, formats strfmt.Registry) error { + + if m.Role != nil { + if err := m.Role.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("role") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("role") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *InstallCmdRequest) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *InstallCmdRequest) UnmarshalBinary(b []byte) error { + var res InstallCmdRequest + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index da2dbc3fbde..27b1a20e6f8 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -5224,13 +5224,7 @@ func init() { "x-go-custom-tag": "gorm:\"type:text\"" }, "high_availability_mode": { - "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", - "type": "string", - "default": "Full", - "enum": [ - "Full", - "None" - ] + "$ref": "#/definitions/high_availability_mode" }, "host_networks": { "description": "List of host networks to be filled during query.", @@ -5543,13 +5537,7 @@ func init() { "$ref": "#/definitions/disk-encryption" }, "high_availability_mode": { - "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", - "type": "string", - "default": "Full", - "enum": [ - "Full", - "None" - ] + "$ref": "#/definitions/high_availability_mode" }, "http_proxy": { "description": "A proxy URL to use for creating HTTP connections outside the cluster.\nhttp://\\\u003cusername\\\u003e:\\\u003cpswd\\\u003e@\\\u003cip\\\u003e:\\\u003cport\\\u003e\n", @@ -6594,6 +6582,15 @@ func init() { } } }, + "high_availability_mode": { + "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", + "type": "string", + "default": "Full", + "enum": [ + "Full", + "None" + ] + }, "host": { "type": "object", "required": [ @@ -7477,6 +7474,91 @@ func init() { "ingress-cert-params": { "type": "string" }, + "install_cmd_request": { + "type": "object", + "required": [ + "cluster_id", + "infra_env_id", + "host_id", + "insecure", + "base_url", + "role", + "bootdevice", + "controller_image", + "high_availability_mode" + ], + "properties": { + "base_url": { + "description": "Service base url to send logs to", + "type": "string" + }, + "bootdevice": { + "description": "Boot device to write image on", + "type": "string" + }, + "ca_cert_path": { + "description": "Path to certificate on the nodes", + "type": "string" + }, + "check_cvo": { + "description": "Check CVO status if needed", + "type": "boolean", + "default": true + }, + "cluster_id": { + "description": "Cluster id", + "type": "string", + "format": "uuid" + }, + "controller_image": { + "description": "Assisted installer controller image", + "type": "string" + }, + "disk_to_format": { + "description": "List of disks to format", + "type": "array", + "items": { + "description": "Disk to format", + "type": "string" + } + }, + "high_availability_mode": { + "$ref": "#/definitions/high_availability_mode" + }, + "host_id": { + "description": "Host id", + "type": "string", + "format": "uuid" + }, + "infra_env_id": { + "description": "Infra env id", + "type": "string", + "format": "uuid" + }, + "insecure": { + "description": "Skip ceritifacate verification", + "type": "boolean" + }, + "mco_image": { + "description": "Machine config operator image", + "type": "string" + }, + "must_gather_image": { + "description": "Must-gather images to use", + "type": "string" + }, + "openshift_version": { + "description": "Version of the OpenShift cluster.", + "type": "string" + }, + "proxy": { + "$ref": "#/definitions/proxy" + }, + "role": { + "$ref": "#/definitions/host-role" + } + } + }, "installer-args-params": { "type": "object", "properties": { @@ -14151,13 +14233,7 @@ func init() { "x-go-custom-tag": "gorm:\"type:text\"" }, "high_availability_mode": { - "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", - "type": "string", - "default": "Full", - "enum": [ - "Full", - "None" - ] + "$ref": "#/definitions/high_availability_mode" }, "host_networks": { "description": "List of host networks to be filled during query.", @@ -14470,13 +14546,7 @@ func init() { "$ref": "#/definitions/disk-encryption" }, "high_availability_mode": { - "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", - "type": "string", - "default": "Full", - "enum": [ - "Full", - "None" - ] + "$ref": "#/definitions/high_availability_mode" }, "http_proxy": { "description": "A proxy URL to use for creating HTTP connections outside the cluster.\nhttp://\\\u003cusername\\\u003e:\\\u003cpswd\\\u003e@\\\u003cip\\\u003e:\\\u003cport\\\u003e\n", @@ -15452,6 +15522,15 @@ func init() { } } }, + "high_availability_mode": { + "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", + "type": "string", + "default": "Full", + "enum": [ + "Full", + "None" + ] + }, "host": { "type": "object", "required": [ @@ -16337,6 +16416,91 @@ func init() { "ingress-cert-params": { "type": "string" }, + "install_cmd_request": { + "type": "object", + "required": [ + "cluster_id", + "infra_env_id", + "host_id", + "insecure", + "base_url", + "role", + "bootdevice", + "controller_image", + "high_availability_mode" + ], + "properties": { + "base_url": { + "description": "Service base url to send logs to", + "type": "string" + }, + "bootdevice": { + "description": "Boot device to write image on", + "type": "string" + }, + "ca_cert_path": { + "description": "Path to certificate on the nodes", + "type": "string" + }, + "check_cvo": { + "description": "Check CVO status if needed", + "type": "boolean", + "default": true + }, + "cluster_id": { + "description": "Cluster id", + "type": "string", + "format": "uuid" + }, + "controller_image": { + "description": "Assisted installer controller image", + "type": "string" + }, + "disk_to_format": { + "description": "List of disks to format", + "type": "array", + "items": { + "description": "Disk to format", + "type": "string" + } + }, + "high_availability_mode": { + "$ref": "#/definitions/high_availability_mode" + }, + "host_id": { + "description": "Host id", + "type": "string", + "format": "uuid" + }, + "infra_env_id": { + "description": "Infra env id", + "type": "string", + "format": "uuid" + }, + "insecure": { + "description": "Skip ceritifacate verification", + "type": "boolean" + }, + "mco_image": { + "description": "Machine config operator image", + "type": "string" + }, + "must_gather_image": { + "description": "Must-gather images to use", + "type": "string" + }, + "openshift_version": { + "description": "Version of the OpenShift cluster.", + "type": "string" + }, + "proxy": { + "$ref": "#/definitions/proxy" + }, + "role": { + "$ref": "#/definitions/host-role" + } + } + }, "installer-args-params": { "type": "object", "properties": { diff --git a/swagger.yaml b/swagger.yaml index df375e328c2..ffaee8b4cc0 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -4095,12 +4095,7 @@ definitions: maxLength: 54 description: Name of the OpenShift cluster. high_availability_mode: - type: string - enum: ['Full', 'None'] - default: 'Full' - description: | - Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster - over multiple master nodes whereas 'None' installs a full cluster over one node. + $ref: '#/definitions/high_availability_mode' openshift_version: type: string description: Version of the OpenShift cluster. @@ -4421,12 +4416,7 @@ definitions: Indicates the type of this object. Will be 'Cluster' if this is a complete object, 'AddHostsCluster' for cluster that add hosts to existing OCP cluster, high_availability_mode: - type: string - enum: ['Full', 'None'] - default: 'Full' - description: | - Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster - over multiple master nodes whereas 'None' installs a full cluster over one node. + $ref: '#/definitions/high_availability_mode' id: type: string format: uuid @@ -4738,6 +4728,14 @@ definitions: $ref: '#/definitions/ovirt-platform' x-nullable: true + high_availability_mode: + type: string + enum: ['Full', 'None'] + default: 'Full' + description: | + Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster + over multiple master nodes whereas 'None' installs a full cluster over one node. + image_info: type: object x-go-custom-tag: gorm:"embedded;embeddedPrefix:image_" @@ -5595,6 +5593,75 @@ definitions: description: Master ip. pattern: '^(?:(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:(?:[0-9a-fA-F]*:[0-9a-fA-F]*){2,}))$' + + install_cmd_request: + type: object + required: + - cluster_id + - infra_env_id + - host_id + - insecure + - base_url + - role + - bootdevice + - controller_image + - high_availability_mode + properties: + cluster_id: + type: string + format: uuid + description: Cluster id + infra_env_id: + type: string + format: uuid + description: Infra env id + host_id: + type: string + format: uuid + description: Host id + base_url: + type: string + description: Service base url to send logs to + insecure: + type: boolean + description: Skip ceritifacate verification + role: + $ref: '#/definitions/host-role' + bootdevice: + type: string + description: Boot device to write image on + controller_image: + type: string + description: Assisted installer controller image + high_availability_mode: + $ref: '#/definitions/high_availability_mode' + + proxy: + $ref: "#/definitions/proxy" + check_cvo: + type: boolean + description: Check CVO status if needed + default: true + disk_to_format: + type: array + description: List of disks to format + items: + type: string + description: Disk to format + must_gather_image: + type: string + description: Must-gather images to use + mco_image: + type: string + description: Machine config operator image + openshift_version: + type: string + description: Version of the OpenShift cluster. + ca_cert_path: + type: string + description: Path to certificate on the nodes + + ntp_synchronization_request: type: object required: From 529c646e3cfcf5aff0d518ec60895bcfba2ae866 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Tue, 22 Mar 2022 14:59:56 +0200 Subject: [PATCH 03/17] MGMT-9451: adding --- models/install_cmd_request.go | 44 +++++++++++++++++++++++++++++++++++ restapi/embedded_spec.go | 36 ++++++++++++++++++++++++++++ swagger.yaml | 14 +++++++++++ 3 files changed, 94 insertions(+) diff --git a/models/install_cmd_request.go b/models/install_cmd_request.go index 2a3bfcd1ec5..6d9b37842b2 100644 --- a/models/install_cmd_request.go +++ b/models/install_cmd_request.go @@ -7,6 +7,7 @@ package models import ( "context" + "strconv" "github.com/go-openapi/errors" "github.com/go-openapi/strfmt" @@ -63,6 +64,13 @@ type InstallCmdRequest struct { // Required: true Insecure *bool `json:"insecure"` + // Core-os installer addtional args + InstallerArgs string `json:"installer_args,omitempty"` + + // Assisted installer image + // Required: true + InstallerImage *string `json:"installer_image"` + // Machine config operator image McoImage string `json:"mco_image,omitempty"` @@ -78,6 +86,9 @@ type InstallCmdRequest struct { // role // Required: true Role *HostRole `json:"role"` + + // List of service ips + ServiceIps []string `json:"service_ips"` } // Validate validates this install cmd request @@ -116,6 +127,10 @@ func (m *InstallCmdRequest) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateInstallerImage(formats); err != nil { + res = append(res, err) + } + if err := m.validateProxy(formats); err != nil { res = append(res, err) } @@ -124,6 +139,10 @@ func (m *InstallCmdRequest) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateServiceIps(formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -229,6 +248,15 @@ func (m *InstallCmdRequest) validateInsecure(formats strfmt.Registry) error { return nil } +func (m *InstallCmdRequest) validateInstallerImage(formats strfmt.Registry) error { + + if err := validate.Required("installer_image", "body", m.InstallerImage); err != nil { + return err + } + + return nil +} + func (m *InstallCmdRequest) validateProxy(formats strfmt.Registry) error { if swag.IsZero(m.Proxy) { // not required return nil @@ -272,6 +300,22 @@ func (m *InstallCmdRequest) validateRole(formats strfmt.Registry) error { return nil } +func (m *InstallCmdRequest) validateServiceIps(formats strfmt.Registry) error { + if swag.IsZero(m.ServiceIps) { // not required + return nil + } + + for i := 0; i < len(m.ServiceIps); i++ { + + if err := validate.Pattern("service_ips"+"."+strconv.Itoa(i), "body", m.ServiceIps[i], `^(?:(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:(?:[0-9a-fA-F]*:[0-9a-fA-F]*){2,}))$`); err != nil { + return err + } + + } + + return nil +} + // ContextValidate validate this install cmd request based on the context it is used func (m *InstallCmdRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { var res []error diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index 27b1a20e6f8..9eee1e7c131 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -7485,6 +7485,7 @@ func init() { "role", "bootdevice", "controller_image", + "installer_image", "high_availability_mode" ], "properties": { @@ -7539,6 +7540,14 @@ func init() { "description": "Skip ceritifacate verification", "type": "boolean" }, + "installer_args": { + "description": "Core-os installer addtional args", + "type": "string" + }, + "installer_image": { + "description": "Assisted installer image", + "type": "string" + }, "mco_image": { "description": "Machine config operator image", "type": "string" @@ -7556,6 +7565,15 @@ func init() { }, "role": { "$ref": "#/definitions/host-role" + }, + "service_ips": { + "description": "List of service ips", + "type": "array", + "items": { + "description": "Service ip.", + "type": "string", + "pattern": "^(?:(?:(?:[0-9]{1,3}\\.){3}[0-9]{1,3})|(?:(?:[0-9a-fA-F]*:[0-9a-fA-F]*){2,}))$" + } } } }, @@ -16427,6 +16445,7 @@ func init() { "role", "bootdevice", "controller_image", + "installer_image", "high_availability_mode" ], "properties": { @@ -16481,6 +16500,14 @@ func init() { "description": "Skip ceritifacate verification", "type": "boolean" }, + "installer_args": { + "description": "Core-os installer addtional args", + "type": "string" + }, + "installer_image": { + "description": "Assisted installer image", + "type": "string" + }, "mco_image": { "description": "Machine config operator image", "type": "string" @@ -16498,6 +16525,15 @@ func init() { }, "role": { "$ref": "#/definitions/host-role" + }, + "service_ips": { + "description": "List of service ips", + "type": "array", + "items": { + "description": "Service ip.", + "type": "string", + "pattern": "^(?:(?:(?:[0-9]{1,3}\\.){3}[0-9]{1,3})|(?:(?:[0-9a-fA-F]*:[0-9a-fA-F]*){2,}))$" + } } } }, diff --git a/swagger.yaml b/swagger.yaml index ffaee8b4cc0..12d8ea42f67 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -5605,6 +5605,7 @@ definitions: - role - bootdevice - controller_image + - installer_image - high_availability_mode properties: cluster_id: @@ -5633,6 +5634,9 @@ definitions: controller_image: type: string description: Assisted installer controller image + installer_image: + type: string + description: Assisted installer image high_availability_mode: $ref: '#/definitions/high_availability_mode' @@ -5660,6 +5664,16 @@ definitions: ca_cert_path: type: string description: Path to certificate on the nodes + service_ips: + type: array + description: List of service ips + items: + type: string + description: Service ip. + pattern: '^(?:(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:(?:[0-9a-fA-F]*:[0-9a-fA-F]*){2,}))$' + installer_args: + type: string + description: Core-os installer addtional args ntp_synchronization_request: From b079c4f8d1132fd2e2a189d61930d171bf35ba0c Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Tue, 22 Mar 2022 17:38:48 +0200 Subject: [PATCH 04/17] MGMT-9451: adding --- internal/host/hostcommands/install_cmd.go | 6 +- models/cluster.go | 2 +- models/cluster_create_params.go | 2 +- models/high_availability_mode.go | 76 ----------------------- models/install_cmd_request.go | 2 +- restapi/embedded_spec.go | 48 +++++++------- swagger.yaml | 8 +-- 7 files changed, 36 insertions(+), 108 deletions(-) delete mode 100644 models/high_availability_mode.go diff --git a/internal/host/hostcommands/install_cmd.go b/internal/host/hostcommands/install_cmd.go index 8dc755175e9..d8ba85f0a4d 100644 --- a/internal/host/hostcommands/install_cmd.go +++ b/internal/host/hostcommands/install_cmd.go @@ -61,7 +61,6 @@ func NewInstallCmd(log logrus.FieldLogger, db *gorm.DB, hwValidator hardware.Val func (i *installCmd) GetSteps(ctx context.Context, host *models.Host) ([]*models.Step, error) { step := &models.Step{} step.StepType = models.StepTypeInstall - step.Command = "bash" cluster, err := common.GetClusterFromDBWithHosts(i.db, *host.ClusterID) if err != nil { @@ -103,6 +102,8 @@ func (i *installCmd) GetSteps(ctx context.Context, host *models.Host) ([]*models } func (i *installCmd) getFullInstallerCommand(cluster *common.Cluster, host *models.Host, infraEnv *common.InfraEnv, bootdevice string, disksToFormat []string) (string, error) { + var request models.InstallCmdRequest + role := common.GetEffectiveRole(host) if host.Bootstrap { role = models.HostRoleBootstrap @@ -113,6 +114,9 @@ func (i *installCmd) getFullInstallerCommand(cluster *common.Cluster, host *mode haMode = *cluster.HighAvailabilityMode } + + + podmanCmd := podmanBaseCmd[:] installerCmdArgs := []string{ "--role", string(role), diff --git a/models/cluster.go b/models/cluster.go index 957b31318dd..260533afee9 100644 --- a/models/cluster.go +++ b/models/cluster.go @@ -86,7 +86,7 @@ type Cluster struct { FeatureUsage string `json:"feature_usage,omitempty" gorm:"type:text"` // high availability mode - HighAvailabilityMode *HighAvailabilityMode `json:"high_availability_mode,omitempty"` + HighAvailabilityMode *ClusterHighAvailabilityMode `json:"high_availability_mode,omitempty"` // List of host networks to be filled during query. HostNetworks []*HostNetwork `json:"host_networks" gorm:"-"` diff --git a/models/cluster_create_params.go b/models/cluster_create_params.go index 8818c0f10d0..8522fb5f376 100644 --- a/models/cluster_create_params.go +++ b/models/cluster_create_params.go @@ -46,7 +46,7 @@ type ClusterCreateParams struct { DiskEncryption *DiskEncryption `json:"disk_encryption,omitempty" gorm:"embedded;embeddedPrefix:disk_encryption_"` // high availability mode - HighAvailabilityMode *HighAvailabilityMode `json:"high_availability_mode,omitempty"` + HighAvailabilityMode *ClusterHighAvailabilityMode `json:"high_availability_mode,omitempty"` // A proxy URL to use for creating HTTP connections outside the cluster. // http://\:\@\:\ diff --git a/models/high_availability_mode.go b/models/high_availability_mode.go deleted file mode 100644 index d4323406137..00000000000 --- a/models/high_availability_mode.go +++ /dev/null @@ -1,76 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "encoding/json" - - "github.com/go-openapi/errors" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/validate" -) - -// HighAvailabilityMode Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster -// over multiple master nodes whereas 'None' installs a full cluster over one node. -// -// -// swagger:model high_availability_mode -type HighAvailabilityMode string - -func NewHighAvailabilityMode(value HighAvailabilityMode) *HighAvailabilityMode { - v := value - return &v -} - -const ( - - // HighAvailabilityModeFull captures enum value "Full" - HighAvailabilityModeFull HighAvailabilityMode = "Full" - - // HighAvailabilityModeNone captures enum value "None" - HighAvailabilityModeNone HighAvailabilityMode = "None" -) - -// for schema -var highAvailabilityModeEnum []interface{} - -func init() { - var res []HighAvailabilityMode - if err := json.Unmarshal([]byte(`["Full","None"]`), &res); err != nil { - panic(err) - } - for _, v := range res { - highAvailabilityModeEnum = append(highAvailabilityModeEnum, v) - } -} - -func (m HighAvailabilityMode) validateHighAvailabilityModeEnum(path, location string, value HighAvailabilityMode) error { - if err := validate.EnumCase(path, location, value, highAvailabilityModeEnum, true); err != nil { - return err - } - return nil -} - -// Validate validates this high availability mode -func (m HighAvailabilityMode) Validate(formats strfmt.Registry) error { - var res []error - - // value enum - if err := m.validateHighAvailabilityModeEnum("", "body", m); err != nil { - return err - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -// ContextValidate validates this high availability mode based on context it is used -func (m HighAvailabilityMode) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - return nil -} diff --git a/models/install_cmd_request.go b/models/install_cmd_request.go index 6d9b37842b2..4adae490d6f 100644 --- a/models/install_cmd_request.go +++ b/models/install_cmd_request.go @@ -48,7 +48,7 @@ type InstallCmdRequest struct { // high availability mode // Required: true - HighAvailabilityMode *HighAvailabilityMode `json:"high_availability_mode"` + HighAvailabilityMode *ClusterHighAvailabilityMode `json:"high_availability_mode"` // Host id // Required: true diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index 9eee1e7c131..43cc17f3e4f 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -5224,7 +5224,7 @@ func init() { "x-go-custom-tag": "gorm:\"type:text\"" }, "high_availability_mode": { - "$ref": "#/definitions/high_availability_mode" + "$ref": "#/definitions/cluster_high_availability_mode" }, "host_networks": { "description": "List of host networks to be filled during query.", @@ -5537,7 +5537,7 @@ func init() { "$ref": "#/definitions/disk-encryption" }, "high_availability_mode": { - "$ref": "#/definitions/high_availability_mode" + "$ref": "#/definitions/cluster_high_availability_mode" }, "http_proxy": { "description": "A proxy URL to use for creating HTTP connections outside the cluster.\nhttp://\\\u003cusername\\\u003e:\\\u003cpswd\\\u003e@\\\u003cip\\\u003e:\\\u003cport\\\u003e\n", @@ -5804,6 +5804,15 @@ func init() { } } }, + "cluster_high_availability_mode": { + "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", + "type": "string", + "default": "Full", + "enum": [ + "Full", + "None" + ] + }, "cluster_network": { "description": "IP address block for pod IP blocks.", "type": "object", @@ -6582,15 +6591,6 @@ func init() { } } }, - "high_availability_mode": { - "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", - "type": "string", - "default": "Full", - "enum": [ - "Full", - "None" - ] - }, "host": { "type": "object", "required": [ @@ -7524,7 +7524,7 @@ func init() { } }, "high_availability_mode": { - "$ref": "#/definitions/high_availability_mode" + "$ref": "#/definitions/cluster_high_availability_mode" }, "host_id": { "description": "Host id", @@ -14251,7 +14251,7 @@ func init() { "x-go-custom-tag": "gorm:\"type:text\"" }, "high_availability_mode": { - "$ref": "#/definitions/high_availability_mode" + "$ref": "#/definitions/cluster_high_availability_mode" }, "host_networks": { "description": "List of host networks to be filled during query.", @@ -14564,7 +14564,7 @@ func init() { "$ref": "#/definitions/disk-encryption" }, "high_availability_mode": { - "$ref": "#/definitions/high_availability_mode" + "$ref": "#/definitions/cluster_high_availability_mode" }, "http_proxy": { "description": "A proxy URL to use for creating HTTP connections outside the cluster.\nhttp://\\\u003cusername\\\u003e:\\\u003cpswd\\\u003e@\\\u003cip\\\u003e:\\\u003cport\\\u003e\n", @@ -14831,6 +14831,15 @@ func init() { } } }, + "cluster_high_availability_mode": { + "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", + "type": "string", + "default": "Full", + "enum": [ + "Full", + "None" + ] + }, "cluster_network": { "description": "IP address block for pod IP blocks.", "type": "object", @@ -15540,15 +15549,6 @@ func init() { } } }, - "high_availability_mode": { - "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", - "type": "string", - "default": "Full", - "enum": [ - "Full", - "None" - ] - }, "host": { "type": "object", "required": [ @@ -16484,7 +16484,7 @@ func init() { } }, "high_availability_mode": { - "$ref": "#/definitions/high_availability_mode" + "$ref": "#/definitions/cluster_high_availability_mode" }, "host_id": { "description": "Host id", diff --git a/swagger.yaml b/swagger.yaml index 12d8ea42f67..b6b38450241 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -4095,7 +4095,7 @@ definitions: maxLength: 54 description: Name of the OpenShift cluster. high_availability_mode: - $ref: '#/definitions/high_availability_mode' + $ref: '#/definitions/cluster_high_availability_mode' openshift_version: type: string description: Version of the OpenShift cluster. @@ -4416,7 +4416,7 @@ definitions: Indicates the type of this object. Will be 'Cluster' if this is a complete object, 'AddHostsCluster' for cluster that add hosts to existing OCP cluster, high_availability_mode: - $ref: '#/definitions/high_availability_mode' + $ref: '#/definitions/cluster_high_availability_mode' id: type: string format: uuid @@ -4728,7 +4728,7 @@ definitions: $ref: '#/definitions/ovirt-platform' x-nullable: true - high_availability_mode: + cluster_high_availability_mode: type: string enum: ['Full', 'None'] default: 'Full' @@ -5638,7 +5638,7 @@ definitions: type: string description: Assisted installer image high_availability_mode: - $ref: '#/definitions/high_availability_mode' + $ref: '#/definitions/cluster_high_availability_mode' proxy: $ref: "#/definitions/proxy" From 5f42e7bb4d0420b73bc74cb10508203aaf130741 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Tue, 22 Mar 2022 17:39:03 +0200 Subject: [PATCH 05/17] MGMT-9451: adding --- models/cluster_high_availability_mode.go | 76 ++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 models/cluster_high_availability_mode.go diff --git a/models/cluster_high_availability_mode.go b/models/cluster_high_availability_mode.go new file mode 100644 index 00000000000..2ee30a6eaad --- /dev/null +++ b/models/cluster_high_availability_mode.go @@ -0,0 +1,76 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" +) + +// ClusterHighAvailabilityMode Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster +// over multiple master nodes whereas 'None' installs a full cluster over one node. +// +// +// swagger:model cluster_high_availability_mode +type ClusterHighAvailabilityMode string + +func NewClusterHighAvailabilityMode(value ClusterHighAvailabilityMode) *ClusterHighAvailabilityMode { + v := value + return &v +} + +const ( + + // ClusterHighAvailabilityModeFull captures enum value "Full" + ClusterHighAvailabilityModeFull ClusterHighAvailabilityMode = "Full" + + // ClusterHighAvailabilityModeNone captures enum value "None" + ClusterHighAvailabilityModeNone ClusterHighAvailabilityMode = "None" +) + +// for schema +var clusterHighAvailabilityModeEnum []interface{} + +func init() { + var res []ClusterHighAvailabilityMode + if err := json.Unmarshal([]byte(`["Full","None"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + clusterHighAvailabilityModeEnum = append(clusterHighAvailabilityModeEnum, v) + } +} + +func (m ClusterHighAvailabilityMode) validateClusterHighAvailabilityModeEnum(path, location string, value ClusterHighAvailabilityMode) error { + if err := validate.EnumCase(path, location, value, clusterHighAvailabilityModeEnum, true); err != nil { + return err + } + return nil +} + +// Validate validates this cluster high availability mode +func (m ClusterHighAvailabilityMode) Validate(formats strfmt.Registry) error { + var res []error + + // value enum + if err := m.validateClusterHighAvailabilityModeEnum("", "body", m); err != nil { + return err + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// ContextValidate validates this cluster high availability mode based on context it is used +func (m ClusterHighAvailabilityMode) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} From 2412d91f27de9a2a198f296d141a2072f2c4b805 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Tue, 22 Mar 2022 20:56:04 +0200 Subject: [PATCH 06/17] MGMT-9451: adding --- internal/host/hostcommands/install_cmd.go | 131 +++++++----------- .../host/hostcommands/install_cmd_test.go | 113 +++++++-------- models/cluster.go | 68 ++++----- models/cluster_create_params.go | 68 ++++----- models/cluster_high_availability_mode.go | 76 ---------- models/install_cmd_request.go | 71 +++++----- restapi/embedded_spec.go | 70 ++++++---- swagger.yaml | 32 +++-- 8 files changed, 283 insertions(+), 346 deletions(-) delete mode 100644 models/cluster_high_availability_mode.go diff --git a/internal/host/hostcommands/install_cmd.go b/internal/host/hostcommands/install_cmd.go index d8ba85f0a4d..1d759ce812d 100644 --- a/internal/host/hostcommands/install_cmd.go +++ b/internal/host/hostcommands/install_cmd.go @@ -7,7 +7,6 @@ import ( "net" "strings" - "github.com/alessio/shellescape" "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" "github.com/openshift/assisted-service/internal/common" @@ -35,15 +34,6 @@ type installCmd struct { versionsHandler versions.Handler } -var podmanBaseCmd = [...]string{ - "podman", "run", "--privileged", "--pid=host", "--net=host", "--name=assisted-installer", - "--volume", "/dev:/dev:rw", - "--volume", "/opt:/opt:rw", - "--volume", "/var/log:/var/log:rw", - "--volume", "/run/systemd/journal/socket:/run/systemd/journal/socket", - "--volume", "/etc/pki:/etc/pki", - "--env=PULL_SECRET_TOKEN", -} func NewInstallCmd(log logrus.FieldLogger, db *gorm.DB, hwValidator hardware.Validator, ocRelease oc.Release, instructionConfig InstructionConfig, eventsHandler eventsapi.Handler, versionsHandler versions.Handler) *installCmd { @@ -91,7 +81,7 @@ func (i *installCmd) GetSteps(ctx context.Context, host *models.Host) ([]*models return nil, err } - step.Args = []string{"-c", fullCmd} + step.Args = []string{fullCmd} if _, err := hostutil.UpdateHost(i.log, i.db, host.InfraEnvID, *host.ID, *host.Status, "installer_version", i.instructionConfig.InstallerImage); err != nil { @@ -102,8 +92,6 @@ func (i *installCmd) GetSteps(ctx context.Context, host *models.Host) ([]*models } func (i *installCmd) getFullInstallerCommand(cluster *common.Cluster, host *models.Host, infraEnv *common.InfraEnv, bootdevice string, disksToFormat []string) (string, error) { - var request models.InstallCmdRequest - role := common.GetEffectiveRole(host) if host.Bootstrap { role = models.HostRoleBootstrap @@ -114,20 +102,20 @@ func (i *installCmd) getFullInstallerCommand(cluster *common.Cluster, host *mode haMode = *cluster.HighAvailabilityMode } + request := models.InstallCmdRequest{ + Role: &role, + BaseURL: swag.String(strings.TrimSpace(i.instructionConfig.ServiceBaseURL)), + ClusterID: host.ClusterID, + HostID: host.ID, + InfraEnvID: &host.InfraEnvID, + Insecure: swag.Bool(i.instructionConfig.SkipCertVerification), + Bootdevice:swag.String(bootdevice), + HighAvailabilityMode: &haMode, + ControllerImage: swag.String(i.instructionConfig.ControllerImage), + DiskToFormat: disksToFormat, + CheckCvo: swag.Bool(i.instructionConfig.CheckClusterVersion), - - podmanCmd := podmanBaseCmd[:] - installerCmdArgs := []string{ - "--role", string(role), - "--infra-env-id", host.InfraEnvID.String(), - "--cluster-id", host.ClusterID.String(), - "--host-id", string(*host.ID), - "--boot-device", bootdevice, - "--url", i.instructionConfig.ServiceBaseURL, - "--high-availability-mode", haMode, - "--controller-image", i.instructionConfig.ControllerImage, - "--agent-image", i.instructionConfig.AgentImage, } // those flags are not used on day2 installation @@ -137,47 +125,26 @@ func (i *installCmd) getFullInstallerCommand(cluster *common.Cluster, host *mode return "", err } - mcoImage, err := i.ocRelease.GetMCOImage(i.log, *releaseImage.URL, i.instructionConfig.ReleaseImageMirror, cluster.PullSecret) + request.McoImage, err = i.ocRelease.GetMCOImage(i.log, *releaseImage.URL, i.instructionConfig.ReleaseImageMirror, cluster.PullSecret) if err != nil { return "", err } - i.log.Infof("Install command releaseImage: %s, mcoImage: %s", *releaseImage.URL, mcoImage) + i.log.Infof("Install command releaseImage: %s, mcoImage: %s", *releaseImage.URL, request.McoImage) mustGatherMap, err := i.versionsHandler.GetMustGatherImages(cluster.OpenshiftVersion, cluster.CPUArchitecture, cluster.PullSecret) if err != nil { return "", err } - mustGatherImages, err := i.getMustGatherArgument(mustGatherMap) + request.MustGatherImage, err = i.getMustGatherArgument(mustGatherMap) if err != nil { return "", err } - installerCmdArgs = append(installerCmdArgs, "--must-gather-image", mustGatherImages) - installerCmdArgs = append(installerCmdArgs, "--openshift-version", cluster.OpenshiftVersion) - installerCmdArgs = append(installerCmdArgs, "--mco-image", mcoImage) - } - - for _, diskToFormat := range disksToFormat { - installerCmdArgs = append(installerCmdArgs, "--format-disk") - installerCmdArgs = append(installerCmdArgs, diskToFormat) - } - - /* - boolean flag must be used either without value (flag present means True) or in the format of =True|False. - format is not supported by golang flag package and will cause the flags processing to finish - before processing the rest of the input flags - */ - if i.instructionConfig.SkipCertVerification { - installerCmdArgs = append(installerCmdArgs, "--insecure") - } - - if i.instructionConfig.CheckClusterVersion { - installerCmdArgs = append(installerCmdArgs, "--check-cluster-version") + request.OpenshiftVersion = cluster.OpenshiftVersion } if i.hasCACert() { - podmanCmd = append(podmanCmd, "--volume", fmt.Sprintf("%s:%s:rw", common.HostCACertPath, common.HostCACertPath)) - installerCmdArgs = append(installerCmdArgs, "--cacert", common.HostCACertPath) + request.CaCertPath = common.HostCACertPath } hostInstallerArgs, err := constructHostInstallerArgs(cluster, host, infraEnv, i.log) @@ -186,57 +153,42 @@ func (i *installCmd) getFullInstallerCommand(cluster *common.Cluster, host *mode } if hostInstallerArgs != "" { - installerCmdArgs = append(installerCmdArgs, "--installer-args", hostInstallerArgs) + request.InstallerArgs = hostInstallerArgs } - noProxyArgs := i.getProxyArguments(cluster.Name, cluster.BaseDNSDomain, cluster.HTTPProxy, cluster.HTTPSProxy, cluster.NoProxy) - if len(noProxyArgs) > 0 { - installerCmdArgs = append(installerCmdArgs, noProxyArgs...) - } + request.Proxy = i.getProxyArguments(cluster.Name, cluster.BaseDNSDomain, cluster.HTTPProxy, cluster.HTTPSProxy, cluster.NoProxy) if i.instructionConfig.ServiceIPs != "" { - installerCmdArgs = append(installerCmdArgs, "--service-ips", i.instructionConfig.ServiceIPs) + request.ServiceIps = strings.Split(i.instructionConfig.ServiceIPs, ",") } - return fmt.Sprintf("%s %s %s", shellescape.QuoteCommand(podmanCmd), i.instructionConfig.InstallerImage, - shellescape.QuoteCommand(installerCmdArgs)), nil -} - -func (i *installCmd) getMustGatherArgument(mustGatherMap versions.MustGatherVersion) (string, error) { - //for backward compatability, if must gather images map contains only the ocp must gather - //we shall send a single image. otherwise, we shall send a json structure holding all the - //relevant images - if len(mustGatherMap) == 1 && mustGatherMap["ocp"] != "" { - return mustGatherMap["ocp"], nil - } - - arg, err := json.Marshal(mustGatherMap) + b, err := json.Marshal(&request) if err != nil { - i.log.WithError(err).Errorf("can not encode must-gather image map") + i.log.WithError(err).Warn("Json marshal") return "", err } - return string(arg), nil + + return string(b), nil } -func (i *installCmd) getProxyArguments(clusterName, baseDNSDomain, httpProxy, httpsProxy, noProxy string) []string { - cmd := make([]string, 0) +func (i *installCmd) getProxyArguments(clusterName, baseDNSDomain, httpProxy, httpsProxy, noProxy string) *models.Proxy { + var proxy models.Proxy if httpProxy == "" && httpsProxy == "" { - return cmd + return nil } if httpProxy != "" { - cmd = append(cmd, "--http-proxy", httpProxy) + proxy.HTTPProxy = swag.String(httpProxy) } if httpsProxy != "" { - cmd = append(cmd, "--https-proxy", httpsProxy) + proxy.HTTPSProxy = swag.String(httpsProxy) } noProxyTrim := strings.TrimSpace(noProxy) if noProxyTrim == "*" { - cmd = append(cmd, "--no-proxy", noProxyTrim) + proxy.NoProxy = swag.String(noProxyTrim) } else { - noProxyUpdated := []string{} if noProxyTrim != "" { noProxyUpdated = append(noProxyUpdated, noProxyTrim) @@ -249,12 +201,29 @@ func (i *installCmd) getProxyArguments(clusterName, baseDNSDomain, httpProxy, ht ".svc", ".cluster.local", fmt.Sprintf("api-int.%s.%s", clusterName, baseDNSDomain)) - cmd = append(cmd, "--no-proxy", strings.Join(noProxyUpdated, ",")) + proxy.NoProxy = swag.String(strings.Join(noProxyUpdated, ",")) } - return cmd + return &proxy } +func (i *installCmd) getMustGatherArgument(mustGatherMap versions.MustGatherVersion) (string, error) { + //for backward compatability, if must gather images map contains only the ocp must gather + //we shall send a single image. otherwise, we shall send a json structure holding all the + //relevant images + if len(mustGatherMap) == 1 && mustGatherMap["ocp"] != "" { + return mustGatherMap["ocp"], nil + } + + arg, err := json.Marshal(mustGatherMap) + if err != nil { + i.log.WithError(err).Errorf("can not encode must-gather image map") + return "", err + } + return string(arg), nil +} + + func (i *installCmd) hasCACert() bool { return i.instructionConfig.ServiceCACertPath != "" } diff --git a/internal/host/hostcommands/install_cmd_test.go b/internal/host/hostcommands/install_cmd_test.go index 09b68171768..85a7289b7de 100644 --- a/internal/host/hostcommands/install_cmd_test.go +++ b/internal/host/hostcommands/install_cmd_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + log "github.com/sirupsen/logrus" "regexp" "strings" @@ -289,7 +290,7 @@ var _ = Describe("installcmd arguments", func() { BeforeSuite(func() { db, dbName = common.PrepareTestDB() - cluster = createClusterInDb(db, models.ClusterHighAvailabilityModeNone) + cluster = createClusterInDb(db, string(models.ClusterHighAvailabilityModeNone)) infraEnv = createInfraEnvInDb(db, *cluster.ID) infraEnvId = *infraEnv.ID host = createHostInDb(db, infraEnvId, *cluster.ID, models.HostRoleMaster, false, "") @@ -379,7 +380,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - verifyArgInCommand(stepReply[0].Args[1], "--url", config.ServiceBaseURL, 1) + request := getRequest(stepReply[0]) + Expect(swag.StringValue(request.BaseURL)).To(Equal(config.ServiceBaseURL)) }) It("verify high-availability-mode is None", func() { @@ -387,7 +389,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - verifyArgInCommand(stepReply[0].Args[1], "--high-availability-mode", models.ClusterHighAvailabilityModeNone, 1) + request := getRequest(stepReply[0]) + Expect(*request.HighAvailabilityMode).To(Equal(models.ClusterHighAvailabilityModeNone)) }) It("verify empty value", func() { @@ -399,7 +402,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - verifyArgInCommand(stepReply[0].Args[1], "--mco-image", "''", 1) + request := getRequest(stepReply[0]) + Expect(request.McoImage).To(Equal("''")) }) It("verify escaped whitespace value", func() { @@ -412,16 +416,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - verifyArgInCommand(stepReply[0].Args[1], "--mco-image", fmt.Sprintf("'%s'", value), 1) - }) - - It("validate that pki was mounted", func() { - config := &InstructionConfig{} - installCmd := NewInstallCmd(common.GetTestLog(), db, validator, mockRelease, *config, mockEvents, mockVersions) - stepReply, err := installCmd.GetSteps(ctx, &host) - Expect(err).NotTo(HaveOccurred()) - Expect(stepReply).NotTo(BeNil()) - Expect(strings.Contains(stepReply[0].Args[1], "/etc/pki:/etc/pki")).Should(BeTrue()) + request := getRequest(stepReply[0]) + Expect(request.McoImage).To(Equal(fmt.Sprintf("'%s'", value))) }) It("no must-gather , mco and openshift version in day2 installation", func() { @@ -430,23 +426,21 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - Expect(strings.Contains(stepReply[0].Args[1], "--mco-image")).Should(BeFalse()) - Expect(strings.Contains(stepReply[0].Args[1], "--openshift-version")).Should(BeFalse()) - Expect(strings.Contains(stepReply[0].Args[1], "--must-gather-image")).Should(BeFalse()) + request := getRequest(stepReply[0]) + Expect(request.McoImage).To(BeEmpty()) + Expect(request.OpenshiftVersion).To(BeEmpty()) + Expect(request.MustGatherImage).To(BeEmpty()) }) Context("CA certificate", func() { - volumeMount := fmt.Sprintf("--volume %s:%s:rw", common.HostCACertPath, common.HostCACertPath) - cacertArgs := fmt.Sprintf("--cacert %s", common.HostCACertPath) - It("no CA certificate", func() { config := &InstructionConfig{} installCmd := NewInstallCmd(common.GetTestLog(), db, validator, mockRelease, *config, mockEvents, mockVersions) stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - Expect(strings.Join(stepReply[0].Args, " ")).NotTo(ContainSubstring(volumeMount)) - Expect(strings.Join(stepReply[0].Args, " ")).NotTo(ContainSubstring(cacertArgs)) + request := getRequest(stepReply[0]) + Expect(request.CaCertPath).To(BeEmpty()) }) It("with CA certificate", func() { @@ -455,8 +449,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - Expect(strings.Join(stepReply[0].Args, " ")).To(ContainSubstring(volumeMount)) - Expect(strings.Join(stepReply[0].Args, " ")).To(ContainSubstring(cacertArgs)) + request := getRequest(stepReply[0]) + Expect(request.CaCertPath).To(Equal(common.HostCACertPath)) }) }) }) @@ -477,14 +471,16 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - verifyArgInCommand(stepReply[0].Args[1], "--installer-args", fmt.Sprintf("'%s'", host.InstallerArgs), 1) + request := getRequest(stepReply[0]) + Expect(request.InstallerArgs).To(Equal(host.InstallerArgs)) }) It("empty installer args", func() { host.InstallerArgs = "" stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - Expect(strings.Contains(stepReply[0].Args[1], "--installer-args")).Should(BeFalse()) + request := getRequest(stepReply[0]) + Expect(request.InstallerArgs).To(BeEmpty()) }) It("empty installer args with static ip config", func() { @@ -493,7 +489,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - verifyArgInCommand(stepReply[0].Args[1], "--installer-args", fmt.Sprintf("'%s'", `["--copy-network"]`), 1) + request := getRequest(stepReply[0]) + Expect(request.InstallerArgs).To(Equal(`["--copy-network"]`)) }) It("non-empty installer args with static ip config", func() { @@ -502,7 +499,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - verifyArgInCommand(stepReply[0].Args[1], "--installer-args", fmt.Sprintf("'%s'", `["--append-karg","nameserver=8.8.8.8","-n","--copy-network"]`), 1) + request := getRequest(stepReply[0]) + Expect(request.InstallerArgs).To(Equal(`["--append-karg","nameserver=8.8.8.8","-n","--copy-network"]`)) }) It("non-empty installer args with copy network with static ip config", func() { @@ -511,7 +509,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - verifyArgInCommand(stepReply[0].Args[1], "--installer-args", fmt.Sprintf("'%s'", host.InstallerArgs), 1) + request := getRequest(stepReply[0]) + Expect(request.InstallerArgs).To(Equal(host.InstallerArgs)) }) }) @@ -559,12 +558,12 @@ var _ = Describe("installcmd arguments", func() { }) It("no-proxy without httpProxy", func() { args := installCmd.getProxyArguments("t-cluster", "proxy.org", "", "", "domain.com,192.168.1.0/24") - Expect(args).Should(Equal([]string{})) + Expect(args).Should(BeNil()) }) It("default no-proxy", func() { noProxy := installCmd.getProxyArguments("t-cluster", "proxy.org", "http://10.56.20.90:8080", "", "") - Expect(noProxy).Should(Equal([]string{ + Expect(noProxy.NoProxy).Should(Equal([]string{ "--http-proxy", "http://10.56.20.90:8080", "--no-proxy", @@ -573,7 +572,7 @@ var _ = Describe("installcmd arguments", func() { }) It("updated no-proxy", func() { noProxy := installCmd.getProxyArguments("t-cluster", "proxy.org", "http://10.56.20.90:8080", "", "domain.org,127.0.0.2") - Expect(noProxy).Should(Equal([]string{ + Expect(noProxy.NoProxy).Should(Equal([]string{ "--http-proxy", "http://10.56.20.90:8080", "--no-proxy", @@ -582,7 +581,7 @@ var _ = Describe("installcmd arguments", func() { }) It("all-excluded no-proxy", func() { noProxy := installCmd.getProxyArguments("t-cluster", "proxy.org", "http://10.56.20.90:8080", "", "*") - Expect(noProxy).Should(Equal([]string{ + Expect(noProxy.NoProxy).Should(Equal([]string{ "--http-proxy", "http://10.56.20.90:8080", "--no-proxy", @@ -592,7 +591,7 @@ var _ = Describe("installcmd arguments", func() { }) It("all-excluded no-proxy with spaces", func() { noProxy := installCmd.getProxyArguments("t-cluster", "proxy.org", "http://10.56.20.90:8080", "", " * ") - Expect(noProxy).Should(Equal([]string{ + Expect(noProxy.NoProxy).Should(Equal([]string{ "--http-proxy", "http://10.56.20.90:8080", "--no-proxy", @@ -1013,12 +1012,12 @@ func getBootableDiskNames(disks []*models.Disk) []string { }).([]string) } -func verifyArgInCommand(command, key, value string, count int) { - r := regexp.MustCompile(fmt.Sprintf(`%s ([^ ]+)`, key)) - match := r.FindAllStringSubmatch(command, -1) - Expect(match).NotTo(BeNil()) - Expect(match).To(HaveLen(count)) - Expect(strings.TrimSpace(match[0][1])).To(Equal(quoteString(value))) + +func getRequest(reply *models.Step) *models.InstallCmdRequest { + request := models.InstallCmdRequest{} + err := json.Unmarshal([]byte(reply.Args[0]), &request) + Expect(err).NotTo(HaveOccurred()) + return &request } func verifyDiskFormatCommand(command string, value string, exists bool) { @@ -1047,7 +1046,7 @@ func quoteString(value string) string { return value } -func createClusterInDb(db *gorm.DB, haMode string) common.Cluster { +func createClusterInDb(db *gorm.DB, haMode models.ClusterHighAvailabilityMode) common.Cluster { clusterId := strfmt.UUID(uuid.New().String()) cluster := common.Cluster{Cluster: models.Cluster{ ID: &clusterId, @@ -1102,19 +1101,25 @@ func postvalidation(isstepreplynil bool, issteperrnil bool, expectedstepreply *m } func validateInstallCommand(installCmd *installCmd, reply *models.Step, role models.HostRole, infraEnvId, clusterId, hostId strfmt.UUID, - bootDevice string, bootableDisks []string, haMode string) { + bootDevice string, bootableDisks []string, haMode models.ClusterHighAvailabilityMode) { ExpectWithOffset(1, reply.StepType).To(Equal(models.StepTypeInstall)) mustGatherImage, _ := installCmd.getMustGatherArgument(defaultMustGatherVersion) - verifyArgInCommand(reply.Args[1], "--infra-env-id", string(infraEnvId), 1) - verifyArgInCommand(reply.Args[1], "--cluster-id", string(clusterId), 1) - verifyArgInCommand(reply.Args[1], "--host-id", string(hostId), 1) - verifyArgInCommand(reply.Args[1], "--high-availability-mode", haMode, 1) - verifyArgInCommand(reply.Args[1], "--openshift-version", common.TestDefaultConfig.OpenShiftVersion, 1) - verifyArgInCommand(reply.Args[1], "--role", string(role), 1) - verifyArgInCommand(reply.Args[1], "--boot-device", bootDevice, 1) - verifyArgInCommand(reply.Args[1], "--url", installCmd.instructionConfig.ServiceBaseURL, 1) - verifyArgInCommand(reply.Args[1], "--mco-image", defaultMCOImage, 1) - verifyArgInCommand(reply.Args[1], "--controller-image", installCmd.instructionConfig.ControllerImage, 1) - verifyArgInCommand(reply.Args[1], "--agent-image", installCmd.instructionConfig.AgentImage, 1) - verifyArgInCommand(reply.Args[1], "--must-gather-image", mustGatherImage, 1) + request := models.InstallCmdRequest{} + err := json.Unmarshal([]byte(reply.Args[0]), &request) + Expect(err).NotTo(HaveOccurred()) + Expect(request.InfraEnvID).To(Equal(infraEnvId)) + Expect(request.ClusterID).To(Equal(clusterId)) + Expect(request.HostID).To(Equal(hostId)) + Expect(request.HighAvailabilityMode).To(Equal(haMode)) + Expect(request.OpenshiftVersion).To(Equal(common.TestDefaultConfig.OpenShiftVersion)) + Expect(request.Role).To(Equal(role)) + Expect(request.InfraEnvID).To(Equal(infraEnvId)) + Expect(request.ClusterID).To(Equal(clusterId)) + Expect(request.HostID).To(Equal(hostId)) + Expect(request.Bootdevice).To(Equal(bootDevice)) + Expect(request.BaseURL).To(Equal(installCmd.instructionConfig.ServiceBaseURL)) + Expect(request.McoImage).To(Equal(defaultMCOImage)) + Expect(request.ControllerImage).To(Equal(installCmd.instructionConfig.ControllerImage)) + Expect(request.ClusterID).To(Equal(clusterId)) + Expect(request.MustGatherImage).To(Equal(mustGatherImage)) } diff --git a/models/cluster.go b/models/cluster.go index 260533afee9..038990eceeb 100644 --- a/models/cluster.go +++ b/models/cluster.go @@ -85,8 +85,11 @@ type Cluster struct { // JSON-formatted string containing the usage information by feature name FeatureUsage string `json:"feature_usage,omitempty" gorm:"type:text"` - // high availability mode - HighAvailabilityMode *ClusterHighAvailabilityMode `json:"high_availability_mode,omitempty"` + // Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster + // over multiple master nodes whereas 'None' installs a full cluster over one node. + // + // Enum: [Full None] + HighAvailabilityMode *string `json:"high_availability_mode,omitempty"` // List of host networks to be filled during query. HostNetworks []*HostNetwork `json:"host_networks" gorm:"-"` @@ -528,20 +531,43 @@ func (m *Cluster) validateDiskEncryption(formats strfmt.Registry) error { return nil } +var clusterTypeHighAvailabilityModePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["Full","None"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + clusterTypeHighAvailabilityModePropEnum = append(clusterTypeHighAvailabilityModePropEnum, v) + } +} + +const ( + + // ClusterHighAvailabilityModeFull captures enum value "Full" + ClusterHighAvailabilityModeFull string = "Full" + + // ClusterHighAvailabilityModeNone captures enum value "None" + ClusterHighAvailabilityModeNone string = "None" +) + +// prop value enum +func (m *Cluster) validateHighAvailabilityModeEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, clusterTypeHighAvailabilityModePropEnum, true); err != nil { + return err + } + return nil +} + func (m *Cluster) validateHighAvailabilityMode(formats strfmt.Registry) error { if swag.IsZero(m.HighAvailabilityMode) { // not required return nil } - if m.HighAvailabilityMode != nil { - if err := m.HighAvailabilityMode.Validate(formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("high_availability_mode") - } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("high_availability_mode") - } - return err - } + // value enum + if err := m.validateHighAvailabilityModeEnum("high_availability_mode", "body", *m.HighAvailabilityMode); err != nil { + return err } return nil @@ -1113,10 +1139,6 @@ func (m *Cluster) ContextValidate(ctx context.Context, formats strfmt.Registry) res = append(res, err) } - if err := m.contextValidateHighAvailabilityMode(ctx, formats); err != nil { - res = append(res, err) - } - if err := m.contextValidateHostNetworks(ctx, formats); err != nil { res = append(res, err) } @@ -1199,22 +1221,6 @@ func (m *Cluster) contextValidateDiskEncryption(ctx context.Context, formats str return nil } -func (m *Cluster) contextValidateHighAvailabilityMode(ctx context.Context, formats strfmt.Registry) error { - - if m.HighAvailabilityMode != nil { - if err := m.HighAvailabilityMode.ContextValidate(ctx, formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("high_availability_mode") - } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("high_availability_mode") - } - return err - } - } - - return nil -} - func (m *Cluster) contextValidateHostNetworks(ctx context.Context, formats strfmt.Registry) error { for i := 0; i < len(m.HostNetworks); i++ { diff --git a/models/cluster_create_params.go b/models/cluster_create_params.go index 8522fb5f376..7c3b8947961 100644 --- a/models/cluster_create_params.go +++ b/models/cluster_create_params.go @@ -45,8 +45,11 @@ type ClusterCreateParams struct { // Installation disks encryption mode and host roles to be applied. DiskEncryption *DiskEncryption `json:"disk_encryption,omitempty" gorm:"embedded;embeddedPrefix:disk_encryption_"` - // high availability mode - HighAvailabilityMode *ClusterHighAvailabilityMode `json:"high_availability_mode,omitempty"` + // Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster + // over multiple master nodes whereas 'None' installs a full cluster over one node. + // + // Enum: [Full None] + HighAvailabilityMode *string `json:"high_availability_mode,omitempty"` // A proxy URL to use for creating HTTP connections outside the cluster. // http://\:\@\:\ @@ -273,20 +276,43 @@ func (m *ClusterCreateParams) validateDiskEncryption(formats strfmt.Registry) er return nil } +var clusterCreateParamsTypeHighAvailabilityModePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["Full","None"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + clusterCreateParamsTypeHighAvailabilityModePropEnum = append(clusterCreateParamsTypeHighAvailabilityModePropEnum, v) + } +} + +const ( + + // ClusterCreateParamsHighAvailabilityModeFull captures enum value "Full" + ClusterCreateParamsHighAvailabilityModeFull string = "Full" + + // ClusterCreateParamsHighAvailabilityModeNone captures enum value "None" + ClusterCreateParamsHighAvailabilityModeNone string = "None" +) + +// prop value enum +func (m *ClusterCreateParams) validateHighAvailabilityModeEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, clusterCreateParamsTypeHighAvailabilityModePropEnum, true); err != nil { + return err + } + return nil +} + func (m *ClusterCreateParams) validateHighAvailabilityMode(formats strfmt.Registry) error { if swag.IsZero(m.HighAvailabilityMode) { // not required return nil } - if m.HighAvailabilityMode != nil { - if err := m.HighAvailabilityMode.Validate(formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("high_availability_mode") - } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("high_availability_mode") - } - return err - } + // value enum + if err := m.validateHighAvailabilityModeEnum("high_availability_mode", "body", *m.HighAvailabilityMode); err != nil { + return err } return nil @@ -569,10 +595,6 @@ func (m *ClusterCreateParams) ContextValidate(ctx context.Context, formats strfm res = append(res, err) } - if err := m.contextValidateHighAvailabilityMode(ctx, formats); err != nil { - res = append(res, err) - } - if err := m.contextValidateIgnitionEndpoint(ctx, formats); err != nil { res = append(res, err) } @@ -635,22 +657,6 @@ func (m *ClusterCreateParams) contextValidateDiskEncryption(ctx context.Context, return nil } -func (m *ClusterCreateParams) contextValidateHighAvailabilityMode(ctx context.Context, formats strfmt.Registry) error { - - if m.HighAvailabilityMode != nil { - if err := m.HighAvailabilityMode.ContextValidate(ctx, formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("high_availability_mode") - } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("high_availability_mode") - } - return err - } - } - - return nil -} - func (m *ClusterCreateParams) contextValidateIgnitionEndpoint(ctx context.Context, formats strfmt.Registry) error { if m.IgnitionEndpoint != nil { diff --git a/models/cluster_high_availability_mode.go b/models/cluster_high_availability_mode.go deleted file mode 100644 index 2ee30a6eaad..00000000000 --- a/models/cluster_high_availability_mode.go +++ /dev/null @@ -1,76 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "encoding/json" - - "github.com/go-openapi/errors" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/validate" -) - -// ClusterHighAvailabilityMode Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster -// over multiple master nodes whereas 'None' installs a full cluster over one node. -// -// -// swagger:model cluster_high_availability_mode -type ClusterHighAvailabilityMode string - -func NewClusterHighAvailabilityMode(value ClusterHighAvailabilityMode) *ClusterHighAvailabilityMode { - v := value - return &v -} - -const ( - - // ClusterHighAvailabilityModeFull captures enum value "Full" - ClusterHighAvailabilityModeFull ClusterHighAvailabilityMode = "Full" - - // ClusterHighAvailabilityModeNone captures enum value "None" - ClusterHighAvailabilityModeNone ClusterHighAvailabilityMode = "None" -) - -// for schema -var clusterHighAvailabilityModeEnum []interface{} - -func init() { - var res []ClusterHighAvailabilityMode - if err := json.Unmarshal([]byte(`["Full","None"]`), &res); err != nil { - panic(err) - } - for _, v := range res { - clusterHighAvailabilityModeEnum = append(clusterHighAvailabilityModeEnum, v) - } -} - -func (m ClusterHighAvailabilityMode) validateClusterHighAvailabilityModeEnum(path, location string, value ClusterHighAvailabilityMode) error { - if err := validate.EnumCase(path, location, value, clusterHighAvailabilityModeEnum, true); err != nil { - return err - } - return nil -} - -// Validate validates this cluster high availability mode -func (m ClusterHighAvailabilityMode) Validate(formats strfmt.Registry) error { - var res []error - - // value enum - if err := m.validateClusterHighAvailabilityModeEnum("", "body", m); err != nil { - return err - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -// ContextValidate validates this cluster high availability mode based on context it is used -func (m ClusterHighAvailabilityMode) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - return nil -} diff --git a/models/install_cmd_request.go b/models/install_cmd_request.go index 4adae490d6f..4bd13b9c6f2 100644 --- a/models/install_cmd_request.go +++ b/models/install_cmd_request.go @@ -7,6 +7,7 @@ package models import ( "context" + "encoding/json" "strconv" "github.com/go-openapi/errors" @@ -44,11 +45,14 @@ type InstallCmdRequest struct { ControllerImage *string `json:"controller_image"` // List of disks to format - DiskToFormat []string `json:"disk_to_format"` + DisksToFormat []string `json:"disks_to_format"` - // high availability mode + // Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster + // over multiple master nodes whereas 'None' installs a full cluster over one node. + // // Required: true - HighAvailabilityMode *ClusterHighAvailabilityMode `json:"high_availability_mode"` + // Enum: [Full None] + HighAvailabilityMode *string `json:"high_availability_mode"` // Host id // Required: true @@ -189,25 +193,44 @@ func (m *InstallCmdRequest) validateControllerImage(formats strfmt.Registry) err return nil } -func (m *InstallCmdRequest) validateHighAvailabilityMode(formats strfmt.Registry) error { +var installCmdRequestTypeHighAvailabilityModePropEnum []interface{} - if err := validate.Required("high_availability_mode", "body", m.HighAvailabilityMode); err != nil { +func init() { + var res []string + if err := json.Unmarshal([]byte(`["Full","None"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + installCmdRequestTypeHighAvailabilityModePropEnum = append(installCmdRequestTypeHighAvailabilityModePropEnum, v) + } +} + +const ( + + // InstallCmdRequestHighAvailabilityModeFull captures enum value "Full" + InstallCmdRequestHighAvailabilityModeFull string = "Full" + + // InstallCmdRequestHighAvailabilityModeNone captures enum value "None" + InstallCmdRequestHighAvailabilityModeNone string = "None" +) + +// prop value enum +func (m *InstallCmdRequest) validateHighAvailabilityModeEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, installCmdRequestTypeHighAvailabilityModePropEnum, true); err != nil { return err } + return nil +} + +func (m *InstallCmdRequest) validateHighAvailabilityMode(formats strfmt.Registry) error { if err := validate.Required("high_availability_mode", "body", m.HighAvailabilityMode); err != nil { return err } - if m.HighAvailabilityMode != nil { - if err := m.HighAvailabilityMode.Validate(formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("high_availability_mode") - } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("high_availability_mode") - } - return err - } + // value enum + if err := m.validateHighAvailabilityModeEnum("high_availability_mode", "body", *m.HighAvailabilityMode); err != nil { + return err } return nil @@ -320,10 +343,6 @@ func (m *InstallCmdRequest) validateServiceIps(formats strfmt.Registry) error { func (m *InstallCmdRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { var res []error - if err := m.contextValidateHighAvailabilityMode(ctx, formats); err != nil { - res = append(res, err) - } - if err := m.contextValidateProxy(ctx, formats); err != nil { res = append(res, err) } @@ -338,22 +357,6 @@ func (m *InstallCmdRequest) ContextValidate(ctx context.Context, formats strfmt. return nil } -func (m *InstallCmdRequest) contextValidateHighAvailabilityMode(ctx context.Context, formats strfmt.Registry) error { - - if m.HighAvailabilityMode != nil { - if err := m.HighAvailabilityMode.ContextValidate(ctx, formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("high_availability_mode") - } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("high_availability_mode") - } - return err - } - } - - return nil -} - func (m *InstallCmdRequest) contextValidateProxy(ctx context.Context, formats strfmt.Registry) error { if m.Proxy != nil { diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index 43cc17f3e4f..2edc9886043 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -5224,7 +5224,13 @@ func init() { "x-go-custom-tag": "gorm:\"type:text\"" }, "high_availability_mode": { - "$ref": "#/definitions/cluster_high_availability_mode" + "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", + "type": "string", + "default": "Full", + "enum": [ + "Full", + "None" + ] }, "host_networks": { "description": "List of host networks to be filled during query.", @@ -5537,7 +5543,13 @@ func init() { "$ref": "#/definitions/disk-encryption" }, "high_availability_mode": { - "$ref": "#/definitions/cluster_high_availability_mode" + "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", + "type": "string", + "default": "Full", + "enum": [ + "Full", + "None" + ] }, "http_proxy": { "description": "A proxy URL to use for creating HTTP connections outside the cluster.\nhttp://\\\u003cusername\\\u003e:\\\u003cpswd\\\u003e@\\\u003cip\\\u003e:\\\u003cport\\\u003e\n", @@ -5804,15 +5816,6 @@ func init() { } } }, - "cluster_high_availability_mode": { - "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", - "type": "string", - "default": "Full", - "enum": [ - "Full", - "None" - ] - }, "cluster_network": { "description": "IP address block for pod IP blocks.", "type": "object", @@ -7515,7 +7518,7 @@ func init() { "description": "Assisted installer controller image", "type": "string" }, - "disk_to_format": { + "disks_to_format": { "description": "List of disks to format", "type": "array", "items": { @@ -7524,7 +7527,13 @@ func init() { } }, "high_availability_mode": { - "$ref": "#/definitions/cluster_high_availability_mode" + "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", + "type": "string", + "default": "Full", + "enum": [ + "Full", + "None" + ] }, "host_id": { "description": "Host id", @@ -14251,7 +14260,13 @@ func init() { "x-go-custom-tag": "gorm:\"type:text\"" }, "high_availability_mode": { - "$ref": "#/definitions/cluster_high_availability_mode" + "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", + "type": "string", + "default": "Full", + "enum": [ + "Full", + "None" + ] }, "host_networks": { "description": "List of host networks to be filled during query.", @@ -14564,7 +14579,13 @@ func init() { "$ref": "#/definitions/disk-encryption" }, "high_availability_mode": { - "$ref": "#/definitions/cluster_high_availability_mode" + "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", + "type": "string", + "default": "Full", + "enum": [ + "Full", + "None" + ] }, "http_proxy": { "description": "A proxy URL to use for creating HTTP connections outside the cluster.\nhttp://\\\u003cusername\\\u003e:\\\u003cpswd\\\u003e@\\\u003cip\\\u003e:\\\u003cport\\\u003e\n", @@ -14831,15 +14852,6 @@ func init() { } } }, - "cluster_high_availability_mode": { - "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", - "type": "string", - "default": "Full", - "enum": [ - "Full", - "None" - ] - }, "cluster_network": { "description": "IP address block for pod IP blocks.", "type": "object", @@ -16475,7 +16487,7 @@ func init() { "description": "Assisted installer controller image", "type": "string" }, - "disk_to_format": { + "disks_to_format": { "description": "List of disks to format", "type": "array", "items": { @@ -16484,7 +16496,13 @@ func init() { } }, "high_availability_mode": { - "$ref": "#/definitions/cluster_high_availability_mode" + "description": "Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster\nover multiple master nodes whereas 'None' installs a full cluster over one node.\n", + "type": "string", + "default": "Full", + "enum": [ + "Full", + "None" + ] }, "host_id": { "description": "Host id", diff --git a/swagger.yaml b/swagger.yaml index b6b38450241..ed68f470d3d 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -4095,7 +4095,12 @@ definitions: maxLength: 54 description: Name of the OpenShift cluster. high_availability_mode: - $ref: '#/definitions/cluster_high_availability_mode' + type: string + enum: ['Full', 'None'] + default: 'Full' + description: | + Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster + over multiple master nodes whereas 'None' installs a full cluster over one node. openshift_version: type: string description: Version of the OpenShift cluster. @@ -4416,7 +4421,12 @@ definitions: Indicates the type of this object. Will be 'Cluster' if this is a complete object, 'AddHostsCluster' for cluster that add hosts to existing OCP cluster, high_availability_mode: - $ref: '#/definitions/cluster_high_availability_mode' + type: string + enum: ['Full', 'None'] + default: 'Full' + description: | + Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster + over multiple master nodes whereas 'None' installs a full cluster over one node. id: type: string format: uuid @@ -4728,14 +4738,6 @@ definitions: $ref: '#/definitions/ovirt-platform' x-nullable: true - cluster_high_availability_mode: - type: string - enum: ['Full', 'None'] - default: 'Full' - description: | - Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster - over multiple master nodes whereas 'None' installs a full cluster over one node. - image_info: type: object x-go-custom-tag: gorm:"embedded;embeddedPrefix:image_" @@ -5638,15 +5640,19 @@ definitions: type: string description: Assisted installer image high_availability_mode: - $ref: '#/definitions/cluster_high_availability_mode' - + type: string + enum: ['Full', 'None'] + default: 'Full' + description: | + Guaranteed availability of the installed cluster. 'Full' installs a Highly-Available cluster + over multiple master nodes whereas 'None' installs a full cluster over one node. proxy: $ref: "#/definitions/proxy" check_cvo: type: boolean description: Check CVO status if needed default: true - disk_to_format: + disks_to_format: type: array description: List of disks to format items: From 93764a860ae27fc7ccb7215344bad4e64183946c Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Tue, 22 Mar 2022 21:45:16 +0200 Subject: [PATCH 07/17] MGMT-9451: adding --- go.mod | 1 - go.sum | 2 - internal/host/hostcommands/install_cmd.go | 2 +- .../host/hostcommands/install_cmd_test.go | 57 +++++++------------ 4 files changed, 23 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index 85a2b8abc00..8010adfa91b 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.17 require ( github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d - github.com/alessio/shellescape v1.4.1 github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/aws/aws-sdk-go v1.34.28 github.com/buger/jsonparser v1.1.1 diff --git a/go.sum b/go.sum index d6e8126ce63..d844a5d318b 100644 --- a/go.sum +++ b/go.sum @@ -122,8 +122,6 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= -github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= diff --git a/internal/host/hostcommands/install_cmd.go b/internal/host/hostcommands/install_cmd.go index 1d759ce812d..22ba7488205 100644 --- a/internal/host/hostcommands/install_cmd.go +++ b/internal/host/hostcommands/install_cmd.go @@ -112,7 +112,7 @@ func (i *installCmd) getFullInstallerCommand(cluster *common.Cluster, host *mode Bootdevice:swag.String(bootdevice), HighAvailabilityMode: &haMode, ControllerImage: swag.String(i.instructionConfig.ControllerImage), - DiskToFormat: disksToFormat, + DisksToFormat: disksToFormat, CheckCvo: swag.Bool(i.instructionConfig.CheckClusterVersion), diff --git a/internal/host/hostcommands/install_cmd_test.go b/internal/host/hostcommands/install_cmd_test.go index 85a7289b7de..8774007d900 100644 --- a/internal/host/hostcommands/install_cmd_test.go +++ b/internal/host/hostcommands/install_cmd_test.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - log "github.com/sirupsen/logrus" "regexp" "strings" @@ -316,7 +315,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - Expect(strings.Contains(stepReply[0].Args[1], "--insecure")).Should(BeFalse()) + request := getRequest(stepReply[0]) + Expect(swag.BoolValue(request.Insecure)).Should(BeFalse()) }) It("insecure_cert_is_set_to_false", func() { @@ -327,7 +327,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - Expect(strings.Contains(stepReply[0].Args[1], "--insecure")).Should(BeFalse()) + request := getRequest(stepReply[0]) + Expect(swag.BoolValue(request.Insecure)).Should(BeFalse()) }) It("insecure_cert_is_set_to_true", func() { @@ -338,7 +339,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - Expect(strings.Contains(stepReply[0].Args[1], "--insecure")).Should(BeTrue()) + request := getRequest(stepReply[0]) + Expect(swag.BoolValue(request.Insecure)).Should(BeTrue()) }) It("check_cluster_version_is_false_by_default", func() { @@ -347,7 +349,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - Expect(strings.Contains(stepReply[0].Args[1], "--check-cluster-version")).Should(BeFalse()) + request := getRequest(stepReply[0]) + Expect(swag.BoolValue(request.CheckCvo)).To(BeFalse()) }) It("check_cluster_version_is_set_to_false", func() { @@ -358,7 +361,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - Expect(strings.Contains(stepReply[0].Args[1], "--check-cluster-version")).Should(BeFalse()) + request := getRequest(stepReply[0]) + Expect(swag.BoolValue(request.CheckCvo)).To(BeFalse()) }) It("check_cluster_version_is_set_to_true", func() { @@ -369,7 +373,8 @@ var _ = Describe("installcmd arguments", func() { stepReply, err := installCmd.GetSteps(ctx, &host) Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) - Expect(strings.Contains(stepReply[0].Args[1], "--check-cluster-version")).Should(BeTrue()) + request := getRequest(stepReply[0]) + Expect(swag.BoolValue(request.CheckCvo)).To(BeTrue()) }) It("target_url_is_passed", func() { @@ -403,21 +408,7 @@ var _ = Describe("installcmd arguments", func() { Expect(err).NotTo(HaveOccurred()) Expect(stepReply).NotTo(BeNil()) request := getRequest(stepReply[0]) - Expect(request.McoImage).To(Equal("''")) - }) - - It("verify escaped whitespace value", func() { - value := "\nescaped_\n\t_value\n" - mockRelease = oc.NewMockRelease(ctrl) - mockRelease.EXPECT().GetMCOImage(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(value, nil).AnyTimes() - mockVersions.EXPECT().GetMustGatherImages(gomock.Any(), gomock.Any(), gomock.Any()).Return(defaultMustGatherVersion, nil).AnyTimes() - - installCmd := NewInstallCmd(common.GetTestLog(), db, validator, mockRelease, InstructionConfig{}, mockEvents, mockVersions) - stepReply, err := installCmd.GetSteps(ctx, &host) - Expect(err).NotTo(HaveOccurred()) - Expect(stepReply).NotTo(BeNil()) - request := getRequest(stepReply[0]) - Expect(request.McoImage).To(Equal(fmt.Sprintf("'%s'", value))) + Expect(request.McoImage).To(Equal("")) }) It("no must-gather , mco and openshift version in day2 installation", func() { @@ -563,30 +554,26 @@ var _ = Describe("installcmd arguments", func() { It("default no-proxy", func() { noProxy := installCmd.getProxyArguments("t-cluster", "proxy.org", "http://10.56.20.90:8080", "", "") - Expect(noProxy.NoProxy).Should(Equal([]string{ - "--http-proxy", - "http://10.56.20.90:8080", - "--no-proxy", - "127.0.0.1,localhost,.svc,.cluster.local,api-int.t-cluster.proxy.org", - })) + Expect(noProxy.HTTPProxy).Should(Equal("http://10.56.20.90:8080")) + Expect(noProxy.NoProxy).Should(Equal( + "127.0.0.1,localhost,.svc,.cluster.local,api-int.t-cluster.proxy.org")) }) It("updated no-proxy", func() { noProxy := installCmd.getProxyArguments("t-cluster", "proxy.org", "http://10.56.20.90:8080", "", "domain.org,127.0.0.2") - Expect(noProxy.NoProxy).Should(Equal([]string{ + Expect(noProxy.NoProxy).Should(Equal(strings.Join([]string{ "--http-proxy", "http://10.56.20.90:8080", "--no-proxy", "domain.org,127.0.0.2,127.0.0.1,localhost,.svc,.cluster.local,api-int.t-cluster.proxy.org", - })) + }, ","))) }) It("all-excluded no-proxy", func() { noProxy := installCmd.getProxyArguments("t-cluster", "proxy.org", "http://10.56.20.90:8080", "", "*") - Expect(noProxy.NoProxy).Should(Equal([]string{ + Expect(noProxy.NoProxy).Should(Equal(strings.Join([]string{ "--http-proxy", "http://10.56.20.90:8080", "--no-proxy", - "*", - })) + "*"}, ","))) }) It("all-excluded no-proxy with spaces", func() { @@ -1046,7 +1033,7 @@ func quoteString(value string) string { return value } -func createClusterInDb(db *gorm.DB, haMode models.ClusterHighAvailabilityMode) common.Cluster { +func createClusterInDb(db *gorm.DB, haMode string) common.Cluster { clusterId := strfmt.UUID(uuid.New().String()) cluster := common.Cluster{Cluster: models.Cluster{ ID: &clusterId, @@ -1101,7 +1088,7 @@ func postvalidation(isstepreplynil bool, issteperrnil bool, expectedstepreply *m } func validateInstallCommand(installCmd *installCmd, reply *models.Step, role models.HostRole, infraEnvId, clusterId, hostId strfmt.UUID, - bootDevice string, bootableDisks []string, haMode models.ClusterHighAvailabilityMode) { + bootDevice string, bootableDisks []string, haMode string) { ExpectWithOffset(1, reply.StepType).To(Equal(models.StepTypeInstall)) mustGatherImage, _ := installCmd.getMustGatherArgument(defaultMustGatherVersion) request := models.InstallCmdRequest{} From 0dad885c65c5dfe936ef3bb8b6c9f19d996b0829 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Wed, 23 Mar 2022 17:29:54 +0200 Subject: [PATCH 08/17] MGMT-9451: adding install --- internal/host/hostcommands/install_cmd.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/host/hostcommands/install_cmd.go b/internal/host/hostcommands/install_cmd.go index 22ba7488205..b71df2d25d4 100644 --- a/internal/host/hostcommands/install_cmd.go +++ b/internal/host/hostcommands/install_cmd.go @@ -114,8 +114,7 @@ func (i *installCmd) getFullInstallerCommand(cluster *common.Cluster, host *mode ControllerImage: swag.String(i.instructionConfig.ControllerImage), DisksToFormat: disksToFormat, CheckCvo: swag.Bool(i.instructionConfig.CheckClusterVersion), - - + InstallerImage: swag.String(i.instructionConfig.InstallerImage), } // those flags are not used on day2 installation From 53ded39c53a15692404118680f75e6fb8f3044d6 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Wed, 23 Mar 2022 17:30:18 +0200 Subject: [PATCH 09/17] MGMT-9451: adding next_step_runner --- swagger.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/swagger.yaml b/swagger.yaml index ed68f470d3d..5dc4e32726d 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -5535,6 +5535,7 @@ definitions: - infra_env_id - host_id - insecure + - base_url properties: infra_env_id: type: string @@ -5547,6 +5548,12 @@ definitions: insecure: type: boolean description: Skip ceritifacate verification + base_url: + type: string + description: Service base url to connect + ca_cert_path: + type: string + description: Path to certificate on the nodes logs_gather_cmd_request: type: object From dc37743307521d634c5ed03fe00645fff3ec2773 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Wed, 23 Mar 2022 17:34:04 +0200 Subject: [PATCH 10/17] MGMT-9451: adding next_step_runner --- models/next_step_cmd_request.go | 20 ++++++++++++++++++++ restapi/embedded_spec.go | 22 ++++++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/models/next_step_cmd_request.go b/models/next_step_cmd_request.go index 270e6fc4e1c..b0c9486d426 100644 --- a/models/next_step_cmd_request.go +++ b/models/next_step_cmd_request.go @@ -19,6 +19,13 @@ import ( // swagger:model next_step_cmd_request type NextStepCmdRequest struct { + // Service base url to connect + // Required: true + BaseURL *string `json:"base_url"` + + // Path to certificate on the nodes + CaCertPath string `json:"ca_cert_path,omitempty"` + // Host id // Required: true // Format: uuid @@ -38,6 +45,10 @@ type NextStepCmdRequest struct { func (m *NextStepCmdRequest) Validate(formats strfmt.Registry) error { var res []error + if err := m.validateBaseURL(formats); err != nil { + res = append(res, err) + } + if err := m.validateHostID(formats); err != nil { res = append(res, err) } @@ -56,6 +67,15 @@ func (m *NextStepCmdRequest) Validate(formats strfmt.Registry) error { return nil } +func (m *NextStepCmdRequest) validateBaseURL(formats strfmt.Registry) error { + + if err := validate.Required("base_url", "body", m.BaseURL); err != nil { + return err + } + + return nil +} + func (m *NextStepCmdRequest) validateHostID(formats strfmt.Registry) error { if err := validate.Required("host_id", "body", m.HostID); err != nil { diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index 2edc9886043..ab4c4ae7765 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -8031,9 +8031,18 @@ func init() { "required": [ "infra_env_id", "host_id", - "insecure" + "insecure", + "base_url" ], "properties": { + "base_url": { + "description": "Service base url to connect", + "type": "string" + }, + "ca_cert_path": { + "description": "Path to certificate on the nodes", + "type": "string" + }, "host_id": { "description": "Host id", "type": "string", @@ -16989,9 +16998,18 @@ func init() { "required": [ "infra_env_id", "host_id", - "insecure" + "insecure", + "base_url" ], "properties": { + "base_url": { + "description": "Service base url to connect", + "type": "string" + }, + "ca_cert_path": { + "description": "Path to certificate on the nodes", + "type": "string" + }, "host_id": { "description": "Host id", "type": "string", From 3faaf783a6580c27dd3711d7e7b03f4527fb2b10 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Wed, 23 Mar 2022 23:30:05 +0200 Subject: [PATCH 11/17] MGMT-9451: add new commands , install --- internal/host/hostcommands/install_cmd.go | 24 +++++++++---------- .../host/hostcommands/install_cmd_test.go | 10 +------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/internal/host/hostcommands/install_cmd.go b/internal/host/hostcommands/install_cmd.go index b71df2d25d4..f2a63aed952 100644 --- a/internal/host/hostcommands/install_cmd.go +++ b/internal/host/hostcommands/install_cmd.go @@ -34,7 +34,6 @@ type installCmd struct { versionsHandler versions.Handler } - func NewInstallCmd(log logrus.FieldLogger, db *gorm.DB, hwValidator hardware.Validator, ocRelease oc.Release, instructionConfig InstructionConfig, eventsHandler eventsapi.Handler, versionsHandler versions.Handler) *installCmd { return &installCmd{ @@ -103,18 +102,18 @@ func (i *installCmd) getFullInstallerCommand(cluster *common.Cluster, host *mode } request := models.InstallCmdRequest{ - Role: &role, - BaseURL: swag.String(strings.TrimSpace(i.instructionConfig.ServiceBaseURL)), - ClusterID: host.ClusterID, - HostID: host.ID, - InfraEnvID: &host.InfraEnvID, - Insecure: swag.Bool(i.instructionConfig.SkipCertVerification), - Bootdevice:swag.String(bootdevice), + Role: &role, + BaseURL: swag.String(strings.TrimSpace(i.instructionConfig.ServiceBaseURL)), + ClusterID: host.ClusterID, + HostID: host.ID, + InfraEnvID: &host.InfraEnvID, + Insecure: swag.Bool(i.instructionConfig.SkipCertVerification), + Bootdevice: swag.String(bootdevice), HighAvailabilityMode: &haMode, - ControllerImage: swag.String(i.instructionConfig.ControllerImage), - DisksToFormat: disksToFormat, - CheckCvo: swag.Bool(i.instructionConfig.CheckClusterVersion), - InstallerImage: swag.String(i.instructionConfig.InstallerImage), + ControllerImage: swag.String(i.instructionConfig.ControllerImage), + DisksToFormat: disksToFormat, + CheckCvo: swag.Bool(i.instructionConfig.CheckClusterVersion), + InstallerImage: swag.String(i.instructionConfig.InstallerImage), } // those flags are not used on day2 installation @@ -222,7 +221,6 @@ func (i *installCmd) getMustGatherArgument(mustGatherMap versions.MustGatherVers return string(arg), nil } - func (i *installCmd) hasCACert() bool { return i.instructionConfig.ServiceCACertPath != "" } diff --git a/internal/host/hostcommands/install_cmd_test.go b/internal/host/hostcommands/install_cmd_test.go index 8774007d900..a3e96a171fa 100644 --- a/internal/host/hostcommands/install_cmd_test.go +++ b/internal/host/hostcommands/install_cmd_test.go @@ -289,7 +289,7 @@ var _ = Describe("installcmd arguments", func() { BeforeSuite(func() { db, dbName = common.PrepareTestDB() - cluster = createClusterInDb(db, string(models.ClusterHighAvailabilityModeNone)) + cluster = createClusterInDb(db, models.ClusterHighAvailabilityModeNone) infraEnv = createInfraEnvInDb(db, *cluster.ID) infraEnvId = *infraEnv.ID host = createHostInDb(db, infraEnvId, *cluster.ID, models.HostRoleMaster, false, "") @@ -999,7 +999,6 @@ func getBootableDiskNames(disks []*models.Disk) []string { }).([]string) } - func getRequest(reply *models.Step) *models.InstallCmdRequest { request := models.InstallCmdRequest{} err := json.Unmarshal([]byte(reply.Args[0]), &request) @@ -1026,13 +1025,6 @@ func verifyDiskFormatCommand(command string, value string, exists bool) { Expect(matchValue()).To(Equal(exists)) } -func quoteString(value string) string { - if strings.ContainsRune(value, '"') && !(strings.Index(value, "'") == 0) { - return fmt.Sprintf("'%s'", value) - } - return value -} - func createClusterInDb(db *gorm.DB, haMode string) common.Cluster { clusterId := strfmt.UUID(uuid.New().String()) cluster := common.Cluster{Cluster: models.Cluster{ From 389dca69f1d26d3c944f13386bf2af9dc6fab832 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Wed, 23 Mar 2022 23:35:03 +0200 Subject: [PATCH 12/17] MGMT-9451: add new commands , next_step_runner --- internal/bminventory/inventory.go | 18 ++-- internal/bminventory/inventory_test.go | 16 ++-- .../host/hostcommands/next_step_runner_cmd.go | 47 +++++----- .../hostcommands/next_step_runner_cmd_test.go | 89 +++++++++---------- models/next_step_cmd_request.go | 3 + restapi/embedded_spec.go | 8 ++ swagger.yaml | 3 + 7 files changed, 99 insertions(+), 85 deletions(-) diff --git a/internal/bminventory/inventory.go b/internal/bminventory/inventory.go index f30e5e74179..7f4e0338d0b 100644 --- a/internal/bminventory/inventory.go +++ b/internal/bminventory/inventory.go @@ -2877,7 +2877,7 @@ func (b *bareMetalInventory) getImageInfo(clusterId *strfmt.UUID) (*models.Image return &models.ImageInfo{}, nil } -func (b *bareMetalInventory) generateV2NextStepRunnerCommand(ctx context.Context, params *installer.V2RegisterHostParams) *models.HostRegistrationResponseAO1NextStepRunnerCommand { +func (b *bareMetalInventory) generateV2NextStepRunnerCommand(ctx context.Context, params *installer.V2RegisterHostParams) (*models.HostRegistrationResponseAO1NextStepRunnerCommand, error) { if params.NewHostParams.DiscoveryAgentVersion != b.AgentDockerImg { log := logutil.FromContext(ctx, b.log) @@ -2887,17 +2887,17 @@ func (b *bareMetalInventory) generateV2NextStepRunnerCommand(ctx context.Context config := hostcommands.NextStepRunnerConfig{ ServiceBaseURL: b.ServiceBaseURL, - InfraEnvID: params.InfraEnvID.String(), - HostID: params.NewHostParams.HostID.String(), + InfraEnvID: params.InfraEnvID, + HostID: *params.NewHostParams.HostID, UseCustomCACert: b.ServiceCACertPath != "", NextStepRunnerImage: b.AgentDockerImg, SkipCertVerification: b.SkipCertVerification, } - command, args := hostcommands.GetNextStepRunnerCommand(&config) + command, args, err := hostcommands.GetNextStepRunnerCommand(&config) return &models.HostRegistrationResponseAO1NextStepRunnerCommand{ Command: command, Args: *args, - } + }, err } func returnRegisterHostTransitionError( @@ -4655,9 +4655,15 @@ func (b *bareMetalInventory) V2RegisterHost(ctx context.Context, params installe eventgen.SendHostRegistrationSucceededEvent(ctx, b.eventsHandler, *params.NewHostParams.HostID, params.InfraEnvID, host.ClusterID, hostutil.GetHostnameForMsg(host)) + nextStepRunnerCommand, err := b.generateV2NextStepRunnerCommand(ctx, ¶ms) + if err != nil { + log.WithError(err).Errorf("Fail to create nextStepRunnerCommand") + return common.GenerateErrorResponder(err) + } + hostRegistration := models.HostRegistrationResponse{ Host: *host, - NextStepRunnerCommand: b.generateV2NextStepRunnerCommand(ctx, ¶ms), + NextStepRunnerCommand: nextStepRunnerCommand, } if err := tx.Commit().Error; err != nil { diff --git a/internal/bminventory/inventory_test.go b/internal/bminventory/inventory_test.go index 26772d13335..8ddd13c50f1 100644 --- a/internal/bminventory/inventory_test.go +++ b/internal/bminventory/inventory_test.go @@ -455,7 +455,7 @@ var _ = Describe("RegisterHost", func() { Expect(payload).ShouldNot(BeNil()) command := payload.NextStepRunnerCommand Expect(command).ShouldNot(BeNil()) - Expect(command.Command).ShouldNot(BeEmpty()) + Expect(command.Command).Should(BeEmpty()) Expect(command.Args).ShouldNot(BeEmpty()) }) } @@ -638,7 +638,7 @@ var _ = Describe("v2RegisterHost", func() { Expect(payload).ShouldNot(BeNil()) command := payload.NextStepRunnerCommand Expect(command).ShouldNot(BeNil()) - Expect(command.Command).ShouldNot(BeEmpty()) + Expect(command.Command).Should(BeEmpty()) Expect(command.Args).ShouldNot(BeEmpty()) }) } @@ -10900,7 +10900,8 @@ var _ = Describe("update image version", func() { agentImage := fmt.Sprintf("%s:%s", "quay.io/ocpmetal/agent", uuid.New().String()) bm.AgentDockerImg = agentImage params.NewHostParams.DiscoveryAgentVersion = agentImage - bm.generateV2NextStepRunnerCommand(ctx, params) + _, err := bm.generateV2NextStepRunnerCommand(ctx, params) + Expect(err).NotTo(HaveOccurred()) Expect(logHook.AllEntries()).To(BeEmpty()) }) @@ -10908,7 +10909,8 @@ var _ = Describe("update image version", func() { imageName := "quay.io/edge-infrastructure/assisted-installer-agent" bm.AgentDockerImg = fmt.Sprintf("%s:%s", imageName, uuid.New().String()) params.NewHostParams.DiscoveryAgentVersion = fmt.Sprintf("%s:%s", imageName, uuid.New().String()) - bm.generateV2NextStepRunnerCommand(ctx, params) + _, err := bm.generateV2NextStepRunnerCommand(ctx, params) + Expect(err).NotTo(HaveOccurred()) Expect(logHook.LastEntry().Message).To(ContainSubstring("uses an outdated agent image")) }) @@ -10916,7 +10918,8 @@ var _ = Describe("update image version", func() { imageTag := uuid.New().String() bm.AgentDockerImg = fmt.Sprintf("%s:%s", "quay.io/edge-infrastructure/assisted-installer-agent", imageTag) params.NewHostParams.DiscoveryAgentVersion = fmt.Sprintf("%s:%s", "quay.io/ocpmetal/agent", imageTag) - bm.generateV2NextStepRunnerCommand(ctx, params) + _, err := bm.generateV2NextStepRunnerCommand(ctx, params) + Expect(err).NotTo(HaveOccurred()) Expect(logHook.LastEntry().Message).To(ContainSubstring("uses an outdated agent image")) }) @@ -10925,7 +10928,8 @@ var _ = Describe("update image version", func() { imageName := "edge-infrastructure/assisted-installer-agent" bm.AgentDockerImg = fmt.Sprintf("%s/%s:%s", "quay.io", imageName, imageTag) params.NewHostParams.DiscoveryAgentVersion = fmt.Sprintf("%s/%s:%s", "docker.io", imageName, imageTag) - bm.generateV2NextStepRunnerCommand(ctx, params) + _, err := bm.generateV2NextStepRunnerCommand(ctx, params) + Expect(err).NotTo(HaveOccurred()) Expect(logHook.LastEntry().Message).To(ContainSubstring("uses an outdated agent image")) }) }) diff --git a/internal/host/hostcommands/next_step_runner_cmd.go b/internal/host/hostcommands/next_step_runner_cmd.go index 8df2b1624e3..cbede312c23 100644 --- a/internal/host/hostcommands/next_step_runner_cmd.go +++ b/internal/host/hostcommands/next_step_runner_cmd.go @@ -1,48 +1,43 @@ package hostcommands import ( - "fmt" - "strconv" + "encoding/json" "strings" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" "github.com/openshift/assisted-service/internal/common" + "github.com/openshift/assisted-service/models" + log "github.com/sirupsen/logrus" ) type NextStepRunnerConfig struct { ServiceBaseURL string - InfraEnvID string - HostID string + InfraEnvID strfmt.UUID + HostID strfmt.UUID UseCustomCACert bool NextStepRunnerImage string SkipCertVerification bool } -func GetNextStepRunnerCommand(config *NextStepRunnerConfig) (string, *[]string) { - - arguments := []string{"run", "--rm", "-ti", "--privileged", "--pid=host", "--net=host", - "-v", "/dev:/dev:rw", "-v", "/opt:/opt:rw", - "-v", "/run/systemd/journal/socket:/run/systemd/journal/socket", - "-v", "/var/log:/var/log:rw", - "-v", "/run/media:/run/media:rw", - "-v", "/etc/pki:/etc/pki"} +func GetNextStepRunnerCommand(config *NextStepRunnerConfig) (string, *[]string, error) { + request := models.NextStepCmdRequest{ + InfraEnvID: &config.InfraEnvID, + HostID: &config.HostID, + Insecure: swag.Bool(config.SkipCertVerification), + BaseURL: swag.String(strings.TrimSpace(config.ServiceBaseURL)), + } if config.UseCustomCACert { - arguments = append(arguments, "-v", fmt.Sprintf("%s:%s", common.HostCACertPath, common.HostCACertPath)) + request.CaCertPath = common.HostCACertPath } - arguments = append(arguments, - "--env", "PULL_SECRET_TOKEN", - "--env", "CONTAINERS_CONF", - "--env", "CONTAINERS_STORAGE_CONF", - "--env", "HTTP_PROXY", "--env", "HTTPS_PROXY", "--env", "NO_PROXY", - "--env", "http_proxy", "--env", "https_proxy", "--env", "no_proxy", - "--name", "next-step-runner", config.NextStepRunnerImage, "next_step_runner", - "--url", strings.TrimSpace(config.ServiceBaseURL), "--infra-env-id", config.InfraEnvID, "--host-id", config.HostID, - "--agent-version", config.NextStepRunnerImage, fmt.Sprintf("--insecure=%s", strconv.FormatBool(config.SkipCertVerification))) - - if config.UseCustomCACert { - arguments = append(arguments, "--cacert", common.HostCACertPath) + b, err := json.Marshal(&request) + if err != nil { + log.WithError(err).Warn("Json marshal") + return "", nil, err } + arguments := []string{string(b)} - return "podman", &arguments + return "", &arguments, nil } diff --git a/internal/host/hostcommands/next_step_runner_cmd_test.go b/internal/host/hostcommands/next_step_runner_cmd_test.go index 70877403537..7cdef7714e6 100644 --- a/internal/host/hostcommands/next_step_runner_cmd_test.go +++ b/internal/host/hostcommands/next_step_runner_cmd_test.go @@ -1,23 +1,33 @@ package hostcommands import ( + "encoding/json" "fmt" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" "github.com/google/uuid" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/openshift/assisted-service/internal/common" + "github.com/openshift/assisted-service/models" ) +func getNextStepRequest(args []string) *models.NextStepCmdRequest { + request := models.NextStepCmdRequest{} + err := json.Unmarshal([]byte(args[0]), &request) + Expect(err).NotTo(HaveOccurred()) + return &request +} + var _ = Describe("Format command for starting next step agent", func() { var config NextStepRunnerConfig - infraEnvId := uuid.New().String() - hostID := uuid.New().String() + infraEnvId := strfmt.UUID(uuid.New().String()) + hostID := strfmt.UUID(uuid.New().String()) serviceURL := uuid.New().String() image := uuid.New().String() - certVolume := fmt.Sprintf("%s:%s", common.HostCACertPath, common.HostCACertPath) BeforeEach(func() { config = NextStepRunnerConfig{ @@ -29,70 +39,55 @@ var _ = Describe("Format command for starting next step agent", func() { It("standard formatting", func() { config.ServiceBaseURL = serviceURL - command, args := GetNextStepRunnerCommand(&config) - Expect(command).Should(Equal("podman")) - assertValue("--infra-env-id", infraEnvId, *args) - assertValue("--host-id", hostID, *args) - assertValue("--url", serviceURL, *args) - assertValue("--agent-version", image, *args) - Expect(*args).ShouldNot(ContainElement("--cacert")) - Expect(*args).ShouldNot(ContainElement(certVolume)) - Expect(*args).Should(ContainElement("/etc/pki:/etc/pki")) - Expect(*args).Should(ContainElement("--insecure=false")) - Expect(*args).ShouldNot(ContainElement("--insecure=true")) + command, args, err := GetNextStepRunnerCommand(&config) + Expect(err).ToNot(HaveOccurred()) + Expect(command).Should(Equal("")) + request := getNextStepRequest(*args) + Expect(swag.BoolValue(request.Insecure)).Should(BeFalse()) + Expect(request.HostID.String()).Should(Equal(hostID.String())) + Expect(request.InfraEnvID.String()).Should(Equal(infraEnvId.String())) + Expect(request.BaseURL).Should(Equal(serviceURL)) + Expect(request.CaCertPath).Should(BeFalse()) }) It("trim service URL", func() { config.ServiceBaseURL = fmt.Sprintf(" %s ", serviceURL) Expect(config.ServiceBaseURL).ShouldNot(Equal(serviceURL)) - _, args := GetNextStepRunnerCommand(&config) - assertValue("--url", serviceURL, *args) + _, args, err := GetNextStepRunnerCommand(&config) + Expect(err).ToNot(HaveOccurred()) + request := getNextStepRequest(*args) + Expect(request.BaseURL).Should(Equal(serviceURL)) }) It("without custom CA certificate", func() { config.UseCustomCACert = false - _, args := GetNextStepRunnerCommand(&config) - - Expect(*args).ShouldNot(ContainElement("--cacert")) - Expect(*args).ShouldNot(ContainElement(certVolume)) + _, args, err := GetNextStepRunnerCommand(&config) + Expect(err).ToNot(HaveOccurred()) + request := getNextStepRequest(*args) + Expect(request.CaCertPath).Should(BeEmpty()) }) It("with custom CA certificate", func() { config.UseCustomCACert = true - _, args := GetNextStepRunnerCommand(&config) - assertValue("--cacert", common.HostCACertPath, *args) - Expect(*args).Should(ContainElement(certVolume)) + _, args, err := GetNextStepRunnerCommand(&config) + Expect(err).ToNot(HaveOccurred()) + request := getNextStepRequest(*args) + Expect(request.CaCertPath).Should(Equal(common.HostCACertPath)) }) It("certificate verification on", func() { config.SkipCertVerification = false - _, args := GetNextStepRunnerCommand(&config) - Expect(*args).Should(ContainElement("--insecure=false")) - Expect(*args).ShouldNot(ContainElement("--insecure=true")) + _, args, err := GetNextStepRunnerCommand(&config) + Expect(err).ToNot(HaveOccurred()) + request := getNextStepRequest(*args) + Expect(swag.BoolValue(request.Insecure)).Should(BeFalse()) }) It("certificate verification off", func() { config.SkipCertVerification = true - _, args := GetNextStepRunnerCommand(&config) - Expect(*args).Should(ContainElement("--insecure=true")) - Expect(*args).ShouldNot(ContainElement("--insecure=false")) + _, args, err := GetNextStepRunnerCommand(&config) + Expect(err).ToNot(HaveOccurred()) + request := getNextStepRequest(*args) + Expect(swag.BoolValue(request.Insecure)).Should(BeTrue()) }) }) - -func assertValue(key string, value string, args []string) { - i := search(key, args) - Expect(i).Should(BeNumerically(">", -1)) - Expect(i).Should(BeNumerically("<", len(args)-1)) - Expect(args[i+1]).Should(Equal(value)) -} - -func search(term string, s []string) int { - - for i, v := range s { - if v == term { - return i - } - } - - return -1 -} diff --git a/models/next_step_cmd_request.go b/models/next_step_cmd_request.go index b0c9486d426..d24c18591c1 100644 --- a/models/next_step_cmd_request.go +++ b/models/next_step_cmd_request.go @@ -19,6 +19,9 @@ import ( // swagger:model next_step_cmd_request type NextStepCmdRequest struct { + // Agent image version + AgentVersion string `json:"agent_version,omitempty"` + // Service base url to connect // Required: true BaseURL *string `json:"base_url"` diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index ab4c4ae7765..688576cfa18 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -8035,6 +8035,10 @@ func init() { "base_url" ], "properties": { + "agent_version": { + "description": "Agent image version", + "type": "string" + }, "base_url": { "description": "Service base url to connect", "type": "string" @@ -17002,6 +17006,10 @@ func init() { "base_url" ], "properties": { + "agent_version": { + "description": "Agent image version", + "type": "string" + }, "base_url": { "description": "Service base url to connect", "type": "string" diff --git a/swagger.yaml b/swagger.yaml index 5dc4e32726d..4b663c8a4bd 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -5554,6 +5554,9 @@ definitions: ca_cert_path: type: string description: Path to certificate on the nodes + agent_version: + type: string + description: Agent image version logs_gather_cmd_request: type: object From ac476f144d3bebf1b1685d7ef9f6c52d473424f1 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Wed, 23 Mar 2022 23:51:15 +0200 Subject: [PATCH 13/17] MGMT-9451: add new commands , next_step_runner --- swagger.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/swagger.yaml b/swagger.yaml index 4b663c8a4bd..aa103f17eae 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -5536,6 +5536,7 @@ definitions: - host_id - insecure - base_url + - agent_version properties: infra_env_id: type: string From 7331d05235144a566865ff0653d62dca7a49bc33 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Wed, 23 Mar 2022 23:58:16 +0200 Subject: [PATCH 14/17] MGMT-9451: add new commands , next_step_runner --- models/next_step_cmd_request.go | 16 +++++++++++++++- restapi/embedded_spec.go | 6 ++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/models/next_step_cmd_request.go b/models/next_step_cmd_request.go index d24c18591c1..edf1fe88cc8 100644 --- a/models/next_step_cmd_request.go +++ b/models/next_step_cmd_request.go @@ -20,7 +20,8 @@ import ( type NextStepCmdRequest struct { // Agent image version - AgentVersion string `json:"agent_version,omitempty"` + // Required: true + AgentVersion *string `json:"agent_version"` // Service base url to connect // Required: true @@ -48,6 +49,10 @@ type NextStepCmdRequest struct { func (m *NextStepCmdRequest) Validate(formats strfmt.Registry) error { var res []error + if err := m.validateAgentVersion(formats); err != nil { + res = append(res, err) + } + if err := m.validateBaseURL(formats); err != nil { res = append(res, err) } @@ -70,6 +75,15 @@ func (m *NextStepCmdRequest) Validate(formats strfmt.Registry) error { return nil } +func (m *NextStepCmdRequest) validateAgentVersion(formats strfmt.Registry) error { + + if err := validate.Required("agent_version", "body", m.AgentVersion); err != nil { + return err + } + + return nil +} + func (m *NextStepCmdRequest) validateBaseURL(formats strfmt.Registry) error { if err := validate.Required("base_url", "body", m.BaseURL); err != nil { diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index 688576cfa18..70560c40a65 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -8032,7 +8032,8 @@ func init() { "infra_env_id", "host_id", "insecure", - "base_url" + "base_url", + "agent_version" ], "properties": { "agent_version": { @@ -17003,7 +17004,8 @@ func init() { "infra_env_id", "host_id", "insecure", - "base_url" + "base_url", + "agent_version" ], "properties": { "agent_version": { From 5795d00f9f95995ccc829d9bfaaadd4eccb06365 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Thu, 24 Mar 2022 00:56:38 +0200 Subject: [PATCH 15/17] MGMT-9451: add new commands , install --- .../host/hostcommands/install_cmd_test.go | 93 +++++++------------ 1 file changed, 32 insertions(+), 61 deletions(-) diff --git a/internal/host/hostcommands/install_cmd_test.go b/internal/host/hostcommands/install_cmd_test.go index a3e96a171fa..0892688b45e 100644 --- a/internal/host/hostcommands/install_cmd_test.go +++ b/internal/host/hostcommands/install_cmd_test.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "regexp" "strings" "github.com/go-openapi/strfmt" @@ -196,8 +195,8 @@ var _ = Describe("installcmd", func() { mockFormatEvent(disks[0], 0) prepareGetStep(sdb) stepReply, stepErr = installCmd.GetSteps(ctx, &host) - verifyDiskFormatCommand(stepReply[0].Args[1], disks[0].ID, false) - }) + verifyDiskFormatCommand(stepReply[0], disks[0].ID, false) + }) It("format_one_bootable", func() { disks := []*models.Disk{ @@ -213,9 +212,9 @@ var _ = Describe("installcmd", func() { validateInstallCommand(installCmd, stepReply[0], models.HostRoleMaster, infraEnvId, clusterId, *host.ID, sdb.ID, getBootableDiskNames(disks), models.ClusterHighAvailabilityModeFull) hostFromDb := hostutil.GetHostFromDB(*host.ID, infraEnvId, db) Expect(hostFromDb.InstallerVersion).Should(Equal(DefaultInstructionConfig.InstallerImage)) - verifyDiskFormatCommand(stepReply[0].Args[1], sda.ID, true) - verifyDiskFormatCommand(stepReply[0].Args[1], sdb.ID, false) - verifyDiskFormatCommand(stepReply[0].Args[1], sdh.ID, false) + verifyDiskFormatCommand(stepReply[0], sda.ID, true) + verifyDiskFormatCommand(stepReply[0], sdb.ID, false) + verifyDiskFormatCommand(stepReply[0], sdh.ID, false) }) It("format_multiple_bootable_skip", func() { @@ -248,11 +247,11 @@ var _ = Describe("installcmd", func() { validateInstallCommand(installCmd, stepReply[0], models.HostRoleMaster, infraEnvId, clusterId, *host.ID, sdb.ID, []string{sda.ID, sdc.ID}, models.ClusterHighAvailabilityModeFull) hostFromDb := hostutil.GetHostFromDB(*host.ID, infraEnvId, db) Expect(hostFromDb.InstallerVersion).Should(Equal(DefaultInstructionConfig.InstallerImage)) - verifyDiskFormatCommand(stepReply[0].Args[1], sda.ID, true) - verifyDiskFormatCommand(stepReply[0].Args[1], sdc.ID, true) - verifyDiskFormatCommand(stepReply[0].Args[1], sdi.ID, false) - verifyDiskFormatCommand(stepReply[0].Args[1], sdg.ID, false) - verifyDiskFormatCommand(stepReply[0].Args[1], sdj.ID, false) + verifyDiskFormatCommand(stepReply[0], sda.ID, true) + verifyDiskFormatCommand(stepReply[0], sdc.ID, true) + verifyDiskFormatCommand(stepReply[0], sdi.ID, false) + verifyDiskFormatCommand(stepReply[0], sdg.ID, false) + verifyDiskFormatCommand(stepReply[0], sdj.ID, false) }) }) @@ -554,36 +553,25 @@ var _ = Describe("installcmd arguments", func() { It("default no-proxy", func() { noProxy := installCmd.getProxyArguments("t-cluster", "proxy.org", "http://10.56.20.90:8080", "", "") - Expect(noProxy.HTTPProxy).Should(Equal("http://10.56.20.90:8080")) - Expect(noProxy.NoProxy).Should(Equal( + Expect(swag.StringValue(noProxy.HTTPProxy)).Should(Equal("http://10.56.20.90:8080")) + Expect(swag.StringValue(noProxy.NoProxy)).Should(Equal( "127.0.0.1,localhost,.svc,.cluster.local,api-int.t-cluster.proxy.org")) }) It("updated no-proxy", func() { noProxy := installCmd.getProxyArguments("t-cluster", "proxy.org", "http://10.56.20.90:8080", "", "domain.org,127.0.0.2") - Expect(noProxy.NoProxy).Should(Equal(strings.Join([]string{ - "--http-proxy", - "http://10.56.20.90:8080", - "--no-proxy", - "domain.org,127.0.0.2,127.0.0.1,localhost,.svc,.cluster.local,api-int.t-cluster.proxy.org", - }, ","))) + Expect(swag.StringValue(noProxy.HTTPProxy)).Should(Equal("http://10.56.20.90:8080")) + Expect(swag.StringValue(noProxy.NoProxy)).Should(Equal( + "domain.org,127.0.0.2,127.0.0.1,localhost,.svc,.cluster.local,api-int.t-cluster.proxy.org")) }) It("all-excluded no-proxy", func() { noProxy := installCmd.getProxyArguments("t-cluster", "proxy.org", "http://10.56.20.90:8080", "", "*") - Expect(noProxy.NoProxy).Should(Equal(strings.Join([]string{ - "--http-proxy", - "http://10.56.20.90:8080", - "--no-proxy", - "*"}, ","))) - + Expect(swag.StringValue(noProxy.HTTPProxy)).Should(Equal("http://10.56.20.90:8080")) + Expect(swag.StringValue(noProxy.NoProxy)).Should(Equal("*")) }) It("all-excluded no-proxy with spaces", func() { noProxy := installCmd.getProxyArguments("t-cluster", "proxy.org", "http://10.56.20.90:8080", "", " * ") - Expect(noProxy.NoProxy).Should(Equal([]string{ - "--http-proxy", - "http://10.56.20.90:8080", - "--no-proxy", - "*", - })) + Expect(swag.StringValue(noProxy.HTTPProxy)).Should(Equal("http://10.56.20.90:8080")) + Expect(swag.StringValue(noProxy.NoProxy)).Should(Equal("*")) }) }) }) @@ -1006,23 +994,10 @@ func getRequest(reply *models.Step) *models.InstallCmdRequest { return &request } -func verifyDiskFormatCommand(command string, value string, exists bool) { - r := regexp.MustCompile(`--format-disk ([^\s]+)`) - matches := r.FindAllStringSubmatch(command, -1) - matchValue := func() bool { - if matches == nil { - //empty format command - return false - } - for _, match := range matches { - if match[1] == value { - //found value in command - return true - } - } - return false - } - Expect(matchValue()).To(Equal(exists)) +func verifyDiskFormatCommand(reply *models.Step, value string, exists bool) { + request := getRequest(reply) + contains := funk.ContainsString(request.DisksToFormat, value) + Expect(contains).To(Equal(exists)) } func createClusterInDb(db *gorm.DB, haMode string) common.Cluster { @@ -1075,7 +1050,7 @@ func postvalidation(isstepreplynil bool, issteperrnil bool, expectedstepreply *m ExpectWithOffset(1, expectedstepreply).Should(BeNil()) } else { ExpectWithOffset(1, expectedstepreply.StepType).To(Equal(models.StepTypeInstall)) - ExpectWithOffset(1, strings.Contains(expectedstepreply.Args[1], string(expectedrole))).To(Equal(true)) + ExpectWithOffset(1, strings.Contains(expectedstepreply.Args[0], string(expectedrole))).To(Equal(true)) } } @@ -1086,19 +1061,15 @@ func validateInstallCommand(installCmd *installCmd, reply *models.Step, role mod request := models.InstallCmdRequest{} err := json.Unmarshal([]byte(reply.Args[0]), &request) Expect(err).NotTo(HaveOccurred()) - Expect(request.InfraEnvID).To(Equal(infraEnvId)) - Expect(request.ClusterID).To(Equal(clusterId)) - Expect(request.HostID).To(Equal(hostId)) - Expect(request.HighAvailabilityMode).To(Equal(haMode)) + Expect(request.InfraEnvID.String()).To(Equal(infraEnvId.String())) + Expect(request.ClusterID.String()).To(Equal(clusterId.String())) + Expect(request.HostID.String()).To(Equal(hostId.String())) + Expect(swag.StringValue(request.HighAvailabilityMode)).To(Equal(haMode)) Expect(request.OpenshiftVersion).To(Equal(common.TestDefaultConfig.OpenShiftVersion)) - Expect(request.Role).To(Equal(role)) - Expect(request.InfraEnvID).To(Equal(infraEnvId)) - Expect(request.ClusterID).To(Equal(clusterId)) - Expect(request.HostID).To(Equal(hostId)) - Expect(request.Bootdevice).To(Equal(bootDevice)) - Expect(request.BaseURL).To(Equal(installCmd.instructionConfig.ServiceBaseURL)) + Expect(*request.Role).To(Equal(role)) + Expect(swag.StringValue(request.Bootdevice)).To(Equal(bootDevice)) + Expect(swag.StringValue(request.BaseURL)).To(Equal(installCmd.instructionConfig.ServiceBaseURL)) Expect(request.McoImage).To(Equal(defaultMCOImage)) - Expect(request.ControllerImage).To(Equal(installCmd.instructionConfig.ControllerImage)) - Expect(request.ClusterID).To(Equal(clusterId)) + Expect(swag.StringValue(request.ControllerImage)).To(Equal(installCmd.instructionConfig.ControllerImage)) Expect(request.MustGatherImage).To(Equal(mustGatherImage)) } From d485336bdcde0bcb91da998669c02e60c6c15f17 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Thu, 24 Mar 2022 00:57:25 +0200 Subject: [PATCH 16/17] MGMT-9451: add new commands , fixing tests --- .../host/hostcommands/instruction_manager_test.go | 14 +++++++------- .../hostcommands/stop_installation_cmd_test.go | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/internal/host/hostcommands/instruction_manager_test.go b/internal/host/hostcommands/instruction_manager_test.go index ae64e9d7dc3..04fa71586d8 100644 --- a/internal/host/hostcommands/instruction_manager_test.go +++ b/internal/host/hostcommands/instruction_manager_test.go @@ -131,19 +131,19 @@ var _ = Describe("instruction_manager", func() { }) It("error", func() { checkStep(models.HostStatusError, []models.StepType{ - models.StepTypeExecute, models.StepTypeExecute, + models.StepTypeLogsGather, models.StepTypeStopInstallation, }) }) It("error with already uploades logs", func() { host.LogsCollectedAt = strfmt.DateTime(time.Now()) db.Save(&host) checkStep(models.HostStatusError, []models.StepType{ - models.StepTypeExecute, + models.StepTypeStopInstallation, }) }) It("cancelled", func() { checkStep(models.HostStatusCancelled, []models.StepType{ - models.StepTypeExecute, models.StepTypeExecute, + models.StepTypeLogsGather, models.StepTypeStopInstallation, }) }) It("installing", func() { @@ -224,12 +224,12 @@ var _ = Describe("instruction_manager", func() { }) It("error", func() { checkStep(models.HostStatusError, []models.StepType{ - models.StepTypeExecute, models.StepTypeExecute, + models.StepTypeLogsGather, models.StepTypeStopInstallation, }) }) It("cancelled", func() { checkStep(models.HostStatusCancelled, []models.StepType{ - models.StepTypeExecute, models.StepTypeExecute, + models.StepTypeLogsGather, models.StepTypeStopInstallation, }) }) It("installing", func() { @@ -344,7 +344,6 @@ var _ = Describe("instruction_manager", func() { }) It("Should filter out StepTypeDhcpLeaseAllocate when: HostState=installing DisabledSteps=execute,dhcp-lease-allocate.", func() { instMng = createInstMngWithDisabledSteps([]models.StepType{ - models.StepTypeExecute, models.StepTypeDhcpLeaseAllocate, }) checkStep(models.HostStatusInstalling, []models.StepType{ @@ -353,7 +352,8 @@ var _ = Describe("instruction_manager", func() { }) It("Should filter out StepTypeExecute (No steps) when: HostState=error DisabledSteps=execute.", func() { instMng = createInstMngWithDisabledSteps([]models.StepType{ - models.StepTypeExecute, + models.StepTypeLogsGather, + models.StepTypeStopInstallation, models.StepTypeDhcpLeaseAllocate, }) checkStep(models.HostStatusError, []models.StepType{}) diff --git a/internal/host/hostcommands/stop_installation_cmd_test.go b/internal/host/hostcommands/stop_installation_cmd_test.go index d23c5982780..72debbd578a 100644 --- a/internal/host/hostcommands/stop_installation_cmd_test.go +++ b/internal/host/hostcommands/stop_installation_cmd_test.go @@ -36,7 +36,7 @@ var _ = Describe("stop-podman", func() { It("get_step", func() { stepReply, stepErr = stopCmd.GetSteps(ctx, &host) - Expect(stepReply[0].StepType).To(Equal(models.StepTypeExecute)) + Expect(stepReply[0].StepType).To(Equal(models.StepTypeStopInstallation)) Expect(stepErr).ShouldNot(HaveOccurred()) }) From 0788cd8cc0d1a6a0964e43d7f27c897ac64943b5 Mon Sep 17 00:00:00 2001 From: Igal Tsoiref Date: Thu, 24 Mar 2022 00:57:39 +0200 Subject: [PATCH 17/17] MGMT-9451: add new commands , next_step_runner --- internal/host/hostcommands/next_step_runner_cmd.go | 1 + internal/host/hostcommands/next_step_runner_cmd_test.go | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/internal/host/hostcommands/next_step_runner_cmd.go b/internal/host/hostcommands/next_step_runner_cmd.go index cbede312c23..c360bce6b8b 100644 --- a/internal/host/hostcommands/next_step_runner_cmd.go +++ b/internal/host/hostcommands/next_step_runner_cmd.go @@ -27,6 +27,7 @@ func GetNextStepRunnerCommand(config *NextStepRunnerConfig) (string, *[]string, HostID: &config.HostID, Insecure: swag.Bool(config.SkipCertVerification), BaseURL: swag.String(strings.TrimSpace(config.ServiceBaseURL)), + AgentVersion: swag.String(config.NextStepRunnerImage), } if config.UseCustomCACert { request.CaCertPath = common.HostCACertPath diff --git a/internal/host/hostcommands/next_step_runner_cmd_test.go b/internal/host/hostcommands/next_step_runner_cmd_test.go index 7cdef7714e6..af95fb9289a 100644 --- a/internal/host/hostcommands/next_step_runner_cmd_test.go +++ b/internal/host/hostcommands/next_step_runner_cmd_test.go @@ -46,8 +46,9 @@ var _ = Describe("Format command for starting next step agent", func() { Expect(swag.BoolValue(request.Insecure)).Should(BeFalse()) Expect(request.HostID.String()).Should(Equal(hostID.String())) Expect(request.InfraEnvID.String()).Should(Equal(infraEnvId.String())) - Expect(request.BaseURL).Should(Equal(serviceURL)) - Expect(request.CaCertPath).Should(BeFalse()) + Expect(swag.StringValue(request.BaseURL)).Should(Equal(serviceURL)) + Expect(request.CaCertPath).Should(BeEmpty()) + Expect(swag.StringValue(request.AgentVersion)).Should(Equal(image)) }) It("trim service URL", func() { @@ -56,7 +57,7 @@ var _ = Describe("Format command for starting next step agent", func() { _, args, err := GetNextStepRunnerCommand(&config) Expect(err).ToNot(HaveOccurred()) request := getNextStepRequest(*args) - Expect(request.BaseURL).Should(Equal(serviceURL)) + Expect(swag.StringValue(request.BaseURL)).Should(Equal(serviceURL)) }) It("without custom CA certificate", func() {