diff --git a/api/v1beta2/ibmpowervscluster_webhook.go b/api/v1beta2/ibmpowervscluster_webhook.go index 52ce0086c7..744dc4a94d 100644 --- a/api/v1beta2/ibmpowervscluster_webhook.go +++ b/api/v1beta2/ibmpowervscluster_webhook.go @@ -105,10 +105,12 @@ func (r *IBMPowerVSCluster) validateIBMPowerVSClusterNetwork() *field.Error { func (r *IBMPowerVSCluster) validateIBMPowerVSClusterLoadBalancerNames() (allErrs field.ErrorList) { found := make(map[string]bool) for i, loadbalancer := range r.Spec.LoadBalancers { - if found[loadbalancer.Name] { - allErrs = append(allErrs, field.Duplicate(field.NewPath("spec", fmt.Sprintf("loadbalancers[%d]", i)), map[string]interface{}{"Name": loadbalancer.Name})) + if loadbalancer.Name != "" { + if found[loadbalancer.Name] { + allErrs = append(allErrs, field.Duplicate(field.NewPath("spec", fmt.Sprintf("loadbalancers[%d]", i)), map[string]interface{}{"Name": loadbalancer.Name})) + } + found[loadbalancer.Name] = true } - found[loadbalancer.Name] = true } return allErrs @@ -117,10 +119,12 @@ func (r *IBMPowerVSCluster) validateIBMPowerVSClusterLoadBalancerNames() (allErr func (r *IBMPowerVSCluster) validateIBMPowerVSClusterVPCSubnetNames() (allErrs field.ErrorList) { found := make(map[string]bool) for i, subnet := range r.Spec.VPCSubnets { - if found[*subnet.Name] { - allErrs = append(allErrs, field.Duplicate(field.NewPath("spec", fmt.Sprintf("vpcSubnets[%d]", i)), map[string]interface{}{"Name": *subnet.Name})) + if subnet.Name != nil { + if found[*subnet.Name] { + allErrs = append(allErrs, field.Duplicate(field.NewPath("spec", fmt.Sprintf("vpcSubnets[%d]", i)), map[string]interface{}{"Name": *subnet.Name})) + } + found[*subnet.Name] = true } - found[*subnet.Name] = true } return allErrs @@ -130,6 +134,9 @@ func (r *IBMPowerVSCluster) validateIBMPowerVSClusterTransitGateway() *field.Err if r.Spec.Zone == nil && r.Spec.VPC == nil { return nil } + if r.Spec.TransitGateway == nil { + return nil + } if _, globalRouting, _ := genUtil.GetTransitGatewayLocationAndRouting(r.Spec.Zone, r.Spec.VPC.Region); r.Spec.TransitGateway.GlobalRouting != nil && !*r.Spec.TransitGateway.GlobalRouting && globalRouting != nil && *globalRouting { return field.Invalid(field.NewPath("spec.transitGateway.globalRouting"), r.Spec.TransitGateway.GlobalRouting, "global routing is required since PowerVS and VPC region are from different region") } diff --git a/cloud/scope/powervs_cluster.go b/cloud/scope/powervs_cluster.go index 81ac4506d5..1cf6963ca2 100644 --- a/cloud/scope/powervs_cluster.go +++ b/cloud/scope/powervs_cluster.go @@ -380,14 +380,8 @@ func (s *PowerVSClusterScope) ServiceInstance() *infrav1beta2.IBMPowerVSResource return s.IBMPowerVSCluster.Spec.ServiceInstance } -// GetServiceInstanceID get the service instance id. +// GetServiceInstanceID returns service instance id set in status field of IBMPowerVSCluster object. If it doesn't exist, returns empty string. func (s *PowerVSClusterScope) GetServiceInstanceID() string { - if s.IBMPowerVSCluster.Spec.ServiceInstanceID != "" { - return s.IBMPowerVSCluster.Spec.ServiceInstanceID - } - if s.IBMPowerVSCluster.Spec.ServiceInstance != nil && s.IBMPowerVSCluster.Spec.ServiceInstance.ID != nil { - return *s.IBMPowerVSCluster.Spec.ServiceInstance.ID - } if s.IBMPowerVSCluster.Status.ServiceInstance != nil && s.IBMPowerVSCluster.Status.ServiceInstance.ID != nil { return *s.IBMPowerVSCluster.Status.ServiceInstance.ID } @@ -450,11 +444,8 @@ func (s *PowerVSClusterScope) Network() *infrav1beta2.IBMPowerVSResourceReferenc return &s.IBMPowerVSCluster.Spec.Network } -// GetDHCPServerID returns the DHCP id from spec or status of IBMPowerVSCluster object. +// GetDHCPServerID returns the DHCP id from status of IBMPowerVSCluster object. If it doesn't exist, returns nil. func (s *PowerVSClusterScope) GetDHCPServerID() *string { - if s.IBMPowerVSCluster.Spec.DHCPServer != nil && s.IBMPowerVSCluster.Spec.DHCPServer.ID != nil { - return s.IBMPowerVSCluster.Spec.DHCPServer.ID - } if s.IBMPowerVSCluster.Status.DHCPServer != nil { return s.IBMPowerVSCluster.Status.DHCPServer.ID } @@ -471,11 +462,8 @@ func (s *PowerVSClusterScope) VPC() *infrav1beta2.VPCResourceReference { return s.IBMPowerVSCluster.Spec.VPC } -// GetVPCID returns the VPC id. +// GetVPCID returns the VPC id set in status field of IBMPowerVSCluster object. If it doesn't exist, returns nil. func (s *PowerVSClusterScope) GetVPCID() *string { - if s.IBMPowerVSCluster.Spec.VPC != nil && s.IBMPowerVSCluster.Spec.VPC.ID != nil { - return s.IBMPowerVSCluster.Spec.VPC.ID - } if s.IBMPowerVSCluster.Status.VPC != nil { return s.IBMPowerVSCluster.Status.VPC.ID } @@ -496,15 +484,6 @@ func (s *PowerVSClusterScope) GetVPCSubnetID(subnetName string) *string { // GetVPCSubnetIDs returns all the VPC subnet ids. func (s *PowerVSClusterScope) GetVPCSubnetIDs() []*string { subnets := []*string{} - // use the vpc subnet id set by user. - for _, subnet := range s.IBMPowerVSCluster.Spec.VPCSubnets { - if subnet.ID != nil { - subnets = append(subnets, subnet.ID) - } - } - if len(subnets) != 0 { - return subnets - } if s.IBMPowerVSCluster.Status.VPCSubnet == nil { return nil } @@ -514,8 +493,8 @@ func (s *PowerVSClusterScope) GetVPCSubnetIDs() []*string { return subnets } -// SetVPCSubnetID set the VPC subnet id. -func (s *PowerVSClusterScope) SetVPCSubnetID(name string, resource infrav1beta2.ResourceReference) { +// SetVPCSubnetStatus set the VPC subnet id. +func (s *PowerVSClusterScope) SetVPCSubnetStatus(name string, resource infrav1beta2.ResourceReference) { s.V(3).Info("Setting status", "name", name, "resource", resource) if s.IBMPowerVSCluster.Status.VPCSubnet == nil { s.IBMPowerVSCluster.Status.VPCSubnet = make(map[string]infrav1beta2.ResourceReference) @@ -552,8 +531,8 @@ func (s *PowerVSClusterScope) GetVPCSecurityGroupByID(securityGroupID string) (* return nil, nil, nil } -// SetVPCSecurityGroup set the VPC security group id. -func (s *PowerVSClusterScope) SetVPCSecurityGroup(name string, resource infrav1beta2.VPCSecurityGroupStatus) { +// SetVPCSecurityGroupStatus set the VPC security group id. +func (s *PowerVSClusterScope) SetVPCSecurityGroupStatus(name string, resource infrav1beta2.VPCSecurityGroupStatus) { s.V(3).Info("Setting VPC security group status", "name", name, "resource", resource) if s.IBMPowerVSCluster.Status.VPCSecurityGroups == nil { s.IBMPowerVSCluster.Status.VPCSecurityGroups = make(map[string]infrav1beta2.VPCSecurityGroupStatus) @@ -583,20 +562,29 @@ func (s *PowerVSClusterScope) GetTransitGatewayID() *string { } // PublicLoadBalancer returns the cluster public loadBalancer information. -func (s *PowerVSClusterScope) PublicLoadBalancer() *infrav1beta2.VPCLoadBalancerSpec { +func (s *PowerVSClusterScope) PublicLoadBalancer() (*infrav1beta2.VPCLoadBalancerSpec, error) { // if the user did not specify any loadbalancer then return the public loadbalancer created by the controller. if len(s.IBMPowerVSCluster.Spec.LoadBalancers) == 0 { return &infrav1beta2.VPCLoadBalancerSpec{ Name: *s.GetServiceName(infrav1beta2.ResourceTypeLoadBalancer), Public: ptr.To(true), - } + }, nil } for _, lb := range s.IBMPowerVSCluster.Spec.LoadBalancers { + if lb.ID != nil && lb.Name == "" { + loadBalancer, _, err := s.IBMVPCClient.GetLoadBalancer(&vpcv1.GetLoadBalancerOptions{ + ID: lb.ID, + }) + if err != nil { + return nil, err + } + lb.Name = *loadBalancer.Name + } if lb.Public != nil && *lb.Public { - return &lb + return &lb, nil } } - return nil + return nil, nil } // SetLoadBalancerStatus set the loadBalancer id. @@ -646,7 +634,7 @@ func (s *PowerVSClusterScope) GetLoadBalancerHostName(name string) *string { return nil } -// GetResourceGroupID returns the resource group id if it present under spec or statue filed of IBMPowerVSCluster object +// GetResourceGroupID returns the resource group id if it present under spec or status filed of IBMPowerVSCluster object // or returns empty string. func (s *PowerVSClusterScope) GetResourceGroupID() string { if s.IBMPowerVSCluster.Spec.ResourceGroup != nil && s.IBMPowerVSCluster.Spec.ResourceGroup.ID != nil { @@ -699,7 +687,7 @@ func (s *PowerVSClusterScope) ReconcileResourceGroup() error { // ReconcilePowerVSServiceInstance reconciles Power VS service instance. func (s *PowerVSClusterScope) ReconcilePowerVSServiceInstance() (bool, error) { - // Verify if service instance id is set in spec or status field of IBMPowerVSCluster object. + // Verify if service instance id is set in status field of IBMPowerVSCluster object. serviceInstanceID := s.GetServiceInstanceID() if serviceInstanceID != "" { s.V(3).Info("PowerVS service instance ID is set, fetching details", "id", serviceInstanceID) @@ -728,6 +716,7 @@ func (s *PowerVSClusterScope) ReconcilePowerVSServiceInstance() (bool, error) { } // Set the status of IBMPowerVSCluster object with serviceInstanceID and ControllerCreated to false as PowerVS service instance is already exist in cloud. if serviceInstanceID != "" { + s.V(3).Info("Found PowerVS service instance in IBM Cloud", "id", serviceInstanceID) s.SetStatus(infrav1beta2.ResourceTypeServiceInstance, infrav1beta2.ResourceReference{ID: &serviceInstanceID, ControllerCreated: ptr.To(false)}) return requeue, nil } @@ -765,17 +754,38 @@ func (s *PowerVSClusterScope) checkServiceInstanceState(instance resourcecontrol return false, nil } -// checkServiceInstance checks PowerVS service instance exist in cloud. +// checkServiceInstance checks PowerVS service instance exist in cloud by ID or name. func (s *PowerVSClusterScope) isServiceInstanceExists() (string, bool, error) { s.V(3).Info("Checking for PowerVS service instance in IBM Cloud") - // Fetches service instance by name. - serviceInstance, err := s.getServiceInstance() + var ( + id string + err error + serviceInstance *resourcecontrollerv2.ResourceInstance + ) + + if s.IBMPowerVSCluster.Spec.ServiceInstanceID != "" { + id = s.IBMPowerVSCluster.Spec.ServiceInstanceID + } else if s.IBMPowerVSCluster.Spec.ServiceInstance != nil && s.IBMPowerVSCluster.Spec.ServiceInstance.ID != nil { + id = *s.IBMPowerVSCluster.Spec.ServiceInstance.ID + } + + if id != "" { + // Fetches service instance by ID. + serviceInstance, _, err = s.ResourceClient.GetResourceInstance(&resourcecontrollerv2.GetResourceInstanceOptions{ + ID: &id, + }) + } else { + // Fetches service instance by name. + serviceInstance, err = s.getServiceInstance() + } + if err != nil { s.Error(err, "failed to get PowerVS service instance") return "", false, err } + if serviceInstance == nil { - s.V(3).Info("PowerVS service instance with given name does not exist in IBM Cloud", "name", *s.GetServiceName(infrav1beta2.ResourceTypeServiceInstance)) + s.V(3).Info("PowerVS service instance with given ID or name does not exist in IBM Cloud") return "", false, nil } @@ -854,30 +864,14 @@ func (s *PowerVSClusterScope) ReconcileNetwork() (bool, error) { return false, nil } -// checkNetwork checks the network exist in cloud. +// checkNetwork checks if network exists in cloud with given name or ID mentioned in spec. func (s *PowerVSClusterScope) checkNetwork() (*string, error) { - // get network from cloud. s.V(3).Info("Checking if PowerVS network exists in IBM Cloud") - networkID, err := s.getNetwork() - if err != nil { - s.Error(err, "failed to get PowerVS network") - return nil, err - } - if networkID == nil { - s.V(3).Info("Unable to find PowerVS network in IBM Cloud", "network", s.IBMPowerVSCluster.Spec.Network) - return nil, nil - } - return networkID, nil -} - -func (s *PowerVSClusterScope) getNetwork() (*string, error) { - // fetch the network associated with network id if s.IBMPowerVSCluster.Spec.Network.ID != nil { network, err := s.IBMPowerVSClient.GetNetworkByID(*s.IBMPowerVSCluster.Spec.Network.ID) if err != nil { return nil, err } - s.V(3).Info("Found the PowerVS network", "id", network.NetworkID) return network.NetworkID, nil } @@ -895,20 +889,16 @@ func (s *PowerVSClusterScope) getNetwork() (*string, error) { if err != nil { return nil, err } - if network == nil { + if network == nil && network.NetworkID == nil { + s.V(3).Info("Unable to find PowerVS network in IBM Cloud", "network", s.IBMPowerVSCluster.Spec.Network) return nil, nil } return network.NetworkID, nil - //TODO: Support regular expression } // isDHCPServerActive checks if the DHCP server status is active. func (s *PowerVSClusterScope) isDHCPServerActive() (bool, error) { - dhcpID := *s.GetDHCPServerID() - if dhcpID == "" { - return false, fmt.Errorf("DHCP ID is empty") - } - dhcpServer, err := s.IBMPowerVSClient.GetDHCPServer(dhcpID) + dhcpServer, err := s.IBMPowerVSClient.GetDHCPServer(*s.GetDHCPServerID()) if err != nil { return false, err } @@ -1004,6 +994,7 @@ func (s *PowerVSClusterScope) ReconcileVPC() (bool, error) { return false, err } if id != "" { + s.V(3).Info("VPC found in IBM Cloud", "id", id) s.SetStatus(infrav1beta2.ResourceTypeVPC, infrav1beta2.ResourceReference{ID: &id, ControllerCreated: ptr.To(false)}) return false, nil } @@ -1023,7 +1014,16 @@ func (s *PowerVSClusterScope) ReconcileVPC() (bool, error) { // checkVPC checks VPC exist in cloud. func (s *PowerVSClusterScope) checkVPC() (string, error) { - vpcDetails, err := s.getVPCByName() + var err error + var vpcDetails *vpcv1.VPC + if s.IBMPowerVSCluster.Spec.VPC != nil && s.IBMPowerVSCluster.Spec.VPC.ID != nil { + vpcDetails, _, err = s.IBMVPCClient.GetVPC(&vpcv1.GetVPCOptions{ + ID: s.IBMPowerVSCluster.Spec.VPC.ID, + }) + } else { + vpcDetails, err = s.getVPCByName() + } + if err != nil { s.Error(err, "failed to get VPC") return "", err @@ -1100,7 +1100,7 @@ func (s *PowerVSClusterScope) ReconcileVPCSubnets() (bool, error) { } } for index, subnet := range s.IBMPowerVSCluster.Spec.VPCSubnets { - if subnet.Name == nil { + if subnet.ID == nil && subnet.Name == nil { subnet.Name = ptr.To(fmt.Sprintf("%s-%d", *s.GetServiceName(infrav1beta2.ResourceTypeSubnet), index)) } subnets = append(subnets, subnet) @@ -1113,6 +1113,7 @@ func (s *PowerVSClusterScope) ReconcileVPCSubnets() (bool, error) { } else { subnetID = s.GetVPCSubnetID(*subnet.Name) } + if subnetID != nil { s.V(3).Info("VPC subnet ID is set, fetching details", "id", *subnetID) subnetDetails, _, err := s.IBMVPCClient.GetSubnet(&vpcv1.GetSubnetOptions{ @@ -1125,6 +1126,7 @@ func (s *PowerVSClusterScope) ReconcileVPCSubnets() (bool, error) { return false, fmt.Errorf("failed to get VPC subnet with ID %s", *subnetID) } // check for next subnet + s.SetVPCSubnetStatus(*subnetDetails.Name, infrav1beta2.ResourceReference{ID: subnetDetails.ID}) continue } @@ -1136,7 +1138,7 @@ func (s *PowerVSClusterScope) ReconcileVPCSubnets() (bool, error) { } if vpcSubnetID != "" { s.V(3).Info("Found VPC subnet in IBM Cloud", "id", vpcSubnetID) - s.SetVPCSubnetID(*subnet.Name, infrav1beta2.ResourceReference{ID: &vpcSubnetID, ControllerCreated: ptr.To(false)}) + s.SetVPCSubnetStatus(*subnet.Name, infrav1beta2.ResourceReference{ID: &vpcSubnetID, ControllerCreated: ptr.To(false)}) // check for next subnet continue } @@ -1148,13 +1150,13 @@ func (s *PowerVSClusterScope) ReconcileVPCSubnets() (bool, error) { return false, err } s.Info("Created VPC subnet", "id", subnetID) - s.SetVPCSubnetID(*subnet.Name, infrav1beta2.ResourceReference{ID: subnetID, ControllerCreated: ptr.To(true)}) + s.SetVPCSubnetStatus(*subnet.Name, infrav1beta2.ResourceReference{ID: subnetID, ControllerCreated: ptr.To(true)}) return true, nil } return false, nil } -// checkVPCSubnet checks VPC subnet exist in cloud. +// checkVPCSubnet checks if VPC subnet by the given name exists in cloud. func (s *PowerVSClusterScope) checkVPCSubnet(subnetName string) (string, error) { vpcSubnet, err := s.IBMVPCClient.GetVPCSubnetByName(subnetName) if err != nil { @@ -1262,7 +1264,7 @@ func (s *PowerVSClusterScope) ReconcileVPCSecurityGroups() error { } if sg != nil { s.V(3).Info("VPC security group already exists", "name", *sg.Name) - s.SetVPCSecurityGroup(*sg.Name, infrav1beta2.VPCSecurityGroupStatus{ + s.SetVPCSecurityGroupStatus(*sg.Name, infrav1beta2.VPCSecurityGroupStatus{ ID: sg.ID, RuleIDs: ruleIDs, ControllerCreated: ptr.To(false), @@ -1275,7 +1277,7 @@ func (s *PowerVSClusterScope) ReconcileVPCSecurityGroups() error { return fmt.Errorf("failed to create VPC security group: %w", err) } s.Info("VPC security group created", "name", *securityGroup.Name) - s.SetVPCSecurityGroup(*securityGroup.Name, infrav1beta2.VPCSecurityGroupStatus{ + s.SetVPCSecurityGroupStatus(*securityGroup.Name, infrav1beta2.VPCSecurityGroupStatus{ ID: securityGroupID, ControllerCreated: ptr.To(true), }) @@ -1414,7 +1416,7 @@ func (s *PowerVSClusterScope) createVPCSecurityGroupRulesAndSetStatus(ogSecurity } s.Info("VPC security group rules created", "security group name", *securityGroupName) - s.SetVPCSecurityGroup(*securityGroupName, infrav1beta2.VPCSecurityGroupStatus{ + s.SetVPCSecurityGroupStatus(*securityGroupName, infrav1beta2.VPCSecurityGroupStatus{ ID: securityGroupID, RuleIDs: ruleIDs, ControllerCreated: ptr.To(true), @@ -1769,7 +1771,6 @@ func (s *PowerVSClusterScope) checkTransitGatewayConnectionStatus(con tgapiv1.Tr s.V(3).Info("Checking the status of transit gateway connection", "name", *con.Name) switch *con.Status { case string(infrav1beta2.TransitGatewayConnectionStateAttached): - s.V(3).Info("Transit gateway connection is in attached state") return false, nil case string(infrav1beta2.TransitGatewayConnectionStateFailed): return false, fmt.Errorf("failed to attach connection to transit gateway, current status: %s", *con.Status) @@ -1791,6 +1792,10 @@ func (s *PowerVSClusterScope) createTransitGateway() (*string, error) { return nil, fmt.Errorf("failed to fetch resource group ID for resource group %v, ID is empty", s.ResourceGroup()) } + if s.IBMPowerVSCluster.Status.ServiceInstance == nil || s.IBMPowerVSCluster.Status.VPC == nil { + return nil, fmt.Errorf("failed to proeceed with transit gateway creation as either one of VPC or PowerVS service instance reconciliation is not successful") + } + location, globalRouting, err := genUtil.GetTransitGatewayLocationAndRouting(s.Zone(), s.VPC().Region) if err != nil { return nil, fmt.Errorf("failed to get transit gateway location and routing: %w", err) @@ -1798,11 +1803,11 @@ func (s *PowerVSClusterScope) createTransitGateway() (*string, error) { // throw error when user tries to use local routing where global routing is required. // TODO: Add a webhook validation for below condition. - if s.IBMPowerVSCluster.Spec.TransitGateway.GlobalRouting != nil && !*s.IBMPowerVSCluster.Spec.TransitGateway.GlobalRouting && *globalRouting { + if s.IBMPowerVSCluster.Spec.TransitGateway != nil && s.IBMPowerVSCluster.Spec.TransitGateway.GlobalRouting != nil && !*s.IBMPowerVSCluster.Spec.TransitGateway.GlobalRouting && *globalRouting { return nil, fmt.Errorf("failed to use local routing for transit gateway since powervs and vpc are in different region and requires global routing") } // setting global routing to true when it is set by user. - if s.IBMPowerVSCluster.Spec.TransitGateway.GlobalRouting != nil && *s.IBMPowerVSCluster.Spec.TransitGateway.GlobalRouting { + if s.IBMPowerVSCluster.Spec.TransitGateway != nil && s.IBMPowerVSCluster.Spec.TransitGateway.GlobalRouting != nil && *s.IBMPowerVSCluster.Spec.TransitGateway.GlobalRouting { globalRouting = ptr.To(true) } @@ -1858,7 +1863,7 @@ func (s *PowerVSClusterScope) ReconcileLoadBalancers() (bool, error) { loadBalancers = append(loadBalancers, loadBalancer) } for index, loadBalancer := range s.IBMPowerVSCluster.Spec.LoadBalancers { - if loadBalancer.Name == "" { + if loadBalancer.ID == nil && loadBalancer.Name == "" { loadBalancer.Name = fmt.Sprintf("%s-%d", *s.GetServiceName(infrav1beta2.ResourceTypeLoadBalancer), index) } loadBalancers = append(loadBalancers, loadBalancer) @@ -1899,6 +1904,7 @@ func (s *PowerVSClusterScope) ReconcileLoadBalancers() (bool, error) { return false, err } if loadBalancerStatus != nil { + s.V(3).Info("Found VPC load balancer in IBM Cloud", "id", *loadBalancerStatus.ID) s.SetLoadBalancerStatus(loadBalancer.Name, *loadBalancerStatus) continue } @@ -1949,7 +1955,7 @@ func (s *PowerVSClusterScope) checkLoadBalancerPort(lb infrav1beta2.VPCLoadBalan return nil } -// checkLoadBalancer checks loadBalancer in cloud. +// checkLoadBalancer checks if VPC load balancer by the given name exists in cloud. func (s *PowerVSClusterScope) checkLoadBalancer(lb infrav1beta2.VPCLoadBalancerSpec) (*infrav1beta2.VPCLoadBalancerStatus, error) { loadBalancer, err := s.IBMVPCClient.GetLoadBalancerByName(lb.Name) if err != nil { @@ -2247,7 +2253,9 @@ func (s *PowerVSClusterScope) fetchResourceGroupID() (string, error) { func (s *PowerVSClusterScope) fetchVPCCRN() (*string, error) { vpcID := s.GetVPCID() if vpcID == nil { - return nil, fmt.Errorf("VPC ID is empty") + if s.IBMPowerVSCluster.Spec.VPC != nil && s.IBMPowerVSCluster.Spec.VPC.ID != nil { + vpcID = s.IBMPowerVSCluster.Spec.VPC.ID + } } vpcDetails, _, err := s.IBMVPCClient.GetVPC(&vpcv1.GetVPCOptions{ ID: vpcID, @@ -2261,6 +2269,13 @@ func (s *PowerVSClusterScope) fetchVPCCRN() (*string, error) { // fetchPowerVSServiceInstanceCRN returns Power VS service instance CRN. func (s *PowerVSClusterScope) fetchPowerVSServiceInstanceCRN() (*string, error) { serviceInstanceID := s.GetServiceInstanceID() + if serviceInstanceID == "" { + if s.IBMPowerVSCluster.Spec.ServiceInstanceID != "" { + serviceInstanceID = s.IBMPowerVSCluster.Spec.ServiceInstanceID + } else if s.IBMPowerVSCluster.Spec.ServiceInstance != nil && s.IBMPowerVSCluster.Spec.ServiceInstance.ID != nil { + serviceInstanceID = *s.IBMPowerVSCluster.Spec.ServiceInstance.ID + } + } pvsDetails, _, err := s.ResourceClient.GetResourceInstance(&resourcecontrollerv2.GetResourceInstanceOptions{ ID: &serviceInstanceID, }) diff --git a/controllers/ibmpowervscluster_controller.go b/controllers/ibmpowervscluster_controller.go index ec7d385e99..eac48c112a 100644 --- a/controllers/ibmpowervscluster_controller.go +++ b/controllers/ibmpowervscluster_controller.go @@ -331,7 +331,11 @@ func (r *IBMPowerVSClusterReconciler) reconcile(clusterScope *scope.PowerVSClust } // update cluster object with loadbalancer host - loadBalancer := clusterScope.PublicLoadBalancer() + loadBalancer, err := clusterScope.PublicLoadBalancer() + if err != nil { + return reconcile.Result{}, fmt.Errorf("failed to fetch public loadbalancer: %w", err) + } + if loadBalancer == nil { return reconcile.Result{}, fmt.Errorf("failed to fetch public loadbalancer") }