├── docs ├── examples │ ├── tencent-cloud-eni.md │ └── tencent-cloud-service-nodeport.md ├── Roadmap.md ├── design │ ├── media │ │ ├── lbcf-arch.png │ │ ├── lbcf-consistency.png │ │ ├── when-lb-webhooks-are-invoked.png │ │ └── when-backend-webhooks-are-invoked.png │ ├── proposal │ │ ├── dry-run-mode.md │ │ ├── metrics.md │ │ ├── shared-lb-in-namespaces.md │ │ ├── multiple-ports-and-loadbalancers-in-backendgroup.md │ │ └── deregister-policy.md │ ├── lbcf-architecture.md │ └── lbcf-consistency-design.md └── install.md ├── deployments ├── certs │ ├── rootCA.srl │ ├── rootCA.crt │ ├── server.csr │ ├── server.crt │ ├── rootCA.key │ └── server.key ├── service.yaml ├── rbac.yaml ├── deployment.yaml ├── crd.yaml └── secret.yaml ├── CHANGELOG ├── CHANGELOG-1.3.1.md ├── CHANGELOG-1.1.1.md ├── CHANGELOG-1.2.0.md └── CHANGELOG-1.3.0.md ├── .github └── workflows │ ├── build.yml │ └── release.yml ├── pkg ├── apis │ └── lbcf.tkestack.io │ │ ├── v1 │ │ ├── doc.go │ │ ├── zz_generated.defaults.go │ │ └── register.go │ │ └── v1beta1 │ │ ├── doc.go │ │ ├── zz_generated.defaults.go │ │ └── register.go ├── client-go │ ├── clientset │ │ └── versioned │ │ │ ├── doc.go │ │ │ ├── fake │ │ │ ├── doc.go │ │ │ ├── register.go │ │ │ └── clientset_generated.go │ │ │ ├── typed │ │ │ └── lbcf.tkestack.io │ │ │ │ ├── v1 │ │ │ │ ├── generated_expansion.go │ │ │ │ ├── doc.go │ │ │ │ ├── fake │ │ │ │ │ ├── doc.go │ │ │ │ │ ├── fake_lbcf.tkestack.io_client.go │ │ │ │ │ └── fake_bind.go │ │ │ │ └── lbcf.tkestack.io_client.go │ │ │ │ └── v1beta1 │ │ │ │ ├── fake │ │ │ │ ├── doc.go │ │ │ │ ├── fake_lbcf.tkestack.io_client.go │ │ │ │ ├── fake_backendgroup.go │ │ │ │ ├── fake_loadbalancer.go │ │ │ │ ├── fake_backendrecord.go │ │ │ │ └── fake_loadbalancerdriver.go │ │ │ │ ├── doc.go │ │ │ │ ├── generated_expansion.go │ │ │ │ └── lbcf.tkestack.io_client.go │ │ │ ├── scheme │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ └── clientset.go │ ├── listers │ │ └── lbcf.tkestack.io │ │ │ ├── v1 │ │ │ ├── expansion_generated.go │ │ │ └── bind.go │ │ │ └── v1beta1 │ │ │ ├── expansion_generated.go │ │ │ ├── backendgroup.go │ │ │ ├── loadbalancer.go │ │ │ ├── backendrecord.go │ │ │ └── loadbalancerdriver.go │ └── informers │ │ └── externalversions │ │ ├── internalinterfaces │ │ └── factory_interfaces.go │ │ ├── lbcf.tkestack.io │ │ ├── v1 │ │ │ ├── interface.go │ │ │ └── bind.go │ │ ├── interface.go │ │ └── v1beta1 │ │ │ ├── interface.go │ │ │ ├── backendgroup.go │ │ │ ├── loadbalancer.go │ │ │ ├── backendrecord.go │ │ │ └── loadbalancerdriver.go │ │ └── generic.go ├── version │ └── version.go ├── lbcfcontroller │ ├── driver_controller.go │ ├── driver_controller_test.go │ ├── util │ │ └── sync_result.go │ └── admission │ │ ├── mutate_test.go │ │ └── admission_webhook_server_test.go ├── api │ └── bind │ │ └── util.go └── metrics │ └── metrics.go ├── .golangci.yml ├── .gitignore ├── go.mod ├── cmd └── lbcf-controller │ ├── lbcf-controller.go │ └── app │ ├── config │ └── config.go │ ├── server.go │ └── context │ └── context.go ├── Makefile ├── README.md └── CONTRIBUTING.md /docs/examples/tencent-cloud-eni.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/examples/tencent-cloud-service-nodeport.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /deployments/certs/rootCA.srl: -------------------------------------------------------------------------------- 1 | B66F8BC9AC5EE048 2 | -------------------------------------------------------------------------------- /docs/Roadmap.md: -------------------------------------------------------------------------------- 1 | see wiki [Roadmap](https://github.com/tkestack/lb-controlling-framework/wiki/Roadmap) -------------------------------------------------------------------------------- /docs/design/media/lbcf-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkestack/lb-controlling-framework/HEAD/docs/design/media/lbcf-arch.png -------------------------------------------------------------------------------- /docs/design/media/lbcf-consistency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkestack/lb-controlling-framework/HEAD/docs/design/media/lbcf-consistency.png -------------------------------------------------------------------------------- /docs/design/media/when-lb-webhooks-are-invoked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkestack/lb-controlling-framework/HEAD/docs/design/media/when-lb-webhooks-are-invoked.png -------------------------------------------------------------------------------- /docs/design/media/when-backend-webhooks-are-invoked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tkestack/lb-controlling-framework/HEAD/docs/design/media/when-backend-webhooks-are-invoked.png -------------------------------------------------------------------------------- /CHANGELOG/CHANGELOG-1.3.1.md: -------------------------------------------------------------------------------- 1 | # v1.3.1 2 | ## Changelog since v1.3.0 3 | 4 | * `Fixed`: enqueue registered backend in addBackendRecord if it's ensurePolicy is always. [#1b4cc](https://github.com/tkestack/lb-controlling-framework/commit/1b4cc037e5ff1f9fd1ac9acb1c2638d7d9193c2c) 5 | 6 | 7 | -------------------------------------------------------------------------------- /deployments/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: lbcf-controller 5 | namespace: kube-system 6 | spec: 7 | ports: 8 | - name: admit-server 9 | port: 443 10 | targetPort: 443 11 | - name: healthz 12 | port: 11029 13 | targetPort: 11029 14 | selector: 15 | lbcf.tkestack.io/component: lbcf-controller 16 | sessionAffinity: None 17 | type: ClusterIP -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-18.04 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | 13 | - uses: actions/cache@v1 14 | with: 15 | path: ~/go/pkg/mod 16 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 17 | restore-keys: | 18 | ${{ runner.os }}-go- 19 | 20 | - run: | 21 | make 22 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | create: 5 | tags: 6 | - v* 7 | 8 | jobs: 9 | release: 10 | 11 | runs-on: ubuntu-18.04 12 | 13 | steps: 14 | - uses: actions/checkout@v1 15 | 16 | - uses: actions/cache@v1 17 | with: 18 | path: ~/go/pkg/mod 19 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 20 | restore-keys: | 21 | ${{ runner.os }}-go- 22 | 23 | - uses: azure/docker-login@v1 24 | with: 25 | username: ${{ secrets.REGISTRY_USERNAME }} 26 | password: ${{ secrets.REGISTRY_PASSWORD }} 27 | - run: | 28 | make push 29 | -------------------------------------------------------------------------------- /pkg/apis/lbcf.tkestack.io/v1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2015 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package 18 | // +groupName=lbcf.tkestack.io 19 | 20 | package v1 21 | -------------------------------------------------------------------------------- /pkg/apis/lbcf.tkestack.io/v1beta1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2015 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package 18 | // +groupName=lbcf.tkestack.io 19 | 20 | package v1beta1 21 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | # timeout for analysis, e.g. 30s, 5m 3 | deadline: 10m 4 | # include test files or not 5 | tests: true 6 | # disallowed from the implicit automatic updating of go.mod described above 7 | modules-download-mode: readonly 8 | # which dirs to skip: they won't be analyzed; 9 | skip-dirs: 10 | - pkg/client-go 11 | 12 | linters: 13 | disable-all: true 14 | enable: 15 | - unused 16 | - gofmt 17 | - ineffassign 18 | - govet 19 | - deadcode 20 | - structcheck 21 | - varcheck 22 | - typecheck 23 | - golint 24 | - unconvert 25 | - staticcheck 26 | - gosimple 27 | 28 | issues: 29 | exclude-rules: 30 | - linters: 31 | - staticcheck 32 | text: "SA1019:" 33 | 34 | service: 35 | golangci-lint-version: 1.20.x 36 | -------------------------------------------------------------------------------- /docs/design/proposal/dry-run-mode.md: -------------------------------------------------------------------------------- 1 | # Scenario 2 | Updating lbcf-controller or the drivers may cause unexpected behaviors, so the developers want to test their work in a real cluster without modifying it. 3 | 4 | 5 | In dry-run mode, the following statements are true: 6 | 7 | * Drivers may specify if they accept dry-run webhook requests by setting `acceptDryRunCall` in `LoadBalancerDriver`. If true, a `dryRun` flag is set in all webhook requests. Otherwise, no webhooks will be invoked. No matter and `lbcf-controller` treat them as failed. 8 | * `lbcf-controller` treat all dry-run webhook response as failed, so that the status of any CRD is not changed 9 | * `lbcf-controller` always print webhook names and parameters in log. 10 | * Given an object that `lbcf-controller` is watching, it is processed only once, even after informer resync -------------------------------------------------------------------------------- /docs/install.md: -------------------------------------------------------------------------------- 1 | ## 系统要求: 2 | 3 | * K8S 1.10及以上版本 4 | 5 | * 开启Dynamic Admission Control,在apiserver中添加启动参数: 6 | * --enable-admission-plugins=MutatingAdmissionWebhook,ValidatingAdmissionWebhook 7 | 8 | * K8S 1.10版本,在apiserver中额外添加参数: 9 | 10 | * --feature-gates=CustomResourceSubresources=true 11 | 12 | 推荐环境: 13 | 14 | 在[腾讯云](https://cloud.tencent.com/product/tke)上购买1.12.4版本集群,无需修改任何参数,开箱可用 15 | 16 | 17 | ## 步骤1: 制作镜像 18 | 19 | 进入项目根目录,运行命令制作镜像 20 | ```bash 21 | make image 22 | ``` 23 | 24 | ## 步骤2:修改YAML中的镜像名称 25 | 26 | [deployments目录](/deployments)中包含了部署LBCF需要的所有YAML, 在其中找到[deployment.yaml](/deployments/deployment.yaml)并使用步骤1生成的镜像替换文件中的`${IMAGE_NAME}` 27 | 28 | ## 步骤3:安装YAML 29 | 30 | 登陆K8S集群,使用`kubectl apply -f $file_name` 命令安装[deployments目录](/deployments)下的所有YAML文件。 31 | 32 | *注:deployments目录中使用的所有证书皆为自签名证书,可按需替换* 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows: 2 | Thumbs.db 3 | ehthumbs.db 4 | Desktop.ini 5 | 6 | # OSX leaves these everywhere on SMB shares 7 | ._* 8 | 9 | # OSX trash 10 | .DS_Store 11 | 12 | # Eclipse files 13 | .classpath 14 | .project 15 | .settings/** 16 | 17 | # Files generated by JetBrains IDEs, e.g. IntelliJ IDEA 18 | .idea/ 19 | *.iml 20 | 21 | # Vscode files 22 | .vscode 23 | 24 | # This is where the result of the go build goes 25 | /_output/ 26 | /output/ 27 | /debug/ 28 | /vendor/ 29 | 30 | # Emacs save files 31 | *~ 32 | \#*\# 33 | .\#* 34 | 35 | # Vim-related files 36 | [._]*.s[a-w][a-z] 37 | [._]s[a-w][a-z] 38 | *.un~ 39 | Session.vim 40 | .netrwhist 41 | 42 | # cscope-related files 43 | cscope.* 44 | 45 | # Go test binaries 46 | *.test 47 | 48 | # Mercurial files 49 | **/.hg 50 | **/.hg* 51 | 52 | # Vagrant 53 | .vagrant 54 | 55 | # direnv .envrc files 56 | .envrc -------------------------------------------------------------------------------- /CHANGELOG/CHANGELOG-1.1.1.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [v1.1.1](#v111) 4 | - [Changelog since v1.1.0](#changelog-since-v110) 5 | 6 | 7 | 8 | # v1.1.1 9 | ## Changelog since v1.1.0 10 | Makefile changes: 11 | 12 | * `ADD`: allow build with golang 1.14 [#04231](https://github.com/tkestack/lb-controlling-framework/commit/04231222042243be4d33067b6a54a962535f6ebf) 13 | * `ADD`: generate client-go with `make gen` [#9b140](https://github.com/tkestack/lb-controlling-framework/commit/9b140954f8afc9815f1b1492649531dddfe2732e) 14 | * `CHANGE`: substitute K8S dependencies for direct import of Kubernetes/Kubernetes [#16963](https://github.com/tkestack/lb-controlling-framework/commit/489303d516c09fac4161e5e744ff0e8990f492c3) 15 | * `ADD`: add short name for LBCF CRD [#be852](https://github.com/tkestack/lb-controlling-framework/commit/be85269875845fe3d6ba24903743f89647d8beac) -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module tkestack.io/lb-controlling-framework 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f // indirect 7 | github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f // indirect 8 | github.com/emicklei/go-restful v2.9.5+incompatible 9 | github.com/evanphx/json-patch v4.4.0+incompatible 10 | github.com/imdario/mergo v0.3.7 // indirect 11 | github.com/moul/http2curl v1.0.0 // indirect 12 | github.com/parnurzeal/gorequest v0.2.15 13 | github.com/prometheus/client_golang v1.5.1 14 | github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a // indirect 15 | github.com/spf13/cobra v0.0.5 16 | github.com/spf13/pflag v1.0.5 17 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 18 | k8s.io/api v0.17.0 19 | k8s.io/apimachinery v0.17.0 20 | k8s.io/client-go v0.17.0 21 | k8s.io/klog v1.0.0 22 | ) 23 | -------------------------------------------------------------------------------- /deployments/rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: lbcf-controller 5 | namespace: kube-system 6 | --- 7 | apiVersion: rbac.authorization.k8s.io/v1 8 | kind: ClusterRole 9 | metadata: 10 | name: lbcf-controller 11 | rules: 12 | - apiGroups: 13 | - "" 14 | resources: 15 | - pods 16 | - services 17 | - events 18 | - nodes 19 | verbs: 20 | - '*' 21 | - apiGroups: 22 | - lbcf.tkestack.io 23 | resources: 24 | - '*' 25 | verbs: 26 | - '*' 27 | --- 28 | kind: ClusterRoleBinding 29 | apiVersion: rbac.authorization.k8s.io/v1 30 | metadata: 31 | name: lbcf-controller 32 | subjects: 33 | - kind: ServiceAccount 34 | name: lbcf-controller 35 | namespace: kube-system 36 | roleRef: 37 | kind: ClusterRole 38 | name: lbcf-controller 39 | apiGroup: rbac.authorization.k8s.io 40 | 41 | -------------------------------------------------------------------------------- /deployments/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: lbcf-controller 5 | namespace: kube-system 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | lbcf.tkestack.io/component: lbcf-controller 11 | template: 12 | metadata: 13 | labels: 14 | lbcf.tkestack.io/component: lbcf-controller 15 | spec: 16 | priorityClassName: "system-node-critical" 17 | serviceAccountName: lbcf-controller 18 | containers: 19 | - name: controller 20 | image: ${IMAGE_NAME} 21 | imagePullPolicy: IfNotPresent 22 | ports: 23 | - containerPort: 443 24 | name: admit-server 25 | volumeMounts: 26 | - name: server-tls 27 | mountPath: /etc/lbcf 28 | volumes: 29 | - name: server-tls 30 | secret: 31 | secretName: lbcf-controller 32 | 33 | 34 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | // This package has the automatically generated clientset. 22 | package versioned 23 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | // This package has the automatically generated fake clientset. 22 | package fake 23 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package v1 22 | 23 | type BindExpansion interface{} 24 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/scheme/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | // This package contains the scheme of the automatically generated clientset. 22 | package scheme 23 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | // This package has the automatically generated typed clients. 22 | package v1 23 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | // Package fake has the automatically generated clients. 22 | package fake 23 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | // Package fake has the automatically generated clients. 22 | package fake 23 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | // This package has the automatically generated typed clients. 22 | package v1beta1 23 | -------------------------------------------------------------------------------- /docs/design/proposal/metrics.md: -------------------------------------------------------------------------------- 1 | The following metrics are added in v1.2.0: 2 | 3 | |key|labels|data type|describe| 4 | |:---:|:---:|:---:|:---:| 5 | |pending_key|key_kind|GaugeVec|number of LBCF CRD objects waiting to be processed| 6 | |working_key|key_kind|GaugeVec|number of LBCF CRD objects being processed| 7 | |webhook_calls|driver_name,webhook_name|CounterVec|number of webhook calls| 8 | |webhook_errors|driver_name,webhook_name|CounterVec|number of webhook calls that have error - network error, 404, etc.| 9 | |webhook_fails|driver_name,webhook_name|CounterVec|number of webhook requests that drivers respond with failure| 10 | |webhook_latency_bucket|driver_name,webhook_name|HistogramVec|time it takes to receive response from driver| 11 | 12 | The following metrics are added in v1.3.0: 13 | 14 | |key|labels|data type|describe| 15 | |:---:|:---:|:---:|:---:| 16 | |k8s_operation_latency|pending_key,k8s_op_type|HistogramVec|time it takes to finish a K8S operation(CREATE/UPDATE/DELETE)| 17 | |key_process_latency|crd|HistogramVec|time it takes to finish processing a LBCF CRD object| 18 | -------------------------------------------------------------------------------- /docs/design/proposal/shared-lb-in-namespaces.md: -------------------------------------------------------------------------------- 1 | # Background 2 | It's common that cluster admin creates some load balancers and share them in specific namespaces. In such scenario, 3 | users that only authorized to specific namespaces are allowed to use the load balancers, but not allowed to create or modify them. 4 | 5 | # Solution 6 | We add a `scope` parameter in `LoadBalancer.spec`, it indicates in which namespaces the LoadBalancer is available. 7 | ```yaml 8 | apiVersion: lbcf.tkestack.io/v1beta1 9 | kind: LoadBalancer 10 | metadata: 11 | name: lbcf-my-load-balancer 12 | namespace: kube-system 13 | spec: 14 | lbDriver: xxxxx 15 | lbSpec: 16 | lbID: xxxxx 17 | scope: 18 | - namespace-a 19 | - namespace-b 20 | attributes: 21 | attr: xxxxx 22 | ``` 23 | Specification: 24 | 1. `name` must begin with `lbcf-` 25 | 2. `namespace` must be `kube-system` 26 | 3. if `name` begins with `lbcf-`, the `namespace` must be `kube-system` 27 | 4. `scope` consists of namespaces. `*` indicates all namespaces, including the ones not yet created. If not specifed, 28 | the LoadBalancer is only available in `kube-system`. -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | type BackendGroupExpansion interface{} 24 | 25 | type BackendRecordExpansion interface{} 26 | 27 | type LoadBalancerExpansion interface{} 28 | 29 | type LoadBalancerDriverExpansion interface{} 30 | -------------------------------------------------------------------------------- /deployments/certs/rootCA.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC2jCCAcICCQCBwgfwwvA+xDANBgkqhkiG9w0BAQsFADAuMQswCQYDVQQGEwJD 3 | TjEQMA4GA1UECgwHVGVuY2VudDENMAsGA1UEAwwETEJDRjAgFw0yMDEyMzAwNDI1 4 | MTBaGA8yMTIwMTIwNjA0MjUxMFowLjELMAkGA1UEBhMCQ04xEDAOBgNVBAoMB1Rl 5 | bmNlbnQxDTALBgNVBAMMBExCQ0YwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK 6 | AoIBAQDXm75oVuZZHyx/f33mjb0jVwZGHJp+Dkf7zrJaCpdOHVBl8uZyoKdfsp4U 7 | G6yWtR/vbzwmzN2EwBUq1qDwThUqY5PSNIQ6e+G098r9hF9iodK0CSHL1AlRlZfB 8 | Mh1981xiP0Jrqu2G35FkmVuTDdRKWDk8+RfH3YcMeK3ZJPhURJGzcRPr/K6kMJRP 9 | ezHELjGqfmpLpJ8c492LY5rm7aalfV2i65JEr/K4wc1+6zZAr7L3ms3mo4ud8OZu 10 | 9Z/6q3bqQUZ7mzfQ6HI1NZ5iH6/hHcZ4pQMq4MjY8jZ5FrjJEG1viAuFdOfzwFci 11 | eoRgZ8z967PAhee30VAfDDP9YUMrAgMBAAEwDQYJKoZIhvcNAQELBQADggEBABvZ 12 | ACZz8DbOn8a+jVeqKeoUDePxo7jfnwmvPL5cKpwC1uS6EgZNxSGVBKYES2N0tZpw 13 | oSkcHAigs1owhy7o/ZXfXzExQtrA/RYAPNf616w0R0bDUxSiTe2OBn9Dk6iiXtaC 14 | sWeWGJtetL4OJKSe+fE0qQHpNMIkObL2x7m4lSFNxQACwOrViotE1zyVcXlfJDPv 15 | s04HEz6WPciZPvDcY/CEJl/30E00VJT88X3neA6kCULoMW721oqsJQILc8eBnApD 16 | 7T2tRuD2xjG7wHOF34PiLyUFMTSqfogysyeQmG4IoT5OqpRtEaGwobuu8+T7unud 17 | Amd4bXIT/vamPltJ6uc= 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /deployments/certs/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIC3jCCAcYCAQAwLjELMAkGA1UEBhMCQ04xEDAOBgNVBAoMB1RlbmNlbnQxDTAL 3 | BgNVBAMMBExCQ0YwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6IGCB 4 | xxVF3vr5JI4dsGjFII6BAxj7wHsTfLSV/1hDhcRj2wmo2wgQ7DmLcHm9RwPdCqTI 5 | Fx3UeJ7iSzOdPuSYWSuzcEtaY8wKd8X/G9gIwdm+pbWTEsz0pIfYTzOp7A588ICx 6 | Hq/BParTzDGVo7715k1esjqrHlgQNv3b5eTBj41+KnKZomCY0BRaoJnH9oyeO1lP 7 | l7dKdVmkOIcC2g+1OU1PK7V75KyuG257601JCvSddVwQhPSSLXPcZ0RCuD02E8i+ 8 | hBBWJSwx4Rqd6sjNhx/8Y9+pQqVzDpi7R19BTGzyv/yy6+uB1cGde+MjH7xiJTiZ 9 | 4x4/rlD5E26aUrpJAgMBAAGgazBpBgkqhkiG9w0BCQ4xXDBaMA4GA1UdDwEB/wQE 10 | AwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwKQYDVR0RBCIwIIIe 11 | bGJjZi1jb250cm9sbGVyLmt1YmUtc3lzdGVtLnN2MA0GCSqGSIb3DQEBCwUAA4IB 12 | AQAIg/va49DocJCHypg30bnzH22aqHScX3U0Mu4pioJdrC6Z0xkj6wV2ukGVGxnh 13 | V7pF/XzeG6a1/L12DhHk2Lj5QOQX70ZsrG06dBuN7Aqx2TxCLaAOJVKeCbXpWxJ7 14 | IkcTUg8hSMA+lgdYC6ovX1E2R7gt+RWBgIyPczNoHt7gAm9Fr52OoYD6lY055QsF 15 | 9T6+2cR6w+vNCAXDcCs4bqFxyrrIXUitpqGiJNUGeEAxAJar2of91uaqtP517m7L 16 | RU102v2XuSGRb+wQOLTSAdq/B5wTQXZx7OG65xrNFN114uFI+4TNzxYv77BAobp8 17 | MmTpRDTtCh1m4f1NVqnBiy8u 18 | -----END CERTIFICATE REQUEST----- 19 | -------------------------------------------------------------------------------- /pkg/client-go/listers/lbcf.tkestack.io/v1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by lister-gen. DO NOT EDIT. 20 | 21 | package v1 22 | 23 | // BindListerExpansion allows custom methods to be added to 24 | // BindLister. 25 | type BindListerExpansion interface{} 26 | 27 | // BindNamespaceListerExpansion allows custom methods to be added to 28 | // BindNamespaceLister. 29 | type BindNamespaceListerExpansion interface{} 30 | -------------------------------------------------------------------------------- /cmd/lbcf-controller/lbcf-controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack available. 3 | * 4 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 7 | * this file except in compliance with the License. You may obtain a copy of the 8 | * License at 9 | * 10 | * https://opensource.org/licenses/Apache-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations under the License. 16 | */ 17 | 18 | package main 19 | 20 | import ( 21 | "fmt" 22 | _ "net/http/pprof" 23 | "os" 24 | 25 | "tkestack.io/lb-controlling-framework/cmd/lbcf-controller/app" 26 | 27 | "k8s.io/klog" 28 | ) 29 | 30 | func main() { 31 | command := app.NewServer() 32 | defer klog.Flush() 33 | 34 | if err := command.Execute(); err != nil { 35 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 36 | os.Exit(1) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /deployments/certs/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDPjCCAiagAwIBAgIJALZvi8msXuBKMA0GCSqGSIb3DQEBCwUAMC4xCzAJBgNV 3 | BAYTAkNOMRAwDgYDVQQKDAdUZW5jZW50MQ0wCwYDVQQDDARMQkNGMCAXDTIwMTIz 4 | MDA0MjUxMFoYDzIxMjAxMjA2MDQyNTEwWjAuMQswCQYDVQQGEwJDTjEQMA4GA1UE 5 | CgwHVGVuY2VudDENMAsGA1UEAwwETEJDRjCCASIwDQYJKoZIhvcNAQEBBQADggEP 6 | ADCCAQoCggEBANLO29mtw4Yg7tgAwNvzLyx2ZXgHc9OYb1FQK9jj1Cd9p26+6L06 7 | TiEPW3UWQqRJPIDIY9sVQIndSdFEr8G0vzP+oBi6Sa8WBTqrcY7lzs8b5P6uwXGg 8 | afy9fwOW1gL++QVKtcqLYDU6kwUoePFpqePKqQ5P3A3wJ2wbSAztnRmsUsS3BTw0 9 | TMMW/Z5DvVChMrgCwHlIaqPHPEa138xCew+h8F/tIQ50UmqfL7ZoRQ6tw+lM8aWN 10 | 8JXiGPDscl0j0nIIAOP4hfNm5b+POcqeSfCTLNX06WJwJiZfif5HazVyO84VPUsK 11 | 0wLSViLCY1Z5ePlR+Uj1nkyfUQq1uIrC9SMCAwEAAaNdMFswDgYDVR0PAQH/BAQD 12 | AgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAqBgNVHREEIzAhgh9s 13 | YmNmLWNvbnRyb2xsZXIua3ViZS1zeXN0ZW0uc3ZjMA0GCSqGSIb3DQEBCwUAA4IB 14 | AQC+u+hIaV4PX8v9i+HWrBgzW9/VSiE73VrdLmF/6wonrZyhda/E34nMnd7uLsbl 15 | OfIEq9dl2TpyFsyyqAu5I7Hfdzt4TztzgaaojUzJSpIiLDA4Ns2mhXX8cmJzkct+ 16 | msecEUNUzzFCzRCxHFJhQsBcbS9sGfU7BcWEW2Yx6UhPq7AqLRE5nq2VN+8ra2Wu 17 | 6Rhc2ArmlXOnion0FE4KNs1jPg9C7HzABx7FAU5KJqs+fN62JQ5LtSW1XYFQbIM4 18 | hzUJ38zTYUzSXZinhHUO/HA2oY7ZwG33UjYvSw2XRRR8Air9Lj0BZYo36OoR7S69 19 | AASxLZ2P53fcIR+0ayd7advx 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /pkg/apis/lbcf.tkestack.io/v1/zz_generated.defaults.go: -------------------------------------------------------------------------------- 1 | // +build !ignore_autogenerated 2 | 3 | /* 4 | * Tencent is pleased to support the open source community by making TKEStack 5 | * available. 6 | * 7 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 10 | * this file except in compliance with the License. You may obtain a copy of the 11 | * License at 12 | * 13 | * https://opensource.org/licenses/Apache-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 17 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 18 | * specific language governing permissions and limitations under the License. 19 | */ 20 | 21 | // Code generated by defaulter-gen. DO NOT EDIT. 22 | 23 | package v1 24 | 25 | import ( 26 | runtime "k8s.io/apimachinery/pkg/runtime" 27 | ) 28 | 29 | // RegisterDefaults adds defaulters functions to the given scheme. 30 | // Public to allow building arbitrary schemes. 31 | // All generated defaulters are covering - they call all nested defaulters. 32 | func RegisterDefaults(scheme *runtime.Scheme) error { 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /pkg/apis/lbcf.tkestack.io/v1beta1/zz_generated.defaults.go: -------------------------------------------------------------------------------- 1 | // +build !ignore_autogenerated 2 | 3 | /* 4 | * Tencent is pleased to support the open source community by making TKEStack 5 | * available. 6 | * 7 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 10 | * this file except in compliance with the License. You may obtain a copy of the 11 | * License at 12 | * 13 | * https://opensource.org/licenses/Apache-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 17 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 18 | * specific language governing permissions and limitations under the License. 19 | */ 20 | 21 | // Code generated by defaulter-gen. DO NOT EDIT. 22 | 23 | package v1beta1 24 | 25 | import ( 26 | runtime "k8s.io/apimachinery/pkg/runtime" 27 | ) 28 | 29 | // RegisterDefaults adds defaulters functions to the given scheme. 30 | // Public to allow building arbitrary schemes. 31 | // All generated defaulters are covering - they call all nested defaulters. 32 | func RegisterDefaults(scheme *runtime.Scheme) error { 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /docs/design/proposal/multiple-ports-and-loadbalancers-in-backendgroup.md: -------------------------------------------------------------------------------- 1 | # Background 2 | 3 | There has been some complaint about the inconvenience of `BackendGroup`, including: 4 | * When someone wants to register multiple Pod ports to load balancers, multiple `BackendGroup` must be created because there is only one port can be specified in the `BackendGroup` 5 | * It's not uncommon to register given Pods to multiple load balancers, in such scenario, multiple pairs of `LoadBalancer` and `BackendGroup` must be created 6 | 7 | # Solution 8 | 1. Substitute `loadBalancers` for `lbName` in `BackendGroup.spec`, backends (Pods/Service NodePort/Static) will be registered to every load balancer in `BackendGroup.spec.loadBalancers` 9 | 2. For `BackendGroup` of type `pods`, users may specify multiple ports in `BackendGroup.spec.ports` 10 | 11 | # other changes 12 | 13 | `portNumber` is deprecated, use `port` instead. 14 | 15 | # updated BackendGroup 16 | 17 | ```yaml 18 | apiVersion: tke.cloud.tencent.com/v1beta1 19 | kind: BackendGroup 20 | metadata: 21 | name: my-bg 22 | spec: 23 | loadBalancers: 24 | - my-load-balancer-1 25 | - my-load-balancer-2 26 | pods: 27 | ports: 28 | - port: 80 29 | protocol: TCP 30 | - port: 90 31 | protocol: UDP 32 | byLabel: 33 | app: my-web-server 34 | ``` 35 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1/fake/fake_lbcf.tkestack.io_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package fake 22 | 23 | import ( 24 | rest "k8s.io/client-go/rest" 25 | testing "k8s.io/client-go/testing" 26 | v1 "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1" 27 | ) 28 | 29 | type FakeLbcfV1 struct { 30 | *testing.Fake 31 | } 32 | 33 | func (c *FakeLbcfV1) Binds(namespace string) v1.BindInterface { 34 | return &FakeBinds{c, namespace} 35 | } 36 | 37 | // RESTClient returns a RESTClient that is used to communicate 38 | // with API server by this client implementation. 39 | func (c *FakeLbcfV1) RESTClient() rest.Interface { 40 | var ret *rest.RESTClient 41 | return ret 42 | } 43 | -------------------------------------------------------------------------------- /pkg/apis/lbcf.tkestack.io/v1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2015 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | "k8s.io/apimachinery/pkg/runtime" 22 | "k8s.io/apimachinery/pkg/runtime/schema" 23 | ) 24 | 25 | var SchemeGroupVersion = schema.GroupVersion{Group: "lbcf.tkestack.io", Version: "v1"} 26 | 27 | var ( 28 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) 29 | AddToScheme = SchemeBuilder.AddToScheme 30 | ) 31 | 32 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 33 | func Resource(resource string) schema.GroupResource { 34 | return SchemeGroupVersion.WithResource(resource).GroupResource() 35 | } 36 | 37 | // Adds the list of known types to the given scheme. 38 | func addKnownTypes(scheme *runtime.Scheme) error { 39 | scheme.AddKnownTypes(SchemeGroupVersion, 40 | &Bind{}, 41 | &BindList{}, 42 | ) 43 | 44 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 45 | return nil 46 | } 47 | -------------------------------------------------------------------------------- /CHANGELOG/CHANGELOG-1.2.0.md: -------------------------------------------------------------------------------- 1 | # v1.2.0 2 | ## Changelog since v1.1.0 3 | 4 | ### Features: 5 | 6 | * `Added`: dry-run mode. [#80d54](https://github.com/tkestack/lb-controlling-framework/commit/80d545843e5353377331d1af7c0aa1f0f2b4caec) [proposal](/docs/design/proposal/dry-run-mode.md) 7 | * `Added`: multiple ports and loadbalancers may be set in one BackendGroup. [#d8624](https://github.com/tkestack/lb-controlling-framework/commit/d86249de75b1d7d5c7d2c36cd7fb9baff1096dd1) [proposal](/docs/design/proposal/multiple-ports-and-loadbalancers-in-backendgroup.md) 8 | * `Added`: exposes some metrics for prometheus. [#400ba](https://github.com/tkestack/lb-controlling-framework/commit/400baf84b81448375632b48d8b077b4a1bd638bc) [proposal](/docs/design/proposal/metrics.md) 9 | * `Deprecated`: `lbName` and `portNumber` in BackendGroup are deprecated, please use `loadBalancers` and `port` instead. [#d8624](https://github.com/tkestack/lb-controlling-framework/commit/d86249de75b1d7d5c7d2c36cd7fb9baff1096dd1) [proposal](/docs/design/proposal/multiple-ports-and-loadbalancers-in-backendgroup.md) 10 | 11 | ### Other changes: 12 | * `Changed`: BackendGroup status is updated before BackendRecords are created/updated/deleted. [#58af2](https://github.com/tkestack/lb-controlling-framework/commit/58af27c4a58803d484407b60fffbd49a064a419e) 13 | * `Added`: lbcf-controller prints flags being used in bootstrap. [#926d6](https://github.com/tkestack/lb-controlling-framework/commit/926d660f401eccecb937d17bf8ed04572e57398c) 14 | * `Fixed`: lbcf-controller invokes webhook `ensureLoadBalancer` and `ensureBackend` after restarted, even though the `ensurePolicy` is `IfNotSucc`. [#91eea](https://github.com/tkestack/lb-controlling-framework/commit/91eea633c9dcdbaed9f729d28b1fab57f7e504dd) -------------------------------------------------------------------------------- /deployments/certs/rootCA.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAsC41bCKJjcMhfVdVZBksp/LHzc/uO9VPlOl3LydnGWergDBM 3 | JjDDJzjqQJSF9A0JLWzDT2XR3YHmVOd0Cvaj/NBcdJME7TEEpkXIbtyxbCAKaSRn 4 | nEz9+9qMrOVDwgBr27BzfnD79V/2ZBdSOkqnh/JCfZP/85vLdKsryWG8hVJNZrFR 5 | XKn34Cm6MLh7pZVk48b4FIbVQcGeVBXLS7fxmrJ1MHjyRSkAEMM98pzOe+TG3k5+ 6 | uBK6cUjBawhY+hPBWdEi+LQ/5GIdhLFGLf1sMOrKqv6Tu7bFVfAmIlf0WdwJMlbj 7 | 2QGR1FIX1Hf/iMsgcm6gkBLM2aWOWyXD3Cn1lQIDAQABAoIBAQClp+1HbfoUt6Nn 8 | rZR2+EzK5jcEyDxjOiEIDbWpOs1wT9AsSj1vs23sFVH9wylo3lEAy0GiCEUamCex 9 | MaglHt/2uRwV6J87P1n11auuwgh5eG8Ric96YdJ223pmn3PkmGzSNsmB3E6s27xb 10 | RKpmcQexhhMK7Pw/XQAjBUe4pROT7sy05V7v07+HaJs/EOh/q+i2gOS9G8B1hni9 11 | Dwt3LHn2UDpq/DxROqbFBT+JjcKOqxtdEPV7TAx/vICCbZ5973EWl02hhrJ4uojT 12 | Ek6S8EqVIOG9G97NdzjNY5wK+TxqB/UjR+MzYodH91qfCY6N2B4nd432ri2/mRTc 13 | KlpJqWpBAoGBAORmNJAkUDLKcs3vFy3gnS0XTO2Idse581aNLrnQ+hyJPwAYLt8g 14 | fUJ0E076JoY/GVjA1wezOUaDsKlFhpbwtbZXj17P0P3VUMClsocz5kdeJdmvFXAo 15 | y61tMLESfun9YKxU0mDm+M37llJfT96aCz+qRltuFvGLUpHLP3KOs4IJAoGBAMV4 16 | jmt4GcMcYKi1NCmIXTV4eAicdksgRFaAgPOxGPDmK4rZsnGKdPx4CZLueDWXRyv6 17 | GniwHFjiVOaSpDGbomUEXZ28m2u836/RlIMdn4qy7rjok/M0CnuNmXjfiRz1j2pH 18 | W7BSiGi9S6JmykzJ3UQZBNxTWGfdkkWulkk+OcotAoGAXargsaCC12GZVYVRLzpn 19 | mz9sCBooBF7pQbyixgfDGwLaOHKyfkU3uZIa/Q+vzux/u5tSVFEXEykcwT7HJI3R 20 | J9ee75YwsnjSJj+OCM6rCOe+hBi+pQHGDfiyuFvKerGz/NjIcn8m2GruShfWjIcG 21 | R/TP590tQaAOm8YL3jJRwekCgYBcOPxShomJjKQ7xjyxNOVLBpMQennohg5EU8ll 22 | hgz+3I/zTc4/pokSK8FU5JgxdxAfIrPgL2ddv34lHNEf9e52vP43n5D6VQAmrXtt 23 | bJVJAl3o733BNEm9ABlv0P3JD4nF+cOBaloYiGddViIekJwMpJ6XgzkjcOBSOMIp 24 | PK1ilQKBgQDHqLscWkuUsaKFzRmAcyG7moNq/n5DZxf36GsNS9oRhmRdxHnGfOp/ 25 | G3VAUvZSSthHgeTQvIWflWop3a+r1jw0ocAYtaXmm+M9Uy9oKcZuvm2iCCWNoU13 26 | 35BpGxv1tiuf+F8nvy+W5bJTds0eUZH/+O5h95y9M/3cS3UmZZfyLg== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /deployments/certs/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEA0s7b2a3DhiDu2ADA2/MvLHZleAdz05hvUVAr2OPUJ32nbr7o 3 | vTpOIQ9bdRZCpEk8gMhj2xVAid1J0USvwbS/M/6gGLpJrxYFOqtxjuXOzxvk/q7B 4 | caBp/L1/A5bWAv75BUq1yotgNTqTBSh48Wmp48qpDk/cDfAnbBtIDO2dGaxSxLcF 5 | PDRMwxb9nkO9UKEyuALAeUhqo8c8RrXfzEJ7D6HwX+0hDnRSap8vtmhFDq3D6Uzx 6 | pY3wleIY8OxyXSPScggA4/iF82blv485yp5J8JMs1fTpYnAmJl+J/kdrNXI7zhU9 7 | SwrTAtJWIsJjVnl4+VH5SPWeTJ9RCrW4isL1IwIDAQABAoIBAEDspJkuAwHUMrsj 8 | wEH9a5HuBOIqqWmJkP8iCd8Ki9R9xos9EMD2rAlSiYBOEsg2JgQjs11N9kp/dLSW 9 | yuqFmD2TNgtnlDnwNjwTgS3ZaRAwLx6hA8LS/NFyKyQX2GGj1V3j3Ik806yRFaaJ 10 | CHaRbFlTmS1nOwav5/RLkq0ooTG+acGiONpgp393RmQesurFRmWB8MSTpWchZ+/z 11 | cqYOojm14QnoEQHBUUnY59yROXxezqYcbPkhC8qnGYwtS5mjVgQNM6+Y0cgFOryl 12 | MPH2r+Fkkd22obD18bIbSh8+pm8XHFG0e4Tswwsxp8w+u9JePih2qEF2YisZiRMJ 13 | wqMgfgECgYEA7HHxynsdzPPJ8rNme0smyhV3m6qnN74PHG2r54NfLHS9LAyOmHD8 14 | krgwf0T24m8+DRTEgF+53swR8ZCMv28FkK3A2TChhZI3NHwsoqNJf/7ZWwrnO5gI 15 | SEQN9LYdISsl76qttJizU99nQlVmIgTNAOJ4hHzp7G1IDo6dHS0MSaECgYEA5D4f 16 | TNvBJGMNP1Ui+kQUn3422NPZls5/no/wq/Z7GOzGmLKh3taqV41eiM1BnoS/OcLW 17 | vEmbl3lqOmkdV7msanZpjjjqAkv+ClO43hbl9sqa1LTta4nGtEg6sxS2PbCh/k2a 18 | tVL1ru38vszFK7FUl6loT9yaG5TrPxQOl1jNsEMCgYEA2winK6KntaA1eT6V9itl 19 | MJl4Zt1M8MeBKh2yvNInTYCLag3r3u30HFrCmnOhnZvdyLJvYljLT8iN6tC0gfZw 20 | GlnLp6d0Sc9skpNhqfxH72l/ouZT1RH+witBHmvCSmK1TvM23XED1vPCrWF9LpBx 21 | 9JrXeCxbayjFMq8MfuWnV2ECgYA/xHNuP79YcSwUU67wCPFSFiswrQ+PqKXTIRf2 22 | k2iU8CIUK2Q6I/N3fpG42s/IgAIFG0BvXolP6qYZJ6EBD2jyXZ7kE1adyalyLS3r 23 | Lq6VIsnbP6lNcDLJz5xGyDSaS60WpYvhuQnXE7qXfBJiQKsHrFbuaQ3NQu/usaXZ 24 | 9v+QjQKBgQDo2XmeKnD3y6fA/dGgEmkevNIovrH5SdYxEk3wUil8p+gszHeYeyos 25 | 3IC/Ul3VHSmER74hPkH68Lz9xjoyUTW+AVzkJpDZgHLzOTM8W5zf34XNWA4QWLn+ 26 | AbX49sEmh7zyEZWH7/F35V8LCffOnyWgdqlZxDRz1CbzlRWNANLOUA== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /pkg/apis/lbcf.tkestack.io/v1beta1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2015 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | "k8s.io/apimachinery/pkg/runtime" 22 | "k8s.io/apimachinery/pkg/runtime/schema" 23 | ) 24 | 25 | var SchemeGroupVersion = schema.GroupVersion{Group: "lbcf.tkestack.io", Version: "v1beta1"} 26 | 27 | var ( 28 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) 29 | AddToScheme = SchemeBuilder.AddToScheme 30 | ) 31 | 32 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 33 | func Resource(resource string) schema.GroupResource { 34 | return SchemeGroupVersion.WithResource(resource).GroupResource() 35 | } 36 | 37 | // Adds the list of known types to the given scheme. 38 | func addKnownTypes(scheme *runtime.Scheme) error { 39 | scheme.AddKnownTypes(SchemeGroupVersion, 40 | &LoadBalancer{}, 41 | &LoadBalancerList{}, 42 | &BackendGroup{}, 43 | &BackendGroupList{}, 44 | &LoadBalancerDriver{}, 45 | &LoadBalancerDriverList{}, 46 | &BackendRecord{}, 47 | &BackendRecordList{}, 48 | ) 49 | 50 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /pkg/client-go/informers/externalversions/internalinterfaces/factory_interfaces.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by informer-gen. DO NOT EDIT. 20 | 21 | package internalinterfaces 22 | 23 | import ( 24 | time "time" 25 | 26 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | runtime "k8s.io/apimachinery/pkg/runtime" 28 | cache "k8s.io/client-go/tools/cache" 29 | versioned "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned" 30 | ) 31 | 32 | // NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. 33 | type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer 34 | 35 | // SharedInformerFactory a small interface to allow for adding an informer without an import cycle 36 | type SharedInformerFactory interface { 37 | Start(stopCh <-chan struct{}) 38 | InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer 39 | } 40 | 41 | // TweakListOptionsFunc is a function that transforms a v1.ListOptions. 42 | type TweakListOptionsFunc func(*v1.ListOptions) 43 | -------------------------------------------------------------------------------- /pkg/client-go/informers/externalversions/lbcf.tkestack.io/v1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by informer-gen. DO NOT EDIT. 20 | 21 | package v1 22 | 23 | import ( 24 | internalinterfaces "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions/internalinterfaces" 25 | ) 26 | 27 | // Interface provides access to all the informers in this group version. 28 | type Interface interface { 29 | // Binds returns a BindInformer. 30 | Binds() BindInformer 31 | } 32 | 33 | type version struct { 34 | factory internalinterfaces.SharedInformerFactory 35 | namespace string 36 | tweakListOptions internalinterfaces.TweakListOptionsFunc 37 | } 38 | 39 | // New returns a new Interface. 40 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 41 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 42 | } 43 | 44 | // Binds returns a BindInformer. 45 | func (v *version) Binds() BindInformer { 46 | return &bindInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 47 | } 48 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1/fake/fake_lbcf.tkestack.io_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package fake 22 | 23 | import ( 24 | rest "k8s.io/client-go/rest" 25 | testing "k8s.io/client-go/testing" 26 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1" 27 | ) 28 | 29 | type FakeLbcfV1beta1 struct { 30 | *testing.Fake 31 | } 32 | 33 | func (c *FakeLbcfV1beta1) BackendGroups(namespace string) v1beta1.BackendGroupInterface { 34 | return &FakeBackendGroups{c, namespace} 35 | } 36 | 37 | func (c *FakeLbcfV1beta1) BackendRecords(namespace string) v1beta1.BackendRecordInterface { 38 | return &FakeBackendRecords{c, namespace} 39 | } 40 | 41 | func (c *FakeLbcfV1beta1) LoadBalancers(namespace string) v1beta1.LoadBalancerInterface { 42 | return &FakeLoadBalancers{c, namespace} 43 | } 44 | 45 | func (c *FakeLbcfV1beta1) LoadBalancerDrivers(namespace string) v1beta1.LoadBalancerDriverInterface { 46 | return &FakeLoadBalancerDrivers{c, namespace} 47 | } 48 | 49 | // RESTClient returns a RESTClient that is used to communicate 50 | // with API server by this client implementation. 51 | func (c *FakeLbcfV1beta1) RESTClient() rest.Interface { 52 | var ret *rest.RESTClient 53 | return ret 54 | } 55 | -------------------------------------------------------------------------------- /deployments/crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: loadbalancerdrivers.lbcf.tkestack.io 5 | spec: 6 | group: lbcf.tkestack.io 7 | names: 8 | kind: LoadBalancerDriver 9 | listKind: LoadBalancerDriverList 10 | plural: loadbalancerdrivers 11 | singular: loadbalancerdriver 12 | shortNames: 13 | - driver 14 | scope: Namespaced 15 | subresources: 16 | status: {} 17 | version: v1beta1 18 | --- 19 | apiVersion: apiextensions.k8s.io/v1beta1 20 | kind: CustomResourceDefinition 21 | metadata: 22 | name: loadbalancers.lbcf.tkestack.io 23 | spec: 24 | group: lbcf.tkestack.io 25 | names: 26 | kind: LoadBalancer 27 | listKind: LoadBalancerList 28 | plural: loadbalancers 29 | singular: loadbalancer 30 | shortNames: 31 | - lb 32 | scope: Namespaced 33 | subresources: 34 | status: {} 35 | version: v1beta1 36 | --- 37 | apiVersion: apiextensions.k8s.io/v1beta1 38 | kind: CustomResourceDefinition 39 | metadata: 40 | name: backendgroups.lbcf.tkestack.io 41 | spec: 42 | group: lbcf.tkestack.io 43 | names: 44 | kind: BackendGroup 45 | listKind: BackendGroupList 46 | plural: backendgroups 47 | singular: backendgroup 48 | shortNames: 49 | - bg 50 | scope: Namespaced 51 | subresources: 52 | status: {} 53 | version: v1beta1 54 | --- 55 | apiVersion: apiextensions.k8s.io/v1beta1 56 | kind: CustomResourceDefinition 57 | metadata: 58 | name: backendrecords.lbcf.tkestack.io 59 | spec: 60 | group: lbcf.tkestack.io 61 | names: 62 | kind: BackendRecord 63 | listKind: BackendRecordList 64 | plural: backendrecords 65 | singular: backendrecord 66 | shortNames: 67 | - br 68 | scope: Namespaced 69 | subresources: 70 | status: {} 71 | version: v1beta1 72 | 73 | --- 74 | 75 | apiVersion: apiextensions.k8s.io/v1beta1 76 | kind: CustomResourceDefinition 77 | metadata: 78 | name: binds.lbcf.tkestack.io 79 | spec: 80 | group: lbcf.tkestack.io 81 | names: 82 | kind: Bind 83 | listKind: BindList 84 | plural: binds 85 | singular: bind 86 | scope: Namespaced 87 | subresources: 88 | status: {} 89 | version: v1 90 | -------------------------------------------------------------------------------- /pkg/client-go/listers/lbcf.tkestack.io/v1beta1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by lister-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | // BackendGroupListerExpansion allows custom methods to be added to 24 | // BackendGroupLister. 25 | type BackendGroupListerExpansion interface{} 26 | 27 | // BackendGroupNamespaceListerExpansion allows custom methods to be added to 28 | // BackendGroupNamespaceLister. 29 | type BackendGroupNamespaceListerExpansion interface{} 30 | 31 | // BackendRecordListerExpansion allows custom methods to be added to 32 | // BackendRecordLister. 33 | type BackendRecordListerExpansion interface{} 34 | 35 | // BackendRecordNamespaceListerExpansion allows custom methods to be added to 36 | // BackendRecordNamespaceLister. 37 | type BackendRecordNamespaceListerExpansion interface{} 38 | 39 | // LoadBalancerListerExpansion allows custom methods to be added to 40 | // LoadBalancerLister. 41 | type LoadBalancerListerExpansion interface{} 42 | 43 | // LoadBalancerNamespaceListerExpansion allows custom methods to be added to 44 | // LoadBalancerNamespaceLister. 45 | type LoadBalancerNamespaceListerExpansion interface{} 46 | 47 | // LoadBalancerDriverListerExpansion allows custom methods to be added to 48 | // LoadBalancerDriverLister. 49 | type LoadBalancerDriverListerExpansion interface{} 50 | 51 | // LoadBalancerDriverNamespaceListerExpansion allows custom methods to be added to 52 | // LoadBalancerDriverNamespaceLister. 53 | type LoadBalancerDriverNamespaceListerExpansion interface{} 54 | -------------------------------------------------------------------------------- /pkg/client-go/informers/externalversions/lbcf.tkestack.io/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by informer-gen. DO NOT EDIT. 20 | 21 | package lbcf 22 | 23 | import ( 24 | internalinterfaces "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions/internalinterfaces" 25 | v1 "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions/lbcf.tkestack.io/v1" 26 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions/lbcf.tkestack.io/v1beta1" 27 | ) 28 | 29 | // Interface provides access to each of this group's versions. 30 | type Interface interface { 31 | // V1 provides access to shared informers for resources in V1. 32 | V1() v1.Interface 33 | // V1beta1 provides access to shared informers for resources in V1beta1. 34 | V1beta1() v1beta1.Interface 35 | } 36 | 37 | type group struct { 38 | factory internalinterfaces.SharedInformerFactory 39 | namespace string 40 | tweakListOptions internalinterfaces.TweakListOptionsFunc 41 | } 42 | 43 | // New returns a new Interface. 44 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 45 | return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 46 | } 47 | 48 | // V1 returns a new v1.Interface. 49 | func (g *group) V1() v1.Interface { 50 | return v1.New(g.factory, g.namespace, g.tweakListOptions) 51 | } 52 | 53 | // V1beta1 returns a new v1beta1.Interface. 54 | func (g *group) V1beta1() v1beta1.Interface { 55 | return v1beta1.New(g.factory, g.namespace, g.tweakListOptions) 56 | } 57 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/fake/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package fake 22 | 23 | import ( 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | runtime "k8s.io/apimachinery/pkg/runtime" 26 | schema "k8s.io/apimachinery/pkg/runtime/schema" 27 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 28 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 29 | lbcfv1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1" 30 | lbcfv1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 31 | ) 32 | 33 | var scheme = runtime.NewScheme() 34 | var codecs = serializer.NewCodecFactory(scheme) 35 | var parameterCodec = runtime.NewParameterCodec(scheme) 36 | var localSchemeBuilder = runtime.SchemeBuilder{ 37 | lbcfv1.AddToScheme, 38 | lbcfv1beta1.AddToScheme, 39 | } 40 | 41 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 42 | // of clientsets, like in: 43 | // 44 | // import ( 45 | // "k8s.io/client-go/kubernetes" 46 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 47 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 48 | // ) 49 | // 50 | // kclientset, _ := kubernetes.NewForConfig(c) 51 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 52 | // 53 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 54 | // correctly. 55 | var AddToScheme = localSchemeBuilder.AddToScheme 56 | 57 | func init() { 58 | v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) 59 | utilruntime.Must(AddToScheme(scheme)) 60 | } 61 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/scheme/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package scheme 22 | 23 | import ( 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | runtime "k8s.io/apimachinery/pkg/runtime" 26 | schema "k8s.io/apimachinery/pkg/runtime/schema" 27 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 28 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 29 | lbcfv1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1" 30 | lbcfv1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 31 | ) 32 | 33 | var Scheme = runtime.NewScheme() 34 | var Codecs = serializer.NewCodecFactory(Scheme) 35 | var ParameterCodec = runtime.NewParameterCodec(Scheme) 36 | var localSchemeBuilder = runtime.SchemeBuilder{ 37 | lbcfv1.AddToScheme, 38 | lbcfv1beta1.AddToScheme, 39 | } 40 | 41 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 42 | // of clientsets, like in: 43 | // 44 | // import ( 45 | // "k8s.io/client-go/kubernetes" 46 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 47 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 48 | // ) 49 | // 50 | // kclientset, _ := kubernetes.NewForConfig(c) 51 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 52 | // 53 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 54 | // correctly. 55 | var AddToScheme = localSchemeBuilder.AddToScheme 56 | 57 | func init() { 58 | v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) 59 | utilruntime.Must(AddToScheme(Scheme)) 60 | } 61 | -------------------------------------------------------------------------------- /docs/design/lbcf-architecture.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [设计目标](#设计目标) 4 | - [架构设计](#架构设计) 5 | 6 | 7 | 8 | ## 设计目标 9 | 10 | **LBCF**是专为Kubernetes平台操作负载均衡设计的通用框架,定位于对社区service-controller方案的增强,相较于社区的service-controller,LBCF具有以下特点: 11 | 12 | * 每个Pod可以独立绑定 13 | 14 | 不同于service-controller通过nodePort将多个Pod作为整体进行绑定的方式,LBCF可以将每个Pod独立绑定,因此,对于被操作的负载均衡而言,每一个被绑定的backend都只对应一个Pod 15 | 16 | * 兼容绑定Service NodePort 17 | 18 | LBCF兼容了使用Service NodePort的绑定方式,但与service-controller不同的是,使用LBCF绑定的Service NodePort地址可以与其他地址共享同一个负载均衡 19 | 20 | * 支持负载均衡共享 21 | 22 | 不论是Pod独立绑定还是使用Service NodePort,LBCF都能支持负载均衡的共享。原因在于LBCF不以全量diff的方式决定需要进行的绑定/解绑操作,而是为每个需要绑定的backend(Pod或NodePort)单独维护绑定任务,这使得LBCF在进行绑定与解绑操作时不会影响到相同LB下的其他backend,从而可以实现LB的共享 23 | 24 | * 灵活的扩展 25 | 26 | LBCF对容器生命周期中的各种事件进行了封装,并以Webhook的方式对外暴露,开发者只需按照[LBCF Webhook规范](lbcf-webhook-specification.md)的要求实现一个Webhook服务器即可完成对负载均衡的定制化控制 27 | 28 | * 异步操作 29 | 30 | 对于一些耗时较长的操作(如创建负载均衡),开发者可以将操作以异步方式实现,LBCF支持操作结果的循环查询 31 | 32 | * 优化的交互逻辑 33 | 34 | service-controller在交互逻辑上存在一些弊病,如:无法拒绝非法请求、难以直观观察绑定状态、信息反馈过度依赖自身日志等。 35 | 36 | LBCF对上述缺点进行了针对性的优化设计,如:支持使用者进行请求的校验、以Events的方式对外输webhook调用结果、使用status.condition记录当前状态等。使用者无需了解LBCF内部实现即可进行系统调试与二次开发。 37 | 38 | 39 | ## 架构设计 40 | 41 | ![](media/lbcf-arch.png) 42 | 43 | LBCF架构中,负载均衡操作由两部分协同完成,分别为执行统一管理逻辑的lbcf-controller与执行自定义操作逻辑的Webhook server,二者之间使用[LBCF Webhook规范](lbcf-webhook-specification.md)进行通信。 44 | 45 | * lbcf-controller 46 | 47 | lbcf-controller将负载均衡的管理抽象为8个统一操作,分别对应[LBCF Webhook规范](lbcf-webhook-specification.md)中的8个webhook, lbcf-controller对每次webhook的调用时机、调用结果以及重试策略进行管理。 48 | 49 | 由于lbcf-controller会将webhook的调用结果持久化保存至K8S,因此Webhook server可以是无状态的。 50 | 51 | * Webhook server 52 | 53 | Webhook server的作用类似于操作系统中的硬件驱动程序,外部负载均衡/名字服务即是接入操作系统的各种硬件,Webhook server接收来自操作系统(LBCF)的统一指令(Webhook调用),进行自定义操作后返回统一格式的操作结果。 54 | 55 | LBCF定义了4种CRD,其中3种用来进行用户交互,1种用来保存系统当前状态: 56 | 57 | * LoadBalancerDriver 58 | 59 | LoadBalancerDriver用来描述Webhook server,包括server的地址、每种webhook的超时时间等 60 | 61 | * LoadBalancer 62 | 63 | LoadBalancer用来描述被操作的负载均衡,包括负载均衡的唯一标识(如lbID)、使用的属性(如健康检查、会话保持)等 64 | 65 | LoadBalancer中的字段由Webhook server实现者定义,并由Webhook server进行解析 66 | 67 | * BackendGroup 68 | 69 | BackendGroup用来描述被操作的backend,分为Pod、Service以及静态地址3中类型,Webhook server实现方可以在BackendGroup中定义绑定操作使用的额外参数(如权重) 70 | 71 | * BackendRecord 72 | 73 | BackendRecord由lbcf-controller根据提交到K8S的上述3中CRD自动生成,用来保存每个负载均衡backend的当前状态,如绑定使用的参数、绑定结果等 74 | 75 | 4种CRD的详细定义见[LBCF CRD定义](lbcf-crd.md)) 76 | 77 | -------------------------------------------------------------------------------- /cmd/lbcf-controller/app/config/config.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack available. 3 | * 4 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 7 | * this file except in compliance with the License. You may obtain a copy of the 8 | * License at 9 | * 10 | * https://opensource.org/licenses/Apache-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations under the License. 16 | */ 17 | 18 | package config 19 | 20 | import ( 21 | "time" 22 | 23 | flag "github.com/spf13/pflag" 24 | ) 25 | 26 | type Config struct { 27 | InformerResyncPeriod time.Duration 28 | MinRetryDelay time.Duration 29 | RetryDelayStep time.Duration 30 | MaxRetryDelay time.Duration 31 | KubeConfig string 32 | ServerCrt string 33 | ServerKey string 34 | DryRun bool 35 | ClientQPS float32 36 | ClientBurst int 37 | } 38 | 39 | func NewConfig() *Config { 40 | return &Config{} 41 | } 42 | 43 | func (o *Config) AddFlags(fs *flag.FlagSet) { 44 | fs.DurationVar(&o.InformerResyncPeriod, "informer-resync-period", 1*time.Minute, "resync period for informers") 45 | fs.DurationVar(&o.MinRetryDelay, "min-retry-delay", 5*time.Second, "minimum retry delay for failed webhook calls") 46 | fs.DurationVar(&o.RetryDelayStep, "retry-delay-step", 10*time.Second, "the value added to retry delay for each webhook failure") 47 | fs.DurationVar(&o.MaxRetryDelay, "max-retry-delay", 2*time.Minute, "maximum retry delay for failed webhook calls") 48 | fs.StringVar(&o.KubeConfig, "kubeconfig", "", "Path to kubeconfig file with authorization information") 49 | fs.StringVar(&o.ServerCrt, "server-crt", "/etc/lbcf/server.crt", "Path to crt file for admit webhook server") 50 | fs.StringVar(&o.ServerKey, "server-key", "/etc/lbcf/server.key", "Path to key file for admit webhook server") 51 | fs.BoolVar(&o.DryRun, "dry-run", false, "If true, only print the webhooks that would be invoked, without invoking them") 52 | fs.Float32Var(&o.ClientQPS, "client-qps", 200, "qps of lbcf client") 53 | fs.IntVar(&o.ClientBurst, "client-burst", 400, "burst of lbcf client") 54 | } 55 | -------------------------------------------------------------------------------- /pkg/version/version.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack available. 3 | * 4 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 7 | * this file except in compliance with the License. You may obtain a copy of the 8 | * License at 9 | * 10 | * https://opensource.org/licenses/Apache-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations under the License. 16 | * 17 | */ 18 | 19 | package version 20 | 21 | import ( 22 | "encoding/json" 23 | "fmt" 24 | "os" 25 | "runtime" 26 | 27 | flag "github.com/spf13/pflag" 28 | ) 29 | 30 | var ( 31 | // GitVersion is semantic version. 32 | GitVersion = "v0.0.0-master+$Format:%h$" 33 | // GitCommit sha1 from git, output of $(git rev-parse HEAD) 34 | GitCommit = "$Format:%H$" 35 | // GitTreeState state of git tree, either "clean" or "dirty" 36 | GitTreeState = "" 37 | // BuildDate in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') 38 | BuildDate = "1970-01-01T00:00:00Z" 39 | 40 | versionFlag bool 41 | ) 42 | 43 | func init() { 44 | flag.BoolVar(&versionFlag, "version", false, "Print version information and quit") 45 | } 46 | 47 | // PrintAndExitIfRequested will check if the -version flag was passed 48 | // and, if so, print the version and exit. 49 | func PrintAndExitIfRequested() { 50 | if versionFlag { 51 | fmt.Println(Get().String()) 52 | os.Exit(0) 53 | } 54 | } 55 | 56 | type Info struct { 57 | GitVersion string `json:"gitVersion"` 58 | GitCommit string `json:"gitCommit"` 59 | GitTreeState string `json:"gitTreeState"` 60 | BuildDate string `json:"buildDate"` 61 | GoVersion string `json:"goVersion"` 62 | Compiler string `json:"compiler"` 63 | Platform string `json:"platform"` 64 | } 65 | 66 | func (i Info) String() string { 67 | b, err := json.MarshalIndent(i, "", " ") 68 | if err != nil { 69 | return err.Error() 70 | } 71 | return string(b) 72 | } 73 | 74 | func Get() Info { 75 | return Info{ 76 | GitVersion: GitVersion, 77 | GitCommit: GitCommit, 78 | GitTreeState: GitTreeState, 79 | BuildDate: BuildDate, 80 | GoVersion: runtime.Version(), 81 | Compiler: runtime.Compiler, 82 | Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH), 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /cmd/lbcf-controller/app/server.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack available. 3 | * 4 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 7 | * this file except in compliance with the License. You may obtain a copy of the 8 | * License at 9 | * 10 | * https://opensource.org/licenses/Apache-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations under the License. 16 | */ 17 | 18 | package app 19 | 20 | import ( 21 | goflag "flag" 22 | "net/http" 23 | "os" 24 | 25 | "tkestack.io/lb-controlling-framework/cmd/lbcf-controller/app/config" 26 | "tkestack.io/lb-controlling-framework/cmd/lbcf-controller/app/context" 27 | "tkestack.io/lb-controlling-framework/pkg/lbcfcontroller" 28 | "tkestack.io/lb-controlling-framework/pkg/lbcfcontroller/admission" 29 | "tkestack.io/lb-controlling-framework/pkg/version" 30 | 31 | "github.com/prometheus/client_golang/prometheus/promhttp" 32 | "github.com/spf13/cobra" 33 | "github.com/spf13/pflag" 34 | "k8s.io/apimachinery/pkg/util/wait" 35 | "k8s.io/klog" 36 | ) 37 | 38 | func NewServer() *cobra.Command { 39 | cfg := config.NewConfig() 40 | rootCmd := &cobra.Command{ 41 | Use: "lbcf-controller", 42 | Run: func(cmd *cobra.Command, args []string) { 43 | version.PrintAndExitIfRequested() 44 | printFlags(cmd.Flags()) 45 | 46 | ctx := context.NewContext(cfg) 47 | admissionWebhookServer := admission.NewWebhookServer(ctx, cfg.ServerCrt, cfg.ServerKey) 48 | lbcf := lbcfcontroller.NewController(ctx) 49 | 50 | ctx.Start() 51 | admissionWebhookServer.Start() 52 | lbcf.Start() 53 | 54 | mux := http.NewServeMux() 55 | mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { 56 | w.Write([]byte("ok")) 57 | }) 58 | mux.Handle("/metrics", promhttp.Handler()) 59 | go http.ListenAndServe(":11029", mux) 60 | 61 | <-wait.NeverStop 62 | }, 63 | } 64 | 65 | fs := goflag.NewFlagSet(os.Args[0], goflag.ExitOnError) 66 | klog.InitFlags(fs) 67 | rootCmd.Flags().AddGoFlagSet(fs) 68 | cfg.AddFlags(rootCmd.Flags()) 69 | return rootCmd 70 | } 71 | 72 | func printFlags(fs *pflag.FlagSet) { 73 | klog.Infof("Using flags:") 74 | fs.VisitAll(func(flag *pflag.Flag) { 75 | klog.Infof("\t%s: %s", flag.Name, flag.Value.String()) 76 | }) 77 | } 78 | -------------------------------------------------------------------------------- /docs/design/lbcf-consistency-design.md: -------------------------------------------------------------------------------- 1 | # Issues of common controllers 2 | Many controllers are developed based on K8S service controller, these controllers have several issues: 3 | 1. When the Service was delete and the controller some how missed the event, such as the controller was down, the controller will never know which load balancer it was handling, and the Pods will not be deregistered. 4 | 2. Pods under a service can NOT share the load balancers with servers from other environment. Since the controller keeps comparing endpoints in K8S cluster and servers in the load balancer, it keeps deleting all servers that not in the endpoint list. 5 | 3. One can NOT manipulate the load balancer manually. If the controller makes a mistake, the mistake is kept until the controller is killed, for the controller periodically sync the load balancer servers with endpoints in the K8S cluster. 6 | 7 | Some controllers tries to solve above issues by watching and reacting to events, which is unreliable because events in K8S are never re-sent. Once the controller got killed or hangs, the events are lost forever. 8 | 9 | # Solution of LBCF 10 | There are several goals LBCF aims to achieve: 11 | 1. Pods can share load balacers with other Pods or other servers 12 | 2. Manually manipulating the load balancers should be allowed 13 | 3. The LBCF controller is allowed to be killed at any time 14 | 4. The LBCF controller should make every thing right after it started 15 | 16 | The following figure shows how LBCF do it. 17 | 18 | ![LBCF keeps pod information in BackendRecords](/docs/design/media/lbcf-consistency.png) 19 | 20 | STAGE 1: LBCF controller create a `BackendRecord` for each `Ready` Pod, all the information that is used to register the pod to the load balancer is stored in the `BackendRecord`. Furthermore, all `BackendRecord`s have `finalizer` set, which makes them can't be deleted before dereigstering is done. 21 | 22 | STAGE 2: Suppose the LBCF controller is killed and Pod 2 was deleted before LBCF controller restarted. Even though LBCF controller will not receive any events that indicate Pod 2 was deleted, it can still realize it by not able to find Pod 2 in the cluster. (LBCF knows there should be Pod 2 because it is recorded in the `BackendGroup`) 23 | 24 | STAGE 3: Once LBCF controller realized Pod 2 was gone, it tries to delete `BR2`. The deleting is blocked, for there is a finalizer on BR 2. LBCF controller watches all `BackendRecord`s, and start the deregistering process once it finds the `deletionTimestamp` is set. 25 | 26 | STAGE 4: Once the deregistering process is finished, LBCF controller delete the finalizer on the `BackendGroup` so that it will be GC by K8S. -------------------------------------------------------------------------------- /CHANGELOG/CHANGELOG-1.3.0.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [v1.3.0](#v130) 4 | - [Changelog since v1.2.0](#changelog-since-v120) 5 | - [Features:](#features) 6 | 7 | 8 | 9 | # v1.3.0 10 | ## Changelog since v1.2.0 11 | 12 | ### Features: 13 | 14 | * `Added`: two new metrics. [#51e6f](https://github.com/tkestack/lb-controlling-framework/commit/51e6f407e31a1a39e2f8e0e4938b27627c390ea7), [#82c8d](https://github.com/tkestack/lb-controlling-framework/commit/82c8d7da9a0fcfcb81946de972908f06ecd36a38), [proposal](/docs/design/proposal/metrics.md) 15 | * `Added`: deregister policy, users may define a pod deregistering policy other than K8S, which deregisters a pod if it's not ready. [proposal](/docs/design/proposal/deregister-policy.md) 16 | 17 | There are 3 available policies in LBCF: 18 | * `IfNotReady`: The default policy, same as K8S, pods are deregistered if `pod.status.condition[].Ready` is not `True` 19 | * `IfNotRunning`: Pods are deregistered if `pod.status.phase` is not `Running`. [#618c9](https://github.com/tkestack/lb-controlling-framework/commit/618c9c16414e70107474265ed71120c2fd396abe) 20 | * `Webhook`: A hightly customizable policy, driver developers may implement their own policy based on Pod. [#3a6c1](https://github.com/tkestack/lb-controlling-framework/commit/3a6c12529d297b7a3f76d9b87b39c5a4de312c72), [#9c037](https://github.com/tkestack/lb-controlling-framework/commit/9c0370290a116ad8c145d65994f57ac170abad37), [#6cd79](https://github.com/tkestack/lb-controlling-framework/commit/6cd7951fadc8a11948b7d68a9a3125c5581111ae), [#ab517](https://github.com/tkestack/lb-controlling-framework/commit/ab517ebecc07ae3e89f0d6cc8f9ab5d57a949873), [#bc406](https://github.com/tkestack/lb-controlling-framework/commit/bc40676818d5ae764c9cb39c7965a896aeebe0d7), [#43751](https://github.com/tkestack/lb-controlling-framework/commit/4375126156f5b54cbd2724936fc10e1962a01e15), [#4ca73](https://github.com/tkestack/lb-controlling-framework/commit/4ca73a2d4416a66ca61a194c2324e05a2d334342) 21 | 22 | * `Added`: allow user specified path prefix in webhook calls. [#1cebb](https://github.com/tkestack/lb-controlling-framework/commit/1cebb40515d2ec5ebf3593e1ed288664ec59e3c2) 23 | 24 | ### Other changes: 25 | * `Fixed`: set portNumber in generateBackendAddr webhook request. [#1ae6a](https://github.com/tkestack/lb-controlling-framework/commit/1ae6ab13736f2d1c174ae55d97c36f3845b09038) 26 | * `Fixed`: deleteBackendRecord handles not found error. [#447c1](https://github.com/tkestack/lb-controlling-framework/commit/447c17a078e95e6fff9c1549d43335890e1c3742) 27 | * `Fixed`: registered backend not enqueued in add event & backendrecord update triggers ensureBackend webhook. [#1e55e](https://github.com/tkestack/lb-controlling-framework/commit/1e55e330043fecad9c110723b3f81107f904d03d) 28 | 29 | 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Tencent is pleased to support the open source community by making TKEStack 2 | # available. 3 | # 4 | # Copyright (C) 2012-2019 Tencent. All Rights Reserved. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use 7 | # this file except in compliance with the License. You may obtain a copy of the 8 | # License at 9 | # 10 | # https://opensource.org/licenses/Apache-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | # WARRANTIES OF ANY KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations under the License. 16 | 17 | .PHONY: all 18 | all: test build 19 | 20 | # ============================================================================== 21 | # Build options 22 | 23 | ROOT_PACKAGE=tkestack.io/lb-controlling-framework 24 | VERSION_PACKAGE=tkestack.io/lb-controlling-framework/pkg/version 25 | 26 | # ============================================================================== 27 | # Includes 28 | 29 | include build/lib/common.mk 30 | include build/lib/golang.mk 31 | include build/lib/image.mk 32 | include build/lib/gen.mk 33 | 34 | # ============================================================================== 35 | # Usage 36 | 37 | define USAGE_OPTIONS 38 | 39 | Options: 40 | DEBUG Whether to generate debug symbols. Default is 0. 41 | IMAGES Backend images to make. All by default. 42 | PLATFORMS The platform to build. Default is host platform and arch. 43 | BINS The binaries to build. Default is all of cmd. 44 | VERSION The version information compiled into binaries. 45 | The default is obtained from git. 46 | V Set to 1 enable verbose build. Default is 0. 47 | endef 48 | export USAGE_OPTIONS 49 | 50 | # ============================================================================== 51 | # Targets 52 | 53 | ## gen: Generate codes for API definitions. 54 | .PHONY: gen 55 | gen: 56 | @$(MAKE) gen.run 57 | 58 | ## build: Build source code for host platform. 59 | .PHONY: build 60 | build: 61 | @$(MAKE) go.build 62 | 63 | ## build.all: Build source code for all platforms. 64 | .PHONY: build.all 65 | build.all: 66 | @$(MAKE) go.build.all 67 | 68 | ## image: Build docker images. 69 | .PHONY: image 70 | image: 71 | @$(MAKE) image.build 72 | 73 | ## push: Build docker images and push to registry. 74 | .PHONY: push 75 | push: 76 | @$(MAKE) image.push 77 | 78 | ## lint: Check syntax and styling of go sources. 79 | .PHONY: lint 80 | lint: 81 | @$(MAKE) go.lint 82 | 83 | ## test: Run unit test. 84 | .PHONY: test 85 | test: 86 | @$(MAKE) go.test 87 | 88 | .PHONY: help 89 | help: Makefile 90 | @echo -e "\nUsage: make ...\n\nTargets:" 91 | @sed -n 's/^##//p' $< | column -t -s ':' | sed -e 's/^/ /' 92 | @echo "$$USAGE_OPTIONS" 93 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1/lbcf.tkestack.io_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package v1 22 | 23 | import ( 24 | rest "k8s.io/client-go/rest" 25 | v1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1" 26 | "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned/scheme" 27 | ) 28 | 29 | type LbcfV1Interface interface { 30 | RESTClient() rest.Interface 31 | BindsGetter 32 | } 33 | 34 | // LbcfV1Client is used to interact with features provided by the lbcf.tkestack.io group. 35 | type LbcfV1Client struct { 36 | restClient rest.Interface 37 | } 38 | 39 | func (c *LbcfV1Client) Binds(namespace string) BindInterface { 40 | return newBinds(c, namespace) 41 | } 42 | 43 | // NewForConfig creates a new LbcfV1Client for the given config. 44 | func NewForConfig(c *rest.Config) (*LbcfV1Client, error) { 45 | config := *c 46 | if err := setConfigDefaults(&config); err != nil { 47 | return nil, err 48 | } 49 | client, err := rest.RESTClientFor(&config) 50 | if err != nil { 51 | return nil, err 52 | } 53 | return &LbcfV1Client{client}, nil 54 | } 55 | 56 | // NewForConfigOrDie creates a new LbcfV1Client for the given config and 57 | // panics if there is an error in the config. 58 | func NewForConfigOrDie(c *rest.Config) *LbcfV1Client { 59 | client, err := NewForConfig(c) 60 | if err != nil { 61 | panic(err) 62 | } 63 | return client 64 | } 65 | 66 | // New creates a new LbcfV1Client for the given RESTClient. 67 | func New(c rest.Interface) *LbcfV1Client { 68 | return &LbcfV1Client{c} 69 | } 70 | 71 | func setConfigDefaults(config *rest.Config) error { 72 | gv := v1.SchemeGroupVersion 73 | config.GroupVersion = &gv 74 | config.APIPath = "/apis" 75 | config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() 76 | 77 | if config.UserAgent == "" { 78 | config.UserAgent = rest.DefaultKubernetesUserAgent() 79 | } 80 | 81 | return nil 82 | } 83 | 84 | // RESTClient returns a RESTClient that is used to communicate 85 | // with API server by this client implementation. 86 | func (c *LbcfV1Client) RESTClient() rest.Interface { 87 | if c == nil { 88 | return nil 89 | } 90 | return c.restClient 91 | } 92 | -------------------------------------------------------------------------------- /pkg/lbcfcontroller/driver_controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack available. 3 | * 4 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 7 | * this file except in compliance with the License. You may obtain a copy of the 8 | * License at 9 | * 10 | * https://opensource.org/licenses/Apache-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations under the License. 16 | */ 17 | 18 | package lbcfcontroller 19 | 20 | import ( 21 | lbcfapi "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 22 | lbcfclient "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned" 23 | "tkestack.io/lb-controlling-framework/pkg/client-go/listers/lbcf.tkestack.io/v1beta1" 24 | "tkestack.io/lb-controlling-framework/pkg/lbcfcontroller/util" 25 | 26 | "k8s.io/apimachinery/pkg/api/errors" 27 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 | "k8s.io/client-go/tools/cache" 29 | ) 30 | 31 | func newDriverController(client lbcfclient.Interface, lister v1beta1.LoadBalancerDriverLister, dryRun bool) *driverController { 32 | return &driverController{ 33 | lbcfClient: client, 34 | lister: lister, 35 | dryRun: dryRun, 36 | } 37 | } 38 | 39 | type driverController struct { 40 | lbcfClient lbcfclient.Interface 41 | lister v1beta1.LoadBalancerDriverLister 42 | dryRun bool 43 | } 44 | 45 | func (c *driverController) syncDriver(key string) *util.SyncResult { 46 | namespace, name, err := cache.SplitMetaNamespaceKey(key) 47 | if err != nil { 48 | return util.ErrorResult(err) 49 | } 50 | driver, err := c.lister.LoadBalancerDrivers(namespace).Get(name) 51 | if errors.IsNotFound(err) { 52 | return util.FinishedResult() 53 | } else if err != nil { 54 | return util.ErrorResult(err) 55 | } 56 | 57 | if driver.DeletionTimestamp != nil { 58 | return util.FinishedResult() 59 | } 60 | 61 | // in dry-run mode, status of the driver will not be updated 62 | if c.dryRun { 63 | return util.FinishedResult() 64 | } 65 | 66 | // update driver status 67 | if len(driver.Status.Conditions) == 0 { 68 | driver.Status = lbcfapi.LoadBalancerDriverStatus{ 69 | Conditions: []lbcfapi.LoadBalancerDriverCondition{ 70 | { 71 | Type: lbcfapi.DriverAccepted, 72 | Status: lbcfapi.ConditionTrue, 73 | LastTransitionTime: v1.Now(), 74 | }, 75 | }, 76 | } 77 | _, err := c.lbcfClient.LbcfV1beta1().LoadBalancerDrivers(namespace).UpdateStatus(driver) 78 | if err != nil { 79 | return util.ErrorResult(err) 80 | } 81 | return util.FinishedResult() 82 | } 83 | return util.FinishedResult() 84 | } 85 | -------------------------------------------------------------------------------- /pkg/client-go/informers/externalversions/lbcf.tkestack.io/v1beta1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by informer-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | internalinterfaces "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions/internalinterfaces" 25 | ) 26 | 27 | // Interface provides access to all the informers in this group version. 28 | type Interface interface { 29 | // BackendGroups returns a BackendGroupInformer. 30 | BackendGroups() BackendGroupInformer 31 | // BackendRecords returns a BackendRecordInformer. 32 | BackendRecords() BackendRecordInformer 33 | // LoadBalancers returns a LoadBalancerInformer. 34 | LoadBalancers() LoadBalancerInformer 35 | // LoadBalancerDrivers returns a LoadBalancerDriverInformer. 36 | LoadBalancerDrivers() LoadBalancerDriverInformer 37 | } 38 | 39 | type version struct { 40 | factory internalinterfaces.SharedInformerFactory 41 | namespace string 42 | tweakListOptions internalinterfaces.TweakListOptionsFunc 43 | } 44 | 45 | // New returns a new Interface. 46 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 47 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 48 | } 49 | 50 | // BackendGroups returns a BackendGroupInformer. 51 | func (v *version) BackendGroups() BackendGroupInformer { 52 | return &backendGroupInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 53 | } 54 | 55 | // BackendRecords returns a BackendRecordInformer. 56 | func (v *version) BackendRecords() BackendRecordInformer { 57 | return &backendRecordInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 58 | } 59 | 60 | // LoadBalancers returns a LoadBalancerInformer. 61 | func (v *version) LoadBalancers() LoadBalancerInformer { 62 | return &loadBalancerInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 63 | } 64 | 65 | // LoadBalancerDrivers returns a LoadBalancerDriverInformer. 66 | func (v *version) LoadBalancerDrivers() LoadBalancerDriverInformer { 67 | return &loadBalancerDriverInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 68 | } 69 | -------------------------------------------------------------------------------- /pkg/client-go/informers/externalversions/generic.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by informer-gen. DO NOT EDIT. 20 | 21 | package externalversions 22 | 23 | import ( 24 | "fmt" 25 | 26 | schema "k8s.io/apimachinery/pkg/runtime/schema" 27 | cache "k8s.io/client-go/tools/cache" 28 | v1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1" 29 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 30 | ) 31 | 32 | // GenericInformer is type of SharedIndexInformer which will locate and delegate to other 33 | // sharedInformers based on type 34 | type GenericInformer interface { 35 | Informer() cache.SharedIndexInformer 36 | Lister() cache.GenericLister 37 | } 38 | 39 | type genericInformer struct { 40 | informer cache.SharedIndexInformer 41 | resource schema.GroupResource 42 | } 43 | 44 | // Informer returns the SharedIndexInformer. 45 | func (f *genericInformer) Informer() cache.SharedIndexInformer { 46 | return f.informer 47 | } 48 | 49 | // Lister returns the GenericLister. 50 | func (f *genericInformer) Lister() cache.GenericLister { 51 | return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) 52 | } 53 | 54 | // ForResource gives generic access to a shared informer of the matching type 55 | // TODO extend this to unknown resources with a client pool 56 | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { 57 | switch resource { 58 | // Group=lbcf.tkestack.io, Version=v1 59 | case v1.SchemeGroupVersion.WithResource("binds"): 60 | return &genericInformer{resource: resource.GroupResource(), informer: f.Lbcf().V1().Binds().Informer()}, nil 61 | 62 | // Group=lbcf.tkestack.io, Version=v1beta1 63 | case v1beta1.SchemeGroupVersion.WithResource("backendgroups"): 64 | return &genericInformer{resource: resource.GroupResource(), informer: f.Lbcf().V1beta1().BackendGroups().Informer()}, nil 65 | case v1beta1.SchemeGroupVersion.WithResource("backendrecords"): 66 | return &genericInformer{resource: resource.GroupResource(), informer: f.Lbcf().V1beta1().BackendRecords().Informer()}, nil 67 | case v1beta1.SchemeGroupVersion.WithResource("loadbalancers"): 68 | return &genericInformer{resource: resource.GroupResource(), informer: f.Lbcf().V1beta1().LoadBalancers().Informer()}, nil 69 | case v1beta1.SchemeGroupVersion.WithResource("loadbalancerdrivers"): 70 | return &genericInformer{resource: resource.GroupResource(), informer: f.Lbcf().V1beta1().LoadBalancerDrivers().Informer()}, nil 71 | 72 | } 73 | 74 | return nil, fmt.Errorf("no informer found for %v", resource) 75 | } 76 | -------------------------------------------------------------------------------- /pkg/lbcfcontroller/driver_controller_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 THL A29 Limited, a Tencent company. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package lbcfcontroller 18 | 19 | import ( 20 | "fmt" 21 | "testing" 22 | 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | "k8s.io/client-go/tools/cache" 25 | "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned/fake" 26 | 27 | lbcfapi "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 28 | ) 29 | 30 | func TestDriverControllerSyncDriverCreate(t *testing.T) { 31 | driver := newFakeDriver("kube-system", fmt.Sprintf("%s%s", lbcfapi.SystemDriverPrefix, "driver")) 32 | 33 | key, _ := cache.DeletionHandlingMetaNamespaceKeyFunc(driver) 34 | ctrl := newDriverController( 35 | fake.NewSimpleClientset(driver), 36 | &fakeDriverLister{ 37 | get: driver, 38 | }, 39 | false) 40 | result := ctrl.syncDriver(key) 41 | if !result.IsFinished() { 42 | t.Logf("%v", result.GetFailReason()) 43 | t.Fatalf("expect succ result, get %#v", result) 44 | } 45 | } 46 | 47 | func TestDriverControllerSyncDriverAccepted(t *testing.T) { 48 | driver := newFakeDriver("kube-system", fmt.Sprintf("%s%s", lbcfapi.SystemDriverPrefix, "driver")) 49 | driver.Status = lbcfapi.LoadBalancerDriverStatus{ 50 | Conditions: []lbcfapi.LoadBalancerDriverCondition{ 51 | { 52 | Type: lbcfapi.DriverAccepted, 53 | Status: lbcfapi.ConditionTrue, 54 | }, 55 | }, 56 | } 57 | key, _ := cache.DeletionHandlingMetaNamespaceKeyFunc(driver) 58 | ctrl := newDriverController( 59 | fake.NewSimpleClientset(), 60 | &fakeDriverLister{ 61 | get: driver, 62 | }, 63 | false) 64 | result := ctrl.syncDriver(key) 65 | if !result.IsFinished() { 66 | t.Logf("%v", result.GetFailReason()) 67 | t.Fatalf("expect succ result, get %#v", result) 68 | } 69 | } 70 | 71 | func TestDriverControllerSyncDriverNotFound(t *testing.T) { 72 | driver := newFakeDriver("kube-system", fmt.Sprintf("%s%s", lbcfapi.SystemDriverPrefix, "driver")) 73 | 74 | key, _ := cache.DeletionHandlingMetaNamespaceKeyFunc(driver) 75 | ctrl := newDriverController(fake.NewSimpleClientset(), &fakeDriverLister{}, false) 76 | result := ctrl.syncDriver(key) 77 | if !result.IsFinished() { 78 | t.Fatalf("expect succ result, get %v", result) 79 | } 80 | } 81 | 82 | func TestDriverControllerSyncDriverDeleting(t *testing.T) { 83 | driver := newFakeDriver("kube-system", fmt.Sprintf("%s%s", lbcfapi.SystemDriverPrefix, "driver")) 84 | ts := metav1.Now() 85 | driver.DeletionTimestamp = &ts 86 | 87 | key, _ := cache.DeletionHandlingMetaNamespaceKeyFunc(driver) 88 | ctrl := newDriverController( 89 | fake.NewSimpleClientset(), 90 | &fakeDriverLister{ 91 | get: driver, 92 | }, 93 | false) 94 | result := ctrl.syncDriver(key) 95 | if !result.IsFinished() { 96 | t.Fatalf("expect succ result, get %v", result) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Load Balancer Controlling Framework (LBCF) 2 | 3 | LBCF是一款部署在Kubernetes内的通用负载均衡控制面框架,实现了可靠的一致性保证与灵活的扩展接口。通过实现LBCF提供的扩展接口,您可以快速实现可靠的负载均衡/名字服务对接。 4 | 5 | LBCF自上线以来,没有发生过容器的错误绑定或错误解绑,这一切都源自LBCF设计了可靠的一致性保证机制,详见文档: [LBCF的一致性保证](/docs/design/lbcf-consistency-design.md) 6 | 7 | 可扩展性是LBCF的核心,为此,LBCF针对负载均衡操作特点,在Pod生命周期中设计了9个可实现自定义逻辑的Webhook,webhook定义见文档:[LBCF CRD设计](/docs/design/lbcf-crd.md) 8 | 9 | --- 10 | 11 | ## 安装LBCF 12 | 13 | 见文档:[安装LBCF](/docs/install.md) 14 | 15 | --- 16 | ## 基于LBCF实现业务逻辑 17 | 得益于LBCF的可靠性与扩展能力,我们的用户实现了众多高度定制化的业务需求。在使用LBCF前,这些需求往往需要单独开发controller,并经过漫长的周期才能逐渐稳定。 18 | 19 | ### 将Pod注册至第三方系统(负载均衡/名字服务/其他) 20 | 标题中提到的"第三方系统"并不特指任何系统,只要其提供了API,并且业务需求符合"Pod启动时注册,Pod结束时注销"的行为模式,就都可以使用LBCF。LBCF的一些用户就实现了将Pod注册至自己内部系统的功能。 21 | 22 | #### Pod生命周期监听 23 | 使用LBCF后,您无需自行实现Pod生命周期的监听,您只需在接收端(在LBCF中称为Driver)实现自己的业务逻辑即可。LBCF会在以下时刻触发Webhook: 24 | * Pod非Ready --> Pod Ready 25 | * Pod Ready --> Pod非Ready 26 | * Pod 被设置`deletionTimestamp` 27 | * Pod Ready,但不再被用户指定为需要注册 28 | * Pod Ready,并重新被用户指定为需要注册 29 | PS: 当Pod发生扩/缩容时,LBCF也会自动响应。 30 | 31 | #### 调用第三方API 32 | 当Webhook触发时,Webhook请求中会携带相关Pod的信息,您可以按需进行信息处理与第三方API调用: 33 | [generateBackendAddr](/docs/design/lbcf-webhook-specification.md#generatebackendaddr): 用于生成注册Pod时使用的参数 34 | [ensureBackend](/docs/design/lbcf-webhook-specification.md#ensurebackend): 用于将`generateBackendAddr`生成的参数注册至第三方系统 35 | [deregisterBackend](/docs/design/lbcf-webhook-specification.md#deregisterbackend): 用于将`generateBackendAddr`生成的参数从第三方系统注销 36 | 37 | #### 第三方系统的自定义参数 38 | 调用第三方系统API时必然要填写一些系统相关参数,这些参数不可能完全来自K8S。因此,LBCF允许Driver实现自定义参数,并支持Driver对用户输入进行校验。 39 | 40 | #### 面向平台使用者的系统运维 41 | 阅读系统日志是困难且痛苦的,为此,LBCF将Webhook的响应与系统关键状态都以K8S event的形式输出至了相关CRD对象中,用户使用`kubectl describe`命令就可以看到系统状态。 42 | 更重要的是,这些event中包含的是Driver返回的业务信息,而不是LBCF的内部信息,即便用户对LBCF一无所知,依然可以明白系统在何时发生了什么。 43 | 以下event摘自真实环境,其中`addr`中的内容就是由Driver定义的 44 | ```yaml 45 | Events: 46 | Type Reason Age From Message 47 | ---- ------ ---- ---- ------- 48 | Normal SuccGenerateAddr 22s lbcf-controller addr: {"instanceID":"","eIP":"10.0.3.244","port":80} 49 | Normal SuccEnsureBackend 16s lbcf-controller Successfully ensured backend 50 | ``` 51 | 52 | ### 可选的Pod解绑条件 53 | K8S中对Pod是否需要解绑的判断依据主要是Pod的`Ready`条件和`deletionTimestamp`,LBCF完全支持这种判断,同时还提供了2种新的判断条件: 54 | * 按Running状态判断解绑:kubelet在某些情况下会影响Pod Ready的值([issue #78733](https://github.com/kubernetes/kubernetes/issues/78733)),虽然可以快速回复,但对于一些金融类业务的用户来说,这依然是不可接受的 55 | * 自定义解绑条件:一些K8S平台提供了Pod镜像快速升级的功能,为了进一步减小业务中断时间,Pod在此种情况下不需要在状态变化而解绑。为了将这种快速升级与Pod的异常状态进行区分,这些快速升级技术通常都对Pod进行了特殊处理。 56 | 具体设计见文档:[可配置的解绑条件设计](/docs/design/proposal/deregister-policy.md) 57 | 58 | ### 已实现的业务需求 59 | 业务需求从来不会因K8S的限制而发生改变,这些业务对负载均衡的使用提出了多种多样的需求,这些需求都可以在LBCF的框架内通过自定义逻辑实现。 60 | 61 | #### 高度定制化的业务需求 62 | 以下需求来自LBCF服务的某**一个**真实业务: 63 | * 每个Pod独占一个LB端口 64 | * 每20个Pod使用一个LB 65 | * Pod扩容时,LB也需要扩容(购买新的LB) 66 | * Pod缩容时,LB也需要缩容(删除LB) 67 | * 所有Pod都来自同一个statefulset,不接受使用多个statefulset的方案 68 | * Pod使用了快速升级技术,期间Pod状态会变为`Pending`,但不允许解绑 69 | * 必须能兼容K8S常规的Pod状态变化(非Ready的Pod需要被解绑) 70 | * LB的接口存在诸多限制,不能同时处理2个请求(调用API时需由调用方加锁) 71 | 72 | #### 对网络有限制的LB 73 | 有些LB会对容器网络提出额外需求,需要在注册Pod地址时进行一些定制化配置,由于LBCF是一个纯控制面框架,因此这种LB也可以使用LBCF对接。 74 | 75 | ## LBCF设计文档 76 | 77 | * [LBCF架构设计](/docs/design/lbcf-architecture.md) 78 | 79 | * [LBCF CRD设计](/docs/design/lbcf-crd.md) 80 | 81 | * [LBCF Webhook规范](/docs/design/lbcf-webhook-specification.md) 82 | 83 | * [操作手册](/docs/design/how-to-use.md) 84 | 85 | * [一些feature设计](/docs/design/proposal) 86 | 87 | -------------------------------------------------------------------------------- /pkg/client-go/listers/lbcf.tkestack.io/v1/bind.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by lister-gen. DO NOT EDIT. 20 | 21 | package v1 22 | 23 | import ( 24 | "k8s.io/apimachinery/pkg/api/errors" 25 | "k8s.io/apimachinery/pkg/labels" 26 | "k8s.io/client-go/tools/cache" 27 | v1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1" 28 | ) 29 | 30 | // BindLister helps list Binds. 31 | type BindLister interface { 32 | // List lists all Binds in the indexer. 33 | List(selector labels.Selector) (ret []*v1.Bind, err error) 34 | // Binds returns an object that can list and get Binds. 35 | Binds(namespace string) BindNamespaceLister 36 | BindListerExpansion 37 | } 38 | 39 | // bindLister implements the BindLister interface. 40 | type bindLister struct { 41 | indexer cache.Indexer 42 | } 43 | 44 | // NewBindLister returns a new BindLister. 45 | func NewBindLister(indexer cache.Indexer) BindLister { 46 | return &bindLister{indexer: indexer} 47 | } 48 | 49 | // List lists all Binds in the indexer. 50 | func (s *bindLister) List(selector labels.Selector) (ret []*v1.Bind, err error) { 51 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 52 | ret = append(ret, m.(*v1.Bind)) 53 | }) 54 | return ret, err 55 | } 56 | 57 | // Binds returns an object that can list and get Binds. 58 | func (s *bindLister) Binds(namespace string) BindNamespaceLister { 59 | return bindNamespaceLister{indexer: s.indexer, namespace: namespace} 60 | } 61 | 62 | // BindNamespaceLister helps list and get Binds. 63 | type BindNamespaceLister interface { 64 | // List lists all Binds in the indexer for a given namespace. 65 | List(selector labels.Selector) (ret []*v1.Bind, err error) 66 | // Get retrieves the Bind from the indexer for a given namespace and name. 67 | Get(name string) (*v1.Bind, error) 68 | BindNamespaceListerExpansion 69 | } 70 | 71 | // bindNamespaceLister implements the BindNamespaceLister 72 | // interface. 73 | type bindNamespaceLister struct { 74 | indexer cache.Indexer 75 | namespace string 76 | } 77 | 78 | // List lists all Binds in the indexer for a given namespace. 79 | func (s bindNamespaceLister) List(selector labels.Selector) (ret []*v1.Bind, err error) { 80 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 81 | ret = append(ret, m.(*v1.Bind)) 82 | }) 83 | return ret, err 84 | } 85 | 86 | // Get retrieves the Bind from the indexer for a given namespace and name. 87 | func (s bindNamespaceLister) Get(name string) (*v1.Bind, error) { 88 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 89 | if err != nil { 90 | return nil, err 91 | } 92 | if !exists { 93 | return nil, errors.NewNotFound(v1.Resource("bind"), name) 94 | } 95 | return obj.(*v1.Bind), nil 96 | } 97 | -------------------------------------------------------------------------------- /pkg/api/bind/util.go: -------------------------------------------------------------------------------- 1 | package bind 2 | 3 | import ( 4 | "reflect" 5 | "time" 6 | 7 | v1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1" 8 | "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 9 | ) 10 | 11 | // DeregIfNotRunning returns true if backend should be deregistered when not running, instead of not ready 12 | func DeregIfNotRunning(bind *v1.Bind) bool { 13 | if bind.Spec.DeregisterPolicy != nil && *bind.Spec.DeregisterPolicy == v1.DeregisterIfNotRunning { 14 | return true 15 | } 16 | return false 17 | } 18 | 19 | // DeregByWebhook returns true if the webhook should determine if the backend should be deregistered 20 | func DeregByWebhook(bind *v1.Bind) bool { 21 | if bind.Spec.DeregisterPolicy != nil && 22 | *bind.Spec.DeregisterPolicy == v1.DeregisterWebhook && 23 | bind.Spec.DeregisterWebhook != nil { 24 | return true 25 | } 26 | return false 27 | } 28 | 29 | // ConvertEnsurePolicy converts EnsurePolicyConfig of v1 to v1beta1 30 | func ConvertEnsurePolicy(ensurePolicy *v1.EnsurePolicyConfig) *v1beta1.EnsurePolicyConfig { 31 | if ensurePolicy == nil { 32 | return nil 33 | } 34 | var policy v1beta1.EnsurePolicyType 35 | switch ensurePolicy.Policy { 36 | case v1.PolicyIfNotSucc: 37 | policy = v1beta1.PolicyIfNotSucc 38 | case v1.PolicyAlways: 39 | policy = v1beta1.PolicyAlways 40 | default: 41 | policy = v1beta1.PolicyIfNotSucc 42 | } 43 | 44 | var period *v1beta1.Duration 45 | if ensurePolicy.ResyncPeriodInSeconds != nil { 46 | period = &v1beta1.Duration{ 47 | Duration: time.Duration(*ensurePolicy.ResyncPeriodInSeconds) * time.Second, 48 | } 49 | } 50 | return &v1beta1.EnsurePolicyConfig{ 51 | Policy: policy, 52 | MinPeriod: period, 53 | } 54 | } 55 | 56 | // IsLoadBalancerCreated returns true if the Created condition is True 57 | func IsLoadBalancerCreated(status v1.TargetLoadBalancerStatus) bool { 58 | for _, cond := range status.Conditions { 59 | if cond.Type == v1.LBCreated && cond.Status == v1.ConditionTrue { 60 | return true 61 | } 62 | } 63 | return false 64 | } 65 | 66 | // IsLoadBalancerReady returns true if the Ready condition is True 67 | func IsLoadBalancerReady(status v1.TargetLoadBalancerStatus) bool { 68 | for _, cond := range status.Conditions { 69 | if cond.Type == v1.LBReady && cond.Status == v1.ConditionTrue { 70 | return true 71 | } 72 | } 73 | return false 74 | } 75 | 76 | // AddOrUpdateLBCondition is an helper function to add specific LoadBalancer condition. 77 | // If a condition with same type exists, the existing one will be overwritten, otherwise, a new condition will be inserted. 78 | func AddOrUpdateLBCondition( 79 | cur []v1.TargetLoadBalancerCondition, 80 | delta v1.TargetLoadBalancerCondition) []v1.TargetLoadBalancerCondition { 81 | cpy := append(make([]v1.TargetLoadBalancerCondition, 0), cur...) 82 | found := false 83 | for i := range cpy { 84 | if cpy[i].Type == delta.Type { 85 | found = true 86 | cpy[i] = delta 87 | break 88 | } 89 | } 90 | if !found { 91 | cpy = append(cpy, delta) 92 | } 93 | return cpy 94 | } 95 | 96 | func NeedUpdateRecord(curObj *v1beta1.BackendRecord, expectObj *v1beta1.BackendRecord) bool { 97 | if !reflect.DeepEqual(curObj.Spec.LBAttributes, expectObj.Spec.LBAttributes) { 98 | return true 99 | } 100 | if !reflect.DeepEqual(curObj.Spec.Parameters, expectObj.Spec.Parameters) { 101 | return true 102 | } 103 | if !reflect.DeepEqual(curObj.Spec.EnsurePolicy, expectObj.Spec.EnsurePolicy) { 104 | return true 105 | } 106 | return false 107 | } 108 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/fake/clientset_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package fake 22 | 23 | import ( 24 | "k8s.io/apimachinery/pkg/runtime" 25 | "k8s.io/apimachinery/pkg/watch" 26 | "k8s.io/client-go/discovery" 27 | fakediscovery "k8s.io/client-go/discovery/fake" 28 | "k8s.io/client-go/testing" 29 | clientset "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned" 30 | lbcfv1 "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1" 31 | fakelbcfv1 "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1/fake" 32 | lbcfv1beta1 "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1" 33 | fakelbcfv1beta1 "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1/fake" 34 | ) 35 | 36 | // NewSimpleClientset returns a clientset that will respond with the provided objects. 37 | // It's backed by a very simple object tracker that processes creates, updates and deletions as-is, 38 | // without applying any validations and/or defaults. It shouldn't be considered a replacement 39 | // for a real clientset and is mostly useful in simple unit tests. 40 | func NewSimpleClientset(objects ...runtime.Object) *Clientset { 41 | o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) 42 | for _, obj := range objects { 43 | if err := o.Add(obj); err != nil { 44 | panic(err) 45 | } 46 | } 47 | 48 | cs := &Clientset{tracker: o} 49 | cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} 50 | cs.AddReactor("*", "*", testing.ObjectReaction(o)) 51 | cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { 52 | gvr := action.GetResource() 53 | ns := action.GetNamespace() 54 | watch, err := o.Watch(gvr, ns) 55 | if err != nil { 56 | return false, nil, err 57 | } 58 | return true, watch, nil 59 | }) 60 | 61 | return cs 62 | } 63 | 64 | // Clientset implements clientset.Interface. Meant to be embedded into a 65 | // struct to get a default implementation. This makes faking out just the method 66 | // you want to test easier. 67 | type Clientset struct { 68 | testing.Fake 69 | discovery *fakediscovery.FakeDiscovery 70 | tracker testing.ObjectTracker 71 | } 72 | 73 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 74 | return c.discovery 75 | } 76 | 77 | func (c *Clientset) Tracker() testing.ObjectTracker { 78 | return c.tracker 79 | } 80 | 81 | var _ clientset.Interface = &Clientset{} 82 | 83 | // LbcfV1 retrieves the LbcfV1Client 84 | func (c *Clientset) LbcfV1() lbcfv1.LbcfV1Interface { 85 | return &fakelbcfv1.FakeLbcfV1{Fake: &c.Fake} 86 | } 87 | 88 | // LbcfV1beta1 retrieves the LbcfV1beta1Client 89 | func (c *Clientset) LbcfV1beta1() lbcfv1beta1.LbcfV1beta1Interface { 90 | return &fakelbcfv1beta1.FakeLbcfV1beta1{Fake: &c.Fake} 91 | } 92 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1/lbcf.tkestack.io_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | rest "k8s.io/client-go/rest" 25 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 26 | "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned/scheme" 27 | ) 28 | 29 | type LbcfV1beta1Interface interface { 30 | RESTClient() rest.Interface 31 | BackendGroupsGetter 32 | BackendRecordsGetter 33 | LoadBalancersGetter 34 | LoadBalancerDriversGetter 35 | } 36 | 37 | // LbcfV1beta1Client is used to interact with features provided by the lbcf.tkestack.io group. 38 | type LbcfV1beta1Client struct { 39 | restClient rest.Interface 40 | } 41 | 42 | func (c *LbcfV1beta1Client) BackendGroups(namespace string) BackendGroupInterface { 43 | return newBackendGroups(c, namespace) 44 | } 45 | 46 | func (c *LbcfV1beta1Client) BackendRecords(namespace string) BackendRecordInterface { 47 | return newBackendRecords(c, namespace) 48 | } 49 | 50 | func (c *LbcfV1beta1Client) LoadBalancers(namespace string) LoadBalancerInterface { 51 | return newLoadBalancers(c, namespace) 52 | } 53 | 54 | func (c *LbcfV1beta1Client) LoadBalancerDrivers(namespace string) LoadBalancerDriverInterface { 55 | return newLoadBalancerDrivers(c, namespace) 56 | } 57 | 58 | // NewForConfig creates a new LbcfV1beta1Client for the given config. 59 | func NewForConfig(c *rest.Config) (*LbcfV1beta1Client, error) { 60 | config := *c 61 | if err := setConfigDefaults(&config); err != nil { 62 | return nil, err 63 | } 64 | client, err := rest.RESTClientFor(&config) 65 | if err != nil { 66 | return nil, err 67 | } 68 | return &LbcfV1beta1Client{client}, nil 69 | } 70 | 71 | // NewForConfigOrDie creates a new LbcfV1beta1Client for the given config and 72 | // panics if there is an error in the config. 73 | func NewForConfigOrDie(c *rest.Config) *LbcfV1beta1Client { 74 | client, err := NewForConfig(c) 75 | if err != nil { 76 | panic(err) 77 | } 78 | return client 79 | } 80 | 81 | // New creates a new LbcfV1beta1Client for the given RESTClient. 82 | func New(c rest.Interface) *LbcfV1beta1Client { 83 | return &LbcfV1beta1Client{c} 84 | } 85 | 86 | func setConfigDefaults(config *rest.Config) error { 87 | gv := v1beta1.SchemeGroupVersion 88 | config.GroupVersion = &gv 89 | config.APIPath = "/apis" 90 | config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() 91 | 92 | if config.UserAgent == "" { 93 | config.UserAgent = rest.DefaultKubernetesUserAgent() 94 | } 95 | 96 | return nil 97 | } 98 | 99 | // RESTClient returns a RESTClient that is used to communicate 100 | // with API server by this client implementation. 101 | func (c *LbcfV1beta1Client) RESTClient() rest.Interface { 102 | if c == nil { 103 | return nil 104 | } 105 | return c.restClient 106 | } 107 | -------------------------------------------------------------------------------- /docs/design/proposal/deregister-policy.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [Background](#background) 4 | - [Solution](#solution) 5 | - [BackendGroup update](#backendgroup-update) 6 | - [deregisterPolicy](#deregisterpolicy) 7 | - [deregisterWebhook](#deregisterwebhook) 8 | - [new webhook](#new-webhook) 9 | - [request](#request) 10 | - [response](#response) 11 | 12 | 13 | 14 | # Background 15 | 1. There are factors other than Pod's `readinessProbe` that impact a Pod's `Ready` condition (see issue [#78733](https://github.com/kubernetes/kubernetes/issues/78733)), even though the connection down time is short, it's still unacceptable to our financial users. Getting rid of the `readinessProbe` is not an option because it's an important flag that indicates Pod status during Pod creating. 16 | 2. There are techniques that can minimize the down time of Pod image updating to about 2 seconds. In such scenario, it's not necessary to deregister the pod and register it back later. These techniques need special treatment so that they can be distinguished from other container exceptions. 17 | 18 | # Solution 19 | 20 | ## BackendGroup update 21 | There are two parameters added in `BackendGroup`: `deregisterPolicy` and `deregisterWebhook`. 22 | ```yaml 23 | apiVersion: lbcf.tkestack.io/v1beta1 24 | kind: BackendGroup 25 | metadata: 26 | name: bg 27 | spec: 28 | loadBalancers: 29 | - lb1 30 | - lb2 31 | deregisterPolicy: Webhook 32 | deregisterWebhook: 33 | driverName: lbcf-example-driver 34 | failurePolicy: DoNothing 35 | pods: 36 | ports: 37 | - port: 80 38 | - port: 90 39 | protocol: UDP 40 | ``` 41 | 42 | ### deregisterPolicy 43 | This the parameter users tell LBCF when their Pods should be deregistered. There are 3 available policies: 44 | * `IfNotReady`: The default policy, same as K8S, pods are deregistered if `pod.status.condition[].Ready` is not `True`. 45 | * `IfNotRunning`: Pods are deregistered if `pod.status.phase` is not `Running`. 46 | * `Webhook`: A hightly customizable policy, driver developers may implement their own policy based on Pod. When used, `deregisterWebhook` must also be specified 47 | **Note:** `deregisterPolicy` has no effect on registering a Pod, the standard of registering a Pod is always `pod.status.condition[].Ready` equals `True` 48 | 49 | ### deregisterWebhook 50 | This parameter must be specified if `deregisterPolicy` is `Webhook`. 51 | 52 | `driverName`: The name of `LoadBalancerDriver`. 53 | `failurePolicy`: Action taken by LBCF if invoking webhook failed. There are 3 available options: 54 | * `DoNothing`: No Pods will be deregistered. This is the default value. 55 | * `IfNotReady`: Same as the `IfNotReady` of `deregisterPolicy` 56 | * `IfNotRunning`: Same as the `IfNotRunning` of `deregisterPolicy` 57 | 58 | ## new webhook 59 | A new webhook called `judgePodDeregister` is added. If the `deregisterPolicy` is `Webhook`, a request will be send to the driver. 60 | 61 | The webhook defines as follows: 62 | 63 | ### request 64 | 65 | ``` 66 | Method: POST 67 | Content-Type: application/json 68 | Path: /judgePodDeregister 69 | ``` 70 | 71 | |Field|Type|Description| 72 | |:---:|:---:|:---:| 73 | |dryRun|bool|If lbcf-controller is running in dry-run mode| 74 | |notReadyPods|[]*[K8S.Pod](https://kubernetes.io/docs/concepts/workloads/pods/pod/)|Pods that are neither ready nor deleting, in JSON format| 75 | 76 | ### response 77 | 78 | |Field|Type|Required|Description| 79 | |:---:|:---:|:---:|:---:| 80 | |succ|bool|True|Indicates if the request is processed successfully. If not, the `failurePolicy` specified in `BackendGroup` is used| 81 | |msg|string|False|some human readable message| 82 | |doNotDeregister|[]*[K8S.Pod](https://kubernetes.io/docs/concepts/workloads/pods/pod/)|True|Pods that should not be deregistered| 83 | 84 | -------------------------------------------------------------------------------- /deployments/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: lbcf-controller 5 | namespace: kube-system 6 | type: Opaque 7 | data: 8 | server.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBMHM3YjJhM0RoaUR1MkFEQTIvTXZMSFpsZUFkejA1aHZVVkFyMk9QVUozMm5icjdvCnZUcE9JUTliZFJaQ3BFazhnTWhqMnhWQWlkMUowVVN2d2JTL00vNmdHTHBKcnhZRk9xdHhqdVhPenh2ay9xN0IKY2FCcC9MMS9BNWJXQXY3NUJVcTF5b3RnTlRxVEJTaDQ4V21wNDhxcERrL2NEZkFuYkJ0SURPMmRHYXhTeExjRgpQRFJNd3hiOW5rTzlVS0V5dUFMQWVVaHFvOGM4UnJYZnpFSjdENkh3WCswaERuUlNhcDh2dG1oRkRxM0Q2VXp4CnBZM3dsZUlZOE94eVhTUFNjZ2dBNC9pRjgyYmx2NDg1eXA1SjhKTXMxZlRwWW5BbUpsK0ova2RyTlhJN3poVTkKU3dyVEF0SldJc0pqVm5sNCtWSDVTUFdlVEo5UkNyVzRpc0wxSXdJREFRQUJBb0lCQUVEc3BKa3VBd0hVTXJzagp3RUg5YTVIdUJPSXFxV21Ka1A4aUNkOEtpOVI5eG9zOUVNRDJyQWxTaVlCT0VzZzJKZ1FqczExTjlrcC9kTFNXCnl1cUZtRDJUTmd0bmxEbndOandUZ1MzWmFSQXdMeDZoQThMUy9ORnlLeVFYMkdHajFWM2ozSWs4MDZ5UkZhYUoKQ0hhUmJGbFRtUzFuT3dhdjUvUkxrcTBvb1RHK2FjR2lPTnBncDM5M1JtUWVzdXJGUm1XQjhNU1RwV2NoWisvegpjcVlPb2ptMTRRbm9FUUhCVVVuWTU5eVJPWHhlenFZY2JQa2hDOHFuR1l3dFM1bWpWZ1FOTTYrWTBjZ0ZPcnlsCk1QSDJyK0Zra2QyMm9iRDE4YkliU2g4K3BtOFhIRkcwZTRUc3d3c3hwOHcrdTlKZVBpaDJxRUYyWWlzWmlSTUoKd3FNZ2ZnRUNnWUVBN0hIeHluc2R6UFBKOHJObWUwc215aFYzbTZxbk43NFBIRzJyNTROZkxIUzlMQXlPbUhEOAprcmd3ZjBUMjRtOCtEUlRFZ0YrNTNzd1I4WkNNdjI4RmtLM0EyVENoaFpJM05Id3NvcU5KZi83Wld3cm5PNWdJClNFUU45TFlkSVNzbDc2cXR0Sml6VTk5blFsVm1JZ1ROQU9KNGhIenA3RzFJRG82ZEhTME1TYUVDZ1lFQTVENGYKVE52QkpHTU5QMVVpK2tRVW4zNDIyTlBabHM1L25vL3dxL1o3R096R21MS2gzdGFxVjQxZWlNMUJub1MvT2NMVwp2RW1ibDNscU9ta2RWN21zYW5acGpqanFBa3YrQ2xPNDNoYmw5c3FhMUxUdGE0bkd0RWc2c3hTMlBiQ2gvazJhCnRWTDFydTM4dnN6Rks3RlVsNmxvVDl5YUc1VHJQeFFPbDFqTnNFTUNnWUVBMndpbks2S250YUExZVQ2VjlpdGwKTUpsNFp0MU04TWVCS2gyeXZOSW5UWUNMYWczcjN1MzBIRnJDbW5PaG5admR5TEp2WWxqTFQ4aU42dEMwZ2ZadwpHbG5McDZkMFNjOXNrcE5ocWZ4SDcybC9vdVpUMVJIK3dpdEJIbXZDU21LMVR2TTIzWEVEMXZQQ3JXRjlMcEJ4CjlKclhlQ3hiYXlqRk1xOE1mdVduVjJFQ2dZQS94SE51UDc5WWNTd1VVNjd3Q1BGU0Zpc3dyUStQcUtYVElSZjIKazJpVThDSVVLMlE2SS9OM2ZwRzQycy9JZ0FJRkcwQnZYb2xQNnFZWko2RUJEMmp5WFo3a0UxYWR5YWx5TFMzcgpMcTZWSXNuYlA2bE5jRExKejV4R3lEU2FTNjBXcFl2aHVRblhFN3FYZkJKaVFLc0hyRmJ1YVEzTlF1L3VzYVhaCjl2K1FqUUtCZ1FEbzJYbWVLbkQzeTZmQS9kR2dFbWtldk5Jb3ZySDVTZFl4RWszd1VpbDhwK2dzekhlWWV5b3MKM0lDL1VsM1ZIU21FUjc0aFBrSDY4THo5eGpveVVUVytBVnprSnBEWmdITHpPVE04VzV6ZjM0WE5XQTRRV0xuKwpBYlg0OXNFbWg3enlFWldINy9GMzVWOExDZmZPbnlXZ2RxbFp4RFJ6MUNiemxSV05BTkxPVUE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= 9 | server.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURQakNDQWlhZ0F3SUJBZ0lKQUxadmk4bXNYdUJLTUEwR0NTcUdTSWIzRFFFQkN3VUFNQzR4Q3pBSkJnTlYKQkFZVEFrTk9NUkF3RGdZRFZRUUtEQWRVWlc1alpXNTBNUTB3Q3dZRFZRUUREQVJNUWtOR01DQVhEVEl3TVRJegpNREEwTWpVeE1Gb1lEekl4TWpBeE1qQTJNRFF5TlRFd1dqQXVNUXN3Q1FZRFZRUUdFd0pEVGpFUU1BNEdBMVVFCkNnd0hWR1Z1WTJWdWRERU5NQXNHQTFVRUF3d0VURUpEUmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVAKQURDQ0FRb0NnZ0VCQU5MTzI5bXR3NFlnN3RnQXdOdnpMeXgyWlhnSGM5T1liMUZRSzlqajFDZDlwMjYrNkwwNgpUaUVQVzNVV1FxUkpQSURJWTlzVlFJbmRTZEZFcjhHMHZ6UCtvQmk2U2E4V0JUcXJjWTdsenM4YjVQNnV3WEdnCmFmeTlmd09XMWdMKytRVkt0Y3FMWURVNmt3VW9lUEZwcWVQS3FRNVAzQTN3SjJ3YlNBenRuUm1zVXNTM0JUdzAKVE1NVy9aNUR2VkNoTXJnQ3dIbElhcVBIUEVhMTM4eENldytoOEYvdElRNTBVbXFmTDdab1JRNnR3K2xNOGFXTgo4SlhpR1BEc2NsMGowbklJQU9QNGhmTm01YitQT2NxZVNmQ1RMTlgwNldKd0ppWmZpZjVIYXpWeU84NFZQVXNLCjB3TFNWaUxDWTFaNWVQbFIrVWoxbmt5ZlVRcTF1SXJDOVNNQ0F3RUFBYU5kTUZzd0RnWURWUjBQQVFIL0JBUUQKQWdXZ01CMEdBMVVkSlFRV01CUUdDQ3NHQVFVRkJ3TUNCZ2dyQmdFRkJRY0RBVEFxQmdOVkhSRUVJekFoZ2g5cwpZbU5tTFdOdmJuUnliMnhzWlhJdWEzVmlaUzF6ZVhOMFpXMHVjM1pqTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCCkFRQyt1K2hJYVY0UFg4djlpK0hXckJnelc5L1ZTaUU3M1ZyZExtRi82d29uclp5aGRhL0UzNG5NbmQ3dUxzYmwKT2ZJRXE5ZGwyVHB5RnN5eXFBdTVJN0hmZHp0NFR6dHpnYWFvalV6SlNwSWlMREE0TnMybWhYWDhjbUp6a2N0Kwptc2VjRVVOVXp6RkN6UkN4SEZKaFFzQmNiUzlzR2ZVN0JjV0VXMll4NlVoUHE3QXFMUkU1bnEyVk4rOHJhMld1CjZSaGMyQXJtbFhPbmlvbjBGRTRLTnMxalBnOUM3SHpBQng3RkFVNUtKcXMrZk42MkpRNUx0U1cxWFlGUWJJTTQKaHpVSjM4elRZVXpTWFppbmhIVU8vSEEyb1k3WndHMzNVall2U3cyWFJSUjhBaXI5TGowQlpZbzM2T29SN1M2OQpBQVN4TFoyUDUzZmNJUiswYXlkN2FkdngKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= -------------------------------------------------------------------------------- /pkg/lbcfcontroller/util/sync_result.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack available. 3 | * 4 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 7 | * this file except in compliance with the License. You may obtain a copy of the 8 | * License at 9 | * 10 | * https://opensource.org/licenses/Apache-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations under the License. 16 | */ 17 | 18 | package util 19 | 20 | import ( 21 | "time" 22 | ) 23 | 24 | // FinishedResult returns a new SyncResult that call IsFinished() on it will return true 25 | func FinishedResult() *SyncResult { 26 | return &SyncResult{} 27 | } 28 | 29 | // ErrorResult returns a new SyncResult that call IsError() on it will return true 30 | func ErrorResult(err error) *SyncResult { 31 | return &SyncResult{ 32 | faild: &failedOp{ 33 | reason: err.Error(), 34 | }, 35 | } 36 | } 37 | 38 | // FailResult returns a new SyncResult that call IsFailed() on it will return true 39 | func FailResult(delay time.Duration, msg string) *SyncResult { 40 | return &SyncResult{ 41 | faild: &failedOp{ 42 | reason: msg, 43 | nextRetryDelay: delay, 44 | isWebhookFail: true, 45 | }, 46 | } 47 | } 48 | 49 | // AsyncResult returns a new SyncResult that call IsPeriodic() on it will return true 50 | func AsyncResult(period time.Duration) *SyncResult { 51 | return &SyncResult{ 52 | async: &asyncOp{ 53 | nextCheckDelay: period, 54 | }, 55 | } 56 | } 57 | 58 | // PeriodicResult returns a new SyncResult that call IsPeriodic() on it will return true 59 | func PeriodicResult(period time.Duration) *SyncResult { 60 | return &SyncResult{ 61 | periodic: &periodicOp{ 62 | nextRunDelay: period, 63 | }, 64 | } 65 | } 66 | 67 | // SyncResult stores result for sync method of controllers 68 | type SyncResult struct { 69 | faild *failedOp 70 | async *asyncOp 71 | periodic *periodicOp 72 | } 73 | 74 | // IsFinished indicates the operation is successfully finished 75 | func (s *SyncResult) IsFinished() bool { 76 | return !s.IsFailed() && !s.IsRunning() && !s.IsPeriodic() 77 | } 78 | 79 | // IsFailed indicates no error occured during operation, but the operation failed 80 | func (s *SyncResult) IsFailed() bool { 81 | return s.faild != nil 82 | } 83 | 84 | // IsRunning indicates the operation is still in progress 85 | func (s *SyncResult) IsRunning() bool { 86 | return s.async != nil 87 | } 88 | 89 | // IsPeriodic indicates the operation successfully finished and should be called periodically 90 | func (s *SyncResult) IsPeriodic() bool { 91 | return s.periodic != nil 92 | } 93 | 94 | // GetFailReason returns the error stored in SyncResult 95 | func (s *SyncResult) GetFailReason() string { 96 | if s.faild == nil { 97 | return "" 98 | } 99 | return s.faild.reason 100 | } 101 | 102 | // GetNextRun returns in how long time the operation should be retried 103 | func (s *SyncResult) GetNextRun() time.Duration { 104 | if s.faild != nil { 105 | return s.faild.nextRetryDelay 106 | } else if s.async != nil { 107 | return s.async.nextCheckDelay 108 | } else if s.periodic != nil { 109 | return s.periodic.nextRunDelay 110 | } 111 | return 0 112 | } 113 | 114 | type failedOp struct { 115 | nextRetryDelay time.Duration 116 | reason string 117 | isWebhookFail bool 118 | } 119 | 120 | type asyncOp struct { 121 | nextCheckDelay time.Duration 122 | } 123 | 124 | type periodicOp struct { 125 | nextRunDelay time.Duration 126 | } 127 | -------------------------------------------------------------------------------- /pkg/client-go/listers/lbcf.tkestack.io/v1beta1/backendgroup.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by lister-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | "k8s.io/apimachinery/pkg/api/errors" 25 | "k8s.io/apimachinery/pkg/labels" 26 | "k8s.io/client-go/tools/cache" 27 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 28 | ) 29 | 30 | // BackendGroupLister helps list BackendGroups. 31 | type BackendGroupLister interface { 32 | // List lists all BackendGroups in the indexer. 33 | List(selector labels.Selector) (ret []*v1beta1.BackendGroup, err error) 34 | // BackendGroups returns an object that can list and get BackendGroups. 35 | BackendGroups(namespace string) BackendGroupNamespaceLister 36 | BackendGroupListerExpansion 37 | } 38 | 39 | // backendGroupLister implements the BackendGroupLister interface. 40 | type backendGroupLister struct { 41 | indexer cache.Indexer 42 | } 43 | 44 | // NewBackendGroupLister returns a new BackendGroupLister. 45 | func NewBackendGroupLister(indexer cache.Indexer) BackendGroupLister { 46 | return &backendGroupLister{indexer: indexer} 47 | } 48 | 49 | // List lists all BackendGroups in the indexer. 50 | func (s *backendGroupLister) List(selector labels.Selector) (ret []*v1beta1.BackendGroup, err error) { 51 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 52 | ret = append(ret, m.(*v1beta1.BackendGroup)) 53 | }) 54 | return ret, err 55 | } 56 | 57 | // BackendGroups returns an object that can list and get BackendGroups. 58 | func (s *backendGroupLister) BackendGroups(namespace string) BackendGroupNamespaceLister { 59 | return backendGroupNamespaceLister{indexer: s.indexer, namespace: namespace} 60 | } 61 | 62 | // BackendGroupNamespaceLister helps list and get BackendGroups. 63 | type BackendGroupNamespaceLister interface { 64 | // List lists all BackendGroups in the indexer for a given namespace. 65 | List(selector labels.Selector) (ret []*v1beta1.BackendGroup, err error) 66 | // Get retrieves the BackendGroup from the indexer for a given namespace and name. 67 | Get(name string) (*v1beta1.BackendGroup, error) 68 | BackendGroupNamespaceListerExpansion 69 | } 70 | 71 | // backendGroupNamespaceLister implements the BackendGroupNamespaceLister 72 | // interface. 73 | type backendGroupNamespaceLister struct { 74 | indexer cache.Indexer 75 | namespace string 76 | } 77 | 78 | // List lists all BackendGroups in the indexer for a given namespace. 79 | func (s backendGroupNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.BackendGroup, err error) { 80 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 81 | ret = append(ret, m.(*v1beta1.BackendGroup)) 82 | }) 83 | return ret, err 84 | } 85 | 86 | // Get retrieves the BackendGroup from the indexer for a given namespace and name. 87 | func (s backendGroupNamespaceLister) Get(name string) (*v1beta1.BackendGroup, error) { 88 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 89 | if err != nil { 90 | return nil, err 91 | } 92 | if !exists { 93 | return nil, errors.NewNotFound(v1beta1.Resource("backendgroup"), name) 94 | } 95 | return obj.(*v1beta1.BackendGroup), nil 96 | } 97 | -------------------------------------------------------------------------------- /pkg/client-go/listers/lbcf.tkestack.io/v1beta1/loadbalancer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by lister-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | "k8s.io/apimachinery/pkg/api/errors" 25 | "k8s.io/apimachinery/pkg/labels" 26 | "k8s.io/client-go/tools/cache" 27 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 28 | ) 29 | 30 | // LoadBalancerLister helps list LoadBalancers. 31 | type LoadBalancerLister interface { 32 | // List lists all LoadBalancers in the indexer. 33 | List(selector labels.Selector) (ret []*v1beta1.LoadBalancer, err error) 34 | // LoadBalancers returns an object that can list and get LoadBalancers. 35 | LoadBalancers(namespace string) LoadBalancerNamespaceLister 36 | LoadBalancerListerExpansion 37 | } 38 | 39 | // loadBalancerLister implements the LoadBalancerLister interface. 40 | type loadBalancerLister struct { 41 | indexer cache.Indexer 42 | } 43 | 44 | // NewLoadBalancerLister returns a new LoadBalancerLister. 45 | func NewLoadBalancerLister(indexer cache.Indexer) LoadBalancerLister { 46 | return &loadBalancerLister{indexer: indexer} 47 | } 48 | 49 | // List lists all LoadBalancers in the indexer. 50 | func (s *loadBalancerLister) List(selector labels.Selector) (ret []*v1beta1.LoadBalancer, err error) { 51 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 52 | ret = append(ret, m.(*v1beta1.LoadBalancer)) 53 | }) 54 | return ret, err 55 | } 56 | 57 | // LoadBalancers returns an object that can list and get LoadBalancers. 58 | func (s *loadBalancerLister) LoadBalancers(namespace string) LoadBalancerNamespaceLister { 59 | return loadBalancerNamespaceLister{indexer: s.indexer, namespace: namespace} 60 | } 61 | 62 | // LoadBalancerNamespaceLister helps list and get LoadBalancers. 63 | type LoadBalancerNamespaceLister interface { 64 | // List lists all LoadBalancers in the indexer for a given namespace. 65 | List(selector labels.Selector) (ret []*v1beta1.LoadBalancer, err error) 66 | // Get retrieves the LoadBalancer from the indexer for a given namespace and name. 67 | Get(name string) (*v1beta1.LoadBalancer, error) 68 | LoadBalancerNamespaceListerExpansion 69 | } 70 | 71 | // loadBalancerNamespaceLister implements the LoadBalancerNamespaceLister 72 | // interface. 73 | type loadBalancerNamespaceLister struct { 74 | indexer cache.Indexer 75 | namespace string 76 | } 77 | 78 | // List lists all LoadBalancers in the indexer for a given namespace. 79 | func (s loadBalancerNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.LoadBalancer, err error) { 80 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 81 | ret = append(ret, m.(*v1beta1.LoadBalancer)) 82 | }) 83 | return ret, err 84 | } 85 | 86 | // Get retrieves the LoadBalancer from the indexer for a given namespace and name. 87 | func (s loadBalancerNamespaceLister) Get(name string) (*v1beta1.LoadBalancer, error) { 88 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 89 | if err != nil { 90 | return nil, err 91 | } 92 | if !exists { 93 | return nil, errors.NewNotFound(v1beta1.Resource("loadbalancer"), name) 94 | } 95 | return obj.(*v1beta1.LoadBalancer), nil 96 | } 97 | -------------------------------------------------------------------------------- /pkg/client-go/listers/lbcf.tkestack.io/v1beta1/backendrecord.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by lister-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | "k8s.io/apimachinery/pkg/api/errors" 25 | "k8s.io/apimachinery/pkg/labels" 26 | "k8s.io/client-go/tools/cache" 27 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 28 | ) 29 | 30 | // BackendRecordLister helps list BackendRecords. 31 | type BackendRecordLister interface { 32 | // List lists all BackendRecords in the indexer. 33 | List(selector labels.Selector) (ret []*v1beta1.BackendRecord, err error) 34 | // BackendRecords returns an object that can list and get BackendRecords. 35 | BackendRecords(namespace string) BackendRecordNamespaceLister 36 | BackendRecordListerExpansion 37 | } 38 | 39 | // backendRecordLister implements the BackendRecordLister interface. 40 | type backendRecordLister struct { 41 | indexer cache.Indexer 42 | } 43 | 44 | // NewBackendRecordLister returns a new BackendRecordLister. 45 | func NewBackendRecordLister(indexer cache.Indexer) BackendRecordLister { 46 | return &backendRecordLister{indexer: indexer} 47 | } 48 | 49 | // List lists all BackendRecords in the indexer. 50 | func (s *backendRecordLister) List(selector labels.Selector) (ret []*v1beta1.BackendRecord, err error) { 51 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 52 | ret = append(ret, m.(*v1beta1.BackendRecord)) 53 | }) 54 | return ret, err 55 | } 56 | 57 | // BackendRecords returns an object that can list and get BackendRecords. 58 | func (s *backendRecordLister) BackendRecords(namespace string) BackendRecordNamespaceLister { 59 | return backendRecordNamespaceLister{indexer: s.indexer, namespace: namespace} 60 | } 61 | 62 | // BackendRecordNamespaceLister helps list and get BackendRecords. 63 | type BackendRecordNamespaceLister interface { 64 | // List lists all BackendRecords in the indexer for a given namespace. 65 | List(selector labels.Selector) (ret []*v1beta1.BackendRecord, err error) 66 | // Get retrieves the BackendRecord from the indexer for a given namespace and name. 67 | Get(name string) (*v1beta1.BackendRecord, error) 68 | BackendRecordNamespaceListerExpansion 69 | } 70 | 71 | // backendRecordNamespaceLister implements the BackendRecordNamespaceLister 72 | // interface. 73 | type backendRecordNamespaceLister struct { 74 | indexer cache.Indexer 75 | namespace string 76 | } 77 | 78 | // List lists all BackendRecords in the indexer for a given namespace. 79 | func (s backendRecordNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.BackendRecord, err error) { 80 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 81 | ret = append(ret, m.(*v1beta1.BackendRecord)) 82 | }) 83 | return ret, err 84 | } 85 | 86 | // Get retrieves the BackendRecord from the indexer for a given namespace and name. 87 | func (s backendRecordNamespaceLister) Get(name string) (*v1beta1.BackendRecord, error) { 88 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 89 | if err != nil { 90 | return nil, err 91 | } 92 | if !exists { 93 | return nil, errors.NewNotFound(v1beta1.Resource("backendrecord"), name) 94 | } 95 | return obj.(*v1beta1.BackendRecord), nil 96 | } 97 | -------------------------------------------------------------------------------- /pkg/client-go/informers/externalversions/lbcf.tkestack.io/v1/bind.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by informer-gen. DO NOT EDIT. 20 | 21 | package v1 22 | 23 | import ( 24 | time "time" 25 | 26 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | runtime "k8s.io/apimachinery/pkg/runtime" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | cache "k8s.io/client-go/tools/cache" 30 | lbcftkestackiov1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1" 31 | versioned "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned" 32 | internalinterfaces "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions/internalinterfaces" 33 | v1 "tkestack.io/lb-controlling-framework/pkg/client-go/listers/lbcf.tkestack.io/v1" 34 | ) 35 | 36 | // BindInformer provides access to a shared informer and lister for 37 | // Binds. 38 | type BindInformer interface { 39 | Informer() cache.SharedIndexInformer 40 | Lister() v1.BindLister 41 | } 42 | 43 | type bindInformer struct { 44 | factory internalinterfaces.SharedInformerFactory 45 | tweakListOptions internalinterfaces.TweakListOptionsFunc 46 | namespace string 47 | } 48 | 49 | // NewBindInformer constructs a new informer for Bind type. 50 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 51 | // one. This reduces memory footprint and number of connections to the server. 52 | func NewBindInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 53 | return NewFilteredBindInformer(client, namespace, resyncPeriod, indexers, nil) 54 | } 55 | 56 | // NewFilteredBindInformer constructs a new informer for Bind type. 57 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 58 | // one. This reduces memory footprint and number of connections to the server. 59 | func NewFilteredBindInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 60 | return cache.NewSharedIndexInformer( 61 | &cache.ListWatch{ 62 | ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { 63 | if tweakListOptions != nil { 64 | tweakListOptions(&options) 65 | } 66 | return client.LbcfV1().Binds(namespace).List(options) 67 | }, 68 | WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { 69 | if tweakListOptions != nil { 70 | tweakListOptions(&options) 71 | } 72 | return client.LbcfV1().Binds(namespace).Watch(options) 73 | }, 74 | }, 75 | &lbcftkestackiov1.Bind{}, 76 | resyncPeriod, 77 | indexers, 78 | ) 79 | } 80 | 81 | func (f *bindInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 82 | return NewFilteredBindInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 83 | } 84 | 85 | func (f *bindInformer) Informer() cache.SharedIndexInformer { 86 | return f.factory.InformerFor(&lbcftkestackiov1.Bind{}, f.defaultInformer) 87 | } 88 | 89 | func (f *bindInformer) Lister() v1.BindLister { 90 | return v1.NewBindLister(f.Informer().GetIndexer()) 91 | } 92 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/clientset.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package versioned 22 | 23 | import ( 24 | "fmt" 25 | 26 | discovery "k8s.io/client-go/discovery" 27 | rest "k8s.io/client-go/rest" 28 | flowcontrol "k8s.io/client-go/util/flowcontrol" 29 | lbcfv1 "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1" 30 | lbcfv1beta1 "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1" 31 | ) 32 | 33 | type Interface interface { 34 | Discovery() discovery.DiscoveryInterface 35 | LbcfV1() lbcfv1.LbcfV1Interface 36 | LbcfV1beta1() lbcfv1beta1.LbcfV1beta1Interface 37 | } 38 | 39 | // Clientset contains the clients for groups. Each group has exactly one 40 | // version included in a Clientset. 41 | type Clientset struct { 42 | *discovery.DiscoveryClient 43 | lbcfV1 *lbcfv1.LbcfV1Client 44 | lbcfV1beta1 *lbcfv1beta1.LbcfV1beta1Client 45 | } 46 | 47 | // LbcfV1 retrieves the LbcfV1Client 48 | func (c *Clientset) LbcfV1() lbcfv1.LbcfV1Interface { 49 | return c.lbcfV1 50 | } 51 | 52 | // LbcfV1beta1 retrieves the LbcfV1beta1Client 53 | func (c *Clientset) LbcfV1beta1() lbcfv1beta1.LbcfV1beta1Interface { 54 | return c.lbcfV1beta1 55 | } 56 | 57 | // Discovery retrieves the DiscoveryClient 58 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 59 | if c == nil { 60 | return nil 61 | } 62 | return c.DiscoveryClient 63 | } 64 | 65 | // NewForConfig creates a new Clientset for the given config. 66 | // If config's RateLimiter is not set and QPS and Burst are acceptable, 67 | // NewForConfig will generate a rate-limiter in configShallowCopy. 68 | func NewForConfig(c *rest.Config) (*Clientset, error) { 69 | configShallowCopy := *c 70 | if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { 71 | if configShallowCopy.Burst <= 0 { 72 | 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") 73 | } 74 | configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) 75 | } 76 | var cs Clientset 77 | var err error 78 | cs.lbcfV1, err = lbcfv1.NewForConfig(&configShallowCopy) 79 | if err != nil { 80 | return nil, err 81 | } 82 | cs.lbcfV1beta1, err = lbcfv1beta1.NewForConfig(&configShallowCopy) 83 | if err != nil { 84 | return nil, err 85 | } 86 | 87 | cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) 88 | if err != nil { 89 | return nil, err 90 | } 91 | return &cs, nil 92 | } 93 | 94 | // NewForConfigOrDie creates a new Clientset for the given config and 95 | // panics if there is an error in the config. 96 | func NewForConfigOrDie(c *rest.Config) *Clientset { 97 | var cs Clientset 98 | cs.lbcfV1 = lbcfv1.NewForConfigOrDie(c) 99 | cs.lbcfV1beta1 = lbcfv1beta1.NewForConfigOrDie(c) 100 | 101 | cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) 102 | return &cs 103 | } 104 | 105 | // New creates a new Clientset for the given RESTClient. 106 | func New(c rest.Interface) *Clientset { 107 | var cs Clientset 108 | cs.lbcfV1 = lbcfv1.New(c) 109 | cs.lbcfV1beta1 = lbcfv1beta1.New(c) 110 | 111 | cs.DiscoveryClient = discovery.NewDiscoveryClient(c) 112 | return &cs 113 | } 114 | -------------------------------------------------------------------------------- /pkg/client-go/listers/lbcf.tkestack.io/v1beta1/loadbalancerdriver.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by lister-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | "k8s.io/apimachinery/pkg/api/errors" 25 | "k8s.io/apimachinery/pkg/labels" 26 | "k8s.io/client-go/tools/cache" 27 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 28 | ) 29 | 30 | // LoadBalancerDriverLister helps list LoadBalancerDrivers. 31 | type LoadBalancerDriverLister interface { 32 | // List lists all LoadBalancerDrivers in the indexer. 33 | List(selector labels.Selector) (ret []*v1beta1.LoadBalancerDriver, err error) 34 | // LoadBalancerDrivers returns an object that can list and get LoadBalancerDrivers. 35 | LoadBalancerDrivers(namespace string) LoadBalancerDriverNamespaceLister 36 | LoadBalancerDriverListerExpansion 37 | } 38 | 39 | // loadBalancerDriverLister implements the LoadBalancerDriverLister interface. 40 | type loadBalancerDriverLister struct { 41 | indexer cache.Indexer 42 | } 43 | 44 | // NewLoadBalancerDriverLister returns a new LoadBalancerDriverLister. 45 | func NewLoadBalancerDriverLister(indexer cache.Indexer) LoadBalancerDriverLister { 46 | return &loadBalancerDriverLister{indexer: indexer} 47 | } 48 | 49 | // List lists all LoadBalancerDrivers in the indexer. 50 | func (s *loadBalancerDriverLister) List(selector labels.Selector) (ret []*v1beta1.LoadBalancerDriver, err error) { 51 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 52 | ret = append(ret, m.(*v1beta1.LoadBalancerDriver)) 53 | }) 54 | return ret, err 55 | } 56 | 57 | // LoadBalancerDrivers returns an object that can list and get LoadBalancerDrivers. 58 | func (s *loadBalancerDriverLister) LoadBalancerDrivers(namespace string) LoadBalancerDriverNamespaceLister { 59 | return loadBalancerDriverNamespaceLister{indexer: s.indexer, namespace: namespace} 60 | } 61 | 62 | // LoadBalancerDriverNamespaceLister helps list and get LoadBalancerDrivers. 63 | type LoadBalancerDriverNamespaceLister interface { 64 | // List lists all LoadBalancerDrivers in the indexer for a given namespace. 65 | List(selector labels.Selector) (ret []*v1beta1.LoadBalancerDriver, err error) 66 | // Get retrieves the LoadBalancerDriver from the indexer for a given namespace and name. 67 | Get(name string) (*v1beta1.LoadBalancerDriver, error) 68 | LoadBalancerDriverNamespaceListerExpansion 69 | } 70 | 71 | // loadBalancerDriverNamespaceLister implements the LoadBalancerDriverNamespaceLister 72 | // interface. 73 | type loadBalancerDriverNamespaceLister struct { 74 | indexer cache.Indexer 75 | namespace string 76 | } 77 | 78 | // List lists all LoadBalancerDrivers in the indexer for a given namespace. 79 | func (s loadBalancerDriverNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.LoadBalancerDriver, err error) { 80 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 81 | ret = append(ret, m.(*v1beta1.LoadBalancerDriver)) 82 | }) 83 | return ret, err 84 | } 85 | 86 | // Get retrieves the LoadBalancerDriver from the indexer for a given namespace and name. 87 | func (s loadBalancerDriverNamespaceLister) Get(name string) (*v1beta1.LoadBalancerDriver, error) { 88 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 89 | if err != nil { 90 | return nil, err 91 | } 92 | if !exists { 93 | return nil, errors.NewNotFound(v1beta1.Resource("loadbalancerdriver"), name) 94 | } 95 | return obj.(*v1beta1.LoadBalancerDriver), nil 96 | } 97 | -------------------------------------------------------------------------------- /pkg/client-go/informers/externalversions/lbcf.tkestack.io/v1beta1/backendgroup.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by informer-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | time "time" 25 | 26 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | runtime "k8s.io/apimachinery/pkg/runtime" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | cache "k8s.io/client-go/tools/cache" 30 | lbcftkestackiov1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 31 | versioned "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned" 32 | internalinterfaces "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions/internalinterfaces" 33 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/client-go/listers/lbcf.tkestack.io/v1beta1" 34 | ) 35 | 36 | // BackendGroupInformer provides access to a shared informer and lister for 37 | // BackendGroups. 38 | type BackendGroupInformer interface { 39 | Informer() cache.SharedIndexInformer 40 | Lister() v1beta1.BackendGroupLister 41 | } 42 | 43 | type backendGroupInformer struct { 44 | factory internalinterfaces.SharedInformerFactory 45 | tweakListOptions internalinterfaces.TweakListOptionsFunc 46 | namespace string 47 | } 48 | 49 | // NewBackendGroupInformer constructs a new informer for BackendGroup type. 50 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 51 | // one. This reduces memory footprint and number of connections to the server. 52 | func NewBackendGroupInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 53 | return NewFilteredBackendGroupInformer(client, namespace, resyncPeriod, indexers, nil) 54 | } 55 | 56 | // NewFilteredBackendGroupInformer constructs a new informer for BackendGroup type. 57 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 58 | // one. This reduces memory footprint and number of connections to the server. 59 | func NewFilteredBackendGroupInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 60 | return cache.NewSharedIndexInformer( 61 | &cache.ListWatch{ 62 | ListFunc: func(options v1.ListOptions) (runtime.Object, error) { 63 | if tweakListOptions != nil { 64 | tweakListOptions(&options) 65 | } 66 | return client.LbcfV1beta1().BackendGroups(namespace).List(options) 67 | }, 68 | WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { 69 | if tweakListOptions != nil { 70 | tweakListOptions(&options) 71 | } 72 | return client.LbcfV1beta1().BackendGroups(namespace).Watch(options) 73 | }, 74 | }, 75 | &lbcftkestackiov1beta1.BackendGroup{}, 76 | resyncPeriod, 77 | indexers, 78 | ) 79 | } 80 | 81 | func (f *backendGroupInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 82 | return NewFilteredBackendGroupInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 83 | } 84 | 85 | func (f *backendGroupInformer) Informer() cache.SharedIndexInformer { 86 | return f.factory.InformerFor(&lbcftkestackiov1beta1.BackendGroup{}, f.defaultInformer) 87 | } 88 | 89 | func (f *backendGroupInformer) Lister() v1beta1.BackendGroupLister { 90 | return v1beta1.NewBackendGroupLister(f.Informer().GetIndexer()) 91 | } 92 | -------------------------------------------------------------------------------- /pkg/client-go/informers/externalversions/lbcf.tkestack.io/v1beta1/loadbalancer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by informer-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | time "time" 25 | 26 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | runtime "k8s.io/apimachinery/pkg/runtime" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | cache "k8s.io/client-go/tools/cache" 30 | lbcftkestackiov1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 31 | versioned "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned" 32 | internalinterfaces "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions/internalinterfaces" 33 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/client-go/listers/lbcf.tkestack.io/v1beta1" 34 | ) 35 | 36 | // LoadBalancerInformer provides access to a shared informer and lister for 37 | // LoadBalancers. 38 | type LoadBalancerInformer interface { 39 | Informer() cache.SharedIndexInformer 40 | Lister() v1beta1.LoadBalancerLister 41 | } 42 | 43 | type loadBalancerInformer struct { 44 | factory internalinterfaces.SharedInformerFactory 45 | tweakListOptions internalinterfaces.TweakListOptionsFunc 46 | namespace string 47 | } 48 | 49 | // NewLoadBalancerInformer constructs a new informer for LoadBalancer type. 50 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 51 | // one. This reduces memory footprint and number of connections to the server. 52 | func NewLoadBalancerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 53 | return NewFilteredLoadBalancerInformer(client, namespace, resyncPeriod, indexers, nil) 54 | } 55 | 56 | // NewFilteredLoadBalancerInformer constructs a new informer for LoadBalancer type. 57 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 58 | // one. This reduces memory footprint and number of connections to the server. 59 | func NewFilteredLoadBalancerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 60 | return cache.NewSharedIndexInformer( 61 | &cache.ListWatch{ 62 | ListFunc: func(options v1.ListOptions) (runtime.Object, error) { 63 | if tweakListOptions != nil { 64 | tweakListOptions(&options) 65 | } 66 | return client.LbcfV1beta1().LoadBalancers(namespace).List(options) 67 | }, 68 | WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { 69 | if tweakListOptions != nil { 70 | tweakListOptions(&options) 71 | } 72 | return client.LbcfV1beta1().LoadBalancers(namespace).Watch(options) 73 | }, 74 | }, 75 | &lbcftkestackiov1beta1.LoadBalancer{}, 76 | resyncPeriod, 77 | indexers, 78 | ) 79 | } 80 | 81 | func (f *loadBalancerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 82 | return NewFilteredLoadBalancerInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 83 | } 84 | 85 | func (f *loadBalancerInformer) Informer() cache.SharedIndexInformer { 86 | return f.factory.InformerFor(&lbcftkestackiov1beta1.LoadBalancer{}, f.defaultInformer) 87 | } 88 | 89 | func (f *loadBalancerInformer) Lister() v1beta1.LoadBalancerLister { 90 | return v1beta1.NewLoadBalancerLister(f.Informer().GetIndexer()) 91 | } 92 | -------------------------------------------------------------------------------- /pkg/client-go/informers/externalversions/lbcf.tkestack.io/v1beta1/backendrecord.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by informer-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | time "time" 25 | 26 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | runtime "k8s.io/apimachinery/pkg/runtime" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | cache "k8s.io/client-go/tools/cache" 30 | lbcftkestackiov1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 31 | versioned "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned" 32 | internalinterfaces "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions/internalinterfaces" 33 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/client-go/listers/lbcf.tkestack.io/v1beta1" 34 | ) 35 | 36 | // BackendRecordInformer provides access to a shared informer and lister for 37 | // BackendRecords. 38 | type BackendRecordInformer interface { 39 | Informer() cache.SharedIndexInformer 40 | Lister() v1beta1.BackendRecordLister 41 | } 42 | 43 | type backendRecordInformer struct { 44 | factory internalinterfaces.SharedInformerFactory 45 | tweakListOptions internalinterfaces.TweakListOptionsFunc 46 | namespace string 47 | } 48 | 49 | // NewBackendRecordInformer constructs a new informer for BackendRecord type. 50 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 51 | // one. This reduces memory footprint and number of connections to the server. 52 | func NewBackendRecordInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 53 | return NewFilteredBackendRecordInformer(client, namespace, resyncPeriod, indexers, nil) 54 | } 55 | 56 | // NewFilteredBackendRecordInformer constructs a new informer for BackendRecord type. 57 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 58 | // one. This reduces memory footprint and number of connections to the server. 59 | func NewFilteredBackendRecordInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 60 | return cache.NewSharedIndexInformer( 61 | &cache.ListWatch{ 62 | ListFunc: func(options v1.ListOptions) (runtime.Object, error) { 63 | if tweakListOptions != nil { 64 | tweakListOptions(&options) 65 | } 66 | return client.LbcfV1beta1().BackendRecords(namespace).List(options) 67 | }, 68 | WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { 69 | if tweakListOptions != nil { 70 | tweakListOptions(&options) 71 | } 72 | return client.LbcfV1beta1().BackendRecords(namespace).Watch(options) 73 | }, 74 | }, 75 | &lbcftkestackiov1beta1.BackendRecord{}, 76 | resyncPeriod, 77 | indexers, 78 | ) 79 | } 80 | 81 | func (f *backendRecordInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 82 | return NewFilteredBackendRecordInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 83 | } 84 | 85 | func (f *backendRecordInformer) Informer() cache.SharedIndexInformer { 86 | return f.factory.InformerFor(&lbcftkestackiov1beta1.BackendRecord{}, f.defaultInformer) 87 | } 88 | 89 | func (f *backendRecordInformer) Lister() v1beta1.BackendRecordLister { 90 | return v1beta1.NewBackendRecordLister(f.Informer().GetIndexer()) 91 | } 92 | -------------------------------------------------------------------------------- /pkg/client-go/informers/externalversions/lbcf.tkestack.io/v1beta1/loadbalancerdriver.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by informer-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | time "time" 25 | 26 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | runtime "k8s.io/apimachinery/pkg/runtime" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | cache "k8s.io/client-go/tools/cache" 30 | lbcftkestackiov1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 31 | versioned "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned" 32 | internalinterfaces "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions/internalinterfaces" 33 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/client-go/listers/lbcf.tkestack.io/v1beta1" 34 | ) 35 | 36 | // LoadBalancerDriverInformer provides access to a shared informer and lister for 37 | // LoadBalancerDrivers. 38 | type LoadBalancerDriverInformer interface { 39 | Informer() cache.SharedIndexInformer 40 | Lister() v1beta1.LoadBalancerDriverLister 41 | } 42 | 43 | type loadBalancerDriverInformer struct { 44 | factory internalinterfaces.SharedInformerFactory 45 | tweakListOptions internalinterfaces.TweakListOptionsFunc 46 | namespace string 47 | } 48 | 49 | // NewLoadBalancerDriverInformer constructs a new informer for LoadBalancerDriver type. 50 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 51 | // one. This reduces memory footprint and number of connections to the server. 52 | func NewLoadBalancerDriverInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 53 | return NewFilteredLoadBalancerDriverInformer(client, namespace, resyncPeriod, indexers, nil) 54 | } 55 | 56 | // NewFilteredLoadBalancerDriverInformer constructs a new informer for LoadBalancerDriver type. 57 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 58 | // one. This reduces memory footprint and number of connections to the server. 59 | func NewFilteredLoadBalancerDriverInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 60 | return cache.NewSharedIndexInformer( 61 | &cache.ListWatch{ 62 | ListFunc: func(options v1.ListOptions) (runtime.Object, error) { 63 | if tweakListOptions != nil { 64 | tweakListOptions(&options) 65 | } 66 | return client.LbcfV1beta1().LoadBalancerDrivers(namespace).List(options) 67 | }, 68 | WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { 69 | if tweakListOptions != nil { 70 | tweakListOptions(&options) 71 | } 72 | return client.LbcfV1beta1().LoadBalancerDrivers(namespace).Watch(options) 73 | }, 74 | }, 75 | &lbcftkestackiov1beta1.LoadBalancerDriver{}, 76 | resyncPeriod, 77 | indexers, 78 | ) 79 | } 80 | 81 | func (f *loadBalancerDriverInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 82 | return NewFilteredLoadBalancerDriverInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 83 | } 84 | 85 | func (f *loadBalancerDriverInformer) Informer() cache.SharedIndexInformer { 86 | return f.factory.InformerFor(&lbcftkestackiov1beta1.LoadBalancerDriver{}, f.defaultInformer) 87 | } 88 | 89 | func (f *loadBalancerDriverInformer) Lister() v1beta1.LoadBalancerDriverLister { 90 | return v1beta1.NewLoadBalancerDriverLister(f.Informer().GetIndexer()) 91 | } 92 | -------------------------------------------------------------------------------- /pkg/metrics/metrics.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/prometheus/client_golang/prometheus" 7 | "github.com/prometheus/client_golang/prometheus/promauto" 8 | ) 9 | 10 | var ( 11 | webhookCalls *prometheus.CounterVec 12 | webhookErrors *prometheus.CounterVec 13 | webhookFails *prometheus.CounterVec 14 | webhookLatency *prometheus.HistogramVec 15 | k8sOpLatency *prometheus.HistogramVec 16 | keyProcessLatency *prometheus.HistogramVec 17 | pendingKeys *prometheus.GaugeVec 18 | workingKeys *prometheus.GaugeVec 19 | ) 20 | 21 | const ( 22 | labelKeyKind = "key_kind" 23 | labelDriverName = "driver_name" 24 | labelWebhookName = "webhook_name" 25 | labelK8sOpObj = "k8s_op_obj" 26 | labelK8sOpType = "k8s_op_type" 27 | labelCRD = "crd" 28 | 29 | OpCreate = "Create" 30 | OpUpdate = "Update" 31 | OpUpdateStatus = "UpdateStatus" 32 | OpDelete = "Delete" 33 | ) 34 | 35 | func init() { 36 | webhookCalls = promauto.NewCounterVec( 37 | prometheus.CounterOpts{ 38 | Name: "webhook_calls", 39 | Help: "The total number of webhook calls", 40 | }, 41 | []string{labelDriverName, labelWebhookName}) 42 | 43 | webhookErrors = promauto.NewCounterVec( 44 | prometheus.CounterOpts{ 45 | Name: "webhook_errors", 46 | Help: "The total number of webhook errors (mostly network errors)", 47 | }, 48 | []string{labelDriverName, labelWebhookName}) 49 | 50 | webhookFails = promauto.NewCounterVec( 51 | prometheus.CounterOpts{ 52 | Name: "webhook_fails", 53 | Help: "The total number of webhooks calls that drivers responded with succ=fail or status=Fail", 54 | }, 55 | []string{labelDriverName, labelWebhookName}) 56 | 57 | webhookLatency = promauto.NewHistogramVec( 58 | prometheus.HistogramOpts{ 59 | Name: "webhook_latency", 60 | Help: "webhook latencies in seconds for each non-error call", 61 | Buckets: []float64{0.02, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 62 | 2.0, 3.0, 4.0, 5.0, 10.0, 20.0, 30.0}, 63 | }, 64 | []string{labelDriverName, labelWebhookName}) 65 | 66 | k8sOpLatency = promauto.NewHistogramVec( 67 | prometheus.HistogramOpts{ 68 | Name: "k8s_operation_latency", 69 | Help: "k8s operation latencies in seconds", 70 | Buckets: []float64{0.02, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 71 | 2.0, 3.0, 4.0, 5.0, 10.0, 20.0, 30.0}, 72 | }, 73 | []string{labelK8sOpObj, labelK8sOpType}) 74 | 75 | keyProcessLatency = promauto.NewHistogramVec( 76 | prometheus.HistogramOpts{ 77 | Name: "key_process_latency", 78 | Help: "key process latencies in seconds", 79 | Buckets: []float64{0.02, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 80 | 2.0, 3.0, 4.0, 5.0, 10.0, 20.0, 30.0}, 81 | }, 82 | []string{labelCRD}) 83 | 84 | pendingKeys = promauto.NewGaugeVec( 85 | prometheus.GaugeOpts{ 86 | Name: "pending_key", 87 | Help: "The number of keys waiting to be processed", 88 | }, 89 | []string{labelKeyKind}) 90 | 91 | workingKeys = promauto.NewGaugeVec( 92 | prometheus.GaugeOpts{ 93 | Name: "working_key", 94 | Help: "The number of keys being processed", 95 | }, 96 | []string{labelKeyKind}) 97 | } 98 | 99 | func WebhookCallsInc(driverName, webhookName string) { 100 | l := prometheus.Labels{ 101 | labelDriverName: driverName, 102 | labelWebhookName: webhookName, 103 | } 104 | webhookCalls.With(l).Inc() 105 | } 106 | 107 | func WebhookErrorsInc(driverName, webhookName string) { 108 | l := prometheus.Labels{ 109 | labelDriverName: driverName, 110 | labelWebhookName: webhookName, 111 | } 112 | webhookErrors.With(l).Inc() 113 | } 114 | 115 | func WebhookFailsInc(driverName, webhookName string) { 116 | l := prometheus.Labels{ 117 | labelDriverName: driverName, 118 | labelWebhookName: webhookName, 119 | } 120 | webhookFails.With(l).Inc() 121 | } 122 | 123 | func WebhookLatencyObserve(driverName, webhookName string, elapsed time.Duration) { 124 | l := prometheus.Labels{ 125 | labelDriverName: driverName, 126 | labelWebhookName: webhookName, 127 | } 128 | webhookLatency.With(l).Observe(elapsed.Seconds()) 129 | 130 | } 131 | 132 | func K8SOpLatencyObserve(obj, op string, elapsed time.Duration) { 133 | l := prometheus.Labels{ 134 | labelK8sOpObj: obj, 135 | labelK8sOpType: op, 136 | } 137 | k8sOpLatency.With(l).Observe(elapsed.Seconds()) 138 | } 139 | 140 | func KeyProcessLatencyObserve(crd string, elapsed time.Duration) { 141 | l := prometheus.Labels{ 142 | labelCRD: crd, 143 | } 144 | keyProcessLatency.With(l).Observe(elapsed.Seconds()) 145 | } 146 | 147 | func PendingKeysSet(kind string, value float64) { 148 | l := prometheus.Labels{ 149 | labelKeyKind: kind, 150 | } 151 | pendingKeys.With(l).Set(value) 152 | } 153 | 154 | func WorkingKeysInc(kind string) { 155 | l := prometheus.Labels{ 156 | labelKeyKind: kind, 157 | } 158 | workingKeys.With(l).Inc() 159 | } 160 | 161 | func WorkingKeysDec(kind string) { 162 | l := prometheus.Labels{ 163 | labelKeyKind: kind, 164 | } 165 | workingKeys.With(l).Dec() 166 | } 167 | -------------------------------------------------------------------------------- /cmd/lbcf-controller/app/context/context.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack available. 3 | * 4 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 7 | * this file except in compliance with the License. You may obtain a copy of the 8 | * License at 9 | * 10 | * https://opensource.org/licenses/Apache-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations under the License. 16 | */ 17 | 18 | package context 19 | 20 | import ( 21 | "tkestack.io/lb-controlling-framework/cmd/lbcf-controller/app/config" 22 | lbcfv1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1" 23 | lbcfv1beta "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 24 | lbcfclient "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned" 25 | lbcfclientset "tkestack.io/lb-controlling-framework/pkg/client-go/clientset/versioned" 26 | "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions" 27 | lbcfclientv1 "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions/lbcf.tkestack.io/v1" 28 | "tkestack.io/lb-controlling-framework/pkg/client-go/informers/externalversions/lbcf.tkestack.io/v1beta1" 29 | 30 | apicorev1 "k8s.io/api/core/v1" 31 | "k8s.io/apimachinery/pkg/runtime" 32 | "k8s.io/apimachinery/pkg/util/wait" 33 | "k8s.io/client-go/informers" 34 | v1 "k8s.io/client-go/informers/core/v1" 35 | "k8s.io/client-go/kubernetes" 36 | corev1 "k8s.io/client-go/kubernetes/typed/core/v1" 37 | "k8s.io/client-go/rest" 38 | "k8s.io/client-go/tools/clientcmd" 39 | "k8s.io/client-go/tools/record" 40 | "k8s.io/klog" 41 | ) 42 | 43 | func NewContext(cfg *config.Config) *Context { 44 | c := &Context{ 45 | Cfg: cfg, 46 | } 47 | clientCfg := getClientConfigOrDie(cfg.KubeConfig, cfg.ClientQPS, cfg.ClientBurst) 48 | 49 | c.K8sClient = kubernetes.NewForConfigOrDie(clientCfg) 50 | c.LbcfClient = lbcfclientset.NewForConfigOrDie(clientCfg) 51 | 52 | c.K8sFactory = informers.NewSharedInformerFactory(c.K8sClient, cfg.InformerResyncPeriod) 53 | c.LbcfFactory = externalversions.NewSharedInformerFactory(c.LbcfClient, cfg.InformerResyncPeriod) 54 | 55 | c.PodInformer = c.K8sFactory.Core().V1().Pods() 56 | c.SvcInformer = c.K8sFactory.Core().V1().Services() 57 | c.NodeInformer = c.K8sFactory.Core().V1().Nodes() 58 | c.LBInformer = c.LbcfFactory.Lbcf().V1beta1().LoadBalancers() 59 | c.LBDriverInformer = c.LbcfFactory.Lbcf().V1beta1().LoadBalancerDrivers() 60 | c.BGInformer = c.LbcfFactory.Lbcf().V1beta1().BackendGroups() 61 | c.BRInformer = c.LbcfFactory.Lbcf().V1beta1().BackendRecords() 62 | c.BindInformer = c.LbcfFactory.Lbcf().V1().Binds() 63 | 64 | c.EventBroadCaster = record.NewBroadcaster() 65 | scheme := runtime.NewScheme() 66 | if err := lbcfv1beta.SchemeBuilder.AddToScheme(scheme); err != nil { 67 | klog.Fatal(err.Error()) 68 | } 69 | if err := lbcfv1.SchemeBuilder.AddToScheme(scheme); err != nil { 70 | klog.Fatal(err.Error()) 71 | } 72 | c.EventRecorder = c.EventBroadCaster.NewRecorder(scheme, apicorev1.EventSource{ 73 | Component: "lbcf-controller", 74 | }) 75 | return c 76 | } 77 | 78 | type Context struct { 79 | Cfg *config.Config 80 | 81 | K8sClient *kubernetes.Clientset 82 | LbcfClient *lbcfclient.Clientset 83 | 84 | K8sFactory informers.SharedInformerFactory 85 | LbcfFactory externalversions.SharedInformerFactory 86 | 87 | PodInformer v1.PodInformer 88 | SvcInformer v1.ServiceInformer 89 | NodeInformer v1.NodeInformer 90 | LBInformer v1beta1.LoadBalancerInformer 91 | LBDriverInformer v1beta1.LoadBalancerDriverInformer 92 | BGInformer v1beta1.BackendGroupInformer 93 | BRInformer v1beta1.BackendRecordInformer 94 | BindInformer lbcfclientv1.BindInformer 95 | 96 | EventBroadCaster record.EventBroadcaster 97 | EventRecorder record.EventRecorder 98 | } 99 | 100 | func (c *Context) Start() { 101 | c.K8sFactory.Start(wait.NeverStop) 102 | c.LbcfFactory.Start(wait.NeverStop) 103 | c.EventBroadCaster.StartRecordingToSink(&corev1.EventSinkImpl{Interface: c.K8sClient.CoreV1().Events("")}) 104 | } 105 | 106 | func (c *Context) WaitForCacheSync() { 107 | c.K8sFactory.WaitForCacheSync(wait.NeverStop) 108 | c.LbcfFactory.WaitForCacheSync(wait.NeverStop) 109 | } 110 | 111 | func (c *Context) IsDryRun() bool { 112 | return c.Cfg.DryRun 113 | } 114 | 115 | func getClientConfigOrDie(kubeConfig string, qps float32, burst int) *rest.Config { 116 | var cfg *rest.Config 117 | if kubeConfig != "" { 118 | clientCfg, err := clientcmd.BuildConfigFromFlags("", kubeConfig) 119 | if err != nil { 120 | klog.Fatal(err) 121 | } 122 | cfg = clientCfg 123 | } else { 124 | clientCfg, err := rest.InClusterConfig() 125 | if err != nil { 126 | klog.Fatal(err) 127 | } 128 | cfg = clientCfg 129 | } 130 | cfg.QPS = qps 131 | cfg.Burst = burst 132 | return cfg 133 | } 134 | -------------------------------------------------------------------------------- /pkg/lbcfcontroller/admission/mutate_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 THL A29 Limited, a Tencent company. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package admission 18 | 19 | import ( 20 | "encoding/json" 21 | "testing" 22 | 23 | jsonpatch "github.com/evanphx/json-patch" 24 | v1 "k8s.io/api/core/v1" 25 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | "k8s.io/apimachinery/pkg/util/sets" 27 | ) 28 | 29 | func TestAddLabel(t *testing.T) { 30 | type testCase struct { 31 | obj *v1.Pod 32 | existkey string 33 | existValue string 34 | newKey string 35 | newValue string 36 | createLabel bool 37 | isReplace bool 38 | } 39 | cases := []testCase{ 40 | { 41 | obj: &v1.Pod{}, 42 | newKey: "test/key", 43 | newValue: "test/value", 44 | createLabel: true, 45 | isReplace: false, 46 | }, 47 | { 48 | obj: &v1.Pod{ 49 | ObjectMeta: metav1.ObjectMeta{ 50 | Labels: map[string]string{ 51 | "another/key": "another/value", 52 | }, 53 | }, 54 | }, 55 | existkey: "another/key", 56 | existValue: "another/value", 57 | newKey: "test/key", 58 | newValue: "test/value", 59 | createLabel: false, 60 | isReplace: false, 61 | }, 62 | { 63 | obj: &v1.Pod{ 64 | ObjectMeta: metav1.ObjectMeta{ 65 | Labels: map[string]string{ 66 | "test/key": "another/value", 67 | }, 68 | }, 69 | }, 70 | existkey: "test/key", 71 | existValue: "another/value", 72 | newKey: "test/key", 73 | newValue: "test/value", 74 | createLabel: false, 75 | isReplace: true, 76 | }, 77 | } 78 | 79 | for _, c := range cases { 80 | origin, err := json.Marshal(c.obj) 81 | if err != nil { 82 | t.Fatal(err.Error()) 83 | } 84 | p, err := json.Marshal([]Patch{addLabel(c.createLabel, c.isReplace, c.newKey, c.newValue)}) 85 | if err != nil { 86 | t.Fatal(err.Error()) 87 | } 88 | patch, err := jsonpatch.DecodePatch(p) 89 | if err != nil { 90 | t.Fatal(err.Error()) 91 | } 92 | modified, err := patch.Apply(origin) 93 | if err != nil { 94 | t.Fatal(err.Error()) 95 | } 96 | modifiedObj := &v1.Pod{} 97 | if err := json.Unmarshal(modified, modifiedObj); err != nil { 98 | t.Fatal(err.Error()) 99 | } 100 | v, ok := modifiedObj.Labels[c.newKey] 101 | if !ok { 102 | t.Fatalf("label not added") 103 | } else if v != c.newValue { 104 | t.Fatalf("expect value %s, get %s", c.newValue, v) 105 | } 106 | if c.existkey != "" { 107 | v, ok := modifiedObj.Labels[c.existkey] 108 | if !ok { 109 | t.Fatalf("existing key deleted") 110 | } 111 | if c.existkey == c.newKey && v != c.newValue { 112 | t.Fatalf("exist key should be replaced") 113 | } else if c.existkey != c.newKey && v != c.existValue { 114 | t.Fatalf("exist key should not be replaced") 115 | } 116 | } 117 | } 118 | } 119 | 120 | func TestAddFinalizer(t *testing.T) { 121 | type testCase struct { 122 | obj *v1.Pod 123 | newFinalizer string 124 | createFinalizer bool 125 | } 126 | 127 | cases := []testCase{ 128 | { 129 | obj: &v1.Pod{}, 130 | newFinalizer: "test/finalizer", 131 | createFinalizer: true, 132 | }, 133 | { 134 | obj: &v1.Pod{ 135 | ObjectMeta: metav1.ObjectMeta{ 136 | Finalizers: []string{ 137 | "another/finalizer", 138 | }, 139 | }, 140 | }, 141 | newFinalizer: "test/finalizer", 142 | createFinalizer: false, 143 | }, 144 | } 145 | 146 | for _, c := range cases { 147 | origin, err := json.Marshal(c.obj) 148 | if err != nil { 149 | t.Fatal(err.Error()) 150 | } 151 | p, err := json.Marshal([]Patch{addFinalizer(c.createFinalizer, c.newFinalizer)}) 152 | if err != nil { 153 | t.Fatal(err.Error()) 154 | } 155 | patch, err := jsonpatch.DecodePatch(p) 156 | if err != nil { 157 | t.Fatal(err.Error()) 158 | } 159 | modified, err := patch.Apply(origin) 160 | if err != nil { 161 | t.Fatal(err.Error()) 162 | } 163 | modifiedObj := &v1.Pod{} 164 | if err := json.Unmarshal(modified, modifiedObj); err != nil { 165 | t.Fatal(err.Error()) 166 | } 167 | 168 | if c.createFinalizer { 169 | if len(modifiedObj.Finalizers) != 1 { 170 | t.Fatalf("expect 1") 171 | } 172 | if modifiedObj.Finalizers[0] != c.newFinalizer { 173 | t.Fatalf("expect %s, get %s", c.newFinalizer, modifiedObj.Finalizers[0]) 174 | } 175 | } else { 176 | if len(modifiedObj.Finalizers) != len(c.obj.Finalizers)+1 { 177 | t.Fatalf("expect %d, get %d", len(c.obj.Finalizers)+1, len(modifiedObj.Finalizers)) 178 | } 179 | fs := sets.NewString(modifiedObj.Finalizers...) 180 | for _, exist := range c.obj.Finalizers { 181 | if !fs.Has(exist) { 182 | t.Fatalf("%s not found", exist) 183 | } 184 | } 185 | if !fs.Has(c.newFinalizer) { 186 | t.Fatalf("%s not added", c.newFinalizer) 187 | } 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1/fake/fake_bind.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package fake 22 | 23 | import ( 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | labels "k8s.io/apimachinery/pkg/labels" 26 | schema "k8s.io/apimachinery/pkg/runtime/schema" 27 | types "k8s.io/apimachinery/pkg/types" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | testing "k8s.io/client-go/testing" 30 | lbcftkestackiov1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1" 31 | ) 32 | 33 | // FakeBinds implements BindInterface 34 | type FakeBinds struct { 35 | Fake *FakeLbcfV1 36 | ns string 37 | } 38 | 39 | var bindsResource = schema.GroupVersionResource{Group: "lbcf.tkestack.io", Version: "v1", Resource: "binds"} 40 | 41 | var bindsKind = schema.GroupVersionKind{Group: "lbcf.tkestack.io", Version: "v1", Kind: "Bind"} 42 | 43 | // Get takes name of the bind, and returns the corresponding bind object, and an error if there is any. 44 | func (c *FakeBinds) Get(name string, options v1.GetOptions) (result *lbcftkestackiov1.Bind, err error) { 45 | obj, err := c.Fake. 46 | Invokes(testing.NewGetAction(bindsResource, c.ns, name), &lbcftkestackiov1.Bind{}) 47 | 48 | if obj == nil { 49 | return nil, err 50 | } 51 | return obj.(*lbcftkestackiov1.Bind), err 52 | } 53 | 54 | // List takes label and field selectors, and returns the list of Binds that match those selectors. 55 | func (c *FakeBinds) List(opts v1.ListOptions) (result *lbcftkestackiov1.BindList, err error) { 56 | obj, err := c.Fake. 57 | Invokes(testing.NewListAction(bindsResource, bindsKind, c.ns, opts), &lbcftkestackiov1.BindList{}) 58 | 59 | if obj == nil { 60 | return nil, err 61 | } 62 | 63 | label, _, _ := testing.ExtractFromListOptions(opts) 64 | if label == nil { 65 | label = labels.Everything() 66 | } 67 | list := &lbcftkestackiov1.BindList{ListMeta: obj.(*lbcftkestackiov1.BindList).ListMeta} 68 | for _, item := range obj.(*lbcftkestackiov1.BindList).Items { 69 | if label.Matches(labels.Set(item.Labels)) { 70 | list.Items = append(list.Items, item) 71 | } 72 | } 73 | return list, err 74 | } 75 | 76 | // Watch returns a watch.Interface that watches the requested binds. 77 | func (c *FakeBinds) Watch(opts v1.ListOptions) (watch.Interface, error) { 78 | return c.Fake. 79 | InvokesWatch(testing.NewWatchAction(bindsResource, c.ns, opts)) 80 | 81 | } 82 | 83 | // Create takes the representation of a bind and creates it. Returns the server's representation of the bind, and an error, if there is any. 84 | func (c *FakeBinds) Create(bind *lbcftkestackiov1.Bind) (result *lbcftkestackiov1.Bind, err error) { 85 | obj, err := c.Fake. 86 | Invokes(testing.NewCreateAction(bindsResource, c.ns, bind), &lbcftkestackiov1.Bind{}) 87 | 88 | if obj == nil { 89 | return nil, err 90 | } 91 | return obj.(*lbcftkestackiov1.Bind), err 92 | } 93 | 94 | // Update takes the representation of a bind and updates it. Returns the server's representation of the bind, and an error, if there is any. 95 | func (c *FakeBinds) Update(bind *lbcftkestackiov1.Bind) (result *lbcftkestackiov1.Bind, err error) { 96 | obj, err := c.Fake. 97 | Invokes(testing.NewUpdateAction(bindsResource, c.ns, bind), &lbcftkestackiov1.Bind{}) 98 | 99 | if obj == nil { 100 | return nil, err 101 | } 102 | return obj.(*lbcftkestackiov1.Bind), err 103 | } 104 | 105 | // UpdateStatus was generated because the type contains a Status member. 106 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 107 | func (c *FakeBinds) UpdateStatus(bind *lbcftkestackiov1.Bind) (*lbcftkestackiov1.Bind, error) { 108 | obj, err := c.Fake. 109 | Invokes(testing.NewUpdateSubresourceAction(bindsResource, "status", c.ns, bind), &lbcftkestackiov1.Bind{}) 110 | 111 | if obj == nil { 112 | return nil, err 113 | } 114 | return obj.(*lbcftkestackiov1.Bind), err 115 | } 116 | 117 | // Delete takes name of the bind and deletes it. Returns an error if one occurs. 118 | func (c *FakeBinds) Delete(name string, options *v1.DeleteOptions) error { 119 | _, err := c.Fake. 120 | Invokes(testing.NewDeleteAction(bindsResource, c.ns, name), &lbcftkestackiov1.Bind{}) 121 | 122 | return err 123 | } 124 | 125 | // DeleteCollection deletes a collection of objects. 126 | func (c *FakeBinds) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { 127 | action := testing.NewDeleteCollectionAction(bindsResource, c.ns, listOptions) 128 | 129 | _, err := c.Fake.Invokes(action, &lbcftkestackiov1.BindList{}) 130 | return err 131 | } 132 | 133 | // Patch applies the patch and returns the patched bind. 134 | func (c *FakeBinds) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *lbcftkestackiov1.Bind, err error) { 135 | obj, err := c.Fake. 136 | Invokes(testing.NewPatchSubresourceAction(bindsResource, c.ns, name, pt, data, subresources...), &lbcftkestackiov1.Bind{}) 137 | 138 | if obj == nil { 139 | return nil, err 140 | } 141 | return obj.(*lbcftkestackiov1.Bind), err 142 | } 143 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1/fake/fake_backendgroup.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package fake 22 | 23 | import ( 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | labels "k8s.io/apimachinery/pkg/labels" 26 | schema "k8s.io/apimachinery/pkg/runtime/schema" 27 | types "k8s.io/apimachinery/pkg/types" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | testing "k8s.io/client-go/testing" 30 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 31 | ) 32 | 33 | // FakeBackendGroups implements BackendGroupInterface 34 | type FakeBackendGroups struct { 35 | Fake *FakeLbcfV1beta1 36 | ns string 37 | } 38 | 39 | var backendgroupsResource = schema.GroupVersionResource{Group: "lbcf.tkestack.io", Version: "v1beta1", Resource: "backendgroups"} 40 | 41 | var backendgroupsKind = schema.GroupVersionKind{Group: "lbcf.tkestack.io", Version: "v1beta1", Kind: "BackendGroup"} 42 | 43 | // Get takes name of the backendGroup, and returns the corresponding backendGroup object, and an error if there is any. 44 | func (c *FakeBackendGroups) Get(name string, options v1.GetOptions) (result *v1beta1.BackendGroup, err error) { 45 | obj, err := c.Fake. 46 | Invokes(testing.NewGetAction(backendgroupsResource, c.ns, name), &v1beta1.BackendGroup{}) 47 | 48 | if obj == nil { 49 | return nil, err 50 | } 51 | return obj.(*v1beta1.BackendGroup), err 52 | } 53 | 54 | // List takes label and field selectors, and returns the list of BackendGroups that match those selectors. 55 | func (c *FakeBackendGroups) List(opts v1.ListOptions) (result *v1beta1.BackendGroupList, err error) { 56 | obj, err := c.Fake. 57 | Invokes(testing.NewListAction(backendgroupsResource, backendgroupsKind, c.ns, opts), &v1beta1.BackendGroupList{}) 58 | 59 | if obj == nil { 60 | return nil, err 61 | } 62 | 63 | label, _, _ := testing.ExtractFromListOptions(opts) 64 | if label == nil { 65 | label = labels.Everything() 66 | } 67 | list := &v1beta1.BackendGroupList{ListMeta: obj.(*v1beta1.BackendGroupList).ListMeta} 68 | for _, item := range obj.(*v1beta1.BackendGroupList).Items { 69 | if label.Matches(labels.Set(item.Labels)) { 70 | list.Items = append(list.Items, item) 71 | } 72 | } 73 | return list, err 74 | } 75 | 76 | // Watch returns a watch.Interface that watches the requested backendGroups. 77 | func (c *FakeBackendGroups) Watch(opts v1.ListOptions) (watch.Interface, error) { 78 | return c.Fake. 79 | InvokesWatch(testing.NewWatchAction(backendgroupsResource, c.ns, opts)) 80 | 81 | } 82 | 83 | // Create takes the representation of a backendGroup and creates it. Returns the server's representation of the backendGroup, and an error, if there is any. 84 | func (c *FakeBackendGroups) Create(backendGroup *v1beta1.BackendGroup) (result *v1beta1.BackendGroup, err error) { 85 | obj, err := c.Fake. 86 | Invokes(testing.NewCreateAction(backendgroupsResource, c.ns, backendGroup), &v1beta1.BackendGroup{}) 87 | 88 | if obj == nil { 89 | return nil, err 90 | } 91 | return obj.(*v1beta1.BackendGroup), err 92 | } 93 | 94 | // Update takes the representation of a backendGroup and updates it. Returns the server's representation of the backendGroup, and an error, if there is any. 95 | func (c *FakeBackendGroups) Update(backendGroup *v1beta1.BackendGroup) (result *v1beta1.BackendGroup, err error) { 96 | obj, err := c.Fake. 97 | Invokes(testing.NewUpdateAction(backendgroupsResource, c.ns, backendGroup), &v1beta1.BackendGroup{}) 98 | 99 | if obj == nil { 100 | return nil, err 101 | } 102 | return obj.(*v1beta1.BackendGroup), err 103 | } 104 | 105 | // UpdateStatus was generated because the type contains a Status member. 106 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 107 | func (c *FakeBackendGroups) UpdateStatus(backendGroup *v1beta1.BackendGroup) (*v1beta1.BackendGroup, error) { 108 | obj, err := c.Fake. 109 | Invokes(testing.NewUpdateSubresourceAction(backendgroupsResource, "status", c.ns, backendGroup), &v1beta1.BackendGroup{}) 110 | 111 | if obj == nil { 112 | return nil, err 113 | } 114 | return obj.(*v1beta1.BackendGroup), err 115 | } 116 | 117 | // Delete takes name of the backendGroup and deletes it. Returns an error if one occurs. 118 | func (c *FakeBackendGroups) Delete(name string, options *v1.DeleteOptions) error { 119 | _, err := c.Fake. 120 | Invokes(testing.NewDeleteAction(backendgroupsResource, c.ns, name), &v1beta1.BackendGroup{}) 121 | 122 | return err 123 | } 124 | 125 | // DeleteCollection deletes a collection of objects. 126 | func (c *FakeBackendGroups) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { 127 | action := testing.NewDeleteCollectionAction(backendgroupsResource, c.ns, listOptions) 128 | 129 | _, err := c.Fake.Invokes(action, &v1beta1.BackendGroupList{}) 130 | return err 131 | } 132 | 133 | // Patch applies the patch and returns the patched backendGroup. 134 | func (c *FakeBackendGroups) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.BackendGroup, err error) { 135 | obj, err := c.Fake. 136 | Invokes(testing.NewPatchSubresourceAction(backendgroupsResource, c.ns, name, pt, data, subresources...), &v1beta1.BackendGroup{}) 137 | 138 | if obj == nil { 139 | return nil, err 140 | } 141 | return obj.(*v1beta1.BackendGroup), err 142 | } 143 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1/fake/fake_loadbalancer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package fake 22 | 23 | import ( 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | labels "k8s.io/apimachinery/pkg/labels" 26 | schema "k8s.io/apimachinery/pkg/runtime/schema" 27 | types "k8s.io/apimachinery/pkg/types" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | testing "k8s.io/client-go/testing" 30 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 31 | ) 32 | 33 | // FakeLoadBalancers implements LoadBalancerInterface 34 | type FakeLoadBalancers struct { 35 | Fake *FakeLbcfV1beta1 36 | ns string 37 | } 38 | 39 | var loadbalancersResource = schema.GroupVersionResource{Group: "lbcf.tkestack.io", Version: "v1beta1", Resource: "loadbalancers"} 40 | 41 | var loadbalancersKind = schema.GroupVersionKind{Group: "lbcf.tkestack.io", Version: "v1beta1", Kind: "LoadBalancer"} 42 | 43 | // Get takes name of the loadBalancer, and returns the corresponding loadBalancer object, and an error if there is any. 44 | func (c *FakeLoadBalancers) Get(name string, options v1.GetOptions) (result *v1beta1.LoadBalancer, err error) { 45 | obj, err := c.Fake. 46 | Invokes(testing.NewGetAction(loadbalancersResource, c.ns, name), &v1beta1.LoadBalancer{}) 47 | 48 | if obj == nil { 49 | return nil, err 50 | } 51 | return obj.(*v1beta1.LoadBalancer), err 52 | } 53 | 54 | // List takes label and field selectors, and returns the list of LoadBalancers that match those selectors. 55 | func (c *FakeLoadBalancers) List(opts v1.ListOptions) (result *v1beta1.LoadBalancerList, err error) { 56 | obj, err := c.Fake. 57 | Invokes(testing.NewListAction(loadbalancersResource, loadbalancersKind, c.ns, opts), &v1beta1.LoadBalancerList{}) 58 | 59 | if obj == nil { 60 | return nil, err 61 | } 62 | 63 | label, _, _ := testing.ExtractFromListOptions(opts) 64 | if label == nil { 65 | label = labels.Everything() 66 | } 67 | list := &v1beta1.LoadBalancerList{ListMeta: obj.(*v1beta1.LoadBalancerList).ListMeta} 68 | for _, item := range obj.(*v1beta1.LoadBalancerList).Items { 69 | if label.Matches(labels.Set(item.Labels)) { 70 | list.Items = append(list.Items, item) 71 | } 72 | } 73 | return list, err 74 | } 75 | 76 | // Watch returns a watch.Interface that watches the requested loadBalancers. 77 | func (c *FakeLoadBalancers) Watch(opts v1.ListOptions) (watch.Interface, error) { 78 | return c.Fake. 79 | InvokesWatch(testing.NewWatchAction(loadbalancersResource, c.ns, opts)) 80 | 81 | } 82 | 83 | // Create takes the representation of a loadBalancer and creates it. Returns the server's representation of the loadBalancer, and an error, if there is any. 84 | func (c *FakeLoadBalancers) Create(loadBalancer *v1beta1.LoadBalancer) (result *v1beta1.LoadBalancer, err error) { 85 | obj, err := c.Fake. 86 | Invokes(testing.NewCreateAction(loadbalancersResource, c.ns, loadBalancer), &v1beta1.LoadBalancer{}) 87 | 88 | if obj == nil { 89 | return nil, err 90 | } 91 | return obj.(*v1beta1.LoadBalancer), err 92 | } 93 | 94 | // Update takes the representation of a loadBalancer and updates it. Returns the server's representation of the loadBalancer, and an error, if there is any. 95 | func (c *FakeLoadBalancers) Update(loadBalancer *v1beta1.LoadBalancer) (result *v1beta1.LoadBalancer, err error) { 96 | obj, err := c.Fake. 97 | Invokes(testing.NewUpdateAction(loadbalancersResource, c.ns, loadBalancer), &v1beta1.LoadBalancer{}) 98 | 99 | if obj == nil { 100 | return nil, err 101 | } 102 | return obj.(*v1beta1.LoadBalancer), err 103 | } 104 | 105 | // UpdateStatus was generated because the type contains a Status member. 106 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 107 | func (c *FakeLoadBalancers) UpdateStatus(loadBalancer *v1beta1.LoadBalancer) (*v1beta1.LoadBalancer, error) { 108 | obj, err := c.Fake. 109 | Invokes(testing.NewUpdateSubresourceAction(loadbalancersResource, "status", c.ns, loadBalancer), &v1beta1.LoadBalancer{}) 110 | 111 | if obj == nil { 112 | return nil, err 113 | } 114 | return obj.(*v1beta1.LoadBalancer), err 115 | } 116 | 117 | // Delete takes name of the loadBalancer and deletes it. Returns an error if one occurs. 118 | func (c *FakeLoadBalancers) Delete(name string, options *v1.DeleteOptions) error { 119 | _, err := c.Fake. 120 | Invokes(testing.NewDeleteAction(loadbalancersResource, c.ns, name), &v1beta1.LoadBalancer{}) 121 | 122 | return err 123 | } 124 | 125 | // DeleteCollection deletes a collection of objects. 126 | func (c *FakeLoadBalancers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { 127 | action := testing.NewDeleteCollectionAction(loadbalancersResource, c.ns, listOptions) 128 | 129 | _, err := c.Fake.Invokes(action, &v1beta1.LoadBalancerList{}) 130 | return err 131 | } 132 | 133 | // Patch applies the patch and returns the patched loadBalancer. 134 | func (c *FakeLoadBalancers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.LoadBalancer, err error) { 135 | obj, err := c.Fake. 136 | Invokes(testing.NewPatchSubresourceAction(loadbalancersResource, c.ns, name, pt, data, subresources...), &v1beta1.LoadBalancer{}) 137 | 138 | if obj == nil { 139 | return nil, err 140 | } 141 | return obj.(*v1beta1.LoadBalancer), err 142 | } 143 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1/fake/fake_backendrecord.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package fake 22 | 23 | import ( 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | labels "k8s.io/apimachinery/pkg/labels" 26 | schema "k8s.io/apimachinery/pkg/runtime/schema" 27 | types "k8s.io/apimachinery/pkg/types" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | testing "k8s.io/client-go/testing" 30 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 31 | ) 32 | 33 | // FakeBackendRecords implements BackendRecordInterface 34 | type FakeBackendRecords struct { 35 | Fake *FakeLbcfV1beta1 36 | ns string 37 | } 38 | 39 | var backendrecordsResource = schema.GroupVersionResource{Group: "lbcf.tkestack.io", Version: "v1beta1", Resource: "backendrecords"} 40 | 41 | var backendrecordsKind = schema.GroupVersionKind{Group: "lbcf.tkestack.io", Version: "v1beta1", Kind: "BackendRecord"} 42 | 43 | // Get takes name of the backendRecord, and returns the corresponding backendRecord object, and an error if there is any. 44 | func (c *FakeBackendRecords) Get(name string, options v1.GetOptions) (result *v1beta1.BackendRecord, err error) { 45 | obj, err := c.Fake. 46 | Invokes(testing.NewGetAction(backendrecordsResource, c.ns, name), &v1beta1.BackendRecord{}) 47 | 48 | if obj == nil { 49 | return nil, err 50 | } 51 | return obj.(*v1beta1.BackendRecord), err 52 | } 53 | 54 | // List takes label and field selectors, and returns the list of BackendRecords that match those selectors. 55 | func (c *FakeBackendRecords) List(opts v1.ListOptions) (result *v1beta1.BackendRecordList, err error) { 56 | obj, err := c.Fake. 57 | Invokes(testing.NewListAction(backendrecordsResource, backendrecordsKind, c.ns, opts), &v1beta1.BackendRecordList{}) 58 | 59 | if obj == nil { 60 | return nil, err 61 | } 62 | 63 | label, _, _ := testing.ExtractFromListOptions(opts) 64 | if label == nil { 65 | label = labels.Everything() 66 | } 67 | list := &v1beta1.BackendRecordList{ListMeta: obj.(*v1beta1.BackendRecordList).ListMeta} 68 | for _, item := range obj.(*v1beta1.BackendRecordList).Items { 69 | if label.Matches(labels.Set(item.Labels)) { 70 | list.Items = append(list.Items, item) 71 | } 72 | } 73 | return list, err 74 | } 75 | 76 | // Watch returns a watch.Interface that watches the requested backendRecords. 77 | func (c *FakeBackendRecords) Watch(opts v1.ListOptions) (watch.Interface, error) { 78 | return c.Fake. 79 | InvokesWatch(testing.NewWatchAction(backendrecordsResource, c.ns, opts)) 80 | 81 | } 82 | 83 | // Create takes the representation of a backendRecord and creates it. Returns the server's representation of the backendRecord, and an error, if there is any. 84 | func (c *FakeBackendRecords) Create(backendRecord *v1beta1.BackendRecord) (result *v1beta1.BackendRecord, err error) { 85 | obj, err := c.Fake. 86 | Invokes(testing.NewCreateAction(backendrecordsResource, c.ns, backendRecord), &v1beta1.BackendRecord{}) 87 | 88 | if obj == nil { 89 | return nil, err 90 | } 91 | return obj.(*v1beta1.BackendRecord), err 92 | } 93 | 94 | // Update takes the representation of a backendRecord and updates it. Returns the server's representation of the backendRecord, and an error, if there is any. 95 | func (c *FakeBackendRecords) Update(backendRecord *v1beta1.BackendRecord) (result *v1beta1.BackendRecord, err error) { 96 | obj, err := c.Fake. 97 | Invokes(testing.NewUpdateAction(backendrecordsResource, c.ns, backendRecord), &v1beta1.BackendRecord{}) 98 | 99 | if obj == nil { 100 | return nil, err 101 | } 102 | return obj.(*v1beta1.BackendRecord), err 103 | } 104 | 105 | // UpdateStatus was generated because the type contains a Status member. 106 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 107 | func (c *FakeBackendRecords) UpdateStatus(backendRecord *v1beta1.BackendRecord) (*v1beta1.BackendRecord, error) { 108 | obj, err := c.Fake. 109 | Invokes(testing.NewUpdateSubresourceAction(backendrecordsResource, "status", c.ns, backendRecord), &v1beta1.BackendRecord{}) 110 | 111 | if obj == nil { 112 | return nil, err 113 | } 114 | return obj.(*v1beta1.BackendRecord), err 115 | } 116 | 117 | // Delete takes name of the backendRecord and deletes it. Returns an error if one occurs. 118 | func (c *FakeBackendRecords) Delete(name string, options *v1.DeleteOptions) error { 119 | _, err := c.Fake. 120 | Invokes(testing.NewDeleteAction(backendrecordsResource, c.ns, name), &v1beta1.BackendRecord{}) 121 | 122 | return err 123 | } 124 | 125 | // DeleteCollection deletes a collection of objects. 126 | func (c *FakeBackendRecords) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { 127 | action := testing.NewDeleteCollectionAction(backendrecordsResource, c.ns, listOptions) 128 | 129 | _, err := c.Fake.Invokes(action, &v1beta1.BackendRecordList{}) 130 | return err 131 | } 132 | 133 | // Patch applies the patch and returns the patched backendRecord. 134 | func (c *FakeBackendRecords) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.BackendRecord, err error) { 135 | obj, err := c.Fake. 136 | Invokes(testing.NewPatchSubresourceAction(backendrecordsResource, c.ns, name, pt, data, subresources...), &v1beta1.BackendRecord{}) 137 | 138 | if obj == nil { 139 | return nil, err 140 | } 141 | return obj.(*v1beta1.BackendRecord), err 142 | } 143 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # CONTRIBUTING 2 | 3 | Welcome to [report Issues](https://github.com/tkestack/lb-controlling-framework/issues) or [pull requests](https://github.com/tkestack/lb-controlling-framework/pulls). It's recommended to read the following Contributing Guide first before contributing. 4 | 5 | This document provides a set of best practices for open source contributions - bug reports, code submissions / pull requests, etc. 6 | 7 | ## Issues 8 | 9 | We use Github Issues to track public bugs and feature requests. 10 | 11 | ### Due diligence 12 | 13 | Before submitting a issue, please do the following: 14 | 15 | * Perform **basic troubleshooting** steps: 16 | * Make sure you’re on the latest version. If you’re not on the most recent version, your problem may have been solved already! Upgrading is always the best first step. 17 | * Try older versions. If you’re already on the latest release, try rolling back a few minor versions (e.g. if on 1.7, try 1.5 or 1.6) and see if the problem goes away. This will help the devs narrow down when the problem first arose in the commit log. 18 | * Try switching up dependency versions. If the software in question has dependencies (other libraries, etc) try upgrading/downgrading those as well. 19 | * Search the project’s bug/issue tracker to make sure it’s not a known issue. 20 | * If you don’t find a pre-existing issue, consider checking with the mailing list and/or IRC channel in case the problem is non-bug-related. 21 | 22 | ### What to put in your bug report 23 | 24 | Make sure your report gets the attention it deserves: bug reports with missing information may be ignored or punted back to you, delaying a fix. The below constitutes a bare minimum; more info is almost always better: 25 | 26 | * What version of the core programming language interpreter/compiler are you using? For example, if it’s a Golang project, are you using Golang 1.13? Golang 1.12? 27 | * What operating system are you on? Windows? (32-bit? 64-bit?) Mac OS X? (10.14? 10.10?) Linux? (Which distro? Which version of that distro? 32 or 64 bits?) Again, more detail is better. 28 | * Which version or versions of the software are you using? Ideally, you followed the advice above and have ruled out (or verified that the problem exists in) a few different versions. 29 | * How can the developers recreate the bug on their end? If possible, include a copy of your code, the command you used to invoke it, and the full output of your run (if applicable.) A common tactic is to pare down your code until a simple (but still bug-causing) “base case” remains. Not only can this help you identify problems which aren’t real bugs, but it means the developer can get to fixing the bug faster. 30 | 31 | ## Pull Requests 32 | 33 | We strongly welcome your pull request to make TKEStack project better. 34 | 35 | ### Licensing of contributed material 36 | 37 | Keep in mind as you contribute, that code, docs and other material submitted to open source projects are usually considered licensed under the same terms as the rest of the work. 38 | 39 | Anything submitted to a project falls under the licensing terms in the repository’s top level LICENSE file. Per-file copyright/license headers are typically extraneous and undesirable. Please don’t add your own copyright headers to new files unless the project’s license actually requires them! 40 | 41 | ### Branch Management 42 | 43 | There are three main branches here: 44 | 45 | 1. `master` branch. 46 | 1. It is the latest (pre-)release branch. We use `master` for tags, with version number `1.1.0`, `1.2.0`, `1.3.0`... 47 | 2. **Don't submit any PR on `master` branch.** 48 | 2. `dev` branch. 49 | 1. It is our stable developing branch. After full testing, `dev` will be merged to `master` branch for the next release. 50 | 2. **You are recommended to submit bugfix or feature PR on `dev` branch.** 51 | 3. `hotfix` branch. 52 | 1. It is the latest tag version for hot fix. If we accept your pull request, we may just tag with version number `1.1.1`, `1.2.3`. 53 | 2. **Only submit urgent PR on `hotfix` branch for next specific release.** 54 | 55 | Normal bugfix or feature request should be submitted to `dev` branch. After full testing, we will merge them to `master` branch for the next release. 56 | 57 | If you have some urgent bugfixes on a published version, but the `master` branch have already far away with the latest tag version, you can submit a PR on hotfix. And it will be cherry picked to `dev` branch if it is possible. 58 | 59 | ``` 60 | master 61 | ↑ 62 | dev <--- hotfix PR 63 | ↑ 64 | feature/bugfix PR 65 | ``` 66 | 67 | ### Make Pull Requests 68 | 69 | The code team will monitor all pull request, we run some code check and test on it. After all tests passed, we will accecpt this PR. But it won't merge to `master` branch at once, which have some delay. 70 | 71 | Before submitting a pull request, please make sure the followings are done: 72 | 73 | 1. Fork the repo and create your branch from `master` or `hotfix`. 74 | 2. Update code or documentation if you have changed APIs. 75 | 3. Add the copyright notice to the top of any new files you've added. 76 | 4. Check your code lints and checkstyles. 77 | 5. Test and test again your code. 78 | 6. Now, you can submit your pull request on `dev` or `hotfix` branch. 79 | 80 | ## Code Conventions 81 | 82 | Use [Kubernetes Code Conventions](https://github.com/kubernetes/community/blob/master/contributors/guide/coding-conventions.md) for all projects in the TKEStack organization. 83 | 84 | ## Documentation isn’t optional 85 | 86 | It’s not! Patches without documentation will be returned to sender. By “documentation” we mean: 87 | 88 | * Docstrings must be created or updated for public API functions/methods/etc. (This step is optional for some bugfixes.) 89 | * New features should ideally include updates to prose documentation, including useful example code snippets. 90 | * All submissions should have a changelog entry crediting the contributor and/or any individuals instrumental in identifying the problem. 91 | 92 | ## Tests aren’t optional 93 | 94 | Any bugfix that doesn’t include a test proving the existence of the bug being fixed, may be suspect. Ditto for new features that can’t prove they actually work. 95 | 96 | We’ve found that test-first development really helps make features better architected and identifies potential edge cases earlier instead of later. Writing tests before the implementation is strongly encouraged. 97 | -------------------------------------------------------------------------------- /pkg/lbcfcontroller/admission/admission_webhook_server_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 THL A29 Limited, a Tencent company. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package admission 18 | 19 | import ( 20 | "k8s.io/api/admission/v1beta1" 21 | "k8s.io/apimachinery/pkg/types" 22 | "testing" 23 | ) 24 | 25 | func TestValidate_OperationCreate(t *testing.T) { 26 | var createCnt, updateCnt, deleteCnt int 27 | createFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 28 | createCnt++ 29 | return &v1beta1.AdmissionResponse{ 30 | Allowed: true, 31 | } 32 | } 33 | updateFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 34 | updateCnt++ 35 | return &v1beta1.AdmissionResponse{ 36 | Allowed: true, 37 | } 38 | } 39 | deleteFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 40 | deleteCnt++ 41 | return &v1beta1.AdmissionResponse{ 42 | Allowed: true, 43 | } 44 | } 45 | ar := &v1beta1.AdmissionReview{ 46 | Request: &v1beta1.AdmissionRequest{ 47 | UID: types.UID("12345"), 48 | Operation: v1beta1.Create, 49 | }, 50 | } 51 | resp := validate(ar, createFunc, updateFunc, deleteFunc) 52 | if !resp.Response.Allowed { 53 | t.Fatalf("expect allow") 54 | } else if resp.Response.UID != "12345" { 55 | t.Fatalf("expect uid 12345, get %v", resp.Response.UID) 56 | } else if updateCnt != 0 || deleteCnt != 0 { 57 | t.Fatalf("updateCnt: %d, deleteCnt: %d", updateCnt, deleteCnt) 58 | } else if createCnt != 1 { 59 | t.Fatalf("createCnt: %d", createCnt) 60 | } 61 | } 62 | 63 | func TestValidate_OperationUpdate(t *testing.T) { 64 | var createCnt, updateCnt, deleteCnt int 65 | createFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 66 | createCnt++ 67 | return &v1beta1.AdmissionResponse{ 68 | Allowed: true, 69 | } 70 | } 71 | updateFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 72 | updateCnt++ 73 | return &v1beta1.AdmissionResponse{ 74 | Allowed: true, 75 | } 76 | } 77 | deleteFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 78 | deleteCnt++ 79 | return &v1beta1.AdmissionResponse{ 80 | Allowed: true, 81 | } 82 | } 83 | ar := &v1beta1.AdmissionReview{ 84 | Request: &v1beta1.AdmissionRequest{ 85 | UID: types.UID("12345"), 86 | Operation: v1beta1.Update, 87 | }, 88 | } 89 | resp := validate(ar, createFunc, updateFunc, deleteFunc) 90 | if !resp.Response.Allowed { 91 | t.Fatalf("expect allow") 92 | } else if resp.Response.UID != "12345" { 93 | t.Fatalf("expect uid 12345, get %v", resp.Response.UID) 94 | } else if createCnt != 0 || deleteCnt != 0 { 95 | t.Fatalf("createCnt: %d, deleteCnt: %d", createCnt, deleteCnt) 96 | } else if updateCnt != 1 { 97 | t.Fatalf("updateCnt: %d", updateCnt) 98 | } 99 | } 100 | 101 | func TestValidate_OperationDelete(t *testing.T) { 102 | var createCnt, updateCnt, deleteCnt int 103 | createFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 104 | createCnt++ 105 | return &v1beta1.AdmissionResponse{ 106 | Allowed: true, 107 | } 108 | } 109 | updateFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 110 | updateCnt++ 111 | return &v1beta1.AdmissionResponse{ 112 | Allowed: true, 113 | } 114 | } 115 | deleteFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 116 | deleteCnt++ 117 | return &v1beta1.AdmissionResponse{ 118 | Allowed: true, 119 | } 120 | } 121 | ar := &v1beta1.AdmissionReview{ 122 | Request: &v1beta1.AdmissionRequest{ 123 | UID: types.UID("12345"), 124 | Operation: v1beta1.Delete, 125 | }, 126 | } 127 | resp := validate(ar, createFunc, updateFunc, deleteFunc) 128 | if !resp.Response.Allowed { 129 | t.Fatalf("expect allow") 130 | } else if resp.Response.UID != "12345" { 131 | t.Fatalf("expect uid 12345, get %v", resp.Response.UID) 132 | } else if createCnt != 0 || updateCnt != 0 { 133 | t.Fatalf("createCnt: %d, updateCnt: %d", createCnt, updateCnt) 134 | } else if deleteCnt != 1 { 135 | t.Fatalf("deleteCnt: %d", deleteCnt) 136 | } 137 | } 138 | 139 | func TestValidate_OperationConnect(t *testing.T) { 140 | var createCnt, updateCnt, deleteCnt int 141 | createFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 142 | createCnt++ 143 | return &v1beta1.AdmissionResponse{ 144 | Allowed: true, 145 | } 146 | } 147 | updateFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 148 | updateCnt++ 149 | return &v1beta1.AdmissionResponse{ 150 | Allowed: true, 151 | } 152 | } 153 | deleteFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 154 | deleteCnt++ 155 | return &v1beta1.AdmissionResponse{ 156 | Allowed: true, 157 | } 158 | } 159 | ar := &v1beta1.AdmissionReview{ 160 | Request: &v1beta1.AdmissionRequest{ 161 | UID: types.UID("12345"), 162 | Operation: v1beta1.Connect, 163 | }, 164 | } 165 | resp := validate(ar, createFunc, updateFunc, deleteFunc) 166 | if !resp.Response.Allowed { 167 | t.Fatalf("expect allow") 168 | } else if resp.Response.UID != "12345" { 169 | t.Fatalf("expect uid 12345, get %v", resp.Response.UID) 170 | } else if createCnt != 0 || updateCnt != 0 || deleteCnt != 0 { 171 | t.Fatalf("createCnt: %d, updateCnt: %d, deleteCnt: %d", createCnt, updateCnt, deleteCnt) 172 | } 173 | } 174 | 175 | func TestMutate(t *testing.T) { 176 | mutateFunc := func(*v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { 177 | return &v1beta1.AdmissionResponse{ 178 | Allowed: true, 179 | } 180 | } 181 | ar := &v1beta1.AdmissionReview{ 182 | Request: &v1beta1.AdmissionRequest{ 183 | UID: types.UID("12345"), 184 | Operation: v1beta1.Delete, 185 | }, 186 | } 187 | resp := mutate(ar, mutateFunc) 188 | if !resp.Response.Allowed { 189 | t.Fatalf("expect allow") 190 | } else if resp.Response.UID != "12345" { 191 | t.Fatalf("expect uid 12345, get %v", resp.Response.UID) 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /pkg/client-go/clientset/versioned/typed/lbcf.tkestack.io/v1beta1/fake/fake_loadbalancerdriver.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Tencent is pleased to support the open source community by making TKEStack 3 | * available. 4 | * 5 | * Copyright (C) 2012-2019 Tencent. All Rights Reserved. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 8 | * this file except in compliance with the License. You may obtain a copy of the 9 | * License at 10 | * 11 | * https://opensource.org/licenses/Apache-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations under the License. 17 | */ 18 | 19 | // Code generated by client-gen. DO NOT EDIT. 20 | 21 | package fake 22 | 23 | import ( 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | labels "k8s.io/apimachinery/pkg/labels" 26 | schema "k8s.io/apimachinery/pkg/runtime/schema" 27 | types "k8s.io/apimachinery/pkg/types" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | testing "k8s.io/client-go/testing" 30 | v1beta1 "tkestack.io/lb-controlling-framework/pkg/apis/lbcf.tkestack.io/v1beta1" 31 | ) 32 | 33 | // FakeLoadBalancerDrivers implements LoadBalancerDriverInterface 34 | type FakeLoadBalancerDrivers struct { 35 | Fake *FakeLbcfV1beta1 36 | ns string 37 | } 38 | 39 | var loadbalancerdriversResource = schema.GroupVersionResource{Group: "lbcf.tkestack.io", Version: "v1beta1", Resource: "loadbalancerdrivers"} 40 | 41 | var loadbalancerdriversKind = schema.GroupVersionKind{Group: "lbcf.tkestack.io", Version: "v1beta1", Kind: "LoadBalancerDriver"} 42 | 43 | // Get takes name of the loadBalancerDriver, and returns the corresponding loadBalancerDriver object, and an error if there is any. 44 | func (c *FakeLoadBalancerDrivers) Get(name string, options v1.GetOptions) (result *v1beta1.LoadBalancerDriver, err error) { 45 | obj, err := c.Fake. 46 | Invokes(testing.NewGetAction(loadbalancerdriversResource, c.ns, name), &v1beta1.LoadBalancerDriver{}) 47 | 48 | if obj == nil { 49 | return nil, err 50 | } 51 | return obj.(*v1beta1.LoadBalancerDriver), err 52 | } 53 | 54 | // List takes label and field selectors, and returns the list of LoadBalancerDrivers that match those selectors. 55 | func (c *FakeLoadBalancerDrivers) List(opts v1.ListOptions) (result *v1beta1.LoadBalancerDriverList, err error) { 56 | obj, err := c.Fake. 57 | Invokes(testing.NewListAction(loadbalancerdriversResource, loadbalancerdriversKind, c.ns, opts), &v1beta1.LoadBalancerDriverList{}) 58 | 59 | if obj == nil { 60 | return nil, err 61 | } 62 | 63 | label, _, _ := testing.ExtractFromListOptions(opts) 64 | if label == nil { 65 | label = labels.Everything() 66 | } 67 | list := &v1beta1.LoadBalancerDriverList{ListMeta: obj.(*v1beta1.LoadBalancerDriverList).ListMeta} 68 | for _, item := range obj.(*v1beta1.LoadBalancerDriverList).Items { 69 | if label.Matches(labels.Set(item.Labels)) { 70 | list.Items = append(list.Items, item) 71 | } 72 | } 73 | return list, err 74 | } 75 | 76 | // Watch returns a watch.Interface that watches the requested loadBalancerDrivers. 77 | func (c *FakeLoadBalancerDrivers) Watch(opts v1.ListOptions) (watch.Interface, error) { 78 | return c.Fake. 79 | InvokesWatch(testing.NewWatchAction(loadbalancerdriversResource, c.ns, opts)) 80 | 81 | } 82 | 83 | // Create takes the representation of a loadBalancerDriver and creates it. Returns the server's representation of the loadBalancerDriver, and an error, if there is any. 84 | func (c *FakeLoadBalancerDrivers) Create(loadBalancerDriver *v1beta1.LoadBalancerDriver) (result *v1beta1.LoadBalancerDriver, err error) { 85 | obj, err := c.Fake. 86 | Invokes(testing.NewCreateAction(loadbalancerdriversResource, c.ns, loadBalancerDriver), &v1beta1.LoadBalancerDriver{}) 87 | 88 | if obj == nil { 89 | return nil, err 90 | } 91 | return obj.(*v1beta1.LoadBalancerDriver), err 92 | } 93 | 94 | // Update takes the representation of a loadBalancerDriver and updates it. Returns the server's representation of the loadBalancerDriver, and an error, if there is any. 95 | func (c *FakeLoadBalancerDrivers) Update(loadBalancerDriver *v1beta1.LoadBalancerDriver) (result *v1beta1.LoadBalancerDriver, err error) { 96 | obj, err := c.Fake. 97 | Invokes(testing.NewUpdateAction(loadbalancerdriversResource, c.ns, loadBalancerDriver), &v1beta1.LoadBalancerDriver{}) 98 | 99 | if obj == nil { 100 | return nil, err 101 | } 102 | return obj.(*v1beta1.LoadBalancerDriver), err 103 | } 104 | 105 | // UpdateStatus was generated because the type contains a Status member. 106 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 107 | func (c *FakeLoadBalancerDrivers) UpdateStatus(loadBalancerDriver *v1beta1.LoadBalancerDriver) (*v1beta1.LoadBalancerDriver, error) { 108 | obj, err := c.Fake. 109 | Invokes(testing.NewUpdateSubresourceAction(loadbalancerdriversResource, "status", c.ns, loadBalancerDriver), &v1beta1.LoadBalancerDriver{}) 110 | 111 | if obj == nil { 112 | return nil, err 113 | } 114 | return obj.(*v1beta1.LoadBalancerDriver), err 115 | } 116 | 117 | // Delete takes name of the loadBalancerDriver and deletes it. Returns an error if one occurs. 118 | func (c *FakeLoadBalancerDrivers) Delete(name string, options *v1.DeleteOptions) error { 119 | _, err := c.Fake. 120 | Invokes(testing.NewDeleteAction(loadbalancerdriversResource, c.ns, name), &v1beta1.LoadBalancerDriver{}) 121 | 122 | return err 123 | } 124 | 125 | // DeleteCollection deletes a collection of objects. 126 | func (c *FakeLoadBalancerDrivers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { 127 | action := testing.NewDeleteCollectionAction(loadbalancerdriversResource, c.ns, listOptions) 128 | 129 | _, err := c.Fake.Invokes(action, &v1beta1.LoadBalancerDriverList{}) 130 | return err 131 | } 132 | 133 | // Patch applies the patch and returns the patched loadBalancerDriver. 134 | func (c *FakeLoadBalancerDrivers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.LoadBalancerDriver, err error) { 135 | obj, err := c.Fake. 136 | Invokes(testing.NewPatchSubresourceAction(loadbalancerdriversResource, c.ns, name, pt, data, subresources...), &v1beta1.LoadBalancerDriver{}) 137 | 138 | if obj == nil { 139 | return nil, err 140 | } 141 | return obj.(*v1beta1.LoadBalancerDriver), err 142 | } 143 | --------------------------------------------------------------------------------