├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ └── issue-template.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── cmd └── main.go ├── deploy ├── crd.yml ├── deployment.yml ├── rbac.yml └── sa.yml ├── docs └── images │ └── controller.png ├── example └── test-vm.yml ├── go.mod ├── go.sum ├── hack ├── k8s │ ├── boilerplate.go.txt │ ├── tools.go │ ├── update-generated.sh │ └── verify-codegen.sh └── test-go.sh └── pkg ├── apis └── cloudnative │ ├── register.go │ └── v1alpha1 │ ├── doc.go │ ├── register.go │ ├── types.go │ └── zz_generated.deepcopy.go ├── controller ├── controller.go └── util.go ├── driver ├── docker.go └── driver.go ├── generated ├── clientset │ └── versioned │ │ ├── clientset.go │ │ ├── doc.go │ │ ├── fake │ │ ├── clientset_generated.go │ │ ├── doc.go │ │ └── register.go │ │ ├── scheme │ │ ├── doc.go │ │ └── register.go │ │ └── typed │ │ └── cloudnative │ │ └── v1alpha1 │ │ ├── cloudnative_client.go │ │ ├── doc.go │ │ ├── fake │ │ ├── doc.go │ │ ├── fake_cloudnative_client.go │ │ └── fake_virtualmachine.go │ │ ├── generated_expansion.go │ │ └── virtualmachine.go ├── informers │ └── externalversions │ │ ├── cloudnative │ │ ├── interface.go │ │ └── v1alpha1 │ │ │ ├── interface.go │ │ │ └── virtualmachine.go │ │ ├── factory.go │ │ ├── generic.go │ │ └── internalinterfaces │ │ └── factory_interfaces.go └── listers │ └── cloudnative │ └── v1alpha1 │ ├── expansion_generated.go │ └── virtualmachine.go └── version ├── version.go └── version_test.go /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @kairen 2 | 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Issue template 3 | about: The template for reporting issues. 4 | title: Issue brief description 5 | labels: 6 | assignees: 7 | 8 | --- 9 | 10 | 11 | 12 | **Is this a BUG REPORT or FEATURE REQUEST?**: 13 | 14 | **What happened**: 15 | 16 | **What you expected to happen**: 17 | 18 | **How to reproduce it (as minimally and precisely as possible)**: 19 | 20 | **Anything else we need to know?**: 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | **Before submitting a pull request**, please make sure the following is done: 4 | 5 | ### Checklist 6 | 7 | - [ ] Fork [the repository](https://github.com/cloud-native-taiwan/controller101) and create your new branch from `master`. 8 | - [ ] Please mention the name of community in Pull Request title. 9 | - [ ] Git Commit Messages 10 | - [ ] Use the present tense (Also in Pull Request title): "Add feature" not "Added feature" 11 | - [ ] Use the imperative mood (Also in Pull Request title): "Move cursor to..." not "Moves cursor to..." 12 | - [ ] Use rebase to squash/fixup dummy/unnecessary commits into only one commit. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.exe~ 3 | *.dll 4 | *.so 5 | *.dylib 6 | *.out 7 | 8 | .DS_Store 9 | vendor/ 10 | out/ 11 | tmp/ 12 | .vscode/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | os: linux 3 | go: 4 | - 1.12.x 5 | go_import_path: github.com/cloud-native-taiwan/controller101 6 | env: 7 | - GO111MODULE=on 8 | script: 9 | - make test 10 | - make verify-codegen 11 | - make 12 | after_success: 13 | - bash <(curl -s https://codecov.io/bash) 14 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM kairen/golang-dep:1.12-alpine AS build 2 | LABEL maintainer="Kyle Bai " 3 | 4 | ENV GOPATH "/go" 5 | ENV PROJECT_PATH "$GOPATH/src/github.com/cloud-native-taiwan/controller101" 6 | ENV GO111MODULE "on" 7 | 8 | COPY . $PROJECT_PATH 9 | RUN cd $PROJECT_PATH && \ 10 | make && mv out/controller /tmp/controller 11 | 12 | # Running stage 13 | FROM alpine:3.7 14 | COPY --from=build /tmp/controller /bin/controller 15 | ENTRYPOINT ["controller"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION_MAJOR ?= 0 2 | VERSION_MINOR ?= 1 3 | VERSION_BUILD ?= 0 4 | VERSION ?= v$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_BUILD) 5 | 6 | ORG := github.com 7 | OWNER := cloud-native-taiwan 8 | REPOPATH ?= $(ORG)/$(OWNER)/controller101 9 | 10 | $(shell mkdir -p ./out) 11 | 12 | ############ 13 | # Building # 14 | ############ 15 | 16 | .PHONY: build 17 | build: out/controller 18 | 19 | .PHONY: out/controller 20 | out/controller: 21 | go build -ldflags="-s -w -X $(REPOPATH)/pkg/version.version=$(VERSION)" \ 22 | -a -o $@ cmd/main.go 23 | 24 | .PHONY: build_image 25 | build_image: 26 | docker build -t kairen/controller101:$(VERSION) . 27 | 28 | ############## 29 | # Generating # 30 | ############## 31 | 32 | vendor: 33 | go mod vendor 34 | 35 | .PHONY: verify-codegen 36 | verify-codegen: vendor 37 | ./hack/k8s/verify-codegen.sh 38 | 39 | .PHONY: codegen 40 | codegen: vendor 41 | ./hack/k8s/update-generated.sh 42 | 43 | ########### 44 | # Testing # 45 | ########### 46 | 47 | .PHONY: test 48 | test: 49 | ./hack/test-go.sh 50 | 51 | .PHONY: clean 52 | clean: 53 | rm -rf out/ vendor/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Controller 101 2 | This repository implements a simple controller for watching `VM` resources as defined with a [CRD](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/). 3 | 4 | This example will show you how to perform basic operations such as: 5 | 6 | * [x] How to create a custom resource of type `VM` using CRD API. 7 | * [x] How to operate instances of type `VM`. 8 | * [x] How to implement a controller for handling an instance of type `VM` to move the current state towards the desired state. 9 | * [x] How to use Finalizer on instances of type `VM`. 10 | * [x] How to implement LeaseLock for multiple controllers. 11 | * [ ] How to expose metrics of the controller. 12 | 13 | ## Building from Source 14 | Clone the repo in whatever working directory you like, and run the following commands: 15 | 16 | ```sh 17 | $ export GO111MODULE=on 18 | $ git clone https://github.com/cloud-native-taiwan/controller101 19 | $ cd controller101 20 | $ make 21 | ``` 22 | 23 | ## Running 24 | Run the following command to debug: 25 | 26 | ```sh 27 | $ minikube start --kubernetes-version=v1.15.4 28 | $ eval $(minikube docker-env) 29 | $ POD_NAME=test1 go run cmd/main.go --kubeconfig=$HOME/.kube/config \ 30 | -v=3 --logtostderr \ 31 | --lease-lock-namespace=default \ 32 | --vm-driver=docker 33 | ... 34 | I1015 02:16:08.067269 53517 leaderelection.go:242] attempting to acquire leader lease default/controller101... 35 | I1015 02:16:08.083723 53517 leaderelection.go:252] successfully acquired lease default/controller101 36 | I1015 02:16:08.083830 53517 controller.go:77] Starting the controller 37 | I1015 02:16:08.083846 53517 controller.go:78] Waiting for the informer caches to sync 38 | I1015 02:16:08.185334 53517 controller.go:86] Started workers 39 | I1015 02:16:08.185379 53517 main.go:144] test1: leading 40 | ``` 41 | 42 | ## Deploy in the cluster 43 | Run the following command to deploy the controller: 44 | 45 | ```sh 46 | $ minikube start --kubernetes-version=v1.15.4 47 | $ minikube docker-env 48 | $ kubectl -n kube-system create secret generic docker-certs \ 49 | --from-file=$HOME/.minikube/certs/ca.pem \ 50 | --from-file=$HOME/.minikube/certs/cert.pem \ 51 | --from-file=$HOME/.minikube/certs/key.pem 52 | 53 | # Modify envs in `deploy/deployment.yml` to reflect you need values: 54 | $ kubectl apply -f deploy/ 55 | ``` -------------------------------------------------------------------------------- /cmd/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 main 18 | 19 | import ( 20 | "context" 21 | goflag "flag" 22 | "fmt" 23 | "os" 24 | "os/signal" 25 | "syscall" 26 | "time" 27 | 28 | "github.com/cloud-native-taiwan/controller101/pkg/controller" 29 | "github.com/cloud-native-taiwan/controller101/pkg/driver" 30 | cloudnative "github.com/cloud-native-taiwan/controller101/pkg/generated/clientset/versioned" 31 | cloudnativeinformer "github.com/cloud-native-taiwan/controller101/pkg/generated/informers/externalversions" 32 | "github.com/cloud-native-taiwan/controller101/pkg/version" 33 | flag "github.com/spf13/pflag" 34 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 35 | clientset "k8s.io/client-go/kubernetes" 36 | "k8s.io/client-go/rest" 37 | "k8s.io/client-go/tools/clientcmd" 38 | "k8s.io/client-go/tools/leaderelection" 39 | "k8s.io/client-go/tools/leaderelection/resourcelock" 40 | "k8s.io/klog" 41 | ) 42 | 43 | const defaultSyncTime = time.Second * 30 44 | 45 | var ( 46 | kubeconfig string 47 | showVersion bool 48 | threads int 49 | leaderElect bool 50 | id string 51 | leaseLockName string 52 | leaseLockNamespace string 53 | driverName string 54 | ) 55 | 56 | func parseFlags() { 57 | flag.StringVarP(&kubeconfig, "kubeconfig", "", "", "Absolute path to the kubeconfig file.") 58 | flag.IntVarP(&threads, "threads", "", 2, "Number of worker threads used by the controller.") 59 | flag.StringVarP(&id, "holder-identity", "", os.Getenv("POD_NAME"), "the holder identity name") 60 | flag.StringVarP(&driverName, "vm-driver", "", "", "Driver is one of: [fake docker].") 61 | flag.BoolVarP(&leaderElect, "leader-elect", "", true, "Start a leader election client and gain leadership before executing the main loop. ") 62 | flag.StringVar(&leaseLockName, "lease-lock-name", "controller101", "the lease lock resource name") 63 | flag.StringVar(&leaseLockNamespace, "lease-lock-namespace", os.Getenv("POD_NAMESPACE"), "the lease lock resource namespace") 64 | flag.BoolVarP(&showVersion, "version", "", false, "Display the version.") 65 | flag.CommandLine.AddGoFlagSet(goflag.CommandLine) 66 | flag.Parse() 67 | } 68 | 69 | func restConfig(kubeconfig string) (*rest.Config, error) { 70 | if kubeconfig != "" { 71 | cfg, err := clientcmd.BuildConfigFromFlags("", kubeconfig) 72 | if err != nil { 73 | return nil, err 74 | } 75 | return cfg, nil 76 | } 77 | 78 | cfg, err := rest.InClusterConfig() 79 | if err != nil { 80 | return nil, err 81 | } 82 | return cfg, nil 83 | } 84 | 85 | func main() { 86 | parseFlags() 87 | 88 | if showVersion { 89 | fmt.Fprintf(os.Stdout, "%s\n", version.GetVersion()) 90 | os.Exit(0) 91 | } 92 | 93 | k8scfg, err := restConfig(kubeconfig) 94 | if err != nil { 95 | klog.Fatalf("Error to build rest config: %s", err.Error()) 96 | } 97 | 98 | k8sclientset := clientset.NewForConfigOrDie(k8scfg) 99 | clientset, err := cloudnative.NewForConfig(k8scfg) 100 | if err != nil { 101 | klog.Fatalf("Error to build cloudnative clientset: %s", err.Error()) 102 | } 103 | 104 | var vmDriver driver.Interface 105 | switch driverName { 106 | case "docker": 107 | docker, err := driver.NewDockerDriver() 108 | if err != nil { 109 | klog.Fatalf("Error to new docker driver: %s", err.Error()) 110 | } 111 | vmDriver = docker 112 | default: 113 | klog.Fatalf("The driver '%s' is not supported.", driverName) 114 | } 115 | 116 | informer := cloudnativeinformer.NewSharedInformerFactory(clientset, defaultSyncTime) 117 | controller := controller.New(clientset, informer, vmDriver) 118 | ctx, cancel := context.WithCancel(context.Background()) 119 | signalChan := make(chan os.Signal, 1) 120 | signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM) 121 | 122 | if leaderElect { 123 | lock := &resourcelock.LeaseLock{ 124 | LeaseMeta: metav1.ObjectMeta{ 125 | Name: leaseLockName, 126 | Namespace: leaseLockNamespace, 127 | }, 128 | Client: k8sclientset.CoordinationV1(), 129 | LockConfig: resourcelock.ResourceLockConfig{ 130 | Identity: id, 131 | }, 132 | } 133 | go leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{ 134 | Lock: lock, 135 | ReleaseOnCancel: true, 136 | LeaseDuration: 60 * time.Second, 137 | RenewDeadline: 15 * time.Second, 138 | RetryPeriod: 5 * time.Second, 139 | Callbacks: leaderelection.LeaderCallbacks{ 140 | OnStartedLeading: func(ctx context.Context) { 141 | if err := controller.Run(ctx, threads); err != nil { 142 | klog.Fatalf("Error to run the controller instance: %s.", err) 143 | } 144 | klog.Infof("%s: leading", id) 145 | }, 146 | OnStoppedLeading: func() { 147 | controller.Stop() 148 | klog.Infof("%s: lost", id) 149 | }, 150 | }, 151 | }) 152 | } else { 153 | if err := controller.Run(ctx, threads); err != nil { 154 | klog.Fatalf("Error to run the controller instance: %s.", err) 155 | } 156 | } 157 | 158 | <-signalChan 159 | cancel() 160 | controller.Stop() 161 | } 162 | -------------------------------------------------------------------------------- /deploy/crd.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: virtualmachines.cloudnative.tw 5 | spec: 6 | group: cloudnative.tw 7 | version: v1alpha1 8 | names: 9 | kind: VirtualMachine 10 | singular: virtualmachine 11 | plural: virtualmachines 12 | shortNames: 13 | - vm 14 | - vms 15 | scope: Namespaced 16 | additionalPrinterColumns: 17 | - name: Status 18 | type: string 19 | JSONPath: .status.phase 20 | - name: CPU 21 | type: number 22 | JSONPath: .status.server.usage.cpu 23 | - name: Memory 24 | type: number 25 | JSONPath: .status.server.usage.memory 26 | - name: Age 27 | type: date 28 | JSONPath: .metadata.creationTimestamp -------------------------------------------------------------------------------- /deploy/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller101 5 | namespace: kube-system 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | k8s-app: controller101 11 | strategy: 12 | type: Recreate 13 | template: 14 | metadata: 15 | labels: 16 | k8s-app: controller101 17 | spec: 18 | priorityClassName: system-cluster-critical 19 | tolerations: 20 | - key: CriticalAddonsOnly 21 | operator: Exists 22 | - effect: NoSchedule 23 | key: node-role.kubernetes.io/master 24 | serviceAccountName: controller101 25 | containers: 26 | - name: controller 27 | image: kairen/controller101:v0.1.0 28 | env: 29 | - name: DOCKER_HOST 30 | value: "tcp://192.168.99.158:2376" 31 | - name: DOCKER_TLS_VERIFY 32 | value: "1" 33 | - name: DOCKER_CERT_PATH 34 | value: "/etc/docker-certs" 35 | args: 36 | - --v=2 37 | - --logtostderr=true 38 | - --vm-driver=docker 39 | - --leader-elect=false 40 | volumeMounts: 41 | - name: docker-certs 42 | mountPath: "/etc/docker-certs" 43 | readOnly: true 44 | volumes: 45 | - name: docker-certs 46 | secret: 47 | secretName: docker-certs 48 | -------------------------------------------------------------------------------- /deploy/rbac.yml: -------------------------------------------------------------------------------- 1 | kind: ClusterRole 2 | apiVersion: rbac.authorization.k8s.io/v1beta1 3 | metadata: 4 | name: controller101-role 5 | rules: 6 | - apiGroups: 7 | - cloudnative.tw 8 | resources: 9 | - "virtualmachines" 10 | verbs: 11 | - "*" 12 | --- 13 | kind: ClusterRoleBinding 14 | apiVersion: rbac.authorization.k8s.io/v1beta1 15 | metadata: 16 | name: controller101-rolebinding 17 | roleRef: 18 | apiGroup: rbac.authorization.k8s.io 19 | kind: ClusterRole 20 | name: controller101-role 21 | subjects: 22 | - kind: ServiceAccount 23 | namespace: kube-system 24 | name: controller101 -------------------------------------------------------------------------------- /deploy/sa.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: controller101 5 | namespace: kube-system -------------------------------------------------------------------------------- /docs/images/controller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kairen/controller101/53626123149c407352bd821fa818744b879e1795/docs/images/controller.png -------------------------------------------------------------------------------- /example/test-vm.yml: -------------------------------------------------------------------------------- 1 | apiVersion: cloudnative.tw/v1alpha1 2 | kind: VirtualMachine 3 | metadata: 4 | name: test-vm 5 | spec: 6 | resource: 7 | cpu: 1 8 | memory: 4G -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/cloud-native-taiwan/controller101 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/Microsoft/go-winio v0.4.14 // indirect 7 | github.com/docker/distribution v2.8.0+incompatible // indirect 8 | github.com/docker/docker v1.13.1 9 | github.com/docker/go-connections v0.4.0 // indirect 10 | github.com/docker/go-units v0.4.0 // indirect 11 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b 12 | github.com/opencontainers/go-digest v1.0.0-rc1 // indirect 13 | github.com/spf13/pflag v1.0.3 14 | github.com/stretchr/testify v1.3.0 15 | github.com/thoas/go-funk v0.4.0 16 | k8s.io/api v0.0.0-20191005115622-2e41325d9e4b 17 | k8s.io/apimachinery v0.0.0-20191005115455-e71eb83a557c 18 | k8s.io/client-go v0.0.0-20191005115821-b1fd78950135 19 | k8s.io/code-generator v0.0.0-20191003035328-700b1226c0bd 20 | k8s.io/klog v1.0.0 21 | ) 22 | 23 | replace ( 24 | golang.org/x/crypto => golang.org/x/crypto v0.0.0-20181025213731-e84da0312774 25 | golang.org/x/lint => golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1 26 | golang.org/x/oauth2 => golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a 27 | golang.org/x/sync => golang.org/x/sync v0.0.0-20181108010431-42b317875d0f 28 | golang.org/x/sys => golang.org/x/sys v0.0.0-20190209173611-3b5209105503 29 | golang.org/x/text => golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db 30 | golang.org/x/time => golang.org/x/time v0.0.0-20161028155119-f51c12702a4d 31 | k8s.io/api => k8s.io/api v0.0.0-20191005115622-2e41325d9e4b 32 | k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20191005115455-e71eb83a557c 33 | k8s.io/client-go => k8s.io/client-go v0.0.0-20191005115821-b1fd78950135 34 | k8s.io/code-generator => k8s.io/code-generator v0.0.0-20191003035328-700b1226c0bd 35 | ) 36 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= 5 | github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= 6 | github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= 7 | github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 8 | github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 9 | github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= 10 | github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= 11 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 12 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 13 | github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= 14 | github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= 15 | github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= 16 | github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 17 | github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= 18 | github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 19 | github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 20 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= 21 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 22 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 23 | github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 24 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 25 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 26 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 27 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 28 | github.com/docker/distribution v2.8.0+incompatible h1:l9EaZDICImO1ngI+uTifW+ZYvvz7fKISBAKpg+MbWbY= 29 | github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 30 | github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo= 31 | github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 32 | github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= 33 | github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= 34 | github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= 35 | github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 36 | github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= 37 | github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 38 | github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 39 | github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= 40 | github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 41 | github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I= 42 | github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 43 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 44 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 45 | github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 46 | github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= 47 | github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= 48 | github.com/go-openapi/jsonpointer v0.19.2 h1:A9+F4Dc/MCNB5jibxf6rRvOvR/iFgQdyNx9eIhnGqq0= 49 | github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= 50 | github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= 51 | github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w= 52 | github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= 53 | github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= 54 | github.com/go-openapi/spec v0.19.2 h1:SStNd1jRcYtfKCN7R0laGNs80WYYvn5CbBjM2sOmCrE= 55 | github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= 56 | github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= 57 | github.com/go-openapi/swag v0.19.2 h1:jvO6bCMBEilGwMfHhrd61zIID4oIFdwb76V17SM88dE= 58 | github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= 59 | github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I= 60 | github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 61 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= 62 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 63 | github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8= 64 | github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 65 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 66 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 67 | github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 68 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 69 | github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= 70 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 71 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 72 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 73 | github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= 74 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 75 | github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= 76 | github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= 77 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 78 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 79 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 80 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 81 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 82 | github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k= 83 | github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= 84 | github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= 85 | github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 86 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 87 | github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= 88 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 89 | github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= 90 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 91 | github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= 92 | github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 93 | github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 94 | github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= 95 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 96 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 97 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 98 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 99 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 100 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 101 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 102 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 103 | github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= 104 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 105 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 106 | github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 107 | github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63 h1:nTT4s92Dgz2HlrB2NaMgvlfqHH39OgMhA7z3PK7PGD4= 108 | github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 109 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 110 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 111 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 112 | github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 113 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 114 | github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= 115 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 116 | github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 117 | github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= 118 | github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 119 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 120 | github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= 121 | github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 122 | github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 123 | github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= 124 | github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 125 | github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= 126 | github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 127 | github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= 128 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 129 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 130 | github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 131 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 132 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 133 | github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= 134 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= 135 | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 136 | github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 137 | github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= 138 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 139 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 140 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 141 | github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 142 | github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 143 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 144 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 145 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 146 | github.com/thoas/go-funk v0.4.0 h1:KBaa5NL7NMtsFlQaD8nQMbDt1wuM+OOaNQyYNYQFhVo= 147 | github.com/thoas/go-funk v0.4.0/go.mod h1:mlR+dHGb+4YgXkf13rkQTuzrneeHANxOm6+ZnEV9HsA= 148 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 149 | golang.org/x/crypto v0.0.0-20181025213731-e84da0312774 h1:a4tQYYYuK9QdeO/+kEvNYyuR21S+7ve5EANok6hABhI= 150 | golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 151 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 152 | golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 153 | golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495 h1:I6A9Ag9FpEKOjcKrRNjQkPHawoXIhKyTGfvvjFAiiAk= 154 | golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 155 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 156 | golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 157 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 158 | golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 159 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 160 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 161 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 162 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 163 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 164 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 165 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 166 | golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68= 167 | golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 168 | golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA= 169 | golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 170 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 171 | golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7vhXAZQ9hiP+1Q/DMrWg= 172 | golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 173 | golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU= 174 | golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 175 | golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wktg7Jn/a/fNmr33HSj8g= 176 | golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 177 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 178 | golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 179 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 180 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 181 | golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 182 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 183 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 184 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 185 | golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 186 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac h1:MQEvx39qSf8vyrx3XRaOe+j1UDIzKwkYOVObRgGPVqI= 187 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 188 | gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw= 189 | gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= 190 | gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= 191 | gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e h1:jRyg0XfpwWlhEV8mDfdNGBeSJM2fuyh9Yjrnd8kF2Ts= 192 | gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= 193 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 194 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 195 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 196 | google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= 197 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 198 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 199 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 200 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 201 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 202 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 203 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 204 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 205 | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 206 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 207 | gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o= 208 | gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 209 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 210 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 211 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 212 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 213 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 214 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 215 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 216 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 217 | k8s.io/api v0.0.0-20191005115622-2e41325d9e4b h1:j1mSRwavnCC3Q5QpgH0ldhap5qeCnRuf7xl0l1VUzdM= 218 | k8s.io/api v0.0.0-20191005115622-2e41325d9e4b/go.mod h1:V9fqJJO3eGaWUKb9e6wH3fx7JXl1IaSC1VhSLk7GJjA= 219 | k8s.io/apimachinery v0.0.0-20191005115455-e71eb83a557c h1:FtM+eSMYMvnIMrryXaITj7oerp5l1uetUQ0/BKsc/rg= 220 | k8s.io/apimachinery v0.0.0-20191005115455-e71eb83a557c/go.mod h1:92mWDd8Ji2sw2157KIgino5wCxffA8KSvhW2oY4ypdw= 221 | k8s.io/client-go v0.0.0-20191005115821-b1fd78950135 h1:KRmmu0QoQRZxRuQVyzWs3fMyZ85ZJf7PpnnpH4FvuyU= 222 | k8s.io/client-go v0.0.0-20191005115821-b1fd78950135/go.mod h1:y9Rvsae8RfW0HpclmE1lCx4wUxrLDRhXv9gh8SWYhvc= 223 | k8s.io/code-generator v0.0.0-20191003035328-700b1226c0bd h1:5WjZ3cIbClYC5mJf+H/ODCo36y8rRqtZRxol4Ujln8c= 224 | k8s.io/code-generator v0.0.0-20191003035328-700b1226c0bd/go.mod h1:HC9p4y3SBN+txSs8x57qmNPXFZ/CxdCHiDTNnocCSEw= 225 | k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 226 | k8s.io/gengo v0.0.0-20190822140433-26a664648505 h1:ZY6yclUKVbZ+SdWnkfY+Je5vrMpKOxmGeKRbsXVmqYM= 227 | k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 228 | k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 229 | k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 230 | k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= 231 | k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= 232 | k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf h1:EYm5AW/UUDbnmnI+gK0TJDVK9qPLhM+sRHYanNKw0EQ= 233 | k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= 234 | k8s.io/utils v0.0.0-20190920012459-5008bf6f8cd6 h1:rfepARh/ECp66dk9TTmT//1PBkHffjnxhdOrgH4m+eA= 235 | k8s.io/utils v0.0.0-20190920012459-5008bf6f8cd6/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= 236 | modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= 237 | modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= 238 | modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= 239 | modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= 240 | modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= 241 | sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= 242 | sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= 243 | sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= 244 | -------------------------------------------------------------------------------- /hack/k8s/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | */ -------------------------------------------------------------------------------- /hack/k8s/tools.go: -------------------------------------------------------------------------------- 1 | // +build tools 2 | 3 | /* 4 | Copyright © 2019 The controller101 Authors. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-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, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | // This package imports things required by build scripts, to force `go mod` to see them as dependencies 20 | // See https://github.com/golang/go/issues/25922 21 | 22 | package tools 23 | 24 | import ( 25 | _ "k8s.io/code-generator" 26 | ) 27 | -------------------------------------------------------------------------------- /hack/k8s/update-generated.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright © 2019 The controller101 Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/../.. 22 | CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)} 23 | bash "${CODEGEN_PKG}"/generate-groups.sh "deepcopy,client,informer,lister" \ 24 | github.com/cloud-native-taiwan/controller101/pkg/generated \ 25 | github.com/cloud-native-taiwan/controller101/pkg/apis \ 26 | "cloudnative:v1alpha1" \ 27 | --output-base "$(dirname ${BASH_SOURCE})/../../../../../" \ 28 | --go-header-file ${SCRIPT_ROOT}/hack/k8s/boilerplate.go.txt -------------------------------------------------------------------------------- /hack/k8s/verify-codegen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright © 2019 The controller101 Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/../.. 22 | 23 | DIFFROOT="${SCRIPT_ROOT}/pkg" 24 | TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg" 25 | _tmp="${SCRIPT_ROOT}/_tmp" 26 | 27 | cleanup() { 28 | rm -rf "${_tmp}" 29 | } 30 | trap "cleanup" EXIT SIGINT 31 | 32 | cleanup 33 | 34 | mkdir -p "${TMP_DIFFROOT}" 35 | cp -a "${DIFFROOT}"/* "${TMP_DIFFROOT}" 36 | 37 | "${SCRIPT_ROOT}/hack/k8s/update-generated.sh" 38 | echo "diffing ${DIFFROOT} against freshly generated codegen" 39 | ret=0 40 | diff -Naupr "${DIFFROOT}" "${TMP_DIFFROOT}" || ret=$? 41 | cp -a "${TMP_DIFFROOT}"/* "${DIFFROOT}" 42 | if [[ $ret -eq 0 ]] 43 | then 44 | echo "${DIFFROOT} up to date." 45 | else 46 | echo "${DIFFROOT} is out of date. Please run hack/k8s/update-generated.sh" 47 | exit 1 48 | fi -------------------------------------------------------------------------------- /hack/test-go.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright © 2019 The controller101 Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | REPO_PATH="github.com/cloud-native-taiwan/controller101" 20 | 21 | COV_FILE=coverage.txt 22 | COV_TMP_FILE=coverage_tmp.txt 23 | 24 | echo "Running go tests..." 25 | cd ${GOPATH}/src/${REPO_PATH} 26 | rm -f out/$COV_FILE || true 27 | echo "mode: count" > out/$COV_FILE 28 | for pkg in $(go list -f '{{ if .TestGoFiles }} {{.ImportPath}} {{end}}' ./...); do 29 | go test -tags "container_image_ostree_stub containers_image_openpgp" -v $pkg -covermode=count -coverprofile=out/$COV_TMP_FILE 30 | tail -n +2 out/$COV_TMP_FILE >> out/$COV_FILE || (echo "Unable to append coverage for $pkg" && exit 1) 31 | done 32 | rm -rf out/$COV_TMP_FILE 33 | 34 | ignore="vendor\|\_gopath\|assets.go\|\_test.go\|out\|api" 35 | 36 | echo "Checking gofmt..." 37 | set +e 38 | files=$(gofmt -l -s . | grep -v ${ignore}) 39 | set -e 40 | if [[ $files ]]; then 41 | echo "Gofmt errors in files: $files" 42 | exit 1 43 | fi 44 | -------------------------------------------------------------------------------- /pkg/apis/cloudnative/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 cloudnative 18 | 19 | // GroupName is the group name used in this package 20 | const ( 21 | GroupName = "cloudnative.tw" 22 | ) 23 | -------------------------------------------------------------------------------- /pkg/apis/cloudnative/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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=cloudnative.tw 19 | 20 | // Package v1alpha1 is the v1alpha1 version of the API. 21 | package v1alpha1 // import "github.com/cloud-native-taiwan/controller101/pkg/apis/cloudnative/v1alpha1" 22 | -------------------------------------------------------------------------------- /pkg/apis/cloudnative/v1alpha1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 v1alpha1 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 | "github.com/cloud-native-taiwan/controller101/pkg/apis/cloudnative" 25 | ) 26 | 27 | // SchemeGroupVersion is group version used to register these objects 28 | var SchemeGroupVersion = schema.GroupVersion{Group: cloudnative.GroupName, Version: "v1alpha1"} 29 | 30 | // Kind takes an unqualified kind and returns back a Group qualified GroupKind 31 | func Kind(kind string) schema.GroupKind { 32 | return SchemeGroupVersion.WithKind(kind).GroupKind() 33 | } 34 | 35 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 36 | func Resource(resource string) schema.GroupResource { 37 | return SchemeGroupVersion.WithResource(resource).GroupResource() 38 | } 39 | 40 | var ( 41 | // SchemeBuilder initializes a scheme builder 42 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) 43 | // AddToScheme is a global function that registers this API group & version to a scheme 44 | AddToScheme = SchemeBuilder.AddToScheme 45 | ) 46 | 47 | // Adds the list of known types to Scheme. 48 | func addKnownTypes(scheme *runtime.Scheme) error { 49 | scheme.AddKnownTypes(SchemeGroupVersion, 50 | &VirtualMachine{}, 51 | &VirtualMachineList{}, 52 | ) 53 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /pkg/apis/cloudnative/v1alpha1/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 v1alpha1 18 | 19 | import ( 20 | corev1 "k8s.io/api/core/v1" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | ) 23 | 24 | // +genclient 25 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 26 | 27 | type VirtualMachine struct { 28 | metav1.TypeMeta `json:",inline"` 29 | metav1.ObjectMeta `json:"metadata,omitempty"` 30 | 31 | Spec VirtualMachineSpec `json:"spec"` 32 | Status VirtualMachineStatus `json:"status"` 33 | } 34 | 35 | type VirtualMachineSpec struct { 36 | Resource corev1.ResourceList `json:"resource"` 37 | } 38 | 39 | type VirtualMachinePhase string 40 | 41 | const ( 42 | VirtualMachineNone VirtualMachinePhase = "" 43 | VirtualMachineCreating VirtualMachinePhase = "Creating" 44 | VirtualMachineActive VirtualMachinePhase = "Active" 45 | VirtualMachineFailed VirtualMachinePhase = "Failed" 46 | VirtualMachineTerminating VirtualMachinePhase = "Terminating" 47 | VirtualMachineUnknown VirtualMachinePhase = "Unknown" 48 | ) 49 | 50 | type ResourceUsage struct { 51 | CPU float64 `json:"cpu"` 52 | Memory float64 `json:"memory"` 53 | } 54 | 55 | type ServerStatus struct { 56 | ID string `json:"id"` 57 | State string `json:"state"` 58 | Usage ResourceUsage `json:"usage"` 59 | } 60 | 61 | type VirtualMachineStatus struct { 62 | Phase VirtualMachinePhase `json:"phase"` 63 | Reason string `json:"reason,omitempty"` 64 | Server ServerStatus `json:"server,omitempty"` 65 | LastUpdateTime metav1.Time `json:"lastUpdateTime"` 66 | } 67 | 68 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 69 | 70 | type VirtualMachineList struct { 71 | metav1.TypeMeta `json:",inline"` 72 | metav1.ListMeta `json:"metadata"` 73 | 74 | Items []VirtualMachine `json:"items"` 75 | } 76 | -------------------------------------------------------------------------------- /pkg/apis/cloudnative/v1alpha1/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | // +build !ignore_autogenerated 2 | 3 | /* 4 | Copyright © 2019 The controller101 Authors. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-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, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | // Code generated by deepcopy-gen. DO NOT EDIT. 19 | 20 | package v1alpha1 21 | 22 | import ( 23 | v1 "k8s.io/api/core/v1" 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | ) 26 | 27 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 28 | func (in *ResourceUsage) DeepCopyInto(out *ResourceUsage) { 29 | *out = *in 30 | return 31 | } 32 | 33 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceUsage. 34 | func (in *ResourceUsage) DeepCopy() *ResourceUsage { 35 | if in == nil { 36 | return nil 37 | } 38 | out := new(ResourceUsage) 39 | in.DeepCopyInto(out) 40 | return out 41 | } 42 | 43 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 44 | func (in *ServerStatus) DeepCopyInto(out *ServerStatus) { 45 | *out = *in 46 | out.Usage = in.Usage 47 | return 48 | } 49 | 50 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerStatus. 51 | func (in *ServerStatus) DeepCopy() *ServerStatus { 52 | if in == nil { 53 | return nil 54 | } 55 | out := new(ServerStatus) 56 | in.DeepCopyInto(out) 57 | return out 58 | } 59 | 60 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 61 | func (in *VirtualMachine) DeepCopyInto(out *VirtualMachine) { 62 | *out = *in 63 | out.TypeMeta = in.TypeMeta 64 | in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) 65 | in.Spec.DeepCopyInto(&out.Spec) 66 | in.Status.DeepCopyInto(&out.Status) 67 | return 68 | } 69 | 70 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachine. 71 | func (in *VirtualMachine) DeepCopy() *VirtualMachine { 72 | if in == nil { 73 | return nil 74 | } 75 | out := new(VirtualMachine) 76 | in.DeepCopyInto(out) 77 | return out 78 | } 79 | 80 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 81 | func (in *VirtualMachine) DeepCopyObject() runtime.Object { 82 | if c := in.DeepCopy(); c != nil { 83 | return c 84 | } 85 | return nil 86 | } 87 | 88 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 89 | func (in *VirtualMachineList) DeepCopyInto(out *VirtualMachineList) { 90 | *out = *in 91 | out.TypeMeta = in.TypeMeta 92 | in.ListMeta.DeepCopyInto(&out.ListMeta) 93 | if in.Items != nil { 94 | in, out := &in.Items, &out.Items 95 | *out = make([]VirtualMachine, len(*in)) 96 | for i := range *in { 97 | (*in)[i].DeepCopyInto(&(*out)[i]) 98 | } 99 | } 100 | return 101 | } 102 | 103 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineList. 104 | func (in *VirtualMachineList) DeepCopy() *VirtualMachineList { 105 | if in == nil { 106 | return nil 107 | } 108 | out := new(VirtualMachineList) 109 | in.DeepCopyInto(out) 110 | return out 111 | } 112 | 113 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 114 | func (in *VirtualMachineList) DeepCopyObject() runtime.Object { 115 | if c := in.DeepCopy(); c != nil { 116 | return c 117 | } 118 | return nil 119 | } 120 | 121 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 122 | func (in *VirtualMachineSpec) DeepCopyInto(out *VirtualMachineSpec) { 123 | *out = *in 124 | if in.Resource != nil { 125 | in, out := &in.Resource, &out.Resource 126 | *out = make(v1.ResourceList, len(*in)) 127 | for key, val := range *in { 128 | (*out)[key] = val.DeepCopy() 129 | } 130 | } 131 | return 132 | } 133 | 134 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineSpec. 135 | func (in *VirtualMachineSpec) DeepCopy() *VirtualMachineSpec { 136 | if in == nil { 137 | return nil 138 | } 139 | out := new(VirtualMachineSpec) 140 | in.DeepCopyInto(out) 141 | return out 142 | } 143 | 144 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 145 | func (in *VirtualMachineStatus) DeepCopyInto(out *VirtualMachineStatus) { 146 | *out = *in 147 | out.Server = in.Server 148 | in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime) 149 | return 150 | } 151 | 152 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineStatus. 153 | func (in *VirtualMachineStatus) DeepCopy() *VirtualMachineStatus { 154 | if in == nil { 155 | return nil 156 | } 157 | out := new(VirtualMachineStatus) 158 | in.DeepCopyInto(out) 159 | return out 160 | } 161 | -------------------------------------------------------------------------------- /pkg/controller/controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 controller 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "time" 23 | 24 | v1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/apis/cloudnative/v1alpha1" 25 | "github.com/cloud-native-taiwan/controller101/pkg/driver" 26 | cloudnative "github.com/cloud-native-taiwan/controller101/pkg/generated/clientset/versioned" 27 | cloudnativeinformer "github.com/cloud-native-taiwan/controller101/pkg/generated/informers/externalversions" 28 | listerv1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/generated/listers/cloudnative/v1alpha1" 29 | "github.com/golang/glog" 30 | "k8s.io/apimachinery/pkg/api/errors" 31 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 32 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 33 | "k8s.io/apimachinery/pkg/util/wait" 34 | "k8s.io/client-go/tools/cache" 35 | "k8s.io/client-go/util/workqueue" 36 | "k8s.io/klog" 37 | ) 38 | 39 | const ( 40 | resouceName = "VirtualMachine" 41 | periodSec = 20 42 | finalizerName = "finalizer.cloudnative.tw" 43 | ) 44 | 45 | type Controller struct { 46 | clientset cloudnative.Interface 47 | informer cloudnativeinformer.SharedInformerFactory 48 | lister listerv1alpha1.VirtualMachineLister 49 | synced cache.InformerSynced 50 | queue workqueue.RateLimitingInterface 51 | vm driver.Interface 52 | } 53 | 54 | func New(clientset cloudnative.Interface, informer cloudnativeinformer.SharedInformerFactory, vm driver.Interface) *Controller { 55 | vmInformer := informer.Cloudnative().V1alpha1().VirtualMachines() 56 | controller := &Controller{ 57 | clientset: clientset, 58 | informer: informer, 59 | vm: vm, 60 | lister: vmInformer.Lister(), 61 | synced: vmInformer.Informer().HasSynced, 62 | queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), resouceName), 63 | } 64 | 65 | vmInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ 66 | AddFunc: controller.enqueue, 67 | UpdateFunc: func(old, new interface{}) { 68 | controller.enqueue(new) 69 | }, 70 | // DeleteFunc: controller.deleteObject, 71 | }) 72 | return controller 73 | } 74 | 75 | func (c *Controller) Run(ctx context.Context, threadiness int) error { 76 | go c.informer.Start(ctx.Done()) 77 | klog.Info("Starting the controller") 78 | klog.Info("Waiting for the informer caches to sync") 79 | if ok := cache.WaitForCacheSync(ctx.Done(), c.synced); !ok { 80 | return fmt.Errorf("failed to wait for caches to sync") 81 | } 82 | 83 | for i := 0; i < threadiness; i++ { 84 | go wait.Until(c.runWorker, time.Second, ctx.Done()) 85 | } 86 | klog.Info("Started workers") 87 | return nil 88 | } 89 | 90 | func (c *Controller) Stop() { 91 | glog.Info("Stopping the controller") 92 | c.queue.ShutDown() 93 | } 94 | 95 | func (c *Controller) runWorker() { 96 | defer utilruntime.HandleCrash() 97 | for c.processNextWorkItem() { 98 | } 99 | } 100 | 101 | func (c *Controller) processNextWorkItem() bool { 102 | obj, shutdown := c.queue.Get() 103 | if shutdown { 104 | return false 105 | } 106 | 107 | err := func(obj interface{}) error { 108 | defer c.queue.Done(obj) 109 | key, ok := obj.(string) 110 | if !ok { 111 | c.queue.Forget(obj) 112 | utilruntime.HandleError(fmt.Errorf("Controller expected string in workqueue but got %#v", obj)) 113 | return nil 114 | } 115 | 116 | if err := c.syncHandler(key); err != nil { 117 | c.queue.AddRateLimited(key) 118 | return fmt.Errorf("Controller error syncing '%s': %s, requeuing", key, err.Error()) 119 | } 120 | 121 | c.queue.Forget(obj) 122 | glog.Infof("Controller successfully synced '%s'", key) 123 | return nil 124 | }(obj) 125 | 126 | if err != nil { 127 | utilruntime.HandleError(err) 128 | return true 129 | } 130 | return true 131 | } 132 | 133 | func (c *Controller) enqueue(obj interface{}) { 134 | key, err := cache.MetaNamespaceKeyFunc(obj) 135 | if err != nil { 136 | utilruntime.HandleError(err) 137 | return 138 | } 139 | c.queue.Add(key) 140 | } 141 | 142 | func (c *Controller) syncHandler(key string) error { 143 | namespace, name, err := cache.SplitMetaNamespaceKey(key) 144 | if err != nil { 145 | utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key)) 146 | return err 147 | } 148 | 149 | vm, err := c.lister.VirtualMachines(namespace).Get(name) 150 | if err != nil { 151 | if errors.IsNotFound(err) { 152 | utilruntime.HandleError(fmt.Errorf("virtualmachine '%s' in work queue no longer exists", key)) 153 | return err 154 | } 155 | return err 156 | } 157 | 158 | switch vm.Status.Phase { 159 | case v1alpha1.VirtualMachineNone: 160 | if err := c.makeCreatingPhase(vm); err != nil { 161 | return err 162 | } 163 | case v1alpha1.VirtualMachineCreating, v1alpha1.VirtualMachineFailed: 164 | if err := c.createServer(vm); err != nil { 165 | return err 166 | } 167 | case v1alpha1.VirtualMachineActive: 168 | if !vm.ObjectMeta.DeletionTimestamp.IsZero() { 169 | if err := c.makeTerminatingPhase(vm); err != nil { 170 | return err 171 | } 172 | return nil 173 | } 174 | 175 | if err := c.updateUsage(vm); err != nil { 176 | return err 177 | } 178 | case v1alpha1.VirtualMachineTerminating: 179 | if err := c.deleteServer(vm); err != nil { 180 | return err 181 | } 182 | } 183 | return nil 184 | } 185 | 186 | func (c *Controller) deleteObject(obj interface{}) { 187 | vm := obj.(*v1alpha1.VirtualMachine) 188 | if err := c.vm.DeleteServer(vm.Name); err != nil { 189 | klog.Errorf("Failed to delete the '%s' server: %v", vm.Name, err) 190 | } 191 | } 192 | 193 | func (c *Controller) makeCreatingPhase(vm *v1alpha1.VirtualMachine) error { 194 | vmCopy := vm.DeepCopy() 195 | return c.updateStatus(vmCopy, v1alpha1.VirtualMachineCreating, nil) 196 | } 197 | 198 | func (c *Controller) makeTerminatingPhase(vm *v1alpha1.VirtualMachine) error { 199 | vmCopy := vm.DeepCopy() 200 | return c.updateStatus(vmCopy, v1alpha1.VirtualMachineTerminating, nil) 201 | } 202 | 203 | func (c *Controller) createServer(vm *v1alpha1.VirtualMachine) error { 204 | vmCopy := vm.DeepCopy() 205 | ok, _ := c.vm.IsServerExist(vm.Name) 206 | if !ok { 207 | req := &driver.CreateRequest{ 208 | Name: vm.Name, 209 | CPU: vm.Spec.Resource.Cpu().Value(), 210 | Memory: vm.Spec.Resource.Memory().Value(), 211 | } 212 | resp, err := c.vm.CreateServer(req) 213 | if err != nil { 214 | if err := c.updateStatus(vmCopy, v1alpha1.VirtualMachineFailed, err); err != nil { 215 | return err 216 | } 217 | return err 218 | } 219 | vmCopy.Status.Server.ID = resp.ID 220 | 221 | if err := c.appendServerStatus(vmCopy); err != nil { 222 | return err 223 | } 224 | 225 | addFinalizer(&vmCopy.ObjectMeta, finalizerName) 226 | if err := c.updateStatus(vmCopy, v1alpha1.VirtualMachineActive, nil); err != nil { 227 | return err 228 | } 229 | } 230 | return nil 231 | } 232 | 233 | func (c *Controller) appendServerStatus(vm *v1alpha1.VirtualMachine) error { 234 | status, err := c.vm.GetServerStatus(vm.Name) 235 | if err != nil { 236 | return err 237 | } 238 | 239 | vm.Status.Server.Usage.CPU = status.CPUPercentage 240 | vm.Status.Server.Usage.Memory = status.MemoryPercentage 241 | vm.Status.Server.State = status.State 242 | return nil 243 | } 244 | 245 | func (c *Controller) updateUsage(vm *v1alpha1.VirtualMachine) error { 246 | vmCopy := vm.DeepCopy() 247 | t := subtractTime(vmCopy.Status.LastUpdateTime.Time) 248 | if t.Seconds() > periodSec { 249 | if err := c.appendServerStatus(vmCopy); err != nil { 250 | return err 251 | } 252 | 253 | if err := c.updateStatus(vmCopy, v1alpha1.VirtualMachineActive, nil); err != nil { 254 | return err 255 | } 256 | } 257 | return nil 258 | } 259 | 260 | func (c *Controller) updateStatus(vm *v1alpha1.VirtualMachine, phase v1alpha1.VirtualMachinePhase, reason error) error { 261 | vm.Status.Reason = "" 262 | if reason != nil { 263 | vm.Status.Reason = reason.Error() 264 | } 265 | 266 | vm.Status.Phase = phase 267 | vm.Status.LastUpdateTime = metav1.NewTime(time.Now()) 268 | _, err := c.clientset.CloudnativeV1alpha1().VirtualMachines(vm.Namespace).Update(vm) 269 | return err 270 | } 271 | 272 | func (c *Controller) deleteServer(vm *v1alpha1.VirtualMachine) error { 273 | vmCopy := vm.DeepCopy() 274 | if err := c.vm.DeleteServer(vmCopy.Name); err != nil { 275 | // Requeuing object to workqueue for retrying 276 | return err 277 | } 278 | 279 | removeFinalizer(&vmCopy.ObjectMeta, finalizerName) 280 | if err := c.updateStatus(vmCopy, v1alpha1.VirtualMachineTerminating, nil); err != nil { 281 | return err 282 | } 283 | return nil 284 | } 285 | -------------------------------------------------------------------------------- /pkg/controller/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 controller 18 | 19 | import ( 20 | "time" 21 | 22 | "github.com/thoas/go-funk" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | ) 25 | 26 | func subtractTime(t time.Time) time.Duration { 27 | now := time.Now() 28 | then := now.Sub(t) 29 | return then 30 | } 31 | 32 | func addFinalizer(meta *metav1.ObjectMeta, finalizer string) { 33 | if !funk.ContainsString(meta.Finalizers, finalizer) { 34 | meta.Finalizers = append(meta.Finalizers, finalizer) 35 | } 36 | } 37 | 38 | func removeFinalizer(meta *metav1.ObjectMeta, finalizer string) { 39 | meta.Finalizers = funk.FilterString(meta.Finalizers, func(s string) bool { 40 | return s != finalizer 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /pkg/driver/docker.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 driver 18 | 19 | import ( 20 | "context" 21 | "encoding/json" 22 | "fmt" 23 | "io/ioutil" 24 | 25 | "github.com/docker/docker/api/types" 26 | "github.com/docker/docker/api/types/container" 27 | "github.com/docker/docker/api/types/filters" 28 | "github.com/docker/docker/client" 29 | ) 30 | 31 | const ( 32 | repository = "docker.io/library" 33 | imageName = "nginx:1.17.4" 34 | ) 35 | 36 | type DockerDriver struct { 37 | client *client.Client 38 | } 39 | 40 | func NewDockerDriver() (*DockerDriver, error) { 41 | cli, err := client.NewEnvClient() 42 | if err != nil { 43 | return nil, err 44 | } 45 | return &DockerDriver{client: cli}, nil 46 | } 47 | 48 | func (d *DockerDriver) pullImage(name string) error { 49 | opts := types.ImageListOptions{Filters: filters.NewArgs()} 50 | opts.Filters.Add("reference", name) 51 | imageList, err := d.client.ImageList(context.Background(), opts) 52 | if err != nil { 53 | return err 54 | } 55 | 56 | imageFullName := fmt.Sprintf("%s/%s", repository, name) 57 | if len(imageList) == 0 { 58 | _, err := d.client.ImagePull(context.Background(), imageFullName, types.ImagePullOptions{}) 59 | if err != nil { 60 | return err 61 | } 62 | } 63 | return nil 64 | } 65 | 66 | func (d *DockerDriver) CreateServer(req *CreateRequest) (*CreateReponse, error) { 67 | if err := d.pullImage(imageName); err != nil { 68 | return nil, err 69 | } 70 | 71 | config := &container.Config{Image: imageName} 72 | hostConfig := &container.HostConfig{ 73 | Resources: container.Resources{ 74 | NanoCPUs: req.CPU, 75 | Memory: req.Memory, 76 | }, 77 | } 78 | resp, err := d.client.ContainerCreate(context.Background(), config, hostConfig, nil, req.Name) 79 | if err != nil { 80 | return nil, err 81 | } 82 | 83 | if err := d.client.ContainerStart(context.Background(), resp.ID, types.ContainerStartOptions{}); err != nil { 84 | return nil, err 85 | } 86 | return &CreateReponse{ID: resp.ID}, nil 87 | } 88 | 89 | func (d *DockerDriver) GetServerStatus(name string) (*GetStatusReponse, error) { 90 | status := &GetStatusReponse{} 91 | container, err := d.getContainer(name) 92 | if err != nil { 93 | return nil, err 94 | } 95 | status.State = container.State 96 | 97 | resp, err := d.client.ContainerStats(context.Background(), name, false) 98 | if err != nil { 99 | return nil, err 100 | } 101 | defer resp.Body.Close() 102 | 103 | content, err := ioutil.ReadAll(resp.Body) 104 | if err != nil { 105 | return nil, err 106 | } 107 | 108 | v := &types.StatsJSON{} 109 | if err := json.Unmarshal(content, &v); err != nil { 110 | return nil, err 111 | } 112 | 113 | var memPercent = 0.0 114 | previousCPU := v.PreCPUStats.CPUUsage.TotalUsage 115 | previousSystem := v.PreCPUStats.SystemUsage 116 | cpuPercent := calculateCPUPercentUnix(previousCPU, previousSystem, v) 117 | 118 | if v.MemoryStats.Limit != 0 { 119 | memPercent = float64(v.MemoryStats.Usage) / float64(v.MemoryStats.Limit) * 100.0 120 | } 121 | 122 | status.CPUPercentage = cpuPercent 123 | status.MemoryPercentage = memPercent 124 | return status, nil 125 | } 126 | 127 | func calculateCPUPercentUnix(previousCPU, previousSystem uint64, v *types.StatsJSON) float64 { 128 | var ( 129 | cpuPercent = 0.0 130 | cpuDelta = float64(v.CPUStats.CPUUsage.TotalUsage) - float64(previousCPU) 131 | systemDelta = float64(v.CPUStats.SystemUsage) - float64(previousSystem) 132 | ) 133 | 134 | if systemDelta > 0.0 && cpuDelta > 0.0 { 135 | cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0 136 | } 137 | return cpuPercent 138 | } 139 | 140 | func (d *DockerDriver) DeleteServer(name string) error { 141 | if err := d.client.ContainerStop(context.Background(), name, nil); err != nil { 142 | return err 143 | } 144 | return d.client.ContainerRemove(context.Background(), name, types.ContainerRemoveOptions{}) 145 | } 146 | 147 | func (d *DockerDriver) IsServerExist(name string) (bool, error) { 148 | container, err := d.getContainer(name) 149 | if container != nil { 150 | return true, nil 151 | } 152 | return false, err 153 | } 154 | 155 | func (d *DockerDriver) getContainer(name string) (*types.Container, error) { 156 | opts := types.ContainerListOptions{Filters: filters.NewArgs()} 157 | opts.Filters.Add("name", name) 158 | containers, err := d.client.ContainerList(context.Background(), opts) 159 | if err != nil { 160 | return nil, err 161 | } 162 | 163 | if len(containers) < 1 || len(containers) > 1 { 164 | return nil, fmt.Errorf("Failed to get container by '%s' name", name) 165 | } 166 | return &containers[0], nil 167 | } 168 | -------------------------------------------------------------------------------- /pkg/driver/driver.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 driver 18 | 19 | type CreateRequest struct { 20 | Name string 21 | CPU int64 22 | Memory int64 23 | } 24 | 25 | type CreateReponse struct { 26 | ID string 27 | } 28 | 29 | type GetStatusReponse struct { 30 | State string 31 | CPUPercentage float64 32 | MemoryPercentage float64 33 | } 34 | 35 | type Interface interface { 36 | CreateServer(*CreateRequest) (*CreateReponse, error) 37 | DeleteServer(name string) error 38 | IsServerExist(name string) (bool, error) 39 | GetServerStatus(name string) (*GetStatusReponse, error) 40 | } 41 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/clientset.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package versioned 19 | 20 | import ( 21 | "fmt" 22 | 23 | cloudnativev1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/generated/clientset/versioned/typed/cloudnative/v1alpha1" 24 | discovery "k8s.io/client-go/discovery" 25 | rest "k8s.io/client-go/rest" 26 | flowcontrol "k8s.io/client-go/util/flowcontrol" 27 | ) 28 | 29 | type Interface interface { 30 | Discovery() discovery.DiscoveryInterface 31 | CloudnativeV1alpha1() cloudnativev1alpha1.CloudnativeV1alpha1Interface 32 | } 33 | 34 | // Clientset contains the clients for groups. Each group has exactly one 35 | // version included in a Clientset. 36 | type Clientset struct { 37 | *discovery.DiscoveryClient 38 | cloudnativeV1alpha1 *cloudnativev1alpha1.CloudnativeV1alpha1Client 39 | } 40 | 41 | // CloudnativeV1alpha1 retrieves the CloudnativeV1alpha1Client 42 | func (c *Clientset) CloudnativeV1alpha1() cloudnativev1alpha1.CloudnativeV1alpha1Interface { 43 | return c.cloudnativeV1alpha1 44 | } 45 | 46 | // Discovery retrieves the DiscoveryClient 47 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 48 | if c == nil { 49 | return nil 50 | } 51 | return c.DiscoveryClient 52 | } 53 | 54 | // NewForConfig creates a new Clientset for the given config. 55 | // If config's RateLimiter is not set and QPS and Burst are acceptable, 56 | // NewForConfig will generate a rate-limiter in configShallowCopy. 57 | func NewForConfig(c *rest.Config) (*Clientset, error) { 58 | configShallowCopy := *c 59 | if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { 60 | if configShallowCopy.Burst <= 0 { 61 | 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") 62 | } 63 | configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) 64 | } 65 | var cs Clientset 66 | var err error 67 | cs.cloudnativeV1alpha1, err = cloudnativev1alpha1.NewForConfig(&configShallowCopy) 68 | if err != nil { 69 | return nil, err 70 | } 71 | 72 | cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) 73 | if err != nil { 74 | return nil, err 75 | } 76 | return &cs, nil 77 | } 78 | 79 | // NewForConfigOrDie creates a new Clientset for the given config and 80 | // panics if there is an error in the config. 81 | func NewForConfigOrDie(c *rest.Config) *Clientset { 82 | var cs Clientset 83 | cs.cloudnativeV1alpha1 = cloudnativev1alpha1.NewForConfigOrDie(c) 84 | 85 | cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) 86 | return &cs 87 | } 88 | 89 | // New creates a new Clientset for the given RESTClient. 90 | func New(c rest.Interface) *Clientset { 91 | var cs Clientset 92 | cs.cloudnativeV1alpha1 = cloudnativev1alpha1.New(c) 93 | 94 | cs.DiscoveryClient = discovery.NewDiscoveryClient(c) 95 | return &cs 96 | } 97 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // This package has the automatically generated clientset. 19 | package versioned 20 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/fake/clientset_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package fake 19 | 20 | import ( 21 | clientset "github.com/cloud-native-taiwan/controller101/pkg/generated/clientset/versioned" 22 | cloudnativev1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/generated/clientset/versioned/typed/cloudnative/v1alpha1" 23 | fakecloudnativev1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/generated/clientset/versioned/typed/cloudnative/v1alpha1/fake" 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 | ) 30 | 31 | // NewSimpleClientset returns a clientset that will respond with the provided objects. 32 | // It's backed by a very simple object tracker that processes creates, updates and deletions as-is, 33 | // without applying any validations and/or defaults. It shouldn't be considered a replacement 34 | // for a real clientset and is mostly useful in simple unit tests. 35 | func NewSimpleClientset(objects ...runtime.Object) *Clientset { 36 | o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) 37 | for _, obj := range objects { 38 | if err := o.Add(obj); err != nil { 39 | panic(err) 40 | } 41 | } 42 | 43 | cs := &Clientset{tracker: o} 44 | cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} 45 | cs.AddReactor("*", "*", testing.ObjectReaction(o)) 46 | cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { 47 | gvr := action.GetResource() 48 | ns := action.GetNamespace() 49 | watch, err := o.Watch(gvr, ns) 50 | if err != nil { 51 | return false, nil, err 52 | } 53 | return true, watch, nil 54 | }) 55 | 56 | return cs 57 | } 58 | 59 | // Clientset implements clientset.Interface. Meant to be embedded into a 60 | // struct to get a default implementation. This makes faking out just the method 61 | // you want to test easier. 62 | type Clientset struct { 63 | testing.Fake 64 | discovery *fakediscovery.FakeDiscovery 65 | tracker testing.ObjectTracker 66 | } 67 | 68 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 69 | return c.discovery 70 | } 71 | 72 | func (c *Clientset) Tracker() testing.ObjectTracker { 73 | return c.tracker 74 | } 75 | 76 | var _ clientset.Interface = &Clientset{} 77 | 78 | // CloudnativeV1alpha1 retrieves the CloudnativeV1alpha1Client 79 | func (c *Clientset) CloudnativeV1alpha1() cloudnativev1alpha1.CloudnativeV1alpha1Interface { 80 | return &fakecloudnativev1alpha1.FakeCloudnativeV1alpha1{Fake: &c.Fake} 81 | } 82 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // This package has the automatically generated fake clientset. 19 | package fake 20 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/fake/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package fake 19 | 20 | import ( 21 | cloudnativev1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/apis/cloudnative/v1alpha1" 22 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | runtime "k8s.io/apimachinery/pkg/runtime" 24 | schema "k8s.io/apimachinery/pkg/runtime/schema" 25 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 26 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 27 | ) 28 | 29 | var scheme = runtime.NewScheme() 30 | var codecs = serializer.NewCodecFactory(scheme) 31 | var parameterCodec = runtime.NewParameterCodec(scheme) 32 | var localSchemeBuilder = runtime.SchemeBuilder{ 33 | cloudnativev1alpha1.AddToScheme, 34 | } 35 | 36 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 37 | // of clientsets, like in: 38 | // 39 | // import ( 40 | // "k8s.io/client-go/kubernetes" 41 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 42 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 43 | // ) 44 | // 45 | // kclientset, _ := kubernetes.NewForConfig(c) 46 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 47 | // 48 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 49 | // correctly. 50 | var AddToScheme = localSchemeBuilder.AddToScheme 51 | 52 | func init() { 53 | v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) 54 | utilruntime.Must(AddToScheme(scheme)) 55 | } 56 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/scheme/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // This package contains the scheme of the automatically generated clientset. 19 | package scheme 20 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/scheme/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package scheme 19 | 20 | import ( 21 | cloudnativev1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/apis/cloudnative/v1alpha1" 22 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | runtime "k8s.io/apimachinery/pkg/runtime" 24 | schema "k8s.io/apimachinery/pkg/runtime/schema" 25 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 26 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 27 | ) 28 | 29 | var Scheme = runtime.NewScheme() 30 | var Codecs = serializer.NewCodecFactory(Scheme) 31 | var ParameterCodec = runtime.NewParameterCodec(Scheme) 32 | var localSchemeBuilder = runtime.SchemeBuilder{ 33 | cloudnativev1alpha1.AddToScheme, 34 | } 35 | 36 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 37 | // of clientsets, like in: 38 | // 39 | // import ( 40 | // "k8s.io/client-go/kubernetes" 41 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 42 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 43 | // ) 44 | // 45 | // kclientset, _ := kubernetes.NewForConfig(c) 46 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 47 | // 48 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 49 | // correctly. 50 | var AddToScheme = localSchemeBuilder.AddToScheme 51 | 52 | func init() { 53 | v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) 54 | utilruntime.Must(AddToScheme(Scheme)) 55 | } 56 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/typed/cloudnative/v1alpha1/cloudnative_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package v1alpha1 19 | 20 | import ( 21 | v1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/apis/cloudnative/v1alpha1" 22 | "github.com/cloud-native-taiwan/controller101/pkg/generated/clientset/versioned/scheme" 23 | rest "k8s.io/client-go/rest" 24 | ) 25 | 26 | type CloudnativeV1alpha1Interface interface { 27 | RESTClient() rest.Interface 28 | VirtualMachinesGetter 29 | } 30 | 31 | // CloudnativeV1alpha1Client is used to interact with features provided by the cloudnative.tw group. 32 | type CloudnativeV1alpha1Client struct { 33 | restClient rest.Interface 34 | } 35 | 36 | func (c *CloudnativeV1alpha1Client) VirtualMachines(namespace string) VirtualMachineInterface { 37 | return newVirtualMachines(c, namespace) 38 | } 39 | 40 | // NewForConfig creates a new CloudnativeV1alpha1Client for the given config. 41 | func NewForConfig(c *rest.Config) (*CloudnativeV1alpha1Client, error) { 42 | config := *c 43 | if err := setConfigDefaults(&config); err != nil { 44 | return nil, err 45 | } 46 | client, err := rest.RESTClientFor(&config) 47 | if err != nil { 48 | return nil, err 49 | } 50 | return &CloudnativeV1alpha1Client{client}, nil 51 | } 52 | 53 | // NewForConfigOrDie creates a new CloudnativeV1alpha1Client for the given config and 54 | // panics if there is an error in the config. 55 | func NewForConfigOrDie(c *rest.Config) *CloudnativeV1alpha1Client { 56 | client, err := NewForConfig(c) 57 | if err != nil { 58 | panic(err) 59 | } 60 | return client 61 | } 62 | 63 | // New creates a new CloudnativeV1alpha1Client for the given RESTClient. 64 | func New(c rest.Interface) *CloudnativeV1alpha1Client { 65 | return &CloudnativeV1alpha1Client{c} 66 | } 67 | 68 | func setConfigDefaults(config *rest.Config) error { 69 | gv := v1alpha1.SchemeGroupVersion 70 | config.GroupVersion = &gv 71 | config.APIPath = "/apis" 72 | config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() 73 | 74 | if config.UserAgent == "" { 75 | config.UserAgent = rest.DefaultKubernetesUserAgent() 76 | } 77 | 78 | return nil 79 | } 80 | 81 | // RESTClient returns a RESTClient that is used to communicate 82 | // with API server by this client implementation. 83 | func (c *CloudnativeV1alpha1Client) RESTClient() rest.Interface { 84 | if c == nil { 85 | return nil 86 | } 87 | return c.restClient 88 | } 89 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/typed/cloudnative/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // This package has the automatically generated typed clients. 19 | package v1alpha1 20 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/typed/cloudnative/v1alpha1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // Package fake has the automatically generated clients. 19 | package fake 20 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/typed/cloudnative/v1alpha1/fake/fake_cloudnative_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package fake 19 | 20 | import ( 21 | v1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/generated/clientset/versioned/typed/cloudnative/v1alpha1" 22 | rest "k8s.io/client-go/rest" 23 | testing "k8s.io/client-go/testing" 24 | ) 25 | 26 | type FakeCloudnativeV1alpha1 struct { 27 | *testing.Fake 28 | } 29 | 30 | func (c *FakeCloudnativeV1alpha1) VirtualMachines(namespace string) v1alpha1.VirtualMachineInterface { 31 | return &FakeVirtualMachines{c, namespace} 32 | } 33 | 34 | // RESTClient returns a RESTClient that is used to communicate 35 | // with API server by this client implementation. 36 | func (c *FakeCloudnativeV1alpha1) RESTClient() rest.Interface { 37 | var ret *rest.RESTClient 38 | return ret 39 | } 40 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/typed/cloudnative/v1alpha1/fake/fake_virtualmachine.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package fake 19 | 20 | import ( 21 | v1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/apis/cloudnative/v1alpha1" 22 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | labels "k8s.io/apimachinery/pkg/labels" 24 | schema "k8s.io/apimachinery/pkg/runtime/schema" 25 | types "k8s.io/apimachinery/pkg/types" 26 | watch "k8s.io/apimachinery/pkg/watch" 27 | testing "k8s.io/client-go/testing" 28 | ) 29 | 30 | // FakeVirtualMachines implements VirtualMachineInterface 31 | type FakeVirtualMachines struct { 32 | Fake *FakeCloudnativeV1alpha1 33 | ns string 34 | } 35 | 36 | var virtualmachinesResource = schema.GroupVersionResource{Group: "cloudnative.tw", Version: "v1alpha1", Resource: "virtualmachines"} 37 | 38 | var virtualmachinesKind = schema.GroupVersionKind{Group: "cloudnative.tw", Version: "v1alpha1", Kind: "VirtualMachine"} 39 | 40 | // Get takes name of the virtualMachine, and returns the corresponding virtualMachine object, and an error if there is any. 41 | func (c *FakeVirtualMachines) Get(name string, options v1.GetOptions) (result *v1alpha1.VirtualMachine, err error) { 42 | obj, err := c.Fake. 43 | Invokes(testing.NewGetAction(virtualmachinesResource, c.ns, name), &v1alpha1.VirtualMachine{}) 44 | 45 | if obj == nil { 46 | return nil, err 47 | } 48 | return obj.(*v1alpha1.VirtualMachine), err 49 | } 50 | 51 | // List takes label and field selectors, and returns the list of VirtualMachines that match those selectors. 52 | func (c *FakeVirtualMachines) List(opts v1.ListOptions) (result *v1alpha1.VirtualMachineList, err error) { 53 | obj, err := c.Fake. 54 | Invokes(testing.NewListAction(virtualmachinesResource, virtualmachinesKind, c.ns, opts), &v1alpha1.VirtualMachineList{}) 55 | 56 | if obj == nil { 57 | return nil, err 58 | } 59 | 60 | label, _, _ := testing.ExtractFromListOptions(opts) 61 | if label == nil { 62 | label = labels.Everything() 63 | } 64 | list := &v1alpha1.VirtualMachineList{ListMeta: obj.(*v1alpha1.VirtualMachineList).ListMeta} 65 | for _, item := range obj.(*v1alpha1.VirtualMachineList).Items { 66 | if label.Matches(labels.Set(item.Labels)) { 67 | list.Items = append(list.Items, item) 68 | } 69 | } 70 | return list, err 71 | } 72 | 73 | // Watch returns a watch.Interface that watches the requested virtualMachines. 74 | func (c *FakeVirtualMachines) Watch(opts v1.ListOptions) (watch.Interface, error) { 75 | return c.Fake. 76 | InvokesWatch(testing.NewWatchAction(virtualmachinesResource, c.ns, opts)) 77 | 78 | } 79 | 80 | // Create takes the representation of a virtualMachine and creates it. Returns the server's representation of the virtualMachine, and an error, if there is any. 81 | func (c *FakeVirtualMachines) Create(virtualMachine *v1alpha1.VirtualMachine) (result *v1alpha1.VirtualMachine, err error) { 82 | obj, err := c.Fake. 83 | Invokes(testing.NewCreateAction(virtualmachinesResource, c.ns, virtualMachine), &v1alpha1.VirtualMachine{}) 84 | 85 | if obj == nil { 86 | return nil, err 87 | } 88 | return obj.(*v1alpha1.VirtualMachine), err 89 | } 90 | 91 | // Update takes the representation of a virtualMachine and updates it. Returns the server's representation of the virtualMachine, and an error, if there is any. 92 | func (c *FakeVirtualMachines) Update(virtualMachine *v1alpha1.VirtualMachine) (result *v1alpha1.VirtualMachine, err error) { 93 | obj, err := c.Fake. 94 | Invokes(testing.NewUpdateAction(virtualmachinesResource, c.ns, virtualMachine), &v1alpha1.VirtualMachine{}) 95 | 96 | if obj == nil { 97 | return nil, err 98 | } 99 | return obj.(*v1alpha1.VirtualMachine), err 100 | } 101 | 102 | // UpdateStatus was generated because the type contains a Status member. 103 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 104 | func (c *FakeVirtualMachines) UpdateStatus(virtualMachine *v1alpha1.VirtualMachine) (*v1alpha1.VirtualMachine, error) { 105 | obj, err := c.Fake. 106 | Invokes(testing.NewUpdateSubresourceAction(virtualmachinesResource, "status", c.ns, virtualMachine), &v1alpha1.VirtualMachine{}) 107 | 108 | if obj == nil { 109 | return nil, err 110 | } 111 | return obj.(*v1alpha1.VirtualMachine), err 112 | } 113 | 114 | // Delete takes name of the virtualMachine and deletes it. Returns an error if one occurs. 115 | func (c *FakeVirtualMachines) Delete(name string, options *v1.DeleteOptions) error { 116 | _, err := c.Fake. 117 | Invokes(testing.NewDeleteAction(virtualmachinesResource, c.ns, name), &v1alpha1.VirtualMachine{}) 118 | 119 | return err 120 | } 121 | 122 | // DeleteCollection deletes a collection of objects. 123 | func (c *FakeVirtualMachines) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { 124 | action := testing.NewDeleteCollectionAction(virtualmachinesResource, c.ns, listOptions) 125 | 126 | _, err := c.Fake.Invokes(action, &v1alpha1.VirtualMachineList{}) 127 | return err 128 | } 129 | 130 | // Patch applies the patch and returns the patched virtualMachine. 131 | func (c *FakeVirtualMachines) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.VirtualMachine, err error) { 132 | obj, err := c.Fake. 133 | Invokes(testing.NewPatchSubresourceAction(virtualmachinesResource, c.ns, name, pt, data, subresources...), &v1alpha1.VirtualMachine{}) 134 | 135 | if obj == nil { 136 | return nil, err 137 | } 138 | return obj.(*v1alpha1.VirtualMachine), err 139 | } 140 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/typed/cloudnative/v1alpha1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package v1alpha1 19 | 20 | type VirtualMachineExpansion interface{} 21 | -------------------------------------------------------------------------------- /pkg/generated/clientset/versioned/typed/cloudnative/v1alpha1/virtualmachine.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package v1alpha1 19 | 20 | import ( 21 | "time" 22 | 23 | v1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/apis/cloudnative/v1alpha1" 24 | scheme "github.com/cloud-native-taiwan/controller101/pkg/generated/clientset/versioned/scheme" 25 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | types "k8s.io/apimachinery/pkg/types" 27 | watch "k8s.io/apimachinery/pkg/watch" 28 | rest "k8s.io/client-go/rest" 29 | ) 30 | 31 | // VirtualMachinesGetter has a method to return a VirtualMachineInterface. 32 | // A group's client should implement this interface. 33 | type VirtualMachinesGetter interface { 34 | VirtualMachines(namespace string) VirtualMachineInterface 35 | } 36 | 37 | // VirtualMachineInterface has methods to work with VirtualMachine resources. 38 | type VirtualMachineInterface interface { 39 | Create(*v1alpha1.VirtualMachine) (*v1alpha1.VirtualMachine, error) 40 | Update(*v1alpha1.VirtualMachine) (*v1alpha1.VirtualMachine, error) 41 | UpdateStatus(*v1alpha1.VirtualMachine) (*v1alpha1.VirtualMachine, error) 42 | Delete(name string, options *v1.DeleteOptions) error 43 | DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error 44 | Get(name string, options v1.GetOptions) (*v1alpha1.VirtualMachine, error) 45 | List(opts v1.ListOptions) (*v1alpha1.VirtualMachineList, error) 46 | Watch(opts v1.ListOptions) (watch.Interface, error) 47 | Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.VirtualMachine, err error) 48 | VirtualMachineExpansion 49 | } 50 | 51 | // virtualMachines implements VirtualMachineInterface 52 | type virtualMachines struct { 53 | client rest.Interface 54 | ns string 55 | } 56 | 57 | // newVirtualMachines returns a VirtualMachines 58 | func newVirtualMachines(c *CloudnativeV1alpha1Client, namespace string) *virtualMachines { 59 | return &virtualMachines{ 60 | client: c.RESTClient(), 61 | ns: namespace, 62 | } 63 | } 64 | 65 | // Get takes name of the virtualMachine, and returns the corresponding virtualMachine object, and an error if there is any. 66 | func (c *virtualMachines) Get(name string, options v1.GetOptions) (result *v1alpha1.VirtualMachine, err error) { 67 | result = &v1alpha1.VirtualMachine{} 68 | err = c.client.Get(). 69 | Namespace(c.ns). 70 | Resource("virtualmachines"). 71 | Name(name). 72 | VersionedParams(&options, scheme.ParameterCodec). 73 | Do(). 74 | Into(result) 75 | return 76 | } 77 | 78 | // List takes label and field selectors, and returns the list of VirtualMachines that match those selectors. 79 | func (c *virtualMachines) List(opts v1.ListOptions) (result *v1alpha1.VirtualMachineList, err error) { 80 | var timeout time.Duration 81 | if opts.TimeoutSeconds != nil { 82 | timeout = time.Duration(*opts.TimeoutSeconds) * time.Second 83 | } 84 | result = &v1alpha1.VirtualMachineList{} 85 | err = c.client.Get(). 86 | Namespace(c.ns). 87 | Resource("virtualmachines"). 88 | VersionedParams(&opts, scheme.ParameterCodec). 89 | Timeout(timeout). 90 | Do(). 91 | Into(result) 92 | return 93 | } 94 | 95 | // Watch returns a watch.Interface that watches the requested virtualMachines. 96 | func (c *virtualMachines) Watch(opts v1.ListOptions) (watch.Interface, error) { 97 | var timeout time.Duration 98 | if opts.TimeoutSeconds != nil { 99 | timeout = time.Duration(*opts.TimeoutSeconds) * time.Second 100 | } 101 | opts.Watch = true 102 | return c.client.Get(). 103 | Namespace(c.ns). 104 | Resource("virtualmachines"). 105 | VersionedParams(&opts, scheme.ParameterCodec). 106 | Timeout(timeout). 107 | Watch() 108 | } 109 | 110 | // Create takes the representation of a virtualMachine and creates it. Returns the server's representation of the virtualMachine, and an error, if there is any. 111 | func (c *virtualMachines) Create(virtualMachine *v1alpha1.VirtualMachine) (result *v1alpha1.VirtualMachine, err error) { 112 | result = &v1alpha1.VirtualMachine{} 113 | err = c.client.Post(). 114 | Namespace(c.ns). 115 | Resource("virtualmachines"). 116 | Body(virtualMachine). 117 | Do(). 118 | Into(result) 119 | return 120 | } 121 | 122 | // Update takes the representation of a virtualMachine and updates it. Returns the server's representation of the virtualMachine, and an error, if there is any. 123 | func (c *virtualMachines) Update(virtualMachine *v1alpha1.VirtualMachine) (result *v1alpha1.VirtualMachine, err error) { 124 | result = &v1alpha1.VirtualMachine{} 125 | err = c.client.Put(). 126 | Namespace(c.ns). 127 | Resource("virtualmachines"). 128 | Name(virtualMachine.Name). 129 | Body(virtualMachine). 130 | Do(). 131 | Into(result) 132 | return 133 | } 134 | 135 | // UpdateStatus was generated because the type contains a Status member. 136 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 137 | 138 | func (c *virtualMachines) UpdateStatus(virtualMachine *v1alpha1.VirtualMachine) (result *v1alpha1.VirtualMachine, err error) { 139 | result = &v1alpha1.VirtualMachine{} 140 | err = c.client.Put(). 141 | Namespace(c.ns). 142 | Resource("virtualmachines"). 143 | Name(virtualMachine.Name). 144 | SubResource("status"). 145 | Body(virtualMachine). 146 | Do(). 147 | Into(result) 148 | return 149 | } 150 | 151 | // Delete takes name of the virtualMachine and deletes it. Returns an error if one occurs. 152 | func (c *virtualMachines) Delete(name string, options *v1.DeleteOptions) error { 153 | return c.client.Delete(). 154 | Namespace(c.ns). 155 | Resource("virtualmachines"). 156 | Name(name). 157 | Body(options). 158 | Do(). 159 | Error() 160 | } 161 | 162 | // DeleteCollection deletes a collection of objects. 163 | func (c *virtualMachines) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { 164 | var timeout time.Duration 165 | if listOptions.TimeoutSeconds != nil { 166 | timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second 167 | } 168 | return c.client.Delete(). 169 | Namespace(c.ns). 170 | Resource("virtualmachines"). 171 | VersionedParams(&listOptions, scheme.ParameterCodec). 172 | Timeout(timeout). 173 | Body(options). 174 | Do(). 175 | Error() 176 | } 177 | 178 | // Patch applies the patch and returns the patched virtualMachine. 179 | func (c *virtualMachines) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.VirtualMachine, err error) { 180 | result = &v1alpha1.VirtualMachine{} 181 | err = c.client.Patch(pt). 182 | Namespace(c.ns). 183 | Resource("virtualmachines"). 184 | SubResource(subresources...). 185 | Name(name). 186 | Body(data). 187 | Do(). 188 | Into(result) 189 | return 190 | } 191 | -------------------------------------------------------------------------------- /pkg/generated/informers/externalversions/cloudnative/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package cloudnative 19 | 20 | import ( 21 | v1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/generated/informers/externalversions/cloudnative/v1alpha1" 22 | internalinterfaces "github.com/cloud-native-taiwan/controller101/pkg/generated/informers/externalversions/internalinterfaces" 23 | ) 24 | 25 | // Interface provides access to each of this group's versions. 26 | type Interface interface { 27 | // V1alpha1 provides access to shared informers for resources in V1alpha1. 28 | V1alpha1() v1alpha1.Interface 29 | } 30 | 31 | type group struct { 32 | factory internalinterfaces.SharedInformerFactory 33 | namespace string 34 | tweakListOptions internalinterfaces.TweakListOptionsFunc 35 | } 36 | 37 | // New returns a new Interface. 38 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 39 | return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 40 | } 41 | 42 | // V1alpha1 returns a new v1alpha1.Interface. 43 | func (g *group) V1alpha1() v1alpha1.Interface { 44 | return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) 45 | } 46 | -------------------------------------------------------------------------------- /pkg/generated/informers/externalversions/cloudnative/v1alpha1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package v1alpha1 19 | 20 | import ( 21 | internalinterfaces "github.com/cloud-native-taiwan/controller101/pkg/generated/informers/externalversions/internalinterfaces" 22 | ) 23 | 24 | // Interface provides access to all the informers in this group version. 25 | type Interface interface { 26 | // VirtualMachines returns a VirtualMachineInformer. 27 | VirtualMachines() VirtualMachineInformer 28 | } 29 | 30 | type version struct { 31 | factory internalinterfaces.SharedInformerFactory 32 | namespace string 33 | tweakListOptions internalinterfaces.TweakListOptionsFunc 34 | } 35 | 36 | // New returns a new Interface. 37 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 38 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 39 | } 40 | 41 | // VirtualMachines returns a VirtualMachineInformer. 42 | func (v *version) VirtualMachines() VirtualMachineInformer { 43 | return &virtualMachineInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 44 | } 45 | -------------------------------------------------------------------------------- /pkg/generated/informers/externalversions/cloudnative/v1alpha1/virtualmachine.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package v1alpha1 19 | 20 | import ( 21 | time "time" 22 | 23 | cloudnativev1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/apis/cloudnative/v1alpha1" 24 | versioned "github.com/cloud-native-taiwan/controller101/pkg/generated/clientset/versioned" 25 | internalinterfaces "github.com/cloud-native-taiwan/controller101/pkg/generated/informers/externalversions/internalinterfaces" 26 | v1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/generated/listers/cloudnative/v1alpha1" 27 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 | runtime "k8s.io/apimachinery/pkg/runtime" 29 | watch "k8s.io/apimachinery/pkg/watch" 30 | cache "k8s.io/client-go/tools/cache" 31 | ) 32 | 33 | // VirtualMachineInformer provides access to a shared informer and lister for 34 | // VirtualMachines. 35 | type VirtualMachineInformer interface { 36 | Informer() cache.SharedIndexInformer 37 | Lister() v1alpha1.VirtualMachineLister 38 | } 39 | 40 | type virtualMachineInformer struct { 41 | factory internalinterfaces.SharedInformerFactory 42 | tweakListOptions internalinterfaces.TweakListOptionsFunc 43 | namespace string 44 | } 45 | 46 | // NewVirtualMachineInformer constructs a new informer for VirtualMachine type. 47 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 48 | // one. This reduces memory footprint and number of connections to the server. 49 | func NewVirtualMachineInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 50 | return NewFilteredVirtualMachineInformer(client, namespace, resyncPeriod, indexers, nil) 51 | } 52 | 53 | // NewFilteredVirtualMachineInformer constructs a new informer for VirtualMachine type. 54 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 55 | // one. This reduces memory footprint and number of connections to the server. 56 | func NewFilteredVirtualMachineInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 57 | return cache.NewSharedIndexInformer( 58 | &cache.ListWatch{ 59 | ListFunc: func(options v1.ListOptions) (runtime.Object, error) { 60 | if tweakListOptions != nil { 61 | tweakListOptions(&options) 62 | } 63 | return client.CloudnativeV1alpha1().VirtualMachines(namespace).List(options) 64 | }, 65 | WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { 66 | if tweakListOptions != nil { 67 | tweakListOptions(&options) 68 | } 69 | return client.CloudnativeV1alpha1().VirtualMachines(namespace).Watch(options) 70 | }, 71 | }, 72 | &cloudnativev1alpha1.VirtualMachine{}, 73 | resyncPeriod, 74 | indexers, 75 | ) 76 | } 77 | 78 | func (f *virtualMachineInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 79 | return NewFilteredVirtualMachineInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 80 | } 81 | 82 | func (f *virtualMachineInformer) Informer() cache.SharedIndexInformer { 83 | return f.factory.InformerFor(&cloudnativev1alpha1.VirtualMachine{}, f.defaultInformer) 84 | } 85 | 86 | func (f *virtualMachineInformer) Lister() v1alpha1.VirtualMachineLister { 87 | return v1alpha1.NewVirtualMachineLister(f.Informer().GetIndexer()) 88 | } 89 | -------------------------------------------------------------------------------- /pkg/generated/informers/externalversions/factory.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package externalversions 19 | 20 | import ( 21 | reflect "reflect" 22 | sync "sync" 23 | time "time" 24 | 25 | versioned "github.com/cloud-native-taiwan/controller101/pkg/generated/clientset/versioned" 26 | cloudnative "github.com/cloud-native-taiwan/controller101/pkg/generated/informers/externalversions/cloudnative" 27 | internalinterfaces "github.com/cloud-native-taiwan/controller101/pkg/generated/informers/externalversions/internalinterfaces" 28 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | runtime "k8s.io/apimachinery/pkg/runtime" 30 | schema "k8s.io/apimachinery/pkg/runtime/schema" 31 | cache "k8s.io/client-go/tools/cache" 32 | ) 33 | 34 | // SharedInformerOption defines the functional option type for SharedInformerFactory. 35 | type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory 36 | 37 | type sharedInformerFactory struct { 38 | client versioned.Interface 39 | namespace string 40 | tweakListOptions internalinterfaces.TweakListOptionsFunc 41 | lock sync.Mutex 42 | defaultResync time.Duration 43 | customResync map[reflect.Type]time.Duration 44 | 45 | informers map[reflect.Type]cache.SharedIndexInformer 46 | // startedInformers is used for tracking which informers have been started. 47 | // This allows Start() to be called multiple times safely. 48 | startedInformers map[reflect.Type]bool 49 | } 50 | 51 | // WithCustomResyncConfig sets a custom resync period for the specified informer types. 52 | func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { 53 | return func(factory *sharedInformerFactory) *sharedInformerFactory { 54 | for k, v := range resyncConfig { 55 | factory.customResync[reflect.TypeOf(k)] = v 56 | } 57 | return factory 58 | } 59 | } 60 | 61 | // WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. 62 | func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { 63 | return func(factory *sharedInformerFactory) *sharedInformerFactory { 64 | factory.tweakListOptions = tweakListOptions 65 | return factory 66 | } 67 | } 68 | 69 | // WithNamespace limits the SharedInformerFactory to the specified namespace. 70 | func WithNamespace(namespace string) SharedInformerOption { 71 | return func(factory *sharedInformerFactory) *sharedInformerFactory { 72 | factory.namespace = namespace 73 | return factory 74 | } 75 | } 76 | 77 | // NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. 78 | func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { 79 | return NewSharedInformerFactoryWithOptions(client, defaultResync) 80 | } 81 | 82 | // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. 83 | // Listers obtained via this SharedInformerFactory will be subject to the same filters 84 | // as specified here. 85 | // Deprecated: Please use NewSharedInformerFactoryWithOptions instead 86 | func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { 87 | return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) 88 | } 89 | 90 | // NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. 91 | func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { 92 | factory := &sharedInformerFactory{ 93 | client: client, 94 | namespace: v1.NamespaceAll, 95 | defaultResync: defaultResync, 96 | informers: make(map[reflect.Type]cache.SharedIndexInformer), 97 | startedInformers: make(map[reflect.Type]bool), 98 | customResync: make(map[reflect.Type]time.Duration), 99 | } 100 | 101 | // Apply all options 102 | for _, opt := range options { 103 | factory = opt(factory) 104 | } 105 | 106 | return factory 107 | } 108 | 109 | // Start initializes all requested informers. 110 | func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { 111 | f.lock.Lock() 112 | defer f.lock.Unlock() 113 | 114 | for informerType, informer := range f.informers { 115 | if !f.startedInformers[informerType] { 116 | go informer.Run(stopCh) 117 | f.startedInformers[informerType] = true 118 | } 119 | } 120 | } 121 | 122 | // WaitForCacheSync waits for all started informers' cache were synced. 123 | func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { 124 | informers := func() map[reflect.Type]cache.SharedIndexInformer { 125 | f.lock.Lock() 126 | defer f.lock.Unlock() 127 | 128 | informers := map[reflect.Type]cache.SharedIndexInformer{} 129 | for informerType, informer := range f.informers { 130 | if f.startedInformers[informerType] { 131 | informers[informerType] = informer 132 | } 133 | } 134 | return informers 135 | }() 136 | 137 | res := map[reflect.Type]bool{} 138 | for informType, informer := range informers { 139 | res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) 140 | } 141 | return res 142 | } 143 | 144 | // InternalInformerFor returns the SharedIndexInformer for obj using an internal 145 | // client. 146 | func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { 147 | f.lock.Lock() 148 | defer f.lock.Unlock() 149 | 150 | informerType := reflect.TypeOf(obj) 151 | informer, exists := f.informers[informerType] 152 | if exists { 153 | return informer 154 | } 155 | 156 | resyncPeriod, exists := f.customResync[informerType] 157 | if !exists { 158 | resyncPeriod = f.defaultResync 159 | } 160 | 161 | informer = newFunc(f.client, resyncPeriod) 162 | f.informers[informerType] = informer 163 | 164 | return informer 165 | } 166 | 167 | // SharedInformerFactory provides shared informers for resources in all known 168 | // API group versions. 169 | type SharedInformerFactory interface { 170 | internalinterfaces.SharedInformerFactory 171 | ForResource(resource schema.GroupVersionResource) (GenericInformer, error) 172 | WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool 173 | 174 | Cloudnative() cloudnative.Interface 175 | } 176 | 177 | func (f *sharedInformerFactory) Cloudnative() cloudnative.Interface { 178 | return cloudnative.New(f, f.namespace, f.tweakListOptions) 179 | } 180 | -------------------------------------------------------------------------------- /pkg/generated/informers/externalversions/generic.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package externalversions 19 | 20 | import ( 21 | "fmt" 22 | 23 | v1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/apis/cloudnative/v1alpha1" 24 | schema "k8s.io/apimachinery/pkg/runtime/schema" 25 | cache "k8s.io/client-go/tools/cache" 26 | ) 27 | 28 | // GenericInformer is type of SharedIndexInformer which will locate and delegate to other 29 | // sharedInformers based on type 30 | type GenericInformer interface { 31 | Informer() cache.SharedIndexInformer 32 | Lister() cache.GenericLister 33 | } 34 | 35 | type genericInformer struct { 36 | informer cache.SharedIndexInformer 37 | resource schema.GroupResource 38 | } 39 | 40 | // Informer returns the SharedIndexInformer. 41 | func (f *genericInformer) Informer() cache.SharedIndexInformer { 42 | return f.informer 43 | } 44 | 45 | // Lister returns the GenericLister. 46 | func (f *genericInformer) Lister() cache.GenericLister { 47 | return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) 48 | } 49 | 50 | // ForResource gives generic access to a shared informer of the matching type 51 | // TODO extend this to unknown resources with a client pool 52 | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { 53 | switch resource { 54 | // Group=cloudnative.tw, Version=v1alpha1 55 | case v1alpha1.SchemeGroupVersion.WithResource("virtualmachines"): 56 | return &genericInformer{resource: resource.GroupResource(), informer: f.Cloudnative().V1alpha1().VirtualMachines().Informer()}, nil 57 | 58 | } 59 | 60 | return nil, fmt.Errorf("no informer found for %v", resource) 61 | } 62 | -------------------------------------------------------------------------------- /pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package internalinterfaces 19 | 20 | import ( 21 | time "time" 22 | 23 | versioned "github.com/cloud-native-taiwan/controller101/pkg/generated/clientset/versioned" 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | runtime "k8s.io/apimachinery/pkg/runtime" 26 | cache "k8s.io/client-go/tools/cache" 27 | ) 28 | 29 | // NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. 30 | type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer 31 | 32 | // SharedInformerFactory a small interface to allow for adding an informer without an import cycle 33 | type SharedInformerFactory interface { 34 | Start(stopCh <-chan struct{}) 35 | InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer 36 | } 37 | 38 | // TweakListOptionsFunc is a function that transforms a v1.ListOptions. 39 | type TweakListOptionsFunc func(*v1.ListOptions) 40 | -------------------------------------------------------------------------------- /pkg/generated/listers/cloudnative/v1alpha1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by lister-gen. DO NOT EDIT. 17 | 18 | package v1alpha1 19 | 20 | // VirtualMachineListerExpansion allows custom methods to be added to 21 | // VirtualMachineLister. 22 | type VirtualMachineListerExpansion interface{} 23 | 24 | // VirtualMachineNamespaceListerExpansion allows custom methods to be added to 25 | // VirtualMachineNamespaceLister. 26 | type VirtualMachineNamespaceListerExpansion interface{} 27 | -------------------------------------------------------------------------------- /pkg/generated/listers/cloudnative/v1alpha1/virtualmachine.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | // Code generated by lister-gen. DO NOT EDIT. 17 | 18 | package v1alpha1 19 | 20 | import ( 21 | v1alpha1 "github.com/cloud-native-taiwan/controller101/pkg/apis/cloudnative/v1alpha1" 22 | "k8s.io/apimachinery/pkg/api/errors" 23 | "k8s.io/apimachinery/pkg/labels" 24 | "k8s.io/client-go/tools/cache" 25 | ) 26 | 27 | // VirtualMachineLister helps list VirtualMachines. 28 | type VirtualMachineLister interface { 29 | // List lists all VirtualMachines in the indexer. 30 | List(selector labels.Selector) (ret []*v1alpha1.VirtualMachine, err error) 31 | // VirtualMachines returns an object that can list and get VirtualMachines. 32 | VirtualMachines(namespace string) VirtualMachineNamespaceLister 33 | VirtualMachineListerExpansion 34 | } 35 | 36 | // virtualMachineLister implements the VirtualMachineLister interface. 37 | type virtualMachineLister struct { 38 | indexer cache.Indexer 39 | } 40 | 41 | // NewVirtualMachineLister returns a new VirtualMachineLister. 42 | func NewVirtualMachineLister(indexer cache.Indexer) VirtualMachineLister { 43 | return &virtualMachineLister{indexer: indexer} 44 | } 45 | 46 | // List lists all VirtualMachines in the indexer. 47 | func (s *virtualMachineLister) List(selector labels.Selector) (ret []*v1alpha1.VirtualMachine, err error) { 48 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 49 | ret = append(ret, m.(*v1alpha1.VirtualMachine)) 50 | }) 51 | return ret, err 52 | } 53 | 54 | // VirtualMachines returns an object that can list and get VirtualMachines. 55 | func (s *virtualMachineLister) VirtualMachines(namespace string) VirtualMachineNamespaceLister { 56 | return virtualMachineNamespaceLister{indexer: s.indexer, namespace: namespace} 57 | } 58 | 59 | // VirtualMachineNamespaceLister helps list and get VirtualMachines. 60 | type VirtualMachineNamespaceLister interface { 61 | // List lists all VirtualMachines in the indexer for a given namespace. 62 | List(selector labels.Selector) (ret []*v1alpha1.VirtualMachine, err error) 63 | // Get retrieves the VirtualMachine from the indexer for a given namespace and name. 64 | Get(name string) (*v1alpha1.VirtualMachine, error) 65 | VirtualMachineNamespaceListerExpansion 66 | } 67 | 68 | // virtualMachineNamespaceLister implements the VirtualMachineNamespaceLister 69 | // interface. 70 | type virtualMachineNamespaceLister struct { 71 | indexer cache.Indexer 72 | namespace string 73 | } 74 | 75 | // List lists all VirtualMachines in the indexer for a given namespace. 76 | func (s virtualMachineNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.VirtualMachine, err error) { 77 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 78 | ret = append(ret, m.(*v1alpha1.VirtualMachine)) 79 | }) 80 | return ret, err 81 | } 82 | 83 | // Get retrieves the VirtualMachine from the indexer for a given namespace and name. 84 | func (s virtualMachineNamespaceLister) Get(name string) (*v1alpha1.VirtualMachine, error) { 85 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 86 | if err != nil { 87 | return nil, err 88 | } 89 | if !exists { 90 | return nil, errors.NewNotFound(v1alpha1.Resource("virtualmachine"), name) 91 | } 92 | return obj.(*v1alpha1.VirtualMachine), nil 93 | } 94 | -------------------------------------------------------------------------------- /pkg/version/version.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 version 18 | 19 | // version will be overridden with the current version at build time using the -X linker flag 20 | var version = "v0.0.0-unset" 21 | 22 | func GetVersion() string { 23 | return version 24 | } 25 | -------------------------------------------------------------------------------- /pkg/version/version_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 The controller101 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 | package version 17 | 18 | import ( 19 | "testing" 20 | 21 | "github.com/stretchr/testify/assert" 22 | ) 23 | 24 | func TestGetVersion(t *testing.T) { 25 | assert.Equal(t, "v0.0.0-unset", GetVersion()) 26 | 27 | version = "v0.1.0" 28 | assert.Equal(t, "v0.1.0", GetVersion()) 29 | } 30 | --------------------------------------------------------------------------------