diff --git a/api/v1beta2/ibmpowervscluster_types.go b/api/v1beta2/ibmpowervscluster_types.go index 659e8f2b4..6b11e792e 100644 --- a/api/v1beta2/ibmpowervscluster_types.go +++ b/api/v1beta2/ibmpowervscluster_types.go @@ -65,6 +65,7 @@ type IBMPowerVSClusterSpec struct { // when omitted system will dynamically create the service instance with name CLUSTER_NAME-serviceInstance. // when ServiceInstance.ID is set, its expected that there exist a service instance in PowerVS workspace with id or else system will give error. // when ServiceInstance.Name is set, system will first check for service instance with Name in PowerVS workspace, if not exist system will create new instance. + // if there are more than one service instance exist with the ServiceInstance.Name in given Zone, installation fails with an error. Use ServiceInstance.ID in those situations to use the specific service instance. // ServiceInstance.Regex is not yet supported not yet supported and system will ignore the value. // +optional ServiceInstance *IBMPowerVSResourceReference `json:"serviceInstance,omitempty"` diff --git a/cloud/scope/powervs_cluster.go b/cloud/scope/powervs_cluster.go index b7cc7dc01..57e616c14 100644 --- a/cloud/scope/powervs_cluster.go +++ b/cloud/scope/powervs_cluster.go @@ -757,7 +757,7 @@ func (s *PowerVSClusterScope) isServiceInstanceExists() (string, bool, error) { // getServiceInstance return resource instance by name. func (s *PowerVSClusterScope) getServiceInstance() (*resourcecontrollerv2.ResourceInstance, error) { //TODO: Support regular expression - return s.ResourceClient.GetServiceInstance("", *s.GetServiceName(infrav1beta2.ResourceTypeServiceInstance)) + return s.ResourceClient.GetServiceInstance("", *s.GetServiceName(infrav1beta2.ResourceTypeServiceInstance), s.IBMPowerVSCluster.Spec.Zone) } // createServiceInstance creates the service instance. diff --git a/cloud/scope/powervs_image.go b/cloud/scope/powervs_image.go index 485aa1ecb..2fc28a67b 100644 --- a/cloud/scope/powervs_image.go +++ b/cloud/scope/powervs_image.go @@ -50,6 +50,7 @@ type PowerVSImageScopeParams struct { Logger logr.Logger IBMPowerVSImage *infrav1beta2.IBMPowerVSImage ServiceEndpoint []endpoints.ServiceEndpoint + Zone *string } // PowerVSImageScope defines a scope defined around a Power VS Cluster. @@ -116,7 +117,7 @@ func NewPowerVSImageScope(params PowerVSImageScopeParams) (scope *PowerVSImageSc if params.IBMPowerVSImage.Spec.ServiceInstance != nil && params.IBMPowerVSImage.Spec.ServiceInstance.Name != nil { name = *params.IBMPowerVSImage.Spec.ServiceInstance.Name } - serviceInstance, err := rc.GetServiceInstance("", name) + serviceInstance, err := rc.GetServiceInstance("", name, params.Zone) if err != nil { params.Logger.Error(err, "error failed to get service instance id from name", "name", name) return nil, err diff --git a/cloud/scope/powervs_machine.go b/cloud/scope/powervs_machine.go index f423f8c07..6f70a950f 100644 --- a/cloud/scope/powervs_machine.go +++ b/cloud/scope/powervs_machine.go @@ -180,7 +180,7 @@ func NewPowerVSMachineScope(params PowerVSMachineScopeParams) (scope *PowerVSMac serviceInstanceName = *params.IBMPowerVSCluster.Spec.ServiceInstance.Name } } - serviceInstance, err := rc.GetServiceInstance(serviceInstanceID, serviceInstanceName) + serviceInstance, err := rc.GetServiceInstance(serviceInstanceID, serviceInstanceName, params.IBMPowerVSCluster.Spec.Zone) if err != nil { params.Logger.Error(err, "failed to get PowerVS service instance details", "name", serviceInstanceName, "id", serviceInstanceID) return nil, err diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclusters.yaml index 9bf01cd19..eddf3c70c 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclusters.yaml @@ -366,6 +366,7 @@ spec: when omitted system will dynamically create the service instance with name CLUSTER_NAME-serviceInstance. when ServiceInstance.ID is set, its expected that there exist a service instance in PowerVS workspace with id or else system will give error. when ServiceInstance.Name is set, system will first check for service instance with Name in PowerVS workspace, if not exist system will create new instance. + if there are more than one service instance exist with the ServiceInstance.Name in given Zone, installation fails with an error. Use ServiceInstance.ID in those situations to use the specific service instance. ServiceInstance.Regex is not yet supported not yet supported and system will ignore the value. properties: id: diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclustertemplates.yaml index 9d1b390f6..183db4202 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclustertemplates.yaml @@ -397,6 +397,7 @@ spec: when omitted system will dynamically create the service instance with name CLUSTER_NAME-serviceInstance. when ServiceInstance.ID is set, its expected that there exist a service instance in PowerVS workspace with id or else system will give error. when ServiceInstance.Name is set, system will first check for service instance with Name in PowerVS workspace, if not exist system will create new instance. + if there are more than one service instance exist with the ServiceInstance.Name in given Zone, installation fails with an error. Use ServiceInstance.ID in those situations to use the specific service instance. ServiceInstance.Regex is not yet supported not yet supported and system will ignore the value. properties: id: diff --git a/controllers/ibmpowervsimage_controller.go b/controllers/ibmpowervsimage_controller.go index a1fbe81e6..3c037a9fa 100644 --- a/controllers/ibmpowervsimage_controller.go +++ b/controllers/ibmpowervsimage_controller.go @@ -66,11 +66,17 @@ func (r *IBMPowerVSImageReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, err } + cluster, err := scope.GetClusterByName(ctx, r.Client, ibmImage.Namespace, ibmImage.Spec.ClusterName) + if err != nil { + return ctrl.Result{}, err + } + // Create the scope. imageScope, err := scope.NewPowerVSImageScope(scope.PowerVSImageScopeParams{ Client: r.Client, Logger: log, IBMPowerVSImage: ibmImage, + Zone: cluster.Spec.Zone, ServiceEndpoint: r.ServiceEndpoint, }) if err != nil { @@ -91,10 +97,6 @@ func (r *IBMPowerVSImageReconciler) Reconcile(ctx context.Context, req ctrl.Requ return r.reconcileDelete(imageScope) } - cluster, err := scope.GetClusterByName(ctx, r.Client, ibmImage.Namespace, ibmImage.Spec.ClusterName) - if err != nil { - return ctrl.Result{}, err - } return r.reconcile(cluster, imageScope) } diff --git a/pkg/cloud/services/resourcecontroller/resourcecontroller.go b/pkg/cloud/services/resourcecontroller/resourcecontroller.go index d5d98f4ad..fe8f8966d 100644 --- a/pkg/cloud/services/resourcecontroller/resourcecontroller.go +++ b/pkg/cloud/services/resourcecontroller/resourcecontroller.go @@ -27,7 +27,7 @@ type ResourceController interface { ListResourceInstances(listResourceInstancesOptions *resourcecontrollerv2.ListResourceInstancesOptions) (result *resourcecontrollerv2.ResourceInstancesList, response *core.DetailedResponse, err error) GetResourceInstance(*resourcecontrollerv2.GetResourceInstanceOptions) (*resourcecontrollerv2.ResourceInstance, *core.DetailedResponse, error) CreateResourceInstance(*resourcecontrollerv2.CreateResourceInstanceOptions) (*resourcecontrollerv2.ResourceInstance, *core.DetailedResponse, error) - GetServiceInstance(string, string) (*resourcecontrollerv2.ResourceInstance, error) + GetServiceInstance(string, string, *string) (*resourcecontrollerv2.ResourceInstance, error) DeleteResourceInstance(*resourcecontrollerv2.DeleteResourceInstanceOptions) (*core.DetailedResponse, error) GetInstanceByName(string, string, string) (*resourcecontrollerv2.ResourceInstance, error) diff --git a/pkg/cloud/services/resourcecontroller/service.go b/pkg/cloud/services/resourcecontroller/service.go index 09b333f1c..df67ac7c0 100644 --- a/pkg/cloud/services/resourcecontroller/service.go +++ b/pkg/cloud/services/resourcecontroller/service.go @@ -88,7 +88,7 @@ func (s *Service) DeleteResourceInstance(options *resourcecontrollerv2.DeleteRes // GetServiceInstance returns service instance with given name or id. If not found, returns nil. // TODO: Combine GetSreviceInstance() and GetInstanceByName(). -func (s *Service) GetServiceInstance(id, name string) (*resourcecontrollerv2.ResourceInstance, error) { +func (s *Service) GetServiceInstance(id, name string, zone *string) (*resourcecontrollerv2.ResourceInstance, error) { var serviceInstancesList []resourcecontrollerv2.ResourceInstance f := func(start string) (bool, string, error) { listServiceInstanceOptions := &resourcecontrollerv2.ListResourceInstancesOptions{ @@ -110,7 +110,16 @@ func (s *Service) GetServiceInstance(id, name string) (*resourcecontrollerv2.Res return false, "", err } if serviceInstances != nil { - serviceInstancesList = append(serviceInstancesList, serviceInstances.Resources...) + if zone != nil && *zone != "" { + for _, resource := range serviceInstances.Resources { + if *resource.RegionID == *zone { + serviceInstancesList = append(serviceInstancesList, resource) + } + } + } else { + serviceInstancesList = append(serviceInstancesList, serviceInstances.Resources...) + } + nextURL, err := serviceInstances.GetNextStart() if err != nil { return false, "", err