├── .dockerignore ├── .github └── workflows │ ├── release.yaml │ ├── tests.yaml │ ├── vm-example.yaml │ └── vm-kernel.yaml ├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── PROJECT ├── README.md ├── apis └── neonvm │ └── v1 │ ├── groupversion_info.go │ ├── virtualmachine_types.go │ ├── virtualmachine_webhook.go │ ├── virtualmachinemigration_types.go │ ├── virtualmachinemigration_webhook.go │ ├── webhook_suite_test.go │ └── zz_generated.deepcopy.go ├── client ├── clientset │ └── versioned │ │ ├── clientset.go │ │ ├── doc.go │ │ ├── fake │ │ ├── clientset_generated.go │ │ ├── doc.go │ │ └── register.go │ │ ├── scheme │ │ ├── doc.go │ │ └── register.go │ │ └── typed │ │ └── neonvm │ │ └── v1 │ │ ├── doc.go │ │ ├── fake │ │ ├── doc.go │ │ ├── fake_neonvm_client.go │ │ ├── fake_virtualmachine.go │ │ └── fake_virtualmachinemigration.go │ │ ├── generated_expansion.go │ │ ├── neonvm_client.go │ │ ├── virtualmachine.go │ │ └── virtualmachinemigration.go ├── informers │ └── externalversions │ │ ├── factory.go │ │ ├── generic.go │ │ ├── internalinterfaces │ │ └── factory_interfaces.go │ │ └── neonvm │ │ ├── interface.go │ │ └── v1 │ │ ├── interface.go │ │ ├── virtualmachine.go │ │ └── virtualmachinemigration.go └── listers │ └── neonvm │ └── v1 │ ├── expansion_generated.go │ ├── virtualmachine.go │ └── virtualmachinemigration.go ├── config ├── common │ ├── certmanager │ │ ├── certificate.yaml │ │ ├── kustomization.yaml │ │ └── kustomizeconfig.yaml │ ├── controller │ │ ├── kustomization.yaml │ │ └── manager.yaml │ ├── crd │ │ ├── bases │ │ │ ├── vm.neon.tech_virtualmachinemigrations.yaml │ │ │ └── vm.neon.tech_virtualmachines.yaml │ │ ├── kustomization.yaml │ │ ├── kustomizeconfig.yaml │ │ └── patches │ │ │ ├── cainjection_in_virtualmachinemigrations.yaml │ │ │ ├── cainjection_in_virtualmachines.yaml │ │ │ ├── webhook_in_virtualmachinemigrations.yaml │ │ │ └── webhook_in_virtualmachines.yaml │ ├── namespace │ │ ├── kustomization.yaml │ │ └── namespace.yaml │ ├── prometheus │ │ ├── kustomization.yaml │ │ └── monitor.yaml │ ├── rbac │ │ ├── auth_proxy_client_clusterrole.yaml │ │ ├── auth_proxy_role.yaml │ │ ├── auth_proxy_role_binding.yaml │ │ ├── auth_proxy_service.yaml │ │ ├── kustomization.yaml │ │ ├── leader_election_role.yaml │ │ ├── leader_election_role_binding.yaml │ │ ├── role.yaml │ │ ├── role_binding.yaml │ │ ├── service_account.yaml │ │ ├── virtualmachine_editor_role.yaml │ │ ├── virtualmachine_viewer_role.yaml │ │ ├── virtualmachinemigration_editor_role.yaml │ │ └── virtualmachinemigration_viewer_role.yaml │ └── webhook │ │ ├── kustomization.yaml │ │ ├── kustomizeconfig.yaml │ │ ├── manifests.yaml │ │ └── service.yaml ├── default-vxlan │ ├── kustomization.yaml │ ├── manager_auth_proxy_patch.yaml │ ├── manager_config_patch.yaml │ ├── manager_webhook_patch.yaml │ ├── multus │ │ └── kustomization.yaml │ ├── network │ │ ├── kustomization.yaml │ │ └── network.yaml │ ├── vxlan-controller │ │ ├── daemonset.yaml │ │ ├── kustomization.yaml │ │ └── rbac.yaml │ ├── vxlan-ipam │ │ ├── deployment.yaml │ │ ├── kustomization.yaml │ │ ├── rbac.yaml │ │ └── service.yaml │ └── webhookcainjection_patch.yaml └── default │ ├── kustomization.yaml │ ├── manager_auth_proxy_patch.yaml │ ├── manager_config_patch.yaml │ ├── manager_webhook_patch.yaml │ └── webhookcainjection_patch.yaml ├── controllers ├── suite_test.go ├── virtualmachine_controller.go ├── virtualmachine_controller_test.go ├── virtualmachine_qmp_queries.go └── virtualmachinemigration_controller.go ├── go.mod ├── go.sum ├── hack ├── Dockerfile.generate ├── Dockerfile.kernel-builder ├── boilerplate.go.txt ├── generate.sh ├── kind.yaml ├── linux-config-5.15.76 ├── linux-config-5.15.80 └── tools.go ├── main.go ├── migration.md ├── runner ├── Dockerfile └── main.go ├── samples ├── vm-example-full.yaml ├── vm-example-migration.yaml ├── vm-example.yaml └── vm-example │ ├── Dockerfile │ ├── init │ ├── motd │ ├── pg_hba.conf │ └── postgresql.conf ├── tests └── e2e │ ├── kuttl-test.yaml │ └── vm-migration │ ├── 00-assert.yaml │ ├── 00-prepare.yaml │ ├── 01-assert.yaml │ └── 01-migrate.yaml └── tools ├── vm-builder └── main.go └── vxlan ├── Dockerfile ├── controller └── main.go └── ipam └── main.go /.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore build and test binaries. 3 | bin/ 4 | testbin/ 5 | neonvm-multus.yaml 6 | neonvm-vxlan.yaml 7 | neonvm.yaml -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*.*.*" 7 | 8 | env: 9 | KUSTOMIZE_VERSION: "4.5.7" 10 | CONTROLLER_TOOLS_VERSION: "0.9.2" 11 | CODE_GENERATOR_VERSION: "0.26.0" 12 | IMG: "neondatabase/neonvm-controller" 13 | IMG_VXLAN: "neondatabase/neonvm-vxlan-controller" 14 | IMG_RUNNER: "neondatabase/neonvm-runner" 15 | VM_KERNEL_IMAGE: "neondatabase/vm-kernel" 16 | VM_KERNEL_VERSION: "5.15.80" 17 | 18 | jobs: 19 | release: 20 | runs-on: ubuntu-latest 21 | steps: 22 | 23 | - id: get_version 24 | run: echo "version=${{ github.ref_name }}" >> $GITHUB_OUTPUT 25 | 26 | - name: git checkout 27 | uses: actions/checkout@v3 28 | - name: install golang 29 | uses: actions/setup-go@v3 30 | with: 31 | go-version-file: 'go.mod' 32 | cache: true 33 | 34 | - name: generate code and k8s CRDs 35 | run: | 36 | git clone --branch=v${{ env.CODE_GENERATOR_VERSION }} --depth=1 https://github.com/kubernetes/code-generator.git ${RUNNER_TEMP}/code-generator 37 | go install sigs.k8s.io/controller-tools/cmd/controller-gen@v${{ env.CONTROLLER_TOOLS_VERSION }} 38 | ${RUNNER_TEMP}/code-generator/generate-groups.sh "deepcopy,client,informer,lister" github.com/neondatabase/neonvm/client github.com/neondatabase/neonvm/apis neonvm:v1 --go-header-file hack/boilerplate.go.txt 39 | controller-gen rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/common/crd/bases output:rbac:artifacts:config=config/common/rbac output:webhook:artifacts:config=config/common/webhook 40 | 41 | - name: build binaries 42 | run: make build 43 | 44 | - name: docker - install qemu 45 | uses: docker/setup-qemu-action@v2 46 | - name: docker - setup buildx 47 | uses: docker/setup-buildx-action@v2 48 | - name: login to docker hub 49 | uses: docker/login-action@v2 50 | with: 51 | username: ${{ secrets.NEON_DOCKERHUB_USERNAME }} 52 | password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }} 53 | 54 | - name: load vm kernel 55 | run: | 56 | docker pull --quiet ${{ env.VM_KERNEL_IMAGE }}:${{ env.VM_KERNEL_VERSION }} 57 | ID=$(docker create ${{ env.VM_KERNEL_IMAGE }}:${{ env.VM_KERNEL_VERSION }} true) 58 | docker cp ${ID}:/vmlinuz hack/vmlinuz 59 | docker rm -f ${ID} 60 | 61 | - name: build and push runner image 62 | uses: docker/build-push-action@v3 63 | with: 64 | context: . 65 | platforms: linux/amd64 66 | push: true 67 | #push: ${{ github.event_name != 'pull_request' }} 68 | file: runner/Dockerfile 69 | tags: ${{ env.IMG_RUNNER }}:${{ steps.get_version.outputs.version }} 70 | 71 | - name: build and push controller image 72 | uses: docker/build-push-action@v3 73 | with: 74 | build-args: VM_RUNNER_IMAGE=${{ env.IMG_RUNNER }}:${{ steps.get_version.outputs.version }} 75 | context: . 76 | platforms: linux/amd64 77 | push: true 78 | #push: ${{ github.event_name != 'pull_request' }} 79 | tags: ${{ env.IMG }}:${{ steps.get_version.outputs.version }} 80 | 81 | - name: build and push vxlan controller image 82 | uses: docker/build-push-action@v3 83 | with: 84 | context: . 85 | platforms: linux/amd64 86 | push: true 87 | #push: ${{ github.event_name != 'pull_request' }} 88 | file: tools/vxlan/Dockerfile 89 | tags: ${{ env.IMG_VXLAN }}:${{ steps.get_version.outputs.version }} 90 | 91 | - name: render kubernetes resources 92 | uses: stefanprodan/kube-tools@v1 93 | with: 94 | kustomize: ${{ env.KUSTOMIZE_VERSION }} 95 | command: | 96 | kustomize version --short 97 | cd ${GITHUB_WORKSPACE}/config/common/controller && kustomize edit set image controller=${{ env.IMG }}:${{ steps.get_version.outputs.version }} 98 | cd ${GITHUB_WORKSPACE}/config/default-vxlan/vxlan-controller && kustomize edit set image vxlan-controller=${{ env.IMG_VXLAN }}:${{ steps.get_version.outputs.version }} 99 | cd ${GITHUB_WORKSPACE}/config/default-vxlan/vxlan-ipam && kustomize edit set image vxlan-controller=${{ env.IMG_VXLAN }}:${{ steps.get_version.outputs.version }} 100 | cd ${GITHUB_WORKSPACE} 101 | kustomize build config/default-vxlan/multus --output neonvm-multus.yaml 102 | kustomize build config/default-vxlan --output neonvm-vxlan.yaml 103 | kustomize build config/default --output neonvm.yaml 104 | 105 | - name: github release 106 | uses: softprops/action-gh-release@v1 107 | with: 108 | files: | 109 | neonvm-multus.yaml 110 | neonvm-vxlan.yaml 111 | neonvm.yaml 112 | bin/vm-builder 113 | -------------------------------------------------------------------------------- /.github/workflows/tests.yaml: -------------------------------------------------------------------------------- 1 | name: tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - release 8 | pull_request: 9 | 10 | defaults: 11 | run: 12 | shell: bash -euo pipefail {0} 13 | 14 | concurrency: 15 | # Allow only one workflow per any non-`main` branch. 16 | group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref == 'refs/heads/main' && github.sha || 'anysha' }} 17 | cancel-in-progress: true 18 | 19 | jobs: 20 | e2e: 21 | runs-on: [ self-hosted, gen3, small ] 22 | steps: 23 | - uses: actions/checkout@v3 24 | 25 | - uses: actions/setup-go@v3 26 | with: 27 | go-version-file: 'go.mod' 28 | cache: true 29 | 30 | - name: Install dependencies 31 | run: | 32 | LOCALBIN=$(pwd)/bin 33 | mkdir -p ${LOCALBIN} 34 | 35 | # Install kubectl 36 | curl -Lo ${LOCALBIN}/kubectl "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" 37 | chmod +x ${LOCALBIN}/kubectl 38 | 39 | # Install kind 40 | curl -Lo ${LOCALBIN}/kind https://kind.sigs.k8s.io/dl/${KIND_VERSION}/kind-linux-amd64 41 | chmod +x ${LOCALBIN}/kind 42 | 43 | # Install kuttl 44 | curl -Lo ${LOCALBIN}/kubectl-kuttl https://github.com/kudobuilder/kuttl/releases/download/${KUTTL_VERSION}/kubectl-kuttl_${KUTTL_VERSION#v}_linux_x86_64 45 | chmod +x ${LOCALBIN}/kubectl-kuttl 46 | 47 | echo ${LOCALBIN} >> $GITHUB_PATH 48 | env: 49 | KUBECTL_VERSION: v1.26.1 50 | KIND_VERSION: v0.17.0 51 | KUTTL_VERSION: v0.15.0 52 | 53 | - name: Check dependencies 54 | run: | 55 | kubectl version --client --output=yaml 56 | kind version 57 | kubectl kuttl version 58 | 59 | # To save some time use prebuilt vm kernel instead of running `make kernel` (see .github/workflows/release.yaml) 60 | - name: Load VM kernel 61 | run: | 62 | docker pull --quiet ${VM_KERNEL_IMAGE}:${VM_KERNEL_VERSION} 63 | ID=$(docker create ${VM_KERNEL_IMAGE}:${VM_KERNEL_VERSION} true) 64 | docker cp ${ID}:/vmlinuz hack/vmlinuz 65 | docker rm -f ${ID} 66 | env: 67 | VM_KERNEL_IMAGE: "neondatabase/vm-kernel" 68 | VM_KERNEL_VERSION: "5.15.80" 69 | 70 | - run: make local-cluster 71 | 72 | - run: make deploy 73 | 74 | - name: Run make e2e 75 | run: | 76 | kubectl kuttl test --config tests/e2e/kuttl-test.yaml --skip-delete 77 | 78 | - name: Get k8s logs and events 79 | if: failure() 80 | run: | 81 | namespaces=$(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}') 82 | for namespace in $namespaces; do 83 | pods=$(kubectl get pods -n $namespace -o jsonpath='{.items[*].metadata.name}') 84 | for pod in $pods; do 85 | echo "*** Namespace=$namespace Pod=$pod ***" 86 | echo "Logs:" 87 | kubectl logs -n $namespace $pod 88 | echo "Events:" 89 | kubectl get events --namespace $namespace --field-selector involvedObject.name=$pod 90 | echo "" 91 | done 92 | done 93 | 94 | - name: Cleanup 95 | if: always() 96 | run: | 97 | kind delete cluster 98 | -------------------------------------------------------------------------------- /.github/workflows/vm-example.yaml: -------------------------------------------------------------------------------- 1 | name: vm-example 2 | 3 | on: 4 | schedule: 5 | - cron: '42 4 * * 2' # run once a week 6 | workflow_dispatch: # adds ability to run this manually 7 | 8 | jobs: 9 | vm-example: 10 | runs-on: ubuntu-latest 11 | steps: 12 | 13 | - name: git checkout 14 | uses: actions/checkout@v3 15 | 16 | - name: install golang 17 | uses: actions/setup-go@v3 18 | with: 19 | go-version-file: 'go.mod' 20 | cache: true 21 | 22 | - name: build vm-builder 23 | run: go build -o bin/vm-builder tools/vm-builder/main.go 24 | 25 | - name: docker - install qemu 26 | uses: docker/setup-qemu-action@v2 27 | - name: docker - setup buildx 28 | uses: docker/setup-buildx-action@v2 29 | - name: login to docker hub 30 | uses: docker/login-action@v2 31 | with: 32 | username: ${{ secrets.NEON_DOCKERHUB_USERNAME }} 33 | password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }} 34 | 35 | - name: build vm-alpine:3.16 36 | run: bin/vm-builder -src alpine:3.16 -dst neondatabase/vm-alpine:3.16 37 | - name: push vm-alpine:3.16 38 | run: docker push -q neondatabase/vm-alpine:3.16 39 | 40 | - name: build vm-ubuntu:22.04 41 | run: bin/vm-builder -src ubuntu:22.04 -dst neondatabase/vm-ubuntu:22.04 42 | - name: push vm-ubuntu:22.04 43 | run: docker push -q neondatabase/vm-ubuntu:22.04 44 | 45 | - name: build vm-debian:11 46 | run: bin/vm-builder -src debian:11 -dst neondatabase/vm-debian:11 47 | - name: push vm-debian:11 48 | run: docker push -q neondatabase/vm-debian:11 49 | 50 | - name: build vm-postgres:14-alpine 51 | run: bin/vm-builder -src postgres:14-alpine -dst neondatabase/vm-postgres:14-alpine 52 | - name: push vm-postgres:14-alpine 53 | run: docker push -q neondatabase/vm-postgres:14-alpine 54 | -------------------------------------------------------------------------------- /.github/workflows/vm-kernel.yaml: -------------------------------------------------------------------------------- 1 | name: vm-kernel 2 | 3 | on: 4 | schedule: 5 | - cron: '42 4 * * 2' # run once a week 6 | workflow_dispatch: # adds ability to run this manually 7 | 8 | env: 9 | VM_KERNEL_IMAGE: "neondatabase/vm-kernel" 10 | VM_KERNEL_VERSION: "5.15.80" 11 | 12 | jobs: 13 | vm-kernel: 14 | runs-on: ubuntu-latest 15 | steps: 16 | 17 | - name: git checkout 18 | uses: actions/checkout@v3 19 | 20 | - name: docker - install qemu 21 | uses: docker/setup-qemu-action@v2 22 | - name: docker - setup buildx 23 | uses: docker/setup-buildx-action@v2 24 | - name: login to docker hub 25 | uses: docker/login-action@v2 26 | with: 27 | username: ${{ secrets.NEON_DOCKERHUB_USERNAME }} 28 | password: ${{ secrets.NEON_DOCKERHUB_PASSWORD }} 29 | 30 | - name: build linux kernel 31 | uses: docker/build-push-action@v3 32 | with: 33 | build-args: KERNEL_VERSION=${{ env.VM_KERNEL_VERSION }} 34 | context: . 35 | platforms: linux/amd64 36 | push: true 37 | pull: true 38 | no-cache: true 39 | file: hack/Dockerfile.kernel-builder 40 | tags: ${{ env.VM_KERNEL_IMAGE }}:${{ env.VM_KERNEL_VERSION }} 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | testbin/* 10 | Dockerfile.cross 11 | 12 | # Test binary, build with `go test -c` 13 | *.test 14 | 15 | # Output of the go coverage tool, specifically when used with LiteIDE 16 | *.out 17 | 18 | # Kubernetes Generated files - skip generated files, except for vendored files 19 | 20 | !vendor/**/zz_generated.* 21 | 22 | # editor and IDE paraphernalia 23 | .idea 24 | *.swp 25 | *.swo 26 | *~ 27 | 28 | *.qcow2 29 | vmlinuz 30 | neonvm.yaml 31 | neonvm-vxlan.yaml 32 | neonvm-multus.yaml 33 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM golang:1.19 as builder 3 | ARG TARGETOS 4 | ARG TARGETARCH 5 | 6 | WORKDIR /workspace 7 | # Copy the Go Modules manifests 8 | COPY go.mod go.mod 9 | COPY go.sum go.sum 10 | # cache deps before building and copying source so that we don't need to re-download as much 11 | # and so that source changes don't invalidate our downloaded layer 12 | RUN go mod download 13 | 14 | # Copy the go source 15 | COPY main.go main.go 16 | COPY apis/ apis/ 17 | COPY controllers/ controllers/ 18 | 19 | # Build 20 | # the GOARCH has not a default value to allow the binary be built according to the host where the command 21 | # was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO 22 | # the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, 23 | # by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. 24 | RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager main.go 25 | 26 | # Use distroless as minimal base image to package the manager binary 27 | # Refer to https://github.com/GoogleContainerTools/distroless for more details 28 | FROM gcr.io/distroless/static:nonroot 29 | 30 | ARG VM_RUNNER_IMAGE=runner:dev 31 | ENV VM_RUNNER_IMAGE=${VM_RUNNER_IMAGE} 32 | 33 | WORKDIR / 34 | COPY --from=builder /workspace/manager . 35 | USER 65532:65532 36 | 37 | ENTRYPOINT ["/manager"] 38 | -------------------------------------------------------------------------------- /PROJECT: -------------------------------------------------------------------------------- 1 | domain: neon.tech 2 | layout: 3 | - go.kubebuilder.io/v3 4 | plugins: 5 | deploy-image.go.kubebuilder.io/v1-alpha: 6 | resources: 7 | - domain: neon.tech 8 | group: vm 9 | kind: VirtualMachine 10 | options: 11 | containerCommand: ping,8.8.8.8 12 | containerPort: "8080" 13 | image: alpine:3.16 14 | version: v1 15 | projectName: neonvm 16 | repo: github.com/neondatabase/neonvm 17 | resources: 18 | - api: 19 | crdVersion: v1 20 | namespaced: true 21 | controller: true 22 | domain: neon.tech 23 | group: vm 24 | kind: VirtualMachine 25 | path: github.com/neondatabase/neonvm/apis/neonvm/v1 26 | version: v1 27 | webhooks: 28 | defaulting: true 29 | validation: true 30 | webhookVersion: v1 31 | version: "3" 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # :warning: Repository Moved :warning: 2 | 3 | **This repository has been moved to [neondatabase/autoscaling/neonvm](https://github.com/neondatabase/autoscaling/tree/main/neonvm).** 4 | 5 | The NeonVM functionality is now a part of the Autoscaling project. All future updates and development will take place in the new project repository. 6 | 7 | --- 8 | 9 | # NeonVM: QEMU-based virtualization API and controlller for Kubernetes 10 | 11 | ## Description 12 | 13 | ## Getting Started 14 | You’ll need a Kubernetes cluster to run against. You can use [KIND](https://sigs.k8s.io/kind) to get a local cluster for testing, or run against a remote cluster. 15 | **Note:** Your controller will automatically use the current context in your kubeconfig file (i.e. whatever cluster `kubectl cluster-info` shows). 16 | 17 | ### Install cert-manager 18 | 19 | ```console 20 | kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml 21 | ``` 22 | 23 | ### Install NeonVM with VXLAN-based overlay network 24 | 25 | ```console 26 | kubectl apply -f https://github.com/neondatabase/neonvm/releases/latest/download/neonvm-multus.yaml 27 | kubectl apply -f https://github.com/neondatabase/neonvm/releases/latest/download/neonvm-vxlan.yaml 28 | ``` 29 | 30 | ### Run virtual machine 31 | 32 | ```console 33 | cat < 60 | 61 | root@neonvm:~# 62 | root@neonvm:~# apt-get update >/dev/null && apt-get install -y curl >/dev/null 63 | root@neonvm:~# curl -k https://kubernetes/version 64 | { 65 | "major": "1", 66 | "minor": "25", 67 | "gitVersion": "v1.25.2", 68 | "gitCommit": "5835544ca568b757a8ecae5c153f317e5736700e", 69 | "gitTreeState": "clean", 70 | "buildDate": "2022-09-22T05:25:21Z", 71 | "goVersion": "go1.19.1", 72 | "compiler": "gc", 73 | "platform": "linux/amd64" 74 | } 75 | 76 | 77 | ``` 78 | 79 | ### Delete virtual machine 80 | 81 | ```console 82 | kubectl delete neonvm vm-debian 83 | ``` 84 | 85 | 86 | ## Local development 87 | 88 | ### Run NeonVM locally 89 | 90 | #### 1. Create local cluster (with 3 nodes) 91 | 92 | ```sh 93 | make local-cluster 94 | ``` 95 | 96 | #### 2. Build Linux kernel for Guests 97 | 98 | ```sh 99 | make kernel 100 | ``` 101 | 102 | #### 3. Build and deploy controller and VXLAN overlay network to local cluster 103 | 104 | ```sh 105 | make deploy 106 | ``` 107 | 108 | ### Manage Virtual Machines 109 | 110 | #### 1. Run virtual machine 111 | 112 | ```console 113 | kubectl apply -f samples/vm-example.yaml 114 | ``` 115 | 116 | #### 2. Check VM running 117 | 118 | ```sh 119 | kubectl get neonvm example 120 | 121 | kubectl get neonvm example -owide 122 | 123 | kubectl describe neonvm example 124 | ``` 125 | 126 | #### 3. Check logs 127 | 128 | ```sh 129 | VM_POD=$(kubectl get neonvm example -ojsonpath='{.status.podName}') 130 | kubectl logs $VM_POD 131 | ``` 132 | 133 | #### 4. Connect to console inside VM 134 | 135 | ```sh 136 | kubectl exec -it $VM_POD -- screen /dev/pts/0 137 | 138 | 139 | ``` 140 | to exit from console presss `CTRL-a k` (see manual for `screen` tool) 141 | 142 | #### 5. Plug/Unplug CPUs in VM 143 | 144 | edit `.spec.guest.cpus.use` field by editor 145 | 146 | ```sh 147 | kubectl edit neonvm example 148 | ``` 149 | 150 | or apply patch (set `cpus.use` to `2`) 151 | 152 | ```sh 153 | kubectl patch neonvm example --type='json' -p='[{"op": "replace", "path": "/spec/guest/cpus/use", "value":2}]' 154 | ``` 155 | 156 | and then check status by `kubectl get neonvm example` and inspect `/sys/devices/system/cpu` folder inside VM 157 | 158 | #### 6. Plug/Unplug Memory in VM 159 | 160 | edit `.spec.guest.memorySlots.use` field by editor 161 | 162 | ```sh 163 | kubectl edit neonvm example 164 | ``` 165 | 166 | or apply patch (as example set `memorySlots.use` to `4`) 167 | 168 | ```sh 169 | kubectl patch neonvm example --type='json' -p='[{"op": "replace", "path": "/spec/guest/memorySlots/use", "value":4}]' 170 | ``` 171 | 172 | and then check status by `kubectl get neonvm example` and inspect memory inside VM by `free -h` command 173 | 174 | #### 7. Do live migration 175 | 176 | inspect VM details to see on what node it running 177 | 178 | ```sh 179 | $ kubectl get neonvm -owide 180 | NAME CPUS MEMORY POD STATUS AGE NODE IMAGE 181 | example 1 2Gi example-xdw4s Running 31s kind-worker vm-postgres:15-alpine 182 | ``` 183 | 184 | trigger live migration 185 | 186 | ```sh 187 | kubectl apply -f samples/vm-example-migration.yaml 188 | ``` 189 | 190 | inspect migration details 191 | 192 | ```sh 193 | $ kubectl get neonvmm -owide 194 | NAME VM SOURCE SOURCEIP TARGET TARGETIP STATUS AGE 195 | example example example-xdw4s 10.244.1.7 example-7ztb2 10.244.2.6 Succeeded 33s 196 | ``` 197 | 198 | inspect VM details again (look at pod name and node) 199 | 200 | ```sh 201 | $ kubectl get neonvm -owide 202 | NAME CPUS MEMORY POD STATUS AGE NODE IMAGE 203 | example 1 2Gi example-7ztb2 Running 4m12s kind-worker2 vm-postgres:15-alpine 204 | ``` 205 | 206 | inspect migration details 207 | 208 | ```sh 209 | $ kubectl get neonvmm example -ojsonpath='{.status.info}' | jq 210 | { 211 | "compression": { 212 | "compressedSize": 44687045 213 | }, 214 | "downtimeMs": 39, 215 | "ram": { 216 | "total": 2148278272, 217 | "transferred": 76324646 218 | }, 219 | "setupTimeMs": 2, 220 | "status": "completed", 221 | "totalTimeMs": 3861 222 | } 223 | ``` 224 | 225 | ### Uninstall CRDs 226 | To delete the CRDs from the cluster: 227 | 228 | ```sh 229 | make uninstall 230 | ``` 231 | 232 | ### Undeploy controller 233 | UnDeploy the controller to the cluster: 234 | 235 | ```sh 236 | make undeploy 237 | ``` 238 | 239 | ## How it works 240 | This project aims to follow the Kubernetes [Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) 241 | 242 | It uses [Controllers](https://kubernetes.io/docs/concepts/architecture/controller/) 243 | which provides a reconcile function responsible for synchronizing resources untile the desired state is reached on the cluster 244 | 245 | ## Roadmap 246 | 247 | - [x] Implement Webhooks for mutation and validation 248 | - [x] Multus CNI support 249 | - [x] Hot[un]plug CPUs and Memory (via resource patch) 250 | - [x] Live migration CRDs 251 | - [x] Simplify VM disk image creation from any docker image 252 | - [ ] ARM64 support 253 | 254 | 255 | ## License 256 | 257 | Copyright 2022. 258 | 259 | Licensed under the Apache License, Version 2.0 (the "License"); 260 | you may not use this file except in compliance with the License. 261 | You may obtain a copy of the License at 262 | 263 | http://www.apache.org/licenses/LICENSE-2.0 264 | 265 | Unless required by applicable law or agreed to in writing, software 266 | distributed under the License is distributed on an "AS IS" BASIS, 267 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 268 | See the License for the specific language governing permissions and 269 | limitations under the License. 270 | 271 | -------------------------------------------------------------------------------- /apis/neonvm/v1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1 contains API Schema definitions for the vm v1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=vm.neon.tech 20 | package v1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // SchemeGroupVersion is group version used to register these objects 29 | SchemeGroupVersion = schema.GroupVersion{Group: "vm.neon.tech", Version: "v1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 32 | SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | 38 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 39 | func Resource(resource string) schema.GroupResource { 40 | return SchemeGroupVersion.WithResource(resource).GroupResource() 41 | } 42 | -------------------------------------------------------------------------------- /apis/neonvm/v1/virtualmachine_webhook.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | "fmt" 21 | "reflect" 22 | 23 | "k8s.io/apimachinery/pkg/runtime" 24 | ctrl "sigs.k8s.io/controller-runtime" 25 | logf "sigs.k8s.io/controller-runtime/pkg/log" 26 | "sigs.k8s.io/controller-runtime/pkg/webhook" 27 | ) 28 | 29 | // log is for logging in this package. 30 | var virtualmachinelog = logf.Log.WithName("virtualmachine-resource") 31 | 32 | func (r *VirtualMachine) SetupWebhookWithManager(mgr ctrl.Manager) error { 33 | return ctrl.NewWebhookManagedBy(mgr). 34 | For(r). 35 | Complete() 36 | } 37 | 38 | //+kubebuilder:webhook:path=/mutate-vm-neon-tech-v1-virtualmachine,mutating=true,failurePolicy=fail,sideEffects=None,groups=vm.neon.tech,resources=virtualmachines,verbs=create;update,versions=v1,name=mvirtualmachine.kb.io,admissionReviewVersions=v1 39 | 40 | var _ webhook.Defaulter = &VirtualMachine{} 41 | 42 | // Default implements webhook.Defaulter so a webhook will be registered for the type 43 | func (r *VirtualMachine) Default() { 44 | virtualmachinelog.Info("default", "name", r.Name) 45 | 46 | // TODO(user): fill in your defaulting logic. 47 | } 48 | 49 | // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. 50 | //+kubebuilder:webhook:path=/validate-vm-neon-tech-v1-virtualmachine,mutating=false,failurePolicy=fail,sideEffects=None,groups=vm.neon.tech,resources=virtualmachines,verbs=create;update,versions=v1,name=vvirtualmachine.kb.io,admissionReviewVersions=v1 51 | 52 | var _ webhook.Validator = &VirtualMachine{} 53 | 54 | // ValidateCreate implements webhook.Validator so a webhook will be registered for the type 55 | func (r *VirtualMachine) ValidateCreate() error { 56 | virtualmachinelog.Info("validate create", "name", r.Name) 57 | 58 | // validate .spec.guest.cpus.use and .spec.guest.cpus.max 59 | if r.Spec.Guest.CPUs.Use != nil { 60 | if r.Spec.Guest.CPUs.Max == nil { 61 | return fmt.Errorf(".spec.guest.cpus.max must be defined if .spec.guest.cpus.use specified") 62 | } 63 | if *r.Spec.Guest.CPUs.Use < *r.Spec.Guest.CPUs.Min { 64 | return fmt.Errorf(".spec.guest.cpus.use (%d) should be greater than or equal to the .spec.guest.cpus.min (%d)", 65 | *r.Spec.Guest.CPUs.Use, 66 | *r.Spec.Guest.CPUs.Min) 67 | } 68 | if *r.Spec.Guest.CPUs.Use > *r.Spec.Guest.CPUs.Max { 69 | return fmt.Errorf(".spec.guest.cpus.use (%d) should be less than or equal to the .spec.guest.cpus.max (%d)", 70 | *r.Spec.Guest.CPUs.Use, 71 | *r.Spec.Guest.CPUs.Max) 72 | } 73 | } 74 | 75 | // validate .spec.guest.memorySlots.use and .spec.guest.memorySlots.max 76 | if r.Spec.Guest.MemorySlots.Use != nil { 77 | if r.Spec.Guest.MemorySlots.Max == nil { 78 | return fmt.Errorf(".spec.guest.memorySlots.max must be defined if .spec.guest.memorySlots.use specified") 79 | } 80 | if *r.Spec.Guest.MemorySlots.Use < *r.Spec.Guest.MemorySlots.Min { 81 | return fmt.Errorf(".spec.guest.memorySlots.use (%d) should be greater than or equal to the .spec.guest.memorySlots.min (%d)", 82 | *r.Spec.Guest.MemorySlots.Use, 83 | *r.Spec.Guest.MemorySlots.Min) 84 | } 85 | if *r.Spec.Guest.MemorySlots.Use > *r.Spec.Guest.MemorySlots.Max { 86 | return fmt.Errorf(".spec.guest.memorySlots.use (%d) should be less than or equal to the .spec.guest.memorySlots.max (%d)", 87 | *r.Spec.Guest.MemorySlots.Use, 88 | *r.Spec.Guest.MemorySlots.Max) 89 | } 90 | } 91 | 92 | // validate .spec.disk names 93 | for _, disk := range r.Spec.Disks { 94 | virtualmachinelog.Info("validate disk", "name", disk.Name) 95 | if disk.Name == "virtualmachineimages" { 96 | return fmt.Errorf("'virtualmachineimages' is reserved name for .spec.disks[].name") 97 | } 98 | if disk.Name == "vmroot" { 99 | return fmt.Errorf("'vmroot' is reserved name for .spec.disks[].name") 100 | } 101 | if disk.Name == "vmruntime" { 102 | return fmt.Errorf("'vmruntime' is reserved name for .spec.disks[].name") 103 | } 104 | if len(disk.Name) > 32 { 105 | return fmt.Errorf("disk name '%s' too long, should be less than or equal to 32", disk.Name) 106 | } 107 | } 108 | 109 | // validate .spec.guest.ports[].name 110 | for _, port := range r.Spec.Guest.Ports { 111 | virtualmachinelog.Info("validate port ", "name", port.Name) 112 | if len(port.Name) != 0 && port.Name == "qmp" { 113 | return fmt.Errorf("'qmp' is reserved name for .spec.guest.ports[].name") 114 | } 115 | } 116 | 117 | return nil 118 | } 119 | 120 | // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type 121 | func (r *VirtualMachine) ValidateUpdate(old runtime.Object) error { 122 | virtualmachinelog.Info("validate update", "name", r.Name) 123 | 124 | // process immutable fields 125 | before, _ := old.(*VirtualMachine) 126 | 127 | if !reflect.DeepEqual(r.Spec.Guest.CPUs.Min, before.Spec.Guest.CPUs.Min) { 128 | return fmt.Errorf(".spec.guest.cpus.min is immutable") 129 | } 130 | if !reflect.DeepEqual(r.Spec.Guest.CPUs.Max, before.Spec.Guest.CPUs.Max) { 131 | return fmt.Errorf(".spec.guest.cpus.max is immutable") 132 | } 133 | if !reflect.DeepEqual(r.Spec.Guest.MemorySlots.Min, before.Spec.Guest.MemorySlots.Min) { 134 | return fmt.Errorf(".spec.guest.memorySlots.min is immutable") 135 | } 136 | if !reflect.DeepEqual(r.Spec.Guest.MemorySlots.Max, before.Spec.Guest.MemorySlots.Max) { 137 | return fmt.Errorf(".spec.guest.memorySlots.max is immutable") 138 | } 139 | if !reflect.DeepEqual(r.Spec.Guest.Ports, before.Spec.Guest.Ports) { 140 | return fmt.Errorf(".spec.guest.ports is immutable") 141 | } 142 | if !reflect.DeepEqual(r.Spec.Guest.RootDisk, before.Spec.Guest.RootDisk) { 143 | return fmt.Errorf(".spec.guest.rootDisk is immutable") 144 | } 145 | if !reflect.DeepEqual(r.Spec.Guest.Command, before.Spec.Guest.Command) { 146 | return fmt.Errorf(".spec.guest.command is immutable") 147 | } 148 | if !reflect.DeepEqual(r.Spec.Guest.Args, before.Spec.Guest.Args) { 149 | return fmt.Errorf(".spec.guest.args is immutable") 150 | } 151 | if !reflect.DeepEqual(r.Spec.Guest.Env, before.Spec.Guest.Env) { 152 | return fmt.Errorf(".spec.guest.env is immutable") 153 | } 154 | if !reflect.DeepEqual(r.Spec.Disks, before.Spec.Disks) { 155 | return fmt.Errorf(".spec.disks is immutable") 156 | } 157 | 158 | // validate .spec.guest.cpu.use 159 | if r.Spec.Guest.CPUs.Use != nil { 160 | if *r.Spec.Guest.CPUs.Use < *r.Spec.Guest.CPUs.Min { 161 | return fmt.Errorf(".cpus.use (%d) should be greater than or equal to the .cpus.min (%d)", 162 | *r.Spec.Guest.CPUs.Use, 163 | *r.Spec.Guest.CPUs.Min) 164 | } 165 | if *r.Spec.Guest.CPUs.Use > *r.Spec.Guest.CPUs.Max { 166 | return fmt.Errorf(".cpus.use (%d) should be less than or equal to the .cpus.max (%d)", 167 | *r.Spec.Guest.CPUs.Use, 168 | *r.Spec.Guest.CPUs.Max) 169 | } 170 | } 171 | 172 | // validate .spec.guest.memorySlots.use 173 | if r.Spec.Guest.MemorySlots.Use != nil { 174 | if *r.Spec.Guest.MemorySlots.Use < *r.Spec.Guest.MemorySlots.Min { 175 | return fmt.Errorf(".memorySlots.use (%d) should be greater than or equal to the .memorySlots.min (%d)", 176 | *r.Spec.Guest.MemorySlots.Use, 177 | *r.Spec.Guest.MemorySlots.Min) 178 | } 179 | if *r.Spec.Guest.MemorySlots.Use > *r.Spec.Guest.MemorySlots.Max { 180 | return fmt.Errorf(".memorySlots.use (%d) should be less than or equal to the .memorySlots.max (%d)", 181 | *r.Spec.Guest.MemorySlots.Use, 182 | *r.Spec.Guest.MemorySlots.Max) 183 | } 184 | } 185 | 186 | return nil 187 | } 188 | 189 | // ValidateDelete implements webhook.Validator so a webhook will be registered for the type 190 | func (r *VirtualMachine) ValidateDelete() error { 191 | virtualmachinelog.Info("validate delete", "name", r.Name) 192 | 193 | // TODO(user): fill in your validation logic upon object deletion. 194 | return nil 195 | } 196 | -------------------------------------------------------------------------------- /apis/neonvm/v1/virtualmachinemigration_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | corev1 "k8s.io/api/core/v1" 21 | "k8s.io/apimachinery/pkg/api/resource" 22 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | ) 24 | 25 | const MigrationPort int32 = 20187 26 | 27 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 28 | 29 | // VirtualMachineMigrationSpec defines the desired state of VirtualMachineMigration 30 | type VirtualMachineMigrationSpec struct { 31 | VmName string `json:"vmName"` 32 | 33 | // TODO: not implemented 34 | // +optional 35 | NodeSelector map[string]string `json:"nodeSelector,omitempty"` 36 | // TODO: not implemented 37 | // +optional 38 | NodeAffinity *corev1.NodeAffinity `json:"nodeAffinity,omitempty"` 39 | 40 | // +optional 41 | // +kubebuilder:default:=true 42 | PreventMigrationToSameHost bool `json:"preventMigrationToSameHost"` 43 | 44 | // TODO: not implemented 45 | // Set 1 hour as default timeout for migration 46 | // +optional 47 | // +kubebuilder:default:=3600 48 | CompletionTimeout int32 `json:"completionTimeout"` 49 | 50 | // Trigger incremental disk copy migration by default, otherwise full disk copy used in migration 51 | // +optional 52 | // +kubebuilder:default:=true 53 | Incremental bool `json:"incremental"` 54 | 55 | // Use PostCopy migration by default 56 | // +optional 57 | // +kubebuilder:default:=true 58 | AllowPostCopy bool `json:"allowPostCopy"` 59 | 60 | // Use Auto converge by default 61 | // +optional 62 | // +kubebuilder:default:=true 63 | AutoConverge bool `json:"autoConverge"` 64 | 65 | // Set 1 Gbyte/sec as default for migration bandwidth 66 | // +optional 67 | // +kubebuilder:default:="1Gi" 68 | MaxBandwidth resource.Quantity `json:"maxBandwidth"` 69 | } 70 | 71 | // VirtualMachineMigrationStatus defines the observed state of VirtualMachineMigration 72 | type VirtualMachineMigrationStatus struct { 73 | // Represents the observations of a VirtualMachineMigration's current state. 74 | // VirtualMachineMigration.status.conditions.type are: "Available", "Progressing", and "Degraded" 75 | // VirtualMachineMigration.status.conditions.status are one of True, False, Unknown. 76 | // VirtualMachineMigration.status.conditions.reason the value should be a CamelCase string and producers of specific 77 | // condition types may define expected values and meanings for this field, and whether the values 78 | // are considered a guaranteed API. 79 | // VirtualMachineMigration.status.conditions.Message is a human readable message indicating details about the transition. 80 | // For further information see: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties 81 | 82 | Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` 83 | 84 | // The phase of a VM is a simple, high-level summary of where the VM is in its lifecycle. 85 | // +optional 86 | Phase VmmPhase `json:"phase,omitempty"` 87 | // +optional 88 | SourcePodName string `json:"sourcePodName,omitempty"` 89 | // +optional 90 | TargetPodName string `json:"targetPodName,omitempty"` 91 | // +optional 92 | SourcePodIP string `json:"sourcePodIP,omitempty"` 93 | // +optional 94 | TargetPodIP string `json:"targetPodIP,omitempty"` 95 | // +optional 96 | SourceNode string `json:"sourceNode,omitempty"` 97 | // +optional 98 | TargetNode string `json:"targetNode,omitempty"` 99 | // +optional 100 | Info MigrationInfo `json:"info,omitempty"` 101 | } 102 | 103 | type MigrationInfo struct { 104 | // +optional 105 | Status string `json:"status,omitempty"` 106 | // +optional 107 | TotalTimeMs int64 `json:"totalTimeMs,omitempty"` 108 | // +optional 109 | SetupTimeMs int64 `json:"setupTimeMs,omitempty"` 110 | // +optional 111 | DowntimeMs int64 `json:"downtimeMs,omitempty"` 112 | // +optional 113 | Ram MigrationInfoRam `json:"ram,omitempty"` 114 | // +optional 115 | Compression MigrationInfoCompression `json:"compression,omitempty"` 116 | } 117 | 118 | type MigrationInfoRam struct { 119 | // +optional 120 | Transferred int64 `json:"transferred,omitempty"` 121 | // +optional 122 | Remaining int64 `json:"remaining,omitempty"` 123 | // +optional 124 | Total int64 `json:"total,omitempty"` 125 | } 126 | 127 | type MigrationInfoCompression struct { 128 | // +optional 129 | CompressedSize int64 `json:"compressedSize,omitempty"` 130 | // +optional 131 | CompressionRate int64 `json:"compressionRate,omitempty"` 132 | } 133 | 134 | type VmmPhase string 135 | 136 | const ( 137 | // VmmPending means the migration has been accepted by the system, but target vm-runner pod 138 | // has not been started. This includes time before being bound to a node, as well as time spent 139 | // pulling images onto the host. 140 | VmmPending VmmPhase = "Pending" 141 | // VmmRunning means the target vm-runner pod has been bound to a node and have been started. 142 | VmmRunning VmmPhase = "Running" 143 | // VmmSucceeded means that migration finisged with success 144 | VmmSucceeded VmmPhase = "Succeeded" 145 | // VmmFailed means that migration failed 146 | VmmFailed VmmPhase = "Failed" 147 | ) 148 | 149 | //+genclient 150 | //+kubebuilder:object:root=true 151 | //+kubebuilder:subresource:status 152 | //+kubebuilder:resource:singular=neonvmm 153 | 154 | // VirtualMachineMigration is the Schema for the virtualmachinemigrations API 155 | // +kubebuilder:printcolumn:name="VM",type=string,JSONPath=`.spec.vmName` 156 | // +kubebuilder:printcolumn:name="Source",type=string,JSONPath=`.status.sourcePodName` 157 | // +kubebuilder:printcolumn:name="SourceIP",type=string,priority=1,JSONPath=`.status.sourcePodIP` 158 | // +kubebuilder:printcolumn:name="Target",type=string,JSONPath=`.status.targetPodName` 159 | // +kubebuilder:printcolumn:name="TargetIP",type=string,priority=1,JSONPath=`.status.targetPodIP` 160 | // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase` 161 | // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" 162 | type VirtualMachineMigration struct { 163 | metav1.TypeMeta `json:",inline"` 164 | metav1.ObjectMeta `json:"metadata,omitempty"` 165 | 166 | Spec VirtualMachineMigrationSpec `json:"spec,omitempty"` 167 | Status VirtualMachineMigrationStatus `json:"status,omitempty"` 168 | } 169 | 170 | //+kubebuilder:object:root=true 171 | 172 | // VirtualMachineMigrationList contains a list of VirtualMachineMigration 173 | type VirtualMachineMigrationList struct { 174 | metav1.TypeMeta `json:",inline"` 175 | metav1.ListMeta `json:"metadata,omitempty"` 176 | Items []VirtualMachineMigration `json:"items"` 177 | } 178 | 179 | func init() { 180 | SchemeBuilder.Register(&VirtualMachineMigration{}, &VirtualMachineMigrationList{}) 181 | } 182 | -------------------------------------------------------------------------------- /apis/neonvm/v1/virtualmachinemigration_webhook.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/runtime" 21 | ctrl "sigs.k8s.io/controller-runtime" 22 | logf "sigs.k8s.io/controller-runtime/pkg/log" 23 | "sigs.k8s.io/controller-runtime/pkg/webhook" 24 | ) 25 | 26 | // log is for logging in this package. 27 | var virtualmachinemigrationlog = logf.Log.WithName("virtualmachinemigration-resource") 28 | 29 | func (r *VirtualMachineMigration) SetupWebhookWithManager(mgr ctrl.Manager) error { 30 | return ctrl.NewWebhookManagedBy(mgr). 31 | For(r). 32 | Complete() 33 | } 34 | 35 | // TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 36 | 37 | //+kubebuilder:webhook:path=/mutate-vm-neon-tech-v1-virtualmachinemigration,mutating=true,failurePolicy=fail,sideEffects=None,groups=vm.neon.tech,resources=virtualmachinemigrations,verbs=create;update,versions=v1,name=mvirtualmachinemigration.kb.io,admissionReviewVersions=v1 38 | 39 | var _ webhook.Defaulter = &VirtualMachineMigration{} 40 | 41 | // Default implements webhook.Defaulter so a webhook will be registered for the type 42 | func (r *VirtualMachineMigration) Default() { 43 | virtualmachinemigrationlog.Info("default", "name", r.Name) 44 | 45 | // TODO(user): fill in your defaulting logic. 46 | } 47 | 48 | // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. 49 | //+kubebuilder:webhook:path=/validate-vm-neon-tech-v1-virtualmachinemigration,mutating=false,failurePolicy=fail,sideEffects=None,groups=vm.neon.tech,resources=virtualmachinemigrations,verbs=create;update,versions=v1,name=vvirtualmachinemigration.kb.io,admissionReviewVersions=v1 50 | 51 | var _ webhook.Validator = &VirtualMachineMigration{} 52 | 53 | // ValidateCreate implements webhook.Validator so a webhook will be registered for the type 54 | func (r *VirtualMachineMigration) ValidateCreate() error { 55 | virtualmachinemigrationlog.Info("validate create", "name", r.Name) 56 | 57 | // TODO(user): fill in your validation logic upon object creation. 58 | return nil 59 | } 60 | 61 | // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type 62 | func (r *VirtualMachineMigration) ValidateUpdate(old runtime.Object) error { 63 | virtualmachinemigrationlog.Info("validate update", "name", r.Name) 64 | 65 | // TODO(user): fill in your validation logic upon object update. 66 | return nil 67 | } 68 | 69 | // ValidateDelete implements webhook.Validator so a webhook will be registered for the type 70 | func (r *VirtualMachineMigration) ValidateDelete() error { 71 | virtualmachinemigrationlog.Info("validate delete", "name", r.Name) 72 | 73 | // TODO(user): fill in your validation logic upon object deletion. 74 | return nil 75 | } 76 | -------------------------------------------------------------------------------- /apis/neonvm/v1/webhook_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | "context" 21 | "crypto/tls" 22 | "fmt" 23 | "net" 24 | "path/filepath" 25 | "testing" 26 | "time" 27 | 28 | . "github.com/onsi/ginkgo/v2" 29 | . "github.com/onsi/gomega" 30 | 31 | admissionv1beta1 "k8s.io/api/admission/v1beta1" 32 | //+kubebuilder:scaffold:imports 33 | "k8s.io/apimachinery/pkg/runtime" 34 | "k8s.io/client-go/rest" 35 | ctrl "sigs.k8s.io/controller-runtime" 36 | "sigs.k8s.io/controller-runtime/pkg/client" 37 | "sigs.k8s.io/controller-runtime/pkg/envtest" 38 | logf "sigs.k8s.io/controller-runtime/pkg/log" 39 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 40 | ) 41 | 42 | // These tests use Ginkgo (BDD-style Go testing framework). Refer to 43 | // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. 44 | 45 | var cfg *rest.Config 46 | var k8sClient client.Client 47 | var testEnv *envtest.Environment 48 | var ctx context.Context 49 | var cancel context.CancelFunc 50 | 51 | func TestAPIs(t *testing.T) { 52 | RegisterFailHandler(Fail) 53 | 54 | RunSpecs(t, "Webhook Suite") 55 | } 56 | 57 | var _ = BeforeSuite(func() { 58 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 59 | 60 | ctx, cancel = context.WithCancel(context.TODO()) 61 | 62 | By("bootstrapping test environment") 63 | testEnv = &envtest.Environment{ 64 | CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, 65 | ErrorIfCRDPathMissing: false, 66 | WebhookInstallOptions: envtest.WebhookInstallOptions{ 67 | Paths: []string{filepath.Join("..", "..", "config", "webhook")}, 68 | }, 69 | } 70 | 71 | var err error 72 | // cfg is defined in this file globally. 73 | cfg, err = testEnv.Start() 74 | Expect(err).NotTo(HaveOccurred()) 75 | Expect(cfg).NotTo(BeNil()) 76 | 77 | scheme := runtime.NewScheme() 78 | err = AddToScheme(scheme) 79 | Expect(err).NotTo(HaveOccurred()) 80 | 81 | err = admissionv1beta1.AddToScheme(scheme) 82 | Expect(err).NotTo(HaveOccurred()) 83 | 84 | //+kubebuilder:scaffold:scheme 85 | 86 | k8sClient, err = client.New(cfg, client.Options{Scheme: scheme}) 87 | Expect(err).NotTo(HaveOccurred()) 88 | Expect(k8sClient).NotTo(BeNil()) 89 | 90 | // start webhook server using Manager 91 | webhookInstallOptions := &testEnv.WebhookInstallOptions 92 | mgr, err := ctrl.NewManager(cfg, ctrl.Options{ 93 | Scheme: scheme, 94 | Host: webhookInstallOptions.LocalServingHost, 95 | Port: webhookInstallOptions.LocalServingPort, 96 | CertDir: webhookInstallOptions.LocalServingCertDir, 97 | LeaderElection: false, 98 | MetricsBindAddress: "0", 99 | }) 100 | Expect(err).NotTo(HaveOccurred()) 101 | 102 | err = (&VirtualMachine{}).SetupWebhookWithManager(mgr) 103 | Expect(err).NotTo(HaveOccurred()) 104 | 105 | //+kubebuilder:scaffold:webhook 106 | 107 | go func() { 108 | defer GinkgoRecover() 109 | err = mgr.Start(ctx) 110 | Expect(err).NotTo(HaveOccurred()) 111 | }() 112 | 113 | // wait for the webhook server to get ready 114 | dialer := &net.Dialer{Timeout: time.Second} 115 | addrPort := fmt.Sprintf("%s:%d", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort) 116 | Eventually(func() error { 117 | conn, err := tls.DialWithDialer(dialer, "tcp", addrPort, &tls.Config{InsecureSkipVerify: true}) 118 | if err != nil { 119 | return err 120 | } 121 | conn.Close() 122 | return nil 123 | }).Should(Succeed()) 124 | 125 | }) 126 | 127 | var _ = AfterSuite(func() { 128 | cancel() 129 | By("tearing down the test environment") 130 | err := testEnv.Stop() 131 | Expect(err).NotTo(HaveOccurred()) 132 | }) 133 | -------------------------------------------------------------------------------- /client/clientset/versioned/clientset.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | "net/http" 23 | 24 | neonvmv1 "github.com/neondatabase/neonvm/client/clientset/versioned/typed/neonvm/v1" 25 | discovery "k8s.io/client-go/discovery" 26 | rest "k8s.io/client-go/rest" 27 | flowcontrol "k8s.io/client-go/util/flowcontrol" 28 | ) 29 | 30 | type Interface interface { 31 | Discovery() discovery.DiscoveryInterface 32 | NeonvmV1() neonvmv1.NeonvmV1Interface 33 | } 34 | 35 | // Clientset contains the clients for groups. 36 | type Clientset struct { 37 | *discovery.DiscoveryClient 38 | neonvmV1 *neonvmv1.NeonvmV1Client 39 | } 40 | 41 | // NeonvmV1 retrieves the NeonvmV1Client 42 | func (c *Clientset) NeonvmV1() neonvmv1.NeonvmV1Interface { 43 | return c.neonvmV1 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 | // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), 58 | // where httpClient was generated with rest.HTTPClientFor(c). 59 | func NewForConfig(c *rest.Config) (*Clientset, error) { 60 | configShallowCopy := *c 61 | 62 | if configShallowCopy.UserAgent == "" { 63 | configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent() 64 | } 65 | 66 | // share the transport between all clients 67 | httpClient, err := rest.HTTPClientFor(&configShallowCopy) 68 | if err != nil { 69 | return nil, err 70 | } 71 | 72 | return NewForConfigAndClient(&configShallowCopy, httpClient) 73 | } 74 | 75 | // NewForConfigAndClient creates a new Clientset for the given config and http client. 76 | // Note the http client provided takes precedence over the configured transport values. 77 | // If config's RateLimiter is not set and QPS and Burst are acceptable, 78 | // NewForConfigAndClient will generate a rate-limiter in configShallowCopy. 79 | func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) { 80 | configShallowCopy := *c 81 | if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { 82 | if configShallowCopy.Burst <= 0 { 83 | 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") 84 | } 85 | configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) 86 | } 87 | 88 | var cs Clientset 89 | var err error 90 | cs.neonvmV1, err = neonvmv1.NewForConfigAndClient(&configShallowCopy, httpClient) 91 | if err != nil { 92 | return nil, err 93 | } 94 | 95 | cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) 96 | if err != nil { 97 | return nil, err 98 | } 99 | return &cs, nil 100 | } 101 | 102 | // NewForConfigOrDie creates a new Clientset for the given config and 103 | // panics if there is an error in the config. 104 | func NewForConfigOrDie(c *rest.Config) *Clientset { 105 | cs, err := NewForConfig(c) 106 | if err != nil { 107 | panic(err) 108 | } 109 | return cs 110 | } 111 | 112 | // New creates a new Clientset for the given RESTClient. 113 | func New(c rest.Interface) *Clientset { 114 | var cs Clientset 115 | cs.neonvmV1 = neonvmv1.New(c) 116 | 117 | cs.DiscoveryClient = discovery.NewDiscoveryClient(c) 118 | return &cs 119 | } 120 | -------------------------------------------------------------------------------- /client/clientset/versioned/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | -------------------------------------------------------------------------------- /client/clientset/versioned/fake/clientset_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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/neondatabase/neonvm/client/clientset/versioned" 22 | neonvmv1 "github.com/neondatabase/neonvm/client/clientset/versioned/typed/neonvm/v1" 23 | fakeneonvmv1 "github.com/neondatabase/neonvm/client/clientset/versioned/typed/neonvm/v1/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 ( 77 | _ clientset.Interface = &Clientset{} 78 | _ testing.FakeClient = &Clientset{} 79 | ) 80 | 81 | // NeonvmV1 retrieves the NeonvmV1Client 82 | func (c *Clientset) NeonvmV1() neonvmv1.NeonvmV1Interface { 83 | return &fakeneonvmv1.FakeNeonvmV1{Fake: &c.Fake} 84 | } 85 | -------------------------------------------------------------------------------- /client/clientset/versioned/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | -------------------------------------------------------------------------------- /client/clientset/versioned/fake/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | neonvmv1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 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 | 32 | var localSchemeBuilder = runtime.SchemeBuilder{ 33 | neonvmv1.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 | -------------------------------------------------------------------------------- /client/clientset/versioned/scheme/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | -------------------------------------------------------------------------------- /client/clientset/versioned/scheme/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | neonvmv1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 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 | neonvmv1.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 | -------------------------------------------------------------------------------- /client/clientset/versioned/typed/neonvm/v1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 v1 20 | -------------------------------------------------------------------------------- /client/clientset/versioned/typed/neonvm/v1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | -------------------------------------------------------------------------------- /client/clientset/versioned/typed/neonvm/v1/fake/fake_neonvm_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | v1 "github.com/neondatabase/neonvm/client/clientset/versioned/typed/neonvm/v1" 22 | rest "k8s.io/client-go/rest" 23 | testing "k8s.io/client-go/testing" 24 | ) 25 | 26 | type FakeNeonvmV1 struct { 27 | *testing.Fake 28 | } 29 | 30 | func (c *FakeNeonvmV1) VirtualMachines(namespace string) v1.VirtualMachineInterface { 31 | return &FakeVirtualMachines{c, namespace} 32 | } 33 | 34 | func (c *FakeNeonvmV1) VirtualMachineMigrations(namespace string) v1.VirtualMachineMigrationInterface { 35 | return &FakeVirtualMachineMigrations{c, namespace} 36 | } 37 | 38 | // RESTClient returns a RESTClient that is used to communicate 39 | // with API server by this client implementation. 40 | func (c *FakeNeonvmV1) RESTClient() rest.Interface { 41 | var ret *rest.RESTClient 42 | return ret 43 | } 44 | -------------------------------------------------------------------------------- /client/clientset/versioned/typed/neonvm/v1/fake/fake_virtualmachine.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | "context" 22 | 23 | neonvmv1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | labels "k8s.io/apimachinery/pkg/labels" 26 | schema "k8s.io/apimachinery/pkg/runtime/schema" 27 | types "k8s.io/apimachinery/pkg/types" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | testing "k8s.io/client-go/testing" 30 | ) 31 | 32 | // FakeVirtualMachines implements VirtualMachineInterface 33 | type FakeVirtualMachines struct { 34 | Fake *FakeNeonvmV1 35 | ns string 36 | } 37 | 38 | var virtualmachinesResource = schema.GroupVersionResource{Group: "neonvm", Version: "v1", Resource: "virtualmachines"} 39 | 40 | var virtualmachinesKind = schema.GroupVersionKind{Group: "neonvm", Version: "v1", Kind: "VirtualMachine"} 41 | 42 | // Get takes name of the virtualMachine, and returns the corresponding virtualMachine object, and an error if there is any. 43 | func (c *FakeVirtualMachines) Get(ctx context.Context, name string, options v1.GetOptions) (result *neonvmv1.VirtualMachine, err error) { 44 | obj, err := c.Fake. 45 | Invokes(testing.NewGetAction(virtualmachinesResource, c.ns, name), &neonvmv1.VirtualMachine{}) 46 | 47 | if obj == nil { 48 | return nil, err 49 | } 50 | return obj.(*neonvmv1.VirtualMachine), err 51 | } 52 | 53 | // List takes label and field selectors, and returns the list of VirtualMachines that match those selectors. 54 | func (c *FakeVirtualMachines) List(ctx context.Context, opts v1.ListOptions) (result *neonvmv1.VirtualMachineList, err error) { 55 | obj, err := c.Fake. 56 | Invokes(testing.NewListAction(virtualmachinesResource, virtualmachinesKind, c.ns, opts), &neonvmv1.VirtualMachineList{}) 57 | 58 | if obj == nil { 59 | return nil, err 60 | } 61 | 62 | label, _, _ := testing.ExtractFromListOptions(opts) 63 | if label == nil { 64 | label = labels.Everything() 65 | } 66 | list := &neonvmv1.VirtualMachineList{ListMeta: obj.(*neonvmv1.VirtualMachineList).ListMeta} 67 | for _, item := range obj.(*neonvmv1.VirtualMachineList).Items { 68 | if label.Matches(labels.Set(item.Labels)) { 69 | list.Items = append(list.Items, item) 70 | } 71 | } 72 | return list, err 73 | } 74 | 75 | // Watch returns a watch.Interface that watches the requested virtualMachines. 76 | func (c *FakeVirtualMachines) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { 77 | return c.Fake. 78 | InvokesWatch(testing.NewWatchAction(virtualmachinesResource, c.ns, opts)) 79 | 80 | } 81 | 82 | // 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. 83 | func (c *FakeVirtualMachines) Create(ctx context.Context, virtualMachine *neonvmv1.VirtualMachine, opts v1.CreateOptions) (result *neonvmv1.VirtualMachine, err error) { 84 | obj, err := c.Fake. 85 | Invokes(testing.NewCreateAction(virtualmachinesResource, c.ns, virtualMachine), &neonvmv1.VirtualMachine{}) 86 | 87 | if obj == nil { 88 | return nil, err 89 | } 90 | return obj.(*neonvmv1.VirtualMachine), err 91 | } 92 | 93 | // 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. 94 | func (c *FakeVirtualMachines) Update(ctx context.Context, virtualMachine *neonvmv1.VirtualMachine, opts v1.UpdateOptions) (result *neonvmv1.VirtualMachine, err error) { 95 | obj, err := c.Fake. 96 | Invokes(testing.NewUpdateAction(virtualmachinesResource, c.ns, virtualMachine), &neonvmv1.VirtualMachine{}) 97 | 98 | if obj == nil { 99 | return nil, err 100 | } 101 | return obj.(*neonvmv1.VirtualMachine), err 102 | } 103 | 104 | // UpdateStatus was generated because the type contains a Status member. 105 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 106 | func (c *FakeVirtualMachines) UpdateStatus(ctx context.Context, virtualMachine *neonvmv1.VirtualMachine, opts v1.UpdateOptions) (*neonvmv1.VirtualMachine, error) { 107 | obj, err := c.Fake. 108 | Invokes(testing.NewUpdateSubresourceAction(virtualmachinesResource, "status", c.ns, virtualMachine), &neonvmv1.VirtualMachine{}) 109 | 110 | if obj == nil { 111 | return nil, err 112 | } 113 | return obj.(*neonvmv1.VirtualMachine), err 114 | } 115 | 116 | // Delete takes name of the virtualMachine and deletes it. Returns an error if one occurs. 117 | func (c *FakeVirtualMachines) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { 118 | _, err := c.Fake. 119 | Invokes(testing.NewDeleteActionWithOptions(virtualmachinesResource, c.ns, name, opts), &neonvmv1.VirtualMachine{}) 120 | 121 | return err 122 | } 123 | 124 | // DeleteCollection deletes a collection of objects. 125 | func (c *FakeVirtualMachines) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { 126 | action := testing.NewDeleteCollectionAction(virtualmachinesResource, c.ns, listOpts) 127 | 128 | _, err := c.Fake.Invokes(action, &neonvmv1.VirtualMachineList{}) 129 | return err 130 | } 131 | 132 | // Patch applies the patch and returns the patched virtualMachine. 133 | func (c *FakeVirtualMachines) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *neonvmv1.VirtualMachine, err error) { 134 | obj, err := c.Fake. 135 | Invokes(testing.NewPatchSubresourceAction(virtualmachinesResource, c.ns, name, pt, data, subresources...), &neonvmv1.VirtualMachine{}) 136 | 137 | if obj == nil { 138 | return nil, err 139 | } 140 | return obj.(*neonvmv1.VirtualMachine), err 141 | } 142 | -------------------------------------------------------------------------------- /client/clientset/versioned/typed/neonvm/v1/fake/fake_virtualmachinemigration.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | "context" 22 | 23 | neonvmv1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | labels "k8s.io/apimachinery/pkg/labels" 26 | schema "k8s.io/apimachinery/pkg/runtime/schema" 27 | types "k8s.io/apimachinery/pkg/types" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | testing "k8s.io/client-go/testing" 30 | ) 31 | 32 | // FakeVirtualMachineMigrations implements VirtualMachineMigrationInterface 33 | type FakeVirtualMachineMigrations struct { 34 | Fake *FakeNeonvmV1 35 | ns string 36 | } 37 | 38 | var virtualmachinemigrationsResource = schema.GroupVersionResource{Group: "neonvm", Version: "v1", Resource: "virtualmachinemigrations"} 39 | 40 | var virtualmachinemigrationsKind = schema.GroupVersionKind{Group: "neonvm", Version: "v1", Kind: "VirtualMachineMigration"} 41 | 42 | // Get takes name of the virtualMachineMigration, and returns the corresponding virtualMachineMigration object, and an error if there is any. 43 | func (c *FakeVirtualMachineMigrations) Get(ctx context.Context, name string, options v1.GetOptions) (result *neonvmv1.VirtualMachineMigration, err error) { 44 | obj, err := c.Fake. 45 | Invokes(testing.NewGetAction(virtualmachinemigrationsResource, c.ns, name), &neonvmv1.VirtualMachineMigration{}) 46 | 47 | if obj == nil { 48 | return nil, err 49 | } 50 | return obj.(*neonvmv1.VirtualMachineMigration), err 51 | } 52 | 53 | // List takes label and field selectors, and returns the list of VirtualMachineMigrations that match those selectors. 54 | func (c *FakeVirtualMachineMigrations) List(ctx context.Context, opts v1.ListOptions) (result *neonvmv1.VirtualMachineMigrationList, err error) { 55 | obj, err := c.Fake. 56 | Invokes(testing.NewListAction(virtualmachinemigrationsResource, virtualmachinemigrationsKind, c.ns, opts), &neonvmv1.VirtualMachineMigrationList{}) 57 | 58 | if obj == nil { 59 | return nil, err 60 | } 61 | 62 | label, _, _ := testing.ExtractFromListOptions(opts) 63 | if label == nil { 64 | label = labels.Everything() 65 | } 66 | list := &neonvmv1.VirtualMachineMigrationList{ListMeta: obj.(*neonvmv1.VirtualMachineMigrationList).ListMeta} 67 | for _, item := range obj.(*neonvmv1.VirtualMachineMigrationList).Items { 68 | if label.Matches(labels.Set(item.Labels)) { 69 | list.Items = append(list.Items, item) 70 | } 71 | } 72 | return list, err 73 | } 74 | 75 | // Watch returns a watch.Interface that watches the requested virtualMachineMigrations. 76 | func (c *FakeVirtualMachineMigrations) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { 77 | return c.Fake. 78 | InvokesWatch(testing.NewWatchAction(virtualmachinemigrationsResource, c.ns, opts)) 79 | 80 | } 81 | 82 | // Create takes the representation of a virtualMachineMigration and creates it. Returns the server's representation of the virtualMachineMigration, and an error, if there is any. 83 | func (c *FakeVirtualMachineMigrations) Create(ctx context.Context, virtualMachineMigration *neonvmv1.VirtualMachineMigration, opts v1.CreateOptions) (result *neonvmv1.VirtualMachineMigration, err error) { 84 | obj, err := c.Fake. 85 | Invokes(testing.NewCreateAction(virtualmachinemigrationsResource, c.ns, virtualMachineMigration), &neonvmv1.VirtualMachineMigration{}) 86 | 87 | if obj == nil { 88 | return nil, err 89 | } 90 | return obj.(*neonvmv1.VirtualMachineMigration), err 91 | } 92 | 93 | // Update takes the representation of a virtualMachineMigration and updates it. Returns the server's representation of the virtualMachineMigration, and an error, if there is any. 94 | func (c *FakeVirtualMachineMigrations) Update(ctx context.Context, virtualMachineMigration *neonvmv1.VirtualMachineMigration, opts v1.UpdateOptions) (result *neonvmv1.VirtualMachineMigration, err error) { 95 | obj, err := c.Fake. 96 | Invokes(testing.NewUpdateAction(virtualmachinemigrationsResource, c.ns, virtualMachineMigration), &neonvmv1.VirtualMachineMigration{}) 97 | 98 | if obj == nil { 99 | return nil, err 100 | } 101 | return obj.(*neonvmv1.VirtualMachineMigration), err 102 | } 103 | 104 | // UpdateStatus was generated because the type contains a Status member. 105 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 106 | func (c *FakeVirtualMachineMigrations) UpdateStatus(ctx context.Context, virtualMachineMigration *neonvmv1.VirtualMachineMigration, opts v1.UpdateOptions) (*neonvmv1.VirtualMachineMigration, error) { 107 | obj, err := c.Fake. 108 | Invokes(testing.NewUpdateSubresourceAction(virtualmachinemigrationsResource, "status", c.ns, virtualMachineMigration), &neonvmv1.VirtualMachineMigration{}) 109 | 110 | if obj == nil { 111 | return nil, err 112 | } 113 | return obj.(*neonvmv1.VirtualMachineMigration), err 114 | } 115 | 116 | // Delete takes name of the virtualMachineMigration and deletes it. Returns an error if one occurs. 117 | func (c *FakeVirtualMachineMigrations) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { 118 | _, err := c.Fake. 119 | Invokes(testing.NewDeleteActionWithOptions(virtualmachinemigrationsResource, c.ns, name, opts), &neonvmv1.VirtualMachineMigration{}) 120 | 121 | return err 122 | } 123 | 124 | // DeleteCollection deletes a collection of objects. 125 | func (c *FakeVirtualMachineMigrations) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { 126 | action := testing.NewDeleteCollectionAction(virtualmachinemigrationsResource, c.ns, listOpts) 127 | 128 | _, err := c.Fake.Invokes(action, &neonvmv1.VirtualMachineMigrationList{}) 129 | return err 130 | } 131 | 132 | // Patch applies the patch and returns the patched virtualMachineMigration. 133 | func (c *FakeVirtualMachineMigrations) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *neonvmv1.VirtualMachineMigration, err error) { 134 | obj, err := c.Fake. 135 | Invokes(testing.NewPatchSubresourceAction(virtualmachinemigrationsResource, c.ns, name, pt, data, subresources...), &neonvmv1.VirtualMachineMigration{}) 136 | 137 | if obj == nil { 138 | return nil, err 139 | } 140 | return obj.(*neonvmv1.VirtualMachineMigration), err 141 | } 142 | -------------------------------------------------------------------------------- /client/clientset/versioned/typed/neonvm/v1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 v1 19 | 20 | type VirtualMachineExpansion interface{} 21 | 22 | type VirtualMachineMigrationExpansion interface{} 23 | -------------------------------------------------------------------------------- /client/clientset/versioned/typed/neonvm/v1/neonvm_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 v1 19 | 20 | import ( 21 | "net/http" 22 | 23 | v1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 24 | "github.com/neondatabase/neonvm/client/clientset/versioned/scheme" 25 | rest "k8s.io/client-go/rest" 26 | ) 27 | 28 | type NeonvmV1Interface interface { 29 | RESTClient() rest.Interface 30 | VirtualMachinesGetter 31 | VirtualMachineMigrationsGetter 32 | } 33 | 34 | // NeonvmV1Client is used to interact with features provided by the neonvm group. 35 | type NeonvmV1Client struct { 36 | restClient rest.Interface 37 | } 38 | 39 | func (c *NeonvmV1Client) VirtualMachines(namespace string) VirtualMachineInterface { 40 | return newVirtualMachines(c, namespace) 41 | } 42 | 43 | func (c *NeonvmV1Client) VirtualMachineMigrations(namespace string) VirtualMachineMigrationInterface { 44 | return newVirtualMachineMigrations(c, namespace) 45 | } 46 | 47 | // NewForConfig creates a new NeonvmV1Client for the given config. 48 | // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), 49 | // where httpClient was generated with rest.HTTPClientFor(c). 50 | func NewForConfig(c *rest.Config) (*NeonvmV1Client, error) { 51 | config := *c 52 | if err := setConfigDefaults(&config); err != nil { 53 | return nil, err 54 | } 55 | httpClient, err := rest.HTTPClientFor(&config) 56 | if err != nil { 57 | return nil, err 58 | } 59 | return NewForConfigAndClient(&config, httpClient) 60 | } 61 | 62 | // NewForConfigAndClient creates a new NeonvmV1Client for the given config and http client. 63 | // Note the http client provided takes precedence over the configured transport values. 64 | func NewForConfigAndClient(c *rest.Config, h *http.Client) (*NeonvmV1Client, error) { 65 | config := *c 66 | if err := setConfigDefaults(&config); err != nil { 67 | return nil, err 68 | } 69 | client, err := rest.RESTClientForConfigAndClient(&config, h) 70 | if err != nil { 71 | return nil, err 72 | } 73 | return &NeonvmV1Client{client}, nil 74 | } 75 | 76 | // NewForConfigOrDie creates a new NeonvmV1Client for the given config and 77 | // panics if there is an error in the config. 78 | func NewForConfigOrDie(c *rest.Config) *NeonvmV1Client { 79 | client, err := NewForConfig(c) 80 | if err != nil { 81 | panic(err) 82 | } 83 | return client 84 | } 85 | 86 | // New creates a new NeonvmV1Client for the given RESTClient. 87 | func New(c rest.Interface) *NeonvmV1Client { 88 | return &NeonvmV1Client{c} 89 | } 90 | 91 | func setConfigDefaults(config *rest.Config) error { 92 | gv := v1.SchemeGroupVersion 93 | config.GroupVersion = &gv 94 | config.APIPath = "/apis" 95 | config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() 96 | 97 | if config.UserAgent == "" { 98 | config.UserAgent = rest.DefaultKubernetesUserAgent() 99 | } 100 | 101 | return nil 102 | } 103 | 104 | // RESTClient returns a RESTClient that is used to communicate 105 | // with API server by this client implementation. 106 | func (c *NeonvmV1Client) RESTClient() rest.Interface { 107 | if c == nil { 108 | return nil 109 | } 110 | return c.restClient 111 | } 112 | -------------------------------------------------------------------------------- /client/clientset/versioned/typed/neonvm/v1/virtualmachine.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 v1 19 | 20 | import ( 21 | "context" 22 | "time" 23 | 24 | v1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 25 | scheme "github.com/neondatabase/neonvm/client/clientset/versioned/scheme" 26 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | types "k8s.io/apimachinery/pkg/types" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | rest "k8s.io/client-go/rest" 30 | ) 31 | 32 | // VirtualMachinesGetter has a method to return a VirtualMachineInterface. 33 | // A group's client should implement this interface. 34 | type VirtualMachinesGetter interface { 35 | VirtualMachines(namespace string) VirtualMachineInterface 36 | } 37 | 38 | // VirtualMachineInterface has methods to work with VirtualMachine resources. 39 | type VirtualMachineInterface interface { 40 | Create(ctx context.Context, virtualMachine *v1.VirtualMachine, opts metav1.CreateOptions) (*v1.VirtualMachine, error) 41 | Update(ctx context.Context, virtualMachine *v1.VirtualMachine, opts metav1.UpdateOptions) (*v1.VirtualMachine, error) 42 | UpdateStatus(ctx context.Context, virtualMachine *v1.VirtualMachine, opts metav1.UpdateOptions) (*v1.VirtualMachine, error) 43 | Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error 44 | DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error 45 | Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.VirtualMachine, error) 46 | List(ctx context.Context, opts metav1.ListOptions) (*v1.VirtualMachineList, error) 47 | Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) 48 | Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.VirtualMachine, err error) 49 | VirtualMachineExpansion 50 | } 51 | 52 | // virtualMachines implements VirtualMachineInterface 53 | type virtualMachines struct { 54 | client rest.Interface 55 | ns string 56 | } 57 | 58 | // newVirtualMachines returns a VirtualMachines 59 | func newVirtualMachines(c *NeonvmV1Client, namespace string) *virtualMachines { 60 | return &virtualMachines{ 61 | client: c.RESTClient(), 62 | ns: namespace, 63 | } 64 | } 65 | 66 | // Get takes name of the virtualMachine, and returns the corresponding virtualMachine object, and an error if there is any. 67 | func (c *virtualMachines) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.VirtualMachine, err error) { 68 | result = &v1.VirtualMachine{} 69 | err = c.client.Get(). 70 | Namespace(c.ns). 71 | Resource("virtualmachines"). 72 | Name(name). 73 | VersionedParams(&options, scheme.ParameterCodec). 74 | Do(ctx). 75 | Into(result) 76 | return 77 | } 78 | 79 | // List takes label and field selectors, and returns the list of VirtualMachines that match those selectors. 80 | func (c *virtualMachines) List(ctx context.Context, opts metav1.ListOptions) (result *v1.VirtualMachineList, err error) { 81 | var timeout time.Duration 82 | if opts.TimeoutSeconds != nil { 83 | timeout = time.Duration(*opts.TimeoutSeconds) * time.Second 84 | } 85 | result = &v1.VirtualMachineList{} 86 | err = c.client.Get(). 87 | Namespace(c.ns). 88 | Resource("virtualmachines"). 89 | VersionedParams(&opts, scheme.ParameterCodec). 90 | Timeout(timeout). 91 | Do(ctx). 92 | Into(result) 93 | return 94 | } 95 | 96 | // Watch returns a watch.Interface that watches the requested virtualMachines. 97 | func (c *virtualMachines) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { 98 | var timeout time.Duration 99 | if opts.TimeoutSeconds != nil { 100 | timeout = time.Duration(*opts.TimeoutSeconds) * time.Second 101 | } 102 | opts.Watch = true 103 | return c.client.Get(). 104 | Namespace(c.ns). 105 | Resource("virtualmachines"). 106 | VersionedParams(&opts, scheme.ParameterCodec). 107 | Timeout(timeout). 108 | Watch(ctx) 109 | } 110 | 111 | // 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. 112 | func (c *virtualMachines) Create(ctx context.Context, virtualMachine *v1.VirtualMachine, opts metav1.CreateOptions) (result *v1.VirtualMachine, err error) { 113 | result = &v1.VirtualMachine{} 114 | err = c.client.Post(). 115 | Namespace(c.ns). 116 | Resource("virtualmachines"). 117 | VersionedParams(&opts, scheme.ParameterCodec). 118 | Body(virtualMachine). 119 | Do(ctx). 120 | Into(result) 121 | return 122 | } 123 | 124 | // 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. 125 | func (c *virtualMachines) Update(ctx context.Context, virtualMachine *v1.VirtualMachine, opts metav1.UpdateOptions) (result *v1.VirtualMachine, err error) { 126 | result = &v1.VirtualMachine{} 127 | err = c.client.Put(). 128 | Namespace(c.ns). 129 | Resource("virtualmachines"). 130 | Name(virtualMachine.Name). 131 | VersionedParams(&opts, scheme.ParameterCodec). 132 | Body(virtualMachine). 133 | Do(ctx). 134 | Into(result) 135 | return 136 | } 137 | 138 | // UpdateStatus was generated because the type contains a Status member. 139 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 140 | func (c *virtualMachines) UpdateStatus(ctx context.Context, virtualMachine *v1.VirtualMachine, opts metav1.UpdateOptions) (result *v1.VirtualMachine, err error) { 141 | result = &v1.VirtualMachine{} 142 | err = c.client.Put(). 143 | Namespace(c.ns). 144 | Resource("virtualmachines"). 145 | Name(virtualMachine.Name). 146 | SubResource("status"). 147 | VersionedParams(&opts, scheme.ParameterCodec). 148 | Body(virtualMachine). 149 | Do(ctx). 150 | Into(result) 151 | return 152 | } 153 | 154 | // Delete takes name of the virtualMachine and deletes it. Returns an error if one occurs. 155 | func (c *virtualMachines) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { 156 | return c.client.Delete(). 157 | Namespace(c.ns). 158 | Resource("virtualmachines"). 159 | Name(name). 160 | Body(&opts). 161 | Do(ctx). 162 | Error() 163 | } 164 | 165 | // DeleteCollection deletes a collection of objects. 166 | func (c *virtualMachines) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { 167 | var timeout time.Duration 168 | if listOpts.TimeoutSeconds != nil { 169 | timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second 170 | } 171 | return c.client.Delete(). 172 | Namespace(c.ns). 173 | Resource("virtualmachines"). 174 | VersionedParams(&listOpts, scheme.ParameterCodec). 175 | Timeout(timeout). 176 | Body(&opts). 177 | Do(ctx). 178 | Error() 179 | } 180 | 181 | // Patch applies the patch and returns the patched virtualMachine. 182 | func (c *virtualMachines) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.VirtualMachine, err error) { 183 | result = &v1.VirtualMachine{} 184 | err = c.client.Patch(pt). 185 | Namespace(c.ns). 186 | Resource("virtualmachines"). 187 | Name(name). 188 | SubResource(subresources...). 189 | VersionedParams(&opts, scheme.ParameterCodec). 190 | Body(data). 191 | Do(ctx). 192 | Into(result) 193 | return 194 | } 195 | -------------------------------------------------------------------------------- /client/clientset/versioned/typed/neonvm/v1/virtualmachinemigration.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 v1 19 | 20 | import ( 21 | "context" 22 | "time" 23 | 24 | v1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 25 | scheme "github.com/neondatabase/neonvm/client/clientset/versioned/scheme" 26 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | types "k8s.io/apimachinery/pkg/types" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | rest "k8s.io/client-go/rest" 30 | ) 31 | 32 | // VirtualMachineMigrationsGetter has a method to return a VirtualMachineMigrationInterface. 33 | // A group's client should implement this interface. 34 | type VirtualMachineMigrationsGetter interface { 35 | VirtualMachineMigrations(namespace string) VirtualMachineMigrationInterface 36 | } 37 | 38 | // VirtualMachineMigrationInterface has methods to work with VirtualMachineMigration resources. 39 | type VirtualMachineMigrationInterface interface { 40 | Create(ctx context.Context, virtualMachineMigration *v1.VirtualMachineMigration, opts metav1.CreateOptions) (*v1.VirtualMachineMigration, error) 41 | Update(ctx context.Context, virtualMachineMigration *v1.VirtualMachineMigration, opts metav1.UpdateOptions) (*v1.VirtualMachineMigration, error) 42 | UpdateStatus(ctx context.Context, virtualMachineMigration *v1.VirtualMachineMigration, opts metav1.UpdateOptions) (*v1.VirtualMachineMigration, error) 43 | Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error 44 | DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error 45 | Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.VirtualMachineMigration, error) 46 | List(ctx context.Context, opts metav1.ListOptions) (*v1.VirtualMachineMigrationList, error) 47 | Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) 48 | Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.VirtualMachineMigration, err error) 49 | VirtualMachineMigrationExpansion 50 | } 51 | 52 | // virtualMachineMigrations implements VirtualMachineMigrationInterface 53 | type virtualMachineMigrations struct { 54 | client rest.Interface 55 | ns string 56 | } 57 | 58 | // newVirtualMachineMigrations returns a VirtualMachineMigrations 59 | func newVirtualMachineMigrations(c *NeonvmV1Client, namespace string) *virtualMachineMigrations { 60 | return &virtualMachineMigrations{ 61 | client: c.RESTClient(), 62 | ns: namespace, 63 | } 64 | } 65 | 66 | // Get takes name of the virtualMachineMigration, and returns the corresponding virtualMachineMigration object, and an error if there is any. 67 | func (c *virtualMachineMigrations) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.VirtualMachineMigration, err error) { 68 | result = &v1.VirtualMachineMigration{} 69 | err = c.client.Get(). 70 | Namespace(c.ns). 71 | Resource("virtualmachinemigrations"). 72 | Name(name). 73 | VersionedParams(&options, scheme.ParameterCodec). 74 | Do(ctx). 75 | Into(result) 76 | return 77 | } 78 | 79 | // List takes label and field selectors, and returns the list of VirtualMachineMigrations that match those selectors. 80 | func (c *virtualMachineMigrations) List(ctx context.Context, opts metav1.ListOptions) (result *v1.VirtualMachineMigrationList, err error) { 81 | var timeout time.Duration 82 | if opts.TimeoutSeconds != nil { 83 | timeout = time.Duration(*opts.TimeoutSeconds) * time.Second 84 | } 85 | result = &v1.VirtualMachineMigrationList{} 86 | err = c.client.Get(). 87 | Namespace(c.ns). 88 | Resource("virtualmachinemigrations"). 89 | VersionedParams(&opts, scheme.ParameterCodec). 90 | Timeout(timeout). 91 | Do(ctx). 92 | Into(result) 93 | return 94 | } 95 | 96 | // Watch returns a watch.Interface that watches the requested virtualMachineMigrations. 97 | func (c *virtualMachineMigrations) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { 98 | var timeout time.Duration 99 | if opts.TimeoutSeconds != nil { 100 | timeout = time.Duration(*opts.TimeoutSeconds) * time.Second 101 | } 102 | opts.Watch = true 103 | return c.client.Get(). 104 | Namespace(c.ns). 105 | Resource("virtualmachinemigrations"). 106 | VersionedParams(&opts, scheme.ParameterCodec). 107 | Timeout(timeout). 108 | Watch(ctx) 109 | } 110 | 111 | // Create takes the representation of a virtualMachineMigration and creates it. Returns the server's representation of the virtualMachineMigration, and an error, if there is any. 112 | func (c *virtualMachineMigrations) Create(ctx context.Context, virtualMachineMigration *v1.VirtualMachineMigration, opts metav1.CreateOptions) (result *v1.VirtualMachineMigration, err error) { 113 | result = &v1.VirtualMachineMigration{} 114 | err = c.client.Post(). 115 | Namespace(c.ns). 116 | Resource("virtualmachinemigrations"). 117 | VersionedParams(&opts, scheme.ParameterCodec). 118 | Body(virtualMachineMigration). 119 | Do(ctx). 120 | Into(result) 121 | return 122 | } 123 | 124 | // Update takes the representation of a virtualMachineMigration and updates it. Returns the server's representation of the virtualMachineMigration, and an error, if there is any. 125 | func (c *virtualMachineMigrations) Update(ctx context.Context, virtualMachineMigration *v1.VirtualMachineMigration, opts metav1.UpdateOptions) (result *v1.VirtualMachineMigration, err error) { 126 | result = &v1.VirtualMachineMigration{} 127 | err = c.client.Put(). 128 | Namespace(c.ns). 129 | Resource("virtualmachinemigrations"). 130 | Name(virtualMachineMigration.Name). 131 | VersionedParams(&opts, scheme.ParameterCodec). 132 | Body(virtualMachineMigration). 133 | Do(ctx). 134 | Into(result) 135 | return 136 | } 137 | 138 | // UpdateStatus was generated because the type contains a Status member. 139 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 140 | func (c *virtualMachineMigrations) UpdateStatus(ctx context.Context, virtualMachineMigration *v1.VirtualMachineMigration, opts metav1.UpdateOptions) (result *v1.VirtualMachineMigration, err error) { 141 | result = &v1.VirtualMachineMigration{} 142 | err = c.client.Put(). 143 | Namespace(c.ns). 144 | Resource("virtualmachinemigrations"). 145 | Name(virtualMachineMigration.Name). 146 | SubResource("status"). 147 | VersionedParams(&opts, scheme.ParameterCodec). 148 | Body(virtualMachineMigration). 149 | Do(ctx). 150 | Into(result) 151 | return 152 | } 153 | 154 | // Delete takes name of the virtualMachineMigration and deletes it. Returns an error if one occurs. 155 | func (c *virtualMachineMigrations) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { 156 | return c.client.Delete(). 157 | Namespace(c.ns). 158 | Resource("virtualmachinemigrations"). 159 | Name(name). 160 | Body(&opts). 161 | Do(ctx). 162 | Error() 163 | } 164 | 165 | // DeleteCollection deletes a collection of objects. 166 | func (c *virtualMachineMigrations) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { 167 | var timeout time.Duration 168 | if listOpts.TimeoutSeconds != nil { 169 | timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second 170 | } 171 | return c.client.Delete(). 172 | Namespace(c.ns). 173 | Resource("virtualmachinemigrations"). 174 | VersionedParams(&listOpts, scheme.ParameterCodec). 175 | Timeout(timeout). 176 | Body(&opts). 177 | Do(ctx). 178 | Error() 179 | } 180 | 181 | // Patch applies the patch and returns the patched virtualMachineMigration. 182 | func (c *virtualMachineMigrations) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.VirtualMachineMigration, err error) { 183 | result = &v1.VirtualMachineMigration{} 184 | err = c.client.Patch(pt). 185 | Namespace(c.ns). 186 | Resource("virtualmachinemigrations"). 187 | Name(name). 188 | SubResource(subresources...). 189 | VersionedParams(&opts, scheme.ParameterCodec). 190 | Body(data). 191 | Do(ctx). 192 | Into(result) 193 | return 194 | } 195 | -------------------------------------------------------------------------------- /client/informers/externalversions/generic.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | v1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 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=neonvm, Version=v1 55 | case v1.SchemeGroupVersion.WithResource("virtualmachines"): 56 | return &genericInformer{resource: resource.GroupResource(), informer: f.Neonvm().V1().VirtualMachines().Informer()}, nil 57 | case v1.SchemeGroupVersion.WithResource("virtualmachinemigrations"): 58 | return &genericInformer{resource: resource.GroupResource(), informer: f.Neonvm().V1().VirtualMachineMigrations().Informer()}, nil 59 | 60 | } 61 | 62 | return nil, fmt.Errorf("no informer found for %v", resource) 63 | } 64 | -------------------------------------------------------------------------------- /client/informers/externalversions/internalinterfaces/factory_interfaces.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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/neondatabase/neonvm/client/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 | -------------------------------------------------------------------------------- /client/informers/externalversions/neonvm/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 neonvm 19 | 20 | import ( 21 | internalinterfaces "github.com/neondatabase/neonvm/client/informers/externalversions/internalinterfaces" 22 | v1 "github.com/neondatabase/neonvm/client/informers/externalversions/neonvm/v1" 23 | ) 24 | 25 | // Interface provides access to each of this group's versions. 26 | type Interface interface { 27 | // V1 provides access to shared informers for resources in V1. 28 | V1() v1.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 | // V1 returns a new v1.Interface. 43 | func (g *group) V1() v1.Interface { 44 | return v1.New(g.factory, g.namespace, g.tweakListOptions) 45 | } 46 | -------------------------------------------------------------------------------- /client/informers/externalversions/neonvm/v1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 v1 19 | 20 | import ( 21 | internalinterfaces "github.com/neondatabase/neonvm/client/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 | // VirtualMachineMigrations returns a VirtualMachineMigrationInformer. 29 | VirtualMachineMigrations() VirtualMachineMigrationInformer 30 | } 31 | 32 | type version struct { 33 | factory internalinterfaces.SharedInformerFactory 34 | namespace string 35 | tweakListOptions internalinterfaces.TweakListOptionsFunc 36 | } 37 | 38 | // New returns a new Interface. 39 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 40 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 41 | } 42 | 43 | // VirtualMachines returns a VirtualMachineInformer. 44 | func (v *version) VirtualMachines() VirtualMachineInformer { 45 | return &virtualMachineInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 46 | } 47 | 48 | // VirtualMachineMigrations returns a VirtualMachineMigrationInformer. 49 | func (v *version) VirtualMachineMigrations() VirtualMachineMigrationInformer { 50 | return &virtualMachineMigrationInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 51 | } 52 | -------------------------------------------------------------------------------- /client/informers/externalversions/neonvm/v1/virtualmachine.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 v1 19 | 20 | import ( 21 | "context" 22 | time "time" 23 | 24 | neonvmv1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 25 | versioned "github.com/neondatabase/neonvm/client/clientset/versioned" 26 | internalinterfaces "github.com/neondatabase/neonvm/client/informers/externalversions/internalinterfaces" 27 | v1 "github.com/neondatabase/neonvm/client/listers/neonvm/v1" 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | runtime "k8s.io/apimachinery/pkg/runtime" 30 | watch "k8s.io/apimachinery/pkg/watch" 31 | cache "k8s.io/client-go/tools/cache" 32 | ) 33 | 34 | // VirtualMachineInformer provides access to a shared informer and lister for 35 | // VirtualMachines. 36 | type VirtualMachineInformer interface { 37 | Informer() cache.SharedIndexInformer 38 | Lister() v1.VirtualMachineLister 39 | } 40 | 41 | type virtualMachineInformer struct { 42 | factory internalinterfaces.SharedInformerFactory 43 | tweakListOptions internalinterfaces.TweakListOptionsFunc 44 | namespace string 45 | } 46 | 47 | // NewVirtualMachineInformer constructs a new informer for VirtualMachine type. 48 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 49 | // one. This reduces memory footprint and number of connections to the server. 50 | func NewVirtualMachineInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 51 | return NewFilteredVirtualMachineInformer(client, namespace, resyncPeriod, indexers, nil) 52 | } 53 | 54 | // NewFilteredVirtualMachineInformer constructs a new informer for VirtualMachine type. 55 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 56 | // one. This reduces memory footprint and number of connections to the server. 57 | func NewFilteredVirtualMachineInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 58 | return cache.NewSharedIndexInformer( 59 | &cache.ListWatch{ 60 | ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { 61 | if tweakListOptions != nil { 62 | tweakListOptions(&options) 63 | } 64 | return client.NeonvmV1().VirtualMachines(namespace).List(context.TODO(), options) 65 | }, 66 | WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { 67 | if tweakListOptions != nil { 68 | tweakListOptions(&options) 69 | } 70 | return client.NeonvmV1().VirtualMachines(namespace).Watch(context.TODO(), options) 71 | }, 72 | }, 73 | &neonvmv1.VirtualMachine{}, 74 | resyncPeriod, 75 | indexers, 76 | ) 77 | } 78 | 79 | func (f *virtualMachineInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 80 | return NewFilteredVirtualMachineInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 81 | } 82 | 83 | func (f *virtualMachineInformer) Informer() cache.SharedIndexInformer { 84 | return f.factory.InformerFor(&neonvmv1.VirtualMachine{}, f.defaultInformer) 85 | } 86 | 87 | func (f *virtualMachineInformer) Lister() v1.VirtualMachineLister { 88 | return v1.NewVirtualMachineLister(f.Informer().GetIndexer()) 89 | } 90 | -------------------------------------------------------------------------------- /client/informers/externalversions/neonvm/v1/virtualmachinemigration.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 v1 19 | 20 | import ( 21 | "context" 22 | time "time" 23 | 24 | neonvmv1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 25 | versioned "github.com/neondatabase/neonvm/client/clientset/versioned" 26 | internalinterfaces "github.com/neondatabase/neonvm/client/informers/externalversions/internalinterfaces" 27 | v1 "github.com/neondatabase/neonvm/client/listers/neonvm/v1" 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | runtime "k8s.io/apimachinery/pkg/runtime" 30 | watch "k8s.io/apimachinery/pkg/watch" 31 | cache "k8s.io/client-go/tools/cache" 32 | ) 33 | 34 | // VirtualMachineMigrationInformer provides access to a shared informer and lister for 35 | // VirtualMachineMigrations. 36 | type VirtualMachineMigrationInformer interface { 37 | Informer() cache.SharedIndexInformer 38 | Lister() v1.VirtualMachineMigrationLister 39 | } 40 | 41 | type virtualMachineMigrationInformer struct { 42 | factory internalinterfaces.SharedInformerFactory 43 | tweakListOptions internalinterfaces.TweakListOptionsFunc 44 | namespace string 45 | } 46 | 47 | // NewVirtualMachineMigrationInformer constructs a new informer for VirtualMachineMigration type. 48 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 49 | // one. This reduces memory footprint and number of connections to the server. 50 | func NewVirtualMachineMigrationInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 51 | return NewFilteredVirtualMachineMigrationInformer(client, namespace, resyncPeriod, indexers, nil) 52 | } 53 | 54 | // NewFilteredVirtualMachineMigrationInformer constructs a new informer for VirtualMachineMigration type. 55 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 56 | // one. This reduces memory footprint and number of connections to the server. 57 | func NewFilteredVirtualMachineMigrationInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 58 | return cache.NewSharedIndexInformer( 59 | &cache.ListWatch{ 60 | ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { 61 | if tweakListOptions != nil { 62 | tweakListOptions(&options) 63 | } 64 | return client.NeonvmV1().VirtualMachineMigrations(namespace).List(context.TODO(), options) 65 | }, 66 | WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { 67 | if tweakListOptions != nil { 68 | tweakListOptions(&options) 69 | } 70 | return client.NeonvmV1().VirtualMachineMigrations(namespace).Watch(context.TODO(), options) 71 | }, 72 | }, 73 | &neonvmv1.VirtualMachineMigration{}, 74 | resyncPeriod, 75 | indexers, 76 | ) 77 | } 78 | 79 | func (f *virtualMachineMigrationInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 80 | return NewFilteredVirtualMachineMigrationInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 81 | } 82 | 83 | func (f *virtualMachineMigrationInformer) Informer() cache.SharedIndexInformer { 84 | return f.factory.InformerFor(&neonvmv1.VirtualMachineMigration{}, f.defaultInformer) 85 | } 86 | 87 | func (f *virtualMachineMigrationInformer) Lister() v1.VirtualMachineMigrationLister { 88 | return v1.NewVirtualMachineMigrationLister(f.Informer().GetIndexer()) 89 | } 90 | -------------------------------------------------------------------------------- /client/listers/neonvm/v1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 v1 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 | 28 | // VirtualMachineMigrationListerExpansion allows custom methods to be added to 29 | // VirtualMachineMigrationLister. 30 | type VirtualMachineMigrationListerExpansion interface{} 31 | 32 | // VirtualMachineMigrationNamespaceListerExpansion allows custom methods to be added to 33 | // VirtualMachineMigrationNamespaceLister. 34 | type VirtualMachineMigrationNamespaceListerExpansion interface{} 35 | -------------------------------------------------------------------------------- /client/listers/neonvm/v1/virtualmachine.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 v1 19 | 20 | import ( 21 | v1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 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 | // All objects returned here must be treated as read-only. 29 | type VirtualMachineLister interface { 30 | // List lists all VirtualMachines in the indexer. 31 | // Objects returned here must be treated as read-only. 32 | List(selector labels.Selector) (ret []*v1.VirtualMachine, err error) 33 | // VirtualMachines returns an object that can list and get VirtualMachines. 34 | VirtualMachines(namespace string) VirtualMachineNamespaceLister 35 | VirtualMachineListerExpansion 36 | } 37 | 38 | // virtualMachineLister implements the VirtualMachineLister interface. 39 | type virtualMachineLister struct { 40 | indexer cache.Indexer 41 | } 42 | 43 | // NewVirtualMachineLister returns a new VirtualMachineLister. 44 | func NewVirtualMachineLister(indexer cache.Indexer) VirtualMachineLister { 45 | return &virtualMachineLister{indexer: indexer} 46 | } 47 | 48 | // List lists all VirtualMachines in the indexer. 49 | func (s *virtualMachineLister) List(selector labels.Selector) (ret []*v1.VirtualMachine, err error) { 50 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 51 | ret = append(ret, m.(*v1.VirtualMachine)) 52 | }) 53 | return ret, err 54 | } 55 | 56 | // VirtualMachines returns an object that can list and get VirtualMachines. 57 | func (s *virtualMachineLister) VirtualMachines(namespace string) VirtualMachineNamespaceLister { 58 | return virtualMachineNamespaceLister{indexer: s.indexer, namespace: namespace} 59 | } 60 | 61 | // VirtualMachineNamespaceLister helps list and get VirtualMachines. 62 | // All objects returned here must be treated as read-only. 63 | type VirtualMachineNamespaceLister interface { 64 | // List lists all VirtualMachines in the indexer for a given namespace. 65 | // Objects returned here must be treated as read-only. 66 | List(selector labels.Selector) (ret []*v1.VirtualMachine, err error) 67 | // Get retrieves the VirtualMachine from the indexer for a given namespace and name. 68 | // Objects returned here must be treated as read-only. 69 | Get(name string) (*v1.VirtualMachine, error) 70 | VirtualMachineNamespaceListerExpansion 71 | } 72 | 73 | // virtualMachineNamespaceLister implements the VirtualMachineNamespaceLister 74 | // interface. 75 | type virtualMachineNamespaceLister struct { 76 | indexer cache.Indexer 77 | namespace string 78 | } 79 | 80 | // List lists all VirtualMachines in the indexer for a given namespace. 81 | func (s virtualMachineNamespaceLister) List(selector labels.Selector) (ret []*v1.VirtualMachine, err error) { 82 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 83 | ret = append(ret, m.(*v1.VirtualMachine)) 84 | }) 85 | return ret, err 86 | } 87 | 88 | // Get retrieves the VirtualMachine from the indexer for a given namespace and name. 89 | func (s virtualMachineNamespaceLister) Get(name string) (*v1.VirtualMachine, error) { 90 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 91 | if err != nil { 92 | return nil, err 93 | } 94 | if !exists { 95 | return nil, errors.NewNotFound(v1.Resource("virtualmachine"), name) 96 | } 97 | return obj.(*v1.VirtualMachine), nil 98 | } 99 | -------------------------------------------------------------------------------- /client/listers/neonvm/v1/virtualmachinemigration.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 v1 19 | 20 | import ( 21 | v1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 22 | "k8s.io/apimachinery/pkg/api/errors" 23 | "k8s.io/apimachinery/pkg/labels" 24 | "k8s.io/client-go/tools/cache" 25 | ) 26 | 27 | // VirtualMachineMigrationLister helps list VirtualMachineMigrations. 28 | // All objects returned here must be treated as read-only. 29 | type VirtualMachineMigrationLister interface { 30 | // List lists all VirtualMachineMigrations in the indexer. 31 | // Objects returned here must be treated as read-only. 32 | List(selector labels.Selector) (ret []*v1.VirtualMachineMigration, err error) 33 | // VirtualMachineMigrations returns an object that can list and get VirtualMachineMigrations. 34 | VirtualMachineMigrations(namespace string) VirtualMachineMigrationNamespaceLister 35 | VirtualMachineMigrationListerExpansion 36 | } 37 | 38 | // virtualMachineMigrationLister implements the VirtualMachineMigrationLister interface. 39 | type virtualMachineMigrationLister struct { 40 | indexer cache.Indexer 41 | } 42 | 43 | // NewVirtualMachineMigrationLister returns a new VirtualMachineMigrationLister. 44 | func NewVirtualMachineMigrationLister(indexer cache.Indexer) VirtualMachineMigrationLister { 45 | return &virtualMachineMigrationLister{indexer: indexer} 46 | } 47 | 48 | // List lists all VirtualMachineMigrations in the indexer. 49 | func (s *virtualMachineMigrationLister) List(selector labels.Selector) (ret []*v1.VirtualMachineMigration, err error) { 50 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 51 | ret = append(ret, m.(*v1.VirtualMachineMigration)) 52 | }) 53 | return ret, err 54 | } 55 | 56 | // VirtualMachineMigrations returns an object that can list and get VirtualMachineMigrations. 57 | func (s *virtualMachineMigrationLister) VirtualMachineMigrations(namespace string) VirtualMachineMigrationNamespaceLister { 58 | return virtualMachineMigrationNamespaceLister{indexer: s.indexer, namespace: namespace} 59 | } 60 | 61 | // VirtualMachineMigrationNamespaceLister helps list and get VirtualMachineMigrations. 62 | // All objects returned here must be treated as read-only. 63 | type VirtualMachineMigrationNamespaceLister interface { 64 | // List lists all VirtualMachineMigrations in the indexer for a given namespace. 65 | // Objects returned here must be treated as read-only. 66 | List(selector labels.Selector) (ret []*v1.VirtualMachineMigration, err error) 67 | // Get retrieves the VirtualMachineMigration from the indexer for a given namespace and name. 68 | // Objects returned here must be treated as read-only. 69 | Get(name string) (*v1.VirtualMachineMigration, error) 70 | VirtualMachineMigrationNamespaceListerExpansion 71 | } 72 | 73 | // virtualMachineMigrationNamespaceLister implements the VirtualMachineMigrationNamespaceLister 74 | // interface. 75 | type virtualMachineMigrationNamespaceLister struct { 76 | indexer cache.Indexer 77 | namespace string 78 | } 79 | 80 | // List lists all VirtualMachineMigrations in the indexer for a given namespace. 81 | func (s virtualMachineMigrationNamespaceLister) List(selector labels.Selector) (ret []*v1.VirtualMachineMigration, err error) { 82 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 83 | ret = append(ret, m.(*v1.VirtualMachineMigration)) 84 | }) 85 | return ret, err 86 | } 87 | 88 | // Get retrieves the VirtualMachineMigration from the indexer for a given namespace and name. 89 | func (s virtualMachineMigrationNamespaceLister) Get(name string) (*v1.VirtualMachineMigration, error) { 90 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 91 | if err != nil { 92 | return nil, err 93 | } 94 | if !exists { 95 | return nil, errors.NewNotFound(v1.Resource("virtualmachinemigration"), name) 96 | } 97 | return obj.(*v1.VirtualMachineMigration), nil 98 | } 99 | -------------------------------------------------------------------------------- /config/common/certmanager/certificate.yaml: -------------------------------------------------------------------------------- 1 | # The following manifests contain a self-signed issuer CR and a certificate CR. 2 | # More document can be found at https://docs.cert-manager.io 3 | # WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes. 4 | apiVersion: cert-manager.io/v1 5 | kind: Issuer 6 | metadata: 7 | labels: 8 | app.kuberentes.io/name: issuer 9 | app.kubernetes.io/instance: selfsigned-issuer 10 | app.kubernetes.io/component: certificate 11 | app.kubernetes.io/created-by: neonvm 12 | app.kubernetes.io/part-of: neonvm 13 | app.kubernetes.io/managed-by: kustomize 14 | name: selfsigned-issuer 15 | namespace: system 16 | spec: 17 | selfSigned: {} 18 | --- 19 | apiVersion: cert-manager.io/v1 20 | kind: Certificate 21 | metadata: 22 | labels: 23 | app.kubernetes.io/name: certificate 24 | app.kubernetes.io/instance: serving-cert 25 | app.kubernetes.io/component: certificate 26 | app.kubernetes.io/created-by: neonvm 27 | app.kubernetes.io/part-of: neonvm 28 | app.kubernetes.io/managed-by: kustomize 29 | name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml 30 | namespace: system 31 | spec: 32 | # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize 33 | dnsNames: 34 | - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc 35 | - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local 36 | issuerRef: 37 | kind: Issuer 38 | name: selfsigned-issuer 39 | secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize 40 | -------------------------------------------------------------------------------- /config/common/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - certificate.yaml 3 | 4 | configurations: 5 | - kustomizeconfig.yaml 6 | -------------------------------------------------------------------------------- /config/common/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref and var substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | 10 | varReference: 11 | - kind: Certificate 12 | group: cert-manager.io 13 | path: spec/commonName 14 | - kind: Certificate 15 | group: cert-manager.io 16 | path: spec/dnsNames 17 | -------------------------------------------------------------------------------- /config/common/controller/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - manager.yaml 6 | images: 7 | - name: controller 8 | newName: controller 9 | newTag: dev 10 | -------------------------------------------------------------------------------- /config/common/controller/manager.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller 6 | namespace: system 7 | labels: 8 | control-plane: controller 9 | app.kubernetes.io/name: deployment 10 | app.kubernetes.io/instance: controller 11 | app.kubernetes.io/component: manager 12 | app.kubernetes.io/created-by: neonvm 13 | app.kubernetes.io/part-of: neonvm 14 | app.kubernetes.io/managed-by: kustomize 15 | spec: 16 | selector: 17 | matchLabels: 18 | control-plane: controller 19 | replicas: 1 20 | template: 21 | metadata: 22 | annotations: 23 | kubectl.kubernetes.io/default-container: manager 24 | labels: 25 | control-plane: controller 26 | spec: 27 | # TODO(user): Uncomment the following code to configure the nodeAffinity expression 28 | # according to the platforms which are supported by your solution. 29 | # It is considered best practice to support multiple architectures. You can 30 | # build your manager image using the makefile target docker-buildx. 31 | # affinity: 32 | # nodeAffinity: 33 | # requiredDuringSchedulingIgnoredDuringExecution: 34 | # nodeSelectorTerms: 35 | # - matchExpressions: 36 | # - key: kubernetes.io/arch 37 | # operator: In 38 | # values: 39 | # - amd64 40 | # - arm64 41 | # - ppc64le 42 | # - s390x 43 | # - key: kubernetes.io/os 44 | # operator: In 45 | # values: 46 | # - linux 47 | securityContext: 48 | runAsNonRoot: true 49 | # TODO(user): For common cases that do not require escalating privileges 50 | # it is recommended to ensure that all your Pods/Containers are restrictive. 51 | # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted 52 | # Please uncomment the following code if your project does NOT have to work on old Kubernetes 53 | # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ). 54 | # seccompProfile: 55 | # type: RuntimeDefault 56 | containers: 57 | - command: 58 | - /manager 59 | args: 60 | - --leader-elect 61 | image: controller:dev 62 | name: manager 63 | securityContext: 64 | allowPrivilegeEscalation: false 65 | capabilities: 66 | drop: 67 | - "ALL" 68 | livenessProbe: 69 | httpGet: 70 | path: /healthz 71 | port: 8081 72 | initialDelaySeconds: 15 73 | periodSeconds: 20 74 | readinessProbe: 75 | httpGet: 76 | path: /readyz 77 | port: 8081 78 | initialDelaySeconds: 5 79 | periodSeconds: 10 80 | # TODO(user): Configure the resources accordingly based on the project requirements. 81 | # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ 82 | resources: 83 | limits: 84 | cpu: 500m 85 | memory: 128Mi 86 | requests: 87 | cpu: 10m 88 | memory: 64Mi 89 | serviceAccountName: controller 90 | terminationGracePeriodSeconds: 10 91 | -------------------------------------------------------------------------------- /config/common/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/vm.neon.tech_virtualmachines.yaml 6 | - bases/vm.neon.tech_virtualmachinemigrations.yaml 7 | #+kubebuilder:scaffold:crdkustomizeresource 8 | 9 | patchesStrategicMerge: 10 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. 11 | # patches here are for enabling the conversion webhook for each CRD 12 | - patches/webhook_in_virtualmachines.yaml 13 | - patches/webhook_in_virtualmachinemigrations.yaml 14 | #+kubebuilder:scaffold:crdkustomizewebhookpatch 15 | 16 | # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. 17 | # patches here are for enabling the CA injection for each CRD 18 | - patches/cainjection_in_virtualmachines.yaml 19 | - patches/cainjection_in_virtualmachinemigrations.yaml 20 | #+kubebuilder:scaffold:crdkustomizecainjectionpatch 21 | 22 | # the following config is for teaching kustomize how to do kustomization for CRDs. 23 | configurations: 24 | - kustomizeconfig.yaml 25 | -------------------------------------------------------------------------------- /config/common/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /config/common/crd/patches/cainjection_in_virtualmachinemigrations.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: virtualmachinemigrations.vm.neon.tech 8 | -------------------------------------------------------------------------------- /config/common/crd/patches/cainjection_in_virtualmachines.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: virtualmachines.vm.neon.tech 8 | -------------------------------------------------------------------------------- /config/common/crd/patches/webhook_in_virtualmachinemigrations.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: virtualmachinemigrations.vm.neon.tech 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /config/common/crd/patches/webhook_in_virtualmachines.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: virtualmachines.vm.neon.tech 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /config/common/namespace/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | namespace: neonvm-system 5 | 6 | resources: 7 | - namespace.yaml 8 | -------------------------------------------------------------------------------- /config/common/namespace/namespace.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: system 6 | -------------------------------------------------------------------------------- /config/common/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /config/common/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller 8 | app.kubernetes.io/name: servicemonitor 9 | app.kubernetes.io/instance: controller-metrics-monitor 10 | app.kubernetes.io/component: metrics 11 | app.kubernetes.io/created-by: neonvm 12 | app.kubernetes.io/part-of: neonvm 13 | app.kubernetes.io/managed-by: kustomize 14 | name: controller-metrics-monitor 15 | namespace: system 16 | spec: 17 | endpoints: 18 | - path: /metrics 19 | port: https 20 | scheme: https 21 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 22 | tlsConfig: 23 | insecureSkipVerify: true 24 | selector: 25 | matchLabels: 26 | control-plane: controller 27 | -------------------------------------------------------------------------------- /config/common/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: clusterrole 6 | app.kubernetes.io/instance: metrics-reader 7 | app.kubernetes.io/component: kube-rbac-proxy 8 | app.kubernetes.io/created-by: neonvm 9 | app.kubernetes.io/part-of: neonvm 10 | app.kubernetes.io/managed-by: kustomize 11 | name: metrics-reader 12 | rules: 13 | - nonResourceURLs: 14 | - "/metrics" 15 | verbs: 16 | - get 17 | -------------------------------------------------------------------------------- /config/common/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: clusterrole 6 | app.kubernetes.io/instance: proxy-role 7 | app.kubernetes.io/component: kube-rbac-proxy 8 | app.kubernetes.io/created-by: neonvm 9 | app.kubernetes.io/part-of: neonvm 10 | app.kubernetes.io/managed-by: kustomize 11 | name: proxy-role 12 | rules: 13 | - apiGroups: 14 | - authentication.k8s.io 15 | resources: 16 | - tokenreviews 17 | verbs: 18 | - create 19 | - apiGroups: 20 | - authorization.k8s.io 21 | resources: 22 | - subjectaccessreviews 23 | verbs: 24 | - create 25 | -------------------------------------------------------------------------------- /config/common/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: clusterrolebinding 6 | app.kubernetes.io/instance: proxy-rolebinding 7 | app.kubernetes.io/component: kube-rbac-proxy 8 | app.kubernetes.io/created-by: neonvm 9 | app.kubernetes.io/part-of: neonvm 10 | app.kubernetes.io/managed-by: kustomize 11 | name: proxy-rolebinding 12 | roleRef: 13 | apiGroup: rbac.authorization.k8s.io 14 | kind: ClusterRole 15 | name: proxy-role 16 | subjects: 17 | - kind: ServiceAccount 18 | name: controller 19 | namespace: system 20 | -------------------------------------------------------------------------------- /config/common/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller 6 | app.kubernetes.io/name: service 7 | app.kubernetes.io/instance: controller-metrics-service 8 | app.kubernetes.io/component: kube-rbac-proxy 9 | app.kubernetes.io/created-by: neonvm 10 | app.kubernetes.io/part-of: neonvm 11 | app.kubernetes.io/managed-by: kustomize 12 | name: controller-metrics-service 13 | namespace: system 14 | spec: 15 | ports: 16 | - name: https 17 | port: 8443 18 | protocol: TCP 19 | targetPort: https 20 | selector: 21 | control-plane: controller 22 | -------------------------------------------------------------------------------- /config/common/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | - auth_proxy_service.yaml 16 | - auth_proxy_role.yaml 17 | - auth_proxy_role_binding.yaml 18 | - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /config/common/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: role 7 | app.kubernetes.io/instance: leader-election-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: neonvm 10 | app.kubernetes.io/part-of: neonvm 11 | app.kubernetes.io/managed-by: kustomize 12 | name: leader-election-role 13 | rules: 14 | - apiGroups: 15 | - "" 16 | resources: 17 | - configmaps 18 | verbs: 19 | - get 20 | - list 21 | - watch 22 | - create 23 | - update 24 | - patch 25 | - delete 26 | - apiGroups: 27 | - coordination.k8s.io 28 | resources: 29 | - leases 30 | verbs: 31 | - get 32 | - list 33 | - watch 34 | - create 35 | - update 36 | - patch 37 | - delete 38 | - apiGroups: 39 | - "" 40 | resources: 41 | - events 42 | verbs: 43 | - create 44 | - patch 45 | -------------------------------------------------------------------------------- /config/common/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: rolebinding 6 | app.kubernetes.io/instance: leader-election-rolebinding 7 | app.kubernetes.io/component: rbac 8 | app.kubernetes.io/created-by: neonvm 9 | app.kubernetes.io/part-of: neonvm 10 | app.kubernetes.io/managed-by: kustomize 11 | name: leader-election-rolebinding 12 | roleRef: 13 | apiGroup: rbac.authorization.k8s.io 14 | kind: Role 15 | name: leader-election-role 16 | subjects: 17 | - kind: ServiceAccount 18 | name: controller 19 | namespace: system 20 | -------------------------------------------------------------------------------- /config/common/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: manager-role 7 | rules: 8 | - apiGroups: 9 | - "" 10 | resources: 11 | - events 12 | verbs: 13 | - create 14 | - patch 15 | - apiGroups: 16 | - "" 17 | resources: 18 | - pods 19 | verbs: 20 | - create 21 | - delete 22 | - get 23 | - list 24 | - patch 25 | - update 26 | - watch 27 | - apiGroups: 28 | - "" 29 | resources: 30 | - pods/status 31 | verbs: 32 | - get 33 | - list 34 | - watch 35 | - apiGroups: 36 | - vm.neon.tech 37 | resources: 38 | - virtualmachinemigrations 39 | verbs: 40 | - create 41 | - delete 42 | - get 43 | - list 44 | - patch 45 | - update 46 | - watch 47 | - apiGroups: 48 | - vm.neon.tech 49 | resources: 50 | - virtualmachinemigrations/finalizers 51 | verbs: 52 | - update 53 | - apiGroups: 54 | - vm.neon.tech 55 | resources: 56 | - virtualmachinemigrations/status 57 | verbs: 58 | - get 59 | - patch 60 | - update 61 | - apiGroups: 62 | - vm.neon.tech 63 | resources: 64 | - virtualmachines 65 | verbs: 66 | - create 67 | - delete 68 | - get 69 | - list 70 | - patch 71 | - update 72 | - watch 73 | - apiGroups: 74 | - vm.neon.tech 75 | resources: 76 | - virtualmachines/finalizers 77 | verbs: 78 | - update 79 | - apiGroups: 80 | - vm.neon.tech 81 | resources: 82 | - virtualmachines/status 83 | verbs: 84 | - get 85 | - patch 86 | - update 87 | -------------------------------------------------------------------------------- /config/common/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: clusterrolebinding 6 | app.kubernetes.io/instance: manager-rolebinding 7 | app.kubernetes.io/component: rbac 8 | app.kubernetes.io/created-by: neonvm 9 | app.kubernetes.io/part-of: neonvm 10 | app.kubernetes.io/managed-by: kustomize 11 | name: manager-rolebinding 12 | roleRef: 13 | apiGroup: rbac.authorization.k8s.io 14 | kind: ClusterRole 15 | name: manager-role 16 | subjects: 17 | - kind: ServiceAccount 18 | name: controller 19 | namespace: system 20 | -------------------------------------------------------------------------------- /config/common/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: serviceaccount 6 | app.kuberentes.io/instance: controller 7 | app.kubernetes.io/component: rbac 8 | app.kubernetes.io/created-by: neonvm 9 | app.kubernetes.io/part-of: neonvm 10 | app.kubernetes.io/managed-by: kustomize 11 | name: controller 12 | namespace: system 13 | -------------------------------------------------------------------------------- /config/common/rbac/virtualmachine_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit virtualmachines. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrole 7 | app.kubernetes.io/instance: virtualmachine-editor-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: neonvm 10 | app.kubernetes.io/part-of: neonvm 11 | app.kubernetes.io/managed-by: kustomize 12 | name: virtualmachine-editor-role 13 | rules: 14 | - apiGroups: 15 | - vm.neon.tech 16 | resources: 17 | - virtualmachines 18 | verbs: 19 | - create 20 | - delete 21 | - get 22 | - list 23 | - patch 24 | - update 25 | - watch 26 | - apiGroups: 27 | - vm.neon.tech 28 | resources: 29 | - virtualmachines/status 30 | verbs: 31 | - get 32 | -------------------------------------------------------------------------------- /config/common/rbac/virtualmachine_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view virtualmachines. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrole 7 | app.kubernetes.io/instance: virtualmachine-viewer-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: neonvm 10 | app.kubernetes.io/part-of: neonvm 11 | app.kubernetes.io/managed-by: kustomize 12 | name: virtualmachine-viewer-role 13 | rules: 14 | - apiGroups: 15 | - vm.neon.tech 16 | resources: 17 | - virtualmachines 18 | verbs: 19 | - get 20 | - list 21 | - watch 22 | - apiGroups: 23 | - vm.neon.tech 24 | resources: 25 | - virtualmachines/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /config/common/rbac/virtualmachinemigration_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit virtualmachinemigrations. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrole 7 | app.kubernetes.io/instance: virtualmachinemigration-editor-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: neonvm 10 | app.kubernetes.io/part-of: neonvm 11 | app.kubernetes.io/managed-by: kustomize 12 | name: virtualmachinemigration-editor-role 13 | rules: 14 | - apiGroups: 15 | - vm.neon.tech 16 | resources: 17 | - virtualmachinemigrations 18 | verbs: 19 | - create 20 | - delete 21 | - get 22 | - list 23 | - patch 24 | - update 25 | - watch 26 | - apiGroups: 27 | - vm.neon.tech 28 | resources: 29 | - virtualmachinemigrations/status 30 | verbs: 31 | - get 32 | -------------------------------------------------------------------------------- /config/common/rbac/virtualmachinemigration_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view virtualmachinemigrations. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrole 7 | app.kubernetes.io/instance: virtualmachinemigration-viewer-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: neonvm 10 | app.kubernetes.io/part-of: neonvm 11 | app.kubernetes.io/managed-by: kustomize 12 | name: virtualmachinemigration-viewer-role 13 | rules: 14 | - apiGroups: 15 | - vm.neon.tech 16 | resources: 17 | - virtualmachinemigrations 18 | verbs: 19 | - get 20 | - list 21 | - watch 22 | - apiGroups: 23 | - vm.neon.tech 24 | resources: 25 | - virtualmachinemigrations/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /config/common/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /config/common/webhook/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # the following config is for teaching kustomize where to look at when substituting vars. 2 | # It requires kustomize v2.1.0 or newer to work properly. 3 | nameReference: 4 | - kind: Service 5 | version: v1 6 | fieldSpecs: 7 | - kind: MutatingWebhookConfiguration 8 | group: admissionregistration.k8s.io 9 | path: webhooks/clientConfig/service/name 10 | - kind: ValidatingWebhookConfiguration 11 | group: admissionregistration.k8s.io 12 | path: webhooks/clientConfig/service/name 13 | 14 | namespace: 15 | - kind: MutatingWebhookConfiguration 16 | group: admissionregistration.k8s.io 17 | path: webhooks/clientConfig/service/namespace 18 | create: true 19 | - kind: ValidatingWebhookConfiguration 20 | group: admissionregistration.k8s.io 21 | path: webhooks/clientConfig/service/namespace 22 | create: true 23 | 24 | varReference: 25 | - path: metadata/annotations 26 | -------------------------------------------------------------------------------- /config/common/webhook/manifests.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: MutatingWebhookConfiguration 4 | metadata: 5 | creationTimestamp: null 6 | name: mutating-webhook-configuration 7 | webhooks: 8 | - admissionReviewVersions: 9 | - v1 10 | clientConfig: 11 | service: 12 | name: webhook-service 13 | namespace: system 14 | path: /mutate-vm-neon-tech-v1-virtualmachine 15 | failurePolicy: Fail 16 | name: mvirtualmachine.kb.io 17 | rules: 18 | - apiGroups: 19 | - vm.neon.tech 20 | apiVersions: 21 | - v1 22 | operations: 23 | - CREATE 24 | - UPDATE 25 | resources: 26 | - virtualmachines 27 | sideEffects: None 28 | - admissionReviewVersions: 29 | - v1 30 | clientConfig: 31 | service: 32 | name: webhook-service 33 | namespace: system 34 | path: /mutate-vm-neon-tech-v1-virtualmachinemigration 35 | failurePolicy: Fail 36 | name: mvirtualmachinemigration.kb.io 37 | rules: 38 | - apiGroups: 39 | - vm.neon.tech 40 | apiVersions: 41 | - v1 42 | operations: 43 | - CREATE 44 | - UPDATE 45 | resources: 46 | - virtualmachinemigrations 47 | sideEffects: None 48 | --- 49 | apiVersion: admissionregistration.k8s.io/v1 50 | kind: ValidatingWebhookConfiguration 51 | metadata: 52 | creationTimestamp: null 53 | name: validating-webhook-configuration 54 | webhooks: 55 | - admissionReviewVersions: 56 | - v1 57 | clientConfig: 58 | service: 59 | name: webhook-service 60 | namespace: system 61 | path: /validate-vm-neon-tech-v1-virtualmachine 62 | failurePolicy: Fail 63 | name: vvirtualmachine.kb.io 64 | rules: 65 | - apiGroups: 66 | - vm.neon.tech 67 | apiVersions: 68 | - v1 69 | operations: 70 | - CREATE 71 | - UPDATE 72 | resources: 73 | - virtualmachines 74 | sideEffects: None 75 | - admissionReviewVersions: 76 | - v1 77 | clientConfig: 78 | service: 79 | name: webhook-service 80 | namespace: system 81 | path: /validate-vm-neon-tech-v1-virtualmachinemigration 82 | failurePolicy: Fail 83 | name: vvirtualmachinemigration.kb.io 84 | rules: 85 | - apiGroups: 86 | - vm.neon.tech 87 | apiVersions: 88 | - v1 89 | operations: 90 | - CREATE 91 | - UPDATE 92 | resources: 93 | - virtualmachinemigrations 94 | sideEffects: None 95 | -------------------------------------------------------------------------------- /config/common/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: service 7 | app.kubernetes.io/instance: webhook-service 8 | app.kubernetes.io/component: webhook 9 | app.kubernetes.io/created-by: neonvm 10 | app.kubernetes.io/part-of: neonvm 11 | app.kubernetes.io/managed-by: kustomize 12 | name: webhook-service 13 | namespace: system 14 | spec: 15 | ports: 16 | - port: 443 17 | protocol: TCP 18 | targetPort: 9443 19 | selector: 20 | control-plane: controller 21 | -------------------------------------------------------------------------------- /config/default-vxlan/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: neonvm-system 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: neonvm- 10 | 11 | # Labels to add to all resources and selectors. 12 | #commonLabels: 13 | # someName: someValue 14 | 15 | bases: 16 | - ../common/namespace 17 | - ../common/crd 18 | - ../common/rbac 19 | - ../common/controller 20 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 21 | # crd/kustomization.yaml 22 | - ../common/webhook 23 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. 24 | - ../common/certmanager 25 | # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. 26 | #- ../common/prometheus 27 | - vxlan-ipam 28 | - vxlan-controller 29 | - network 30 | 31 | patchesStrategicMerge: 32 | - manager_config_patch.yaml 33 | 34 | # Protect the /metrics endpoint by putting it behind auth. 35 | # If you want your controller to expose the /metrics 36 | # endpoint w/o any authn/z, please comment the following line. 37 | - manager_auth_proxy_patch.yaml 38 | 39 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 40 | # crd/kustomization.yaml 41 | - manager_webhook_patch.yaml 42 | 43 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 44 | # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. 45 | # 'CERTMANAGER' needs to be enabled to use ca injection 46 | - webhookcainjection_patch.yaml 47 | 48 | # the following config is for teaching kustomize how to do var substitution 49 | vars: 50 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. 51 | - name: CERTIFICATE_NAMESPACE # namespace of the certificate CR 52 | objref: 53 | kind: Certificate 54 | group: cert-manager.io 55 | version: v1 56 | name: serving-cert # this name should match the one in certificate.yaml 57 | fieldref: 58 | fieldpath: metadata.namespace 59 | - name: CERTIFICATE_NAME 60 | objref: 61 | kind: Certificate 62 | group: cert-manager.io 63 | version: v1 64 | name: serving-cert # this name should match the one in certificate.yaml 65 | - name: SERVICE_NAMESPACE # namespace of the service 66 | objref: 67 | kind: Service 68 | version: v1 69 | name: webhook-service 70 | fieldref: 71 | fieldpath: metadata.namespace 72 | - name: SERVICE_NAME 73 | objref: 74 | kind: Service 75 | version: v1 76 | name: webhook-service 77 | -------------------------------------------------------------------------------- /config/default-vxlan/manager_auth_proxy_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: controller 7 | namespace: system 8 | spec: 9 | template: 10 | spec: 11 | affinity: 12 | nodeAffinity: 13 | requiredDuringSchedulingIgnoredDuringExecution: 14 | nodeSelectorTerms: 15 | - matchExpressions: 16 | - key: kubernetes.io/arch 17 | operator: In 18 | values: 19 | - amd64 20 | - arm64 21 | - ppc64le 22 | - s390x 23 | - key: kubernetes.io/os 24 | operator: In 25 | values: 26 | - linux 27 | containers: 28 | - name: kube-rbac-proxy 29 | securityContext: 30 | allowPrivilegeEscalation: false 31 | capabilities: 32 | drop: 33 | - "ALL" 34 | image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0 35 | args: 36 | - "--secure-listen-address=0.0.0.0:8443" 37 | - "--upstream=http://127.0.0.1:8080/" 38 | - "--logtostderr=true" 39 | - "--v=0" 40 | ports: 41 | - containerPort: 8443 42 | protocol: TCP 43 | name: https 44 | resources: 45 | limits: 46 | cpu: 500m 47 | memory: 128Mi 48 | requests: 49 | cpu: 5m 50 | memory: 64Mi 51 | -------------------------------------------------------------------------------- /config/default-vxlan/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | args: 12 | - "--health-probe-bind-address=:8081" 13 | - "--metrics-bind-address=127.0.0.1:8080" 14 | - "--leader-elect" 15 | - "--zap-devel=false" 16 | - "--zap-time-encoding=iso8601" 17 | env: 18 | - name: IPAM_SERVER 19 | value: "http://neonvm-vxlan-ipam:9090" 20 | -------------------------------------------------------------------------------- /config/default-vxlan/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /tmp/k8s-webhook-server/serving-certs 17 | name: cert 18 | readOnly: true 19 | volumes: 20 | - name: cert 21 | secret: 22 | defaultMode: 420 23 | secretName: webhook-server-cert 24 | -------------------------------------------------------------------------------- /config/default-vxlan/multus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | bases: 5 | - https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/v3.9.3/deployments/multus-daemonset-thick-plugin.yml 6 | -------------------------------------------------------------------------------- /config/default-vxlan/network/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - network.yaml 6 | -------------------------------------------------------------------------------- /config/default-vxlan/network/network.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: "k8s.cni.cncf.io/v1" 2 | kind: NetworkAttachmentDefinition 3 | metadata: 4 | name: overlay-net 5 | namespace: system 6 | spec: 7 | config: '{ 8 | "cniVersion": "0.3.1", 9 | "name": "neonvm-overlay-net", 10 | "type": "bridge", 11 | "bridge": "neon-br0", 12 | "ipam": {} 13 | }' 14 | -------------------------------------------------------------------------------- /config/default-vxlan/vxlan-controller/daemonset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: vxlan-controller 5 | namespace: system 6 | labels: 7 | control-plane: vxlan-controller 8 | app.kubernetes.io/name: daemonset 9 | app.kubernetes.io/instance: vxlan-controller 10 | app.kubernetes.io/component: vxlan-controller 11 | app.kubernetes.io/created-by: neonvm 12 | app.kubernetes.io/part-of: neonvm 13 | app.kubernetes.io/managed-by: kustomize 14 | spec: 15 | revisionHistoryLimit: 10 16 | selector: 17 | matchLabels: 18 | app.kubernetes.io/component: vxlan-controller 19 | template: 20 | metadata: 21 | annotations: 22 | kubectl.kubernetes.io/default-container: vxlan-controller 23 | labels: 24 | app.kubernetes.io/component: vxlan-controller 25 | spec: 26 | hostNetwork: true 27 | dnsPolicy: ClusterFirstWithHostNet 28 | serviceAccount: vxlan-controller 29 | serviceAccountName: vxlan-controller 30 | terminationGracePeriodSeconds: 10 31 | securityContext: {} 32 | affinity: 33 | nodeAffinity: 34 | requiredDuringSchedulingIgnoredDuringExecution: 35 | nodeSelectorTerms: 36 | - matchExpressions: 37 | - key: kubernetes.io/arch 38 | operator: In 39 | values: 40 | - amd64 41 | - key: kubernetes.io/os 42 | operator: In 43 | values: 44 | - linux 45 | initContainers: 46 | - name: install-cni 47 | image: vxlan-controller:dev 48 | imagePullPolicy: IfNotPresent 49 | command: 50 | - /bin/sh 51 | - -c 52 | - 'cp -rf /opt/cni/bin /host/opt/cni' 53 | volumeMounts: 54 | - mountPath: /host/opt/cni/bin 55 | name: cni-bin-dir 56 | containers: 57 | - name: vxlan-controller 58 | image: vxlan-controller:dev 59 | imagePullPolicy: IfNotPresent 60 | env: 61 | - name: MY_NODE_IP 62 | valueFrom: 63 | fieldRef: 64 | fieldPath: status.hostIP 65 | - name: IPAM_SERVER 66 | value: "http://neonvm-vxlan-ipam:9090" 67 | lifecycle: 68 | preStop: 69 | exec: 70 | command: ["vxlan-controller", "-delete"] 71 | volumeMounts: 72 | - mountPath: /host/opt/cni/bin 73 | name: cni-bin-dir 74 | resources: 75 | limits: 76 | cpu: 100m 77 | memory: 50Mi 78 | requests: 79 | cpu: 100m 80 | memory: 50Mi 81 | securityContext: 82 | capabilities: 83 | add: 84 | - NET_RAW 85 | - NET_ADMIN 86 | privileged: false 87 | tolerations: 88 | - operator: Exists 89 | volumes: 90 | # Used by install-cni. 91 | - name: cni-bin-dir 92 | hostPath: 93 | path: /opt/cni/bin 94 | -------------------------------------------------------------------------------- /config/default-vxlan/vxlan-controller/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - daemonset.yaml 6 | - rbac.yaml 7 | 8 | images: 9 | - name: vxlan-controller 10 | newName: vxlan-controller 11 | newTag: dev 12 | -------------------------------------------------------------------------------- /config/default-vxlan/vxlan-controller/rbac.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: vxlan-controller 6 | namespace: system 7 | 8 | --- 9 | apiVersion: rbac.authorization.k8s.io/v1 10 | kind: ClusterRole 11 | metadata: 12 | name: vxlan-controller 13 | rules: 14 | - apiGroups: 15 | - "" 16 | resources: ["nodes"] 17 | verbs: ["list"] 18 | 19 | --- 20 | apiVersion: rbac.authorization.k8s.io/v1 21 | kind: ClusterRoleBinding 22 | metadata: 23 | name: vxlan-controller 24 | roleRef: 25 | apiGroup: rbac.authorization.k8s.io 26 | kind: ClusterRole 27 | name: vxlan-controller 28 | subjects: 29 | - kind: ServiceAccount 30 | name: vxlan-controller 31 | namespace: system 32 | -------------------------------------------------------------------------------- /config/default-vxlan/vxlan-ipam/deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: vxlan-ipam 6 | namespace: system 7 | labels: 8 | control-plane: vxlan-ipam 9 | app.kubernetes.io/name: deployment 10 | app.kubernetes.io/instance: vxlan-ipam 11 | app.kubernetes.io/component: vxlan-ipam 12 | app.kubernetes.io/created-by: neonvm 13 | app.kubernetes.io/part-of: neonvm 14 | app.kubernetes.io/managed-by: kustomize 15 | spec: 16 | strategy: 17 | type: Recreate 18 | selector: 19 | matchLabels: 20 | app.kubernetes.io/component: vxlan-ipam 21 | replicas: 1 22 | template: 23 | metadata: 24 | annotations: 25 | kubectl.kubernetes.io/default-container: vxlan-ipam 26 | labels: 27 | app.kubernetes.io/component: vxlan-ipam 28 | spec: 29 | serviceAccount: vxlan-ipam 30 | serviceAccountName: vxlan-ipam 31 | terminationGracePeriodSeconds: 10 32 | securityContext: {} 33 | affinity: 34 | nodeAffinity: 35 | requiredDuringSchedulingIgnoredDuringExecution: 36 | nodeSelectorTerms: 37 | - matchExpressions: 38 | - key: kubernetes.io/arch 39 | operator: In 40 | values: 41 | - amd64 42 | - key: kubernetes.io/os 43 | operator: In 44 | values: 45 | - linux 46 | containers: 47 | - name: vxlan-ipam 48 | image: vxlan-controller:dev 49 | imagePullPolicy: IfNotPresent 50 | args: ["vxlan-ipam"] 51 | envFrom: 52 | - configMapRef: 53 | name: vxlan-ipam 54 | ports: 55 | - containerPort: 9090 56 | name: grpc 57 | protocol: TCP 58 | readinessProbe: 59 | exec: 60 | command: ["/usr/bin/grpc_health_probe", "-addr=:9090"] 61 | initialDelaySeconds: 5 62 | livenessProbe: 63 | exec: 64 | command: ["/usr/bin/grpc_health_probe", "-addr=:9090"] 65 | initialDelaySeconds: 10 66 | resources: 67 | limits: 68 | cpu: 100m 69 | memory: 50Mi 70 | requests: 71 | cpu: 100m 72 | memory: 50Mi 73 | -------------------------------------------------------------------------------- /config/default-vxlan/vxlan-ipam/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | configMapGenerator: 5 | - literals: 6 | - GOIPAM_CIDR=10.100.0.0/20 7 | - GOIPAM_LOG_LEVEL=debug 8 | - GOIPAM_CONFIGMAP_NAME=neonvm-vxlan-ipam-data 9 | name: vxlan-ipam 10 | namespace: neonvm-system 11 | 12 | generatorOptions: 13 | disableNameSuffixHash: true 14 | 15 | resources: 16 | - deployment.yaml 17 | - service.yaml 18 | - rbac.yaml 19 | 20 | images: 21 | - name: vxlan-controller 22 | newName: vxlan-controller 23 | newTag: dev 24 | -------------------------------------------------------------------------------- /config/default-vxlan/vxlan-ipam/rbac.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: vxlan-ipam 6 | namespace: system 7 | 8 | --- 9 | apiVersion: rbac.authorization.k8s.io/v1 10 | kind: Role 11 | metadata: 12 | name: vxlan-ipam 13 | namespace: system 14 | rules: 15 | - apiGroups: [""] 16 | resources: ["configmaps"] 17 | verbs: ["get", "create", "update", "delete"] 18 | #resourceNames: ["vxlan-ipam"] 19 | 20 | --- 21 | apiVersion: rbac.authorization.k8s.io/v1 22 | kind: RoleBinding 23 | metadata: 24 | name: vxlan-ipam 25 | namespace: system 26 | roleRef: 27 | apiGroup: rbac.authorization.k8s.io 28 | kind: Role 29 | name: vxlan-ipam 30 | subjects: 31 | - kind: ServiceAccount 32 | name: vxlan-ipam 33 | namespace: system 34 | -------------------------------------------------------------------------------- /config/default-vxlan/vxlan-ipam/service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: vxlan-ipam 6 | namespace: system 7 | labels: 8 | control-plane: vxlan-ipam 9 | app.kubernetes.io/name: deployment 10 | app.kubernetes.io/instance: vxlan-ipam 11 | app.kubernetes.io/component: vxlan-ipam 12 | app.kubernetes.io/created-by: neonvm 13 | app.kubernetes.io/part-of: neonvm 14 | app.kubernetes.io/managed-by: kustomize 15 | spec: 16 | clusterIP: None 17 | ports: 18 | - port: 9090 19 | protocol: TCP 20 | targetPort: grpc 21 | selector: 22 | app.kubernetes.io/component: vxlan-ipam 23 | -------------------------------------------------------------------------------- /config/default-vxlan/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch add annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | labels: 7 | app.kubernetes.io/name: mutatingwebhookconfiguration 8 | app.kubernetes.io/instance: mutating-webhook-configuration 9 | app.kubernetes.io/component: webhook 10 | app.kubernetes.io/created-by: neonvm 11 | app.kubernetes.io/part-of: neonvm 12 | app.kubernetes.io/managed-by: kustomize 13 | name: mutating-webhook-configuration 14 | annotations: 15 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 16 | --- 17 | apiVersion: admissionregistration.k8s.io/v1 18 | kind: ValidatingWebhookConfiguration 19 | metadata: 20 | labels: 21 | app.kubernetes.io/name: validatingwebhookconfiguration 22 | app.kubernetes.io/instance: validating-webhook-configuration 23 | app.kubernetes.io/component: webhook 24 | app.kubernetes.io/created-by: neonvm 25 | app.kubernetes.io/part-of: neonvm 26 | app.kubernetes.io/managed-by: kustomize 27 | name: validating-webhook-configuration 28 | annotations: 29 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 30 | -------------------------------------------------------------------------------- /config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: neonvm-system 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: neonvm- 10 | 11 | # Labels to add to all resources and selectors. 12 | #commonLabels: 13 | # someName: someValue 14 | 15 | bases: 16 | - ../common/namespace 17 | - ../common/crd 18 | - ../common/rbac 19 | - ../common/controller 20 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 21 | # crd/kustomization.yaml 22 | - ../common/webhook 23 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. 24 | - ../common/certmanager 25 | # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. 26 | #- ../common/prometheus 27 | 28 | patchesStrategicMerge: 29 | - manager_config_patch.yaml 30 | 31 | # Protect the /metrics endpoint by putting it behind auth. 32 | # If you want your controller to expose the /metrics 33 | # endpoint w/o any authn/z, please comment the following line. 34 | - manager_auth_proxy_patch.yaml 35 | 36 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 37 | # crd/kustomization.yaml 38 | - manager_webhook_patch.yaml 39 | 40 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 41 | # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. 42 | # 'CERTMANAGER' needs to be enabled to use ca injection 43 | - webhookcainjection_patch.yaml 44 | 45 | # the following config is for teaching kustomize how to do var substitution 46 | vars: 47 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. 48 | - name: CERTIFICATE_NAMESPACE # namespace of the certificate CR 49 | objref: 50 | kind: Certificate 51 | group: cert-manager.io 52 | version: v1 53 | name: serving-cert # this name should match the one in certificate.yaml 54 | fieldref: 55 | fieldpath: metadata.namespace 56 | - name: CERTIFICATE_NAME 57 | objref: 58 | kind: Certificate 59 | group: cert-manager.io 60 | version: v1 61 | name: serving-cert # this name should match the one in certificate.yaml 62 | - name: SERVICE_NAMESPACE # namespace of the service 63 | objref: 64 | kind: Service 65 | version: v1 66 | name: webhook-service 67 | fieldref: 68 | fieldpath: metadata.namespace 69 | - name: SERVICE_NAME 70 | objref: 71 | kind: Service 72 | version: v1 73 | name: webhook-service 74 | -------------------------------------------------------------------------------- /config/default/manager_auth_proxy_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: controller 7 | namespace: system 8 | spec: 9 | template: 10 | spec: 11 | affinity: 12 | nodeAffinity: 13 | requiredDuringSchedulingIgnoredDuringExecution: 14 | nodeSelectorTerms: 15 | - matchExpressions: 16 | - key: kubernetes.io/arch 17 | operator: In 18 | values: 19 | - amd64 20 | - arm64 21 | - ppc64le 22 | - s390x 23 | - key: kubernetes.io/os 24 | operator: In 25 | values: 26 | - linux 27 | containers: 28 | - name: kube-rbac-proxy 29 | securityContext: 30 | allowPrivilegeEscalation: false 31 | capabilities: 32 | drop: 33 | - "ALL" 34 | image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0 35 | args: 36 | - "--secure-listen-address=0.0.0.0:8443" 37 | - "--upstream=http://127.0.0.1:8080/" 38 | - "--logtostderr=true" 39 | - "--v=0" 40 | ports: 41 | - containerPort: 8443 42 | protocol: TCP 43 | name: https 44 | resources: 45 | limits: 46 | cpu: 500m 47 | memory: 128Mi 48 | requests: 49 | cpu: 5m 50 | memory: 64Mi 51 | -------------------------------------------------------------------------------- /config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | args: 12 | - "--health-probe-bind-address=:8081" 13 | - "--metrics-bind-address=127.0.0.1:8080" 14 | - "--leader-elect" 15 | - "--zap-devel=false" 16 | - "--zap-time-encoding=iso8601" 17 | -------------------------------------------------------------------------------- /config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /tmp/k8s-webhook-server/serving-certs 17 | name: cert 18 | readOnly: true 19 | volumes: 20 | - name: cert 21 | secret: 22 | defaultMode: 420 23 | secretName: webhook-server-cert 24 | -------------------------------------------------------------------------------- /config/default/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch add annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | labels: 7 | app.kubernetes.io/name: mutatingwebhookconfiguration 8 | app.kubernetes.io/instance: mutating-webhook-configuration 9 | app.kubernetes.io/component: webhook 10 | app.kubernetes.io/created-by: neonvm 11 | app.kubernetes.io/part-of: neonvm 12 | app.kubernetes.io/managed-by: kustomize 13 | name: mutating-webhook-configuration 14 | annotations: 15 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 16 | --- 17 | apiVersion: admissionregistration.k8s.io/v1 18 | kind: ValidatingWebhookConfiguration 19 | metadata: 20 | labels: 21 | app.kubernetes.io/name: validatingwebhookconfiguration 22 | app.kubernetes.io/instance: validating-webhook-configuration 23 | app.kubernetes.io/component: webhook 24 | app.kubernetes.io/created-by: neonvm 25 | app.kubernetes.io/part-of: neonvm 26 | app.kubernetes.io/managed-by: kustomize 27 | name: validating-webhook-configuration 28 | annotations: 29 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 30 | -------------------------------------------------------------------------------- /controllers/suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 controllers 18 | 19 | import ( 20 | "path/filepath" 21 | "testing" 22 | 23 | . "github.com/onsi/ginkgo/v2" 24 | . "github.com/onsi/gomega" 25 | 26 | "k8s.io/client-go/kubernetes/scheme" 27 | "k8s.io/client-go/rest" 28 | "sigs.k8s.io/controller-runtime/pkg/client" 29 | "sigs.k8s.io/controller-runtime/pkg/envtest" 30 | logf "sigs.k8s.io/controller-runtime/pkg/log" 31 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 32 | 33 | vmv1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 34 | //+kubebuilder:scaffold:imports 35 | ) 36 | 37 | // These tests use Ginkgo (BDD-style Go testing framework). Refer to 38 | // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. 39 | 40 | var cfg *rest.Config 41 | var k8sClient client.Client 42 | var testEnv *envtest.Environment 43 | 44 | func TestAPIs(t *testing.T) { 45 | RegisterFailHandler(Fail) 46 | 47 | RunSpecs(t, "Controller Suite") 48 | } 49 | 50 | var _ = BeforeSuite(func() { 51 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 52 | 53 | By("bootstrapping test environment") 54 | testEnv = &envtest.Environment{ 55 | CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")}, 56 | ErrorIfCRDPathMissing: true, 57 | } 58 | 59 | var err error 60 | // cfg is defined in this file globally. 61 | cfg, err = testEnv.Start() 62 | Expect(err).NotTo(HaveOccurred()) 63 | Expect(cfg).NotTo(BeNil()) 64 | 65 | err = vmv1.AddToScheme(scheme.Scheme) 66 | Expect(err).NotTo(HaveOccurred()) 67 | 68 | //+kubebuilder:scaffold:scheme 69 | 70 | k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) 71 | Expect(err).NotTo(HaveOccurred()) 72 | Expect(k8sClient).NotTo(BeNil()) 73 | 74 | }) 75 | 76 | var _ = AfterSuite(func() { 77 | By("tearing down the test environment") 78 | err := testEnv.Stop() 79 | Expect(err).NotTo(HaveOccurred()) 80 | }) 81 | -------------------------------------------------------------------------------- /controllers/virtualmachine_controller_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 controllers 18 | 19 | import ( 20 | "context" 21 | // "fmt" 22 | "os" 23 | "time" 24 | 25 | . "github.com/onsi/ginkgo/v2" 26 | . "github.com/onsi/gomega" 27 | corev1 "k8s.io/api/core/v1" 28 | "k8s.io/apimachinery/pkg/api/errors" 29 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 | "k8s.io/apimachinery/pkg/types" 31 | "sigs.k8s.io/controller-runtime/pkg/reconcile" 32 | 33 | vmv1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 34 | ) 35 | 36 | var _ = Describe("VirtualMachine controller", func() { 37 | Context("VirtualMachine controller test", func() { 38 | 39 | const VirtualMachineName = "test-virtualmachine" 40 | 41 | ctx := context.Background() 42 | 43 | namespace := &corev1.Namespace{ 44 | ObjectMeta: metav1.ObjectMeta{ 45 | Name: VirtualMachineName, 46 | Namespace: VirtualMachineName, 47 | }, 48 | } 49 | 50 | typeNamespaceName := types.NamespacedName{Name: VirtualMachineName, Namespace: VirtualMachineName} 51 | 52 | BeforeEach(func() { 53 | By("Creating the Namespace to perform the tests") 54 | err := k8sClient.Create(ctx, namespace) 55 | Expect(err).To(Not(HaveOccurred())) 56 | 57 | By("Setting the Image ENV VAR which stores the Operand image") 58 | err = os.Setenv("VM_RUNNER_IMAGE", "runner:test") 59 | Expect(err).To(Not(HaveOccurred())) 60 | }) 61 | 62 | AfterEach(func() { 63 | // TODO(user): Attention if you improve this code by adding other context test you MUST 64 | // be aware of the current delete namespace limitations. More info: https://book.kubebuilder.io/reference/envtest.html#testing-considerations 65 | By("Deleting the Namespace to perform the tests") 66 | _ = k8sClient.Delete(ctx, namespace) 67 | 68 | By("Removing the Image ENV VAR which stores the Operand image") 69 | _ = os.Unsetenv("VM_RUNNER_IMAGE") 70 | }) 71 | 72 | It("should successfully reconcile a custom resource for VirtualMachine", func() { 73 | By("Creating the custom resource for the Kind VirtualMachine") 74 | virtualmachine := &vmv1.VirtualMachine{} 75 | err := k8sClient.Get(ctx, typeNamespaceName, virtualmachine) 76 | if err != nil && errors.IsNotFound(err) { 77 | // Let's mock our custom resource at the same way that we would 78 | // apply on the cluster the manifest under config/samples 79 | virtualmachine := &vmv1.VirtualMachine{ 80 | ObjectMeta: metav1.ObjectMeta{ 81 | Name: VirtualMachineName, 82 | Namespace: namespace.Name, 83 | }, 84 | Spec: vmv1.VirtualMachineSpec{}, 85 | } 86 | 87 | err = k8sClient.Create(ctx, virtualmachine) 88 | Expect(err).To(Not(HaveOccurred())) 89 | } 90 | 91 | By("Checking if the custom resource was successfully created") 92 | Eventually(func() error { 93 | found := &vmv1.VirtualMachine{} 94 | return k8sClient.Get(ctx, typeNamespaceName, found) 95 | }, time.Minute, time.Second).Should(Succeed()) 96 | 97 | By("Reconciling the custom resource created") 98 | virtualmachineReconciler := &VirtualMachineReconciler{ 99 | Client: k8sClient, 100 | Scheme: k8sClient.Scheme(), 101 | } 102 | 103 | _, err = virtualmachineReconciler.Reconcile(ctx, reconcile.Request{ 104 | NamespacedName: typeNamespaceName, 105 | }) 106 | Expect(err).To(Not(HaveOccurred())) 107 | /* 108 | By("Checking if Deployment was successfully created in the reconciliation") 109 | Eventually(func() error { 110 | found := &appsv1.Deployment{} 111 | return k8sClient.Get(ctx, typeNamespaceName, found) 112 | }, time.Minute, time.Second).Should(Succeed()) 113 | */ 114 | /* 115 | By("Checking the latest Status Condition added to the VirtualMachine instance") 116 | Eventually(func() error { 117 | if virtualmachine.Status.Conditions != nil && len(virtualmachine.Status.Conditions) != 0 { 118 | latestStatusCondition := virtualmachine.Status.Conditions[len(virtualmachine.Status.Conditions)-1] 119 | expectedLatestStatusCondition := metav1.Condition{Type: typeAvailableVirtualMachine, 120 | Status: metav1.ConditionTrue, Reason: "Reconciling", 121 | Message: fmt.Sprintf("Deployment for custom resource (%s) with %d replicas created successfully", virtualmachine.Name, virtualmachine.Spec.Size)} 122 | if latestStatusCondition != expectedLatestStatusCondition { 123 | return fmt.Errorf("The latest status condition added to the virtualmachine instance is not as expected") 124 | } 125 | } 126 | return nil 127 | }, time.Minute, time.Second).Should(Succeed()) 128 | */ 129 | }) 130 | }) 131 | }) 132 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/neondatabase/neonvm 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/alessio/shellescape v1.4.1 7 | github.com/bufbuild/connect-go v1.4.1 8 | github.com/bufbuild/connect-grpchealth-go v1.0.0 9 | github.com/bufbuild/connect-grpcreflect-go v1.0.0 10 | github.com/cicdteam/go-ipam v0.2.0 11 | github.com/cilium/cilium v1.11.15 12 | github.com/coreos/go-iptables v0.6.0 13 | github.com/digitalocean/go-qemu v0.0.0-20220826173844-d5f5e3ceed89 14 | github.com/docker/docker v20.10.22+incompatible 15 | github.com/docker/libnetwork v0.8.0-dev.2.0.20210525090646-64b7a4574d14 16 | github.com/kdomanski/iso9660 v0.3.3 17 | github.com/onsi/ginkgo/v2 v2.1.6 18 | github.com/onsi/gomega v1.20.1 19 | github.com/urfave/cli/v2 v2.24.2 20 | github.com/vishvananda/netlink v1.1.1-0.20220125195016-0639e7e787ba 21 | go.uber.org/zap v1.24.0 22 | golang.org/x/net v0.7.0 23 | google.golang.org/grpc v1.51.0 24 | k8s.io/api v0.23.10 25 | k8s.io/apimachinery v0.23.10 26 | k8s.io/apiserver v0.23.10 27 | k8s.io/client-go v0.23.10 28 | sigs.k8s.io/controller-runtime v0.11.2 29 | sigs.k8s.io/controller-tools v0.6.2 30 | ) 31 | 32 | require ( 33 | cloud.google.com/go/compute v1.14.0 // indirect 34 | cloud.google.com/go/compute/metadata v0.2.3 // indirect 35 | github.com/Azure/go-autorest v14.2.0+incompatible // indirect 36 | github.com/Azure/go-autorest/autorest v0.11.27 // indirect 37 | github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect 38 | github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect 39 | github.com/Azure/go-autorest/logger v0.2.1 // indirect 40 | github.com/Azure/go-autorest/tracing v0.6.0 // indirect 41 | github.com/Microsoft/go-winio v0.6.0 // indirect 42 | github.com/avast/retry-go/v4 v4.3.2 // indirect 43 | github.com/beorn7/perks v1.0.1 // indirect 44 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 45 | github.com/coreos/go-semver v0.3.0 // indirect 46 | github.com/coreos/go-systemd/v22 v22.5.0 // indirect 47 | github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect 48 | github.com/davecgh/go-spew v1.1.1 // indirect 49 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 50 | github.com/digitalocean/go-libvirt v0.0.0-20220804181439-8648fbde413e // indirect 51 | github.com/docker/distribution v2.8.1+incompatible // indirect 52 | github.com/docker/go-connections v0.4.0 // indirect 53 | github.com/docker/go-units v0.5.0 // indirect 54 | github.com/evanphx/json-patch v5.6.0+incompatible // indirect 55 | github.com/fatih/color v1.13.0 // indirect 56 | github.com/fsnotify/fsnotify v1.5.4 // indirect 57 | github.com/go-logr/logr v1.2.3 // indirect 58 | github.com/go-logr/zapr v1.2.3 // indirect 59 | github.com/go-redis/redis/v8 v8.11.5 // indirect 60 | github.com/gobuffalo/flect v0.2.3 // indirect 61 | github.com/gogo/protobuf v1.3.2 // indirect 62 | github.com/golang-jwt/jwt/v4 v4.2.0 // indirect 63 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 64 | github.com/golang/protobuf v1.5.2 // indirect 65 | github.com/golang/snappy v0.0.4 // indirect 66 | github.com/google/go-cmp v0.5.9 // indirect 67 | github.com/google/gofuzz v1.2.0 // indirect 68 | github.com/google/uuid v1.3.0 // indirect 69 | github.com/googleapis/gnostic v0.5.5 // indirect 70 | github.com/imdario/mergo v0.3.12 // indirect 71 | github.com/inconshreveable/mousetrap v1.0.0 // indirect 72 | github.com/ishidawataru/sctp v0.0.0-20210707070123-9a39160e9062 // indirect 73 | github.com/jmoiron/sqlx v1.3.5 // indirect 74 | github.com/json-iterator/go v1.1.12 // indirect 75 | github.com/klauspost/compress v1.15.14 // indirect 76 | github.com/lib/pq v1.10.7 // indirect 77 | github.com/mattn/go-colorable v0.1.12 // indirect 78 | github.com/mattn/go-isatty v0.0.14 // indirect 79 | github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect 80 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 81 | github.com/modern-go/reflect2 v1.0.2 // indirect 82 | github.com/montanaflynn/stats v0.6.6 // indirect 83 | github.com/opencontainers/go-digest v1.0.0 // indirect 84 | github.com/opencontainers/image-spec v1.1.0-rc2 // indirect 85 | github.com/pkg/errors v0.9.1 // indirect 86 | github.com/prometheus/client_golang v1.12.2 // indirect 87 | github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a // indirect 88 | github.com/prometheus/common v0.32.1 // indirect 89 | github.com/prometheus/procfs v0.7.3 // indirect 90 | github.com/russross/blackfriday/v2 v2.1.0 // indirect 91 | github.com/sirupsen/logrus v1.9.0 // indirect 92 | github.com/spf13/cobra v1.4.0 // indirect 93 | github.com/spf13/pflag v1.0.5 // indirect 94 | github.com/unrolled/mapstore v1.0.1 // indirect 95 | github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect 96 | github.com/xdg-go/pbkdf2 v1.0.0 // indirect 97 | github.com/xdg-go/scram v1.1.2 // indirect 98 | github.com/xdg-go/stringprep v1.0.4 // indirect 99 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect 100 | github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect 101 | go.etcd.io/etcd/api/v3 v3.5.6 // indirect 102 | go.etcd.io/etcd/client/pkg/v3 v3.5.6 // indirect 103 | go.etcd.io/etcd/client/v3 v3.5.6 // indirect 104 | go.mongodb.org/mongo-driver v1.11.1 // indirect 105 | go.uber.org/atomic v1.10.0 // indirect 106 | go.uber.org/multierr v1.9.0 // indirect 107 | go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab // indirect 108 | golang.org/x/crypto v0.5.0 // indirect 109 | golang.org/x/mod v0.7.0 // indirect 110 | golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect 111 | golang.org/x/sync v0.1.0 // indirect 112 | golang.org/x/sys v0.5.0 // indirect 113 | golang.org/x/term v0.5.0 // indirect 114 | golang.org/x/text v0.7.0 // indirect 115 | golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect 116 | golang.org/x/tools v0.5.0 // indirect 117 | gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect 118 | google.golang.org/appengine v1.6.7 // indirect 119 | google.golang.org/genproto v0.0.0-20230106154932-a12b697841d9 // indirect 120 | google.golang.org/protobuf v1.28.1 // indirect 121 | gopkg.in/inf.v0 v0.9.1 // indirect 122 | gopkg.in/yaml.v2 v2.4.0 // indirect 123 | gopkg.in/yaml.v3 v3.0.1 // indirect 124 | k8s.io/apiextensions-apiserver v0.23.10 // indirect 125 | k8s.io/component-base v0.23.10 // indirect 126 | k8s.io/klog/v2 v2.30.0 // indirect 127 | k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect 128 | k8s.io/utils v0.0.0-20211116205334-6203023598ed // indirect 129 | sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect 130 | sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect 131 | sigs.k8s.io/yaml v1.3.0 // indirect 132 | ) 133 | -------------------------------------------------------------------------------- /hack/Dockerfile.generate: -------------------------------------------------------------------------------- 1 | FROM golang:1.19 2 | 3 | WORKDIR /workspace 4 | 5 | # temporary use old version of contoleer tools to fit k8s 1.23 branch 6 | #ENV CONTROLLER_TOOLS_VERSION v0.11.1 7 | ENV CONTROLLER_TOOLS_VERSION v0.9.2 8 | 9 | ENV CODE_GENERATOR_VERSION v0.26.0 10 | 11 | RUN git clone --branch=${CODE_GENERATOR_VERSION} --depth=1 https://github.com/kubernetes/code-generator.git $GOPATH/src/k8s.io/code-generator 12 | RUN go install sigs.k8s.io/controller-tools/cmd/controller-gen@${CONTROLLER_TOOLS_VERSION} 13 | -------------------------------------------------------------------------------- /hack/Dockerfile.kernel-builder: -------------------------------------------------------------------------------- 1 | FROM debian:11 AS build 2 | 3 | ARG KERNEL_VERSION 4 | 5 | RUN set -e \ 6 | && echo "Build linux kernel ${KERNEL_VERSION}" \ 7 | && test -n "${KERNEL_VERSION}" 8 | 9 | WORKDIR /build 10 | 11 | RUN apt-get update && apt-get -y install \ 12 | curl \ 13 | ca-certificates \ 14 | git \ 15 | build-essential \ 16 | flex \ 17 | bison \ 18 | libelf-dev \ 19 | bc \ 20 | libssl-dev \ 21 | python3 \ 22 | cpio \ 23 | zstd 24 | 25 | RUN set -e \ 26 | && mkdir linux \ 27 | && curl -sfL https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-${KERNEL_VERSION}.tar.xz -o linux-${KERNEL_VERSION} \ 28 | && tar --strip-components=1 -C linux -xf linux-${KERNEL_VERSION} 29 | 30 | ADD hack/linux-config-${KERNEL_VERSION} linux/.config 31 | 32 | RUN cd linux && make -j `nproc` 33 | 34 | FROM scratch 35 | COPY --from=build /build/linux/arch/x86/boot/bzImage /vmlinuz 36 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Generation script that's run inside of the Dockerfile.generate container. 4 | 5 | set -eu -o pipefail 6 | 7 | bash $GOPATH/src/k8s.io/code-generator/generate-groups.sh "deepcopy,client,informer,lister" \ 8 | github.com/neondatabase/neonvm/client \ 9 | github.com/neondatabase/neonvm/apis \ 10 | neonvm:v1 \ 11 | --go-header-file hack/boilerplate.go.txt 12 | 13 | controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./apis/..." 14 | -------------------------------------------------------------------------------- /hack/kind.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | networking: 4 | disableDefaultCNI: true 5 | #podSubnet: "192.168.0.0/16" 6 | nodes: 7 | - role: control-plane 8 | image: kindest/node:v1.23.13 9 | - role: worker 10 | image: kindest/node:v1.23.13 11 | - role: worker 12 | image: kindest/node:v1.23.13 13 | -------------------------------------------------------------------------------- /hack/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | // +build tools 3 | 4 | package tools 5 | 6 | import ( 7 | _ "sigs.k8s.io/controller-tools/cmd/controller-gen" 8 | ) 9 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | "flag" 21 | "os" 22 | 23 | // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) 24 | // to ensure that exec-entrypoint and run can make use of them. 25 | _ "k8s.io/client-go/plugin/pkg/client/auth" 26 | 27 | "k8s.io/apimachinery/pkg/runtime" 28 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 29 | clientgoscheme "k8s.io/client-go/kubernetes/scheme" 30 | ctrl "sigs.k8s.io/controller-runtime" 31 | "sigs.k8s.io/controller-runtime/pkg/healthz" 32 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 33 | 34 | vmv1 "github.com/neondatabase/neonvm/apis/neonvm/v1" 35 | "github.com/neondatabase/neonvm/controllers" 36 | //+kubebuilder:scaffold:imports 37 | ) 38 | 39 | var ( 40 | scheme = runtime.NewScheme() 41 | setupLog = ctrl.Log.WithName("setup") 42 | ) 43 | 44 | func init() { 45 | utilruntime.Must(clientgoscheme.AddToScheme(scheme)) 46 | 47 | utilruntime.Must(vmv1.AddToScheme(scheme)) 48 | //+kubebuilder:scaffold:scheme 49 | } 50 | 51 | func main() { 52 | var metricsAddr string 53 | var enableLeaderElection bool 54 | var probeAddr string 55 | flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") 56 | flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") 57 | flag.BoolVar(&enableLeaderElection, "leader-elect", false, 58 | "Enable leader election for controller manager. "+ 59 | "Enabling this will ensure there is only one active controller manager.") 60 | opts := zap.Options{ 61 | Development: true, 62 | } 63 | opts.BindFlags(flag.CommandLine) 64 | flag.Parse() 65 | 66 | ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) 67 | 68 | mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ 69 | Scheme: scheme, 70 | MetricsBindAddress: metricsAddr, 71 | Port: 9443, 72 | HealthProbeBindAddress: probeAddr, 73 | LeaderElection: enableLeaderElection, 74 | LeaderElectionID: "a3b22509.neon.tech", 75 | // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily 76 | // when the Manager ends. This requires the binary to immediately end when the 77 | // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly 78 | // speeds up voluntary leader transitions as the new leader don't have to wait 79 | // LeaseDuration time first. 80 | // 81 | // In the default scaffold provided, the program ends immediately after 82 | // the manager stops, so would be fine to enable this option. However, 83 | // if you are doing or is intended to do any operation such as perform cleanups 84 | // after the manager stops then its usage might be unsafe. 85 | // LeaderElectionReleaseOnCancel: true, 86 | }) 87 | if err != nil { 88 | setupLog.Error(err, "unable to start manager") 89 | os.Exit(1) 90 | } 91 | 92 | if err = (&controllers.VirtualMachineReconciler{ 93 | Client: mgr.GetClient(), 94 | Scheme: mgr.GetScheme(), 95 | Recorder: mgr.GetEventRecorderFor("virtualmachine-controller"), 96 | }).SetupWithManager(mgr); err != nil { 97 | setupLog.Error(err, "unable to create controller", "controller", "VirtualMachine") 98 | os.Exit(1) 99 | } 100 | if err = (&vmv1.VirtualMachine{}).SetupWebhookWithManager(mgr); err != nil { 101 | setupLog.Error(err, "unable to create webhook", "webhook", "VirtualMachine") 102 | os.Exit(1) 103 | } 104 | if err = (&controllers.VirtualMachineMigrationReconciler{ 105 | Client: mgr.GetClient(), 106 | Scheme: mgr.GetScheme(), 107 | Recorder: mgr.GetEventRecorderFor("virtualmachinemigration-controller"), 108 | }).SetupWithManager(mgr); err != nil { 109 | setupLog.Error(err, "unable to create controller", "controller", "VirtualMachineMigration") 110 | os.Exit(1) 111 | } 112 | if err = (&vmv1.VirtualMachineMigration{}).SetupWebhookWithManager(mgr); err != nil { 113 | setupLog.Error(err, "unable to create webhook", "webhook", "VirtualMachineMigration") 114 | os.Exit(1) 115 | } 116 | //+kubebuilder:scaffold:builder 117 | 118 | if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { 119 | setupLog.Error(err, "unable to set up health check") 120 | os.Exit(1) 121 | } 122 | if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { 123 | setupLog.Error(err, "unable to set up ready check") 124 | os.Exit(1) 125 | } 126 | 127 | setupLog.Info("starting manager") 128 | if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { 129 | setupLog.Error(err, "problem running manager") 130 | os.Exit(1) 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /migration.md: -------------------------------------------------------------------------------- 1 | ## NeonVM migration prototype 2 | 3 | - implement new API and CRDs for VM migrations 4 | - implement new controller or add migration flow to current neonvm controller 5 | 6 | ### Minimal migration specification 7 | 8 | ```yaml 9 | apiVersion: vm.neon.tech/v1 10 | kind: VirtualMachineMigration 11 | metadata: 12 | name: example 13 | spec: 14 | vmName: example-vm 15 | ``` 16 | 17 | ### Full migration specification 18 | 19 | ```yaml 20 | apiVersion: vm.neon.tech/v1 21 | kind: VirtualMachineMigration 22 | metadata: 23 | name: example 24 | labels: {} 25 | annotations: {} 26 | spec: 27 | vmName: example-vm 28 | nodeSelector: {} 29 | nodeAffinity: {} 30 | completionTimeout: 3600 31 | incremental: true 32 | compress: true 33 | autoConverge: true 34 | allowPostCopy: true 35 | maxBandwidth: 10Gi 36 | xbzrleCache: 37 | enabled: true 38 | size: 256Mi 39 | zeroBlocks: true 40 | multifdCompression: zstd 41 | ``` 42 | 43 | ### State of migration 44 | 45 | ```yaml 46 | status: 47 | migrationStatus: completed 48 | completionTimestamp: 2022-12-22T01:01:03Z 49 | totaltime: 128212 ms 50 | downtime: 63 ms 51 | throughput: 1087Mi 52 | sourceNode: node1 53 | targetNode: node2 54 | targetVmName: example-abc 55 | targetPodName: example-abc-def-12345 56 | memory: 57 | transferred: 228391Ki 58 | remaining: 0Ki 59 | total: 8Gi 60 | precopy: 202371Ki 61 | downtime: 26020Ki 62 | pages: 63 | pageSize: 4Ki 64 | duplicate: 2045389 65 | skipped: 0 66 | normal: 52501 67 | pagesPerSecond: 32710 68 | ``` 69 | 70 | ### Questions 71 | 72 | - how generate name for target VM (name prefix/sufix/other) ? 73 | - how long migration resource should be available (`kubectl get neonvmmigrate`) after migration finished ? 74 | - how to cancel migration ? as variant - just delete it (`kubectl delete neonvmmigrate example`) 75 | - should migration controller delete source VM after migration ? 76 | - metrics ? 77 | -------------------------------------------------------------------------------- /runner/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the Go binary 2 | FROM golang:1.19 as builder 3 | ARG TARGETOS 4 | ARG TARGETARCH 5 | 6 | WORKDIR /workspace 7 | # Copy the Go Modules manifests 8 | COPY go.mod go.mod 9 | COPY go.sum go.sum 10 | # cache deps before building and copying source so that we don't need to re-download as much 11 | # and so that source changes don't invalidate our downloaded layer 12 | RUN go mod download 13 | 14 | # Copy the go source 15 | COPY main.go main.go 16 | COPY apis/ apis/ 17 | COPY controllers/ controllers/ 18 | COPY runner/ runner/ 19 | 20 | # Build 21 | # the GOARCH has not a default value to allow the binary be built according to the host where the command 22 | # was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO 23 | # the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, 24 | # by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. 25 | RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o /runner runner/main.go 26 | 27 | FROM alpine:3.16 28 | 29 | RUN apk add --no-cache \ 30 | tini \ 31 | curl \ 32 | screen \ 33 | dnsmasq \ 34 | iptables \ 35 | iproute2 \ 36 | coreutils \ 37 | socat \ 38 | jq \ 39 | busybox-extras \ 40 | e2fsprogs \ 41 | qemu-system-x86_64 \ 42 | qemu-img 43 | 44 | COPY --from=builder /runner /usr/bin/runner 45 | COPY hack/vmlinuz /vm/kernel/vmlinuz 46 | 47 | ENTRYPOINT ["/sbin/tini", "--", "runner"] 48 | -------------------------------------------------------------------------------- /samples/vm-example-full.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: example-config 5 | data: 6 | file1.txt: "just a string" 7 | file2.txt: | 8 | multi-string 1 9 | multi-string 2 10 | multi-string 3 11 | multi-string 4 12 | 13 | --- 14 | apiVersion: v1 15 | kind: Secret 16 | metadata: 17 | name: example-secret 18 | stringData: 19 | secret1: "secret string" 20 | secret2: | 21 | multi-string-secret 1 22 | multi-string-secret 2 23 | multi-string-secret 3 24 | multi-string-secret 4 25 | 26 | --- 27 | apiVersion: vm.neon.tech/v1 28 | kind: VirtualMachine 29 | metadata: 30 | name: example 31 | spec: 32 | guest: 33 | cpus: 34 | min: 1 35 | max: 4 36 | use: 1 37 | memorySlotSize: 1Gi 38 | memorySlots: 39 | min: 1 40 | max: 4 41 | use: 1 42 | rootDisk: 43 | image: vm-postgres:14-alpine 44 | size: 8Gi 45 | command: ["/bin/sh"] 46 | args: 47 | - -c 48 | - | 49 | echo "Hello First World" 50 | echo Hello Second World 51 | echo $VAR1 52 | echo $VAR2 53 | ping 8.8.8.8 54 | env: 55 | - name: VAR1 56 | value: value1 57 | - name: VAR2 58 | value: "value 2" 59 | ports: 60 | - port: 5432 61 | 62 | disks: 63 | - name: disk1 64 | mountPath: /some/path/1 65 | emptyDisk: 66 | size: 2Gi 67 | - name: disk2 68 | mountPath: /some/path/2 69 | configMap: 70 | name: example-config 71 | - name: disk3 72 | mountPath: /some/path/3 73 | readOnly: true 74 | configMap: 75 | name: example-config 76 | items: 77 | - key: file1.txt 78 | path: renamed-file1.txt 79 | - name: disk4 80 | mountPath: /some/path/4 81 | secret: 82 | secretName: example-secret 83 | -------------------------------------------------------------------------------- /samples/vm-example-migration.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: vm.neon.tech/v1 2 | kind: VirtualMachineMigration 3 | metadata: 4 | name: example 5 | spec: 6 | vmName: example 7 | -------------------------------------------------------------------------------- /samples/vm-example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: example 5 | spec: 6 | ports: 7 | - name: postgres 8 | port: 5432 9 | protocol: TCP 10 | targetPort: postgres 11 | nodePort: 30432 12 | - name: pooler 13 | port: 6432 14 | protocol: TCP 15 | targetPort: postgres 16 | nodePort: 30632 17 | - name: host-metrics 18 | port: 9100 19 | protocol: TCP 20 | targetPort: host-metrics 21 | nodePort: 30100 22 | - name: metrics 23 | port: 9187 24 | protocol: TCP 25 | targetPort: metrics 26 | nodePort: 30187 27 | type: NodePort 28 | selector: 29 | vm.neon.tech/name: example 30 | 31 | --- 32 | apiVersion: vm.neon.tech/v1 33 | kind: VirtualMachine 34 | metadata: 35 | name: example 36 | spec: 37 | guest: 38 | cpus: 39 | min: 1 40 | max: 4 41 | use: 2 42 | memorySlotSize: 1Gi 43 | memorySlots: 44 | min: 1 45 | max: 2 46 | use: 2 47 | rootDisk: 48 | image: vm-postgres:15-alpine 49 | size: 8Gi 50 | args: 51 | - -c 52 | - 'config_file=/etc/postgresql/postgresql.conf' 53 | env: 54 | # for testing only - allows login without password 55 | - name: POSTGRES_HOST_AUTH_METHOD 56 | value: trust 57 | ports: 58 | - name: postgres 59 | port: 5432 60 | - name: pooler 61 | port: 5432 62 | - name: host-metrics 63 | port: 9100 64 | - name: metrics 65 | port: 9187 66 | extraNetwork: 67 | enable: true 68 | disks: 69 | - name: pgdata 70 | mountPath: /var/lib/postgresql 71 | emptyDisk: 72 | size: 16Gi 73 | - name: postgres-config 74 | mountPath: /etc/postgresql 75 | configMap: 76 | name: example-config 77 | items: 78 | - key: postgresql.conf 79 | path: postgresql.conf 80 | - name: vector-config 81 | mountPath: /etc/vector 82 | configMap: 83 | name: example-config 84 | items: 85 | - key: vector.yaml 86 | path: vector.yaml 87 | - name: cache 88 | mountPath: /neonvm/cache 89 | tmpfs: 90 | size: 1Gi 91 | 92 | --- 93 | apiVersion: v1 94 | kind: ConfigMap 95 | metadata: 96 | name: example-config 97 | data: 98 | postgresql.conf: | 99 | listen_addresses = '*' 100 | shared_preload_libraries = 'pg_stat_statements' 101 | 102 | max_connections = 64 103 | shared_buffers = 512MB 104 | effective_cache_size = 1536MB 105 | maintenance_work_mem = 128MB 106 | checkpoint_completion_target = 0.9 107 | wal_buffers = 16MB 108 | default_statistics_target = 100 109 | random_page_cost = 1.1 110 | effective_io_concurrency = 200 111 | work_mem = 4MB 112 | min_wal_size = 1GB 113 | max_wal_size = 4GB 114 | max_worker_processes = 4 115 | max_parallel_workers_per_gather = 2 116 | max_parallel_workers = 4 117 | max_parallel_maintenance_workers = 2 118 | 119 | vector.yaml: | 120 | sources: 121 | postgresql_metrics: 122 | type: postgresql_metrics 123 | endpoints: 124 | - "postgres://postgres@localhost:5432" 125 | exclude_databases: 126 | - "^template.*" 127 | sinks: 128 | postgres_exporter: 129 | type: prometheus_exporter 130 | inputs: 131 | - postgresql_metrics 132 | address: "0.0.0.0:9187" 133 | -------------------------------------------------------------------------------- /samples/vm-example/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.16 AS rootdisk 2 | 3 | RUN set -e \ 4 | && apk add --no-cache \ 5 | jq \ 6 | curl \ 7 | ca-certificates \ 8 | util-linux-misc \ 9 | agetty \ 10 | bind-tools \ 11 | tcpdump \ 12 | coreutils \ 13 | udev \ 14 | && passwd -d root \ 15 | && echo 'SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}="1"' | tee /lib/udev/rules.d/80-hotplug-cpu.rules 16 | 17 | ADD motd /etc/motd 18 | RUN rm -f /sbin/init 19 | ADD init /sbin/init 20 | RUN chmod +x /sbin/init 21 | 22 | # postgresql stuff 23 | RUN set -e \ 24 | && apk add --no-cache \ 25 | su-exec \ 26 | postgresql14 27 | # init postgres 28 | ENV PGDATA /var/lib/postgresql 29 | RUN set -e \ 30 | && mkdir -p ${PGDATA} /run/postgresql \ 31 | && chown -R postgres:postgres ${PGDATA} /run/postgresql \ 32 | && su-exec postgres pg_ctl init 33 | 34 | ADD postgresql.conf /etc/postgresql/ 35 | ADD pg_hba.conf /etc/postgresql/ 36 | 37 | 38 | FROM alpine:3.16 AS image 39 | 40 | ARG DISK_SIZE=2G 41 | 42 | COPY --from=rootdisk / /rootdisk 43 | RUN set -e \ 44 | && apk add --no-cache qemu-img e2fsprogs \ 45 | && mkfs.ext4 -d /rootdisk /disk.raw ${DISK_SIZE} \ 46 | && qemu-img convert -f raw -O qcow2 -o cluster_size=2M,lazy_refcounts=on /disk.raw /disk.qcow2 \ 47 | && rm -f /disk.raw \ 48 | && qemu-img info /disk.qcow2 49 | 50 | FROM alpine:3.16 51 | 52 | COPY --from=image /disk.qcow2 / 53 | -------------------------------------------------------------------------------- /samples/vm-example/init: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 4 | 5 | # system mounts 6 | mount -t proc proc /proc 7 | mount -t sysfs sysfs /sys 8 | mkdir -p /dev/pts 9 | mount -t devpts devpts /dev/pts 10 | mkdir -p /dev/shm 11 | chmod 1777 /dev/shm 12 | mount -t tmpfs tmp /dev/shm 13 | 14 | # start udev (mostlry used for auto-online hotplugged CPUs) 15 | udevd --daemon 16 | 17 | # networking 18 | ip link set up dev lo 19 | ETH_LIST=$(find /sys/class/net -mindepth 1 -maxdepth 1 -name "eth*") 20 | for i in ${ETH_LIST}; do 21 | iface=$(basename $i) 22 | ip link set up dev $iface 23 | udhcpc -t 1 -T 1 -A 1 -b -q -i $iface -O 121 -O 119 24 | done 25 | 26 | # postgresql init and start 27 | export PGDATA=/var/lib/postgresql 28 | su-exec postgres pg_ctl start -o '-c config_file=/etc/postgresql/postgresql.conf -c hba_file=/etc/postgresql/pg_hba.conf' 29 | 30 | echo -e "\nBoot took $(cut -d' ' -f1 /proc/uptime) seconds\n" 31 | 32 | echo "Start getty for console" 33 | while true; do 34 | setsid -w /sbin/agetty --8bits --local-line --noissue --noclear --noreset --login-pause --autologin root 115200 ttyS0 35 | sleep 1 36 | done 37 | 38 | echo "Exiting and shuting down vm" 39 | su-exec postgres pg_ctl stop 40 | poweroff -f 41 | -------------------------------------------------------------------------------- /samples/vm-example/motd: -------------------------------------------------------------------------------- 1 | -~*= Example Guest =*~- 2 | 3 | -------------------------------------------------------------------------------- /samples/vm-example/pg_hba.conf: -------------------------------------------------------------------------------- 1 | # ATTENTION 2 | # 3 | # USE IT ONLY FOR TESTS (SEE DANGEROUS PART) 4 | 5 | # TYPE DATABASE USER ADDRESS METHOD 6 | 7 | # "local" is for Unix domain socket connections only 8 | local all all trust 9 | # IPv4 local connections: 10 | host all all 127.0.0.1/32 trust 11 | # IPv6 local connections: 12 | host all all ::1/128 trust 13 | # Allow replication connections from localhost, by a user with the 14 | # replication privilege. 15 | local replication all trust 16 | host replication all 127.0.0.1/32 trust 17 | host replication all ::1/128 trust 18 | 19 | 20 | # DANGEROUS PART! DO NOT USE IN REAL SCENARIO 21 | host all all 10.0.0.0/8 trust 22 | host all all 172.16.0.0/12 trust 23 | host all all 192.168.0.0/16 trust 24 | -------------------------------------------------------------------------------- /samples/vm-example/postgresql.conf: -------------------------------------------------------------------------------- 1 | listen_addresses = '*' 2 | dynamic_shared_memory_type = sysv 3 | -------------------------------------------------------------------------------- /tests/e2e/kuttl-test.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestSuite 3 | testDirs: 4 | - tests/e2e 5 | timeout: 300 6 | parallel: 1 7 | -------------------------------------------------------------------------------- /tests/e2e/vm-migration/00-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | timeout: 90 4 | --- 5 | apiVersion: vm.neon.tech/v1 6 | kind: VirtualMachine 7 | metadata: 8 | name: example 9 | status: 10 | phase: Running 11 | conditions: 12 | - type: Available 13 | status: "True" 14 | --- 15 | apiVersion: v1 16 | kind: pod 17 | metadata: 18 | name: workload 19 | status: 20 | phase: Running 21 | -------------------------------------------------------------------------------- /tests/e2e/vm-migration/00-prepare.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | apply: 4 | - ../../../samples/vm-example.yaml 5 | unitTest: false 6 | --- 7 | apiVersion: v1 8 | kind: Pod 9 | metadata: 10 | name: workload 11 | spec: 12 | initContainers: 13 | - name: wait-for-pg 14 | image: postgres:15-alpine 15 | command: 16 | - sh 17 | - "-c" 18 | - | 19 | set -e 20 | until pg_isready --dbname=postgres --host=example --port=5432; do 21 | sleep 1 22 | done 23 | - name: pgbench-initialize 24 | image: postgres:15-alpine 25 | command: 26 | - pgbench 27 | args: 28 | - postgres://postgres@example:5432/postgres 29 | - --initialize 30 | - --scale=10 31 | containers: 32 | - name: pgbench 33 | image: postgres:15-alpine 34 | command: 35 | - pgbench 36 | args: 37 | - postgres://postgres@example:5432/postgres 38 | - --client=2 39 | - --progress=1 40 | - --progress-timestamp 41 | - --time=600 42 | restartPolicy: Never 43 | -------------------------------------------------------------------------------- /tests/e2e/vm-migration/01-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | timeout: 90 4 | --- 5 | apiVersion: vm.neon.tech/v1 6 | kind: VirtualMachineMigration 7 | metadata: 8 | name: example 9 | status: 10 | phase: Succeeded 11 | --- 12 | apiVersion: vm.neon.tech/v1 13 | kind: VirtualMachine 14 | metadata: 15 | name: example 16 | status: 17 | phase: Running 18 | conditions: 19 | - type: Available 20 | status: "True" 21 | --- 22 | apiVersion: v1 23 | kind: pod 24 | metadata: 25 | name: workload 26 | status: 27 | phase: Running 28 | -------------------------------------------------------------------------------- /tests/e2e/vm-migration/01-migrate.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | apply: 4 | - ../../../samples/vm-example-migration.yaml 5 | unitTest: false 6 | -------------------------------------------------------------------------------- /tools/vxlan/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the Go binary 2 | FROM golang:1.19 as builder 3 | ARG TARGETOS 4 | ARG TARGETARCH 5 | 6 | WORKDIR /workspace 7 | # Copy the Go Modules manifests 8 | COPY go.mod go.mod 9 | COPY go.sum go.sum 10 | # cache deps before building and copying source so that we don't need to re-download as much 11 | # and so that source changes don't invalidate our downloaded layer 12 | RUN go mod download 13 | 14 | # Copy the go source 15 | COPY tools/vxlan/controller/ tools/vxlan/controller/ 16 | COPY tools/vxlan/ipam/ tools/vxlan/ipam/ 17 | 18 | # Build 19 | # the GOARCH has not a default value to allow the binary be built according to the host where the command 20 | # was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO 21 | # the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, 22 | # by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. 23 | RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o /vxlan-controller tools/vxlan/controller/main.go 24 | RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o /vxlan-ipam tools/vxlan/ipam/main.go 25 | 26 | FROM alpine:3.16 27 | 28 | RUN apk add --no-cache \ 29 | tini \ 30 | dnsmasq \ 31 | iptables \ 32 | iproute2 33 | 34 | # add CNI plugins 35 | RUN set -e \ 36 | && wget -q https://github.com/containernetworking/plugins/releases/download/v1.2.0/cni-plugins-linux-amd64-v1.2.0.tgz -O cni.tgz \ 37 | && mkdir -p /opt/cni/bin \ 38 | && tar -xzf cni.tgz -C /opt/cni/bin \ 39 | && rm -f cni.tgz 40 | 41 | RUN set -e \ 42 | && wget -q https://github.com/grpc-ecosystem/grpc-health-probe/releases/latest/download/grpc_health_probe-linux-amd64 -O /usr/bin/grpc_health_probe \ 43 | && chmod +x /usr/bin/grpc_health_probe 44 | 45 | COPY --from=builder /vxlan-controller /usr/bin/vxlan-controller 46 | COPY --from=builder /vxlan-ipam /usr/bin/vxlan-ipam 47 | 48 | ENTRYPOINT ["/sbin/tini", "--"] 49 | CMD ["vxlan-controller"] 50 | -------------------------------------------------------------------------------- /tools/vxlan/ipam/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "log" 7 | "net/http" 8 | "os" 9 | "os/signal" 10 | "syscall" 11 | "time" 12 | 13 | "github.com/bufbuild/connect-go" 14 | grpchealth "github.com/bufbuild/connect-grpchealth-go" 15 | grpcreflect "github.com/bufbuild/connect-grpcreflect-go" 16 | 17 | // compress "github.com/klauspost/connect-compress" 18 | 19 | "github.com/urfave/cli/v2" 20 | "go.uber.org/zap" 21 | "go.uber.org/zap/zapcore" 22 | "golang.org/x/net/http2" 23 | "golang.org/x/net/http2/h2c" 24 | 25 | goipam "github.com/cicdteam/go-ipam" 26 | goipamapiv1 "github.com/cicdteam/go-ipam/api/v1" 27 | "github.com/cicdteam/go-ipam/api/v1/apiv1connect" 28 | "github.com/cicdteam/go-ipam/pkg/service" 29 | ) 30 | 31 | func main() { 32 | 33 | app := &cli.App{ 34 | Name: "vxlan ipam server", 35 | Usage: "grpc server for vxlan ipam", 36 | Flags: []cli.Flag{ 37 | &cli.StringFlag{ 38 | Name: "grpc-server-endpoint", 39 | Value: ":9090", 40 | Usage: "gRPC server endpoint", 41 | EnvVars: []string{"GOIPAM_GRPC_SERVER_ENDPOINT"}, 42 | }, 43 | &cli.StringFlag{ 44 | Name: "cidr", 45 | Value: "10.10.10.0/24", 46 | Usage: "CIDR for IP address management", 47 | EnvVars: []string{"GOIPAM_CIDR"}, 48 | }, 49 | &cli.StringFlag{ 50 | Name: "log-level", 51 | Value: "info", 52 | Usage: "log-level can be one of error|warn|info|debug", 53 | EnvVars: []string{"GOIPAM_LOG_LEVEL"}, 54 | }, 55 | &cli.StringFlag{ 56 | Name: "configmap", 57 | Value: "vxlan-ipam", 58 | Usage: "k8s ConfigMap name where ipam data stored", 59 | EnvVars: []string{"GOIPAM_CONFIGMAP_NAME"}, 60 | }, 61 | &cli.BoolFlag{ 62 | Name: "cache", 63 | Usage: "cache queries to k8s ConfigMap", 64 | Value: true, 65 | EnvVars: []string{"GOIPAM_CONFIGMAP_CACHE"}, 66 | }, 67 | }, 68 | Action: func(ctx *cli.Context) error { 69 | c := getConfig(ctx) 70 | configmap := ctx.String("configmap") 71 | cache := ctx.Bool("cache") 72 | c.Storage = goipam.NewConfigmap(configmap, cache) 73 | s := newServer(c) 74 | return s.Run() 75 | }, 76 | } 77 | 78 | err := app.Run(os.Args) 79 | if err != nil { 80 | log.Fatalf("Error in cli: %v", err) 81 | } 82 | 83 | } 84 | 85 | type config struct { 86 | GrpcServerEndpoint string 87 | Log *zap.SugaredLogger 88 | Storage goipam.Storage 89 | ConfigMapName string 90 | ConfigMapCache bool 91 | Cidr string 92 | } 93 | 94 | func getConfig(ctx *cli.Context) config { 95 | cfg := zap.NewProductionConfig() 96 | level, err := zap.ParseAtomicLevel(ctx.String("log-level")) 97 | if err != nil { 98 | log.Fatal(err) 99 | } 100 | cfg.Level = level 101 | cfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder 102 | zlog, err := cfg.Build() 103 | if err != nil { 104 | log.Fatal(err) 105 | } 106 | 107 | return config{ 108 | GrpcServerEndpoint: ctx.String("grpc-server-endpoint"), 109 | Cidr: ctx.String("cidr"), 110 | Log: zlog.Sugar(), 111 | ConfigMapName: ctx.String("configmap"), 112 | ConfigMapCache: ctx.Bool("cache"), 113 | } 114 | } 115 | 116 | type server struct { 117 | c config 118 | ipamer goipam.Ipamer 119 | storage goipam.Storage 120 | log *zap.SugaredLogger 121 | } 122 | 123 | func newServer(c config) *server { 124 | 125 | return &server{ 126 | c: c, 127 | ipamer: goipam.NewWithStorage(c.Storage), 128 | storage: c.Storage, 129 | log: c.Log, 130 | } 131 | } 132 | func (s *server) Run() error { 133 | s.log.Infow("starting vxlan ipam server", "cidr", s.c.Cidr, "backend", s.storage.Name(), "configmap name", s.c.ConfigMapName, "configmap cache", s.c.ConfigMapCache, "endpoint", s.c.GrpcServerEndpoint) 134 | mux := http.NewServeMux() 135 | 136 | compress1KB := connect.WithCompressMinBytes(1024) 137 | 138 | // The generated constructors return a path and a plain net/http 139 | // handler. 140 | mux.Handle(apiv1connect.NewIpamServiceHandler( 141 | service.New(s.log, s.ipamer), 142 | compress1KB, 143 | )) 144 | 145 | mux.Handle(grpchealth.NewHandler( 146 | grpchealth.NewStaticChecker(apiv1connect.IpamServiceName), 147 | compress1KB, 148 | )) 149 | 150 | mux.Handle(grpcreflect.NewHandlerV1( 151 | grpcreflect.NewStaticReflector(apiv1connect.IpamServiceName), 152 | compress1KB, 153 | )) 154 | 155 | server := http.Server{ 156 | Addr: s.c.GrpcServerEndpoint, 157 | Handler: h2c.NewHandler( 158 | mux, 159 | &http2.Server{}, 160 | ), 161 | ReadHeaderTimeout: 30 * time.Second, 162 | ReadTimeout: 1 * time.Minute, 163 | WriteTimeout: 1 * time.Minute, 164 | MaxHeaderBytes: 8 * 1024, // 8KiB 165 | } 166 | 167 | signals := make(chan os.Signal, 1) 168 | signal.Notify(signals, os.Interrupt, syscall.SIGTERM) 169 | 170 | go func() error { 171 | if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { 172 | log.Printf("HTTP listen and serve: %v", err) 173 | return err 174 | } 175 | return nil 176 | }() 177 | 178 | s.log.Infow("creating prefix", "cidr", s.c.Cidr) 179 | c := apiv1connect.NewIpamServiceClient( 180 | http.DefaultClient, 181 | "http://"+s.c.GrpcServerEndpoint, 182 | connect.WithGRPC(), 183 | ) 184 | 185 | prefixes, err := c.ListPrefixes(context.Background(), connect.NewRequest(&goipamapiv1.ListPrefixesRequest{})) 186 | if err != nil { 187 | return err 188 | } 189 | 190 | prefixAlreadyCreated := false 191 | for _, p := range prefixes.Msg.Prefixes { 192 | if p.Cidr == s.c.Cidr { 193 | prefixAlreadyCreated = true 194 | s.log.Infow("prefix already present, skip prefix creation", "cidr", p.Cidr) 195 | } 196 | } 197 | 198 | if !prefixAlreadyCreated { 199 | result, err := c.CreatePrefix(context.Background(), connect.NewRequest(&goipamapiv1.CreatePrefixRequest{Cidr: s.c.Cidr})) 200 | if err != nil { 201 | return err 202 | } 203 | s.log.Infow("prefix created", "cidr", result.Msg.Prefix.Cidr) 204 | } 205 | 206 | <-signals 207 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 208 | defer cancel() 209 | if err := server.Shutdown(ctx); err != nil { 210 | log.Printf("HTTP shutdown: %v", err) //nolint:gocritic 211 | return err 212 | } 213 | 214 | return nil 215 | } 216 | --------------------------------------------------------------------------------