diff --git a/api/v1alpha4/ibmpowervscluster_types.go b/api/v1alpha4/ibmpowervscluster_types.go index 41cf579d0..afa8bf6af 100644 --- a/api/v1alpha4/ibmpowervscluster_types.go +++ b/api/v1alpha4/ibmpowervscluster_types.go @@ -38,8 +38,8 @@ type IBMPowerVSClusterSpec struct { // ServiceInstanceID is the id of the power cloud instance where the vsi instance will get deployed ServiceInstanceID string `json:"serviceInstanceID"` - // Network is network ID used for the VSI - NetworkID string `json:"networkID"` + // Network is the reference to the Network to use for this cluster. + Network IBMPowerVSResourceReference `json:"network"` // ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. // +optional diff --git a/api/v1alpha4/ibmpowervsmachine_types.go b/api/v1alpha4/ibmpowervsmachine_types.go index f8f65087e..7a0c86956 100644 --- a/api/v1alpha4/ibmpowervsmachine_types.go +++ b/api/v1alpha4/ibmpowervsmachine_types.go @@ -41,9 +41,8 @@ type IBMPowerVSMachineSpec struct { // SSHKey is the name of the SSH key pair provided to the vsi for authenticating users SSHKey string `json:"sshKey,omitempty"` - // ImageID is the id of OS image which would be install on the instance. - // Example: c57eef35-ea0b-45d7-b864-4b0d4893425b - ImageID string `json:"imageID"` + // Image is the reference to the Image from which to create the machine instance. + Image IBMPowerVSResourceReference `json:"image"` // SysType is the System type used to host the vsi SysType string `json:"sysType"` @@ -57,14 +56,27 @@ type IBMPowerVSMachineSpec struct { // Memory is Amount of memory allocated (in GB) Memory string `json:"memory"` - // NetworkID is network ID used for the VSI - NetworkID string `json:"networkID"` + // Network is the reference to the Network to use for this instance. + Network IBMPowerVSResourceReference `json:"network"` // ProviderID is the unique identifier as specified by the cloud provider. // +optional ProviderID *string `json:"providerID,omitempty"` } +// IBMPowerVSResourceReference is a reference to a specific PowerVS resource by ID or Name +// Only one of ID or Name may be specified. Specifying more than one will result in +// a validation error. +type IBMPowerVSResourceReference struct { + // ID of resource + // +optional + ID *string `json:"id,omitempty"` + + // Name of resource + // +optional + Name *string `json:"name,omitempty"` +} + // IBMPowerVSMachineStatus defines the observed state of IBMPowerVSMachine type IBMPowerVSMachineStatus struct { // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster diff --git a/api/v1alpha4/zz_generated.deepcopy.go b/api/v1alpha4/zz_generated.deepcopy.go index 386519c66..b36602e8d 100644 --- a/api/v1alpha4/zz_generated.deepcopy.go +++ b/api/v1alpha4/zz_generated.deepcopy.go @@ -55,7 +55,7 @@ func (in *IBMPowerVSCluster) DeepCopyInto(out *IBMPowerVSCluster) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) out.Status = in.Status } @@ -112,6 +112,7 @@ func (in *IBMPowerVSClusterList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IBMPowerVSClusterSpec) DeepCopyInto(out *IBMPowerVSClusterSpec) { *out = *in + in.Network.DeepCopyInto(&out.Network) out.ControlPlaneEndpoint = in.ControlPlaneEndpoint } @@ -202,6 +203,8 @@ func (in *IBMPowerVSMachineList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IBMPowerVSMachineSpec) DeepCopyInto(out *IBMPowerVSMachineSpec) { *out = *in + in.Image.DeepCopyInto(&out.Image) + in.Network.DeepCopyInto(&out.Network) if in.ProviderID != nil { in, out := &in.ProviderID, &out.ProviderID *out = new(string) @@ -345,6 +348,31 @@ func (in *IBMPowerVSMachineTemplateStatus) DeepCopy() *IBMPowerVSMachineTemplate return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IBMPowerVSResourceReference) DeepCopyInto(out *IBMPowerVSResourceReference) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMPowerVSResourceReference. +func (in *IBMPowerVSResourceReference) DeepCopy() *IBMPowerVSResourceReference { + if in == nil { + return nil + } + out := new(IBMPowerVSResourceReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IBMVPCCluster) DeepCopyInto(out *IBMVPCCluster) { *out = *in diff --git a/cloud/scope/powervs_clients.go b/cloud/scope/powervs_clients.go index 846ed8b21..8e9a7c282 100644 --- a/cloud/scope/powervs_clients.go +++ b/cloud/scope/powervs_clients.go @@ -31,6 +31,7 @@ type IBMPowerVSClient struct { session *ibmpisession.IBMPISession InstanceClient *instance.IBMPIInstanceClient NetworkClient *instance.IBMPINetworkClient + ImageClient *instance.IBMPIImageClient } // NewIBMPowerVSClient creates and returns a IBM Power VS client @@ -43,5 +44,6 @@ func NewIBMPowerVSClient(token, account, cloudInstanceID, region, zone string, d client.InstanceClient = instance.NewIBMPIInstanceClient(client.session, cloudInstanceID) client.NetworkClient = instance.NewIBMPINetworkClient(client.session, cloudInstanceID) + client.ImageClient = instance.NewIBMPIImageClient(client.session, cloudInstanceID) return client, nil } diff --git a/cloud/scope/powervs_machine.go b/cloud/scope/powervs_machine.go index c9eaa99c2..81faf93f0 100644 --- a/cloud/scope/powervs_machine.go +++ b/cloud/scope/powervs_machine.go @@ -25,9 +25,10 @@ import ( "github.com/go-logr/logr" "github.com/pkg/errors" + utils "github.com/ppc64le-cloud/powervs-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" @@ -157,13 +158,23 @@ func (m *PowerVSMachineScope) CreateMachine() (*models.PVMInstanceReference, err return nil, fmt.Errorf("failed to convert Processors(%s) to float64", s.Processors) } + imageID, err := getImageID(s.Image, m) + if err != nil { + return nil, fmt.Errorf("error getting image ID: %v", err) + } + + networkID, err := getNetworkID(s.Network, m) + if err != nil { + return nil, fmt.Errorf("error getting network ID: %v", err) + } + params := &p_cloud_p_vm_instances.PcloudPvminstancesPostParams{ Body: &models.PVMInstanceCreate{ - ImageID: &s.ImageID, + ImageID: imageID, KeyPairName: s.SSHKey, Networks: []*models.PVMInstanceAddNetwork{ { - NetworkID: &s.NetworkID, + NetworkID: networkID, //IPAddress: address, }, }, @@ -216,3 +227,60 @@ func (m *PowerVSMachineScope) GetBootstrapData() (string, error) { return base64.StdEncoding.EncodeToString(value), nil } + +func getImageID(image v1alpha4.IBMPowerVSResourceReference, m *PowerVSMachineScope) (*string, error) { + if image.ID != nil { + return image.ID, nil + } else if image.Name != nil { + images, err := m.GetImages() + if err != nil { + m.Logger.Error(err, "failed to get images") + return nil, err + } + for _, img := range images.Images { + if *image.Name == *img.Name { + m.Logger.Info("image found with ID", "Image", *image.Name, "ID", *img.ImageID) + return img.ImageID, nil + } + } + } else { + return nil, fmt.Errorf("both ID and Name can't be nil") + } + return nil, fmt.Errorf("failed to find an image ID") +} + +func (m *PowerVSMachineScope) GetImages() (*models.Images, error) { + return m.IBMPowerVSClient.ImageClient.GetAll(m.IBMPowerVSMachine.Spec.ServiceInstanceID) +} + +func getNetworkID(network v1alpha4.IBMPowerVSResourceReference, m *PowerVSMachineScope) (*string, error) { + if network.ID != nil { + return network.ID, nil + } else if network.Name != nil { + networks, err := m.GetNetworks() + if err != nil { + m.Logger.Error(err, "failed to get networks") + return nil, err + } + for _, nw := range networks.Networks { + if *network.Name == *nw.Name { + m.Logger.Info("network found with ID", "Network", *network.Name, "ID", *nw.NetworkID) + return nw.NetworkID, nil + } + } + } else { + return nil, fmt.Errorf("both ID and Name can't be nil") + } + + return nil, fmt.Errorf("failed to find a network ID") +} + +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 +} 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 75dfa18d5..3a65ad0d6 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsclusters.yaml @@ -51,15 +51,23 @@ spec: - host - port type: object - networkID: - description: Network is network ID used for the VSI - type: string + network: + description: Network is the reference to the Network to use for this + cluster. + properties: + id: + description: ID of resource + type: string + name: + description: Name of resource + type: string + type: object serviceInstanceID: description: ServiceInstanceID is the id of the power cloud instance where the vsi instance will get deployed type: string required: - - networkID + - network - serviceInstanceID type: object status: diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsmachines.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsmachines.yaml index 2ced0df17..38fb56925 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsmachines.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsmachines.yaml @@ -53,16 +53,31 @@ spec: spec: description: IBMPowerVSMachineSpec defines the desired state of IBMPowerVSMachine properties: - imageID: - description: 'ImageID is the id of OS image which would be install - on the instance. Example: c57eef35-ea0b-45d7-b864-4b0d4893425b' - type: string + image: + description: Image is the reference to the Image from which to create + the machine instance. + properties: + id: + description: ID of resource + type: string + name: + description: Name of resource + type: string + type: object memory: description: Memory is Amount of memory allocated (in GB) type: string - networkID: - description: NetworkID is network ID used for the VSI - type: string + network: + description: Network is the reference to the Network to use for this + instance. + properties: + id: + description: ID of resource + type: string + name: + description: Name of resource + type: string + type: object procType: description: 'ProcType is the processor type, e.g: dedicated, shared, capped' @@ -86,9 +101,9 @@ spec: description: SysType is the System type used to host the vsi type: string required: - - imageID + - image - memory - - networkID + - network - procType - processors - serviceInstanceID diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsmachinetemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsmachinetemplates.yaml index 803cd85c5..98c1e254f 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsmachinetemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_ibmpowervsmachinetemplates.yaml @@ -46,16 +46,31 @@ spec: description: IBMPowerVSMachineSpec defines the desired state of IBMPowerVSMachine properties: - imageID: - description: 'ImageID is the id of OS image which would be - install on the instance. Example: c57eef35-ea0b-45d7-b864-4b0d4893425b' - type: string + image: + description: Image is the reference to the Image from which + to create the machine instance. + properties: + id: + description: ID of resource + type: string + name: + description: Name of resource + type: string + type: object memory: description: Memory is Amount of memory allocated (in GB) type: string - networkID: - description: NetworkID is network ID used for the VSI - type: string + network: + description: Network is the reference to the Network to use + for this instance. + properties: + id: + description: ID of resource + type: string + name: + description: Name of resource + type: string + type: object procType: description: 'ProcType is the processor type, e.g: dedicated, shared, capped' @@ -79,9 +94,9 @@ spec: description: SysType is the System type used to host the vsi type: string required: - - imageID + - image - memory - - networkID + - network - procType - processors - serviceInstanceID diff --git a/docs/book/src/topics/powervs/creating-a-cluster.md b/docs/book/src/topics/powervs/creating-a-cluster.md index 0dfe86e38..6495e9247 100644 --- a/docs/book/src/topics/powervs/creating-a-cluster.md +++ b/docs/book/src/topics/powervs/creating-a-cluster.md @@ -101,9 +101,9 @@ IBMPOWERVS_VIP="192.168.151.22" \ IBMPOWERVS_VIP_EXTERNAL="158.175.162.22" \ IBMPOWERVS_VIP_CIDR="29" \ - IBMPOWERVS_IMAGE_ID="505f57d8-1143-4a99-b67f-7e82d73342bf" \ + IBMPOWERVS_IMAGE_NAME="capibm-powervs-centos-8-1-22-4" \ IBMPOWERVS_SERVICE_INSTANCE_ID="7845d372-d4e1-46b8-91fc-41051c984601" \ - IBMPOWERVS_NETWORK_ID="0ad342f5-f461-414a-a870-e2f2a2b7fa0c" \ + IBMPOWERVS_NETWORK_NAME="capi-test-3" \ clusterctl generate cluster ibm-powervs-1 --kubernetes-version v1.22.4 \ --target-namespace default \ --control-plane-machine-count=3 \ diff --git a/pkg/authenticator.go b/pkg/authenticator.go index 0f8777ec7..bce041bce 100644 --- a/pkg/authenticator.go +++ b/pkg/authenticator.go @@ -18,6 +18,7 @@ package pkg import ( "fmt" + "github.com/IBM/go-sdk-core/v5/core" ) diff --git a/templates/README.md b/templates/README.md index cdca05d64..7f32bc998 100644 --- a/templates/README.md +++ b/templates/README.md @@ -25,9 +25,9 @@ IBMPOWERVS_SSHKEY_NAME="mkumatag-pub-key" \ IBMPOWERVS_VIP="192.168.150.125" \ IBMPOWERVS_VIP_EXTERNAL="158.175.161.125" \ IBMPOWERVS_VIP_CIDR="29" \ -IBMPOWERVS_IMAGE_ID="fb2f75d1-1157-40b9-af2f-5459685ca089" \ +IBMPOWERVS_IMAGE_NAME="capibm-powervs-centos-8-1-22-4" \ IBMPOWERVS_SERVICE_INSTANCE_ID="e449d86e-c3a0-4c07-959e-8557fdf55482" \ -IBMPOWERVS_NETWORK_ID="07ba61c2-64a4-42ce-911e-a3b3656eab7c" \ +IBMPOWERVS_NETWORK_NAME="capi-test-3" \ clusterctl generate cluster ibm-powervs-1 --kubernetes-version v1.21.2 \ --target-namespace default \ --control-plane-machine-count=3 \ diff --git a/templates/cluster-template-powervs.yaml b/templates/cluster-template-powervs.yaml index b1ca772d5..5697b27cf 100644 --- a/templates/cluster-template-powervs.yaml +++ b/templates/cluster-template-powervs.yaml @@ -30,7 +30,8 @@ metadata: name: "${CLUSTER_NAME}" spec: serviceInstanceID: "${IBMPOWERVS_SERVICE_INSTANCE_ID}" - networkID: "${IBMPOWERVS_NETWORK_ID}" + network: + name: "${IBMPOWERVS_NETWORK_NAME}" controlPlaneEndpoint: host: "${IBMPOWERVS_VIP_EXTERNAL}" port: 6443 @@ -157,12 +158,14 @@ spec: spec: serviceInstanceID: "${IBMPOWERVS_SERVICE_INSTANCE_ID}" sshKey: "${IBMPOWERVS_SSHKEY_NAME}" - imageID: "${IBMPOWERVS_IMAGE_ID}" + image: + name: "${IBMPOWERVS_IMAGE_NAME}" sysType: s922 procType: shared processors: "0.25" memory: "8" - networkID: "${IBMPOWERVS_NETWORK_ID}" + network: + name: "${IBMPOWERVS_NETWORK_NAME}" --- apiVersion: cluster.x-k8s.io/v1alpha4 kind: MachineDeployment @@ -196,12 +199,14 @@ spec: spec: serviceInstanceID: "${IBMPOWERVS_SERVICE_INSTANCE_ID}" sshKey: "${IBMPOWERVS_SSHKEY_NAME}" - imageID: "${IBMPOWERVS_IMAGE_ID}" + image: + name: "${IBMPOWERVS_IMAGE_NAME}" sysType: s922 procType: shared processors: "0.25" memory: "8" - networkID: "${IBMPOWERVS_NETWORK_ID}" + network: + name: "${IBMPOWERVS_NETWORK_NAME}" --- apiVersion: bootstrap.cluster.x-k8s.io/v1alpha4 kind: KubeadmConfigTemplate