From 96b900ab898b3fc5df630b747613e03eb0e44108 Mon Sep 17 00:00:00 2001 From: Shilpa-Gokul Date: Thu, 9 Feb 2023 11:13:31 +0530 Subject: [PATCH] Add support for port create command --- cmd/capibmadm/cmd/powervs/port/create.go | 139 +++++++++++++++++++++++ cmd/capibmadm/cmd/powervs/port/doc.go | 18 +++ cmd/capibmadm/cmd/powervs/port/port.go | 32 ++++++ cmd/capibmadm/cmd/powervs/port/type.go | 77 +++++++++++++ cmd/capibmadm/cmd/powervs/powervs.go | 2 + cmd/capibmadm/utils/utils.go | 9 ++ go.mod | 2 +- go.sum | 2 + 8 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 cmd/capibmadm/cmd/powervs/port/create.go create mode 100644 cmd/capibmadm/cmd/powervs/port/doc.go create mode 100644 cmd/capibmadm/cmd/powervs/port/port.go create mode 100644 cmd/capibmadm/cmd/powervs/port/type.go diff --git a/cmd/capibmadm/cmd/powervs/port/create.go b/cmd/capibmadm/cmd/powervs/port/create.go new file mode 100644 index 0000000000..292457e9a3 --- /dev/null +++ b/cmd/capibmadm/cmd/powervs/port/create.go @@ -0,0 +1,139 @@ +/* +Copyright 2023 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 port + +import ( + "context" + "fmt" + client "github.com/IBM-Cloud/power-go-client/clients/instance" + "github.com/IBM-Cloud/power-go-client/power/models" + "github.com/spf13/cobra" + "k8s.io/klog/v2" + "os" + "sigs.k8s.io/cluster-api-provider-ibmcloud/cmd/capibmadm/clients/iam" + "sigs.k8s.io/cluster-api-provider-ibmcloud/cmd/capibmadm/clients/powervs" + "sigs.k8s.io/cluster-api-provider-ibmcloud/cmd/capibmadm/options" + "sigs.k8s.io/cluster-api-provider-ibmcloud/cmd/capibmadm/printer" + "sigs.k8s.io/cluster-api-provider-ibmcloud/cmd/capibmadm/utils" + logf "sigs.k8s.io/cluster-api/cmd/clusterctl/log" + "strings" +) + +type portCreateOptions struct { + networkID string + ipAddress string + description string +} + +func CreateCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "create PORT_NUMBER", + Short: "Create PowerVS Port", + Example: ` +# Create PowerVS port, provided networkID and IPAddress +export IBMCLOUD_API_KEY= +capibmadm powervs port create --network --ip-address <10.10.0.1> --description --service-instance-id --zone `, + } + + var portCreateOption portCreateOptions + cmd.Flags().StringVar(&portCreateOption.networkID, "network", "", "Network ID/ name on which port is to be created (Required)") + cmd.Flags().StringVar(&portCreateOption.ipAddress, "ip-address", "", "IP Address to be assigned to the port") + cmd.Flags().StringVar(&portCreateOption.description, "description", "", "Description of the port") + cmd.RunE = func(cmd *cobra.Command, args []string) error { + if err := createPort(cmd.Context(), portCreateOption); err != nil { + return err + } + return nil + } + options.AddCommonFlags(cmd) + _ = cmd.MarkFlagRequired("network") + return cmd +} + +func createPort(ctx context.Context, portCreateOption portCreateOptions) error { + log := logf.Log + log.Info("Creating Port ", "Network ID/Name", portCreateOption.networkID, "IP Address", portCreateOption.ipAddress, "Description", portCreateOption.description, "service-instance-id", options.GlobalOptions.ServiceInstanceID, "zone", options.GlobalOptions.PowerVSZone) + accountID, err := utils.GetAccountID(ctx, iam.GetIAMAuth()) + if err != nil { + return err + } + session, err := powervs.NewPISession(accountID, options.GlobalOptions.PowerVSZone, options.GlobalOptions.Debug) + if err != nil { + return err + } + + networkClient := client.NewIBMPINetworkClient(ctx, session, options.GlobalOptions.ServiceInstanceID) + networks, err := networkClient.GetAll() + if err != nil { + return err + } + var networkNames, networkIDs []string + for _, net := range networks.Networks { + networkIDs = append(networkIDs, *net.NetworkID) + networkNames = append(networkNames, *net.Name) + } + + var netID string + + if utils.Contains(networkIDs, portCreateOption.networkID) { + netID = portCreateOption.networkID + } else if utils.Contains(networkNames, portCreateOption.networkID) { + for _, n := range networks.Networks { + if *n.Name == portCreateOption.networkID { + netID = *n.NetworkID + } + } + } else { + return fmt.Errorf("not able to find network: \"%s\" by ID or name in the list: ids:[%s], names: [%s]", portCreateOption.networkID, strings.Join(networkIDs, ","), strings.Join(networkNames, ",")) + } + params := &models.NetworkPortCreate{ + IPAddress: portCreateOption.ipAddress, + Description: portCreateOption.description, + } + + port, err := networkClient.CreatePort(netID, params) + if err != nil { + return fmt.Errorf("failed to create a port, err: %v", err) + } + klog.Infof("Successfully created a port, id: %s", *port.PortID) + + listByVersion := PortList{ + Items: []PortSpec{}, + } + + listByVersion.Items = append(listByVersion.Items, PortSpec{ + Description: *port.Description, + ExternalIP: port.ExternalIP, + IPAddress: *port.IPAddress, + MacAddress: *port.MacAddress, + PortID: *port.PortID, + Status: *port.Status, + }) + + printerObj, err := printer.New(options.GlobalOptions.Output, os.Stdout) + if err != nil { + return fmt.Errorf("failed creating output printer: %w", err) + } + + if options.GlobalOptions.Output == printer.PrinterTypeTable { + table := listByVersion.ToTable() + printerObj.Print(table) + } else { + printerObj.Print(listByVersion) + } + return nil +} diff --git a/cmd/capibmadm/cmd/powervs/port/doc.go b/cmd/capibmadm/cmd/powervs/port/doc.go new file mode 100644 index 0000000000..832920f55c --- /dev/null +++ b/cmd/capibmadm/cmd/powervs/port/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2023 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 port contains the commands to operate on Power VS Port resources. +package port diff --git a/cmd/capibmadm/cmd/powervs/port/port.go b/cmd/capibmadm/cmd/powervs/port/port.go new file mode 100644 index 0000000000..b506bfd364 --- /dev/null +++ b/cmd/capibmadm/cmd/powervs/port/port.go @@ -0,0 +1,32 @@ +/* +Copyright 2023 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 port + +import ( + "github.com/spf13/cobra" +) + +// Commands function to add PowerVS port commands. +func Commands() *cobra.Command { + cmd := &cobra.Command{ + Use: "port", + Short: "Perform PowerVS port operations", + } + cmd.AddCommand(CreateCommand()) + + return cmd +} diff --git a/cmd/capibmadm/cmd/powervs/port/type.go b/cmd/capibmadm/cmd/powervs/port/type.go new file mode 100644 index 0000000000..a90b912ba2 --- /dev/null +++ b/cmd/capibmadm/cmd/powervs/port/type.go @@ -0,0 +1,77 @@ +/* + Copyright 2023 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 port + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// PortSpec defines a port +type PortSpec struct { + PortID string `json:"id"` + Description string `json:"description"` + ExternalIP string `json:"externalIP,omitempty"` + IPAddress string `json:"ipAddress"` + MacAddress string `json:"macAddress"` + Status string `json:"status"` +} + +// PortList defines a list of Ports. +type PortList struct { + Items []PortSpec `json:"items"` +} + +// ToTable converts List to *metav1.Table. +func (portList *PortList) ToTable() *metav1.Table { + table := &metav1.Table{ + TypeMeta: metav1.TypeMeta{ + APIVersion: metav1.SchemeGroupVersion.String(), + Kind: "Table", + }, + ColumnDefinitions: []metav1.TableColumnDefinition{ + { + Name: "DESCRIPTION", + Type: "string", + }, + { + Name: "EXTERNALIP", + Type: "string", + }, + { + Name: "IPADDRESS", + Type: "string", + }, + { + Name: "MACADDRESS", + Type: "string", + }, + { + Name: "PORTID", + Type: "string", + }, + { + Name: "STATUS", + Type: "string", + }, + }, + } + + for _, port := range portList.Items { + row := metav1.TableRow{ + Cells: []interface{}{port.Description, port.ExternalIP, port.IPAddress, port.MacAddress, port.PortID, port.Status}, + } + table.Rows = append(table.Rows, row) + } + return table +} diff --git a/cmd/capibmadm/cmd/powervs/powervs.go b/cmd/capibmadm/cmd/powervs/powervs.go index e6f444e490..b6f867c004 100644 --- a/cmd/capibmadm/cmd/powervs/powervs.go +++ b/cmd/capibmadm/cmd/powervs/powervs.go @@ -20,6 +20,7 @@ import ( "github.com/spf13/cobra" "sigs.k8s.io/cluster-api-provider-ibmcloud/cmd/capibmadm/cmd/powervs/network" + "sigs.k8s.io/cluster-api-provider-ibmcloud/cmd/capibmadm/cmd/powervs/port" "sigs.k8s.io/cluster-api-provider-ibmcloud/cmd/capibmadm/options" ) @@ -38,6 +39,7 @@ func Commands() *cobra.Command { _ = cmd.MarkPersistentFlagRequired("zone") cmd.AddCommand(network.Commands()) + cmd.AddCommand(port.Commands()) return cmd } diff --git a/cmd/capibmadm/utils/utils.go b/cmd/capibmadm/utils/utils.go index c258d7cabd..94e456ef33 100644 --- a/cmd/capibmadm/utils/utils.go +++ b/cmd/capibmadm/utils/utils.go @@ -111,3 +111,12 @@ func DereferencePointer(value interface{}) interface{} { } return nil } + +func Contains(s []string, e string) bool { + for _, a := range s { + if a == e { + return true + } + } + return false +} diff --git a/go.mod b/go.mod index 0d7b1d0751..d786af3aae 100644 --- a/go.mod +++ b/go.mod @@ -87,7 +87,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/huandu/xstrings v1.3.3 // indirect github.com/imdario/mergo v0.3.13 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.1 // indirect diff --git a/go.sum b/go.sum index 83b2862045..f400371d6a 100644 --- a/go.sum +++ b/go.sum @@ -506,6 +506,8 @@ github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=