diff --git a/api/v1beta2/ibmpowervscluster_types.go b/api/v1beta2/ibmpowervscluster_types.go index 07f875b8a..dded18652 100644 --- a/api/v1beta2/ibmpowervscluster_types.go +++ b/api/v1beta2/ibmpowervscluster_types.go @@ -220,6 +220,7 @@ func (r *IBMPowerVSCluster) SetConditions(conditions capiv1beta1.Conditions) { r.Status.Conditions = conditions } +// Set sets the details of the resource. func (rf *ResourceReference) Set(resource ResourceReference) { rf.ID = resource.ID if !*rf.ControllerCreated { diff --git a/cloud/scope/powervs_cluster.go b/cloud/scope/powervs_cluster.go index 59cee7316..c040847ac 100644 --- a/cloud/scope/powervs_cluster.go +++ b/cloud/scope/powervs_cluster.go @@ -22,6 +22,8 @@ import ( "fmt" "strings" + "github.com/go-logr/logr" + "github.com/IBM-Cloud/power-go-client/ibmpisession" "github.com/IBM-Cloud/power-go-client/power/models" "github.com/IBM/go-sdk-core/v5/core" @@ -31,12 +33,10 @@ import ( "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" "github.com/IBM/platform-services-go-sdk/resourcemanagerv2" "github.com/IBM/vpc-go-sdk/vpcv1" - "github.com/go-logr/logr" - "k8s.io/klog/v2/klogr" - "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/cos" - "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/globalcatalog" + "k8s.io/klog/v2/klogr" "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" @@ -45,6 +45,8 @@ import ( infrav1beta2 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta2" "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/cos" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/globalcatalog" "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/powervs" "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/resourcecontroller" "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/transitgateway" @@ -57,28 +59,21 @@ import ( const ( // DEBUGLEVEL indicates the debug level of the logs. DEBUGLEVEL = 5 - // PowerVS service and plan name - powerVSService = "power-iaas" - powerVSServicePlan = "power-virtual-server-group" ) const ( // TODO(karthik-k-n)(Doubt): should this be fetched using global catalogs or hardcode like this? - //powerVSResourceID is Power VS power-iaas service id, can be retrieved using ibmcloud cli - // ibmcloud catalog service power-iaas - powerVSResourceID = "abd259f0-9990-11e8-acc8-b9f54a8f1661" - - //powerVSResourcePlanID is Power VS power-iaas plan id, can be retrieved using ibmcloud cli - // ibmcloud catalog service power-iaas + // powerVSResourcePlanID is Power VS power-iaas plan id, can be retrieved using ibmcloud cli + // ibmcloud catalog service power-iaas. powerVSResourcePlanID = "f165dd34-3a40-423b-9d95-e90a23f724dd" - //cosResourceID is IBM COS service id, can be retrieved using ibmcloud cli - // ibmcloud catalog service cloud-object-storage + // cosResourceID is IBM COS service id, can be retrieved using ibmcloud cli + // ibmcloud catalog service cloud-object-storage. cosResourceID = "dff97f5c-bc5e-4455-b470-411c3edbe49c" - //powerVSResourcePlanID is IBM COS plan id, can be retrieved using ibmcloud cli - // ibmcloud catalog service cloud-object-storage + // powerVSResourcePlanID is IBM COS plan id, can be retrieved using ibmcloud cli + // ibmcloud catalog service cloud-object-storage. cosResourcePlanID = "1e4e33e4-cfa6-4f12-9016-be594a6d5f87" ) @@ -138,7 +133,7 @@ type ClusterObject interface { } // NewPowerVSClusterScope creates a new PowerVSClusterScope from the supplied parameters. -func NewPowerVSClusterScope(params PowerVSClusterScopeParams) (*PowerVSClusterScope, error) { +func NewPowerVSClusterScope(params PowerVSClusterScopeParams) (*PowerVSClusterScope, error) { //nolint:gocyclo if params.Client == nil { err := errors.New("error failed to generate new scope from nil Client") return nil, err @@ -337,7 +332,7 @@ func (s *PowerVSClusterScope) GetServiceInstanceID() string { return "" } -// TODO: Can we use generic here +// TODO: Can we use generic here. // SetStatus set the IBMPowerVSCluster status. func (s *PowerVSClusterScope) SetStatus(resourceType ResourceType, resource infrav1beta2.ResourceReference) { @@ -437,7 +432,7 @@ func (s *PowerVSClusterScope) GetVPCSubnetIDs() []*string { if s.IBMPowerVSCluster.Status.VPCSubnet == nil { return nil } - var subnets []*string + subnets := []*string{} for _, subnet := range s.IBMPowerVSCluster.Status.VPCSubnet { subnets = append(subnets, subnet.ID) } @@ -608,7 +603,7 @@ func (s *PowerVSClusterScope) checkServiceInstance() (string, error) { return *serviceInstance.GUID, nil } -// getServiceInstance return resource instance +// getServiceInstance return resource instance. func (s *PowerVSClusterScope) getServiceInstance() (*resourcecontrollerv2.ResourceInstance, error) { //TODO: Support regular expression return s.ResourceClient.GetServiceInstance("", *s.GetServiceName(ServiceInstance)) @@ -623,8 +618,8 @@ func (s *PowerVSClusterScope) createServiceInstance() (*resourcecontrollerv2.Res } // TODO: Do we need to fetch or hardcode - //_, servicePlanID, err := s.CatalogClient.GetServiceInfo(powerVSService, powerVSServicePlan) - //if err != nil { + // _, servicePlanID, err := s.CatalogClient.GetServiceInfo(powerVSService, powerVSServicePlan) + // if err != nil { // return nil, fmt.Errorf("error retrieving id info for powervs service %w", err) //} @@ -750,11 +745,10 @@ func (s *PowerVSClusterScope) createDHCPServer() (*string, error) { } if dhcpServer.Network == nil { return nil, fmt.Errorf("created dhcp server network is nil") - } else { - s.Info("DHCP Server network details", "details", *dhcpServer.Network) - s.SetStatus(Network, infrav1beta2.ResourceReference{ID: dhcpServer.Network.ID, ControllerCreated: pointer.Bool(true)}) } + s.Info("DHCP Server network details", "details", *dhcpServer.Network) + s.SetStatus(Network, infrav1beta2.ResourceReference{ID: dhcpServer.Network.ID, ControllerCreated: pointer.Bool(true)}) return dhcpServer.ID, nil } @@ -774,17 +768,17 @@ func (s *PowerVSClusterScope) ReconcileVPC() error { return fmt.Errorf("error failed to get vpc with id %s", *vpcID) } s.Info("Found VPC with provided id") - //TODO(karthik-k-n): Set status here as well + // TODO(karthik-k-n): Set status here as well return nil } // check vpc exist in cloud - vpcId, err := s.checkVPC() + id, err := s.checkVPC() if err != nil { return err } - if vpcId != "" { - s.SetStatus(VPC, infrav1beta2.ResourceReference{ID: &vpcId, ControllerCreated: pointer.Bool(false)}) + if id != "" { + s.SetStatus(VPC, infrav1beta2.ResourceReference{ID: &id, ControllerCreated: pointer.Bool(false)}) return nil } @@ -941,7 +935,7 @@ func (s *PowerVSClusterScope) createVPCSubnet(subnet infrav1beta2.Subnet) (*stri return nil, err } // TODO(karthik-k-n): Decide on using all zones or using one zone - if vpcZones == nil || len(vpcZones) == 0 { + if len(vpcZones) == 0 { return nil, fmt.Errorf("error getting vpc zones error: %v", err) } zone = vpcZones[0] @@ -1214,9 +1208,9 @@ func (s *PowerVSClusterScope) createLoadBalancer(lb infrav1beta2.VPCLoadBalancer if subnetIds == nil { return nil, fmt.Errorf("error subnet required for load balancer creation") } - for _, subnetId := range subnetIds { + for _, subnetID := range subnetIds { subnet := &vpcv1.SubnetIdentity{ - ID: subnetId, + ID: subnetID, } options.Subnets = append(options.Subnets, subnet) } @@ -1273,6 +1267,7 @@ func (s *PowerVSClusterScope) createLoadBalancer(lb infrav1beta2.VPCLoadBalancer }, nil } +// COSInstance returns the COS instance reference. func (s *PowerVSClusterScope) COSInstance() *infrav1beta2.CosInstance { return s.IBMPowerVSCluster.Spec.CosInstance } @@ -1308,7 +1303,7 @@ func (s *PowerVSClusterScope) ReconcileCOSInstance() error { } apiKey := props["APIKEY"] - if len(apiKey) == 0 { + if apiKey == "" { fmt.Printf("ibmcloud api key is not provided, set %s environmental variable", "IBMCLOUD_API_KEY") } @@ -1400,9 +1395,9 @@ func (s *PowerVSClusterScope) createCOSServiceInstance() (*resourcecontrollerv2. return nil, fmt.Errorf("error getting id for resource group %s, %w", *s.ResourceGroup(), err) } - //TODO(karthik-k-n)(Doubt): should this be fetched or hardcoded - //_, servicePlanID, err := s.CatalogClient.GetServiceInfo(powerVSService, powerVSServicePlan) - //if err != nil { + // TODO(karthik-k-n)(Doubt): should this be fetched or hardcoded + // _, servicePlanID, err := s.CatalogClient.GetServiceInfo(powerVSService, powerVSServicePlan) + // if err != nil { // return nil, fmt.Errorf("error retrieving id info for powervs service %w", err) //} @@ -1466,7 +1461,7 @@ func (s *PowerVSClusterScope) getVPCRegion() *string { return &vpcRegion } -// fetchVPCCRN returns VPC CRN +// fetchVPCCRN returns VPC CRN. func (s *PowerVSClusterScope) fetchVPCCRN() (*string, error) { vpcDetails, _, err := s.IBMVPCClient.GetVPC(&vpcv1.GetVPCOptions{ ID: s.GetVPCID(), @@ -1489,7 +1484,7 @@ func (s *PowerVSClusterScope) fetchPowerVSServiceInstanceCRN() (*string, error) return pvsDetails.CRN, nil } -// TODO(karthik-k-n): Decide on proper naming format for services +// TODO(karthik-k-n): Decide on proper naming format for services. // GetServiceName returns name of given service type from spec or generate a name for it. func (s *PowerVSClusterScope) GetServiceName(resourceType ResourceType) *string { @@ -1556,7 +1551,6 @@ func (s *PowerVSClusterScope) DeleteLoadBalancer() error { } } } - return nil } @@ -1567,28 +1561,29 @@ func (s *PowerVSClusterScope) DeleteVPCSubnet() error { } for _, subnet := range s.IBMPowerVSCluster.Status.VPCSubnet { - if subnet.ID != nil { - net, _, err := s.IBMVPCClient.GetSubnet(&vpcv1.GetSubnetOptions{ - ID: subnet.ID, - }) + if subnet.ID == nil { + continue + } - if err != nil { - if strings.Contains(err.Error(), "Subnet not found") { - return nil - } - return fmt.Errorf("error fetching the subnet: %w", err) - } + net, _, err := s.IBMVPCClient.GetSubnet(&vpcv1.GetSubnetOptions{ + ID: subnet.ID, + }) - _, err = s.IBMVPCClient.DeleteSubnet(&vpcv1.DeleteSubnetOptions{ - ID: net.ID, - }) - if err != nil { - return fmt.Errorf("error deleting VPC subnet: %w", err) + if err != nil { + if strings.Contains(err.Error(), "Subnet not found") { + return nil } - s.Info("VPC subnet successfully deleted") + return fmt.Errorf("error fetching the subnet: %w", err) } - } + _, err = s.IBMVPCClient.DeleteSubnet(&vpcv1.DeleteSubnetOptions{ + ID: net.ID, + }) + if err != nil { + return fmt.Errorf("error deleting VPC subnet: %w", err) + } + s.Info("VPC subnet successfully deleted") + } return nil } @@ -1618,7 +1613,6 @@ func (s *PowerVSClusterScope) DeleteVPC() error { } s.Info("VPC successfully deleted") } - return nil } @@ -1670,7 +1664,6 @@ func (s *PowerVSClusterScope) DeleteTransitGateway() error { } s.Info("Transit gateway successfully deleted") } - return nil } @@ -1695,7 +1688,6 @@ func (s *PowerVSClusterScope) DeleteDHCPServer() error { } s.Info("DHCP server successfully deleted") } - return nil } @@ -1722,9 +1714,8 @@ func (s *PowerVSClusterScope) DeleteServiceInstance() error { return fmt.Errorf("error fetching networks in the service instance: %w", err) } - if servers != nil && len(servers) > 0 { + if len(servers) > 0 { return fmt.Errorf("cannot delete service instance as network is not yet deleted") - } _, err = s.ResourceClient.DeleteResourceInstance(&resourcecontrollerv2.DeleteResourceInstanceOptions{ @@ -1739,10 +1730,9 @@ func (s *PowerVSClusterScope) DeleteServiceInstance() error { s.Info("Service instance successfully deleted") } return nil - } -// DeleteServiceInstance deletes COS instance. +// DeleteCosInstance deletes COS instance. func (s *PowerVSClusterScope) DeleteCosInstance() error { if !s.deleteResource(COSInstance) { return nil @@ -1773,12 +1763,11 @@ func (s *PowerVSClusterScope) DeleteCosInstance() error { } s.Info("COS instance successfully deleted") } - return nil } // deleteResource returns true or false to decide on deleting provided resource. -func (s *PowerVSClusterScope) deleteResource(resourceType ResourceType) bool { +func (s *PowerVSClusterScope) deleteResource(resourceType ResourceType) bool { //nolint:gocyclo switch resourceType { case LoadBalancer: lbs := s.IBMPowerVSCluster.Status.LoadBalancers diff --git a/cloud/scope/powervs_cluster_test.go b/cloud/scope/powervs_cluster_test.go index 7cbbbdaf5..861d7604e 100644 --- a/cloud/scope/powervs_cluster_test.go +++ b/cloud/scope/powervs_cluster_test.go @@ -56,7 +56,7 @@ func TestNewPowerVSClusterScope(t *testing.T) { // Cluster: newCluster(clusterName), // IBMPowerVSCluster: newPowerVSCluster(clusterName), // }, - //}, + // }, } for _, tc := range testCases { g := NewWithT(t) diff --git a/cloud/scope/powervs_image.go b/cloud/scope/powervs_image.go index d7c6078b8..bc6e506fd 100644 --- a/cloud/scope/powervs_image.go +++ b/cloud/scope/powervs_image.go @@ -29,6 +29,7 @@ import ( "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" "k8s.io/klog/v2/klogr" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/cluster-api/util/patch" @@ -120,7 +121,7 @@ func NewPowerVSImageScope(params PowerVSImageScopeParams) (scope *PowerVSImageSc if serviceInstance == nil { return nil, fmt.Errorf("service instance %s is not yet created", name) } - if *serviceInstance.State != "active" { + if *serviceInstance.State != string(infrav1beta2.ServiceInstanceStateActive) { return nil, fmt.Errorf("service instance %s is not in active state", name) } serviceInstanceID = *serviceInstance.GUID diff --git a/cloud/scope/powervs_machine.go b/cloud/scope/powervs_machine.go index d54f8eec6..df1eb5e64 100644 --- a/cloud/scope/powervs_machine.go +++ b/cloud/scope/powervs_machine.go @@ -47,6 +47,7 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/klog/v2/klogr" "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" @@ -98,7 +99,7 @@ type PowerVSMachineScope struct { } // NewPowerVSMachineScope creates a new PowerVSMachineScope from the supplied parameters. -func NewPowerVSMachineScope(params PowerVSMachineScopeParams) (scope *PowerVSMachineScope, err error) { +func NewPowerVSMachineScope(params PowerVSMachineScopeParams) (scope *PowerVSMachineScope, err error) { //nolint:gocyclo scope = &PowerVSMachineScope{} if params.Client == nil { @@ -259,7 +260,7 @@ func (m *PowerVSMachineScope) CreateMachine() (*models.PVMInstanceReference, err } } - //TODO(karthik-k-n): Fix this + // TODO(karthik-k-n): Fix this userData, userDataErr := m.resolveUserData() if userDataErr != nil { return nil, fmt.Errorf("error failed to resolve userdata %w", userDataErr) @@ -397,7 +398,6 @@ func (m *PowerVSMachineScope) createIgnitionData(data []byte) (string, error) { } if exp := m.IBMPowerVSCluster.Spec.CosInstance.PresignedURLDuration; exp != nil { - m.Info("assigning presigned url", "exp", exp) req, _ := cosClient.GetObjectRequest(&s3.GetObjectInput{ Bucket: aws.String(bucket), @@ -413,7 +413,6 @@ func (m *PowerVSMachineScope) createIgnitionData(data []byte) (string, error) { } return objectURL.String(), nil - } func (m *PowerVSMachineScope) ignitionUserData(userData []byte) ([]byte, error) { @@ -461,6 +460,7 @@ func (m *PowerVSMachineScope) ignitionUserData(userData []byte) ([]byte, error) } } +// UseIgnition returns true if user data format is of type 'ignition', else returns false. func (m *PowerVSMachineScope) UseIgnition(userDataFormat string) bool { return userDataFormat == "ignition" || (m.IBMPowerVSMachine.Spec.Ignition != nil) } @@ -537,7 +537,7 @@ func (m *PowerVSMachineScope) createCOSClient() (*cos.Service, error) { return nil, fmt.Errorf("error while fetching service properties: %w", err) } apiKey := props["APIKEY"] - if len(apiKey) == 0 { + if apiKey == "" { fmt.Printf("ibmcloud api key is not provided, set %s environmental variable", "IBMCLOUD_API_KEY") } @@ -550,6 +550,7 @@ func (m *PowerVSMachineScope) createCOSClient() (*cos.Service, error) { return cosClient, nil } +// GetRawBootstrapDataWithFormat returns the bootstrap data if present. func (m *PowerVSMachineScope) GetRawBootstrapDataWithFormat() ([]byte, string, error) { if m.Machine.Spec.Bootstrap.DataSecretName == nil { return nil, "", errors.New("error retrieving bootstrap data: linked Machine's bootstrap.dataSecretName is nil") @@ -862,6 +863,7 @@ func (m *PowerVSMachineScope) SetProviderID(id *string) { } } +// GetMachineInternalIP returns the machine's internal IP. func (m *PowerVSMachineScope) GetMachineInternalIP() string { for _, address := range m.IBMPowerVSMachine.Status.Addresses { if address.Type == corev1.NodeInternalIP { @@ -871,6 +873,7 @@ func (m *PowerVSMachineScope) GetMachineInternalIP() string { return "" } +// CreateVPCLoadBalancerPoolMember creates a member in load balaner pool. func (m *PowerVSMachineScope) CreateVPCLoadBalancerPoolMember() (*vpcv1.LoadBalancerPoolMember, error) { for _, lb := range m.IBMPowerVSCluster.Spec.LoadBalancers { var lbID *string @@ -950,7 +953,7 @@ func (m *PowerVSMachineScope) CreateVPCLoadBalancerPoolMember() (*vpcv1.LoadBala } if *loadBalancer.ProvisioningStatus != string(infrav1beta2.VPCLoadBalancerStateActive) { m.Info("Not able to update pool for loadBalancer , load balancer is not in active state", "loadbalancer", *loadBalancer.Name, "state", *loadBalancer.ProvisioningStatus) - return nil, fmt.Errorf("loadbalancer %s not in active state to update pool memeber", *loadBalancer.Name) + return nil, fmt.Errorf("loadbalancer %s not in active state to update pool member", *loadBalancer.Name) } options := &vpcv1.CreateLoadBalancerPoolMemberOptions{} diff --git a/cloud/scope/powervs_machine_test.go b/cloud/scope/powervs_machine_test.go index 00788954a..7da89d0ee 100644 --- a/cloud/scope/powervs_machine_test.go +++ b/cloud/scope/powervs_machine_test.go @@ -377,15 +377,15 @@ func TestCreateMachinePVS(t *testing.T) { g.Expect(err).To((Not(BeNil()))) }) - //t.Run("Error when both Network id and name are nil", func(t *testing.T) { - // g := NewWithT(t) - // setup(t) - // t.Cleanup(teardown) - // scope := setupPowerVSMachineScope(clusterName, machineName, core.StringPtr(pvsImage), nil, true, mockpowervs) - // mockpowervs.EXPECT().GetAllInstance().Return(pvmInstances, nil) - // _, err := scope.CreateMachine() - // g.Expect(err).To((Not(BeNil()))) - //}) + t.Run("Error when both Network id and name are nil", func(t *testing.T) { + g := NewWithT(t) + setup(t) + t.Cleanup(teardown) + scope := setupPowerVSMachineScope(clusterName, machineName, core.StringPtr(pvsImage), nil, true, mockpowervs) + mockpowervs.EXPECT().GetAllInstance().Return(pvmInstances, nil) + _, err := scope.CreateMachine() + g.Expect(err).To((Not(BeNil()))) + }) t.Run("Error when Image id does not exsist", func(t *testing.T) { g := NewWithT(t) diff --git a/controllers/ibmpowervscluster_controller.go b/controllers/ibmpowervscluster_controller.go index 96c7fe008..8e4083fac 100644 --- a/controllers/ibmpowervscluster_controller.go +++ b/controllers/ibmpowervscluster_controller.go @@ -23,12 +23,14 @@ import ( "time" "github.com/pkg/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" kerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/client-go/tools/record" "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -110,7 +112,7 @@ func (r *IBMPowerVSClusterReconciler) Reconcile(ctx context.Context, req ctrl.Re return r.reconcile(clusterScope) } -func (r *IBMPowerVSClusterReconciler) reconcile(clusterScope *scope.PowerVSClusterScope) (ctrl.Result, error) { //nolint:unparam +func (r *IBMPowerVSClusterReconciler) reconcile(clusterScope *scope.PowerVSClusterScope) (ctrl.Result, error) { if controllerutil.AddFinalizer(clusterScope.IBMPowerVSCluster, infrav1beta2.IBMPowerVSClusterFinalizer) { return ctrl.Result{}, nil } diff --git a/main.go b/main.go index 93679fa1c..215973b4a 100644 --- a/main.go +++ b/main.go @@ -21,7 +21,6 @@ import ( "flag" "fmt" "os" - "sigs.k8s.io/controller-runtime/pkg/webhook" "time" // +kubebuilder:scaffold:imports @@ -35,6 +34,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/webhook" capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/cluster-api/util/flags" diff --git a/pkg/cloud/services/cos/service.go b/pkg/cloud/services/cos/service.go index f6c09e864..ae949e685 100644 --- a/pkg/cloud/services/cos/service.go +++ b/pkg/cloud/services/cos/service.go @@ -32,6 +32,7 @@ import ( "github.com/IBM/ibm-cos-sdk-go/service/s3" ) +// IAMEndpoint represent the IAM authorisation URL. const IAMEndpoint = "https://iam.cloud.ibm.com/identity/token" // Service holds the IBM Cloud Resource Controller Service specific information. @@ -44,6 +45,7 @@ type ServiceOptions struct { *cosSession.Options } +// GetBucketByName returns a bucket with the given name. func (s *Service) GetBucketByName(name string) (*s3.HeadBucketOutput, error) { input := &s3.HeadBucketInput{ Bucket: &name, @@ -51,43 +53,50 @@ func (s *Service) GetBucketByName(name string) (*s3.HeadBucketOutput, error) { return s.client.HeadBucket(input) } +// CreateBucket creates a new bucket in the COS instance. func (s *Service) CreateBucket(input *s3.CreateBucketInput) (*s3.CreateBucketOutput, error) { return s.client.CreateBucket(input) } +// CreateBucketWithContext creates a new bucket with an addition ability to pass context. func (s *Service) CreateBucketWithContext(ctx aws.Context, input *s3.CreateBucketInput, opts ...request.Option) (*s3.CreateBucketOutput, error) { return s.client.CreateBucketWithContext(ctx, input, opts...) } +// PutObject adds an object to a bucket. func (s *Service) PutObject(input *s3.PutObjectInput) (*s3.PutObjectOutput, error) { return s.client.PutObject(input) } +// GetObjectRequest generates a "aws/request.Request" representing the client's request for the GetObject operation. func (s *Service) GetObjectRequest(input *s3.GetObjectInput) (*request.Request, *s3.GetObjectOutput) { return s.client.GetObjectRequest(input) } +// ListObjects returns the list of objects in a bucket. func (s *Service) ListObjects(input *s3.ListObjectsInput) (*s3.ListObjectsOutput, error) { return s.client.ListObjects(input) } +// DeleteObject deletes a object in a bucket. func (s *Service) DeleteObject(input *s3.DeleteObjectInput) (*s3.DeleteObjectOutput, error) { return s.client.DeleteObject(input) } +// PutPublicAccessBlock creates or modifies the PublicAccessBlock configuration for a bucket. func (s *Service) PutPublicAccessBlock(input *s3.PutPublicAccessBlockInput) (*s3.PutPublicAccessBlockOutput, error) { return s.client.PutPublicAccessBlock(input) } // NewService returns a new service for the IBM Cloud Resource Controller api client. -// TODO(karthik-k-n): pass location as a part of options +// TODO(karthik-k-n): pass location as a part of options. func NewService(options ServiceOptions, location, apikey, serviceInstance string) (*Service, error) { if options.Options == nil { options.Options = &cosSession.Options{} } serviceEndpoint := fmt.Sprintf("s3.%s.cloud-object-storage.appdomain.cloud", location) - //TODO(karthik-k-n): handle URL + // TODO(karthik-k-n): handle URL options.Config = aws.Config{ Endpoint: &serviceEndpoint, Region: &location, @@ -114,8 +123,6 @@ func NewService(options ServiceOptions, location, apikey, serviceInstance string // TODO(karthik-k-n): Fix me options.Config.Credentials = ibmiam.NewStaticCredentials(aws.NewConfig(), IAMEndpoint, apikey, serviceInstance) - //options.Config.Credentials = ibmiam.NewEnvCredentials(aws.NewConfig()) - sess, err := cosSession.NewSessionWithOptions(*options.Options) if err != nil { return nil, err diff --git a/pkg/cloud/services/globalcatalog/service.go b/pkg/cloud/services/globalcatalog/service.go index 6b7734d32..51327cfe6 100644 --- a/pkg/cloud/services/globalcatalog/service.go +++ b/pkg/cloud/services/globalcatalog/service.go @@ -18,8 +18,10 @@ package globalcatalog import ( "fmt" + "github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/platform-services-go-sdk/globalcatalogv1" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator" ) @@ -74,23 +76,23 @@ func (s *Service) GetServiceInfo(service string, servicePlan string) (string, st return "", "", fmt.Errorf("could not retrieve service id for service %s", service) } else if servicePlan == "" { return serviceID, "", nil - } else { - kind := "plan" - getChildOpt := globalcatalogv1.GetChildObjectsOptions{ID: &serviceID, Kind: &kind} - var childObjResult *globalcatalogv1.EntrySearchResult - childObjResult, _, err = s.client.GetChildObjects(&getChildOpt) - if err != nil { - return "", "", err - } - for _, plan := range childObjResult.Resources { - if *plan.Name == servicePlan { - servicePlanID = *plan.ID - return serviceID, servicePlanID, nil - } + } + + kind := "plan" + getChildOpt := globalcatalogv1.GetChildObjectsOptions{ID: &serviceID, Kind: &kind} + var childObjResult *globalcatalogv1.EntrySearchResult + childObjResult, _, err = s.client.GetChildObjects(&getChildOpt) + if err != nil { + return "", "", err + } + + for _, plan := range childObjResult.Resources { + if *plan.Name == servicePlan { + servicePlanID = *plan.ID + return serviceID, servicePlanID, nil } } - err = fmt.Errorf("could not retrieve plan id for service name: %s & service plan name: %s", service, servicePlan) - return "", "", err + return "", "", fmt.Errorf("could not retrieve plan id for service name: %s & service plan name: %s", service, servicePlan) } // NewService returns a new service for the IBM Cloud Global catalog api client. diff --git a/pkg/cloud/services/powervs/service.go b/pkg/cloud/services/powervs/service.go index b948fa316..4696d7e16 100644 --- a/pkg/cloud/services/powervs/service.go +++ b/pkg/cloud/services/powervs/service.go @@ -18,30 +18,16 @@ package powervs import ( "context" - "time" "github.com/IBM-Cloud/power-go-client/clients/instance" "github.com/IBM-Cloud/power-go-client/ibmpisession" "github.com/IBM-Cloud/power-go-client/power/client/p_cloud_images" "github.com/IBM-Cloud/power-go-client/power/models" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator" "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/utils" ) -const ( - // PowerVS service and plan name - powerVSService = "power-iaas" - powerVSServicePlan = "power-virtual-server-group" - - // Resource desired states - cloudInstanceActiveState = "active" - cloudInstanceFailedState = "failed" - - // Time duration for monitoring the resource readiness - pollingInterval = time.Second * 5 - cloudInstanceCreationTimeout = time.Minute * 5 -) - var _ PowerVS = &Service{} // Service holds the PowerVS Service specific information. @@ -184,7 +170,7 @@ func (s *Service) DeleteDHCPServer(id string) error { return s.dhcpClient.Delete(id) } -// GetNetworkByName fetches the network with name. If not found returns nil +// GetNetworkByName fetches the network with name. If not found, returns nil. func (s *Service) GetNetworkByName(networkName string) (*models.NetworkReference, error) { var network *models.NetworkReference networks, err := s.GetAllNetwork() diff --git a/pkg/cloud/services/resourcecontroller/service.go b/pkg/cloud/services/resourcecontroller/service.go index 4067f4e47..3005a3f78 100644 --- a/pkg/cloud/services/resourcecontroller/service.go +++ b/pkg/cloud/services/resourcecontroller/service.go @@ -21,30 +21,23 @@ import ( "github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" + "k8s.io/utils/pointer" - "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/utils" "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/utils" ) const ( // TODO(karthik-k-n)(Doubt): should this be fetched using global catalogs or hardcode like this? - //powerVSResourceID is Power VS power-iaas service id, can be retrieved using ibmcloud cli - // ibmcloud catalog service power-iaas + // powerVSResourceID is Power VS power-iaas service id, can be retrieved using ibmcloud cli + // ibmcloud catalog service power-iaas. powerVSResourceID = "abd259f0-9990-11e8-acc8-b9f54a8f1661" - //powerVSResourcePlanID is Power VS power-iaas plan id, can be retrieved using ibmcloud cli - // ibmcloud catalog service power-iaas + // powerVSResourcePlanID is Power VS power-iaas plan id, can be retrieved using ibmcloud cli + // ibmcloud catalog service power-iaas. powerVSResourcePlanID = "f165dd34-3a40-423b-9d95-e90a23f724dd" - - //cosResourceID is IBM COS service id, can be retrieved using ibmcloud cli - // ibmcloud catalog service cloud-object-storage - cosResourceID = "dff97f5c-bc5e-4455-b470-411c3edbe49c" - - //powerVSResourcePlanID is IBM COS plan id, can be retrieved using ibmcloud cli - // ibmcloud catalog service cloud-object-storage - cosResourcePlanID = "1e4e33e4-cfa6-4f12-9016-be594a6d5f87" ) // Service holds the IBM Cloud Resource Controller Service specific information. @@ -87,7 +80,7 @@ func (s *Service) DeleteResourceInstance(options *resourcecontrollerv2.DeleteRes return s.client.DeleteResourceInstance(options) } -// GetServiceInstance returns service instance with given name or id, If not found returns nil. +// GetServiceInstance returns service instance with given name or id. If not found, returns nil. func (s *Service) GetServiceInstance(id, name string) (*resourcecontrollerv2.ResourceInstance, error) { var serviceInstancesList []resourcecontrollerv2.ResourceInstance f := func(start string) (bool, string, error) { @@ -137,7 +130,7 @@ func (s *Service) GetServiceInstance(id, name string) (*resourcecontrollerv2.Res } } -// GetInstanceByName returns instance with given name, planID and resourceID, If not found returns nil. +// GetInstanceByName returns instance with given name, planID and resourceID. If not found, returns nil. func (s *Service) GetInstanceByName(name, resourceID, planID string) (*resourcecontrollerv2.ResourceInstance, error) { var serviceInstancesList []resourcecontrollerv2.ResourceInstance f := func(start string) (bool, string, error) { @@ -182,6 +175,7 @@ func (s *Service) GetInstanceByName(name, resourceID, planID string) (*resourcec } } +// CreateResourceKey creates a new resource key. func (s *Service) CreateResourceKey(options *resourcecontrollerv2.CreateResourceKeyOptions) (*resourcecontrollerv2.ResourceKey, *core.DetailedResponse, error) { return s.client.CreateResourceKey(options) } diff --git a/pkg/cloud/services/transitgateway/service.go b/pkg/cloud/services/transitgateway/service.go index 791950271..d553af167 100644 --- a/pkg/cloud/services/transitgateway/service.go +++ b/pkg/cloud/services/transitgateway/service.go @@ -21,7 +21,6 @@ import ( "time" "github.com/IBM/go-sdk-core/v5/core" - tgapiv1 "github.com/IBM/networking-go-sdk/transitgatewayapisv1" "k8s.io/utils/pointer" @@ -56,10 +55,12 @@ func NewService() (TransitGateway, error) { }, nil } +// GetTransitGateway returns the specified transit gateway. If not found, returns error. func (s *Service) GetTransitGateway(options *tgapiv1.GetTransitGatewayOptions) (*tgapiv1.TransitGateway, *core.DetailedResponse, error) { return s.tgClient.GetTransitGateway(options) } +// GetTransitGatewayByName returns tranit gateway with given name. If not found, returns nil. func (s *Service) GetTransitGatewayByName(name string) (*tgapiv1.TransitGateway, error) { var transitGateway *tgapiv1.TransitGateway @@ -71,7 +72,7 @@ func (s *Service) GetTransitGatewayByName(name string) (*tgapiv1.TransitGateway, for _, tg := range tgList.TransitGateways { if *tg.Name == name { - transitGateway = &tg + *transitGateway = tg return true, "", nil } } @@ -89,26 +90,32 @@ func (s *Service) GetTransitGatewayByName(name string) (*tgapiv1.TransitGateway, return transitGateway, nil } +// ListTransitGatewayConnections lists the transit gateway connections. func (s *Service) ListTransitGatewayConnections(options *tgapiv1.ListTransitGatewayConnectionsOptions) (*tgapiv1.TransitGatewayConnectionCollection, *core.DetailedResponse, error) { return s.tgClient.ListTransitGatewayConnections(options) } +// CreateTransitGateway creates a transit gateway. func (s *Service) CreateTransitGateway(options *tgapiv1.CreateTransitGatewayOptions) (*tgapiv1.TransitGateway, *core.DetailedResponse, error) { return s.tgClient.CreateTransitGateway(options) } +// CreateTransitGatewayConnection creates a transit gateway connection. func (s *Service) CreateTransitGatewayConnection(options *tgapiv1.CreateTransitGatewayConnectionOptions) (*tgapiv1.TransitGatewayConnectionCust, *core.DetailedResponse, error) { return s.tgClient.CreateTransitGatewayConnection(options) } +// GetTransitGatewayConnection returns a transit gateway connection. func (s *Service) GetTransitGatewayConnection(options *tgapiv1.GetTransitGatewayConnectionOptions) (*tgapiv1.TransitGatewayConnectionCust, *core.DetailedResponse, error) { return s.tgClient.GetTransitGatewayConnection(options) } +// DeleteTransitGateway deletes a transit gateway. func (s *Service) DeleteTransitGateway(options *tgapiv1.DeleteTransitGatewayOptions) (*core.DetailedResponse, error) { return s.tgClient.DeleteTransitGateway(options) } +// DeleteTransitGatewayConnection deletes a transit gateway connection. func (s *Service) DeleteTransitGatewayConnection(options *tgapiv1.DeleteTransitGatewayConnectionOptions) (*core.DetailedResponse, error) { return s.tgClient.DeleteTransitGatewayConnection(options) } diff --git a/pkg/cloud/services/vpc/service.go b/pkg/cloud/services/vpc/service.go index 610dc3cf1..69d025b58 100644 --- a/pkg/cloud/services/vpc/service.go +++ b/pkg/cloud/services/vpc/service.go @@ -18,11 +18,12 @@ package vpc import ( "fmt" + "github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/vpc-go-sdk/vpcv1" - "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/utils" "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/utils" ) // Service holds the VPC Service specific information. @@ -165,12 +166,12 @@ func (s *Service) GetInstanceProfile(options *vpcv1.GetInstanceProfileOptions) ( return s.vpcService.GetInstanceProfile(options) } -// GetVPC returns VPC details +// GetVPC returns VPC details. func (s *Service) GetVPC(options *vpcv1.GetVPCOptions) (*vpcv1.VPC, *core.DetailedResponse, error) { return s.vpcService.GetVPC(options) } -// GetVPCByName returns VPC with given name, If not found returns nil +// GetVPCByName returns VPC with given name. If not found, returns nil. func (s *Service) GetVPCByName(vpcName string) (*vpcv1.VPC, error) { var vpc *vpcv1.VPC f := func(start string) (bool, string, error) { @@ -209,12 +210,12 @@ func (s *Service) GetVPCByName(vpcName string) (*vpcv1.VPC, error) { return vpc, nil } -// GetSubnet return subnet +// GetSubnet return subnet. func (s *Service) GetSubnet(options *vpcv1.GetSubnetOptions) (*vpcv1.Subnet, *core.DetailedResponse, error) { return s.vpcService.GetSubnet(options) } -// GetVPCSubnetByName returns subnet with given name, If not found returns nil +// GetVPCSubnetByName returns subnet with given name. If not found, returns nil. func (s *Service) GetVPCSubnetByName(subnetName string) (*vpcv1.Subnet, error) { var subnet *vpcv1.Subnet f := func(start string) (bool, string, error) { @@ -253,7 +254,7 @@ func (s *Service) GetVPCSubnetByName(subnetName string) (*vpcv1.Subnet, error) { return subnet, nil } -// GetLoadBalancerByName returns loadBalancer with given name, If not found returns nil +// GetLoadBalancerByName returns loadBalancer with given name. If not found, returns nil. func (s *Service) GetLoadBalancerByName(loadBalancerName string) (*vpcv1.LoadBalancer, error) { var loadBalancer *vpcv1.LoadBalancer f := func(start string) (bool, string, error) { @@ -292,7 +293,7 @@ func (s *Service) GetLoadBalancerByName(loadBalancerName string) (*vpcv1.LoadBal return loadBalancer, nil } -// GetSubnetAddrPrefix returns subnets address prefix +// GetSubnetAddrPrefix returns subnets address prefix. func (s *Service) GetSubnetAddrPrefix(vpcID, zone string) (string, error) { var addrPrefix *vpcv1.AddressPrefix f := func(start string) (bool, string, error) { diff --git a/util/util.go b/util/util.go index b88504968..ace73c6c8 100644 --- a/util/util.go +++ b/util/util.go @@ -41,7 +41,7 @@ func GetClusterByName(ctx context.Context, c client.Client, namespace, name stri return cluster, nil } -// CreateInfra checks for annotations set on IBMPowerVSCluster object to determine cluster creation workflow +// CreateInfra checks for annotations set on IBMPowerVSCluster object to determine cluster creation workflow. func CreateInfra(cluster infrav1beta2.IBMPowerVSCluster) bool { annotations := cluster.GetAnnotations() if len(annotations) == 0 { @@ -58,7 +58,7 @@ func CreateInfra(cluster infrav1beta2.IBMPowerVSCluster) bool { return createInfra } -//TODO: Move this to powervs-utils +//TODO: Move this to powervs-utils. // Region describes respective IBM Cloud COS region, VPC region and Zones associated with a region in Power VS. type Region struct { @@ -190,7 +190,7 @@ func VPCRegionForPowerVSRegion(region string) (string, error) { return "", fmt.Errorf("VPC region corresponding to a PowerVS region %s not found ", region) } -// VPCZonesForPowerVSRegion returns the VPC zones associated with Power VS region +// VPCZonesForPowerVSRegion returns the VPC zones associated with Power VS region. func VPCZonesForPowerVSRegion(region string) ([]string, error) { if r, ok := Regions[region]; ok { return r.VPCZones, nil