Using client-go to Access the CRD Resource Network of CCI
Initializing a Project
Create a project named examples.com/cci-examples.
The project depends on k8s.io/client-go and k8s.io/code-generator of the following versions (for reference only):
- k8s.io/client-go@kubernetes-1.15.0, k8s.io/code-generator@kubernetes-1.15.0
- k8s.io/client-go@kubernetes-1.16.0, k8s.io/code-generator@kubernetes-1.16.0
- k8s.io/client-go@kubernetes-1.17.0, k8s.io/code-generator@kubernetes-1.17.0
- k8s.io/client-go@kubernetes-1.18.0, k8s.io/code-generator@kubernetes-1.18.0
- k8s.io/client-go@kubernetes-1.19.0, k8s.io/code-generator@kubernetes-1.19.0
- k8s.io/client-go@kubernetes-1.20.0, k8s.io/code-generator@kubernetes-1.20.0
mkdir -p examples.com/cci-examples cd examples.com/cci-examples/ go mod init examples.com/cci-examples go get k8s.io/client-go@kubernetes-1.15.0 go get k8s.io/code-generator@kubernetes-1.15.0
Defining the CRD Resource Network
Create the pkg/apis/networking.cci.io/v1beta1 folder, where networking.cci.io indicates the group of the CRD resource and v1beta1 indicates the version of the CRD resource.
mkdir -p pkg/apis/networking.cci.io/v1beta1
Create the following files in the new folder:
doc.go
// +k8s:deepcopy-gen=package // +groupName=networking.cci.io // +groupGoName=NetworkingCCI package v1beta1
types.go
package v1beta1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // NetworkList is a list of network resource in container. type NetworkList struct { metav1.TypeMeta `json:",inline"` // Standard list metadata. // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata // +optional metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` Items []Network `json:"items" protobuf:"bytes,2,rep,name=items"` } // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Network is a network resource in container. type Network struct { metav1.TypeMeta `json:",inline"` // +optional metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Spec defines the attributes on a network // +optional Spec NetworkSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` // Status describes the network status // +optional Status NetworkStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` } // NetworkSpec describes the attributes on a network resource. type NetworkSpec struct { // network type NetworkType string `json:"networkType,omitempty" protobuf:"bytes,5,opt,name=networkType"` // ID of the VPC to attach AttachedVPC string `json:"attachedVPC,omitempty" protobuf:"bytes,4,opt,name=attachedVPC"` // network ID NetworkID string `json:"networkID,omitempty" protobuf:"bytes,7,opt,name=networkID"` // Subnet ID SubnetID string `json:"subnetID,omitempty" protobuf:"bytes,8,opt,name=subnetID"` // available zone AvailableZone string `json:"availableZone,omitempty" protobuf:"bytes,9,opt,name=availableZone"` // The CIDR of the network CIDR string `json:"cidr,omitempty" protobuf:"bytes,3,opt,name=cidr"` } // NetworkStatus describes the status of a network type NetworkStatus struct { // State describes the network state // +optional State string `json:"state" protobuf:"bytes,1,opt,name=state"` // Message describes why network is in current state // +optional Message string `json:"message,omitempty" protobuf:"bytes,2,opt,name=message"` } const ( // NetworkInitializing means the network is initializing NetworkInitializing = "Initializing" // NetworkPending means the network is processing NetworkPending = "Pending" // NetworkActive means the network is available NetworkActive = "Active" // NetworkFailed means the network is not available NetworkFailed = "Failed" // NetworkTerminating means the network is undergoing graceful termination NetworkTerminating = "Terminating" )
register.go
package v1beta1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) // GroupName is the group name use in this package const GroupName = "networking.cci.io" // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} // Resource takes an unqualified resource and returns a Group qualified GroupResource func Resource(resource string) schema.GroupResource { return SchemeGroupVersion.WithResource(resource).GroupResource() } var ( // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) localSchemeBuilder = &SchemeBuilder AddToScheme = localSchemeBuilder.AddToScheme ) // Adds the list of known types to the given scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &Network{}, &NetworkList{}, ) // Add the watch version that applies metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil }
Creating a Build Script
Create the hack folder for storing the build script and dependency files.
mkdir hack
Create the following files in the hack folder:
tools.go, which is created to depend on code-generator.
// +build tools /* Copyright 2019 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. */ // This package imports things required by build scripts, to force `go mod` to see them as dependencies package tools import _ "k8s.io/code-generator"
update-codegen.sh
#!/usr/bin/env bash # Copyright 2017 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. set -o errexit set -o nounset set -o pipefail SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)} # generate the code with: # --output-base because this script should also be able to run inside the vendor dir of # k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir # instead of the $GOPATH directly. For normal projects this can be dropped. # generators deepcopy,client,informer,lister export CLIENTSET_PKG_NAME=networking.cci.io export CLIENTSET_NAME_VERSIONED=v1beta1 "${CODEGEN_PKG}"/generate-groups.sh "deepcopy,client" \ examples.com/cci-examples/pkg/client examples.com/cci-examples/pkg/apis \ networking.cci.io:v1beta1 \ --output-base "$(dirname "${BASH_SOURCE[0]}")/../../.." \ --go-header-file "${SCRIPT_ROOT}"/hack/boilerplate.go.txt # To use your own boilerplate text append: # --go-header-file "${SCRIPT_ROOT}"/hack/custom-boilerplate.go.txt
Header of the file built by boilerplate.go.txt. You can customize it.
/* 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. */
All preparations are complete. The file structure of the directory is as follows:
├── go.mod ├── go.sum ├── hack │ ├── boilerplate.go.txt │ ├── tools.go │ └── update-codegen.sh └── pkg └── apis └── networking.cci.io └── v1beta1 ├── doc.go ├── register.go └── types.go 5 directories, 8 files
Executing the Name Generation Code
Run the following commands in the Linux environment:
# Generate the vendor folder. go mod vendor # Run the build script. chmod 755 hack/update-codegen.sh # hack/update-codegen.sh will execute vendor/k8s.io/code-generator/generate-groups.sh. chmod 755 vendor/k8s.io/code-generator/generate-groups.sh ./hack/update-codegen.sh
After the commands are executed successfully, code is generated. The directory structure is as follows:
├── go.mod ├── go.sum ├── hack │ ├── boilerplate.go.txt │ ├── tools.go │ └── update-codegen.sh └── pkg ├── apis │ └── networking.cci.io │ └── v1beta1 │ ├── doc.go │ ├── register.go │ ├── types.go │ └── zz_generated.deepcopy.go └── client └── networking.cci.io └── v1beta1 ├── clientset.go ├── doc.go ├── fake │ ├── clientset_generated.go │ ├── doc.go │ └── register.go ├── scheme │ ├── doc.go │ └── register.go └── typed └── networking.cci.io └── v1beta1 ├── doc.go ├── fake │ ├── doc.go │ ├── fake_network.go │ └── fake_networking.cci.io_client.go ├── generated_expansion.go ├── network.go └── networking.cci.io_client.go
Example Code: Creating a Network
The example has been tested for the following versions:
k8s.io/client-go@kubernetes-1.15.0
k8s.io/code-generator@kubernetes-1.15.0
import ( "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/tools/clientcmd" "examples.com/cci-examples/pkg/apis/networking.cci.io/v1beta1" clientset "examples.com/cci-examples/pkg/client/networking.cci.io/v1beta1" ) const ( name = "test-k8s-client-namespace-cn-north-1-default-network" namespace = "test-k8s-client-namespace" ) // CreateNetwork indicates creating a network and waiting until its status changes to Active. // "Namespace and Network": https://support.huaweicloud.com/intl/en-us/devg-cci/cci_05_0023.html. // API Reference: https://support.huaweicloud.com/intl/en-us/api-cci/createNetworkingCciIoV1beta1NamespacedNetwork.html func CreateNetwork() (*v1beta1.Network, error) { config, _ := clientcmd.BuildConfigFromFlags("", "{path to kubeconfig}") cs, err := clientset.NewForConfig(config) if err != nil { return nil, err } projectId := "<Account ID, which can be obtained from My Credentials>" domainId := "<Project ID, which can be obtained from My Credentials>" securityGroupID := "<Security group ID, which can be obtained from the Security Groups page of the Network Console>" availableZone := "<AZ name, for example, cn-north-1a, cn-north-4a, or cn-east-3a>" vpcID := "VPC ID, which can be obtained from the VPC console" cidr := "<Subnet CIDR block, for example, 192.168.128.0/18>" networkID := "<Subnet network ID, which can be obtained from the Subnets page of the VPC console>" subnetID := "<Subnet ID, which can be obtained from the Subnets page of the VPC console>" network := &v1beta1.Network{ ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ "network.alpha.kubernetes.io/default-security-group": securityGroupID, "network.alpha.kubernetes.io/domain-id": domainId, "network.alpha.kubernetes.io/project-id": projectId, }, Name: name, }, Spec: v1beta1.NetworkSpec{ AvailableZone: availableZone, CIDR: cidr, AttachedVPC: vpcID, NetworkID: networkID, NetworkType: "underlay_neutron", SubnetID: subnetID, }, } network, err = cs.NetworkingCCIV1beta1().Networks(namespace).Create(network) if err != nil { return nil, err } // Query the network status and wait until the status changes to Active. err = wait.Poll(time.Second*5, time.Second*30, func() (done bool, err error) { network, err = cs.NetworkingCCIV1beta1().Networks(namespace).Get(name, metav1.GetOptions{}) if err != nil { return false, err } if network.Status.State == v1beta1.NetworkActive { return true, nil } return false, nil }) return network, err }
Feedback
Was this page helpful?
Provide feedbackThank you very much for your feedback. We will continue working to improve the documentation.See the reply and handling status in My Cloud VOC.
For any further questions, feel free to contact us through the chatbot.
Chatbot