diff --git a/cmd/controller-manager/app/controllers.go b/cmd/controller-manager/app/controllers.go index 49e784d6f..aabcb9546 100644 --- a/cmd/controller-manager/app/controllers.go +++ b/cmd/controller-manager/app/controllers.go @@ -32,8 +32,9 @@ import ( "kubesphere.io/kubesphere/pkg/controller/globalrole" "kubesphere.io/kubesphere/pkg/controller/globalrolebinding" "kubesphere.io/kubesphere/pkg/controller/job" + "kubesphere.io/kubesphere/pkg/controller/network/ippool" "kubesphere.io/kubesphere/pkg/controller/network/nsnetworkpolicy" - "kubesphere.io/kubesphere/pkg/controller/network/provider" + "kubesphere.io/kubesphere/pkg/controller/network/nsnetworkpolicy/provider" "kubesphere.io/kubesphere/pkg/controller/pipeline" "kubesphere.io/kubesphere/pkg/controller/s2ibinary" "kubesphere.io/kubesphere/pkg/controller/s2irun" @@ -49,6 +50,8 @@ import ( "kubesphere.io/kubesphere/pkg/simple/client/k8s" ldapclient "kubesphere.io/kubesphere/pkg/simple/client/ldap" "kubesphere.io/kubesphere/pkg/simple/client/network" + ippoolclient "kubesphere.io/kubesphere/pkg/simple/client/network/ippool" + calicoclient "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix" "kubesphere.io/kubesphere/pkg/simple/client/s3" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -62,6 +65,7 @@ func addControllers( devopsClient devops.Interface, s3Client s3.Interface, ldapClient ldapclient.Interface, + options *k8s.KubernetesOptions, authenticationOptions *authoptions.AuthenticationOptions, openpitrixClient openpitrix.Client, multiClusterEnabled bool, @@ -280,6 +284,21 @@ func addControllers( kubernetesInformer.Core().V1().Namespaces(), nsnpProvider, networkOptions.NSNPOptions) } + var ippoolController manager.Runnable + if networkOptions.EnableIPPool { + var ippoolProvider ippoolclient.Provider + ippoolProvider = ippoolclient.NewProvider(client.KubeSphere(), networkOptions.IPPoolOptions) + if networkOptions.IPPoolOptions.Calico != nil { + ippoolProvider = calicoclient.NewProvider(client.KubeSphere(), *networkOptions.IPPoolOptions.Calico, options) + } + ippoolController = ippool.NewIPPoolController(kubesphereInformer.Network().V1alpha1().IPPools(), + kubesphereInformer.Network().V1alpha1().IPAMBlocks(), + client.Kubernetes(), + client.KubeSphere(), + networkOptions.IPPoolOptions, + ippoolProvider) + } + controllers := map[string]manager.Runnable{ "virtualservice-controller": vsController, "destinationrule-controller": drController, @@ -299,6 +318,7 @@ func addControllers( "workspacetemplate-controller": workspaceTemplateController, "workspacerole-controller": workspaceRoleController, "workspacerolebinding-controller": workspaceRoleBindingController, + "ippool-controller": ippoolController, } if devopsClient != nil { diff --git a/cmd/controller-manager/app/server.go b/cmd/controller-manager/app/server.go index e1f1d8ea8..335e26a85 100644 --- a/cmd/controller-manager/app/server.go +++ b/cmd/controller-manager/app/server.go @@ -18,6 +18,8 @@ package app import ( "fmt" + "os" + "github.com/spf13/cobra" utilerrors "k8s.io/apimachinery/pkg/util/errors" cliflag "k8s.io/component-base/cli/flag" @@ -38,7 +40,6 @@ import ( "kubesphere.io/kubesphere/pkg/simple/client/openpitrix" "kubesphere.io/kubesphere/pkg/simple/client/s3" "kubesphere.io/kubesphere/pkg/utils/term" - "os" application "sigs.k8s.io/application/controllers" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/runtime/signals" @@ -212,6 +213,7 @@ func run(s *options.KubeSphereControllerManagerOptions, stopCh <-chan struct{}) devopsClient, s3Client, ldapClient, + s.KubernetesOptions, s.AuthenticationOptions, openpitrixClient, s.MultiClusterOptions.Enable, diff --git a/config/crds/network.kubesphere.io_ipamblocks.yaml b/config/crds/network.kubesphere.io_ipamblocks.yaml new file mode 100644 index 000000000..36dbe66a2 --- /dev/null +++ b/config/crds/network.kubesphere.io_ipamblocks.yaml @@ -0,0 +1,79 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: ipamblocks.network.kubesphere.io +spec: + group: network.kubesphere.io + names: + kind: IPAMBlock + plural: ipamblocks + scope: Cluster + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + description: Standard object's metadata. + type: object + spec: + description: Specification of the IPAMBlock. + properties: + allocations: + items: + type: integer + nullable: true + type: array + attributes: + items: + properties: + handle_id: + type: string + secondary: + additionalProperties: + type: string + type: object + type: object + type: array + cidr: + type: string + deleted: + type: boolean + id: + format: int32 + type: integer + unallocated: + items: + type: integer + type: array + required: + - allocations + - attributes + - cidr + - deleted + - id + - unallocated + type: object + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crds/network.kubesphere.io_ipamhandles.yaml b/config/crds/network.kubesphere.io_ipamhandles.yaml new file mode 100644 index 000000000..031647648 --- /dev/null +++ b/config/crds/network.kubesphere.io_ipamhandles.yaml @@ -0,0 +1,57 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: ipamhandles.network.kubesphere.io +spec: + group: network.kubesphere.io + names: + kind: IPAMHandle + plural: ipamhandles + scope: Cluster + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + description: Standard object's metadata. + type: object + spec: + description: Specification of the IPAMHandle. + properties: + block: + additionalProperties: + type: integer + type: object + deleted: + type: boolean + handleID: + type: string + required: + - block + - deleted + - handleID + type: object + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crds/network.kubesphere.io_ippools.yaml b/config/crds/network.kubesphere.io_ippools.yaml new file mode 100644 index 000000000..26bedfa0c --- /dev/null +++ b/config/crds/network.kubesphere.io_ippools.yaml @@ -0,0 +1,121 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: ippools.network.kubesphere.io +spec: + group: network.kubesphere.io + names: + kind: IPPool + plural: ippools + scope: Cluster + validation: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + blockSize: + description: The block size to use for IP address assignments from this + pool. Defaults to 26 for IPv4 and 112 for IPv6. + type: integer + cidr: + description: The pool CIDR. + type: string + disabled: + description: When disabled is true, IPAM will not assign addresses + from this pool. + type: boolean + dns: + description: DNS contains values interesting for DNS resolvers + properties: + domain: + type: string + nameservers: + items: + type: string + type: array + options: + items: + type: string + type: array + search: + items: + type: string + type: array + type: object + gateway: + type: string + namespace: + type: string + rangeEnd: + type: string + rangeStart: + type: string + routes: + items: + properties: + dst: + type: string + gateway: + type: string + type: object + type: array + type: + type: string + vlanConfig: + properties: + master: + type: string + vlanId: + format: int32 + type: integer + required: + - master + - vlanId + type: object + workspace: + type: string + required: + - cidr + - type + type: object + status: + properties: + allocations: + description: Allocations should equal to (Total - Reserved - Unallocated) + type: integer + capacity: + type: integer + reserved: + type: integer + synced: + type: boolean + unallocated: + type: integer + type: object + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/go.mod b/go.mod index dd304be7b..a6b278dfb 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,8 @@ require ( github.com/aws/aws-sdk-go v1.25.21 github.com/beevik/etree v1.1.0 github.com/container-storage-interface/spec v1.2.0 + github.com/containernetworking/cni v0.8.0 + github.com/davecgh/go-spew v1.1.1 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/docker/distribution v2.7.1+incompatible github.com/docker/docker v1.4.2-0.20190822205725-ed20165a37b4 @@ -94,6 +96,7 @@ require ( k8s.io/klog v1.0.0 k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a k8s.io/kubectl v0.17.3 + k8s.io/utils v0.0.0-20191114184206-e782cd3c129f openpitrix.io/openpitrix v0.4.9-0.20200611125425-ae07f141e797 sigs.k8s.io/application v1.0.0 sigs.k8s.io/controller-runtime v0.5.0 diff --git a/go.sum b/go.sum index 314c8c248..51081fff6 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= code.cloudfoundry.org/bytefmt v0.0.0-20190710193110-1eb035ffe2b6 h1:tW+ztA4A9UT9xnco5wUjW1oNi35k22eUEn9tNpPYVwE= code.cloudfoundry.org/bytefmt v0.0.0-20190710193110-1eb035ffe2b6/go.mod h1:wN/zk7mhREp/oviagqUXY3EwuHhWyOvAdsn5Y4CzOrc= @@ -74,6 +75,8 @@ github.com/container-storage-interface/spec v1.2.0 h1:bD9KIVgaVKKkQ/UbVUY9kCaH/C github.com/container-storage-interface/spec v1.2.0/go.mod h1:6URME8mwIBbpVyZV93Ce5St17xBiQJQY67NDsuohiy4= github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containernetworking/cni v0.8.0 h1:BT9lpgGoH4jw3lFC7Odz2prU5ruiYKcgAjMCbgybcKI= +github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= diff --git a/pkg/apis/network/calicov3/block_affinity_types.go b/pkg/apis/network/calicov3/block_affinity_types.go new file mode 100644 index 000000000..461cfcb9d --- /dev/null +++ b/pkg/apis/network/calicov3/block_affinity_types.go @@ -0,0 +1,41 @@ +// Copyright (c) 2019-2020 Tigera, Inc. All rights reserved. + +// 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 calicov3 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + v3 "github.com/projectcalico/libcalico-go/lib/apis/v3" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient:nonNamespaced +// +k8s:openapi-gen=true +// +kubebuilder:resource:scope=Cluster +type BlockAffinity struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec v3.BlockAffinitySpec `json:"spec,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// BlockAffinityList contains a list of BlockAffinity resources. +type BlockAffinityList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []BlockAffinity `json:"items"` +} diff --git a/pkg/apis/network/calicov3/doc.go b/pkg/apis/network/calicov3/doc.go new file mode 100644 index 000000000..94284e097 --- /dev/null +++ b/pkg/apis/network/calicov3/doc.go @@ -0,0 +1,4 @@ +// API Schema definitions for configuring the installation of Calico and Calico Enterprise +// +k8s:deepcopy-gen=package,register +// +groupName=crd.projectcalico.org +package calicov3 diff --git a/pkg/apis/network/calicov3/ipamblock_types.go b/pkg/apis/network/calicov3/ipamblock_types.go new file mode 100644 index 000000000..f3b343991 --- /dev/null +++ b/pkg/apis/network/calicov3/ipamblock_types.go @@ -0,0 +1,85 @@ +// Copyright (c) 2019-2020 Tigera, Inc. All rights reserved. + +// 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 calicov3 + +import ( + v3 "github.com/projectcalico/libcalico-go/lib/apis/v3" + cnet "github.com/projectcalico/libcalico-go/lib/net" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "strings" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient:nonNamespaced +// +k8s:openapi-gen=true +// +kubebuilder:resource:scope=Cluster +type IPAMBlock struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec v3.IPAMBlockSpec `json:"spec,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// IPAMBlockList contains a list of IPAMBlock resources. +type IPAMBlockList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []IPAMBlock `json:"items"` +} + +func (b *IPAMBlock) NumReservedAddresses() int { + sum := 0 + for _, attrIdx := range b.Spec.Allocations { + if attrIdx == nil { + continue + } + attrs := b.Spec.Attributes[*attrIdx] + if attrs.AttrPrimary == nil || strings.ToLower(*attrs.AttrPrimary) == WindowsReservedHandle { + sum += 1 + } + } + return sum +} + +// Get number of addresses covered by the block +func (b *IPAMBlock) NumAddresses() int { + _, cidr, _ := cnet.ParseCIDR(b.Spec.CIDR) + ones, size := cidr.Mask.Size() + numAddresses := 1 << uint(size-ones) + return numAddresses +} + +func (b *IPAMBlock) NumFreeAddresses() int { + return len(b.Spec.Unallocated) +} + +// windwowsReservedHandle is the handle used to reserve addresses required for Windows +// networking so that workloads do not get assigned these addresses. +const WindowsReservedHandle = "windows-reserved-ipam-handle" + +func (b *IPAMBlock) Empty() bool { + for _, attrIdx := range b.Spec.Allocations { + if attrIdx == nil { + continue + } + attrs := b.Spec.Attributes[*attrIdx] + if attrs.AttrPrimary == nil || strings.ToLower(*attrs.AttrPrimary) != WindowsReservedHandle { + return false + } + } + return true +} diff --git a/pkg/apis/network/calicov3/ippool_types.go b/pkg/apis/network/calicov3/ippool_types.go new file mode 100644 index 000000000..6884b977d --- /dev/null +++ b/pkg/apis/network/calicov3/ippool_types.go @@ -0,0 +1,49 @@ +// Copyright (c) 2017-2020 Tigera, Inc. All rights reserved. + +// 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 calicov3 + +import ( + cnet "github.com/projectcalico/libcalico-go/lib/net" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + v3 "github.com/projectcalico/libcalico-go/lib/apis/v3" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient:nonNamespaced +// +k8s:openapi-gen=true +// +kubebuilder:resource:scope=Cluster +type IPPool struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec v3.IPPoolSpec `json:"spec,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// IPPoolList contains a list of IPPool resources. +type IPPoolList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []IPPool `json:"items"` +} + +func (p IPPool) NumAddresses() int { + _, cidr, _ := cnet.ParseCIDR(p.Spec.CIDR) + ones, size := cidr.Mask.Size() + numAddresses := 1 << uint(size-ones) + return numAddresses +} diff --git a/pkg/apis/network/calicov3/register.go b/pkg/apis/network/calicov3/register.go new file mode 100644 index 000000000..46f571a67 --- /dev/null +++ b/pkg/apis/network/calicov3/register.go @@ -0,0 +1,42 @@ +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. + +// 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 calicov3 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/runtime/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "crd.projectcalico.org", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} + + // AddToScheme is required by pkg/client/... + AddToScheme = SchemeBuilder.AddToScheme +) + +func init() { + SchemeBuilder.Register(&BlockAffinity{}, &BlockAffinityList{}) + SchemeBuilder.Register(&IPAMBlock{}, &IPAMBlockList{}) + SchemeBuilder.Register(&IPPool{}, &IPPoolList{}) +} + +// Resource is required by pkg/client/listers/... +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/pkg/apis/network/calicov3/zz_generated.deepcopy.go b/pkg/apis/network/calicov3/zz_generated.deepcopy.go new file mode 100644 index 000000000..ab3e51879 --- /dev/null +++ b/pkg/apis/network/calicov3/zz_generated.deepcopy.go @@ -0,0 +1,205 @@ +// +build !ignore_autogenerated + +/* +Copyright 2020 The KubeSphere 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 deepcopy-gen. DO NOT EDIT. + +package calicov3 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BlockAffinity) DeepCopyInto(out *BlockAffinity) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockAffinity. +func (in *BlockAffinity) DeepCopy() *BlockAffinity { + if in == nil { + return nil + } + out := new(BlockAffinity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BlockAffinity) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BlockAffinityList) DeepCopyInto(out *BlockAffinityList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]BlockAffinity, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockAffinityList. +func (in *BlockAffinityList) DeepCopy() *BlockAffinityList { + if in == nil { + return nil + } + out := new(BlockAffinityList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BlockAffinityList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPAMBlock) DeepCopyInto(out *IPAMBlock) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAMBlock. +func (in *IPAMBlock) DeepCopy() *IPAMBlock { + if in == nil { + return nil + } + out := new(IPAMBlock) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IPAMBlock) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPAMBlockList) DeepCopyInto(out *IPAMBlockList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]IPAMBlock, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAMBlockList. +func (in *IPAMBlockList) DeepCopy() *IPAMBlockList { + if in == nil { + return nil + } + out := new(IPAMBlockList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IPAMBlockList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPPool) DeepCopyInto(out *IPPool) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPPool. +func (in *IPPool) DeepCopy() *IPPool { + if in == nil { + return nil + } + out := new(IPPool) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IPPool) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPPoolList) DeepCopyInto(out *IPPoolList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]IPPool, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPPoolList. +func (in *IPPoolList) DeepCopy() *IPPoolList { + if in == nil { + return nil + } + out := new(IPPoolList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IPPoolList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/pkg/apis/network/v1alpha1/ipamblock_types.go b/pkg/apis/network/v1alpha1/ipamblock_types.go new file mode 100644 index 000000000..c5272e65c --- /dev/null +++ b/pkg/apis/network/v1alpha1/ipamblock_types.go @@ -0,0 +1,341 @@ +/* +Copyright 2020 The KubeSphere 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 v1alpha1 + +import ( + "fmt" + "github.com/projectcalico/libcalico-go/lib/names" + "math/big" + "reflect" + "strings" + + cnet "github.com/projectcalico/libcalico-go/lib/net" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + ResourceKindIPAMBlock = "IPAMBlock" + ResourceSingularIPAMBlock = "ipamblock" + ResourcePluralIPAMBlock = "ipamblocks" + + IPAMBlockAttributePod = "pod" + IPAMBlockAttributeVm = "vm" + IPAMBlockAttributeWorkloadType = "workload-type" + IPAMBlockAttributeNamespace = "namespace" + IPAMBlockAttributeWorkspace = "workspace" + IPAMBlockAttributeNode = "node" + IPAMBlockAttributePool = "pool-name" + IPAMBlockAttributeType = "pool-type" + + ReservedHandle = "kubesphere-reserved-handle" + ReservedNote = "kubesphere reserved" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:openapi-gen=true +// +kubebuilder:resource:scope=Cluster +type IPAMBlock struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + metav1.ObjectMeta `json:"metadata,omitempty"` + // Specification of the IPAMBlock. + Spec IPAMBlockSpec `json:"spec,omitempty"` +} + +// IPAMBlockSpec contains the specification for an IPAMBlock resource. +type IPAMBlockSpec struct { + ID uint32 `json:"id"` + CIDR string `json:"cidr"` + Allocations []*int `json:"allocations"` + Unallocated []int `json:"unallocated"` + Attributes []AllocationAttribute `json:"attributes"` + Deleted bool `json:"deleted"` +} + +type AllocationAttribute struct { + AttrPrimary string `json:"handle_id,omitempty"` + AttrSecondary map[string]string `json:"secondary,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient:nonNamespaced +type IPAMBlockList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []IPAMBlock `json:"items"` +} + +// The caller needs to check that the returned slice length is correct. +func (b *IPAMBlock) AutoAssign( + num int, handleID string, attrs map[string]string) []cnet.IPNet { + + // Walk the allocations until we find enough addresses. + ordinals := []int{} + for len(b.Spec.Unallocated) > 0 && len(ordinals) < num { + ordinals = append(ordinals, b.Spec.Unallocated[0]) + b.Spec.Unallocated = b.Spec.Unallocated[1:] + } + + // Create slice of IPs and perform the allocations. + ips := []cnet.IPNet{} + ip, mask, _ := cnet.ParseCIDR(b.Spec.CIDR) + for _, o := range ordinals { + attrIndex := b.findOrAddAttribute(handleID, attrs) + b.Spec.Allocations[o] = &attrIndex + ipNets := cnet.IPNet(*mask) + ipNets.IP = cnet.IncrementIP(*ip, big.NewInt(int64(o))).IP + ips = append(ips, ipNets) + } + + return ips +} + +func (b *IPAMBlock) String() string { + return fmt.Sprintf("%d-%s", b.Spec.ID, b.Spec.CIDR) +} + +func (b *IPAMBlock) ID() uint32 { + return b.Spec.ID +} + +func (b *IPAMBlock) BlockName() string { + _, cidr, _ := cnet.ParseCIDR(b.Spec.CIDR) + return fmt.Sprintf("%d-%s", b.ID(), names.CIDRToName(*cidr)) +} + +// Get number of addresses covered by the block +func (b *IPAMBlock) NumAddresses() int { + _, cidr, _ := cnet.ParseCIDR(b.Spec.CIDR) + ones, size := cidr.Mask.Size() + numAddresses := 1 << uint(size-ones) + return numAddresses +} + +// Find the ordinal (i.e. how far into the block) a given IP lies. Returns an error if the IP is outside the block. +func (b *IPAMBlock) IPToOrdinal(ip cnet.IP) (int, error) { + netIP, _, _ := cnet.ParseCIDR(b.Spec.CIDR) + ipAsInt := cnet.IPToBigInt(ip) + baseInt := cnet.IPToBigInt(*netIP) + ord := big.NewInt(0).Sub(ipAsInt, baseInt).Int64() + if ord < 0 || ord >= int64(b.NumAddresses()) { + return 0, fmt.Errorf("IP %s not in block %d-%s", ip, b.Spec.ID, b.Spec.CIDR) + } + return int(ord), nil +} + +func (b *IPAMBlock) NumFreeAddresses() int { + return len(b.Spec.Unallocated) +} + +// empty returns true if the block has released all of its assignable addresses, +// and returns false if any assignable addresses are in use. +func (b *IPAMBlock) Empty() bool { + return b.containsOnlyReservedIPs() +} + +func (b *IPAMBlock) MarkDeleted() { + b.Spec.Deleted = true +} + +func (b *IPAMBlock) IsDeleted() bool { + return b.Spec.Deleted +} + +// containsOnlyReservedIPs returns true if the block is empty excepted for +// expected "reserved" IP addresses. +func (b *IPAMBlock) containsOnlyReservedIPs() bool { + for _, attrIdx := range b.Spec.Allocations { + if attrIdx == nil { + continue + } + attrs := b.Spec.Attributes[*attrIdx] + if strings.ToLower(attrs.AttrPrimary) != ReservedHandle { + return false + } + } + return true +} + +func (b *IPAMBlock) NumReservedAddresses() int { + sum := 0 + for _, attrIdx := range b.Spec.Allocations { + if attrIdx == nil { + continue + } + attrs := b.Spec.Attributes[*attrIdx] + if strings.ToLower(attrs.AttrPrimary) == ReservedHandle { + sum += 1 + } + } + return sum +} + +func (b IPAMBlock) attributeIndexesByHandle(handleID string) []int { + indexes := []int{} + for i, attr := range b.Spec.Attributes { + if attr.AttrPrimary == handleID { + indexes = append(indexes, i) + } + } + return indexes +} + +func (b *IPAMBlock) deleteAttributes(delIndexes, ordinals []int) { + newIndexes := make([]*int, len(b.Spec.Attributes)) + newAttrs := []AllocationAttribute{} + y := 0 // Next free slot in the new attributes list. + for x := range b.Spec.Attributes { + if !intInSlice(x, delIndexes) { + // Attribute at x is not being deleted. Build a mapping + // of old attribute index (x) to new attribute index (y). + newIndex := y + newIndexes[x] = &newIndex + y += 1 + newAttrs = append(newAttrs, b.Spec.Attributes[x]) + } + } + b.Spec.Attributes = newAttrs + + // Update attribute indexes for all allocations in this block. + for i := 0; i < b.NumAddresses(); i++ { + if b.Spec.Allocations[i] != nil { + // Get the new index that corresponds to the old index + // and update the allocation. + newIndex := newIndexes[*b.Spec.Allocations[i]] + b.Spec.Allocations[i] = newIndex + } + } +} + +func (b *IPAMBlock) ReleaseByHandle(handleID string) int { + attrIndexes := b.attributeIndexesByHandle(handleID) + if len(attrIndexes) == 0 { + // Nothing to release. + return 0 + } + + // There are addresses to release. + ordinals := []int{} + var o int + for o = 0; o < b.NumAddresses(); o++ { + // Only check allocated ordinals. + if b.Spec.Allocations[o] != nil && intInSlice(*b.Spec.Allocations[o], attrIndexes) { + // Release this ordinal. + ordinals = append(ordinals, o) + } + } + + // Clean and reorder attributes. + b.deleteAttributes(attrIndexes, ordinals) + + // Release the addresses. + for _, o := range ordinals { + b.Spec.Allocations[o] = nil + b.Spec.Unallocated = append(b.Spec.Unallocated, o) + } + return len(ordinals) +} + +func (b *IPAMBlock) findOrAddAttribute(handleID string, attrs map[string]string) int { + attr := AllocationAttribute{handleID, attrs} + for idx, existing := range b.Spec.Attributes { + if reflect.DeepEqual(attr, existing) { + return idx + } + } + + // Does not exist - add it. + attrIndex := len(b.Spec.Attributes) + b.Spec.Attributes = append(b.Spec.Attributes, attr) + return attrIndex +} + +func intInSlice(searchInt int, slice []int) bool { + for _, v := range slice { + if v == searchInt { + return true + } + } + return false +} + +//This just initializes the data structure and does not call the api to create +func NewBlock(pool *IPPool, cidr cnet.IPNet, rsvdAttr *ReservedAttr) *IPAMBlock { + b := IPAMBlock{} + + b.Labels = map[string]string{ + IPPoolNameLabel: pool.Name, + } + b.Spec.CIDR = cidr.String() + b.Spec.ID = pool.ID() + b.Name = b.BlockName() + + numAddresses := b.NumAddresses() + b.Spec.Allocations = make([]*int, numAddresses) + b.Spec.Unallocated = make([]int, numAddresses) + + // Initialize unallocated ordinals. + for i := 0; i < numAddresses; i++ { + b.Spec.Unallocated[i] = i + } + + if rsvdAttr != nil { + // Reserve IPs based on host reserved attributes. + // For example, with windows OS, the following IP addresses of the block are + // reserved. This is done by pre-allocating them during initialization + // time only. + // IPs : x.0, x.1, x.2 and x.bcastAddr (e.g. x.255 for /24 subnet) + + // nil attributes + attrs := make(map[string]string) + attrs["note"] = rsvdAttr.Note + handleID := rsvdAttr.Handle + b.Spec.Unallocated = b.Spec.Unallocated[rsvdAttr.StartOfBlock : numAddresses-rsvdAttr.EndOfBlock] + attrIndex := len(b.Spec.Attributes) + for i := 0; i < rsvdAttr.StartOfBlock; i++ { + b.Spec.Allocations[i] = &attrIndex + } + for i := 1; i <= rsvdAttr.EndOfBlock; i++ { + b.Spec.Allocations[numAddresses-i] = &attrIndex + } + + // Create slice of IPs and perform the allocations. + attr := AllocationAttribute{ + AttrPrimary: handleID, + AttrSecondary: attrs, + } + b.Spec.Attributes = append(b.Spec.Attributes, attr) + } + + return &b +} + +type ReservedAttr struct { + // Number of addresses reserved from start of the block. + StartOfBlock int + + // Number of addresses reserved from end of the block. + EndOfBlock int + + // Handle for reserved addresses. + Handle string + + // A description about the reserves. + Note string +} diff --git a/pkg/apis/network/v1alpha1/ipamblock_types_test.go b/pkg/apis/network/v1alpha1/ipamblock_types_test.go new file mode 100644 index 000000000..353fc77fc --- /dev/null +++ b/pkg/apis/network/v1alpha1/ipamblock_types_test.go @@ -0,0 +1,85 @@ +/* +Copyright 2020 The KubeSphere 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 v1alpha1 + +import ( + cnet "github.com/projectcalico/libcalico-go/lib/net" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "testing" +) + +func TestIPAMBlock(t *testing.T) { + pool := &IPPool{ + ObjectMeta: v1.ObjectMeta{ + Name: "testippool", + }, + Spec: IPPoolSpec{ + Type: VLAN, + CIDR: "192.168.0.0/24", + RangeEnd: "192.168.0.250", + RangeStart: "192.168.0.10", + }, + } + + handleID := "testhandle" + + _, cidr, _ := cnet.ParseCIDR("192.168.0.0/24") + block := NewBlock(pool, *cidr, &ReservedAttr{ + StartOfBlock: 10, + EndOfBlock: 10, + Handle: ReservedHandle, + Note: ReservedNote, + }) + + reserved := block.NumReservedAddresses() + if reserved != 20 { + t.Fail() + } + + total := block.NumAddresses() + free := block.NumFreeAddresses() + if free != total-reserved { + t.Fail() + } + + t.Log("Allocate 10 addresses from block") + ips := block.AutoAssign(10, handleID, nil) + if len(ips) != 10 { + t.Fail() + } + + free = block.NumFreeAddresses() + if free != total-reserved-10 { + t.Fail() + } + + t.Log("Allocate 1000 addresses from block") + ips = block.AutoAssign(1000, handleID, nil) + if len(ips) != free { + t.Fail() + } + + free = block.NumFreeAddresses() + if free != 0 { + t.Fail() + } + + t.Log("Free address from block") + if block.ReleaseByHandle(handleID) != total-reserved { + t.Fail() + } +} diff --git a/pkg/apis/network/v1alpha1/ipamhandle_types.go b/pkg/apis/network/v1alpha1/ipamhandle_types.go new file mode 100644 index 000000000..1c814343d --- /dev/null +++ b/pkg/apis/network/v1alpha1/ipamhandle_types.go @@ -0,0 +1,110 @@ +/* +Copyright 2020 The KubeSphere 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 v1alpha1 + +import ( + "fmt" + "github.com/projectcalico/libcalico-go/lib/names" + cnet "github.com/projectcalico/libcalico-go/lib/net" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "strconv" + "strings" +) + +const ( + ResourceKindIPAMHandle = "IPAMHandle" + ResourceSingularIPAMHandle = "ipamhandle" + ResourcePluralIPAMHandle = "ipamhandles" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:openapi-gen=true +// +kubebuilder:resource:scope=Cluster +type IPAMHandle struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + metav1.ObjectMeta `json:"metadata,omitempty"` + // Specification of the IPAMHandle. + Spec IPAMHandleSpec `json:"spec,omitempty"` +} + +// IPAMHandleSpec contains the specification for an IPAMHandle resource. +type IPAMHandleSpec struct { + HandleID string `json:"handleID"` + Block map[string]int `json:"block"` + Deleted bool `json:"deleted"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient:nonNamespaced +type IPAMHandleList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []IPAMHandle `json:"items"` +} + +func (h *IPAMHandle) IncrementBlock(block *IPAMBlock, num int) int { + newNum := num + if val, ok := h.Spec.Block[block.String()]; ok { + // An entry exists for this block, increment the number + // of allocations. + newNum = val + num + } + h.Spec.Block[block.String()] = newNum + return newNum +} + +func (h *IPAMHandle) Empty() bool { + return len(h.Spec.Block) == 0 +} + +func (h *IPAMHandle) MarkDeleted() { + h.Spec.Deleted = true +} + +func (h *IPAMHandle) IsDeleted() bool { + return h.Spec.Deleted +} + +func (h *IPAMHandle) DecrementBlock(block *IPAMBlock, num int) (*int, error) { + if current, ok := h.Spec.Block[block.String()]; !ok { + // This entry doesn't exist. + return nil, fmt.Errorf("Tried to decrement block %s by %v but it isn't linked to handle %s", block.BlockName(), num, h.Spec.HandleID) + } else { + newNum := current - num + if newNum < 0 { + return nil, fmt.Errorf("Tried to decrement block %s by %v but it only has %v addresses on handle %s", block.BlockName(), num, current, h.Spec.HandleID) + } + + if newNum == 0 { + delete(h.Spec.Block, block.String()) + } else { + h.Spec.Block[block.String()] = newNum + } + return &newNum, nil + } +} + +func ConvertToBlockName(k string) string { + strs := strings.SplitN(k, "-", 2) + id, _ := strconv.Atoi(strs[0]) + _, blockCIDR, _ := cnet.ParseCIDR(strs[1]) + + return fmt.Sprintf("%d-%s", id, names.CIDRToName(*blockCIDR)) +} diff --git a/pkg/apis/network/v1alpha1/ipamhandle_types_test.go b/pkg/apis/network/v1alpha1/ipamhandle_types_test.go new file mode 100644 index 000000000..47133811d --- /dev/null +++ b/pkg/apis/network/v1alpha1/ipamhandle_types_test.go @@ -0,0 +1,62 @@ +/* +Copyright 2020 The KubeSphere 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 v1alpha1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "testing" +) + +func TestIPAMHandle(t *testing.T) { + block := &IPAMBlock{ + Spec: IPAMBlockSpec{ + ID: 3, + CIDR: "192.168.0.0/24", + }, + } + block.Name = block.BlockName() + + handle := IPAMHandle{ + TypeMeta: v1.TypeMeta{}, + ObjectMeta: v1.ObjectMeta{ + Name: "testhandle", + }, + Spec: IPAMHandleSpec{ + HandleID: "testhandle", + Block: map[string]int{ + block.String(): 10, + }, + }, + } + + t.Log("incrementBlock with 10") + if handle.IncrementBlock(block, 10) != 20 { + t.FailNow() + } + + t.Log("DecrementBlock with 20") + num, _ := handle.DecrementBlock(block, 20) + if *num != 0 { + t.FailNow() + } + + t.Log("DecrementBlock with 1") + _, err := handle.DecrementBlock(block, 1) + if err == nil { + t.FailNow() + } +} diff --git a/pkg/apis/network/v1alpha1/ippool_types.go b/pkg/apis/network/v1alpha1/ippool_types.go new file mode 100644 index 000000000..ce71cf53e --- /dev/null +++ b/pkg/apis/network/v1alpha1/ippool_types.go @@ -0,0 +1,203 @@ +/* +Copyright 2020 The KubeSphere 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 v1alpha1 + +import ( + "fmt" + "math/big" + + cnet "github.com/projectcalico/libcalico-go/lib/net" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + ResourceKindIPPool = "IPPool" + ResourceSingularIPPool = "ippool" + ResourcePluralIPPool = "ippools" + + // scope type > id > name + // id used to detect cidr overlap + IPPoolTypeLabel = "ippool.network.kubesphere.io/type" + IPPoolNameLabel = "ippool.network.kubesphere.io/name" + IPPoolIDLabel = "ippool.network.kubesphere.io/id" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:openapi-gen=true +// +kubebuilder:resource:scope=Cluster +type IPPool struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // +optional + Spec IPPoolSpec `json:"spec,omitempty"` + // +optional + Status IPPoolStatus `json:"status,omitempty"` +} + +type VLANConfig struct { + VlanId uint32 `json:"vlanId"` + Master string `json:"master"` +} + +type Route struct { + Dst string `json:"dst,omitempty"` + GW string `json:"gateway,omitempty"` +} + +// DNS contains values interesting for DNS resolvers +type DNS struct { + Nameservers []string `json:"nameservers,omitempty"` + Domain string `json:"domain,omitempty"` + Search []string `json:"search,omitempty"` + Options []string `json:"options,omitempty"` +} + +type IPPoolStatus struct { + Unallocated int `json:"unallocated,omitempty"` + Allocations int `json:"allocations,omitempty"` + Capacity int `json:"capacity,omitempty"` + Reserved int `json:"reserved,omitempty"` + Synced bool `json:"synced,omitempty"` +} + +type IPPoolSpec struct { + Type string `json:"type"` + + // The pool CIDR. + CIDR string `json:"cidr"` + + // The first ip, inclusive + RangeStart string `json:"rangeStart,omitempty"` + + // The last ip, inclusive + RangeEnd string `json:"rangeEnd,omitempty"` + + // When disabled is true, IPAM will not assign addresses from this pool. + Disabled bool `json:"disabled,omitempty"` + + // The block size to use for IP address assignments from this pool. Defaults to 26 for IPv4 and 112 for IPv6. + BlockSize int `json:"blockSize,omitempty"` + + VLAN VLANConfig `json:"vlanConfig,omitempty"` + + Gateway string `json:"gateway,omitempty"` + Routes []Route `json:"routes,omitempty"` + DNS DNS `json:"dns,omitempty"` + + Workspace string `json:"workspace,omitempty"` + Namespace string `json:"namespace,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient:nonNamespaced +type IPPoolList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []IPPool `json:"items"` +} + +const ( + VLAN = "vlan" + Calico = "calico" + Porter = "porter" + Pod = "pod" + VLANIDStart = 1 + VLANIDEnd = 4097 + PorterID = 4098 + CalicoID = 4099 + PodID = 0 +) + +// Find the ordinal (i.e. how far into the block) a given IP lies. Returns an error if the IP is outside the block. +func (b IPPool) IPToOrdinal(ip cnet.IP) (int, error) { + netIP, _, _ := cnet.ParseCIDR(b.Spec.CIDR) + ipAsInt := cnet.IPToBigInt(ip) + baseInt := cnet.IPToBigInt(*netIP) + ord := big.NewInt(0).Sub(ipAsInt, baseInt).Int64() + if ord < 0 || ord >= int64(b.NumAddresses()) { + return 0, fmt.Errorf("IP %s not in pool %s", ip, b.Spec.CIDR) + } + return int(ord), nil +} + +// Get number of addresses covered by the block +func (b IPPool) NumAddresses() int { + _, cidr, _ := cnet.ParseCIDR(b.Spec.CIDR) + ones, size := cidr.Mask.Size() + numAddresses := 1 << uint(size-ones) + return numAddresses +} + +func (b IPPool) NumReservedAddresses() int { + return b.StartReservedAddressed() + b.EndReservedAddressed() +} + +func (b IPPool) StartReservedAddressed() int { + if b.Spec.RangeStart == "" { + return 0 + } + start, _ := b.IPToOrdinal(*cnet.ParseIP(b.Spec.RangeStart)) + return start +} + +func (b IPPool) EndReservedAddressed() int { + if b.Spec.RangeEnd == "" { + return 0 + } + total := b.NumAddresses() + end, _ := b.IPToOrdinal(*cnet.ParseIP(b.Spec.RangeEnd)) + return total - end - 1 +} + +func (pool IPPool) ID() uint32 { + switch pool.Spec.Type { + case VLAN: + return pool.Spec.VLAN.VlanId + VLANIDStart + case Porter: + return PorterID + case Calico: + return CalicoID + } + + return PodID +} + +func (p IPPool) TypeInvalid() bool { + typeStr := p.Spec.Type + if typeStr == VLAN || typeStr == Porter || typeStr == Pod { + return false + } + + return true +} + +func (p IPPool) Disabled() bool { + return p.Spec.Disabled +} + +func (p IPPool) V4() bool { + ip, _, _ := cnet.ParseCIDR(p.Spec.CIDR) + if ip.To4() != nil { + return true + } + return false +} + +const IPPoolFinalizer = "finalizers.network.kubesphere.io/ippool" diff --git a/pkg/apis/network/v1alpha1/ippool_types_test.go b/pkg/apis/network/v1alpha1/ippool_types_test.go new file mode 100644 index 000000000..b5831d392 --- /dev/null +++ b/pkg/apis/network/v1alpha1/ippool_types_test.go @@ -0,0 +1,65 @@ +/* +Copyright 2020 The KubeSphere 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 v1alpha1 + +import ( + "testing" + + cnet "github.com/projectcalico/libcalico-go/lib/net" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestIPPool(t *testing.T) { + pool := &IPPool{ + ObjectMeta: v1.ObjectMeta{ + Name: "testippool", + }, + Spec: IPPoolSpec{ + Type: VLAN, + CIDR: "192.168.0.0/24", + RangeEnd: "192.168.0.250", + RangeStart: "192.168.0.10", + }, + } + input := cnet.ParseIP("192.168.0.1") + offset, _ := pool.IPToOrdinal(*input) + if offset != 1 { + t.Fail() + } + + input = cnet.ParseIP("192.168.1.1") + _, err := pool.IPToOrdinal(*input) + if err == nil { + t.Fail() + } + + if pool.NumAddresses() != 256 { + t.Fail() + } + + if pool.StartReservedAddressed() != 10 { + t.Fail() + } + + if pool.EndReservedAddressed() != 5 { + t.Fail() + } + + if pool.NumReservedAddresses() != 15 { + t.Fail() + } +} diff --git a/pkg/apis/network/v1alpha1/namespacenetworkpolicy_types.go b/pkg/apis/network/v1alpha1/namespacenetworkpolicy_types.go index 3e674e072..fa1cb572f 100644 --- a/pkg/apis/network/v1alpha1/namespacenetworkpolicy_types.go +++ b/pkg/apis/network/v1alpha1/namespacenetworkpolicy_types.go @@ -148,7 +148,3 @@ type NamespaceNetworkPolicyList struct { metav1.ListMeta `json:"metadata,omitempty"` Items []NamespaceNetworkPolicy `json:"items"` } - -func init() { - SchemeBuilder.Register(&NamespaceNetworkPolicy{}, &NamespaceNetworkPolicyList{}) -} diff --git a/pkg/apis/network/v1alpha1/register.go b/pkg/apis/network/v1alpha1/register.go index 8d0e7a9d0..8247db7b4 100644 --- a/pkg/apis/network/v1alpha1/register.go +++ b/pkg/apis/network/v1alpha1/register.go @@ -1,5 +1,5 @@ /* -Copyright 2019 The KubeSphere authors. +Copyright 2020 The KubeSphere authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -40,6 +40,13 @@ var ( AddToScheme = SchemeBuilder.AddToScheme ) +func init() { + SchemeBuilder.Register(&IPAMHandle{}, &IPAMHandleList{}) + SchemeBuilder.Register(&IPAMBlock{}, &IPAMBlockList{}) + SchemeBuilder.Register(&IPPool{}, &IPPoolList{}) + SchemeBuilder.Register(&NamespaceNetworkPolicy{}, &NamespaceNetworkPolicyList{}) +} + // Resource is required by pkg/client/listers/... func Resource(resource string) schema.GroupResource { return SchemeGroupVersion.WithResource(resource).GroupResource() diff --git a/pkg/apis/network/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/network/v1alpha1/zz_generated.deepcopy.go index 3ff71ded6..c39c5329d 100644 --- a/pkg/apis/network/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/network/v1alpha1/zz_generated.deepcopy.go @@ -16,22 +16,345 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Code generated by deepcopy-gen. DO NOT EDIT. +// Code generated by controller-gen. DO NOT EDIT. package v1alpha1 import ( - v1 "k8s.io/api/networking/v1" + "k8s.io/api/networking/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AllocationAttribute) DeepCopyInto(out *AllocationAttribute) { + *out = *in + if in.AttrSecondary != nil { + in, out := &in.AttrSecondary, &out.AttrSecondary + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllocationAttribute. +func (in *AllocationAttribute) DeepCopy() *AllocationAttribute { + if in == nil { + return nil + } + out := new(AllocationAttribute) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DNS) DeepCopyInto(out *DNS) { + *out = *in + if in.Nameservers != nil { + in, out := &in.Nameservers, &out.Nameservers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Search != nil { + in, out := &in.Search, &out.Search + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Options != nil { + in, out := &in.Options, &out.Options + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNS. +func (in *DNS) DeepCopy() *DNS { + if in == nil { + return nil + } + out := new(DNS) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPAMBlock) DeepCopyInto(out *IPAMBlock) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAMBlock. +func (in *IPAMBlock) DeepCopy() *IPAMBlock { + if in == nil { + return nil + } + out := new(IPAMBlock) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IPAMBlock) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPAMBlockList) DeepCopyInto(out *IPAMBlockList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]IPAMBlock, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAMBlockList. +func (in *IPAMBlockList) DeepCopy() *IPAMBlockList { + if in == nil { + return nil + } + out := new(IPAMBlockList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IPAMBlockList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPAMBlockSpec) DeepCopyInto(out *IPAMBlockSpec) { + *out = *in + if in.Allocations != nil { + in, out := &in.Allocations, &out.Allocations + *out = make([]*int, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(int) + **out = **in + } + } + } + if in.Unallocated != nil { + in, out := &in.Unallocated, &out.Unallocated + *out = make([]int, len(*in)) + copy(*out, *in) + } + if in.Attributes != nil { + in, out := &in.Attributes, &out.Attributes + *out = make([]AllocationAttribute, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAMBlockSpec. +func (in *IPAMBlockSpec) DeepCopy() *IPAMBlockSpec { + if in == nil { + return nil + } + out := new(IPAMBlockSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPAMHandle) DeepCopyInto(out *IPAMHandle) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAMHandle. +func (in *IPAMHandle) DeepCopy() *IPAMHandle { + if in == nil { + return nil + } + out := new(IPAMHandle) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IPAMHandle) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPAMHandleList) DeepCopyInto(out *IPAMHandleList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]IPAMHandle, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAMHandleList. +func (in *IPAMHandleList) DeepCopy() *IPAMHandleList { + if in == nil { + return nil + } + out := new(IPAMHandleList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IPAMHandleList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPAMHandleSpec) DeepCopyInto(out *IPAMHandleSpec) { + *out = *in + if in.Block != nil { + in, out := &in.Block, &out.Block + *out = make(map[string]int, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAMHandleSpec. +func (in *IPAMHandleSpec) DeepCopy() *IPAMHandleSpec { + if in == nil { + return nil + } + out := new(IPAMHandleSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPPool) DeepCopyInto(out *IPPool) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPPool. +func (in *IPPool) DeepCopy() *IPPool { + if in == nil { + return nil + } + out := new(IPPool) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IPPool) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPPoolList) DeepCopyInto(out *IPPoolList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]IPPool, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPPoolList. +func (in *IPPoolList) DeepCopy() *IPPoolList { + if in == nil { + return nil + } + out := new(IPPoolList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IPPoolList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPPoolSpec) DeepCopyInto(out *IPPoolSpec) { + *out = *in + out.VLAN = in.VLAN + if in.Routes != nil { + in, out := &in.Routes, &out.Routes + *out = make([]Route, len(*in)) + copy(*out, *in) + } + in.DNS.DeepCopyInto(&out.DNS) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPPoolSpec. +func (in *IPPoolSpec) DeepCopy() *IPPoolSpec { + if in == nil { + return nil + } + out := new(IPPoolSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPPoolStatus) DeepCopyInto(out *IPPoolStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPPoolStatus. +func (in *IPPoolStatus) DeepCopy() *IPPoolStatus { + if in == nil { + return nil + } + out := new(IPPoolStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespaceNetworkPolicy) DeepCopyInto(out *NamespaceNetworkPolicy) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceNetworkPolicy. @@ -64,7 +387,6 @@ func (in *NamespaceNetworkPolicyList) DeepCopyInto(out *NamespaceNetworkPolicyLi (*in)[i].DeepCopyInto(&(*out)[i]) } } - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceNetworkPolicyList. @@ -107,7 +429,6 @@ func (in *NamespaceNetworkPolicySpec) DeepCopyInto(out *NamespaceNetworkPolicySp *out = make([]v1.PolicyType, len(*in)) copy(*out, *in) } - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceNetworkPolicySpec. @@ -123,7 +444,6 @@ func (in *NamespaceNetworkPolicySpec) DeepCopy() *NamespaceNetworkPolicySpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespaceSelector) DeepCopyInto(out *NamespaceSelector) { *out = *in - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceSelector. @@ -153,7 +473,6 @@ func (in *NetworkPolicyEgressRule) DeepCopyInto(out *NetworkPolicyEgressRule) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicyEgressRule. @@ -183,7 +502,6 @@ func (in *NetworkPolicyIngressRule) DeepCopyInto(out *NetworkPolicyIngressRule) (*in)[i].DeepCopyInto(&(*out)[i]) } } - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicyIngressRule. @@ -214,7 +532,6 @@ func (in *NetworkPolicyPeer) DeepCopyInto(out *NetworkPolicyPeer) { *out = new(ServiceSelector) **out = **in } - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicyPeer. @@ -227,10 +544,39 @@ func (in *NetworkPolicyPeer) DeepCopy() *NetworkPolicyPeer { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReservedAttr) DeepCopyInto(out *ReservedAttr) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReservedAttr. +func (in *ReservedAttr) DeepCopy() *ReservedAttr { + if in == nil { + return nil + } + out := new(ReservedAttr) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Route) DeepCopyInto(out *Route) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Route. +func (in *Route) DeepCopy() *Route { + if in == nil { + return nil + } + out := new(Route) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceSelector) DeepCopyInto(out *ServiceSelector) { *out = *in - return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceSelector. @@ -242,3 +588,18 @@ func (in *ServiceSelector) DeepCopy() *ServiceSelector { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VLANConfig) DeepCopyInto(out *VLANConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VLANConfig. +func (in *VLANConfig) DeepCopy() *VLANConfig { + if in == nil { + return nil + } + out := new(VLANConfig) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_ipamblock.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_ipamblock.go new file mode 100644 index 000000000..3ef9508d7 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_ipamblock.go @@ -0,0 +1,120 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" +) + +// FakeIPAMBlocks implements IPAMBlockInterface +type FakeIPAMBlocks struct { + Fake *FakeNetworkV1alpha1 +} + +var ipamblocksResource = schema.GroupVersionResource{Group: "network.kubesphere.io", Version: "v1alpha1", Resource: "ipamblocks"} + +var ipamblocksKind = schema.GroupVersionKind{Group: "network.kubesphere.io", Version: "v1alpha1", Kind: "IPAMBlock"} + +// Get takes name of the iPAMBlock, and returns the corresponding iPAMBlock object, and an error if there is any. +func (c *FakeIPAMBlocks) Get(name string, options v1.GetOptions) (result *v1alpha1.IPAMBlock, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(ipamblocksResource, name), &v1alpha1.IPAMBlock{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPAMBlock), err +} + +// List takes label and field selectors, and returns the list of IPAMBlocks that match those selectors. +func (c *FakeIPAMBlocks) List(opts v1.ListOptions) (result *v1alpha1.IPAMBlockList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(ipamblocksResource, ipamblocksKind, opts), &v1alpha1.IPAMBlockList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.IPAMBlockList{ListMeta: obj.(*v1alpha1.IPAMBlockList).ListMeta} + for _, item := range obj.(*v1alpha1.IPAMBlockList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested iPAMBlocks. +func (c *FakeIPAMBlocks) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(ipamblocksResource, opts)) +} + +// Create takes the representation of a iPAMBlock and creates it. Returns the server's representation of the iPAMBlock, and an error, if there is any. +func (c *FakeIPAMBlocks) Create(iPAMBlock *v1alpha1.IPAMBlock) (result *v1alpha1.IPAMBlock, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(ipamblocksResource, iPAMBlock), &v1alpha1.IPAMBlock{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPAMBlock), err +} + +// Update takes the representation of a iPAMBlock and updates it. Returns the server's representation of the iPAMBlock, and an error, if there is any. +func (c *FakeIPAMBlocks) Update(iPAMBlock *v1alpha1.IPAMBlock) (result *v1alpha1.IPAMBlock, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(ipamblocksResource, iPAMBlock), &v1alpha1.IPAMBlock{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPAMBlock), err +} + +// Delete takes name of the iPAMBlock and deletes it. Returns an error if one occurs. +func (c *FakeIPAMBlocks) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(ipamblocksResource, name), &v1alpha1.IPAMBlock{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeIPAMBlocks) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(ipamblocksResource, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.IPAMBlockList{}) + return err +} + +// Patch applies the patch and returns the patched iPAMBlock. +func (c *FakeIPAMBlocks) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.IPAMBlock, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(ipamblocksResource, name, pt, data, subresources...), &v1alpha1.IPAMBlock{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPAMBlock), err +} diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_ipamhandle.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_ipamhandle.go new file mode 100644 index 000000000..9e1ac5283 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_ipamhandle.go @@ -0,0 +1,120 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" +) + +// FakeIPAMHandles implements IPAMHandleInterface +type FakeIPAMHandles struct { + Fake *FakeNetworkV1alpha1 +} + +var ipamhandlesResource = schema.GroupVersionResource{Group: "network.kubesphere.io", Version: "v1alpha1", Resource: "ipamhandles"} + +var ipamhandlesKind = schema.GroupVersionKind{Group: "network.kubesphere.io", Version: "v1alpha1", Kind: "IPAMHandle"} + +// Get takes name of the iPAMHandle, and returns the corresponding iPAMHandle object, and an error if there is any. +func (c *FakeIPAMHandles) Get(name string, options v1.GetOptions) (result *v1alpha1.IPAMHandle, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(ipamhandlesResource, name), &v1alpha1.IPAMHandle{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPAMHandle), err +} + +// List takes label and field selectors, and returns the list of IPAMHandles that match those selectors. +func (c *FakeIPAMHandles) List(opts v1.ListOptions) (result *v1alpha1.IPAMHandleList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(ipamhandlesResource, ipamhandlesKind, opts), &v1alpha1.IPAMHandleList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.IPAMHandleList{ListMeta: obj.(*v1alpha1.IPAMHandleList).ListMeta} + for _, item := range obj.(*v1alpha1.IPAMHandleList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested iPAMHandles. +func (c *FakeIPAMHandles) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(ipamhandlesResource, opts)) +} + +// Create takes the representation of a iPAMHandle and creates it. Returns the server's representation of the iPAMHandle, and an error, if there is any. +func (c *FakeIPAMHandles) Create(iPAMHandle *v1alpha1.IPAMHandle) (result *v1alpha1.IPAMHandle, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(ipamhandlesResource, iPAMHandle), &v1alpha1.IPAMHandle{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPAMHandle), err +} + +// Update takes the representation of a iPAMHandle and updates it. Returns the server's representation of the iPAMHandle, and an error, if there is any. +func (c *FakeIPAMHandles) Update(iPAMHandle *v1alpha1.IPAMHandle) (result *v1alpha1.IPAMHandle, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(ipamhandlesResource, iPAMHandle), &v1alpha1.IPAMHandle{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPAMHandle), err +} + +// Delete takes name of the iPAMHandle and deletes it. Returns an error if one occurs. +func (c *FakeIPAMHandles) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(ipamhandlesResource, name), &v1alpha1.IPAMHandle{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeIPAMHandles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(ipamhandlesResource, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.IPAMHandleList{}) + return err +} + +// Patch applies the patch and returns the patched iPAMHandle. +func (c *FakeIPAMHandles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.IPAMHandle, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(ipamhandlesResource, name, pt, data, subresources...), &v1alpha1.IPAMHandle{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPAMHandle), err +} diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_ippool.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_ippool.go new file mode 100644 index 000000000..2cd41edcc --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_ippool.go @@ -0,0 +1,131 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" +) + +// FakeIPPools implements IPPoolInterface +type FakeIPPools struct { + Fake *FakeNetworkV1alpha1 +} + +var ippoolsResource = schema.GroupVersionResource{Group: "network.kubesphere.io", Version: "v1alpha1", Resource: "ippools"} + +var ippoolsKind = schema.GroupVersionKind{Group: "network.kubesphere.io", Version: "v1alpha1", Kind: "IPPool"} + +// Get takes name of the iPPool, and returns the corresponding iPPool object, and an error if there is any. +func (c *FakeIPPools) Get(name string, options v1.GetOptions) (result *v1alpha1.IPPool, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(ippoolsResource, name), &v1alpha1.IPPool{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPPool), err +} + +// List takes label and field selectors, and returns the list of IPPools that match those selectors. +func (c *FakeIPPools) List(opts v1.ListOptions) (result *v1alpha1.IPPoolList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(ippoolsResource, ippoolsKind, opts), &v1alpha1.IPPoolList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.IPPoolList{ListMeta: obj.(*v1alpha1.IPPoolList).ListMeta} + for _, item := range obj.(*v1alpha1.IPPoolList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested iPPools. +func (c *FakeIPPools) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(ippoolsResource, opts)) +} + +// Create takes the representation of a iPPool and creates it. Returns the server's representation of the iPPool, and an error, if there is any. +func (c *FakeIPPools) Create(iPPool *v1alpha1.IPPool) (result *v1alpha1.IPPool, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(ippoolsResource, iPPool), &v1alpha1.IPPool{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPPool), err +} + +// Update takes the representation of a iPPool and updates it. Returns the server's representation of the iPPool, and an error, if there is any. +func (c *FakeIPPools) Update(iPPool *v1alpha1.IPPool) (result *v1alpha1.IPPool, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(ippoolsResource, iPPool), &v1alpha1.IPPool{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPPool), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeIPPools) UpdateStatus(iPPool *v1alpha1.IPPool) (*v1alpha1.IPPool, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(ippoolsResource, "status", iPPool), &v1alpha1.IPPool{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPPool), err +} + +// Delete takes name of the iPPool and deletes it. Returns an error if one occurs. +func (c *FakeIPPools) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(ippoolsResource, name), &v1alpha1.IPPool{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeIPPools) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(ippoolsResource, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.IPPoolList{}) + return err +} + +// Patch applies the patch and returns the patched iPPool. +func (c *FakeIPPools) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.IPPool, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(ippoolsResource, name, pt, data, subresources...), &v1alpha1.IPPool{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.IPPool), err +} diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_network_client.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_network_client.go index ecc3bfdf9..705d6ccec 100644 --- a/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_network_client.go +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/fake/fake_network_client.go @@ -28,6 +28,18 @@ type FakeNetworkV1alpha1 struct { *testing.Fake } +func (c *FakeNetworkV1alpha1) IPAMBlocks() v1alpha1.IPAMBlockInterface { + return &FakeIPAMBlocks{c} +} + +func (c *FakeNetworkV1alpha1) IPAMHandles() v1alpha1.IPAMHandleInterface { + return &FakeIPAMHandles{c} +} + +func (c *FakeNetworkV1alpha1) IPPools() v1alpha1.IPPoolInterface { + return &FakeIPPools{c} +} + func (c *FakeNetworkV1alpha1) NamespaceNetworkPolicies(namespace string) v1alpha1.NamespaceNetworkPolicyInterface { return &FakeNamespaceNetworkPolicies{c, namespace} } diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/generated_expansion.go index f36b84a7b..ec69dfe52 100644 --- a/pkg/client/clientset/versioned/typed/network/v1alpha1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/generated_expansion.go @@ -18,4 +18,10 @@ limitations under the License. package v1alpha1 +type IPAMBlockExpansion interface{} + +type IPAMHandleExpansion interface{} + +type IPPoolExpansion interface{} + type NamespaceNetworkPolicyExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/ipamblock.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/ipamblock.go new file mode 100644 index 000000000..2c75a6a87 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/ipamblock.go @@ -0,0 +1,164 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" +) + +// IPAMBlocksGetter has a method to return a IPAMBlockInterface. +// A group's client should implement this interface. +type IPAMBlocksGetter interface { + IPAMBlocks() IPAMBlockInterface +} + +// IPAMBlockInterface has methods to work with IPAMBlock resources. +type IPAMBlockInterface interface { + Create(*v1alpha1.IPAMBlock) (*v1alpha1.IPAMBlock, error) + Update(*v1alpha1.IPAMBlock) (*v1alpha1.IPAMBlock, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.IPAMBlock, error) + List(opts v1.ListOptions) (*v1alpha1.IPAMBlockList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.IPAMBlock, err error) + IPAMBlockExpansion +} + +// iPAMBlocks implements IPAMBlockInterface +type iPAMBlocks struct { + client rest.Interface +} + +// newIPAMBlocks returns a IPAMBlocks +func newIPAMBlocks(c *NetworkV1alpha1Client) *iPAMBlocks { + return &iPAMBlocks{ + client: c.RESTClient(), + } +} + +// Get takes name of the iPAMBlock, and returns the corresponding iPAMBlock object, and an error if there is any. +func (c *iPAMBlocks) Get(name string, options v1.GetOptions) (result *v1alpha1.IPAMBlock, err error) { + result = &v1alpha1.IPAMBlock{} + err = c.client.Get(). + Resource("ipamblocks"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of IPAMBlocks that match those selectors. +func (c *iPAMBlocks) List(opts v1.ListOptions) (result *v1alpha1.IPAMBlockList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.IPAMBlockList{} + err = c.client.Get(). + Resource("ipamblocks"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested iPAMBlocks. +func (c *iPAMBlocks) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("ipamblocks"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a iPAMBlock and creates it. Returns the server's representation of the iPAMBlock, and an error, if there is any. +func (c *iPAMBlocks) Create(iPAMBlock *v1alpha1.IPAMBlock) (result *v1alpha1.IPAMBlock, err error) { + result = &v1alpha1.IPAMBlock{} + err = c.client.Post(). + Resource("ipamblocks"). + Body(iPAMBlock). + Do(). + Into(result) + return +} + +// Update takes the representation of a iPAMBlock and updates it. Returns the server's representation of the iPAMBlock, and an error, if there is any. +func (c *iPAMBlocks) Update(iPAMBlock *v1alpha1.IPAMBlock) (result *v1alpha1.IPAMBlock, err error) { + result = &v1alpha1.IPAMBlock{} + err = c.client.Put(). + Resource("ipamblocks"). + Name(iPAMBlock.Name). + Body(iPAMBlock). + Do(). + Into(result) + return +} + +// Delete takes name of the iPAMBlock and deletes it. Returns an error if one occurs. +func (c *iPAMBlocks) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("ipamblocks"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *iPAMBlocks) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("ipamblocks"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched iPAMBlock. +func (c *iPAMBlocks) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.IPAMBlock, err error) { + result = &v1alpha1.IPAMBlock{} + err = c.client.Patch(pt). + Resource("ipamblocks"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/ipamhandle.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/ipamhandle.go new file mode 100644 index 000000000..822e9b8df --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/ipamhandle.go @@ -0,0 +1,164 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" +) + +// IPAMHandlesGetter has a method to return a IPAMHandleInterface. +// A group's client should implement this interface. +type IPAMHandlesGetter interface { + IPAMHandles() IPAMHandleInterface +} + +// IPAMHandleInterface has methods to work with IPAMHandle resources. +type IPAMHandleInterface interface { + Create(*v1alpha1.IPAMHandle) (*v1alpha1.IPAMHandle, error) + Update(*v1alpha1.IPAMHandle) (*v1alpha1.IPAMHandle, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.IPAMHandle, error) + List(opts v1.ListOptions) (*v1alpha1.IPAMHandleList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.IPAMHandle, err error) + IPAMHandleExpansion +} + +// iPAMHandles implements IPAMHandleInterface +type iPAMHandles struct { + client rest.Interface +} + +// newIPAMHandles returns a IPAMHandles +func newIPAMHandles(c *NetworkV1alpha1Client) *iPAMHandles { + return &iPAMHandles{ + client: c.RESTClient(), + } +} + +// Get takes name of the iPAMHandle, and returns the corresponding iPAMHandle object, and an error if there is any. +func (c *iPAMHandles) Get(name string, options v1.GetOptions) (result *v1alpha1.IPAMHandle, err error) { + result = &v1alpha1.IPAMHandle{} + err = c.client.Get(). + Resource("ipamhandles"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of IPAMHandles that match those selectors. +func (c *iPAMHandles) List(opts v1.ListOptions) (result *v1alpha1.IPAMHandleList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.IPAMHandleList{} + err = c.client.Get(). + Resource("ipamhandles"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested iPAMHandles. +func (c *iPAMHandles) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("ipamhandles"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a iPAMHandle and creates it. Returns the server's representation of the iPAMHandle, and an error, if there is any. +func (c *iPAMHandles) Create(iPAMHandle *v1alpha1.IPAMHandle) (result *v1alpha1.IPAMHandle, err error) { + result = &v1alpha1.IPAMHandle{} + err = c.client.Post(). + Resource("ipamhandles"). + Body(iPAMHandle). + Do(). + Into(result) + return +} + +// Update takes the representation of a iPAMHandle and updates it. Returns the server's representation of the iPAMHandle, and an error, if there is any. +func (c *iPAMHandles) Update(iPAMHandle *v1alpha1.IPAMHandle) (result *v1alpha1.IPAMHandle, err error) { + result = &v1alpha1.IPAMHandle{} + err = c.client.Put(). + Resource("ipamhandles"). + Name(iPAMHandle.Name). + Body(iPAMHandle). + Do(). + Into(result) + return +} + +// Delete takes name of the iPAMHandle and deletes it. Returns an error if one occurs. +func (c *iPAMHandles) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("ipamhandles"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *iPAMHandles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("ipamhandles"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched iPAMHandle. +func (c *iPAMHandles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.IPAMHandle, err error) { + result = &v1alpha1.IPAMHandle{} + err = c.client.Patch(pt). + Resource("ipamhandles"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/ippool.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/ippool.go new file mode 100644 index 000000000..841c40735 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/ippool.go @@ -0,0 +1,180 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" +) + +// IPPoolsGetter has a method to return a IPPoolInterface. +// A group's client should implement this interface. +type IPPoolsGetter interface { + IPPools() IPPoolInterface +} + +// IPPoolInterface has methods to work with IPPool resources. +type IPPoolInterface interface { + Create(*v1alpha1.IPPool) (*v1alpha1.IPPool, error) + Update(*v1alpha1.IPPool) (*v1alpha1.IPPool, error) + UpdateStatus(*v1alpha1.IPPool) (*v1alpha1.IPPool, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.IPPool, error) + List(opts v1.ListOptions) (*v1alpha1.IPPoolList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.IPPool, err error) + IPPoolExpansion +} + +// iPPools implements IPPoolInterface +type iPPools struct { + client rest.Interface +} + +// newIPPools returns a IPPools +func newIPPools(c *NetworkV1alpha1Client) *iPPools { + return &iPPools{ + client: c.RESTClient(), + } +} + +// Get takes name of the iPPool, and returns the corresponding iPPool object, and an error if there is any. +func (c *iPPools) Get(name string, options v1.GetOptions) (result *v1alpha1.IPPool, err error) { + result = &v1alpha1.IPPool{} + err = c.client.Get(). + Resource("ippools"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of IPPools that match those selectors. +func (c *iPPools) List(opts v1.ListOptions) (result *v1alpha1.IPPoolList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.IPPoolList{} + err = c.client.Get(). + Resource("ippools"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested iPPools. +func (c *iPPools) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("ippools"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a iPPool and creates it. Returns the server's representation of the iPPool, and an error, if there is any. +func (c *iPPools) Create(iPPool *v1alpha1.IPPool) (result *v1alpha1.IPPool, err error) { + result = &v1alpha1.IPPool{} + err = c.client.Post(). + Resource("ippools"). + Body(iPPool). + Do(). + Into(result) + return +} + +// Update takes the representation of a iPPool and updates it. Returns the server's representation of the iPPool, and an error, if there is any. +func (c *iPPools) Update(iPPool *v1alpha1.IPPool) (result *v1alpha1.IPPool, err error) { + result = &v1alpha1.IPPool{} + err = c.client.Put(). + Resource("ippools"). + Name(iPPool.Name). + Body(iPPool). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *iPPools) UpdateStatus(iPPool *v1alpha1.IPPool) (result *v1alpha1.IPPool, err error) { + result = &v1alpha1.IPPool{} + err = c.client.Put(). + Resource("ippools"). + Name(iPPool.Name). + SubResource("status"). + Body(iPPool). + Do(). + Into(result) + return +} + +// Delete takes name of the iPPool and deletes it. Returns an error if one occurs. +func (c *iPPools) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("ippools"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *iPPools) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("ippools"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched iPPool. +func (c *iPPools) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.IPPool, err error) { + result = &v1alpha1.IPPool{} + err = c.client.Patch(pt). + Resource("ippools"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/network/v1alpha1/network_client.go b/pkg/client/clientset/versioned/typed/network/v1alpha1/network_client.go index bbaa12216..63e456746 100644 --- a/pkg/client/clientset/versioned/typed/network/v1alpha1/network_client.go +++ b/pkg/client/clientset/versioned/typed/network/v1alpha1/network_client.go @@ -26,6 +26,9 @@ import ( type NetworkV1alpha1Interface interface { RESTClient() rest.Interface + IPAMBlocksGetter + IPAMHandlesGetter + IPPoolsGetter NamespaceNetworkPoliciesGetter } @@ -34,6 +37,18 @@ type NetworkV1alpha1Client struct { restClient rest.Interface } +func (c *NetworkV1alpha1Client) IPAMBlocks() IPAMBlockInterface { + return newIPAMBlocks(c) +} + +func (c *NetworkV1alpha1Client) IPAMHandles() IPAMHandleInterface { + return newIPAMHandles(c) +} + +func (c *NetworkV1alpha1Client) IPPools() IPPoolInterface { + return newIPPools(c) +} + func (c *NetworkV1alpha1Client) NamespaceNetworkPolicies(namespace string) NamespaceNetworkPolicyInterface { return newNamespaceNetworkPolicies(c, namespace) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index 5407c9e17..c62e4e5a5 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -109,6 +109,12 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Iam().V1alpha2().WorkspaceRoleBindings().Informer()}, nil // Group=network.kubesphere.io, Version=v1alpha1 + case networkv1alpha1.SchemeGroupVersion.WithResource("ipamblocks"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().IPAMBlocks().Informer()}, nil + case networkv1alpha1.SchemeGroupVersion.WithResource("ipamhandles"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().IPAMHandles().Informer()}, nil + case networkv1alpha1.SchemeGroupVersion.WithResource("ippools"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().IPPools().Informer()}, nil case networkv1alpha1.SchemeGroupVersion.WithResource("namespacenetworkpolicies"): return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().NamespaceNetworkPolicies().Informer()}, nil diff --git a/pkg/client/informers/externalversions/network/v1alpha1/interface.go b/pkg/client/informers/externalversions/network/v1alpha1/interface.go index 8312b972a..4aded2d36 100644 --- a/pkg/client/informers/externalversions/network/v1alpha1/interface.go +++ b/pkg/client/informers/externalversions/network/v1alpha1/interface.go @@ -24,6 +24,12 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // IPAMBlocks returns a IPAMBlockInformer. + IPAMBlocks() IPAMBlockInformer + // IPAMHandles returns a IPAMHandleInformer. + IPAMHandles() IPAMHandleInformer + // IPPools returns a IPPoolInformer. + IPPools() IPPoolInformer // NamespaceNetworkPolicies returns a NamespaceNetworkPolicyInformer. NamespaceNetworkPolicies() NamespaceNetworkPolicyInformer } @@ -39,6 +45,21 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// IPAMBlocks returns a IPAMBlockInformer. +func (v *version) IPAMBlocks() IPAMBlockInformer { + return &iPAMBlockInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// IPAMHandles returns a IPAMHandleInformer. +func (v *version) IPAMHandles() IPAMHandleInformer { + return &iPAMHandleInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// IPPools returns a IPPoolInformer. +func (v *version) IPPools() IPPoolInformer { + return &iPPoolInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + // NamespaceNetworkPolicies returns a NamespaceNetworkPolicyInformer. func (v *version) NamespaceNetworkPolicies() NamespaceNetworkPolicyInformer { return &namespaceNetworkPolicyInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/client/informers/externalversions/network/v1alpha1/ipamblock.go b/pkg/client/informers/externalversions/network/v1alpha1/ipamblock.go new file mode 100644 index 000000000..ab880059d --- /dev/null +++ b/pkg/client/informers/externalversions/network/v1alpha1/ipamblock.go @@ -0,0 +1,88 @@ +/* +Copyright 2020 The KubeSphere 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 informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "kubesphere.io/kubesphere/pkg/client/listers/network/v1alpha1" +) + +// IPAMBlockInformer provides access to a shared informer and lister for +// IPAMBlocks. +type IPAMBlockInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.IPAMBlockLister +} + +type iPAMBlockInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewIPAMBlockInformer constructs a new informer for IPAMBlock type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewIPAMBlockInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredIPAMBlockInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredIPAMBlockInformer constructs a new informer for IPAMBlock type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredIPAMBlockInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.NetworkV1alpha1().IPAMBlocks().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.NetworkV1alpha1().IPAMBlocks().Watch(options) + }, + }, + &networkv1alpha1.IPAMBlock{}, + resyncPeriod, + indexers, + ) +} + +func (f *iPAMBlockInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredIPAMBlockInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *iPAMBlockInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&networkv1alpha1.IPAMBlock{}, f.defaultInformer) +} + +func (f *iPAMBlockInformer) Lister() v1alpha1.IPAMBlockLister { + return v1alpha1.NewIPAMBlockLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/network/v1alpha1/ipamhandle.go b/pkg/client/informers/externalversions/network/v1alpha1/ipamhandle.go new file mode 100644 index 000000000..5f3ead0f9 --- /dev/null +++ b/pkg/client/informers/externalversions/network/v1alpha1/ipamhandle.go @@ -0,0 +1,88 @@ +/* +Copyright 2020 The KubeSphere 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 informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "kubesphere.io/kubesphere/pkg/client/listers/network/v1alpha1" +) + +// IPAMHandleInformer provides access to a shared informer and lister for +// IPAMHandles. +type IPAMHandleInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.IPAMHandleLister +} + +type iPAMHandleInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewIPAMHandleInformer constructs a new informer for IPAMHandle type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewIPAMHandleInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredIPAMHandleInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredIPAMHandleInformer constructs a new informer for IPAMHandle type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredIPAMHandleInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.NetworkV1alpha1().IPAMHandles().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.NetworkV1alpha1().IPAMHandles().Watch(options) + }, + }, + &networkv1alpha1.IPAMHandle{}, + resyncPeriod, + indexers, + ) +} + +func (f *iPAMHandleInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredIPAMHandleInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *iPAMHandleInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&networkv1alpha1.IPAMHandle{}, f.defaultInformer) +} + +func (f *iPAMHandleInformer) Lister() v1alpha1.IPAMHandleLister { + return v1alpha1.NewIPAMHandleLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/network/v1alpha1/ippool.go b/pkg/client/informers/externalversions/network/v1alpha1/ippool.go new file mode 100644 index 000000000..566820c9f --- /dev/null +++ b/pkg/client/informers/externalversions/network/v1alpha1/ippool.go @@ -0,0 +1,88 @@ +/* +Copyright 2020 The KubeSphere 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 informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "kubesphere.io/kubesphere/pkg/client/listers/network/v1alpha1" +) + +// IPPoolInformer provides access to a shared informer and lister for +// IPPools. +type IPPoolInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.IPPoolLister +} + +type iPPoolInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewIPPoolInformer constructs a new informer for IPPool type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewIPPoolInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredIPPoolInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredIPPoolInformer constructs a new informer for IPPool type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredIPPoolInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.NetworkV1alpha1().IPPools().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.NetworkV1alpha1().IPPools().Watch(options) + }, + }, + &networkv1alpha1.IPPool{}, + resyncPeriod, + indexers, + ) +} + +func (f *iPPoolInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredIPPoolInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *iPPoolInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&networkv1alpha1.IPPool{}, f.defaultInformer) +} + +func (f *iPPoolInformer) Lister() v1alpha1.IPPoolLister { + return v1alpha1.NewIPPoolLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/listers/network/v1alpha1/expansion_generated.go b/pkg/client/listers/network/v1alpha1/expansion_generated.go index 0b3ad7ac3..74edabe24 100644 --- a/pkg/client/listers/network/v1alpha1/expansion_generated.go +++ b/pkg/client/listers/network/v1alpha1/expansion_generated.go @@ -18,6 +18,18 @@ limitations under the License. package v1alpha1 +// IPAMBlockListerExpansion allows custom methods to be added to +// IPAMBlockLister. +type IPAMBlockListerExpansion interface{} + +// IPAMHandleListerExpansion allows custom methods to be added to +// IPAMHandleLister. +type IPAMHandleListerExpansion interface{} + +// IPPoolListerExpansion allows custom methods to be added to +// IPPoolLister. +type IPPoolListerExpansion interface{} + // NamespaceNetworkPolicyListerExpansion allows custom methods to be added to // NamespaceNetworkPolicyLister. type NamespaceNetworkPolicyListerExpansion interface{} diff --git a/pkg/client/listers/network/v1alpha1/ipamblock.go b/pkg/client/listers/network/v1alpha1/ipamblock.go new file mode 100644 index 000000000..4b74d2667 --- /dev/null +++ b/pkg/client/listers/network/v1alpha1/ipamblock.go @@ -0,0 +1,65 @@ +/* +Copyright 2020 The KubeSphere 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 lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" +) + +// IPAMBlockLister helps list IPAMBlocks. +type IPAMBlockLister interface { + // List lists all IPAMBlocks in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.IPAMBlock, err error) + // Get retrieves the IPAMBlock from the index for a given name. + Get(name string) (*v1alpha1.IPAMBlock, error) + IPAMBlockListerExpansion +} + +// iPAMBlockLister implements the IPAMBlockLister interface. +type iPAMBlockLister struct { + indexer cache.Indexer +} + +// NewIPAMBlockLister returns a new IPAMBlockLister. +func NewIPAMBlockLister(indexer cache.Indexer) IPAMBlockLister { + return &iPAMBlockLister{indexer: indexer} +} + +// List lists all IPAMBlocks in the indexer. +func (s *iPAMBlockLister) List(selector labels.Selector) (ret []*v1alpha1.IPAMBlock, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.IPAMBlock)) + }) + return ret, err +} + +// Get retrieves the IPAMBlock from the index for a given name. +func (s *iPAMBlockLister) Get(name string) (*v1alpha1.IPAMBlock, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("ipamblock"), name) + } + return obj.(*v1alpha1.IPAMBlock), nil +} diff --git a/pkg/client/listers/network/v1alpha1/ipamhandle.go b/pkg/client/listers/network/v1alpha1/ipamhandle.go new file mode 100644 index 000000000..a0796c975 --- /dev/null +++ b/pkg/client/listers/network/v1alpha1/ipamhandle.go @@ -0,0 +1,65 @@ +/* +Copyright 2020 The KubeSphere 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 lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" +) + +// IPAMHandleLister helps list IPAMHandles. +type IPAMHandleLister interface { + // List lists all IPAMHandles in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.IPAMHandle, err error) + // Get retrieves the IPAMHandle from the index for a given name. + Get(name string) (*v1alpha1.IPAMHandle, error) + IPAMHandleListerExpansion +} + +// iPAMHandleLister implements the IPAMHandleLister interface. +type iPAMHandleLister struct { + indexer cache.Indexer +} + +// NewIPAMHandleLister returns a new IPAMHandleLister. +func NewIPAMHandleLister(indexer cache.Indexer) IPAMHandleLister { + return &iPAMHandleLister{indexer: indexer} +} + +// List lists all IPAMHandles in the indexer. +func (s *iPAMHandleLister) List(selector labels.Selector) (ret []*v1alpha1.IPAMHandle, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.IPAMHandle)) + }) + return ret, err +} + +// Get retrieves the IPAMHandle from the index for a given name. +func (s *iPAMHandleLister) Get(name string) (*v1alpha1.IPAMHandle, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("ipamhandle"), name) + } + return obj.(*v1alpha1.IPAMHandle), nil +} diff --git a/pkg/client/listers/network/v1alpha1/ippool.go b/pkg/client/listers/network/v1alpha1/ippool.go new file mode 100644 index 000000000..9cf51c6ee --- /dev/null +++ b/pkg/client/listers/network/v1alpha1/ippool.go @@ -0,0 +1,65 @@ +/* +Copyright 2020 The KubeSphere 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 lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" +) + +// IPPoolLister helps list IPPools. +type IPPoolLister interface { + // List lists all IPPools in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.IPPool, err error) + // Get retrieves the IPPool from the index for a given name. + Get(name string) (*v1alpha1.IPPool, error) + IPPoolListerExpansion +} + +// iPPoolLister implements the IPPoolLister interface. +type iPPoolLister struct { + indexer cache.Indexer +} + +// NewIPPoolLister returns a new IPPoolLister. +func NewIPPoolLister(indexer cache.Indexer) IPPoolLister { + return &iPPoolLister{indexer: indexer} +} + +// List lists all IPPools in the indexer. +func (s *iPPoolLister) List(selector labels.Selector) (ret []*v1alpha1.IPPool, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.IPPool)) + }) + return ret, err +} + +// Get retrieves the IPPool from the index for a given name. +func (s *iPPoolLister) Get(name string) (*v1alpha1.IPPool, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("ippool"), name) + } + return obj.(*v1alpha1.IPPool), nil +} diff --git a/pkg/controller/network/ippool/ippool_controller.go b/pkg/controller/network/ippool/ippool_controller.go new file mode 100644 index 000000000..892e434ee --- /dev/null +++ b/pkg/controller/network/ippool/ippool_controller.go @@ -0,0 +1,354 @@ +/* +Copyright 2020 KubeSphere 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 ippool + +import ( + "fmt" + "reflect" + "time" + + cnet "github.com/projectcalico/libcalico-go/lib/net" + v1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog" + networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + kubesphereclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + networkInformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/network/v1alpha1" + "kubesphere.io/kubesphere/pkg/controller/network/utils" + "kubesphere.io/kubesphere/pkg/simple/client/network/ippool" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +var ( + ErrCIDROverlap = fmt.Errorf("CIDR is overlap") +) + +type IPPoolController struct { + eventBroadcaster record.EventBroadcaster + eventRecorder record.EventRecorder + + provider ippool.Provider + + ippoolInformer networkInformer.IPPoolInformer + ippoolSynced cache.InformerSynced + ippoolQueue workqueue.RateLimitingInterface + + ipamblockInformer networkInformer.IPAMBlockInformer + ipamblockSynced cache.InformerSynced + + client clientset.Interface + kubesphereClient kubesphereclient.Interface + + options ippool.Options +} + +func (c *IPPoolController) ippoolHandle(obj interface{}) { + pool, ok := obj.(*networkv1alpha1.IPPool) + if !ok { + utilruntime.HandleError(fmt.Errorf("IPPool informer returned non-ippool object: %#v", obj)) + return + } + key, err := cache.MetaNamespaceKeyFunc(pool) + if err != nil { + utilruntime.HandleError(fmt.Errorf("couldn't get key for ippool %#v: %v", pool, err)) + return + } + + if utils.NeedToAddFinalizer(pool, networkv1alpha1.IPPoolFinalizer) || utils.IsDeletionCandidate(pool, networkv1alpha1.IPPoolFinalizer) { + c.ippoolQueue.Add(key) + } +} + +func (c *IPPoolController) addFinalizer(pool *networkv1alpha1.IPPool) error { + clone := pool.DeepCopy() + controllerutil.AddFinalizer(clone, networkv1alpha1.IPPoolFinalizer) + clone.Labels = map[string]string{ + networkv1alpha1.IPPoolNameLabel: clone.Name, + networkv1alpha1.IPPoolTypeLabel: clone.Spec.Type, + networkv1alpha1.IPPoolIDLabel: fmt.Sprintf("%d", clone.ID()), + } + pool, err := c.kubesphereClient.NetworkV1alpha1().IPPools().Update(clone) + if err != nil { + klog.V(3).Infof("Error adding finalizer to pool %s: %v", pool.Name, err) + return err + } + klog.V(3).Infof("Added finalizer to pool %s", pool.Name) + return nil +} + +func (c *IPPoolController) removeFinalizer(pool *networkv1alpha1.IPPool) error { + clone := pool.DeepCopy() + controllerutil.RemoveFinalizer(clone, networkv1alpha1.IPPoolFinalizer) + pool, err := c.kubesphereClient.NetworkV1alpha1().IPPools().Update(clone) + if err != nil { + klog.V(3).Infof("Error removing finalizer from pool %s: %v", pool.Name, err) + return err + } + klog.V(3).Infof("Removed protection finalizer from pool %s", pool.Name) + return nil +} + +// check cidr overlap +func (c *IPPoolController) checkIPPool(pool *networkv1alpha1.IPPool) (bool, error) { + _, poolCIDR, err := cnet.ParseCIDR(pool.Spec.CIDR) + if err != nil { + return false, err + } + + pools, err := c.kubesphereClient.NetworkV1alpha1().IPPools().List(metav1.ListOptions{ + LabelSelector: labels.SelectorFromSet(labels.Set{ + networkv1alpha1.IPPoolIDLabel: fmt.Sprintf("%d", pool.ID()), + }).String(), + }) + + if err != nil { + return false, err + } + + for _, p := range pools.Items { + _, cidr, err := cnet.ParseCIDR(p.Spec.CIDR) + if err != nil { + return false, err + } + + if cidr.IsNetOverlap(poolCIDR.IPNet) { + return false, ErrCIDROverlap + } + } + + return true, nil +} + +func (c *IPPoolController) disableIPPool(old *networkv1alpha1.IPPool) error { + if old.Spec.Disabled { + return nil + } + + clone := old.DeepCopy() + clone.Spec.Disabled = true + + old, err := c.kubesphereClient.NetworkV1alpha1().IPPools().Update(clone) + + return err +} + +func (c *IPPoolController) updateIPPoolStatus(old *networkv1alpha1.IPPool) error { + new, err := c.provider.GetIPPoolStats(old) + if err != nil { + return err + } + + if reflect.DeepEqual(old.Status, new.Status) { + return nil + } + + clone := old.DeepCopy() + clone.Status = new.Status + old, err = c.kubesphereClient.NetworkV1alpha1().IPPools().Update(clone) + + return err +} + +func (c *IPPoolController) processIPPool(name string) (*time.Duration, error) { + klog.V(4).Infof("Processing IPPool %s", name) + startTime := time.Now() + defer func() { + klog.V(4).Infof("Finished processing IPPool %s (%v)", name, time.Since(startTime)) + }() + + pool, err := c.ippoolInformer.Lister().Get(name) + if apierrors.IsNotFound(err) { + return nil, nil + } else if err != nil { + return nil, err + } + + if utils.IsDeletionCandidate(pool, networkv1alpha1.IPPoolFinalizer) { + err = c.disableIPPool(pool) + if err != nil { + return nil, err + } + + // Pool should be deleted. Check if it's used and remove finalizer if + // it's not. + canDelete, err := c.provider.DeleteIPPool(pool) + if err != nil { + return nil, err + } + if canDelete { + return nil, c.removeFinalizer(pool) + } + + //The ippool is being used, update status and try again later. + delay := time.Second * 3 + return &delay, c.updateIPPoolStatus(pool) + } + + if utils.NeedToAddFinalizer(pool, networkv1alpha1.IPPoolFinalizer) { + valid, err := c.checkIPPool(pool) + if err != nil { + return nil, err + } + if !valid { + return nil, nil + } + + err = c.addFinalizer(pool) + if err != nil { + return nil, err + } + + err = c.provider.CreateIPPool(pool) + if err != nil { + klog.V(4).Infof("Provider failed to create IPPool %s, err=%v", pool.Name, err) + return nil, err + } + + return nil, c.updateIPPoolStatus(pool) + } + + err = c.provider.UpdateIPPool(pool) + if err != nil { + klog.V(4).Infof("Provider failed to update IPPool %s, err=%v", pool.Name, err) + return nil, err + } + + return nil, c.updateIPPoolStatus(pool) +} + +func (c *IPPoolController) Start(stopCh <-chan struct{}) error { + go c.provider.SyncStatus(stopCh, c.ippoolQueue) + return c.Run(5, stopCh) +} + +func (c *IPPoolController) Run(workers int, stopCh <-chan struct{}) error { + defer utilruntime.HandleCrash() + defer c.ippoolQueue.ShutDown() + + klog.Info("starting ippool controller") + defer klog.Info("shutting down ippool controller") + + if !cache.WaitForCacheSync(stopCh, c.ippoolSynced, c.ipamblockSynced) { + return fmt.Errorf("failed to wait for caches to sync") + } + + for i := 0; i < workers; i++ { + go wait.Until(c.runWorker, time.Second, stopCh) + } + + <-stopCh + return nil +} + +func (c *IPPoolController) runWorker() { + for c.processIPPoolItem() { + } +} + +func (c *IPPoolController) processIPPoolItem() bool { + key, quit := c.ippoolQueue.Get() + if quit { + return false + } + defer c.ippoolQueue.Done(key) + + _, name, err := cache.SplitMetaNamespaceKey(key.(string)) + if err != nil { + utilruntime.HandleError(fmt.Errorf("error parsing ippool key %q: %v", key, err)) + return true + } + + delay, err := c.processIPPool(name) + if err == nil { + c.ippoolQueue.Forget(key) + return true + } else if delay != nil { + c.ippoolQueue.AddAfter(key, *delay) + } + + utilruntime.HandleError(fmt.Errorf("error processing ippool %v (will retry): %v", key, err)) + c.ippoolQueue.AddRateLimited(key) + return true +} + +func (c *IPPoolController) ipamblockHandle(obj interface{}) { + block, ok := obj.(*networkv1alpha1.IPAMBlock) + if !ok { + return + } + + poolName := block.Labels[networkv1alpha1.IPPoolNameLabel] + c.ippoolQueue.Add(poolName) +} + +func NewIPPoolController( + ippoolInformer networkInformer.IPPoolInformer, + ipamblockInformer networkInformer.IPAMBlockInformer, + client clientset.Interface, + kubesphereClient kubesphereclient.Interface, + options ippool.Options, + provider ippool.Provider) *IPPoolController { + + broadcaster := record.NewBroadcaster() + broadcaster.StartLogging(func(format string, args ...interface{}) { + klog.Info(fmt.Sprintf(format, args)) + }) + broadcaster.StartRecordingToSink(&corev1.EventSinkImpl{Interface: client.CoreV1().Events("")}) + recorder := broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cluster-controller"}) + + c := &IPPoolController{ + eventBroadcaster: broadcaster, + eventRecorder: recorder, + ippoolInformer: ippoolInformer, + ippoolSynced: ippoolInformer.Informer().HasSynced, + ippoolQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "ippool"), + ipamblockInformer: ipamblockInformer, + ipamblockSynced: ipamblockInformer.Informer().HasSynced, + client: client, + kubesphereClient: kubesphereClient, + options: options, + provider: provider, + } + + ippoolInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: c.ippoolHandle, + UpdateFunc: func(old, new interface{}) { + c.ippoolHandle(new) + }, + }) + + //just for update ippool status + ipamblockInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: c.ipamblockHandle, + UpdateFunc: func(old, new interface{}) { + c.ipamblockHandle(new) + }, + DeleteFunc: c.ipamblockHandle, + }) + + return c +} diff --git a/pkg/controller/network/ippool/ippool_controller_test.go b/pkg/controller/network/ippool/ippool_controller_test.go new file mode 100644 index 000000000..b04c7e931 --- /dev/null +++ b/pkg/controller/network/ippool/ippool_controller_test.go @@ -0,0 +1,124 @@ +/* +Copyright 2020 The KubeSphere 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 ippool + +import ( + "flag" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8sfake "k8s.io/client-go/kubernetes/fake" + "k8s.io/klog" + "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + ksfake "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake" + ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions" + "kubesphere.io/kubesphere/pkg/controller/network/utils" + "kubesphere.io/kubesphere/pkg/simple/client/network/ippool" + "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/ipam" + "testing" +) + +func TestIPPoolSuit(t *testing.T) { + klog.InitFlags(nil) + flag.Set("logtostderr", "true") + flag.Set("v", "4") + flag.Parse() + klog.SetOutput(GinkgoWriter) + RegisterFailHandler(Fail) + RunSpecs(t, "IPPool Suite") +} + +var _ = Describe("test ippool", func() { + pool := &v1alpha1.IPPool{ + TypeMeta: v1.TypeMeta{}, + ObjectMeta: v1.ObjectMeta{ + Name: "testippool", + }, + Spec: v1alpha1.IPPoolSpec{ + Type: v1alpha1.VLAN, + CIDR: "192.168.0.0/24", + BlockSize: 24, + }, + Status: v1alpha1.IPPoolStatus{}, + } + + ksclient := ksfake.NewSimpleClientset() + k8sclinet := k8sfake.NewSimpleClientset() + options := ippool.Options{} + p := ippool.NewProvider(ksclient, options) + ipamClient := ipam.NewIPAMClient(ksclient, v1alpha1.VLAN) + + ksInformer := ksinformers.NewSharedInformerFactory(ksclient, 0) + ippoolInformer := ksInformer.Network().V1alpha1().IPPools() + ipamblockInformer := ksInformer.Network().V1alpha1().IPAMBlocks() + c := NewIPPoolController(ippoolInformer, ipamblockInformer, k8sclinet, ksclient, options, p) + + stopCh := make(chan struct{}) + go ksInformer.Start(stopCh) + go c.Start(stopCh) + + It("test create ippool", func() { + _, err := ksclient.NetworkV1alpha1().IPPools().Create(pool) + Expect(err).ShouldNot(HaveOccurred()) + Eventually(func() bool { + result, _ := ksclient.NetworkV1alpha1().IPPools().Get(pool.Name, v1.GetOptions{}) + if len(result.Labels) != 3 { + return false + } + + if utils.NeedToAddFinalizer(result, v1alpha1.IPPoolFinalizer) { + return false + } + + return true + }).Should(Equal(true)) + }) + + It("test ippool stats", func() { + ipamClient.AutoAssign(ipam.AutoAssignArgs{ + HandleID: "testhandle", + Attrs: nil, + Pool: "testippool", + }) + + Eventually(func() bool { + result, _ := ksclient.NetworkV1alpha1().IPPools().Get(pool.Name, v1.GetOptions{}) + if result.Status.Allocations != 1 { + return false + } + + return true + }).Should(Equal(true)) + }) + + It("test delete pool", func() { + ipamClient.ReleaseByHandle("testhandle") + Eventually(func() bool { + result, _ := ksclient.NetworkV1alpha1().IPPools().Get(pool.Name, v1.GetOptions{}) + if result.Status.Allocations != 0 { + return false + } + + return true + }).Should(Equal(true)) + + err := ksclient.NetworkV1alpha1().IPPools().Delete(pool.Name, &v1.DeleteOptions{}) + Expect(err).ShouldNot(HaveOccurred()) + blocks, _ := ksclient.NetworkV1alpha1().IPAMBlocks().List(v1.ListOptions{}) + Expect(len(blocks.Items)).Should(Equal(0)) + }) +}) diff --git a/pkg/controller/network/nsnetworkpolicy/nsnetworkpolicy_controller.go b/pkg/controller/network/nsnetworkpolicy/nsnetworkpolicy_controller.go index b27d8293a..4308a2b5a 100644 --- a/pkg/controller/network/nsnetworkpolicy/nsnetworkpolicy_controller.go +++ b/pkg/controller/network/nsnetworkpolicy/nsnetworkpolicy_controller.go @@ -18,6 +18,7 @@ package nsnetworkpolicy import ( "fmt" + "kubesphere.io/kubesphere/pkg/controller/network/types" "net" "sort" "strings" @@ -43,8 +44,7 @@ import ( nspolicy "kubesphere.io/kubesphere/pkg/client/informers/externalversions/network/v1alpha1" workspace "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant/v1alpha1" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/controller/network" - "kubesphere.io/kubesphere/pkg/controller/network/provider" + "kubesphere.io/kubesphere/pkg/controller/network/nsnetworkpolicy/provider" options "kubesphere.io/kubesphere/pkg/simple/client/network" ) @@ -62,7 +62,7 @@ const ( NodeNSNPAnnotationKey = "kubesphere.io/snat-node-ips" - AnnotationNPNAME = network.NSNPPrefix + "network-isolate" + AnnotationNPNAME = types.NSNPPrefix + "network-isolate" //TODO: configure it DNSLocalIP = "169.254.25.10" @@ -222,7 +222,7 @@ func (c *NSNetworkPolicyController) convertPeer(peer v1alpha1.NetworkPolicyPeer, func (c *NSNetworkPolicyController) convertToK8sNP(n *v1alpha1.NamespaceNetworkPolicy) (*netv1.NetworkPolicy, error) { np := &netv1.NetworkPolicy{ ObjectMeta: metav1.ObjectMeta{ - Name: network.NSNPPrefix + n.Name, + Name: types.NSNPPrefix + n.Name, Namespace: n.Namespace, }, Spec: netv1.NetworkPolicySpec{ @@ -564,7 +564,7 @@ func (c *NSNetworkPolicyController) syncNSNP(key string) error { if err != nil { if errors.IsNotFound(err) { klog.V(4).Infof("NSNP %v has been deleted", key) - c.provider.Delete(c.provider.GetKey(network.NSNPPrefix+name, namespace)) + c.provider.Delete(c.provider.GetKey(types.NSNPPrefix+name, namespace)) return nil } diff --git a/pkg/controller/network/nsnetworkpolicy/nsnetworkpolicy_test.go b/pkg/controller/network/nsnetworkpolicy/nsnetworkpolicy_test.go index f15f01e88..615dc5093 100644 --- a/pkg/controller/network/nsnetworkpolicy/nsnetworkpolicy_test.go +++ b/pkg/controller/network/nsnetworkpolicy/nsnetworkpolicy_test.go @@ -37,7 +37,7 @@ import ( nsnppolicyinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/network/v1alpha1" workspaceinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant/v1alpha1" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/controller/network/provider" + "kubesphere.io/kubesphere/pkg/controller/network/nsnetworkpolicy/provider" options "kubesphere.io/kubesphere/pkg/simple/client/network" ) diff --git a/pkg/controller/network/provider/fake_ns.go b/pkg/controller/network/nsnetworkpolicy/provider/fake_ns.go similarity index 100% rename from pkg/controller/network/provider/fake_ns.go rename to pkg/controller/network/nsnetworkpolicy/provider/fake_ns.go diff --git a/pkg/controller/network/provider/namespace_np.go b/pkg/controller/network/nsnetworkpolicy/provider/namespace_np.go similarity index 100% rename from pkg/controller/network/provider/namespace_np.go rename to pkg/controller/network/nsnetworkpolicy/provider/namespace_np.go diff --git a/pkg/controller/network/provider/ns_k8s.go b/pkg/controller/network/nsnetworkpolicy/provider/ns_k8s.go similarity index 98% rename from pkg/controller/network/provider/ns_k8s.go rename to pkg/controller/network/nsnetworkpolicy/provider/ns_k8s.go index deb336c32..a22b00cd4 100644 --- a/pkg/controller/network/provider/ns_k8s.go +++ b/pkg/controller/network/nsnetworkpolicy/provider/ns_k8s.go @@ -19,6 +19,7 @@ package provider import ( "context" "fmt" + "kubesphere.io/kubesphere/pkg/controller/network/types" "reflect" "strings" "sync" @@ -35,7 +36,6 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" "k8s.io/klog" - "kubesphere.io/kubesphere/pkg/controller/network" ) const ( @@ -246,7 +246,7 @@ func NewNsNetworkPolicyProvider(client kubernetes.Interface, npInformer informer // Filter in only objects that are written by policy controller. m := make(map[string]interface{}) for _, policy := range policies { - if strings.HasPrefix(policy.Name, network.NSNPPrefix) { + if strings.HasPrefix(policy.Name, types.NSNPPrefix) { policy.ObjectMeta = metav1.ObjectMeta{Name: policy.Name, Namespace: policy.Namespace} k := c.GetKey(policy.Name, policy.Namespace) m[k] = *policy diff --git a/pkg/controller/network/types.go b/pkg/controller/network/types/types.go similarity index 97% rename from pkg/controller/network/types.go rename to pkg/controller/network/types/types.go index a81d47a7e..d2e150693 100644 --- a/pkg/controller/network/types.go +++ b/pkg/controller/network/types/types.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package network +package types const ( NSNPPrefix = "nsnp-" diff --git a/pkg/controller/network/utils/utils.go b/pkg/controller/network/utils/utils.go new file mode 100644 index 000000000..0133b10f3 --- /dev/null +++ b/pkg/controller/network/utils/utils.go @@ -0,0 +1,71 @@ +package utils + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sort" +) + +// IsDeletionCandidate checks if object is candidate to be deleted +func IsDeletionCandidate(obj metav1.Object, finalizer string) bool { + return obj.GetDeletionTimestamp() != nil && ContainsString(obj.GetFinalizers(), + finalizer, nil) +} + +// NeedToAddFinalizer checks if need to add finalizer to object +func NeedToAddFinalizer(obj metav1.Object, finalizer string) bool { + return obj.GetDeletionTimestamp() == nil && !ContainsString(obj.GetFinalizers(), + finalizer, nil) +} + +// CopyStrings copies the contents of the specified string slice +// into a new slice. +func CopyStrings(s []string) []string { + if s == nil { + return nil + } + c := make([]string, len(s)) + copy(c, s) + return c +} + +// SortStrings sorts the specified string slice in place. It returns the same +// slice that was provided in order to facilitate method chaining. +func SortStrings(s []string) []string { + sort.Strings(s) + return s +} + +// ContainsString checks if a given slice of strings contains the provided string. +// If a modifier func is provided, it is called with the slice item before the comparation. +func ContainsString(slice []string, s string, modifier func(s string) string) bool { + for _, item := range slice { + if item == s { + return true + } + if modifier != nil && modifier(item) == s { + return true + } + } + return false +} + +// RemoveString returns a newly created []string that contains all items from slice that +// are not equal to s and modifier(s) in case modifier func is provided. +func RemoveString(slice []string, s string, modifier func(s string) string) []string { + newSlice := make([]string, 0) + for _, item := range slice { + if item == s { + continue + } + if modifier != nil && modifier(item) == s { + continue + } + newSlice = append(newSlice, item) + } + if len(newSlice) == 0 { + // Sanitize for unit tests so we don't need to distinguish empty array + // and nil. + newSlice = nil + } + return newSlice +} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/clientset.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/clientset.go new file mode 100644 index 000000000..7b15d9765 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/clientset.go @@ -0,0 +1,97 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package versioned + +import ( + "fmt" + + discovery "k8s.io/client-go/discovery" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" + crdcalicov3 "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + CrdCalicov3() crdcalicov3.CrdCalicov3Interface +} + +// Clientset contains the clients for groups. Each group has exactly one +// version included in a Clientset. +type Clientset struct { + *discovery.DiscoveryClient + crdCalicov3 *crdcalicov3.CrdCalicov3Client +} + +// CrdCalicov3 retrieves the CrdCalicov3Client +func (c *Clientset) CrdCalicov3() crdcalicov3.CrdCalicov3Interface { + return c.crdCalicov3 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfig will generate a rate-limiter in configShallowCopy. +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + if configShallowCopy.Burst <= 0 { + return nil, fmt.Errorf("Burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") + } + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + var cs Clientset + var err error + cs.crdCalicov3, err = crdcalicov3.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + var cs Clientset + cs.crdCalicov3 = crdcalicov3.NewForConfigOrDie(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) + return &cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.crdCalicov3 = crdcalicov3.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/doc.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/doc.go new file mode 100644 index 000000000..446c7b501 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +// This package has the automatically generated clientset. +package versioned diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/fake/clientset_generated.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/fake/clientset_generated.go new file mode 100644 index 000000000..79b94cf7f --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/fake/clientset_generated.go @@ -0,0 +1,82 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package fake + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/discovery" + fakediscovery "k8s.io/client-go/discovery/fake" + "k8s.io/client-go/testing" + clientset "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned" + crdcalicov3 "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3" + fakecrdcalicov3 "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake" +) + +// NewSimpleClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +func NewSimpleClientset(objects ...runtime.Object) *Clientset { + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{tracker: o} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.Interface. Meant to be embedded into a +// struct to get a default implementation. This makes faking out just the method +// you want to test easier. +type Clientset struct { + testing.Fake + discovery *fakediscovery.FakeDiscovery + tracker testing.ObjectTracker +} + +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} + +func (c *Clientset) Tracker() testing.ObjectTracker { + return c.tracker +} + +var _ clientset.Interface = &Clientset{} + +// CrdCalicov3 retrieves the CrdCalicov3Client +func (c *Clientset) CrdCalicov3() crdcalicov3.CrdCalicov3Interface { + return &fakecrdcalicov3.FakeCrdCalicov3{Fake: &c.Fake} +} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/fake/doc.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/fake/doc.go new file mode 100644 index 000000000..89d75efb1 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +// This package has the automatically generated fake clientset. +package fake diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/fake/register.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/fake/register.go new file mode 100644 index 000000000..81f055ff0 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/fake/register.go @@ -0,0 +1,56 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + crdcalicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" +) + +var scheme = runtime.NewScheme() +var codecs = serializer.NewCodecFactory(scheme) +var parameterCodec = runtime.NewParameterCodec(scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + crdcalicov3.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(scheme)) +} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/scheme/doc.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/scheme/doc.go new file mode 100644 index 000000000..5421e6d16 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/scheme/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/scheme/register.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/scheme/register.go new file mode 100644 index 000000000..66a4007fd --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/scheme/register.go @@ -0,0 +1,56 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package scheme + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + crdcalicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + crdcalicov3.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/blockaffinity.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/blockaffinity.go new file mode 100644 index 000000000..1f6a82723 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/blockaffinity.go @@ -0,0 +1,164 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package calicov3 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + calicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" + scheme "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned/scheme" +) + +// BlockAffinitiesGetter has a method to return a BlockAffinityInterface. +// A group's client should implement this interface. +type BlockAffinitiesGetter interface { + BlockAffinities() BlockAffinityInterface +} + +// BlockAffinityInterface has methods to work with BlockAffinity resources. +type BlockAffinityInterface interface { + Create(*calicov3.BlockAffinity) (*calicov3.BlockAffinity, error) + Update(*calicov3.BlockAffinity) (*calicov3.BlockAffinity, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*calicov3.BlockAffinity, error) + List(opts v1.ListOptions) (*calicov3.BlockAffinityList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *calicov3.BlockAffinity, err error) + BlockAffinityExpansion +} + +// blockAffinities implements BlockAffinityInterface +type blockAffinities struct { + client rest.Interface +} + +// newBlockAffinities returns a BlockAffinities +func newBlockAffinities(c *CrdCalicov3Client) *blockAffinities { + return &blockAffinities{ + client: c.RESTClient(), + } +} + +// Get takes name of the blockAffinity, and returns the corresponding blockAffinity object, and an error if there is any. +func (c *blockAffinities) Get(name string, options v1.GetOptions) (result *calicov3.BlockAffinity, err error) { + result = &calicov3.BlockAffinity{} + err = c.client.Get(). + Resource("blockaffinities"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of BlockAffinities that match those selectors. +func (c *blockAffinities) List(opts v1.ListOptions) (result *calicov3.BlockAffinityList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &calicov3.BlockAffinityList{} + err = c.client.Get(). + Resource("blockaffinities"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested blockAffinities. +func (c *blockAffinities) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("blockaffinities"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a blockAffinity and creates it. Returns the server's representation of the blockAffinity, and an error, if there is any. +func (c *blockAffinities) Create(blockAffinity *calicov3.BlockAffinity) (result *calicov3.BlockAffinity, err error) { + result = &calicov3.BlockAffinity{} + err = c.client.Post(). + Resource("blockaffinities"). + Body(blockAffinity). + Do(). + Into(result) + return +} + +// Update takes the representation of a blockAffinity and updates it. Returns the server's representation of the blockAffinity, and an error, if there is any. +func (c *blockAffinities) Update(blockAffinity *calicov3.BlockAffinity) (result *calicov3.BlockAffinity, err error) { + result = &calicov3.BlockAffinity{} + err = c.client.Put(). + Resource("blockaffinities"). + Name(blockAffinity.Name). + Body(blockAffinity). + Do(). + Into(result) + return +} + +// Delete takes name of the blockAffinity and deletes it. Returns an error if one occurs. +func (c *blockAffinities) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("blockaffinities"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *blockAffinities) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("blockaffinities"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched blockAffinity. +func (c *blockAffinities) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *calicov3.BlockAffinity, err error) { + result = &calicov3.BlockAffinity{} + err = c.client.Patch(pt). + Resource("blockaffinities"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/doc.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/doc.go new file mode 100644 index 000000000..b84976afc --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package calicov3 diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/doc.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/doc.go new file mode 100644 index 000000000..7e36dbca8 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/fake_blockaffinity.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/fake_blockaffinity.go new file mode 100644 index 000000000..92ee721da --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/fake_blockaffinity.go @@ -0,0 +1,120 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + calicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" +) + +// FakeBlockAffinities implements BlockAffinityInterface +type FakeBlockAffinities struct { + Fake *FakeCrdCalicov3 +} + +var blockaffinitiesResource = schema.GroupVersionResource{Group: "crd.projectcalico.org", Version: "calicov3", Resource: "blockaffinities"} + +var blockaffinitiesKind = schema.GroupVersionKind{Group: "crd.projectcalico.org", Version: "calicov3", Kind: "BlockAffinity"} + +// Get takes name of the blockAffinity, and returns the corresponding blockAffinity object, and an error if there is any. +func (c *FakeBlockAffinities) Get(name string, options v1.GetOptions) (result *calicov3.BlockAffinity, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(blockaffinitiesResource, name), &calicov3.BlockAffinity{}) + if obj == nil { + return nil, err + } + return obj.(*calicov3.BlockAffinity), err +} + +// List takes label and field selectors, and returns the list of BlockAffinities that match those selectors. +func (c *FakeBlockAffinities) List(opts v1.ListOptions) (result *calicov3.BlockAffinityList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(blockaffinitiesResource, blockaffinitiesKind, opts), &calicov3.BlockAffinityList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &calicov3.BlockAffinityList{ListMeta: obj.(*calicov3.BlockAffinityList).ListMeta} + for _, item := range obj.(*calicov3.BlockAffinityList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested blockAffinities. +func (c *FakeBlockAffinities) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(blockaffinitiesResource, opts)) +} + +// Create takes the representation of a blockAffinity and creates it. Returns the server's representation of the blockAffinity, and an error, if there is any. +func (c *FakeBlockAffinities) Create(blockAffinity *calicov3.BlockAffinity) (result *calicov3.BlockAffinity, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(blockaffinitiesResource, blockAffinity), &calicov3.BlockAffinity{}) + if obj == nil { + return nil, err + } + return obj.(*calicov3.BlockAffinity), err +} + +// Update takes the representation of a blockAffinity and updates it. Returns the server's representation of the blockAffinity, and an error, if there is any. +func (c *FakeBlockAffinities) Update(blockAffinity *calicov3.BlockAffinity) (result *calicov3.BlockAffinity, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(blockaffinitiesResource, blockAffinity), &calicov3.BlockAffinity{}) + if obj == nil { + return nil, err + } + return obj.(*calicov3.BlockAffinity), err +} + +// Delete takes name of the blockAffinity and deletes it. Returns an error if one occurs. +func (c *FakeBlockAffinities) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(blockaffinitiesResource, name), &calicov3.BlockAffinity{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeBlockAffinities) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(blockaffinitiesResource, listOptions) + + _, err := c.Fake.Invokes(action, &calicov3.BlockAffinityList{}) + return err +} + +// Patch applies the patch and returns the patched blockAffinity. +func (c *FakeBlockAffinities) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *calicov3.BlockAffinity, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(blockaffinitiesResource, name, pt, data, subresources...), &calicov3.BlockAffinity{}) + if obj == nil { + return nil, err + } + return obj.(*calicov3.BlockAffinity), err +} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/fake_ipamblock.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/fake_ipamblock.go new file mode 100644 index 000000000..c6362927a --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/fake_ipamblock.go @@ -0,0 +1,120 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + calicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" +) + +// FakeIPAMBlocks implements IPAMBlockInterface +type FakeIPAMBlocks struct { + Fake *FakeCrdCalicov3 +} + +var ipamblocksResource = schema.GroupVersionResource{Group: "crd.projectcalico.org", Version: "calicov3", Resource: "ipamblocks"} + +var ipamblocksKind = schema.GroupVersionKind{Group: "crd.projectcalico.org", Version: "calicov3", Kind: "IPAMBlock"} + +// Get takes name of the iPAMBlock, and returns the corresponding iPAMBlock object, and an error if there is any. +func (c *FakeIPAMBlocks) Get(name string, options v1.GetOptions) (result *calicov3.IPAMBlock, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(ipamblocksResource, name), &calicov3.IPAMBlock{}) + if obj == nil { + return nil, err + } + return obj.(*calicov3.IPAMBlock), err +} + +// List takes label and field selectors, and returns the list of IPAMBlocks that match those selectors. +func (c *FakeIPAMBlocks) List(opts v1.ListOptions) (result *calicov3.IPAMBlockList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(ipamblocksResource, ipamblocksKind, opts), &calicov3.IPAMBlockList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &calicov3.IPAMBlockList{ListMeta: obj.(*calicov3.IPAMBlockList).ListMeta} + for _, item := range obj.(*calicov3.IPAMBlockList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested iPAMBlocks. +func (c *FakeIPAMBlocks) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(ipamblocksResource, opts)) +} + +// Create takes the representation of a iPAMBlock and creates it. Returns the server's representation of the iPAMBlock, and an error, if there is any. +func (c *FakeIPAMBlocks) Create(iPAMBlock *calicov3.IPAMBlock) (result *calicov3.IPAMBlock, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(ipamblocksResource, iPAMBlock), &calicov3.IPAMBlock{}) + if obj == nil { + return nil, err + } + return obj.(*calicov3.IPAMBlock), err +} + +// Update takes the representation of a iPAMBlock and updates it. Returns the server's representation of the iPAMBlock, and an error, if there is any. +func (c *FakeIPAMBlocks) Update(iPAMBlock *calicov3.IPAMBlock) (result *calicov3.IPAMBlock, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(ipamblocksResource, iPAMBlock), &calicov3.IPAMBlock{}) + if obj == nil { + return nil, err + } + return obj.(*calicov3.IPAMBlock), err +} + +// Delete takes name of the iPAMBlock and deletes it. Returns an error if one occurs. +func (c *FakeIPAMBlocks) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(ipamblocksResource, name), &calicov3.IPAMBlock{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeIPAMBlocks) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(ipamblocksResource, listOptions) + + _, err := c.Fake.Invokes(action, &calicov3.IPAMBlockList{}) + return err +} + +// Patch applies the patch and returns the patched iPAMBlock. +func (c *FakeIPAMBlocks) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *calicov3.IPAMBlock, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(ipamblocksResource, name, pt, data, subresources...), &calicov3.IPAMBlock{}) + if obj == nil { + return nil, err + } + return obj.(*calicov3.IPAMBlock), err +} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/fake_ippool.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/fake_ippool.go new file mode 100644 index 000000000..e713cf837 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/fake_ippool.go @@ -0,0 +1,120 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + calicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" +) + +// FakeIPPools implements IPPoolInterface +type FakeIPPools struct { + Fake *FakeCrdCalicov3 +} + +var ippoolsResource = schema.GroupVersionResource{Group: "crd.projectcalico.org", Version: "calicov3", Resource: "ippools"} + +var ippoolsKind = schema.GroupVersionKind{Group: "crd.projectcalico.org", Version: "calicov3", Kind: "IPPool"} + +// Get takes name of the iPPool, and returns the corresponding iPPool object, and an error if there is any. +func (c *FakeIPPools) Get(name string, options v1.GetOptions) (result *calicov3.IPPool, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(ippoolsResource, name), &calicov3.IPPool{}) + if obj == nil { + return nil, err + } + return obj.(*calicov3.IPPool), err +} + +// List takes label and field selectors, and returns the list of IPPools that match those selectors. +func (c *FakeIPPools) List(opts v1.ListOptions) (result *calicov3.IPPoolList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(ippoolsResource, ippoolsKind, opts), &calicov3.IPPoolList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &calicov3.IPPoolList{ListMeta: obj.(*calicov3.IPPoolList).ListMeta} + for _, item := range obj.(*calicov3.IPPoolList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested iPPools. +func (c *FakeIPPools) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(ippoolsResource, opts)) +} + +// Create takes the representation of a iPPool and creates it. Returns the server's representation of the iPPool, and an error, if there is any. +func (c *FakeIPPools) Create(iPPool *calicov3.IPPool) (result *calicov3.IPPool, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(ippoolsResource, iPPool), &calicov3.IPPool{}) + if obj == nil { + return nil, err + } + return obj.(*calicov3.IPPool), err +} + +// Update takes the representation of a iPPool and updates it. Returns the server's representation of the iPPool, and an error, if there is any. +func (c *FakeIPPools) Update(iPPool *calicov3.IPPool) (result *calicov3.IPPool, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(ippoolsResource, iPPool), &calicov3.IPPool{}) + if obj == nil { + return nil, err + } + return obj.(*calicov3.IPPool), err +} + +// Delete takes name of the iPPool and deletes it. Returns an error if one occurs. +func (c *FakeIPPools) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(ippoolsResource, name), &calicov3.IPPool{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeIPPools) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(ippoolsResource, listOptions) + + _, err := c.Fake.Invokes(action, &calicov3.IPPoolList{}) + return err +} + +// Patch applies the patch and returns the patched iPPool. +func (c *FakeIPPools) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *calicov3.IPPool, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(ippoolsResource, name, pt, data, subresources...), &calicov3.IPPool{}) + if obj == nil { + return nil, err + } + return obj.(*calicov3.IPPool), err +} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/fake_network_client.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/fake_network_client.go new file mode 100644 index 000000000..bbcf79e90 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/fake/fake_network_client.go @@ -0,0 +1,48 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + calicov3 "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3" +) + +type FakeCrdCalicov3 struct { + *testing.Fake +} + +func (c *FakeCrdCalicov3) BlockAffinities() calicov3.BlockAffinityInterface { + return &FakeBlockAffinities{c} +} + +func (c *FakeCrdCalicov3) IPAMBlocks() calicov3.IPAMBlockInterface { + return &FakeIPAMBlocks{c} +} + +func (c *FakeCrdCalicov3) IPPools() calicov3.IPPoolInterface { + return &FakeIPPools{c} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeCrdCalicov3) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/generated_expansion.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/generated_expansion.go new file mode 100644 index 000000000..504623a9a --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/generated_expansion.go @@ -0,0 +1,25 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package calicov3 + +type BlockAffinityExpansion interface{} + +type IPAMBlockExpansion interface{} + +type IPPoolExpansion interface{} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/ipamblock.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/ipamblock.go new file mode 100644 index 000000000..b8e3f42b5 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/ipamblock.go @@ -0,0 +1,164 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package calicov3 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + calicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" + scheme "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned/scheme" +) + +// IPAMBlocksGetter has a method to return a IPAMBlockInterface. +// A group's client should implement this interface. +type IPAMBlocksGetter interface { + IPAMBlocks() IPAMBlockInterface +} + +// IPAMBlockInterface has methods to work with IPAMBlock resources. +type IPAMBlockInterface interface { + Create(*calicov3.IPAMBlock) (*calicov3.IPAMBlock, error) + Update(*calicov3.IPAMBlock) (*calicov3.IPAMBlock, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*calicov3.IPAMBlock, error) + List(opts v1.ListOptions) (*calicov3.IPAMBlockList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *calicov3.IPAMBlock, err error) + IPAMBlockExpansion +} + +// iPAMBlocks implements IPAMBlockInterface +type iPAMBlocks struct { + client rest.Interface +} + +// newIPAMBlocks returns a IPAMBlocks +func newIPAMBlocks(c *CrdCalicov3Client) *iPAMBlocks { + return &iPAMBlocks{ + client: c.RESTClient(), + } +} + +// Get takes name of the iPAMBlock, and returns the corresponding iPAMBlock object, and an error if there is any. +func (c *iPAMBlocks) Get(name string, options v1.GetOptions) (result *calicov3.IPAMBlock, err error) { + result = &calicov3.IPAMBlock{} + err = c.client.Get(). + Resource("ipamblocks"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of IPAMBlocks that match those selectors. +func (c *iPAMBlocks) List(opts v1.ListOptions) (result *calicov3.IPAMBlockList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &calicov3.IPAMBlockList{} + err = c.client.Get(). + Resource("ipamblocks"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested iPAMBlocks. +func (c *iPAMBlocks) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("ipamblocks"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a iPAMBlock and creates it. Returns the server's representation of the iPAMBlock, and an error, if there is any. +func (c *iPAMBlocks) Create(iPAMBlock *calicov3.IPAMBlock) (result *calicov3.IPAMBlock, err error) { + result = &calicov3.IPAMBlock{} + err = c.client.Post(). + Resource("ipamblocks"). + Body(iPAMBlock). + Do(). + Into(result) + return +} + +// Update takes the representation of a iPAMBlock and updates it. Returns the server's representation of the iPAMBlock, and an error, if there is any. +func (c *iPAMBlocks) Update(iPAMBlock *calicov3.IPAMBlock) (result *calicov3.IPAMBlock, err error) { + result = &calicov3.IPAMBlock{} + err = c.client.Put(). + Resource("ipamblocks"). + Name(iPAMBlock.Name). + Body(iPAMBlock). + Do(). + Into(result) + return +} + +// Delete takes name of the iPAMBlock and deletes it. Returns an error if one occurs. +func (c *iPAMBlocks) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("ipamblocks"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *iPAMBlocks) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("ipamblocks"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched iPAMBlock. +func (c *iPAMBlocks) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *calicov3.IPAMBlock, err error) { + result = &calicov3.IPAMBlock{} + err = c.client.Patch(pt). + Resource("ipamblocks"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/ippool.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/ippool.go new file mode 100644 index 000000000..729d2e5a9 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/ippool.go @@ -0,0 +1,164 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package calicov3 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + calicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" + scheme "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned/scheme" +) + +// IPPoolsGetter has a method to return a IPPoolInterface. +// A group's client should implement this interface. +type IPPoolsGetter interface { + IPPools() IPPoolInterface +} + +// IPPoolInterface has methods to work with IPPool resources. +type IPPoolInterface interface { + Create(*calicov3.IPPool) (*calicov3.IPPool, error) + Update(*calicov3.IPPool) (*calicov3.IPPool, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*calicov3.IPPool, error) + List(opts v1.ListOptions) (*calicov3.IPPoolList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *calicov3.IPPool, err error) + IPPoolExpansion +} + +// iPPools implements IPPoolInterface +type iPPools struct { + client rest.Interface +} + +// newIPPools returns a IPPools +func newIPPools(c *CrdCalicov3Client) *iPPools { + return &iPPools{ + client: c.RESTClient(), + } +} + +// Get takes name of the iPPool, and returns the corresponding iPPool object, and an error if there is any. +func (c *iPPools) Get(name string, options v1.GetOptions) (result *calicov3.IPPool, err error) { + result = &calicov3.IPPool{} + err = c.client.Get(). + Resource("ippools"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of IPPools that match those selectors. +func (c *iPPools) List(opts v1.ListOptions) (result *calicov3.IPPoolList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &calicov3.IPPoolList{} + err = c.client.Get(). + Resource("ippools"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested iPPools. +func (c *iPPools) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("ippools"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a iPPool and creates it. Returns the server's representation of the iPPool, and an error, if there is any. +func (c *iPPools) Create(iPPool *calicov3.IPPool) (result *calicov3.IPPool, err error) { + result = &calicov3.IPPool{} + err = c.client.Post(). + Resource("ippools"). + Body(iPPool). + Do(). + Into(result) + return +} + +// Update takes the representation of a iPPool and updates it. Returns the server's representation of the iPPool, and an error, if there is any. +func (c *iPPools) Update(iPPool *calicov3.IPPool) (result *calicov3.IPPool, err error) { + result = &calicov3.IPPool{} + err = c.client.Put(). + Resource("ippools"). + Name(iPPool.Name). + Body(iPPool). + Do(). + Into(result) + return +} + +// Delete takes name of the iPPool and deletes it. Returns an error if one occurs. +func (c *iPPools) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Resource("ippools"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *iPPools) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("ippools"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched iPPool. +func (c *iPPools) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *calicov3.IPPool, err error) { + result = &calicov3.IPPool{} + err = c.client.Patch(pt). + Resource("ippools"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/network_client.go b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/network_client.go new file mode 100644 index 000000000..d9c1dfbaa --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/clientset/versioned/typed/network/calicov3/network_client.go @@ -0,0 +1,99 @@ +/* +Copyright 2020 The KubeSphere 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 client-gen. DO NOT EDIT. + +package calicov3 + +import ( + rest "k8s.io/client-go/rest" + calicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" + "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned/scheme" +) + +type CrdCalicov3Interface interface { + RESTClient() rest.Interface + BlockAffinitiesGetter + IPAMBlocksGetter + IPPoolsGetter +} + +// CrdCalicov3Client is used to interact with features provided by the crd.projectcalico.org group. +type CrdCalicov3Client struct { + restClient rest.Interface +} + +func (c *CrdCalicov3Client) BlockAffinities() BlockAffinityInterface { + return newBlockAffinities(c) +} + +func (c *CrdCalicov3Client) IPAMBlocks() IPAMBlockInterface { + return newIPAMBlocks(c) +} + +func (c *CrdCalicov3Client) IPPools() IPPoolInterface { + return newIPPools(c) +} + +// NewForConfig creates a new CrdCalicov3Client for the given config. +func NewForConfig(c *rest.Config) (*CrdCalicov3Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &CrdCalicov3Client{client}, nil +} + +// NewForConfigOrDie creates a new CrdCalicov3Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *CrdCalicov3Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new CrdCalicov3Client for the given RESTClient. +func New(c rest.Interface) *CrdCalicov3Client { + return &CrdCalicov3Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := calicov3.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *CrdCalicov3Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/simple/client/network/ippool/calico/client/informers/externalversions/factory.go b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/factory.go new file mode 100644 index 000000000..03bcb6f00 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/factory.go @@ -0,0 +1,180 @@ +/* +Copyright 2020 The KubeSphere 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 informer-gen. DO NOT EDIT. + +package externalversions + +import ( + reflect "reflect" + sync "sync" + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" + versioned "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/informers/externalversions/internalinterfaces" + network "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +// Start initializes all requested informers. +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + go informer.Run(stopCh) + f.startedInformers[informerType] = true + } + } +} + +// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InternalInformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + f.informers[informerType] = informer + + return informer +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + Crd() network.Interface +} + +func (f *sharedInformerFactory) Crd() network.Interface { + return network.New(f, f.namespace, f.tweakListOptions) +} diff --git a/pkg/simple/client/network/ippool/calico/client/informers/externalversions/generic.go b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/generic.go new file mode 100644 index 000000000..7844ec52f --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/generic.go @@ -0,0 +1,66 @@ +/* +Copyright 2020 The KubeSphere 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 informer-gen. DO NOT EDIT. + +package externalversions + +import ( + "fmt" + + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" + calicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=crd.projectcalico.org, Version=calicov3 + case calicov3.SchemeGroupVersion.WithResource("blockaffinities"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Crd().Calicov3().BlockAffinities().Informer()}, nil + case calicov3.SchemeGroupVersion.WithResource("ipamblocks"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Crd().Calicov3().IPAMBlocks().Informer()}, nil + case calicov3.SchemeGroupVersion.WithResource("ippools"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Crd().Calicov3().IPPools().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/pkg/simple/client/network/ippool/calico/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/internalinterfaces/factory_interfaces.go new file mode 100644 index 000000000..d781a4567 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -0,0 +1,40 @@ +/* +Copyright 2020 The KubeSphere 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 informer-gen. DO NOT EDIT. + +package internalinterfaces + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + cache "k8s.io/client-go/tools/cache" + versioned "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned" +) + +// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. +type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer + +// SharedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer +} + +// TweakListOptionsFunc is a function that transforms a v1.ListOptions. +type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3/blockaffinity.go b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3/blockaffinity.go new file mode 100644 index 000000000..4a8d7af5b --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3/blockaffinity.go @@ -0,0 +1,88 @@ +/* +Copyright 2020 The KubeSphere 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 informer-gen. DO NOT EDIT. + +package calicov3 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + networkcalicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" + versioned "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/informers/externalversions/internalinterfaces" + calicov3 "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3" +) + +// BlockAffinityInformer provides access to a shared informer and lister for +// BlockAffinities. +type BlockAffinityInformer interface { + Informer() cache.SharedIndexInformer + Lister() calicov3.BlockAffinityLister +} + +type blockAffinityInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewBlockAffinityInformer constructs a new informer for BlockAffinity type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewBlockAffinityInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredBlockAffinityInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredBlockAffinityInformer constructs a new informer for BlockAffinity type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredBlockAffinityInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CrdCalicov3().BlockAffinities().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CrdCalicov3().BlockAffinities().Watch(options) + }, + }, + &networkcalicov3.BlockAffinity{}, + resyncPeriod, + indexers, + ) +} + +func (f *blockAffinityInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredBlockAffinityInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *blockAffinityInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&networkcalicov3.BlockAffinity{}, f.defaultInformer) +} + +func (f *blockAffinityInformer) Lister() calicov3.BlockAffinityLister { + return calicov3.NewBlockAffinityLister(f.Informer().GetIndexer()) +} diff --git a/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3/interface.go b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3/interface.go new file mode 100644 index 000000000..da5dac4f1 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3/interface.go @@ -0,0 +1,59 @@ +/* +Copyright 2020 The KubeSphere 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 informer-gen. DO NOT EDIT. + +package calicov3 + +import ( + internalinterfaces "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // BlockAffinities returns a BlockAffinityInformer. + BlockAffinities() BlockAffinityInformer + // IPAMBlocks returns a IPAMBlockInformer. + IPAMBlocks() IPAMBlockInformer + // IPPools returns a IPPoolInformer. + IPPools() IPPoolInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// BlockAffinities returns a BlockAffinityInformer. +func (v *version) BlockAffinities() BlockAffinityInformer { + return &blockAffinityInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// IPAMBlocks returns a IPAMBlockInformer. +func (v *version) IPAMBlocks() IPAMBlockInformer { + return &iPAMBlockInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// IPPools returns a IPPoolInformer. +func (v *version) IPPools() IPPoolInformer { + return &iPPoolInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3/ipamblock.go b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3/ipamblock.go new file mode 100644 index 000000000..d59fbe0a9 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3/ipamblock.go @@ -0,0 +1,88 @@ +/* +Copyright 2020 The KubeSphere 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 informer-gen. DO NOT EDIT. + +package calicov3 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + networkcalicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" + versioned "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/informers/externalversions/internalinterfaces" + calicov3 "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3" +) + +// IPAMBlockInformer provides access to a shared informer and lister for +// IPAMBlocks. +type IPAMBlockInformer interface { + Informer() cache.SharedIndexInformer + Lister() calicov3.IPAMBlockLister +} + +type iPAMBlockInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewIPAMBlockInformer constructs a new informer for IPAMBlock type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewIPAMBlockInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredIPAMBlockInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredIPAMBlockInformer constructs a new informer for IPAMBlock type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredIPAMBlockInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CrdCalicov3().IPAMBlocks().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CrdCalicov3().IPAMBlocks().Watch(options) + }, + }, + &networkcalicov3.IPAMBlock{}, + resyncPeriod, + indexers, + ) +} + +func (f *iPAMBlockInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredIPAMBlockInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *iPAMBlockInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&networkcalicov3.IPAMBlock{}, f.defaultInformer) +} + +func (f *iPAMBlockInformer) Lister() calicov3.IPAMBlockLister { + return calicov3.NewIPAMBlockLister(f.Informer().GetIndexer()) +} diff --git a/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3/ippool.go b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3/ippool.go new file mode 100644 index 000000000..b3fdf8109 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3/ippool.go @@ -0,0 +1,88 @@ +/* +Copyright 2020 The KubeSphere 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 informer-gen. DO NOT EDIT. + +package calicov3 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + networkcalicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" + versioned "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/informers/externalversions/internalinterfaces" + calicov3 "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3" +) + +// IPPoolInformer provides access to a shared informer and lister for +// IPPools. +type IPPoolInformer interface { + Informer() cache.SharedIndexInformer + Lister() calicov3.IPPoolLister +} + +type iPPoolInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewIPPoolInformer constructs a new informer for IPPool type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewIPPoolInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredIPPoolInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredIPPoolInformer constructs a new informer for IPPool type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredIPPoolInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CrdCalicov3().IPPools().List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CrdCalicov3().IPPools().Watch(options) + }, + }, + &networkcalicov3.IPPool{}, + resyncPeriod, + indexers, + ) +} + +func (f *iPPoolInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredIPPoolInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *iPPoolInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&networkcalicov3.IPPool{}, f.defaultInformer) +} + +func (f *iPPoolInformer) Lister() calicov3.IPPoolLister { + return calicov3.NewIPPoolLister(f.Informer().GetIndexer()) +} diff --git a/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/interface.go b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/interface.go new file mode 100644 index 000000000..978ac970c --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/interface.go @@ -0,0 +1,46 @@ +/* +Copyright 2020 The KubeSphere 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 informer-gen. DO NOT EDIT. + +package network + +import ( + internalinterfaces "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/informers/externalversions/internalinterfaces" + calicov3 "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/informers/externalversions/network/calicov3" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // Calicov3 provides access to shared informers for resources in Calicov3. + Calicov3() calicov3.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// Calicov3 returns a new calicov3.Interface. +func (g *group) Calicov3() calicov3.Interface { + return calicov3.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3/blockaffinity.go b/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3/blockaffinity.go new file mode 100644 index 000000000..d90977828 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3/blockaffinity.go @@ -0,0 +1,65 @@ +/* +Copyright 2020 The KubeSphere 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 lister-gen. DO NOT EDIT. + +package calicov3 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + calicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" +) + +// BlockAffinityLister helps list BlockAffinities. +type BlockAffinityLister interface { + // List lists all BlockAffinities in the indexer. + List(selector labels.Selector) (ret []*calicov3.BlockAffinity, err error) + // Get retrieves the BlockAffinity from the index for a given name. + Get(name string) (*calicov3.BlockAffinity, error) + BlockAffinityListerExpansion +} + +// blockAffinityLister implements the BlockAffinityLister interface. +type blockAffinityLister struct { + indexer cache.Indexer +} + +// NewBlockAffinityLister returns a new BlockAffinityLister. +func NewBlockAffinityLister(indexer cache.Indexer) BlockAffinityLister { + return &blockAffinityLister{indexer: indexer} +} + +// List lists all BlockAffinities in the indexer. +func (s *blockAffinityLister) List(selector labels.Selector) (ret []*calicov3.BlockAffinity, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*calicov3.BlockAffinity)) + }) + return ret, err +} + +// Get retrieves the BlockAffinity from the index for a given name. +func (s *blockAffinityLister) Get(name string) (*calicov3.BlockAffinity, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(calicov3.Resource("blockaffinity"), name) + } + return obj.(*calicov3.BlockAffinity), nil +} diff --git a/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3/expansion_generated.go b/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3/expansion_generated.go new file mode 100644 index 000000000..51a72a6a8 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3/expansion_generated.go @@ -0,0 +1,31 @@ +/* +Copyright 2020 The KubeSphere 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 lister-gen. DO NOT EDIT. + +package calicov3 + +// BlockAffinityListerExpansion allows custom methods to be added to +// BlockAffinityLister. +type BlockAffinityListerExpansion interface{} + +// IPAMBlockListerExpansion allows custom methods to be added to +// IPAMBlockLister. +type IPAMBlockListerExpansion interface{} + +// IPPoolListerExpansion allows custom methods to be added to +// IPPoolLister. +type IPPoolListerExpansion interface{} diff --git a/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3/ipamblock.go b/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3/ipamblock.go new file mode 100644 index 000000000..9caccfc91 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3/ipamblock.go @@ -0,0 +1,65 @@ +/* +Copyright 2020 The KubeSphere 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 lister-gen. DO NOT EDIT. + +package calicov3 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + calicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" +) + +// IPAMBlockLister helps list IPAMBlocks. +type IPAMBlockLister interface { + // List lists all IPAMBlocks in the indexer. + List(selector labels.Selector) (ret []*calicov3.IPAMBlock, err error) + // Get retrieves the IPAMBlock from the index for a given name. + Get(name string) (*calicov3.IPAMBlock, error) + IPAMBlockListerExpansion +} + +// iPAMBlockLister implements the IPAMBlockLister interface. +type iPAMBlockLister struct { + indexer cache.Indexer +} + +// NewIPAMBlockLister returns a new IPAMBlockLister. +func NewIPAMBlockLister(indexer cache.Indexer) IPAMBlockLister { + return &iPAMBlockLister{indexer: indexer} +} + +// List lists all IPAMBlocks in the indexer. +func (s *iPAMBlockLister) List(selector labels.Selector) (ret []*calicov3.IPAMBlock, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*calicov3.IPAMBlock)) + }) + return ret, err +} + +// Get retrieves the IPAMBlock from the index for a given name. +func (s *iPAMBlockLister) Get(name string) (*calicov3.IPAMBlock, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(calicov3.Resource("ipamblock"), name) + } + return obj.(*calicov3.IPAMBlock), nil +} diff --git a/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3/ippool.go b/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3/ippool.go new file mode 100644 index 000000000..1509f6cad --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/client/listers/network/calicov3/ippool.go @@ -0,0 +1,65 @@ +/* +Copyright 2020 The KubeSphere 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 lister-gen. DO NOT EDIT. + +package calicov3 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + calicov3 "kubesphere.io/kubesphere/pkg/apis/network/calicov3" +) + +// IPPoolLister helps list IPPools. +type IPPoolLister interface { + // List lists all IPPools in the indexer. + List(selector labels.Selector) (ret []*calicov3.IPPool, err error) + // Get retrieves the IPPool from the index for a given name. + Get(name string) (*calicov3.IPPool, error) + IPPoolListerExpansion +} + +// iPPoolLister implements the IPPoolLister interface. +type iPPoolLister struct { + indexer cache.Indexer +} + +// NewIPPoolLister returns a new IPPoolLister. +func NewIPPoolLister(indexer cache.Indexer) IPPoolLister { + return &iPPoolLister{indexer: indexer} +} + +// List lists all IPPools in the indexer. +func (s *iPPoolLister) List(selector labels.Selector) (ret []*calicov3.IPPool, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*calicov3.IPPool)) + }) + return ret, err +} + +// Get retrieves the IPPool from the index for a given name. +func (s *iPPoolLister) Get(name string) (*calicov3.IPPool, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(calicov3.Resource("ippool"), name) + } + return obj.(*calicov3.IPPool), nil +} diff --git a/pkg/simple/client/network/ippool/calico/options.go b/pkg/simple/client/network/ippool/calico/options.go new file mode 100644 index 000000000..60e6f08b1 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/options.go @@ -0,0 +1,23 @@ +/* +Copyright 2020 The KubeSphere 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 calico + +type Options struct { + IPIPMode string `json:"ipipMode,omityempty" yaml:"ipipMode,omityempty"` + VXLANMode string `json:"vxlanMode,omityempty" yaml:"vxlanMode,omityempty"` + NATOutgoing bool `json:"natOutgoing,omitempty" yaml:"natOutgoing,omityempty"` +} diff --git a/pkg/simple/client/network/ippool/calico/provider.go b/pkg/simple/client/network/ippool/calico/provider.go new file mode 100644 index 000000000..38d5dfc73 --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/provider.go @@ -0,0 +1,415 @@ +/* +Copyright 2020 KubeSphere 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 calico + +import ( + "errors" + "fmt" + + v3 "github.com/projectcalico/libcalico-go/lib/apis/v3" + "github.com/projectcalico/libcalico-go/lib/backend/model" + cnet "github.com/projectcalico/libcalico-go/lib/net" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog" + "kubesphere.io/kubesphere/pkg/apis/network/calicov3" + "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + kubesphereclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" + "kubesphere.io/kubesphere/pkg/simple/client/k8s" + calicoset "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +const ( + CalicoNamespaceAnnotationIPPoolV4 = "cni.projectcalico.org/ipv4pools" + CalicoNamespaceAnnotationIPPoolV6 = "cni.projectcalico.org/ipv6pools" + CalicoPodAnnotationIPAddr = "cni.projectcalico.org/ipAddrs" +) + +var ( + ErrBlockInuse = errors.New("ipamblock in using") +) + +type provider struct { + client calicoset.Interface + ksclient kubesphereclient.Interface + options Options +} + +func (c provider) CreateIPPool(pool *v1alpha1.IPPool) error { + calicoPool := &calicov3.IPPool{ + TypeMeta: v1.TypeMeta{}, + ObjectMeta: v1.ObjectMeta{ + Name: pool.Name, + }, + Spec: v3.IPPoolSpec{ + CIDR: pool.Spec.CIDR, + Disabled: pool.Spec.Disabled, + NodeSelector: "all()", + VXLANMode: v3.VXLANMode(c.options.VXLANMode), + IPIPMode: v3.IPIPMode(c.options.IPIPMode), + NATOutgoing: c.options.NATOutgoing, + }, + } + + err := controllerutil.SetControllerReference(pool, calicoPool, scheme.Scheme) + if err != nil { + klog.Warningf("cannot set reference for calico ippool %s, err=%v", pool.Name, err) + } + + _, err = c.client.CrdCalicov3().IPPools().Create(calicoPool) + if k8serrors.IsAlreadyExists(err) { + return nil + } + + return err +} + +func (c provider) UpdateIPPool(pool *v1alpha1.IPPool) error { + return nil +} + +func (c provider) GetIPPoolStats(pool *v1alpha1.IPPool) (*v1alpha1.IPPool, error) { + stats := &v1alpha1.IPPool{} + + calicoPool, err := c.client.CrdCalicov3().IPPools().Get(pool.Name, v1.GetOptions{}) + if err != nil { + return nil, err + } + + blocks, err := c.listBlocks(calicoPool) + if err != nil { + return nil, err + } + + stats.Status.Capacity = pool.NumAddresses() + stats.Status.Reserved = 0 + stats.Status.Unallocated = 0 + stats.Status.Synced = true + stats.Status.Allocations = 0 + + if len(blocks) <= 0 { + stats.Status.Unallocated = pool.NumAddresses() + stats.Status.Allocations = 0 + return stats, nil + } + + for _, block := range blocks { + stats.Status.Allocations += block.NumAddresses() - block.NumFreeAddresses() - block.NumReservedAddresses() + stats.Status.Reserved += block.NumReservedAddresses() + } + + stats.Status.Unallocated = stats.Status.Capacity - stats.Status.Allocations - stats.Status.Reserved + + return stats, nil +} + +func setBlockAffiDeletion(c calicoset.Interface, blockAffi *calicov3.BlockAffinity) error { + if blockAffi.Spec.State == string(model.StatePendingDeletion) { + return nil + } + + blockAffi.Spec.State = string(model.StatePendingDeletion) + _, err := c.CrdCalicov3().BlockAffinities().Update(blockAffi) + return err +} + +func deleteBlockAffi(c calicoset.Interface, blockAffi *calicov3.BlockAffinity) error { + trueStr := fmt.Sprintf("%t", true) + if blockAffi.Spec.Deleted != trueStr { + blockAffi.Spec.Deleted = trueStr + _, err := c.CrdCalicov3().BlockAffinities().Update(blockAffi) + if err != nil { + return err + } + } + + err := c.CrdCalicov3().BlockAffinities().Delete(blockAffi.Name, &v1.DeleteOptions{}) + if err != nil { + return err + } + + return nil +} + +func (c provider) doBlockAffis(pool *calicov3.IPPool, do func(calicoset.Interface, *calicov3.BlockAffinity) error) error { + _, cidrNet, _ := cnet.ParseCIDR(pool.Spec.CIDR) + + blockAffis, err := c.client.CrdCalicov3().BlockAffinities().List(v1.ListOptions{}) + if err != nil { + return err + } + + for _, blockAffi := range blockAffis.Items { + _, blockCIDR, _ := cnet.ParseCIDR(blockAffi.Spec.CIDR) + if !cidrNet.IsNetOverlap(blockCIDR.IPNet) { + continue + } + + err = do(c.client, &blockAffi) + if err != nil { + return err + } + } + + return nil +} + +func (c provider) listBlocks(pool *calicov3.IPPool) ([]calicov3.IPAMBlock, error) { + _, cidrNet, _ := cnet.ParseCIDR(pool.Spec.CIDR) + + blocks, err := c.client.CrdCalicov3().IPAMBlocks().List(v1.ListOptions{}) + if err != nil { + return nil, err + } + + var result []calicov3.IPAMBlock + for _, block := range blocks.Items { + _, blockCIDR, _ := cnet.ParseCIDR(block.Spec.CIDR) + if !cidrNet.IsNetOverlap(blockCIDR.IPNet) { + continue + } + result = append(result, block) + } + + return result, nil +} + +func (c provider) doBlocks(pool *calicov3.IPPool, do func(calicoset.Interface, *calicov3.IPAMBlock) error) error { + blocks, err := c.listBlocks(pool) + if err != nil { + return err + } + + for _, block := range blocks { + err = do(c.client, &block) + if err != nil { + return err + } + } + + return nil +} + +func deleteBlock(c calicoset.Interface, block *calicov3.IPAMBlock) error { + if block.Empty() { + if !block.Spec.Deleted { + block.Spec.Deleted = true + _, err := c.CrdCalicov3().IPAMBlocks().Update(block) + if err != nil { + return err + } + } + } else { + return ErrBlockInuse + } + err := c.CrdCalicov3().IPAMBlocks().Delete(block.Name, &v1.DeleteOptions{}) + if err != nil { + return err + } + + return nil +} + +func (c provider) DeleteIPPool(pool *v1alpha1.IPPool) (bool, error) { + // Deleting a pool requires a little care because of existing endpoints + // using IP addresses allocated in the pool. We do the deletion in + // the following steps: + // - disable the pool so no more IPs are assigned from it + // - remove all affinities associated with the pool + // - delete the pool + + // Get the pool so that we can find the CIDR associated with it. + calicoPool, err := c.client.CrdCalicov3().IPPools().Get(pool.Name, v1.GetOptions{}) + if err != nil { + return false, err + } + + // If the pool is active, set the disabled flag to ensure we stop allocating from this pool. + if !calicoPool.Spec.Disabled { + calicoPool.Spec.Disabled = true + + calicoPool, err = c.client.CrdCalicov3().IPPools().Update(calicoPool) + if err != nil { + return false, err + } + } + + //If the address pool is being used, we return, avoiding deletions that cause other problems. + stat, err := c.GetIPPoolStats(pool) + if err != nil { + return false, err + } + if stat.Status.Allocations > 0 { + return false, nil + } + + //set blockaffi to pendingdelete + err = c.doBlockAffis(calicoPool, setBlockAffiDeletion) + if err != nil { + return false, err + } + + //delete block + err = c.doBlocks(calicoPool, deleteBlock) + if err != nil { + if errors.Is(err, ErrBlockInuse) { + return false, nil + } + return false, err + } + + //delete blockaffi + err = c.doBlockAffis(calicoPool, deleteBlockAffi) + if err != nil { + return false, err + } + + //delete calico ippool + err = c.client.CrdCalicov3().IPPools().Delete(calicoPool.Name, &v1.DeleteOptions{}) + if err != nil { + return false, err + } + + //Congratulations, the ippool has been completely cleared. + return true, nil +} + +//Synchronizing address pools at boot time +func (c provider) syncIPPools() error { + calicoPools, err := c.client.CrdCalicov3().IPPools().List(v1.ListOptions{}) + if err != nil { + klog.V(4).Infof("syncIPPools: cannot list calico ippools, err=%v", err) + return err + } + + pools, err := c.ksclient.NetworkV1alpha1().IPPools().List(v1.ListOptions{}) + if err != nil { + klog.V(4).Infof("syncIPPools: cannot list kubesphere ippools, err=%v", err) + return err + } + + existPools := map[string]bool{} + for _, pool := range pools.Items { + existPools[pool.Name] = true + } + + for _, calicoPool := range calicoPools.Items { + if _, ok := existPools[calicoPool.Name]; !ok { + pool := &v1alpha1.IPPool{ + TypeMeta: v1.TypeMeta{}, + ObjectMeta: v1.ObjectMeta{ + Name: calicoPool.Name, + }, + Spec: v1alpha1.IPPoolSpec{ + Type: v1alpha1.Calico, + CIDR: calicoPool.Spec.CIDR, + Disabled: calicoPool.Spec.Disabled, + BlockSize: calicoPool.Spec.BlockSize, + }, + Status: v1alpha1.IPPoolStatus{}, + } + + _, err = c.ksclient.NetworkV1alpha1().IPPools().Create(pool) + if err != nil { + klog.V(4).Infof("syncIPPools: cannot create kubesphere ippools, err=%v", err) + return err + } + } + } + + return nil +} + +func (c provider) SyncStatus(stopCh <-chan struct{}, q workqueue.RateLimitingInterface) error { + blockWatch, err := c.client.CrdCalicov3().IPAMBlocks().Watch(v1.ListOptions{}) + if err != nil { + return err + } + + ch := blockWatch.ResultChan() + defer blockWatch.Stop() + + for { + select { + case <-stopCh: + return nil + case event, ok := <-ch: + if !ok { + // End of results. + return fmt.Errorf("calico ipamblock watch closed") + } + + if event.Type == watch.Added || event.Type == watch.Deleted || event.Type == watch.Modified { + block := event.Object.(*calicov3.IPAMBlock) + _, blockCIDR, _ := cnet.ParseCIDR(block.Spec.CIDR) + + if block.Labels[v1alpha1.IPPoolNameLabel] != "" { + q.Add(block.Labels[v1alpha1.IPPoolNameLabel]) + continue + } + + pools, err := c.ksclient.NetworkV1alpha1().IPPools().List(v1.ListOptions{}) + if err != nil { + continue + } + + for _, pool := range pools.Items { + _, poolCIDR, _ := cnet.ParseCIDR(pool.Spec.CIDR) + if poolCIDR.IsNetOverlap(blockCIDR.IPNet) { + q.Add(pool.Name) + + block.Labels = map[string]string{ + v1alpha1.IPPoolNameLabel: pool.Name, + } + c.client.CrdCalicov3().IPAMBlocks().Update(block) + break + } + } + } + } + } +} + +func NewProvider(ksclient kubesphereclient.Interface, options Options, k8sOptions *k8s.KubernetesOptions) provider { + config, err := clientcmd.BuildConfigFromFlags("", k8sOptions.KubeConfig) + if err != nil { + klog.Fatalf("failed to build k8s config , err=%v", err) + } + config.QPS = k8sOptions.QPS + config.Burst = k8sOptions.Burst + client, err := calicoset.NewForConfig(config) + if err != nil { + klog.Fatalf("failed to new calico client , err=%v", err) + } + + p := provider{ + client: client, + ksclient: ksclient, + options: options, + } + + if err := p.syncIPPools(); err != nil { + klog.Fatalf("failed to sync calico ippool to kubesphere ippool, err=%v", err) + } + + return p +} diff --git a/pkg/simple/client/network/ippool/calico/provider_test.go b/pkg/simple/client/network/ippool/calico/provider_test.go new file mode 100644 index 000000000..2ad8a664a --- /dev/null +++ b/pkg/simple/client/network/ippool/calico/provider_test.go @@ -0,0 +1,72 @@ +/* +Copyright 2020 The KubeSphere 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 calico + +import ( + "flag" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog" + "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + ksfake "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake" + calicofake "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico/client/clientset/versioned/fake" + "testing" +) + +func TestCalicoIPPoolSuit(t *testing.T) { + klog.InitFlags(nil) + flag.Set("logtostderr", "true") + flag.Set("v", "4") + flag.Parse() + klog.SetOutput(GinkgoWriter) + RegisterFailHandler(Fail) + RunSpecs(t, "Calico IPPool Suite") +} + +var _ = Describe("test calico ippool", func() { + pool := &v1alpha1.IPPool{ + TypeMeta: v1.TypeMeta{}, + ObjectMeta: v1.ObjectMeta{ + Name: "testippool", + }, + Spec: v1alpha1.IPPoolSpec{ + Type: v1alpha1.Calico, + CIDR: "192.168.0.0/16", + BlockSize: 24, + }, + Status: v1alpha1.IPPoolStatus{}, + } + + ksclient := ksfake.NewSimpleClientset(pool) + client := calicofake.NewSimpleClientset() + + p := provider{ + options: Options{ + IPIPMode: "Always", + VXLANMode: "Never", + NATOutgoing: true, + }, + client: client, + ksclient: ksclient, + } + + It("test create calico ippool", func() { + err := p.CreateIPPool(pool) + Expect(err).ShouldNot(HaveOccurred()) + }) +}) diff --git a/pkg/simple/client/network/ippool/ipam/interface.go b/pkg/simple/client/network/ippool/ipam/interface.go new file mode 100644 index 000000000..b584998c8 --- /dev/null +++ b/pkg/simple/client/network/ippool/ipam/interface.go @@ -0,0 +1,47 @@ +/* +Copyright 2020 KubeSphere 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 ipam + +import ( + "github.com/containernetworking/cni/pkg/types/current" + "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" +) + +// ipam.Interface has methods to perform IP address management. +type Interface interface { + // AutoAssign automatically assigns one or more IP addresses as specified by the + // provided AutoAssignArgs. AutoAssign returns the list of the assigned IPv4 addresses, + // and the list of the assigned IPv6 addresses in IPNet format. + // The returned IPNet represents the allocation block from which the IP was allocated, + // which is useful for dataplanes that need to know the subnet (such as Windows). + // + // In case of error, returns the IPs allocated so far along with the error. + AutoAssign(args AutoAssignArgs) (*current.Result, error) + + // ReleaseByHandle releases all IP addresses that have been assigned + // using the provided handle. Returns an error if no addresses + // are assigned with the given handle. + ReleaseByHandle(handleID string) error + + GetUtilization(args GetUtilizationArgs) ([]*PoolUtilization, error) +} + +// Interface used to access the enabled IPPools. +type PoolAccessorInterface interface { + // Returns a list of all pools sorted in alphanumeric name order. + getAllPools() ([]v1alpha1.IPPool, error) +} diff --git a/pkg/simple/client/network/ippool/ipam/ipam.go b/pkg/simple/client/network/ippool/ipam/ipam.go new file mode 100644 index 000000000..a90a206fc --- /dev/null +++ b/pkg/simple/client/network/ippool/ipam/ipam.go @@ -0,0 +1,626 @@ +/* +Copyright 2020 KubeSphere 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 ipam + +import ( + "errors" + "fmt" + "math/big" + "net" + + cnitypes "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/types/current" + "github.com/davecgh/go-spew/spew" + cnet "github.com/projectcalico/libcalico-go/lib/net" + "github.com/projectcalico/libcalico-go/lib/set" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/klog" + "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" + "kubesphere.io/kubesphere/pkg/simple/client/network/utils" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +const ( + // Number of retries when we have an error writing data to etcd. + datastoreRetries = 10 +) + +var ( + ErrNoQualifiedPool = errors.New("cannot find a qualified ippool") + ErrNoFreeBlocks = errors.New("no free blocks in ippool") + ErrMaxRetry = errors.New("Max retries hit - excessive concurrent IPAM requests") + ErrUnknowIPPoolType = errors.New("unknow ippool type") +) + +func (c IPAMClient) getAllPools() ([]v1alpha1.IPPool, error) { + pools, err := c.client.NetworkV1alpha1().IPPools().List(metav1.ListOptions{ + LabelSelector: labels.SelectorFromSet(labels.Set{ + v1alpha1.IPPoolTypeLabel: c.typeStr, + }).String(), + }) + + if err != nil { + return nil, err + } + + return pools.Items, nil +} + +// NewIPAMClient returns a new IPAMClient, which implements Interface. +func NewIPAMClient(client kubesphere.Interface, typeStr string) IPAMClient { + return IPAMClient{ + typeStr: typeStr, + client: client, + } +} + +// IPAMClient implements Interface +type IPAMClient struct { + typeStr string + client kubesphere.Interface +} + +// AutoAssign automatically assigns one or more IP addresses as specified by the +// provided AutoAssignArgs. AutoAssign returns the list of the assigned IPv4 addresses, +// and the list of the assigned IPv6 addresses. +// +// In case of error, returns the IPs allocated so far along with the error. +func (c IPAMClient) AutoAssign(args AutoAssignArgs) (*current.Result, error) { + var ( + result current.Result + err error + ip *cnet.IPNet + pool *v1alpha1.IPPool + ) + + for i := 0; i < datastoreRetries; i++ { + pool, err = c.client.NetworkV1alpha1().IPPools().Get(args.Pool, metav1.GetOptions{}) + if err != nil { + return nil, ErrNoQualifiedPool + } + + if pool.Disabled() { + klog.Infof("provided ippool %s should be enabled", pool.Name) + return nil, ErrNoQualifiedPool + } + + if pool.TypeInvalid() { + return nil, ErrUnknowIPPoolType + } + + ip, err = c.autoAssign(args.HandleID, args.Attrs, pool) + if err != nil { + if errors.Is(err, ErrNoFreeBlocks) { + return nil, err + } + continue + } + break + } + + if err != nil { + klog.Infof("AutoAssign: args=%s, err=%v", spew.Sdump(args), err) + return nil, ErrMaxRetry + } + + version := 4 + if ip.IP.To4() == nil { + version = 6 + } + + result.IPs = append(result.IPs, ¤t.IPConfig{ + Version: fmt.Sprintf("%d", version), + Address: net.IPNet{IP: ip.IP, Mask: ip.Mask}, + Gateway: net.ParseIP(pool.Spec.Gateway), + }) + + for _, route := range pool.Spec.Routes { + _, dst, _ := net.ParseCIDR(route.Dst) + result.Routes = append(result.Routes, &cnitypes.Route{ + Dst: *dst, + GW: net.ParseIP(route.GW), + }) + } + result.DNS.Domain = pool.Spec.DNS.Domain + result.DNS.Options = pool.Spec.DNS.Options + result.DNS.Nameservers = pool.Spec.DNS.Nameservers + result.DNS.Search = pool.Spec.DNS.Search + + poolType := pool.Spec.Type + switch poolType { + case v1alpha1.VLAN: + result.Interfaces = append(result.Interfaces, ¤t.Interface{ + Mac: utils.EthRandomAddr(ip.IP), + }) + } + + return &result, nil +} + +//findOrClaimBlock find an address block with free space, and if it doesn't exist, create it. +func (c IPAMClient) findOrClaimBlock(pool *v1alpha1.IPPool, minFreeIps int) (*v1alpha1.IPAMBlock, error) { + remainingBlocks, err := c.ListBlocks(pool.Name) + if err != nil { + return nil, err + } + + // First, we try to find a block from one of the existing blocks. + for len(remainingBlocks) > 0 { + // Pop first cidr. + block := remainingBlocks[0] + remainingBlocks = remainingBlocks[1:] + + // Pull out the block. + if block.NumFreeAddresses() >= minFreeIps { + return &block, nil + } else { + continue + } + } + + //Second, create unused Address Blocks + b, err := c.findUnclaimedBlock(pool) + if err != nil { + return nil, err + } + controllerutil.SetControllerReference(pool, b, scheme.Scheme) + b, err = c.client.NetworkV1alpha1().IPAMBlocks().Create(b) + if err != nil { + if k8serrors.IsAlreadyExists(err) { + b, err = c.queryBlock(b.BlockName()) + } + if err != nil { + return nil, err + } + } + + if b.NumFreeAddresses() >= minFreeIps { + return b, nil + } else { + errString := fmt.Sprintf("Block '%s' has %d free ips which is less than %d ips required.", b.BlockName(), b.NumFreeAddresses(), minFreeIps) + return nil, errors.New(errString) + } +} + +func (c IPAMClient) autoAssign(handleID string, attrs map[string]string, requestedPool *v1alpha1.IPPool) (*cnet.IPNet, error) { + var ( + result *cnet.IPNet + ) + + b, err := c.findOrClaimBlock(requestedPool, 1) + if err != nil { + return result, err + } + + for i := 0; i < datastoreRetries; i++ { + result, err = c.assignFromExistingBlock(b, handleID, attrs) + if err != nil { + if k8serrors.IsConflict(err) { + b, err = c.queryBlock(b.Name) + if err != nil { + return nil, err + } + + // Block b is in sync with datastore. Retry assigning IP. + continue + } + return nil, err + } + return result, nil + } + + return nil, ErrMaxRetry +} + +func (c IPAMClient) assignFromExistingBlock(block *v1alpha1.IPAMBlock, handleID string, attrs map[string]string) (*cnet.IPNet, error) { + ips := block.AutoAssign(1, handleID, attrs) + if len(ips) == 0 { + return nil, fmt.Errorf("block %s has no availabe IP", block.BlockName()) + } + + err := c.incrementHandle(handleID, block, 1) + if err != nil { + return nil, err + } + + _, err = c.client.NetworkV1alpha1().IPAMBlocks().Update(block) + if err != nil { + if err := c.decrementHandle(handleID, block, 1); err != nil { + klog.Errorf("Failed to decrement handle %s", handleID) + } + return nil, err + } + + return &ips[0], nil +} + +// ReleaseByHandle releases all IP addresses that have been assigned +// using the provided handle. +func (c IPAMClient) ReleaseByHandle(handleID string) error { + handle, err := c.queryHandle(handleID) + if err != nil { + if k8serrors.IsNotFound(err) { + return nil + } + return err + } + + for blockStr, _ := range handle.Spec.Block { + blockName := v1alpha1.ConvertToBlockName(blockStr) + if err := c.releaseByHandle(handleID, blockName); err != nil { + return err + } + } + return nil +} + +func (c IPAMClient) releaseByHandle(handleID string, blockName string) error { + for i := 0; i < datastoreRetries; i++ { + block, err := c.queryBlock(blockName) + if err != nil { + if k8serrors.IsNotFound(err) { + // Block doesn't exist, so all addresses are already + // unallocated. This can happen when a handle is + // overestimating the number of assigned addresses. + return nil + } else { + return err + } + } + + num := block.ReleaseByHandle(handleID) + if num == 0 { + // Block has no addresses with this handle, so + // all addresses are already unallocated. + return nil + } + + if block.Empty() { + if err = c.DeleteBlock(block); err != nil { + if k8serrors.IsConflict(err) { + // Update conflict - retry. + continue + } else if !k8serrors.IsNotFound(err) { + return err + } + } + } else { + // Compare and swap the AllocationBlock using the original + // KVPair read from before. No need to update the Value since we + // have been directly manipulating the value referenced by the KVPair. + _, err = c.client.NetworkV1alpha1().IPAMBlocks().Update(block) + if err != nil { + if k8serrors.IsConflict(err) { + // Comparison failed - retry. + continue + } else { + // Something else - return the error. + return err + } + } + } + + if err = c.decrementHandle(handleID, block, num); err != nil { + klog.Errorf("Failed to decrement handle %s, err=%s", handleID, err) + } + + return nil + } + return ErrMaxRetry +} + +func (c IPAMClient) incrementHandle(handleID string, block *v1alpha1.IPAMBlock, num int) error { + for i := 0; i < datastoreRetries; i++ { + create := false + handle, err := c.queryHandle(handleID) + if err != nil { + if k8serrors.IsNotFound(err) { + // Handle doesn't exist - create it. + handle = &v1alpha1.IPAMHandle{ + ObjectMeta: v1.ObjectMeta{ + Name: handleID, + }, + Spec: v1alpha1.IPAMHandleSpec{ + HandleID: handleID, + Block: map[string]int{}, + }, + } + create = true + } else { + // Unexpected error reading handle. + return err + } + } + + // Increment the handle for this block. + handle.IncrementBlock(block, num) + + if create { + _, err = c.client.NetworkV1alpha1().IPAMHandles().Create(handle) + } else { + _, err = c.client.NetworkV1alpha1().IPAMHandles().Update(handle) + } + if err != nil { + if k8serrors.IsAlreadyExists(err) || k8serrors.IsConflict(err) { + continue + } + return err + } + + return nil + } + + return ErrMaxRetry +} + +func (c IPAMClient) decrementHandle(handleID string, block *v1alpha1.IPAMBlock, num int) error { + for i := 0; i < datastoreRetries; i++ { + handle, err := c.queryHandle(handleID) + if err != nil { + return err + } + + _, err = handle.DecrementBlock(block, num) + if err != nil { + klog.Errorf("decrementHandle: %v", err) + return err + } + + // Update / Delete as appropriate. Since we have been manipulating the + // data in the KVPair, just pass this straight back to the client. + if handle.Empty() { + if err = c.deleteHandle(handle); err != nil { + if k8serrors.IsConflict(err) { + // Update conflict - retry. + continue + } else if !k8serrors.IsNotFound(err) { + return err + } + } + } else { + if _, err = c.client.NetworkV1alpha1().IPAMHandles().Update(handle); err != nil { + if k8serrors.IsConflict(err) { + // Update conflict - retry. + continue + } + return err + } + } + + return nil + } + + return ErrMaxRetry +} + +// GetUtilization returns IP utilization info for the specified pools, or for all pools. +func (c IPAMClient) GetUtilization(args GetUtilizationArgs) ([]*PoolUtilization, error) { + var usage []*PoolUtilization + + // Read all pools. + allPools, err := c.getAllPools() + if err != nil { + return nil, err + } + + // Identify the ones we want and create a PoolUtilization for each of those. + wantAllPools := len(args.Pools) == 0 + wantedPools := set.FromArray(args.Pools) + for _, pool := range allPools { + if wantAllPools || wantedPools.Contains(pool.Name) { + cap := pool.NumAddresses() + reserved := pool.NumReservedAddresses() + usage = append(usage, &PoolUtilization{ + Name: pool.Name, + Capacity: cap, + Reserved: reserved, + Allocate: 0, + Unallocated: cap - reserved, + }) + } + } + + // Find which pool this block belongs to. + for _, poolUse := range usage { + blocks, err := c.ListBlocks(poolUse.Name) + if err != nil { + return nil, err + } + + if len(blocks) <= 0 { + continue + } else { + poolUse.Reserved = 0 + poolUse.Allocate = 0 + } + + for _, block := range blocks { + poolUse.Allocate += block.NumAddresses() - block.NumFreeAddresses() - block.NumReservedAddresses() + poolUse.Reserved += block.NumReservedAddresses() + } + + poolUse.Unallocated = poolUse.Capacity - poolUse.Allocate - poolUse.Reserved + } + + return usage, nil +} + +// findUnclaimedBlock finds a block cidr which does not yet exist within the given list of pools. The provided pools +// should already be sanitized and only include existing, enabled pools. Note that the block may become claimed +// between receiving the cidr from this function and attempting to claim the corresponding block as this function +// does not reserve the returned IPNet. +func (c IPAMClient) findUnclaimedBlock(pool *v1alpha1.IPPool) (*v1alpha1.IPAMBlock, error) { + var result *v1alpha1.IPAMBlock + + // List blocks up front to reduce number of queries. + // We will try to write the block later to prevent races. + existingBlocks, err := c.ListBlocks(pool.Name) + if err != nil { + return nil, err + } + + /// Build a map for faster lookups. + exists := map[string]bool{} + for _, e := range existingBlocks { + exists[fmt.Sprintf("%s", e.Spec.CIDR)] = true + } + + // Iterate through pools to find a new block. + _, cidr, _ := cnet.ParseCIDR(pool.Spec.CIDR) + poolType := pool.Spec.Type + switch poolType { + case v1alpha1.VLAN: + if _, ok := exists[cidr.String()]; !ok { + var reservedAttr *v1alpha1.ReservedAttr + if pool.Spec.RangeStart != "" && pool.Spec.RangeEnd != "" { + reservedAttr = &v1alpha1.ReservedAttr{ + StartOfBlock: pool.StartReservedAddressed(), + EndOfBlock: pool.EndReservedAddressed(), + Handle: v1alpha1.ReservedHandle, + Note: v1alpha1.ReservedNote, + } + } + result = v1alpha1.NewBlock(pool, *cidr, reservedAttr) + } + default: + blocks := blockGenerator(pool) + for subnet := blocks(); subnet != nil; subnet = blocks() { + // Check if a block already exists for this subnet. + if _, ok := exists[fmt.Sprintf("%s", subnet.String())]; !ok { + result = v1alpha1.NewBlock(pool, *subnet, nil) + break + } + } + } + + if result != nil { + return result, nil + } else { + return nil, ErrNoFreeBlocks + } +} + +func (c IPAMClient) ListBlocks(pool string) ([]v1alpha1.IPAMBlock, error) { + blocks, err := c.client.NetworkV1alpha1().IPAMBlocks().List(metav1.ListOptions{ + LabelSelector: labels.SelectorFromSet(labels.Set{ + v1alpha1.IPPoolNameLabel: pool, + }).String(), + }) + if err != nil { + return nil, err + } + + return blocks.Items, nil +} + +// DeleteBlock deletes the given block. +func (c IPAMClient) DeleteBlock(b *v1alpha1.IPAMBlock) error { + if !b.IsDeleted() { + b.MarkDeleted() + _, err := c.client.NetworkV1alpha1().IPAMBlocks().Update(b) + if err != nil { + return err + } + } + return c.client.NetworkV1alpha1().IPAMBlocks().Delete(b.Name, nil) +} + +func (c IPAMClient) queryBlock(blockName string) (*v1alpha1.IPAMBlock, error) { + block, err := c.client.NetworkV1alpha1().IPAMBlocks().Get(blockName, metav1.GetOptions{}) + if err != nil { + return nil, err + } + + if block.IsDeleted() { + err := c.DeleteBlock(block) + if err != nil { + return nil, err + } + + return nil, k8serrors.NewNotFound(v1alpha1.Resource(v1alpha1.ResourcePluralIPAMBlock), blockName) + } + + return block, nil +} + +// queryHandle gets a handle for the given handleID key. +func (c IPAMClient) queryHandle(handleID string) (*v1alpha1.IPAMHandle, error) { + handle, err := c.client.NetworkV1alpha1().IPAMHandles().Get(handleID, metav1.GetOptions{}) + if err != nil { + return nil, err + } + + if handle.IsDeleted() { + err := c.deleteHandle(handle) + if err != nil { + return nil, err + } + + return nil, k8serrors.NewNotFound(v1alpha1.Resource(v1alpha1.ResourcePluralIPAMHandle), handleID) + } + + return handle, nil +} + +// deleteHandle deletes the given handle. +func (c IPAMClient) deleteHandle(h *v1alpha1.IPAMHandle) error { + if !h.IsDeleted() { + h.MarkDeleted() + _, err := c.client.NetworkV1alpha1().IPAMHandles().Update(h) + if err != nil { + return err + } + } + return c.client.NetworkV1alpha1().IPAMHandles().Delete(h.Name, nil) +} + +// Generator to get list of block CIDRs which +// fall within the given cidr. The passed in pool +// must contain the passed in block cidr. +// Returns nil when no more blocks can be generated. +func blockGenerator(pool *v1alpha1.IPPool) func() *cnet.IPNet { + tmp, cidr, _ := cnet.ParseCIDR(pool.Spec.CIDR) + ip := *tmp + + var blockMask net.IPMask + if ip.Version() == 4 { + blockMask = net.CIDRMask(pool.Spec.BlockSize, 32) + } else { + blockMask = net.CIDRMask(pool.Spec.BlockSize, 128) + } + + ones, size := blockMask.Size() + blockSize := new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(size-ones)), nil) + + return func() *cnet.IPNet { + returnIP := ip + + if cidr.Contains(ip.IP) { + ipnet := net.IPNet{IP: returnIP.IP, Mask: blockMask} + cidr := cnet.IPNet{IPNet: ipnet} + ip = cnet.IncrementIP(ip, blockSize) + return &cidr + } else { + return nil + } + } +} diff --git a/pkg/simple/client/network/ippool/ipam/ipam_test.go b/pkg/simple/client/network/ippool/ipam/ipam_test.go new file mode 100644 index 000000000..876571190 --- /dev/null +++ b/pkg/simple/client/network/ippool/ipam/ipam_test.go @@ -0,0 +1,139 @@ +/* +Copyright 2020 KubeSphere 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 ipam + +import ( + "flag" + "fmt" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog" + "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + ksfake "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake" + "testing" +) + +func TestIPAM_blockGenerator(t *testing.T) { + pool := &v1alpha1.IPPool{ + ObjectMeta: v1.ObjectMeta{ + Name: "testippool", + }, + Spec: v1alpha1.IPPoolSpec{ + Type: v1alpha1.VLAN, + CIDR: "192.168.0.0/24", + RangeEnd: "192.168.0.250", + RangeStart: "192.168.0.10", + BlockSize: 25, + }, + } + blocks := blockGenerator(pool) + for subnet := blocks(); subnet != nil; subnet = blocks() { + if subnet.String() != "192.168.0.0/25" && subnet.String() != "192.168.0.128/25" { + t.FailNow() + } + } +} + +func TestIPAMSuit(t *testing.T) { + klog.InitFlags(nil) + flag.Set("logtostderr", "true") + flag.Set("v", "4") + flag.Parse() + klog.SetOutput(GinkgoWriter) + RegisterFailHandler(Fail) + RunSpecs(t, "IPAM Test Suite") +} + +const ( + vlanIPPoolName = "testippool" +) + +var ( + vlanIPPool = &v1alpha1.IPPool{ + TypeMeta: v1.TypeMeta{}, + ObjectMeta: v1.ObjectMeta{ + Name: vlanIPPoolName, + }, + Spec: v1alpha1.IPPoolSpec{ + Type: v1alpha1.VLAN, + CIDR: "192.168.0.0/24", + }, + Status: v1alpha1.IPPoolStatus{}, + } +) + +func newVLANIPAMClient() IPAMClient { + vlanIPPool.Labels = map[string]string{ + v1alpha1.IPPoolTypeLabel: vlanIPPool.Spec.Type, + v1alpha1.IPPoolNameLabel: vlanIPPool.Name, + v1alpha1.IPPoolIDLabel: fmt.Sprintf("%d", vlanIPPool.ID()), + } + return IPAMClient{ + typeStr: v1alpha1.VLAN, + client: ksfake.NewSimpleClientset(vlanIPPool), + } +} + +func TestIpamClient_GetAllPools(t *testing.T) { + c := newVLANIPAMClient() + pools, _ := c.getAllPools() + if len(pools) != 1 { + t.FailNow() + } +} + +var _ = Describe("test vlan ippool", func() { + It("test get all vlan ippool", func() { + c := newVLANIPAMClient() + pools, _ := c.getAllPools() + Expect(len(pools)).To(Equal(1)) + }) + + It("test get pool utilization", func() { + c := newVLANIPAMClient() + stats, _ := c.GetUtilization(GetUtilizationArgs{Pools: []string{vlanIPPoolName}}) + Expect(len(stats)).To(Equal(1)) + Expect(stats[0].Unallocated).To(Equal(256)) + }) + + It("test auto assign/unassign ip", func() { + c := newVLANIPAMClient() + result, _ := c.AutoAssign(AutoAssignArgs{ + HandleID: "testhandle", + Pool: vlanIPPoolName, + }) + Expect(len(result.IPs)).To(Equal(1)) + stats, _ := c.GetUtilization(GetUtilizationArgs{Pools: []string{vlanIPPoolName}}) + Expect(stats[0].Unallocated).To(Equal(255)) + + blocks, _ := c.client.NetworkV1alpha1().IPAMBlocks().List(v1.ListOptions{}) + Expect(len(blocks.Items)).To(Equal(1)) + Expect(blocks.Items[0].BlockName()).To(Equal(fmt.Sprintf("%d-%s", vlanIPPool.ID(), "192-168-0-0-24"))) + + handles, _ := c.client.NetworkV1alpha1().IPAMHandles().List(v1.ListOptions{}) + Expect(len(handles.Items)).To(Equal(1)) + Expect(handles.Items[0].Name).To(Equal("testhandle")) + + Expect(c.ReleaseByHandle("testhandle")).ShouldNot(HaveOccurred()) + blocks, _ = c.client.NetworkV1alpha1().IPAMBlocks().List(v1.ListOptions{}) + Expect(len(blocks.Items)).To(Equal(0)) + + handles, _ = c.client.NetworkV1alpha1().IPAMHandles().List(v1.ListOptions{}) + Expect(len(handles.Items)).To(Equal(0)) + }) +}) diff --git a/pkg/simple/client/network/ippool/ipam/ipam_types.go b/pkg/simple/client/network/ippool/ipam/ipam_types.go new file mode 100644 index 000000000..230a75ac6 --- /dev/null +++ b/pkg/simple/client/network/ippool/ipam/ipam_types.go @@ -0,0 +1,51 @@ +/* +Copyright 2020 KubeSphere 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 ipam + +// AutoAssignArgs defines the set of arguments for assigning one or more +// IP addresses. +type AutoAssignArgs struct { + HandleID string + + // A key/value mapping of metadata to store with the allocations. + Attrs map[string]string + + Pool string +} + +// GetUtilizationArgs defines the set of arguments for requesting IP utilization. +type GetUtilizationArgs struct { + // If specified, the pools whose utilization should be reported. Each string here + // can be a pool name or CIDR. If not specified, this defaults to all pools. + Pools []string +} + +// PoolUtilization reports IP utilization for a single IP pool. +type PoolUtilization struct { + // This pool's name. + Name string + + // Number of possible IPs in this block. + Capacity int + + // Number of available IPs in this block. + Unallocated int + + Allocate int + + Reserved int +} diff --git a/pkg/simple/client/network/ippool/options.go b/pkg/simple/client/network/ippool/options.go new file mode 100644 index 000000000..b9036328f --- /dev/null +++ b/pkg/simple/client/network/ippool/options.go @@ -0,0 +1,23 @@ +/* +Copyright 2020 The KubeSphere 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 ippool + +import "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/calico" + +type Options struct { + Calico *calico.Options `json:"calico,omityempty" yaml:"calico,omityempty"` +} diff --git a/pkg/simple/client/network/ippool/provider.go b/pkg/simple/client/network/ippool/provider.go new file mode 100644 index 000000000..1f5f47e59 --- /dev/null +++ b/pkg/simple/client/network/ippool/provider.go @@ -0,0 +1,98 @@ +/* +Copyright 2020 The KubeSphere 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 ippool + +import ( + "k8s.io/client-go/util/workqueue" + networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + kubesphereclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/ipam" +) + +type Provider interface { + // canDelete indicates whether the address pool is being used or not. + DeleteIPPool(pool *networkv1alpha1.IPPool) (canDelete bool, err error) + CreateIPPool(pool *networkv1alpha1.IPPool) error + UpdateIPPool(pool *networkv1alpha1.IPPool) error + GetIPPoolStats(pool *networkv1alpha1.IPPool) (*networkv1alpha1.IPPool, error) + SyncStatus(stopCh <-chan struct{}, q workqueue.RateLimitingInterface) error +} + +type provider struct { + kubesphereClient kubesphereclient.Interface + ipamclient ipam.IPAMClient +} + +func (p provider) DeleteIPPool(pool *networkv1alpha1.IPPool) (bool, error) { + blocks, err := p.ipamclient.ListBlocks(pool.Name) + if err != nil { + return false, err + } + + for _, block := range blocks { + if block.Empty() { + if err = p.ipamclient.DeleteBlock(&block); err != nil { + return false, err + } + } else { + return false, nil + } + } + + return true, nil +} + +func (p provider) CreateIPPool(pool *networkv1alpha1.IPPool) error { + return nil +} + +func (p provider) UpdateIPPool(pool *networkv1alpha1.IPPool) error { + return nil +} + +func (p provider) SyncStatus(stopCh <-chan struct{}, q workqueue.RateLimitingInterface) error { + return nil +} + +func (p provider) GetIPPoolStats(pool *networkv1alpha1.IPPool) (*networkv1alpha1.IPPool, error) { + stats, err := p.ipamclient.GetUtilization(ipam.GetUtilizationArgs{ + Pools: []string{pool.Name}, + }) + if err != nil { + return nil, err + } + + stat := stats[0] + return &networkv1alpha1.IPPool{ + Status: networkv1alpha1.IPPoolStatus{ + Allocations: stat.Allocate, + Unallocated: stat.Unallocated, + Reserved: stat.Reserved, + Capacity: stat.Capacity, + Synced: true, + }, + }, nil +} + +func NewProvider(clientset kubesphereclient.Interface, options Options) provider { + vlanProvider := provider{ + kubesphereClient: clientset, + ipamclient: ipam.NewIPAMClient(clientset, networkv1alpha1.VLAN), + } + + return vlanProvider +} diff --git a/pkg/simple/client/network/ippool/provider_test.go b/pkg/simple/client/network/ippool/provider_test.go new file mode 100644 index 000000000..fa30254bd --- /dev/null +++ b/pkg/simple/client/network/ippool/provider_test.go @@ -0,0 +1,68 @@ +/* +Copyright 2020 The KubeSphere 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 ippool + +import ( + "testing" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" + fakeks "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake" + "kubesphere.io/kubesphere/pkg/simple/client/network/ippool/ipam" +) + +func testNewProvider() provider { + return NewProvider(fakeks.NewSimpleClientset(), Options{}) +} + +func TestProvider_GetIPPoolStats(t *testing.T) { + p := testNewProvider() + + pool := v1alpha1.IPPool{ + TypeMeta: v1.TypeMeta{}, + ObjectMeta: v1.ObjectMeta{ + Name: "testippool", + Labels: map[string]string{ + v1alpha1.IPPoolTypeLabel: v1alpha1.VLAN, + }, + }, + Spec: v1alpha1.IPPoolSpec{ + Type: v1alpha1.VLAN, + CIDR: "192.168.0.0/24", + }, + Status: v1alpha1.IPPoolStatus{}, + } + + _, err := p.kubesphereClient.NetworkV1alpha1().IPPools().Create(&pool) + if err != nil { + t.FailNow() + } + + p.ipamclient.AutoAssign(ipam.AutoAssignArgs{ + HandleID: "testhandle", + Attrs: nil, + Pool: "testippool", + }) + stat, err := p.GetIPPoolStats(&pool) + if err != nil { + t.FailNow() + } + if stat.Status.Unallocated != pool.NumAddresses()-1 || stat.Status.Reserved != 0 || + stat.Status.Capacity != pool.NumAddresses() || stat.Status.Allocations != 1 { + t.FailNow() + } +} diff --git a/pkg/simple/client/network/options.go b/pkg/simple/client/network/options.go index 2ef689d0b..a75741bc2 100644 --- a/pkg/simple/client/network/options.go +++ b/pkg/simple/client/network/options.go @@ -16,24 +16,33 @@ limitations under the License. package network -import "github.com/spf13/pflag" +import ( + "github.com/spf13/pflag" + "kubesphere.io/kubesphere/pkg/simple/client/network/ippool" +) type NSNPOptions struct { AllowedIngressNamespaces []string `json:"allowedIngressNamespaces,omitempty" yaml:"allowedIngressNamespaces,omitempty"` } type Options struct { - EnableNetworkPolicy bool `json:"enableNetworkPolicy,omitempty" yaml:"enableNetworkPolicy"` - NSNPOptions NSNPOptions `json:"nsnpOptions,omitempty" yaml:"nsnpOptions,omitempty"` + EnableNetworkPolicy bool `json:"enableNetworkPolicy,omitempty" yaml:"enableNetworkPolicy"` + NSNPOptions NSNPOptions `json:"nsnpOptions,omitempty" yaml:"nsnpOptions,omitempty"` + EnableIPPool bool `json:"enableIPPool,omitempty" yaml:"enableIPPool"` + IPPoolOptions ippool.Options `json:"ippoolOptions,omitempty" yaml:"ippoolOptions,omitempty"` } // NewNetworkOptions returns a `zero` instance func NewNetworkOptions() *Options { return &Options{ EnableNetworkPolicy: false, + EnableIPPool: false, NSNPOptions: NSNPOptions{ AllowedIngressNamespaces: []string{}, }, + IPPoolOptions: ippool.Options{ + Calico: nil, + }, } } @@ -44,10 +53,14 @@ func (s *Options) Validate() []error { func (s *Options) ApplyTo(options *Options) { options.EnableNetworkPolicy = s.EnableNetworkPolicy + options.EnableIPPool = s.EnableIPPool options.NSNPOptions = s.NSNPOptions + options.IPPoolOptions = s.IPPoolOptions } func (s *Options) AddFlags(fs *pflag.FlagSet, c *Options) { fs.BoolVar(&s.EnableNetworkPolicy, "enable-network-policy", c.EnableNetworkPolicy, "This field instructs KubeSphere to enable network policy or not.") + fs.BoolVar(&s.EnableIPPool, "enable-ippool", c.EnableIPPool, + "This field instructs KubeSphere to enable ippool or not.") } diff --git a/pkg/simple/client/network/utils/utils.go b/pkg/simple/client/network/utils/utils.go new file mode 100644 index 000000000..707786549 --- /dev/null +++ b/pkg/simple/client/network/utils/utils.go @@ -0,0 +1,37 @@ +/* +Copyright 2020 The KubeSphere 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 ( + "fmt" + "math/rand" + "net" +) + +func EthRandomAddr(ip net.IP) string { + buf := make([]byte, 2) + rand.Read(buf) + + // Clear multicast bit + buf[0] &= 0xfe + // Set the local bit + buf[0] |= 2 + + //TODO support ipv6 + buf = append(buf, []byte(ip)...) + return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]) +}