-
Notifications
You must be signed in to change notification settings - Fork 296
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Cloudstack multiple endpoint for preflight checks #2559
Changes from 1 commit
bda21a0
c464ce9
e8e931f
3efce41
31679e2
461a804
dbdac2b
0a87c51
cbd45c9
369b53d
260ec6e
5382943
dca6a9e
074a62c
bdf278e
40c9ddb
bdbd178
9813e46
2ddc742
187c194
0fe30a1
2ed1d16
f6259dd
3683c61
222889c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -266,6 +266,7 @@ func (f *Factory) WithProvider(clusterConfigFile string, clusterConfig *v1alpha1 | |
return fmt.Errorf("unable to get machine config from file %s: %v", clusterConfigFile, err) | ||
} | ||
|
||
// map[string]*executables.Cmk and map[string]ProviderCmkClient are not compatible so we convert the map manually | ||
cmkClientMap := cloudstack.CmkClientMap{} | ||
for name, cmk := range f.dependencies.Cmks { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could you add a comment explaining this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
cmkClientMap[name] = cmk | ||
|
@@ -419,7 +420,7 @@ func (f *Factory) WithCmk() *Factory { | |
f.WithExecutableBuilder().WithWriter() | ||
|
||
f.buildSteps = append(f.buildSteps, func(ctx context.Context) error { | ||
if f.dependencies.Cmks != nil { | ||
if f.dependencies.Cmks != nil && len(f.dependencies.Cmks) > 0 { | ||
return nil | ||
} | ||
f.dependencies.Cmks = map[string]*executables.Cmk{} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -262,9 +262,6 @@ func (c *Cmk) ValidateDomainPresent(ctx context.Context, domain string) (v1alpha | |
|
||
func (c *Cmk) ValidateNetworkPresent(ctx context.Context, domainId string, network v1alpha1.CloudStackResourceIdentifier, zoneId string, account string, multipleZone bool) error { | ||
command := newCmkCommand("list networks") | ||
if len(network.Id) > 0 { | ||
applyCmkArgs(&command, withCloudStackId(network.Id)) | ||
} | ||
if multipleZone { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we still need this parameter? I think we could get rid of it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like |
||
applyCmkArgs(&command, withCloudStackNetworkType(Shared)) | ||
} | ||
|
@@ -432,14 +429,13 @@ func (c *Cmk) exec(ctx context.Context, args ...string) (stdout bytes.Buffer, er | |
func (c *Cmk) buildCmkConfigFile() (configFile string, err error) { | ||
t := templater.New(c.writer) | ||
|
||
cloudstackPreflightTimeout := defaultCloudStackPreflightTimeout | ||
c.config.Timeout = defaultCloudStackPreflightTimeout | ||
if timeout, isSet := os.LookupEnv("CLOUDSTACK_PREFLIGHT_TIMEOUT"); isSet { | ||
if _, err := strconv.ParseUint(timeout, 10, 16); err != nil { | ||
return "", fmt.Errorf("CLOUDSTACK_PREFLIGHT_TIMEOUT must be a number: %v", err) | ||
} | ||
cloudstackPreflightTimeout = timeout | ||
c.config.Timeout = timeout | ||
} | ||
c.config.Timeout = cloudstackPreflightTimeout | ||
writtenFileName, err := t.WriteToFile(cmkConfigTemplate, c.config, fmt.Sprintf(cmkConfigFileNameTemplate, c.config.Name)) | ||
if err != nil { | ||
return "", fmt.Errorf("creating file for cmk config: %v", err) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -395,15 +395,15 @@ func (p *cloudstackProvider) validateClusterSpec(ctx context.Context, clusterSpe | |
|
||
func (p *cloudstackProvider) SetupAndValidateCreateCluster(ctx context.Context, clusterSpec *cluster.Spec) error { | ||
if err := p.validateEnv(ctx); err != nil { | ||
return fmt.Errorf("failed setup and validations: %v", err) | ||
return fmt.Errorf("validating environment variables: %v", err) | ||
} | ||
|
||
if err := p.validateClusterSpec(ctx, clusterSpec); err != nil { | ||
return fmt.Errorf("failed cluster spec validation: %v", err) | ||
return fmt.Errorf("validating cluster spec: %v", err) | ||
} | ||
|
||
if err := p.setupSSHAuthKeysForCreate(); err != nil { | ||
return fmt.Errorf("failed setup and validations: %v", err) | ||
return fmt.Errorf("setting up SSH keys: %v", err) | ||
} | ||
|
||
if clusterSpec.Cluster.IsManaged() { | ||
|
@@ -434,15 +434,15 @@ func (p *cloudstackProvider) SetupAndValidateCreateCluster(ctx context.Context, | |
|
||
func (p *cloudstackProvider) SetupAndValidateUpgradeCluster(ctx context.Context, cluster *types.Cluster, clusterSpec *cluster.Spec) error { | ||
if err := p.validateEnv(ctx); err != nil { | ||
return fmt.Errorf("failed setup and validations: %v", err) | ||
return fmt.Errorf("validating environment variables: %v", err) | ||
} | ||
|
||
if err := p.validateClusterSpec(ctx, clusterSpec); err != nil { | ||
return fmt.Errorf("failed cluster spec validation: %v", err) | ||
return fmt.Errorf("validating cluster spec: %v", err) | ||
} | ||
|
||
if err := p.setupSSHAuthKeysForUpgrade(); err != nil { | ||
return fmt.Errorf("failed setup and validations: %v", err) | ||
return fmt.Errorf("setting up SSH keys: %v", err) | ||
} | ||
|
||
if err := p.validateMachineConfigsNameUniqueness(ctx, cluster, clusterSpec); err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't this be part of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is just a code clean up change.
to
If you think validateMachineConfigsNameUniqueness is a part of validateClusterSpec then I should be handled in a separate PR because this pattern shows up in vsphere provider as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think vsphere provider code is a good reference. But yea separate pr sounds good to me. |
||
|
@@ -454,7 +454,7 @@ func (p *cloudstackProvider) SetupAndValidateUpgradeCluster(ctx context.Context, | |
func (p *cloudstackProvider) SetupAndValidateDeleteCluster(ctx context.Context, _ *types.Cluster) error { | ||
err := p.validateEnv(ctx) | ||
if err != nil { | ||
return fmt.Errorf("failed setup and validations: %v", err) | ||
return fmt.Errorf("validating environment variables: %v", err) | ||
} | ||
return nil | ||
} | ||
|
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -14,8 +14,8 @@ import ( | |||
) | ||||
|
||||
type Validator struct { | ||||
cmks CmkClientMap | ||||
availabilityZones []localAvailabilityZone | ||||
cmks CmkClientMap | ||||
localAvailabilityZones []localAvailabilityZone | ||||
} | ||||
|
||||
// Taken from https://github.com/shapeblue/cloudstack/blob/08bb4ad9fea7e422c3d3ac6d52f4670b1e89eed7/api/src/main/java/com/cloud/vm/VmDetailConstants.java | ||||
|
@@ -32,8 +32,8 @@ var restrictedUserCustomDetails = [...]string{ | |||
|
||||
func NewValidator(cmks CmkClientMap) *Validator { | ||||
return &Validator{ | ||||
cmks: cmks, | ||||
availabilityZones: []localAvailabilityZone{}, | ||||
cmks: cmks, | ||||
localAvailabilityZones: []localAvailabilityZone{}, | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think you should have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point |
||||
} | ||||
} | ||||
|
||||
|
@@ -59,25 +59,25 @@ type ProviderCmkClient interface { | |||
type CmkClientMap map[string]ProviderCmkClient | ||||
|
||||
func (v *Validator) validateCloudStackAccess(ctx context.Context, datacenterConfig *anywherev1.CloudStackDatacenterConfig) error { | ||||
azNamesToCheck := []string{} | ||||
refNamesToCheck := []string{} | ||||
if len(datacenterConfig.Spec.Domain) > 0 { | ||||
azNamesToCheck = append(azNamesToCheck, decoder.CloudStackGlobalAZ) | ||||
refNamesToCheck = append(refNamesToCheck, decoder.CloudStackGlobalAZ) | ||||
} | ||||
for _, az := range datacenterConfig.Spec.AvailabilityZones { | ||||
azNamesToCheck = append(azNamesToCheck, az.CredentialsRef) | ||||
refNamesToCheck = append(refNamesToCheck, az.CredentialsRef) | ||||
} | ||||
|
||||
for _, azName := range azNamesToCheck { | ||||
cmk, ok := v.cmks[azName] | ||||
for _, refName := range refNamesToCheck { | ||||
cmk, ok := v.cmks[refName] | ||||
if !ok { | ||||
return fmt.Errorf("cannot find CloudStack profile for availability zone %s", azName) | ||||
return fmt.Errorf("cannot find CloudStack profile for credentialsRef %s", refName) | ||||
} | ||||
if err := cmk.ValidateCloudStackConnection(ctx); err != nil { | ||||
return fmt.Errorf("failed validating connection to cloudstack %s: %v", azName, err) | ||||
return fmt.Errorf("failed validating connection to cloudstack %s: %v", refName, err) | ||||
} | ||||
} | ||||
|
||||
logger.MarkPass("Connected to", "servers", azNamesToCheck) | ||||
logger.MarkPass("Connected to", "servers", refNamesToCheck) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what does the formatting look like here? I don't see any %s substitution so I'm a bit confused There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MarkPass takes keysAndValues... so There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you paste an example here for reference? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we are doing a mark pass here, can we make it more readable like |
||||
return nil | ||||
} | ||||
|
||||
|
@@ -86,22 +86,33 @@ func (v *Validator) ValidateCloudStackDatacenterConfig(ctx context.Context, data | |||
return err | ||||
} | ||||
|
||||
for _, az := range v.availabilityZones { | ||||
for _, az := range v.localAvailabilityZones { | ||||
fmt.Printf("az: %+v\n", az.CloudStackAvailabilityZone) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops. Removed. |
||||
_, err := getHostnameFromUrl(az.ManagementApiEndpoint) | ||||
if err != nil { | ||||
return fmt.Errorf("checking management api endpoint: %v", err) | ||||
} | ||||
|
||||
cmk, ok := v.cmks[az.CredentialsRef] | ||||
if !ok { | ||||
return fmt.Errorf("cannot find CloudStack profile for availability zone %s", az.CredentialsRef) | ||||
return fmt.Errorf("cannot find CloudStack profile named %s for availability zone %s", az.CredentialsRef, az.Name) | ||||
} | ||||
endpoint := cmk.GetManagementApiEndpoint() | ||||
if endpoint != az.ManagementApiEndpoint { | ||||
return fmt.Errorf("cloudstack secret management url (%s) differs from cluster spec management url (%s)", | ||||
endpoint, az.ManagementApiEndpoint) | ||||
} | ||||
|
||||
domain, err := cmk.ValidateDomainPresent(ctx, az.Domain) | ||||
if err != nil { | ||||
return err | ||||
} | ||||
az.DomainId = domain.Id | ||||
|
||||
if err := cmk.ValidateAccountPresent(ctx, az.Account, az.DomainId); err != nil { | ||||
return err | ||||
} | ||||
|
||||
zoneId, err := cmk.ValidateZonePresent(ctx, az.CloudStackAvailabilityZone.Zone) | ||||
if err != nil { | ||||
return err | ||||
|
@@ -125,52 +136,37 @@ func (v *Validator) generateLocalAvailabilityZones(ctx context.Context, datacent | |||
} | ||||
|
||||
if len(datacenterConfig.Spec.Domain) > 0 { | ||||
cmk, ok := v.cmks[decoder.CloudStackGlobalAZ] | ||||
_, ok := v.cmks[decoder.CloudStackGlobalAZ] | ||||
if !ok { | ||||
return fmt.Errorf("cannot find CloudStack profile for availability zone %s", decoder.CloudStackGlobalAZ) | ||||
} | ||||
domain, err := cmk.ValidateDomainPresent(ctx, datacenterConfig.Spec.Domain) | ||||
if err != nil { | ||||
return err | ||||
} | ||||
if err := cmk.ValidateAccountPresent(ctx, datacenterConfig.Spec.Account, domain.Id); err != nil { | ||||
return err | ||||
return fmt.Errorf("cannot find CloudStack profile named %s for default availability zone", decoder.CloudStackGlobalAZ) | ||||
} | ||||
for _, zone := range datacenterConfig.Spec.Zones { | ||||
for index, zone := range datacenterConfig.Spec.Zones { | ||||
availabilityZone := localAvailabilityZone{ | ||||
CloudStackAvailabilityZone: &anywherev1.CloudStackAvailabilityZone{ | ||||
Name: fmt.Sprintf("availability-zone-%d", index), | ||||
CredentialsRef: decoder.CloudStackGlobalAZ, | ||||
Domain: datacenterConfig.Spec.Domain, | ||||
Account: datacenterConfig.Spec.Account, | ||||
ManagementApiEndpoint: datacenterConfig.Spec.ManagementApiEndpoint, | ||||
Zone: zone, | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this seems to be missing a name, doesn't it? I think we need the name too for some of the error messages There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding Name as SetDefaults does |
||||
}, | ||||
DomainId: domain.Id, | ||||
} | ||||
v.availabilityZones = append(v.availabilityZones, availabilityZone) | ||||
v.localAvailabilityZones = append(v.localAvailabilityZones, availabilityZone) | ||||
} | ||||
} | ||||
for _, az := range datacenterConfig.Spec.AvailabilityZones { | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need a check for nil before iterating over the items in an array? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need, I think. AvailablityZones is []CloudStackAvailabilityZone and it will be initialized as an empty list. |
||||
cmk, ok := v.cmks[az.CredentialsRef] | ||||
_, ok := v.cmks[az.CredentialsRef] | ||||
if !ok { | ||||
return fmt.Errorf("cannot find CloudStack profile for availability zone %s", az.CredentialsRef) | ||||
} | ||||
domain, err := cmk.ValidateDomainPresent(ctx, az.Domain) | ||||
if err != nil { | ||||
return err | ||||
} | ||||
if err := cmk.ValidateAccountPresent(ctx, az.Account, domain.Id); err != nil { | ||||
return err | ||||
return fmt.Errorf("cannot find CloudStack profile named %s for availability zone %s", az.CredentialsRef, az.Name) | ||||
} | ||||
availabilityZone := localAvailabilityZone{ | ||||
CloudStackAvailabilityZone: &az, | ||||
DomainId: domain.Id, | ||||
} | ||||
v.availabilityZones = append(v.availabilityZones, availabilityZone) | ||||
v.localAvailabilityZones = append(v.localAvailabilityZones, availabilityZone) | ||||
} | ||||
|
||||
if len(v.availabilityZones) <= 0 { | ||||
return fmt.Errorf("CloudStackDatacenterConfig domain or availabilityZones is not set or is empty") | ||||
if len(v.localAvailabilityZones) <= 0 { | ||||
return fmt.Errorf("CloudStackDatacenterConfig domain or localAvailabilityZones is not set or is empty") | ||||
} | ||||
return nil | ||||
} | ||||
|
@@ -286,10 +282,10 @@ func (v *Validator) validateMachineConfig(ctx context.Context, datacenterConfig | |||
} | ||||
} | ||||
|
||||
for _, az := range v.availabilityZones { | ||||
for _, az := range v.localAvailabilityZones { | ||||
cmk, ok := v.cmks[az.CredentialsRef] | ||||
if !ok { | ||||
return fmt.Errorf("cannot find CloudStack profile for availability zone %s", az.CredentialsRef) | ||||
return fmt.Errorf("cannot find CloudStack profile named %s for availability zone %s", az.CredentialsRef, az.Name) | ||||
} | ||||
if err := cmk.ValidateTemplatePresent(ctx, az.DomainId, az.CloudStackAvailabilityZone.Zone.Id, az.Account, machineConfig.Spec.Template); err != nil { | ||||
return fmt.Errorf("validating template: %v", err) | ||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this comment is no longer relevant right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right