diff --git a/Makefile b/Makefile index 528334f79..0f6a3deb8 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,7 @@ GOJQ := $(TOOLS_BIN_DIR)/gojq CONVERSION_GEN := $(TOOLS_BIN_DIR)/conversion-gen GINKGO := $(TOOLS_BIN_DIR)/ginkgo ENVSUBST := $(TOOLS_BIN_DIR)/envsubst +MOCKGEN := $(TOOLS_BIN_DIR)/mockgen STAGING_REGISTRY ?= gcr.io/k8s-staging-capi-ibmcloud STAGING_BUCKET ?= artifacts.k8s-staging-capi-ibmcloud.appspot.com @@ -124,8 +125,13 @@ vet: # Generate code generate: controller-gen + $(MAKE) generate-go $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." +.PHONY: generate-go +generate-go: $(MOCKGEN) + go generate ./... + images: docker-build # find or download controller-gen # download controller-gen if necessary diff --git a/cloud/scope/powervs_clients.go b/cloud/scope/powervs_clients.go deleted file mode 100644 index 3c81038fb..000000000 --- a/cloud/scope/powervs_clients.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright 2021 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package scope - -import ( - "context" - "time" - - "github.com/IBM-Cloud/power-go-client/clients/instance" - "github.com/IBM-Cloud/power-go-client/ibmpisession" -) - -// TIMEOUT is used while creating IBM Power VS client -const TIMEOUT = 1 * time.Hour - -// IBMPowerVSClient used to store IBM Power VS client information -type IBMPowerVSClient struct { - session *ibmpisession.IBMPISession - InstanceClient *instance.IBMPIInstanceClient - NetworkClient *instance.IBMPINetworkClient - ImageClient *instance.IBMPIImageClient -} - -// NewIBMPowerVSClient creates and returns a IBM Power VS client -func NewIBMPowerVSClient(token, account, cloudInstanceID, region, zone string, debug bool) (_ *IBMPowerVSClient, err error) { - client := &IBMPowerVSClient{} - ctx := context.Background() - client.session, err = ibmpisession.New(token, region, debug, account, zone) - if err != nil { - return nil, err - } - - client.InstanceClient = instance.NewIBMPIInstanceClient(ctx, client.session, cloudInstanceID) - client.NetworkClient = instance.NewIBMPINetworkClient(ctx, client.session, cloudInstanceID) - client.ImageClient = instance.NewIBMPIImageClient(ctx, client.session, cloudInstanceID) - return client, nil -} diff --git a/cloud/scope/powervs_cluster.go b/cloud/scope/powervs_cluster.go index 91b80f1e9..ddd2573b3 100644 --- a/cloud/scope/powervs_cluster.go +++ b/cloud/scope/powervs_cluster.go @@ -23,6 +23,9 @@ import ( "github.com/go-logr/logr" "github.com/pkg/errors" + "github.com/IBM-Cloud/power-go-client/ibmpisession" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" utils "github.com/ppc64le-cloud/powervs-utils" "k8s.io/klog/v2/klogr" @@ -31,7 +34,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta1" - "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/powervs" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/resourcecontroller" + servicesutils "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/utils" ) // PowerVSClusterScopeParams defines the input parameters used to create a new PowerVSClusterScope. @@ -48,7 +54,7 @@ type PowerVSClusterScope struct { client client.Client patchHelper *patch.Helper - IBMPowerVSClient *IBMPowerVSClient + IBMPowerVSClient *powervs.Service Cluster *clusterv1.Cluster IBMPowerVSCluster *v1beta1.IBMPowerVSCluster } @@ -66,20 +72,47 @@ func NewPowerVSClusterScope(params PowerVSClusterScopeParams) (*PowerVSClusterSc params.Logger = klogr.New() } - client := pkg.NewClient() - spec := params.IBMPowerVSCluster.Spec - resource, err := client.ResourceClient.GetInstance(spec.ServiceInstanceID) + + auth, err := authenticator.GetAuthenticator() if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to get authenticator") + } + + account, err := servicesutils.GetAccount(auth) + if err != nil { + return nil, errors.Wrap(err, "failed to get account") } - region, err := utils.GetRegion(resource.RegionID) + + rc, err := resourcecontroller.NewService(resourcecontroller.ServiceOptions{}) if err != nil { return nil, err } - zone := resource.RegionID - c, err := NewIBMPowerVSClient(client.Config.IAMAccessToken, client.User.Account, spec.ServiceInstanceID, region, zone, true) + res, _, err := rc.GetResourceInstance( + &resourcecontrollerv2.GetResourceInstanceOptions{ + ID: core.StringPtr(spec.ServiceInstanceID), + }) + if err != nil { + return nil, errors.Wrap(err, "failed to get resource instance") + } + + region, err := utils.GetRegion(*res.RegionID) + if err != nil { + return nil, errors.Wrap(err, "failed to get region") + } + + options := powervs.ServiceOptions{ + PIOptions: &ibmpisession.PIOptions{ + Debug: true, + UserAccount: account, + Region: region, + Zone: *res.RegionID, + }, + CloudInstanceID: spec.ServiceInstanceID, + } + c, err := powervs.NewService(options) + if err != nil { return nil, fmt.Errorf("failed to create NewIBMPowerVSClient") } diff --git a/cloud/scope/powervs_machine.go b/cloud/scope/powervs_machine.go index be82c7010..7f2591baf 100644 --- a/cloud/scope/powervs_machine.go +++ b/cloud/scope/powervs_machine.go @@ -27,9 +27,10 @@ import ( utils "github.com/ppc64le-cloud/powervs-utils" "github.com/IBM-Cloud/power-go-client/ibmpisession" - "github.com/IBM-Cloud/power-go-client/power/client/p_cloud_networks" "github.com/IBM-Cloud/power-go-client/power/client/p_cloud_p_vm_instances" "github.com/IBM-Cloud/power-go-client/power/models" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" @@ -39,7 +40,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta1" - "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/powervs" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/resourcecontroller" + servicesutils "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/utils" ) // PowerVSMachineScopeParams defines the input parameters used to create a new PowerVSMachineScope. @@ -58,7 +62,7 @@ type PowerVSMachineScope struct { client client.Client patchHelper *patch.Helper - IBMPowerVSClient *IBMPowerVSClient + IBMPowerVSClient *powervs.Service Cluster *clusterv1.Cluster Machine *clusterv1.Machine IBMPowerVSCluster *v1beta1.IBMPowerVSCluster @@ -85,21 +89,47 @@ func NewPowerVSMachineScope(params PowerVSMachineScopeParams) (*PowerVSMachineSc } m := params.IBMPowerVSMachine - client := pkg.NewClient() - resource, err := client.ResourceClient.GetInstance(m.Spec.ServiceInstanceID) + auth, err := authenticator.GetAuthenticator() if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to get authenticator") + } + + account, err := servicesutils.GetAccount(auth) + if err != nil { + return nil, errors.Wrap(err, "failed to get account") } - region, err := utils.GetRegion(resource.RegionID) + + rc, err := resourcecontroller.NewService(resourcecontroller.ServiceOptions{}) if err != nil { return nil, err } - zone := resource.RegionID - c, err := NewIBMPowerVSClient(client.Config.IAMAccessToken, client.User.Account, m.Spec.ServiceInstanceID, region, zone, true) + res, _, err := rc.GetResourceInstance( + &resourcecontrollerv2.GetResourceInstanceOptions{ + ID: core.StringPtr(m.Spec.ServiceInstanceID), + }) + if err != nil { + return nil, errors.Wrap(err, "failed to get resource instance") + } + + region, err := utils.GetRegion(*res.RegionID) if err != nil { - return nil, fmt.Errorf("failed to create NewIBMPowerVSClient") + return nil, errors.Wrap(err, "failed to get region") + } + + options := powervs.ServiceOptions{ + PIOptions: &ibmpisession.PIOptions{ + Debug: true, + UserAccount: account, + Region: region, + Zone: *res.RegionID, + }, + CloudInstanceID: m.Spec.ServiceInstanceID, + } + c, err := powervs.NewService(options) + if err != nil { + return nil, fmt.Errorf("failed to create PowerVS service") } helper, err := patch.NewHelper(params.IBMPowerVSMachine, params.Client) @@ -120,7 +150,7 @@ func NewPowerVSMachineScope(params PowerVSMachineScopeParams) (*PowerVSMachineSc } func (m *PowerVSMachineScope) ensureInstanceUnique(instanceName string) (*models.PVMInstanceReference, error) { - instances, err := m.IBMPowerVSClient.InstanceClient.GetAll() + instances, err := m.IBMPowerVSClient.GetAllInstance() if err != nil { return nil, err } @@ -185,7 +215,7 @@ func (m *PowerVSMachineScope) CreateMachine() (*models.PVMInstanceReference, err UserData: cloudInitData, }, } - _, err = m.IBMPowerVSClient.InstanceClient.Create(params.Body) + _, err = m.IBMPowerVSClient.CreateInstance(params.Body) if err != nil { return nil, err } @@ -204,7 +234,7 @@ func (m *PowerVSMachineScope) PatchObject() error { // DeleteMachine deletes the power vs machine associated with machine instance id and service instance id. func (m *PowerVSMachineScope) DeleteMachine() error { - return m.IBMPowerVSClient.InstanceClient.Delete(m.IBMPowerVSMachine.Status.InstanceID) + return m.IBMPowerVSClient.DeleteInstance(m.IBMPowerVSMachine.Status.InstanceID) } // GetBootstrapData returns the base64 encoded bootstrap data from the secret in the Machine's bootstrap.dataSecretName @@ -249,7 +279,7 @@ func getImageID(image v1beta1.IBMPowerVSResourceReference, m *PowerVSMachineScop } func (m *PowerVSMachineScope) GetImages() (*models.Images, error) { - return m.IBMPowerVSClient.ImageClient.GetAll() + return m.IBMPowerVSClient.GetAllImage() } func getNetworkID(network v1beta1.IBMPowerVSResourceReference, m *PowerVSMachineScope) (*string, error) { @@ -275,11 +305,5 @@ func getNetworkID(network v1beta1.IBMPowerVSResourceReference, m *PowerVSMachine } func (m *PowerVSMachineScope) GetNetworks() (*models.Networks, error) { - params := p_cloud_networks.NewPcloudNetworksGetallParamsWithTimeout(TIMEOUT).WithCloudInstanceID(m.IBMPowerVSMachine.Spec.ServiceInstanceID) - resp, err := m.IBMPowerVSClient.session.Power.PCloudNetworks.PcloudNetworksGetall(params, ibmpisession.NewAuth(m.IBMPowerVSClient.session, m.IBMPowerVSMachine.Spec.ServiceInstanceID)) - - if err != nil || resp.Payload == nil { - return nil, err - } - return resp.Payload, nil + return m.IBMPowerVSClient.GetAllNetwork() } diff --git a/controllers/ibmpowervsmachine_controller.go b/controllers/ibmpowervsmachine_controller.go index df0da5283..5e322ba3d 100644 --- a/controllers/ibmpowervsmachine_controller.go +++ b/controllers/ibmpowervsmachine_controller.go @@ -168,7 +168,7 @@ func (r *IBMPowerVSMachineReconciler) reconcileNormal(ctx context.Context, machi } if ins != nil { - instance, err := machineScope.IBMPowerVSClient.InstanceClient.Get(*ins.PvmInstanceID) + instance, err := machineScope.IBMPowerVSClient.GetInstance(*ins.PvmInstanceID) if err != nil { return ctrl.Result{}, err } diff --git a/controllers/ibmvpccluster_controller.go b/controllers/ibmvpccluster_controller.go index 7a9d4cba9..19852d344 100644 --- a/controllers/ibmvpccluster_controller.go +++ b/controllers/ibmvpccluster_controller.go @@ -19,6 +19,7 @@ package controllers import ( "context" "os" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -37,7 +38,6 @@ import ( infrastructurev1beta1 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta1" "sigs.k8s.io/cluster-api-provider-ibmcloud/cloud/scope" - "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg" ) // IBMVPCClusterReconciler reconciles a IBMVPCCluster object @@ -80,7 +80,7 @@ func (r *IBMVPCClusterReconciler) Reconcile(ctx context.Context, req ctrl.Reques // TODO: Will be removed once we find a better way of overriding the service endpoint, generate via spec svcEndpoint := os.Getenv("SERVICE_ENDPOINT") - authenticator, err := pkg.GetAuthenticator() + authenticator, err := authenticator.GetAuthenticator() if err != nil { return ctrl.Result{}, errors.Wrapf(err, "failed to get authenticator") } diff --git a/controllers/ibmvpcmachine_controller.go b/controllers/ibmvpcmachine_controller.go index f3ff7abea..4b33f0e19 100644 --- a/controllers/ibmvpcmachine_controller.go +++ b/controllers/ibmvpcmachine_controller.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "os" + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -38,7 +39,6 @@ import ( infrastructurev1beta1 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta1" "sigs.k8s.io/cluster-api-provider-ibmcloud/cloud/scope" - "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg" ) // IBMVPCMachineReconciler reconciles a IBMVPCMachine object @@ -100,7 +100,7 @@ func (r *IBMVPCMachineReconciler) Reconcile(ctx context.Context, req ctrl.Reques // Create the cluster scope svcEndpoint := os.Getenv("SERVICE_ENDPOINT") - authenticator, err := pkg.GetAuthenticator() + authenticator, err := authenticator.GetAuthenticator() if err != nil { return ctrl.Result{}, errors.Wrapf(err, "failed to get authenticator") } diff --git a/go.mod b/go.mod index 626275c25..657b87f4b 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,13 @@ module sigs.k8s.io/cluster-api-provider-ibmcloud go 1.17 require ( - github.com/IBM-Cloud/bluemix-go v0.0.0-20200921095234-26d1d0148c62 github.com/IBM-Cloud/power-go-client v1.0.88 github.com/IBM/go-sdk-core/v5 v5.9.1 + github.com/IBM/platform-services-go-sdk v0.22.7 github.com/IBM/vpc-go-sdk v0.14.0 github.com/go-logr/logr v1.2.0 github.com/golang-jwt/jwt v3.2.2+incompatible + github.com/golang/mock v1.6.0 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.17.0 github.com/pkg/errors v0.9.1 @@ -69,7 +70,7 @@ require ( github.com/google/go-github/v33 v33.0.0 // indirect github.com/google/go-querystring v1.0.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.2.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/googleapis/gnostic v0.5.5 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.0 // indirect diff --git a/go.sum b/go.sum index 4e29b2cec..9ae1ff32b 100644 --- a/go.sum +++ b/go.sum @@ -66,14 +66,15 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/IBM-Cloud/bluemix-go v0.0.0-20200921095234-26d1d0148c62 h1:8I8Z3mRorZhgT31vXPysZNuVQV7vWR3GSVtmh8xJ9L8= -github.com/IBM-Cloud/bluemix-go v0.0.0-20200921095234-26d1d0148c62/go.mod h1:gPJbH1etcDj7qS/hBRiLuYW9CY0bRcostSKusa51xR0= github.com/IBM-Cloud/power-go-client v1.0.88 h1:JTIyPK5fjXDZoRGvTtegk6D9qtMwgumbzeMz8vV1TGs= github.com/IBM-Cloud/power-go-client v1.0.88/go.mod h1:60o7AE2oDi/0CtoXlQhnCbC3o1fSRgaFCJO6DscmokA= github.com/IBM/go-sdk-core/v5 v5.7.2/go.mod h1:+YbdhrjCHC84ls4MeBp+Hj4NZCni+tDAc0XQUqRO9Jc= github.com/IBM/go-sdk-core/v5 v5.8.0/go.mod h1:+YbdhrjCHC84ls4MeBp+Hj4NZCni+tDAc0XQUqRO9Jc= +github.com/IBM/go-sdk-core/v5 v5.8.2/go.mod h1:axE2JrRq79gIJTjKPBwV6gWHswvVptBjbcvvCPIxARM= github.com/IBM/go-sdk-core/v5 v5.9.1 h1:06pXbD9Rgmqqe2HA5YAeQbB4eYRRFgIoOT+Kh3cp1zo= github.com/IBM/go-sdk-core/v5 v5.9.1/go.mod h1:axE2JrRq79gIJTjKPBwV6gWHswvVptBjbcvvCPIxARM= +github.com/IBM/platform-services-go-sdk v0.22.7 h1:mSTuhMx/t5KLWP2Y87qKjnmW2/PJiYdbZHXPFOIPEn0= +github.com/IBM/platform-services-go-sdk v0.22.7/go.mod h1:0moTvGSCdWiSKPmXejOpblpfya/VgDSeG+x9Tjxy+qI= github.com/IBM/vpc-go-sdk v0.14.0 h1:2uIhMiNiAJC8XiNkjhiMeMGBJlPU0jqE8KON2fvfSZI= github.com/IBM/vpc-go-sdk v0.14.0/go.mod h1:mIUjxBs5viRWIiCqfO/W4HPJ7aC6M+26mR4p5gaVls8= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= @@ -548,6 +549,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -619,8 +621,9 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= diff --git a/hack/tools/Makefile b/hack/tools/Makefile index bff3eb6cb..a52fb42c2 100644 --- a/hack/tools/Makefile +++ b/hack/tools/Makefile @@ -86,3 +86,7 @@ $(GINKGO): $(BIN_DIR) go.mod go.sum ENVSUBST := $(BIN_DIR)/envsubst $(ENVSUBST): $(BIN_DIR) go.mod go.sum go build -tags=tools -o $@ github.com/drone/envsubst/v2/cmd/envsubst + +MOCKGEN := $(BIN_DIR)/mockgen +$(MOCKGEN): $(BIN_DIR) go.mod go.sum + go build -tags=tools -o $@ github.com/golang/mock/mockgen diff --git a/hack/tools/go.mod b/hack/tools/go.mod index 464a33395..bab55c937 100644 --- a/hack/tools/go.mod +++ b/hack/tools/go.mod @@ -4,6 +4,7 @@ go 1.17 require ( github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 + github.com/golang/mock v1.6.0 github.com/golangci/golangci-lint v1.41.1 github.com/itchyny/gojq v0.12.5 github.com/joelanford/go-apidiff v0.1.0 diff --git a/hack/tools/go.sum b/hack/tools/go.sum index cc4109a7c..8e6c0e695 100644 --- a/hack/tools/go.sum +++ b/hack/tools/go.sum @@ -340,6 +340,8 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -1373,6 +1375,7 @@ golang.org/x/tools v0.0.0-20210104081019-d8d6ddbec6ee/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= diff --git a/hack/tools/tools.go b/hack/tools/tools.go index 44047c4ea..4632ddd71 100644 --- a/hack/tools/tools.go +++ b/hack/tools/tools.go @@ -1,3 +1,4 @@ +//go:build tools // +build tools /* @@ -21,6 +22,7 @@ package tools import ( _ "github.com/drone/envsubst/v2/cmd/envsubst" + _ "github.com/golang/mock/mockgen" _ "github.com/golangci/golangci-lint/cmd/golangci-lint" _ "github.com/itchyny/gojq/cmd/gojq" _ "github.com/joelanford/go-apidiff" diff --git a/pkg/client.go b/pkg/client.go deleted file mode 100644 index 0dbd0ac97..000000000 --- a/pkg/client.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -Copyright 2021 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package pkg - -import ( - gohttp "net/http" - "strings" - - "github.com/golang-jwt/jwt" - - "github.com/IBM-Cloud/bluemix-go" - "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2" - "github.com/IBM-Cloud/bluemix-go/authentication" - "github.com/IBM-Cloud/bluemix-go/http" - "github.com/IBM-Cloud/bluemix-go/rest" - bxsession "github.com/IBM-Cloud/bluemix-go/session" - "github.com/IBM/go-sdk-core/v5/core" - - "k8s.io/klog/v2" -) - -// Client is used to communicate with IBM Cloud holds the session and user information -type Client struct { - *bxsession.Session - User *User - ResourceClient controllerv2.ResourceServiceInstanceRepository -} - -func authenticateAPIKey(sess *bxsession.Session) error { - config := sess.Config - tokenRefresher, err := authentication.NewIAMAuthRepository(config, &rest.Client{ - DefaultHeader: gohttp.Header{ - "User-Agent": []string{http.UserAgent()}, - }, - }) - if err != nil { - return err - } - return tokenRefresher.AuthenticateAPIKey(config.BluemixAPIKey) -} - -// User holds the user specific information -type User struct { - ID string - Email string - Account string - cloudName string `default:"bluemix"` - cloudType string `default:"public"` - generation int `default:"2"` -} - -func fetchUserDetails(sess *bxsession.Session, generation int) (*User, error) { - config := sess.Config - user := User{} - var bluemixToken string - - if strings.HasPrefix(config.IAMAccessToken, "Bearer") { - bluemixToken = config.IAMAccessToken[7:len(config.IAMAccessToken)] - } else { - bluemixToken = config.IAMAccessToken - } - - token, err := jwt.Parse(bluemixToken, func(token *jwt.Token) (interface{}, error) { - return "", nil - }) - if err != nil && !strings.Contains(err.Error(), "key is of invalid type") { - return &user, err - } - - claims := token.Claims.(jwt.MapClaims) - if email, ok := claims["email"]; ok { - user.Email = email.(string) - } - user.ID = claims["id"].(string) - user.Account = claims["account"].(map[string]interface{})["bss"].(string) - iss := claims["iss"].(string) - if strings.Contains(iss, "https://iam.cloud.ibm.com") { - user.cloudName = "bluemix" - } else { - user.cloudName = "staging" - } - user.cloudType = "public" - - user.generation = generation - return &user, nil -} - -// NewClient instantiates and returns an IBM Cloud Client object with session, resource controller and userDetails -func NewClient() *Client { - c := &Client{} - - authenticator, err := GetAuthenticator() - if err != nil { - klog.Fatal(err) - } - //TODO: this will be removed once power-go-client migrated to go-sdk-core - auth, ok := authenticator.(*core.IamAuthenticator) - if !ok { - klog.Fatal("failed to assert the authenticator as IAM type, please check the ibm-credentials.env file") - } - bxSess, err := bxsession.New(&bluemix.Config{BluemixAPIKey: auth.ApiKey}) - if err != nil { - klog.Fatal(err) - } - - c.Session = bxSess - - err = authenticateAPIKey(bxSess) - if err != nil { - klog.Fatal(err) - } - - c.User, err = fetchUserDetails(bxSess, 2) - if err != nil { - klog.Fatal(err) - } - - ctrlv2, err := controllerv2.New(bxSess) - if err != nil { - klog.Fatal(err) - } - - c.ResourceClient = ctrlv2.ResourceServiceInstanceV2() - return c -} diff --git a/pkg/authenticator.go b/pkg/cloud/services/authenticator/authenticator.go similarity index 80% rename from pkg/authenticator.go rename to pkg/cloud/services/authenticator/authenticator.go index bce041bce..e122e563f 100644 --- a/pkg/authenticator.go +++ b/pkg/cloud/services/authenticator/authenticator.go @@ -1,5 +1,5 @@ /* -Copyright 2021 The Kubernetes Authors. +Copyright 2022 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package pkg +package authenticator import ( "fmt" @@ -22,6 +22,10 @@ import ( "github.com/IBM/go-sdk-core/v5/core" ) +const ( + serviceIBMCloud = "IBMCLOUD" +) + // This expects the credential file in the following search order: // 1) ${IBM_CREDENTIALS_FILE} // 2) /ibm-credentials.env @@ -33,20 +37,13 @@ import ( // IBMCLOUD_APIKEY=xxxxxxxxxxxxx // IBMCLOUD_AUTH_URL=https://iam.cloud.ibm.com -const ( - serviceIBMCloud = "IBMCLOUD" -) - -// GetAuthenticator instantiates an Authenticator from external config file func GetAuthenticator() (core.Authenticator, error) { auth, err := core.GetAuthenticatorFromEnvironment(serviceIBMCloud) if err != nil { return nil, err } - switch auth.(type) { - case *core.IamAuthenticator: - return auth, nil - default: - return nil, fmt.Errorf("only IAM authenticator is supported") + if auth == nil { + return nil, fmt.Errorf("authenticator can't be nil, please set proper authentication") } + return auth, nil } diff --git a/pkg/cloud/services/powervs/mock/powervs_generated.go b/pkg/cloud/services/powervs/mock/powervs_generated.go new file mode 100644 index 000000000..b5d89240e --- /dev/null +++ b/pkg/cloud/services/powervs/mock/powervs_generated.go @@ -0,0 +1,124 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./powervs.go + +// Package mock is a generated GoMock package. +package mock + +import ( + reflect "reflect" + + models "github.com/IBM-Cloud/power-go-client/power/models" + gomock "github.com/golang/mock/gomock" +) + +// MockPowerVS is a mock of PowerVS interface. +type MockPowerVS struct { + ctrl *gomock.Controller + recorder *MockPowerVSMockRecorder +} + +// MockPowerVSMockRecorder is the mock recorder for MockPowerVS. +type MockPowerVSMockRecorder struct { + mock *MockPowerVS +} + +// NewMockPowerVS creates a new mock instance. +func NewMockPowerVS(ctrl *gomock.Controller) *MockPowerVS { + mock := &MockPowerVS{ctrl: ctrl} + mock.recorder = &MockPowerVSMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockPowerVS) EXPECT() *MockPowerVSMockRecorder { + return m.recorder +} + +// CreateInstance mocks base method. +func (m *MockPowerVS) CreateInstance(body *models.PVMInstanceCreate) (*models.PVMInstanceList, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateInstance", body) + ret0, _ := ret[0].(*models.PVMInstanceList) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateInstance indicates an expected call of CreateInstance. +func (mr *MockPowerVSMockRecorder) CreateInstance(body interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateInstance", reflect.TypeOf((*MockPowerVS)(nil).CreateInstance), body) +} + +// DeleteInstance mocks base method. +func (m *MockPowerVS) DeleteInstance(id string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteInstance", id) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteInstance indicates an expected call of DeleteInstance. +func (mr *MockPowerVSMockRecorder) DeleteInstance(id interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteInstance", reflect.TypeOf((*MockPowerVS)(nil).DeleteInstance), id) +} + +// GetAllImage mocks base method. +func (m *MockPowerVS) GetAllImage() (*models.Images, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAllImage") + ret0, _ := ret[0].(*models.Images) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetAllImage indicates an expected call of GetAllImage. +func (mr *MockPowerVSMockRecorder) GetAllImage() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllImage", reflect.TypeOf((*MockPowerVS)(nil).GetAllImage)) +} + +// GetAllInstance mocks base method. +func (m *MockPowerVS) GetAllInstance() (*models.PVMInstances, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAllInstance") + ret0, _ := ret[0].(*models.PVMInstances) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetAllInstance indicates an expected call of GetAllInstance. +func (mr *MockPowerVSMockRecorder) GetAllInstance() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllInstance", reflect.TypeOf((*MockPowerVS)(nil).GetAllInstance)) +} + +// GetAllNetwork mocks base method. +func (m *MockPowerVS) GetAllNetwork() (*models.Networks, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAllNetwork") + ret0, _ := ret[0].(*models.Networks) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetAllNetwork indicates an expected call of GetAllNetwork. +func (mr *MockPowerVSMockRecorder) GetAllNetwork() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllNetwork", reflect.TypeOf((*MockPowerVS)(nil).GetAllNetwork)) +} diff --git a/pkg/cloud/services/powervs/powervs.go b/pkg/cloud/services/powervs/powervs.go new file mode 100644 index 000000000..1318455ec --- /dev/null +++ b/pkg/cloud/services/powervs/powervs.go @@ -0,0 +1,32 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package powervs + +import ( + "github.com/IBM-Cloud/power-go-client/power/models" +) + +//go:generate ../../../../hack/tools/bin/mockgen -source=./powervs.go -destination=./mock/powervs_generated.go -package=mock +//go:generate /usr/bin/env bash -c "cat ../../../../hack/boilerplate/boilerplate.generatego.txt ./mock/powervs_generated.go > ./mock/_powervs_generated.go && mv ./mock/_powervs_generated.go ./mock/powervs_generated.go" + +type PowerVS interface { + CreateInstance(body *models.PVMInstanceCreate) (*models.PVMInstanceList, error) + DeleteInstance(id string) error + GetAllInstance() (*models.PVMInstances, error) + GetAllImage() (*models.Images, error) + GetAllNetwork() (*models.Networks, error) +} diff --git a/pkg/cloud/services/powervs/service.go b/pkg/cloud/services/powervs/service.go new file mode 100644 index 000000000..9dc9fda85 --- /dev/null +++ b/pkg/cloud/services/powervs/service.go @@ -0,0 +1,95 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package powervs + +import ( + "context" + + "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/models" + + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator" +) + +var _ PowerVS = &Service{} + +// Service holds the PowerVS Service specific information +type Service struct { + session *ibmpisession.IBMPISession + InstanceClient *instance.IBMPIInstanceClient + NetworkClient *instance.IBMPINetworkClient + ImageClient *instance.IBMPIImageClient +} + +type ServiceOptions struct { + *ibmpisession.PIOptions + + CloudInstanceID string +} + +// CreateInstance creates the virtual machine in the Power VS service instance. +func (s *Service) CreateInstance(body *models.PVMInstanceCreate) (*models.PVMInstanceList, error) { + return s.InstanceClient.Create(body) +} + +// DeleteInstance deletes the virtual machine in the Power VS service instance. +func (s *Service) DeleteInstance(id string) error { + return s.InstanceClient.Delete(id) +} + +// GetAllInstance returns all the virtual machine in the Power VS service instance. +func (s *Service) GetAllInstance() (*models.PVMInstances, error) { + return s.InstanceClient.GetAll() +} + +// GetInstance returns the virtual machine in the Power VS service instance. +func (s *Service) GetInstance(id string) (*models.PVMInstance, error) { + return s.InstanceClient.Get(id) +} + +// GetAllImage returns all the images in the Power VS service instance. +func (s *Service) GetAllImage() (*models.Images, error) { + return s.ImageClient.GetAll() +} + +// GetAllNetwork returns all the networks in the Power VS service instance. +func (s *Service) GetAllNetwork() (*models.Networks, error) { + return s.NetworkClient.GetAll() +} + +// NewService returns a new service for the Power VS api client. +func NewService(options ServiceOptions) (*Service, error) { + auth, err := authenticator.GetAuthenticator() + if err != nil { + return nil, err + } + options.Authenticator = auth + session, err := ibmpisession.NewSession(options.PIOptions) + if err != nil { + return nil, err + } + + ctx := context.Background() + + return &Service{ + session: session, + InstanceClient: instance.NewIBMPIInstanceClient(ctx, session, options.CloudInstanceID), + NetworkClient: instance.NewIBMPINetworkClient(ctx, session, options.CloudInstanceID), + ImageClient: instance.NewIBMPIImageClient(ctx, session, options.CloudInstanceID), + }, nil +} diff --git a/pkg/cloud/services/resourcecontroller/resourcecontroller.go b/pkg/cloud/services/resourcecontroller/resourcecontroller.go new file mode 100644 index 000000000..d9ea6f032 --- /dev/null +++ b/pkg/cloud/services/resourcecontroller/resourcecontroller.go @@ -0,0 +1,26 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourcecontroller + +import ( + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" +) + +type ResourceController interface { + ListResourceInstances(listResourceInstancesOptions *resourcecontrollerv2.ListResourceInstancesOptions) (result *resourcecontrollerv2.ResourceInstancesList, response *core.DetailedResponse, err error) +} diff --git a/pkg/cloud/services/resourcecontroller/service.go b/pkg/cloud/services/resourcecontroller/service.go new file mode 100644 index 000000000..8f1d221d5 --- /dev/null +++ b/pkg/cloud/services/resourcecontroller/service.go @@ -0,0 +1,60 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resourcecontroller + +import ( + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2" + + "sigs.k8s.io/cluster-api-provider-ibmcloud/pkg/cloud/services/authenticator" +) + +// Service holds the IBM Cloud Resource Controller Service specific information +type Service struct { + client *resourcecontrollerv2.ResourceControllerV2 +} + +type ServiceOptions struct { + *resourcecontrollerv2.ResourceControllerV2Options +} + +func (s *Service) ListResourceInstances(listResourceInstancesOptions *resourcecontrollerv2.ListResourceInstancesOptions) (result *resourcecontrollerv2.ResourceInstancesList, response *core.DetailedResponse, err error) { + return s.client.ListResourceInstances(listResourceInstancesOptions) +} + +func (s *Service) GetResourceInstance(getResourceInstanceOptions *resourcecontrollerv2.GetResourceInstanceOptions) (result *resourcecontrollerv2.ResourceInstance, response *core.DetailedResponse, err error) { + return s.client.GetResourceInstance(getResourceInstanceOptions) +} + +// NewService returns a new service for the IBM Cloud Resource Controller api client. +func NewService(options ServiceOptions) (*Service, error) { + if options.ResourceControllerV2Options == nil { + options.ResourceControllerV2Options = &resourcecontrollerv2.ResourceControllerV2Options{} + } + auth, err := authenticator.GetAuthenticator() + if err != nil { + return nil, err + } + options.Authenticator = auth + service, err := resourcecontrollerv2.NewResourceControllerV2(options.ResourceControllerV2Options) + if err != nil { + return nil, err + } + return &Service{ + client: service, + }, nil +} diff --git a/pkg/cloud/services/utils/accounts.go b/pkg/cloud/services/utils/accounts.go new file mode 100644 index 000000000..6060a782e --- /dev/null +++ b/pkg/cloud/services/utils/accounts.go @@ -0,0 +1,51 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package utils + +import ( + "net/http" + "strings" + + "github.com/golang-jwt/jwt" + + "github.com/IBM/go-sdk-core/v5/core" +) + +// GetAccount is function parses the account number from the token and returns it +func GetAccount(auth core.Authenticator) (string, error) { + // fake request to get a barer token from the request header + req, err := http.NewRequest("GET", "http://example.com", nil) + if err != nil { + return "", err + } + err = auth.Authenticate(req) + if err != nil { + return "", err + } + bearerToken := req.Header.Get("Authorization") + if strings.HasPrefix(bearerToken, "Bearer") { + bearerToken = bearerToken[7:] + } + token, err := jwt.Parse(bearerToken, func(token *jwt.Token) (interface{}, error) { + return "", nil + }) + if err != nil && !strings.Contains(err.Error(), "key is of invalid type") { + return "", err + } + + return token.Claims.(jwt.MapClaims)["account"].(map[string]interface{})["bss"].(string), nil +}