Skip to content

Commit a32e5f3

Browse files
implement validation checks for failuredomain fields (#9466)
1 parent 44e1fe6 commit a32e5f3

File tree

8 files changed

+956
-106
lines changed

8 files changed

+956
-106
lines changed

pkg/executables/govc.go

Lines changed: 117 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -756,23 +756,22 @@ func (g *Govc) NetworkExists(ctx context.Context, network string) (bool, error)
756756
return exists, nil
757757
}
758758

759-
func (g *Govc) ValidateVCenterSetupMachineConfig(ctx context.Context, datacenterConfig *v1alpha1.VSphereDatacenterConfig, machineConfig *v1alpha1.VSphereMachineConfig, _ *bool) error {
760-
envMap, err := g.validateAndSetupCreds()
759+
// GetDatastorePath validates and returns the full path to a datastore in the specified datacenter.
760+
// Returns an error if the datastore doesn't exist or if the path is invalid.
761+
func (g *Govc) GetDatastorePath(ctx context.Context, datacenter string, datastorePath string, envMap map[string]string) (string, error) {
762+
fullPath, err := prependPath(datastore, datastorePath, datacenter)
761763
if err != nil {
762-
return fmt.Errorf("failed govc validations: %v", err)
764+
return "", err
763765
}
764-
machineConfig.Spec.Datastore, err = prependPath(datastore, machineConfig.Spec.Datastore, datacenterConfig.Spec.Datacenter)
765-
if err != nil {
766-
return err
767-
}
768-
params := []string{"datastore.info", machineConfig.Spec.Datastore}
766+
767+
params := []string{"datastore.info", fullPath}
769768
err = g.Retry(func() error {
770769
_, err = g.ExecuteWithEnv(ctx, envMap, params...)
771770
if err != nil {
772-
datastorePath := filepath.Dir(machineConfig.Spec.Datastore)
773-
isValidDatastorePath := g.isValidPath(ctx, envMap, datastorePath)
771+
parentPath := filepath.Dir(fullPath)
772+
isValidDatastorePath := g.isValidPath(ctx, envMap, parentPath)
774773
if isValidDatastorePath {
775-
leafDir := filepath.Base(machineConfig.Spec.Datastore)
774+
leafDir := filepath.Base(fullPath)
776775
return fmt.Errorf("valid path, but '%s' is not a datastore", leafDir)
777776
} else {
778777
return fmt.Errorf("failed to get datastore: %v", err)
@@ -781,79 +780,151 @@ func (g *Govc) ValidateVCenterSetupMachineConfig(ctx context.Context, datacenter
781780
return nil
782781
})
783782
if err != nil {
784-
return fmt.Errorf("failed to get datastore: %v", err)
783+
return "", fmt.Errorf("failed to get datastore: %v", err)
785784
}
786785
logger.MarkPass("Datastore validated")
786+
return fullPath, nil
787+
}
788+
789+
// GetFolderPath validates or creates a folder in the specified datacenter.
790+
// Returns the full path to the folder or an error if creation fails.
791+
func (g *Govc) GetFolderPath(ctx context.Context, datacenter string, folder string, envMap map[string]string) (string, error) {
792+
if len(folder) == 0 {
793+
return "", nil
794+
}
795+
796+
fullPath, err := prependPath(vm, folder, datacenter)
797+
if err != nil {
798+
return "", err
799+
}
787800

788-
if len(machineConfig.Spec.Folder) > 0 {
789-
machineConfig.Spec.Folder, err = prependPath(vm, machineConfig.Spec.Folder, datacenterConfig.Spec.Datacenter)
801+
params := []string{"folder.info", fullPath}
802+
err = g.Retry(func() error {
803+
_, err := g.ExecuteWithEnv(ctx, envMap, params...)
790804
if err != nil {
791-
return err
792-
}
793-
params = []string{"folder.info", machineConfig.Spec.Folder}
794-
err = g.Retry(func() error {
795-
_, err := g.ExecuteWithEnv(ctx, envMap, params...)
805+
err = g.createFolder(ctx, envMap, fullPath)
796806
if err != nil {
797-
err = g.createFolder(ctx, envMap, machineConfig)
798-
if err != nil {
799-
currPath := "/" + datacenterConfig.Spec.Datacenter + "/"
800-
dirs := strings.Split(machineConfig.Spec.Folder, "/")
801-
for _, dir := range dirs[2:] {
802-
currPath += dir + "/"
803-
if !g.isValidPath(ctx, envMap, currPath) {
804-
return fmt.Errorf("%s is an invalid intermediate directory", currPath)
805-
}
807+
currPath := "/" + datacenter + "/"
808+
dirs := strings.Split(fullPath, "/")
809+
for _, dir := range dirs[2:] {
810+
currPath += dir + "/"
811+
if !g.isValidPath(ctx, envMap, currPath) {
812+
return fmt.Errorf("%s is an invalid intermediate directory", currPath)
806813
}
807-
return err
808814
}
815+
return err
809816
}
810-
return nil
811-
})
812-
if err != nil {
813-
return fmt.Errorf("failed to get folder: %v", err)
814817
}
815-
logger.MarkPass("Folder validated")
818+
return nil
819+
})
820+
if err != nil {
821+
return "", fmt.Errorf("failed to get folder: %v", err)
816822
}
823+
logger.MarkPass("Folder validated")
824+
return fullPath, nil
825+
}
817826

827+
// GetResourcePoolPath finds and validates a resource pool in the specified datacenter.
828+
// Returns an error if the pool doesn't exist or if multiple matching pools are found.
829+
func (g *Govc) GetResourcePoolPath(ctx context.Context, datacenter string, resourcePool string, envMap map[string]string) (string, error) {
818830
var poolInfoResponse bytes.Buffer
819-
params = []string{"find", "-json", "/" + datacenterConfig.Spec.Datacenter, "-type", "p", "-name", filepath.Base(machineConfig.Spec.ResourcePool)}
820-
err = g.Retry(func() error {
831+
params := []string{"find", "-json", "/" + datacenter, "-type", "p", "-name", filepath.Base(resourcePool)}
832+
833+
err := g.Retry(func() error {
834+
var err error
821835
poolInfoResponse, err = g.ExecuteWithEnv(ctx, envMap, params...)
822836
return err
823837
})
824838
if err != nil {
825-
return fmt.Errorf("getting resource pool: %v", err)
839+
return "", fmt.Errorf("getting resource pool: %v", err)
826840
}
827841

828842
poolInfoJson := poolInfoResponse.String()
829843
poolInfoJson = strings.TrimSuffix(poolInfoJson, "\n")
830844
if poolInfoJson == "null" || poolInfoJson == "" {
831-
return fmt.Errorf("resource pool '%s' not found", machineConfig.Spec.ResourcePool)
845+
return "", fmt.Errorf("resource pool '%s' not found", resourcePool)
832846
}
833847

834848
poolInfo := make([]string, 0)
835849
if err = json.Unmarshal([]byte(poolInfoJson), &poolInfo); err != nil {
836-
return fmt.Errorf("failed unmarshalling govc response: %v", err)
850+
return "", fmt.Errorf("failed unmarshalling govc response: %v", err)
837851
}
838852

839-
machineConfig.Spec.ResourcePool = strings.TrimPrefix(machineConfig.Spec.ResourcePool, "*/")
853+
resourcePool = strings.TrimPrefix(resourcePool, "*/")
840854
bPoolFound := false
841855
var foundPool string
842856
for _, p := range poolInfo {
843-
if strings.HasSuffix(p, machineConfig.Spec.ResourcePool) {
857+
if strings.HasSuffix(p, resourcePool) {
844858
if bPoolFound {
845-
return fmt.Errorf("specified resource pool '%s' maps to multiple paths within the datacenter '%s'", machineConfig.Spec.ResourcePool, datacenterConfig.Spec.Datacenter)
859+
return "", fmt.Errorf("specified resource pool '%s' maps to multiple paths within the datacenter '%s'", resourcePool, datacenter)
846860
}
847861
bPoolFound = true
848862
foundPool = p
849863
}
850864
}
851865
if !bPoolFound {
852-
return fmt.Errorf("resource pool '%s' not found", machineConfig.Spec.ResourcePool)
866+
return "", fmt.Errorf("resource pool '%s' not found", resourcePool)
853867
}
854-
machineConfig.Spec.ResourcePool = foundPool
855868

856869
logger.MarkPass("Resource pool validated")
870+
return foundPool, nil
871+
}
872+
873+
// ValidateVCenterSetupMachineConfig validates that all resources specified in a
874+
// VSphereMachineConfig exist and are accessible.
875+
func (g *Govc) ValidateVCenterSetupMachineConfig(ctx context.Context, datacenterConfig *v1alpha1.VSphereDatacenterConfig, machineConfig *v1alpha1.VSphereMachineConfig, _ *bool) error {
876+
envMap, err := g.validateAndSetupCreds()
877+
if err != nil {
878+
return fmt.Errorf("failed govc validations: %v", err)
879+
}
880+
881+
datastore, err := g.GetDatastorePath(ctx, datacenterConfig.Spec.Datacenter, machineConfig.Spec.Datastore, envMap)
882+
if err != nil {
883+
return err
884+
}
885+
machineConfig.Spec.Datastore = datastore
886+
887+
folder, err := g.GetFolderPath(ctx, datacenterConfig.Spec.Datacenter, machineConfig.Spec.Folder, envMap)
888+
if err != nil {
889+
return err
890+
}
891+
machineConfig.Spec.Folder = folder
892+
893+
resourcePool, err := g.GetResourcePoolPath(ctx, datacenterConfig.Spec.Datacenter, machineConfig.Spec.ResourcePool, envMap)
894+
if err != nil {
895+
return err
896+
}
897+
machineConfig.Spec.ResourcePool = resourcePool
898+
899+
return nil
900+
}
901+
902+
// ValidateFailureDomainConfig validates that all resources specified in a VSphere
903+
// failure domain exist and are accessible.
904+
func (g *Govc) ValidateFailureDomainConfig(ctx context.Context, datacenterConfig *v1alpha1.VSphereDatacenterConfig, failureDomain *v1alpha1.FailureDomain) error {
905+
envMap, err := g.validateAndSetupCreds()
906+
if err != nil {
907+
return fmt.Errorf("failed govc validations: %v", err)
908+
}
909+
910+
datastore, err := g.GetDatastorePath(ctx, datacenterConfig.Spec.Datacenter, failureDomain.Datastore, envMap)
911+
if err != nil {
912+
return err
913+
}
914+
failureDomain.Datastore = datastore
915+
916+
folder, err := g.GetFolderPath(ctx, datacenterConfig.Spec.Datacenter, failureDomain.Folder, envMap)
917+
if err != nil {
918+
return err
919+
}
920+
failureDomain.Folder = folder
921+
922+
resourcePool, err := g.GetResourcePoolPath(ctx, datacenterConfig.Spec.Datacenter, failureDomain.ResourcePool, envMap)
923+
if err != nil {
924+
return err
925+
}
926+
failureDomain.ResourcePool = resourcePool
927+
857928
return nil
858929
}
859930

@@ -872,8 +943,8 @@ func prependPath(folderType FolderType, folderPath string, datacenter string) (s
872943
return modPath, nil
873944
}
874945

875-
func (g *Govc) createFolder(ctx context.Context, envMap map[string]string, machineConfig *v1alpha1.VSphereMachineConfig) error {
876-
params := []string{"folder.create", machineConfig.Spec.Folder}
946+
func (g *Govc) createFolder(ctx context.Context, envMap map[string]string, folderPath string) error {
947+
params := []string{"folder.create", folderPath}
877948
err := g.Retry(func() error {
878949
_, err := g.ExecuteWithEnv(ctx, envMap, params...)
879950
if err != nil {

0 commit comments

Comments
 (0)