This commit is contained in:
parent
b253832bd0
commit
efbdd13fd0
|
@ -0,0 +1,3 @@
|
||||||
|
# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file
|
||||||
|
# Ignore build and test binaries.
|
||||||
|
bin/
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
bin/*
|
||||||
|
Dockerfile.cross
|
||||||
|
|
||||||
|
# Test binary, build with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Kubernetes Generated files - skip generated files, except for vendored files
|
||||||
|
|
||||||
|
!vendor/**/zz_generated.*
|
||||||
|
|
||||||
|
# editor and IDE paraphernalia
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Build the manager binary
|
||||||
|
FROM golang:1.20 as builder
|
||||||
|
ARG TARGETOS
|
||||||
|
ARG TARGETARCH
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
# Copy the Go Modules manifests
|
||||||
|
COPY go.mod go.mod
|
||||||
|
COPY go.sum go.sum
|
||||||
|
# cache deps before building and copying source so that we don't need to re-download as much
|
||||||
|
# and so that source changes don't invalidate our downloaded layer
|
||||||
|
ENV GOPROXY=https://goproxy.cn,direct GO111MODULE=on
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
# Copy the go source
|
||||||
|
COPY cmd/main.go cmd/main.go
|
||||||
|
COPY api/ api/
|
||||||
|
COPY internal/controller/ internal/controller/
|
||||||
|
COPY watcher watcher
|
||||||
|
COPY pkg pkg
|
||||||
|
COPY apiserver apiserver
|
||||||
|
|
||||||
|
# Build
|
||||||
|
# the GOARCH has not a default value to allow the binary be built according to the host where the command
|
||||||
|
# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO
|
||||||
|
# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore,
|
||||||
|
# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.
|
||||||
|
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go
|
||||||
|
|
||||||
|
# Use distroless as minimal base image to package the manager binary
|
||||||
|
# Refer to https://github.com/GoogleContainerTools/distroless for more details
|
||||||
|
FROM gcr.io/distroless/static:nonroot
|
||||||
|
WORKDIR /
|
||||||
|
COPY --from=builder /workspace/manager .
|
||||||
|
USER 65532:65532
|
||||||
|
|
||||||
|
ENTRYPOINT ["/manager"]
|
|
@ -0,0 +1,174 @@
|
||||||
|
|
||||||
|
# Image URL to use all building/pushing image targets
|
||||||
|
VER := $(shell git rev-parse HEAD)
|
||||||
|
VER_DEV := $(shell date +%m%d%H%M%S)
|
||||||
|
IMG ?= registry.zelda.io/zelda:${VER}
|
||||||
|
IMG_DEV ?= registry.zelda.io/zelda:${VER_DEV}
|
||||||
|
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
|
||||||
|
ENVTEST_K8S_VERSION = 1.28.0
|
||||||
|
|
||||||
|
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
|
||||||
|
ifeq (,$(shell go env GOBIN))
|
||||||
|
GOBIN=$(shell go env GOPATH)/bin
|
||||||
|
else
|
||||||
|
GOBIN=$(shell go env GOBIN)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# CONTAINER_TOOL defines the container tool to be used for building images.
|
||||||
|
# Be aware that the target commands are only tested with Docker which is
|
||||||
|
# scaffolded by default. However, you might want to replace it to use other
|
||||||
|
# tools. (i.e. podman)
|
||||||
|
CONTAINER_TOOL ?= docker
|
||||||
|
|
||||||
|
# Setting SHELL to bash allows bash commands to be executed by recipes.
|
||||||
|
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
|
||||||
|
SHELL = /usr/bin/env bash -o pipefail
|
||||||
|
.SHELLFLAGS = -ec
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: build
|
||||||
|
|
||||||
|
##@ General
|
||||||
|
|
||||||
|
# The help target prints out all targets with their descriptions organized
|
||||||
|
# beneath their categories. The categories are represented by '##@' and the
|
||||||
|
# target descriptions by '##'. The awk command is responsible for reading the
|
||||||
|
# entire set of makefiles included in this invocation, looking for lines of the
|
||||||
|
# file as xyz: ## something, and then pretty-format the target and help. Then,
|
||||||
|
# if there's a line with ##@ something, that gets pretty-printed as a category.
|
||||||
|
# More info on the usage of ANSI control characters for terminal formatting:
|
||||||
|
# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
|
||||||
|
# More info on the awk command:
|
||||||
|
# http://linuxcommand.org/lc3_adv_awk.php
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
|
help: ## Display this help.
|
||||||
|
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
|
||||||
|
|
||||||
|
##@ Development
|
||||||
|
|
||||||
|
.PHONY: manifests
|
||||||
|
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
|
||||||
|
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
|
||||||
|
|
||||||
|
.PHONY: generate
|
||||||
|
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
|
||||||
|
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
|
||||||
|
|
||||||
|
.PHONY: fmt
|
||||||
|
fmt: ## Run go fmt against code.
|
||||||
|
go fmt ./...
|
||||||
|
|
||||||
|
.PHONY: vet
|
||||||
|
vet: ## Run go vet against code.
|
||||||
|
go vet ./...
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: manifests generate fmt vet envtest ## Run tests.
|
||||||
|
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test ./... -coverprofile cover.out
|
||||||
|
|
||||||
|
##@ Build
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build: manifests generate fmt vet ## Build manager binary.
|
||||||
|
go build -o bin/manager cmd/main.go
|
||||||
|
|
||||||
|
.PHONY: run
|
||||||
|
run: manifests generate fmt vet ## Run a controller from your host.
|
||||||
|
go run ./cmd/main.go
|
||||||
|
|
||||||
|
# If you wish to build the manager image targeting other platforms you can use the --platform flag.
|
||||||
|
# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it.
|
||||||
|
# More info: https://docs.docker.com/develop/develop-images/build_enhancements/
|
||||||
|
.PHONY: docker-build
|
||||||
|
docker-build: ## Build docker image with the manager.
|
||||||
|
$(CONTAINER_TOOL) build -t ${IMG} .
|
||||||
|
|
||||||
|
.PHONY: docker-push
|
||||||
|
docker-push: ## Push docker image with the manager.
|
||||||
|
$(CONTAINER_TOOL) push ${IMG}
|
||||||
|
|
||||||
|
# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple
|
||||||
|
# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:
|
||||||
|
# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/
|
||||||
|
# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/
|
||||||
|
# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=<myregistry/image:<tag>> then the export will fail)
|
||||||
|
# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option.
|
||||||
|
PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
|
||||||
|
.PHONY: docker-buildx
|
||||||
|
docker-buildx: ## Build and push docker image for the manager for cross-platform support
|
||||||
|
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
|
||||||
|
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
|
||||||
|
- $(CONTAINER_TOOL) buildx create --name project-v3-builder
|
||||||
|
$(CONTAINER_TOOL) buildx use project-v3-builder
|
||||||
|
- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .
|
||||||
|
- $(CONTAINER_TOOL) buildx rm project-v3-builder
|
||||||
|
rm Dockerfile.cross
|
||||||
|
|
||||||
|
##@ Deployment
|
||||||
|
|
||||||
|
ifndef ignore-not-found
|
||||||
|
ignore-not-found = false
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
|
||||||
|
$(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f -
|
||||||
|
|
||||||
|
.PHONY: uninstall
|
||||||
|
uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
|
||||||
|
$(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
|
||||||
|
|
||||||
|
.PHONY: deploy
|
||||||
|
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
|
||||||
|
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
|
||||||
|
$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -
|
||||||
|
|
||||||
|
.PHONY: undeploy
|
||||||
|
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
|
||||||
|
$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
|
||||||
|
|
||||||
|
##@ Build Dependencies
|
||||||
|
|
||||||
|
## Location to install dependencies to
|
||||||
|
LOCALBIN ?= $(shell pwd)/bin
|
||||||
|
$(LOCALBIN):
|
||||||
|
mkdir -p $(LOCALBIN)
|
||||||
|
|
||||||
|
## Tool Binaries
|
||||||
|
KUBECTL ?= kubectl
|
||||||
|
KUSTOMIZE ?= $(LOCALBIN)/kustomize
|
||||||
|
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
|
||||||
|
ENVTEST ?= $(LOCALBIN)/setup-envtest
|
||||||
|
|
||||||
|
## Tool Versions
|
||||||
|
KUSTOMIZE_VERSION ?= v5.1.1
|
||||||
|
CONTROLLER_TOOLS_VERSION ?= v0.13.0
|
||||||
|
|
||||||
|
.PHONY: kustomize
|
||||||
|
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. If wrong version is installed, it will be removed before downloading.
|
||||||
|
$(KUSTOMIZE): $(LOCALBIN)
|
||||||
|
@if test -x $(LOCALBIN)/kustomize && ! $(LOCALBIN)/kustomize version | grep -q $(KUSTOMIZE_VERSION); then \
|
||||||
|
echo "$(LOCALBIN)/kustomize version is not expected $(KUSTOMIZE_VERSION). Removing it before installing."; \
|
||||||
|
rm -rf $(LOCALBIN)/kustomize; \
|
||||||
|
fi
|
||||||
|
test -s $(LOCALBIN)/kustomize || GOBIN=$(LOCALBIN) GO111MODULE=on go install sigs.k8s.io/kustomize/kustomize/v5@$(KUSTOMIZE_VERSION)
|
||||||
|
|
||||||
|
.PHONY: controller-gen
|
||||||
|
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. If wrong version is installed, it will be overwritten.
|
||||||
|
$(CONTROLLER_GEN): $(LOCALBIN)
|
||||||
|
test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \
|
||||||
|
GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
|
||||||
|
|
||||||
|
.PHONY: envtest
|
||||||
|
envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
|
||||||
|
$(ENVTEST): $(LOCALBIN)
|
||||||
|
test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
|
||||||
|
|
||||||
|
minikube-build:
|
||||||
|
$(shell eval $$(minikube -p minikube docker-env); docker build --build-arg VERSION=${VER_DEV} --build-arg MODE=Debug -t ${IMG_DEV} .)
|
||||||
|
|
||||||
|
.PHONY: minikube-deploy
|
||||||
|
minikube-deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
|
||||||
|
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG_DEV}
|
||||||
|
$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -
|
|
@ -0,0 +1,101 @@
|
||||||
|
# Code generated by tool. DO NOT EDIT.
|
||||||
|
# This file is used to track the info used to scaffold your project
|
||||||
|
# and allow the plugins properly work.
|
||||||
|
# More info: https://book.kubebuilder.io/reference/project-config.html
|
||||||
|
domain: zelda.io
|
||||||
|
layout:
|
||||||
|
- go.kubebuilder.io/v4
|
||||||
|
projectName: zelda
|
||||||
|
repo: github.com/ycyxuehan/zelda
|
||||||
|
resources:
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
namespaced: true
|
||||||
|
controller: true
|
||||||
|
domain: zelda.io
|
||||||
|
group: zelda.io
|
||||||
|
kind: ZProject
|
||||||
|
path: github.com/ycyxuehan/zelda/api/v1alpha1
|
||||||
|
version: v1alpha1
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
namespaced: true
|
||||||
|
controller: true
|
||||||
|
domain: zelda.io
|
||||||
|
group: zelda.io
|
||||||
|
kind: ZService
|
||||||
|
path: github.com/ycyxuehan/zelda/api/v1alpha1
|
||||||
|
version: v1alpha1
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
namespaced: true
|
||||||
|
controller: true
|
||||||
|
domain: zelda.io
|
||||||
|
group: zelda.io
|
||||||
|
kind: ZUser
|
||||||
|
path: github.com/ycyxuehan/zelda/api/v1alpha1
|
||||||
|
version: v1alpha1
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
namespaced: true
|
||||||
|
controller: true
|
||||||
|
domain: zelda.io
|
||||||
|
group: zelda.io
|
||||||
|
kind: ZGroup
|
||||||
|
path: github.com/ycyxuehan/zelda/api/v1alpha1
|
||||||
|
version: v1alpha1
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
namespaced: true
|
||||||
|
controller: true
|
||||||
|
domain: zelda.io
|
||||||
|
group: zelda.io
|
||||||
|
kind: ZRegistry
|
||||||
|
path: github.com/ycyxuehan/zelda/api/v1alpha1
|
||||||
|
version: v1alpha1
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
namespaced: true
|
||||||
|
controller: true
|
||||||
|
domain: zelda.io
|
||||||
|
group: zelda.io
|
||||||
|
kind: ZScript
|
||||||
|
path: github.com/ycyxuehan/zelda/api/v1alpha1
|
||||||
|
version: v1alpha1
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
namespaced: true
|
||||||
|
controller: true
|
||||||
|
domain: zelda.io
|
||||||
|
group: zelda.io
|
||||||
|
kind: ZBuildTemplate
|
||||||
|
path: github.com/ycyxuehan/zelda/api/v1alpha1
|
||||||
|
version: v1alpha1
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
namespaced: true
|
||||||
|
controller: true
|
||||||
|
domain: zelda.io
|
||||||
|
group: zelda.io
|
||||||
|
kind: ZRunTemplate
|
||||||
|
path: github.com/ycyxuehan/zelda/api/v1alpha1
|
||||||
|
version: v1alpha1
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
namespaced: true
|
||||||
|
controller: true
|
||||||
|
domain: zelda.io
|
||||||
|
group: zelda.io
|
||||||
|
kind: ZBuilder
|
||||||
|
path: github.com/ycyxuehan/zelda/api/v1alpha1
|
||||||
|
version: v1alpha1
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
namespaced: true
|
||||||
|
controller: true
|
||||||
|
domain: zelda.io
|
||||||
|
group: zelda.io
|
||||||
|
kind: ZCustomHost
|
||||||
|
path: github.com/ycyxuehan/zelda/api/v1alpha1
|
||||||
|
version: v1alpha1
|
||||||
|
version: "3"
|
|
@ -0,0 +1,94 @@
|
||||||
|
# zelda
|
||||||
|
// TODO(user): Add simple overview of use/purpose
|
||||||
|
|
||||||
|
## Description
|
||||||
|
// TODO(user): An in-depth paragraph about your project and overview of use
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
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.
|
||||||
|
**Note:** Your controller will automatically use the current context in your kubeconfig file (i.e. whatever cluster `kubectl cluster-info` shows).
|
||||||
|
|
||||||
|
### Running on the cluster
|
||||||
|
1. Install Instances of Custom Resources:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kubectl apply -k config/samples/
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Build and push your image to the location specified by `IMG`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make docker-build docker-push IMG=<some-registry>/zelda:tag
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Deploy the controller to the cluster with the image specified by `IMG`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make deploy IMG=<some-registry>/zelda:tag
|
||||||
|
```
|
||||||
|
|
||||||
|
### Uninstall CRDs
|
||||||
|
To delete the CRDs from the cluster:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make uninstall
|
||||||
|
```
|
||||||
|
|
||||||
|
### Undeploy controller
|
||||||
|
UnDeploy the controller from the cluster:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make undeploy
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
// TODO(user): Add detailed information on how you would like others to contribute to this project
|
||||||
|
|
||||||
|
### How it works
|
||||||
|
This project aims to follow the Kubernetes [Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/).
|
||||||
|
|
||||||
|
It uses [Controllers](https://kubernetes.io/docs/concepts/architecture/controller/),
|
||||||
|
which provide a reconcile function responsible for synchronizing resources until the desired state is reached on the cluster.
|
||||||
|
|
||||||
|
### Test It Out
|
||||||
|
1. Install the CRDs into the cluster:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Run your controller (this will run in the foreground, so switch to a new terminal if you want to leave it running):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make run
|
||||||
|
```
|
||||||
|
|
||||||
|
**NOTE:** You can also run this in one step by running: `make install run`
|
||||||
|
|
||||||
|
### Modifying the API definitions
|
||||||
|
If you are editing the API definitions, generate the manifests such as CRs or CRDs using:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make manifests
|
||||||
|
```
|
||||||
|
|
||||||
|
**NOTE:** Run `make --help` for more information on all potential `make` targets
|
||||||
|
|
||||||
|
More information can be found via the [Kubebuilder Documentation](https://book.kubebuilder.io/introduction.html)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package v1alpha1 contains API Schema definitions for the zelda.io v1alpha1 API group
|
||||||
|
// +kubebuilder:object:generate=true
|
||||||
|
// +groupName=zelda.io
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/scheme"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// GroupVersion is group version used to register these objects
|
||||||
|
GroupVersion = schema.GroupVersion{Group: "zelda.io", Version: "v1alpha1"}
|
||||||
|
|
||||||
|
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
|
||||||
|
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
|
||||||
|
|
||||||
|
// AddToScheme adds the types in this group-version to the given scheme.
|
||||||
|
AddToScheme = SchemeBuilder.AddToScheme
|
||||||
|
)
|
|
@ -0,0 +1,331 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ycyxuehan/zelda/pkg/utils"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Phase string
|
||||||
|
|
||||||
|
const (
|
||||||
|
PhaseCreating Phase = "Creating"
|
||||||
|
PhaseInitial Phase = "Initial"
|
||||||
|
PhaseBuild Phase = "Build"
|
||||||
|
PhasePackage Phase = "Package"
|
||||||
|
PhaseDeploy Phase = "Deploy"
|
||||||
|
PhaseCompleted Phase = "Completed"
|
||||||
|
PhasePending Phase = "Pending"
|
||||||
|
Succeeded string = "Succeeded"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||||
|
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||||
|
//Step status
|
||||||
|
type StepStatus struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Phase corev1.PodPhase `json:"phase,omitempty"`
|
||||||
|
StartedAt metav1.Time `json:"startedAt,omitempty"`
|
||||||
|
FinishedAt metav1.Time `json:"finishedAt,omitempty"`
|
||||||
|
Started *bool `json:"started,omitempty"`
|
||||||
|
Ready bool `json:"ready,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
Reason string `json:"reason,omitempty"`
|
||||||
|
// corev1.ContainerStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStepStatus(status corev1.ContainerStatus) StepStatus {
|
||||||
|
stepStatus := StepStatus{}
|
||||||
|
stepStatus.Started = status.Started
|
||||||
|
stepStatus.Ready = status.Ready
|
||||||
|
stepStatus.Name = status.Name
|
||||||
|
//等待
|
||||||
|
if status.State.Waiting != nil {
|
||||||
|
stepStatus.Phase = corev1.PodPending
|
||||||
|
stepStatus.Message = status.State.Waiting.Message
|
||||||
|
stepStatus.Reason = status.State.Waiting.Reason
|
||||||
|
}
|
||||||
|
//运行中
|
||||||
|
if status.State.Running != nil {
|
||||||
|
stepStatus.Phase = corev1.PodRunning
|
||||||
|
stepStatus.StartedAt = status.State.Running.StartedAt
|
||||||
|
}
|
||||||
|
if status.State.Terminated != nil {
|
||||||
|
if status.State.Terminated.ExitCode != 0 {
|
||||||
|
stepStatus.Phase = corev1.PodFailed
|
||||||
|
} else {
|
||||||
|
stepStatus.Phase = corev1.PodPhase(PhaseCompleted)
|
||||||
|
}
|
||||||
|
stepStatus.FinishedAt = status.State.Terminated.FinishedAt
|
||||||
|
stepStatus.Reason = status.State.Terminated.Reason
|
||||||
|
}
|
||||||
|
|
||||||
|
return stepStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZBuilderSpec defines the desired state of ZBuilder
|
||||||
|
type ZBuilderSpec struct {
|
||||||
|
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
|
||||||
|
// Foo is an example field of ZBuilder. Edit zbuilder_types.go to remove/update
|
||||||
|
// Foo string `json:"foo,omitempty"`
|
||||||
|
Project corev1.ObjectReference `json:"project,omitempty"`
|
||||||
|
SubProject string `json:"subProject,omitempty"`
|
||||||
|
Branch string `json:"branch,omitempty"`
|
||||||
|
CommitHash string `json:"commitHash,omitempty"`
|
||||||
|
ZService corev1.ObjectReference `json:"zservice,omitempty"`
|
||||||
|
Creator string `json:"creator,omitempty"`
|
||||||
|
Build bool `json:"build,omitempty"`
|
||||||
|
Package bool `json:"package,omitempty"`
|
||||||
|
Deploy bool `json:"deploy,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZBuilderStatus defines the observed state of ZBuilder
|
||||||
|
type ZBuilderStatus struct {
|
||||||
|
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
Steps []StepStatus `json:"steps,omitempty"`
|
||||||
|
CreatedAt *metav1.Time `json:"createdAt,omitempty"`
|
||||||
|
FinishedAt *metav1.Time `json:"finishedAt,omitempty"`
|
||||||
|
Phase Phase `json:"phase,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
Reason string `json:"reason,omitempty"`
|
||||||
|
RunAt string `json:"RunAt,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewZbuilderStatus(podStatus *corev1.PodStatus) ZBuilderStatus {
|
||||||
|
zbuilderStatus := ZBuilderStatus{}
|
||||||
|
if podStatus == nil {
|
||||||
|
return zbuilderStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cs := range podStatus.ContainerStatuses {
|
||||||
|
zbuilderStatus.Steps = append(zbuilderStatus.Steps, NewStepStatus(cs))
|
||||||
|
}
|
||||||
|
zbuilderStatus.CreatedAt = podStatus.StartTime
|
||||||
|
switch podStatus.Phase {
|
||||||
|
case corev1.PodPending:
|
||||||
|
zbuilderStatus.Phase = PhasePending
|
||||||
|
case corev1.PodRunning:
|
||||||
|
zbuilderStatus.Phase = PhaseBuild
|
||||||
|
}
|
||||||
|
|
||||||
|
zbuilderStatus.Message = podStatus.Message
|
||||||
|
zbuilderStatus.RunAt = podStatus.HostIP
|
||||||
|
|
||||||
|
return zbuilderStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
func (zbuilderStatus *ZBuilderStatus) SetPhase(phase Phase) {
|
||||||
|
zbuilderStatus.Phase = phase
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
//+kubebuilder:subresource:status
|
||||||
|
|
||||||
|
// ZBuilder is the Schema for the zbuilders API
|
||||||
|
type ZBuilder struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec ZBuilderSpec `json:"spec,omitempty"`
|
||||||
|
Status ZBuilderStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// ZBuilderList contains a list of ZBuilder
|
||||||
|
type ZBuilderList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []ZBuilder `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ZBuilder{}, &ZBuilderList{})
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回workdir的volume mount
|
||||||
|
func (zb *ZBuilder) VolumeMountWorkDir() corev1.VolumeMount {
|
||||||
|
return corev1.VolumeMount{
|
||||||
|
Name: "workdir",
|
||||||
|
MountPath: "/workdir",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回dockerconfig 的volumeMount
|
||||||
|
func (zb *ZBuilder) VolumeMountDockerConfig() corev1.VolumeMount {
|
||||||
|
return corev1.VolumeMount{
|
||||||
|
Name: "dockerconfig",
|
||||||
|
MountPath: "/root/.docker",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回workdir的volume
|
||||||
|
func (zb *ZBuilder) VolumeWorkDir() corev1.Volume {
|
||||||
|
return corev1.Volume{
|
||||||
|
Name: "workdir",
|
||||||
|
VolumeSource: corev1.VolumeSource{
|
||||||
|
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (zb *ZBuilder) VolumeDockerConfig(secret string) corev1.Volume {
|
||||||
|
return corev1.Volume{
|
||||||
|
Name: "dockerconfig",
|
||||||
|
VolumeSource: corev1.VolumeSource{
|
||||||
|
Secret: &corev1.SecretVolumeSource{
|
||||||
|
SecretName: secret,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//编译容器
|
||||||
|
func (zb *ZBuilder) Containers(template *ZBuildTemplateSpec, workdir string) []corev1.Container {
|
||||||
|
containers := []corev1.Container{}
|
||||||
|
for _, step := range template.Steps {
|
||||||
|
volumeMounts := []corev1.VolumeMount{zb.VolumeMountWorkDir(), zb.VolumeMountDockerConfig()}
|
||||||
|
volumeMounts = append(volumeMounts, step.VolumeMounts...)
|
||||||
|
container := corev1.Container{
|
||||||
|
Image: step.Image,
|
||||||
|
VolumeMounts: volumeMounts,
|
||||||
|
Args: step.Args,
|
||||||
|
Command: step.Commands,
|
||||||
|
Env: utils.MergeEnv(utils.MergeOverrideByFirst, zb.DefaultEnv(), step.Env),
|
||||||
|
Name: step.Name,
|
||||||
|
WorkingDir: workdir,
|
||||||
|
}
|
||||||
|
containers = append(containers, container)
|
||||||
|
}
|
||||||
|
return containers
|
||||||
|
}
|
||||||
|
|
||||||
|
//初始化容器,下载git文件
|
||||||
|
func (zb *ZBuilder) InitContainers(gitImage, gitRepo, dockerfile, dockerfilePath string) []corev1.Container {
|
||||||
|
containers := []corev1.Container{
|
||||||
|
//下载git仓库
|
||||||
|
{
|
||||||
|
Image: gitImage,
|
||||||
|
VolumeMounts: []corev1.VolumeMount{zb.VolumeMountWorkDir()},
|
||||||
|
Command: []string{"git"},
|
||||||
|
Args: []string{"clone", "-b", zb.Spec.Branch, gitRepo},
|
||||||
|
WorkingDir: "/workdir",
|
||||||
|
},
|
||||||
|
//写入Dockerfile
|
||||||
|
{
|
||||||
|
Image: gitImage,
|
||||||
|
VolumeMounts: []corev1.VolumeMount{zb.VolumeMountWorkDir()},
|
||||||
|
Command: []string{"echo"},
|
||||||
|
Args: []string{"-e", "${DOCKERFILE}", ">", dockerfilePath},
|
||||||
|
WorkingDir: "/workdir",
|
||||||
|
Env: []corev1.EnvVar{
|
||||||
|
{
|
||||||
|
Name: "DOCKERFILE",
|
||||||
|
Value: dockerfile,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return containers
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据builder创建podspec
|
||||||
|
func (zb *ZBuilder) PodSpec(template *ZBuildTemplateSpec, gitImage string, gitRepo string, subProject *SubProject, registry *ZRegistry) corev1.PodSpec {
|
||||||
|
vols := []corev1.Volume{zb.VolumeWorkDir(), zb.VolumeDockerConfig(registry.GetName())}
|
||||||
|
vols = append(vols, subProject.BuildSpec.Volumes...)
|
||||||
|
spec := corev1.PodSpec{
|
||||||
|
InitContainers: zb.InitContainers(gitImage, gitRepo, subProject.BuildSpec.Dockerfile, zb.WorkPath(zb.RepoPath(gitRepo), subProject.Path, "Dockerfile")),
|
||||||
|
Containers: zb.Containers(template, zb.WorkPath(zb.RepoPath(gitRepo), subProject.Path)),
|
||||||
|
// ImagePullSecrets: secrets,
|
||||||
|
Volumes: vols,
|
||||||
|
RestartPolicy: corev1.RestartPolicyNever,
|
||||||
|
}
|
||||||
|
return spec
|
||||||
|
}
|
||||||
|
|
||||||
|
func (zb *ZBuilder) Pod(template *ZBuildTemplateSpec, gitImage string, gitRepo string, subProject *SubProject, registry *ZRegistry) corev1.Pod {
|
||||||
|
spec := zb.PodSpec(template, gitImage, gitRepo, subProject, registry)
|
||||||
|
pod := corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: zb.GetName(),
|
||||||
|
Namespace: zb.GetNamespace(),
|
||||||
|
OwnerReferences: []metav1.OwnerReference{
|
||||||
|
zb.Owner(),
|
||||||
|
},
|
||||||
|
Labels: zb.ResourceLabels(),
|
||||||
|
},
|
||||||
|
Spec: spec,
|
||||||
|
}
|
||||||
|
return pod
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据repo获取project path
|
||||||
|
func (zb *ZBuilder) RepoPath(repo string) string {
|
||||||
|
strs := strings.Split(repo, "/")
|
||||||
|
if len(strs) < 1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
str := strs[len(strs)-1]
|
||||||
|
strs = strings.Split(str, ".")
|
||||||
|
if len(strs) < 1 {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
return strs[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (zb *ZBuilder) WorkPath(spath ...string) string {
|
||||||
|
return path.Join("/workdir", path.Join(spath...))
|
||||||
|
}
|
||||||
|
|
||||||
|
//这里返回默认env,默认env提供一些基本信息
|
||||||
|
func (zb *ZBuilder) DefaultEnv() []corev1.EnvVar {
|
||||||
|
return []corev1.EnvVar{
|
||||||
|
{Name: "BRANCH", Value: zb.Spec.Branch},
|
||||||
|
{Name: "COMMIT_HASH", Value: zb.Spec.CommitHash},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Owner
|
||||||
|
func (zb *ZBuilder) Owner() metav1.OwnerReference {
|
||||||
|
bTrue := true
|
||||||
|
return metav1.OwnerReference{
|
||||||
|
APIVersion: GroupVersion.Version,
|
||||||
|
Kind: "ZBuilder",
|
||||||
|
Name: zb.GetName(),
|
||||||
|
BlockOwnerDeletion: &bTrue,
|
||||||
|
Controller: &bTrue,
|
||||||
|
UID: zb.GetUID(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Labels
|
||||||
|
func (zb *ZBuilder) ResourceLabels() map[string]string {
|
||||||
|
labels := make(map[string]string)
|
||||||
|
labels["builders.zelda.io"] = zb.Name
|
||||||
|
labels["projects.zelda.io"] = zb.Spec.Project.Name
|
||||||
|
labels["users.zelda.io"] = zb.Spec.Creator
|
||||||
|
labels["projects.zelda.io/branch"] = zb.Spec.Branch
|
||||||
|
return labels
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||||
|
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||||
|
|
||||||
|
type BuildStep struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Image string `json:"image,omitempty"`
|
||||||
|
Commands []string `json:"commands,omitempty"`
|
||||||
|
VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"`
|
||||||
|
Env []corev1.EnvVar `json:"env,omitempty"`
|
||||||
|
Args []string `json:"args,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZBuildTemplateSpec defines the desired state of ZBuildTemplate
|
||||||
|
type ZBuildTemplateSpec struct {
|
||||||
|
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
|
||||||
|
// Foo is an example field of ZBuildTemplate. Edit zbuildtemplate_types.go to remove/update
|
||||||
|
// Foo string `json:"foo,omitempty"`
|
||||||
|
Steps []BuildStep `json:"steps,omitempty"`
|
||||||
|
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZBuildTemplateStatus defines the observed state of ZBuildTemplate
|
||||||
|
type ZBuildTemplateStatus struct {
|
||||||
|
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
//+kubebuilder:subresource:status
|
||||||
|
|
||||||
|
// ZBuildTemplate is the Schema for the zbuildtemplates API
|
||||||
|
type ZBuildTemplate struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec ZBuildTemplateSpec `json:"spec,omitempty"`
|
||||||
|
Status ZBuildTemplateStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// ZBuildTemplateList contains a list of ZBuildTemplate
|
||||||
|
type ZBuildTemplateList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []ZBuildTemplate `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ZBuildTemplate{}, &ZBuildTemplateList{})
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||||
|
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||||
|
|
||||||
|
// ZCustomHostSpec defines the desired state of ZCustomHost
|
||||||
|
type ZCustomHostSpec struct {
|
||||||
|
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
|
||||||
|
// Foo is an example field of ZCustomHost. Edit zcustomhost_types.go to remove/update
|
||||||
|
// Foo string `json:"foo,omitempty"`
|
||||||
|
HostAlias []corev1.HostAlias `json:"hostAlias,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZCustomHostStatus defines the observed state of ZCustomHost
|
||||||
|
type ZCustomHostStatus struct {
|
||||||
|
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
//+kubebuilder:subresource:status
|
||||||
|
|
||||||
|
// ZCustomHost is the Schema for the zcustomhosts API
|
||||||
|
type ZCustomHost struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec ZCustomHostSpec `json:"spec,omitempty"`
|
||||||
|
Status ZCustomHostStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// ZCustomHostList contains a list of ZCustomHost
|
||||||
|
type ZCustomHostList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []ZCustomHost `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ZCustomHost{}, &ZCustomHostList{})
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||||
|
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||||
|
|
||||||
|
// ZGroupSpec defines the desired state of ZGroup
|
||||||
|
type ZGroupSpec struct {
|
||||||
|
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
|
||||||
|
// Foo is an example field of ZGroup. Edit zgroup_types.go to remove/update
|
||||||
|
// Foo string `json:"foo,omitempty"`
|
||||||
|
Rulers []rbacv1.PolicyRule `json:"rulers,omitempty"`
|
||||||
|
ClusterRulers []rbacv1.PolicyRule `json:"clusterRulers,omitempty"`
|
||||||
|
Secrets []corev1.ObjectReference `json:"secrets,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZGroupStatus defines the observed state of ZGroup
|
||||||
|
type ZGroupStatus struct {
|
||||||
|
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
//+kubebuilder:subresource:status
|
||||||
|
|
||||||
|
// ZGroup is the Schema for the zgroups API
|
||||||
|
type ZGroup struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec ZGroupSpec `json:"spec,omitempty"`
|
||||||
|
Status ZGroupStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// ZGroupList contains a list of ZGroup
|
||||||
|
type ZGroupList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []ZGroup `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ZGroup{}, &ZGroupList{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (zg *ZGroup) Owner() metav1.OwnerReference {
|
||||||
|
bTrue := true
|
||||||
|
return metav1.OwnerReference{
|
||||||
|
Name: zg.GetName(),
|
||||||
|
APIVersion: GroupVersion.Version,
|
||||||
|
Kind: "ZGroup",
|
||||||
|
UID: zg.GetUID(),
|
||||||
|
Controller: &bTrue,
|
||||||
|
BlockOwnerDeletion: &bTrue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (zg *ZGroup) ResourceLabels() map[string]string {
|
||||||
|
labels := make(map[string]string)
|
||||||
|
labels["groups.zelda.io"] = zg.GetName()
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回Role
|
||||||
|
func (zg *ZGroup) Role() *rbacv1.Role {
|
||||||
|
if len(zg.Spec.Rulers) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
role := rbacv1.Role{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: zg.Name,
|
||||||
|
Namespace: zg.Namespace,
|
||||||
|
OwnerReferences: []metav1.OwnerReference{
|
||||||
|
zg.Owner(),
|
||||||
|
},
|
||||||
|
Labels: zg.ResourceLabels(),
|
||||||
|
},
|
||||||
|
Rules: zg.Spec.Rulers,
|
||||||
|
}
|
||||||
|
return &role
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回ClusterRole
|
||||||
|
func (zg *ZGroup) ClusterRole() *rbacv1.ClusterRole {
|
||||||
|
if len(zg.Spec.Rulers) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
role := rbacv1.ClusterRole{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: zg.Name,
|
||||||
|
OwnerReferences: []metav1.OwnerReference{
|
||||||
|
zg.Owner(),
|
||||||
|
},
|
||||||
|
Labels: zg.ResourceLabels(),
|
||||||
|
},
|
||||||
|
Rules: zg.Spec.ClusterRulers,
|
||||||
|
}
|
||||||
|
return &role
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回zgroup是否有变更
|
||||||
|
func (zg *ZGroup) IsSpecChanged() (bool, error) {
|
||||||
|
old := ZGroup{}
|
||||||
|
latestConfiguration, ok := zg.GetAnnotations()["kubectl.kubernetes.io/last-applied-configuration"]
|
||||||
|
if !ok {
|
||||||
|
return false, fmt.Errorf("not found annotation")
|
||||||
|
}
|
||||||
|
err := json.Unmarshal([]byte(latestConfiguration), &old)
|
||||||
|
if err != nil { //无法获得旧配置
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
oldString, err := json.Marshal(&old.Spec)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
newString, err := json.Marshal(&zg.Spec)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if string(oldString) != string(newString) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回role的namespacedname
|
||||||
|
func (zg *ZGroup) NamespacedNameRole() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Namespace: zg.GetNamespace(),
|
||||||
|
Name: zg.GetName(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回cluster role的namespaced name
|
||||||
|
func (zg *ZGroup) NamespacedNameClusterRole() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Name: zg.GetName(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ruler和cluster ruler 都为空时,返回true
|
||||||
|
func (zg *ZGroup) IsEmpty() bool {
|
||||||
|
return len(zg.Spec.Rulers) == 0 && len(zg.Spec.ClusterRulers) == 0
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||||
|
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||||
|
type GitSpec struct {
|
||||||
|
Repo string `json:"repo,omitempty"`
|
||||||
|
ID int `json:"id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BuildSpec struct {
|
||||||
|
Template corev1.ObjectReference `json:"template,omitempty"`
|
||||||
|
Volumes []corev1.Volume `json:"volumes,omitempty"`
|
||||||
|
Dockerfile string `json:"dockerfile,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubProject struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Path string `json:"path,omitempty"`
|
||||||
|
BuildSpec BuildSpec `json:"buildSpec,omitempty"`
|
||||||
|
// RunSpec RunSpec `json:"runSpec,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZProjectSpec defines the desired state of ZProject
|
||||||
|
type ZProjectSpec struct {
|
||||||
|
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
|
||||||
|
// Foo is an example field of ZProject. Edit zproject_types.go to remove/update
|
||||||
|
//Foo string `json:"foo,omitempty"`
|
||||||
|
Git GitSpec `json:"git,omitempty"`
|
||||||
|
Registry corev1.ObjectReference `json:"registry,omitempty"`
|
||||||
|
// ImageName string `json:"imageName,omitempty"`
|
||||||
|
SubProjects []SubProject `json:"subProjects,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZProjectStatus defines the observed state of ZProject
|
||||||
|
type ZProjectStatus struct {
|
||||||
|
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
//+kubebuilder:subresource:status
|
||||||
|
|
||||||
|
// ZProject is the Schema for the zprojects API
|
||||||
|
type ZProject struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec ZProjectSpec `json:"spec,omitempty"`
|
||||||
|
Status ZProjectStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// ZProjectList contains a list of ZProject
|
||||||
|
type ZProjectList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []ZProject `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ZProject{}, &ZProjectList{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (zp *ZProject) SubProject(name string) *SubProject {
|
||||||
|
for _, sub := range zp.Spec.SubProjects {
|
||||||
|
if sub.Name == name {
|
||||||
|
return &sub
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (zp *ZProject) NamespacedNameRegistry() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Namespace: zp.Spec.Registry.Namespace,
|
||||||
|
Name: zp.Spec.Registry.Name,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ycyxuehan/zelda/pkg/utils"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||||
|
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||||
|
|
||||||
|
// ZRegistrySpec defines the desired state of ZRegistry
|
||||||
|
type ZRegistrySpec struct {
|
||||||
|
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
|
||||||
|
// Foo is an example field of ZRegistry. Edit zregistry_types.go to remove/update
|
||||||
|
// Foo string `json:"foo,omitempty"`
|
||||||
|
Server string `json:"server,omitempty"`
|
||||||
|
Namespace string `json:"namespace,omitempty"`
|
||||||
|
Username string `json:"username,omitempty"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
Portal string `json:"portal,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZRegistryStatus defines the observed state of ZRegistry
|
||||||
|
type ZRegistryStatus struct {
|
||||||
|
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
//+kubebuilder:subresource:status
|
||||||
|
|
||||||
|
// ZRegistry is the Schema for the zregistries API
|
||||||
|
type ZRegistry struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec ZRegistrySpec `json:"spec,omitempty"`
|
||||||
|
Status ZRegistryStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// ZRegistryList contains a list of ZRegistry
|
||||||
|
type ZRegistryList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []ZRegistry `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ZRegistry{}, &ZRegistryList{})
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回imagetag的registry部分
|
||||||
|
func (zr *ZRegistry) FullImageTag(baseTag string) string {
|
||||||
|
if zr.Spec.Server == "" {
|
||||||
|
return baseTag
|
||||||
|
}
|
||||||
|
if zr.Spec.Namespace == "" {
|
||||||
|
return strings.Join([]string{zr.Spec.Server, baseTag}, "/")
|
||||||
|
}
|
||||||
|
return strings.Join([]string{zr.Spec.Server, zr.Spec.Namespace, baseTag}, "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回登陆registry的secret名称,不需要登陆,返回空
|
||||||
|
func (zr *ZRegistry) ImagePullSecretName() string {
|
||||||
|
if zr.Spec.Username == "" || zr.Spec.Password == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return zr.GetName()
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回登陆registry的secret reference,不需要登陆,返回nil
|
||||||
|
func (zr *ZRegistry) ImagePullSecret() *corev1.LocalObjectReference {
|
||||||
|
if zr.Spec.Username == "" || zr.Spec.Password == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &corev1.LocalObjectReference{
|
||||||
|
Name: zr.GetName(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回子资源secret的namespaced name
|
||||||
|
func (zr *ZRegistry) NamespacedNameSecret() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Namespace: zr.GetNamespace(),
|
||||||
|
Name: zr.GetName(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回子资源secret的name
|
||||||
|
func (zr *ZRegistry) SecreteName() string {
|
||||||
|
return zr.GetName()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func (zr *ZRegistry) Owner() metav1.OwnerReference {
|
||||||
|
bTrue := true
|
||||||
|
return metav1.OwnerReference{
|
||||||
|
Name: zr.GetName(),
|
||||||
|
APIVersion: GroupVersion.Version,
|
||||||
|
Kind: "ZRegistry",
|
||||||
|
UID: zr.GetUID(),
|
||||||
|
Controller: &bTrue,
|
||||||
|
BlockOwnerDeletion: &bTrue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (zr *ZRegistry) ResourceLabels() map[string]string {
|
||||||
|
labels := make(map[string]string)
|
||||||
|
labels["registries.zelda.io"] = zr.GetName()
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回指定namespace的secret
|
||||||
|
func (zr *ZRegistry) NamespacedSecret(namespace string) *corev1.Secret {
|
||||||
|
stringData := make(map[string]string)
|
||||||
|
config := utils.NewDockerConfig(zr.Spec.Server, zr.Spec.Username, zr.Spec.Password)
|
||||||
|
stringData["config.json"] = config.String()
|
||||||
|
stringData[".dockerconfigjson"] = config.String()
|
||||||
|
secret := corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: zr.GetName(),
|
||||||
|
Namespace: namespace,
|
||||||
|
OwnerReferences: []metav1.OwnerReference{
|
||||||
|
zr.Owner(),
|
||||||
|
},
|
||||||
|
Labels: zr.ResourceLabels(),
|
||||||
|
},
|
||||||
|
StringData: stringData,
|
||||||
|
}
|
||||||
|
return &secret
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回registry所在namespace的secrete
|
||||||
|
func (zr *ZRegistry) Secret() *corev1.Secret {
|
||||||
|
return zr.NamespacedSecret(zr.GetNamespace())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (zr *ZRegistry) SecretReference() corev1.LocalObjectReference {
|
||||||
|
return corev1.LocalObjectReference{
|
||||||
|
Name: zr.GetName(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回zuser是否有变更
|
||||||
|
func (zr *ZRegistry) IsSpecChanged() (bool, error) {
|
||||||
|
old := ZRegistry{}
|
||||||
|
latestConfiguration, ok := zr.GetAnnotations()["kubectl.kubernetes.io/last-applied-configuration"]
|
||||||
|
if !ok {
|
||||||
|
return false, fmt.Errorf("not found annotation")
|
||||||
|
}
|
||||||
|
err := json.Unmarshal([]byte(latestConfiguration), &old)
|
||||||
|
if err != nil { //无法获得旧配置
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
oldString, err := json.Marshal(&old.Spec)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
newString, err := json.Marshal(&zr.Spec)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if string(oldString) != string(newString) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||||
|
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||||
|
|
||||||
|
// ZRunTemplateSpec defines the desired state of ZRunTemplate
|
||||||
|
type ZRunTemplateSpec struct {
|
||||||
|
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
|
||||||
|
// Foo is an example field of ZRunTemplate. Edit zruntemplate_types.go to remove/update
|
||||||
|
// Foo string `json:"foo,omitempty"`
|
||||||
|
// corev1.PodSpec `json:",inline"`
|
||||||
|
InitContainers []corev1.Container `json:"initContainers,omitempty"`
|
||||||
|
Containers []corev1.Container `json:"containers,omitempty"`
|
||||||
|
RestartPolicy corev1.RestartPolicy `json:"restartPolicy,omitempty"`
|
||||||
|
// Anffinity *corev1.Affinity `json:"anffinity,omitempty"`
|
||||||
|
Dockerfile string `json:"dockerfile,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZRunTemplateStatus defines the observed state of ZRunTemplate
|
||||||
|
type ZRunTemplateStatus struct {
|
||||||
|
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
//+kubebuilder:subresource:status
|
||||||
|
|
||||||
|
// ZRunTemplate is the Schema for the zruntemplates API
|
||||||
|
type ZRunTemplate struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec ZRunTemplateSpec `json:"spec,omitempty"`
|
||||||
|
Status ZRunTemplateStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// ZRunTemplateList contains a list of ZRunTemplate
|
||||||
|
type ZRunTemplateList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []ZRunTemplate `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ZRunTemplate{}, &ZRunTemplateList{})
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||||
|
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||||
|
|
||||||
|
// ZScriptSpec defines the desired state of ZScript
|
||||||
|
type ZScriptSpec struct {
|
||||||
|
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
|
||||||
|
// Foo is an example field of ZScript. Edit zscript_types.go to remove/update
|
||||||
|
// Foo string `json:"foo,omitempty"`
|
||||||
|
RunSpec RunSpec `json:"runSpec,omitempty"` //run template for the script
|
||||||
|
Path string `json:"path,omitempty"` //script path
|
||||||
|
Project corev1.ObjectReference `json:"project,omitempty"` //存放脚本的项目
|
||||||
|
Branch string `json:"branch,omitempty"` //code branch
|
||||||
|
Env []corev1.EnvVar `json:"env,omitempty"` //env
|
||||||
|
CustomHost corev1.ObjectReference `json:"customHost,omitempty"` //host aliases, link to resource ZCustomHost
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZScriptStatus defines the observed state of ZScript
|
||||||
|
type ZScriptStatus struct {
|
||||||
|
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
//+kubebuilder:subresource:status
|
||||||
|
|
||||||
|
// ZScript is the Schema for the zscripts API
|
||||||
|
type ZScript struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec ZScriptSpec `json:"spec,omitempty"`
|
||||||
|
Status ZScriptStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// ZScriptList contains a list of ZScript
|
||||||
|
type ZScriptList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []ZScript `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ZScript{}, &ZScriptList{})
|
||||||
|
}
|
|
@ -0,0 +1,507 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ycyxuehan/zelda/pkg/utils"
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
batchv1 "k8s.io/api/batch/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||||
|
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||||
|
|
||||||
|
type ServiceSpec struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Ports []corev1.ServicePort `json:"ports,omitempty"`
|
||||||
|
Type corev1.ServiceType `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss *ServiceSpec) ServiceSpec(selector map[string]string) corev1.ServiceSpec {
|
||||||
|
spec := corev1.ServiceSpec{
|
||||||
|
Ports: ss.Ports,
|
||||||
|
Selector: selector,
|
||||||
|
Type: ss.Type,
|
||||||
|
}
|
||||||
|
return spec
|
||||||
|
}
|
||||||
|
|
||||||
|
//Pod status
|
||||||
|
type PodStatus struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Phase corev1.PodPhase `json:"phase,omitempty"`
|
||||||
|
RunAt string `json:"runAt,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PodStatusMap map[string]PodStatus
|
||||||
|
|
||||||
|
//Deployment status
|
||||||
|
type DeploymentStatus struct {
|
||||||
|
AvailableReplicas int32 `json:"availableReplicas,omitempty"`
|
||||||
|
ReadyReplicas int32 `json:"readyReplicas,omitempty"`
|
||||||
|
Replicas int32 `json:"replicas,omitempty"`
|
||||||
|
UpdatedReplicas int32 `json:"updatedReplicas,omitempty"`
|
||||||
|
UnavailableReplicas int32 `json:"unavailableReplicas,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//Job status
|
||||||
|
type JobStatus struct {
|
||||||
|
CompletionTime *metav1.Time `json:"completionTime,omitempty"`
|
||||||
|
Succeeded int32 `json:"succeeded,omitempty"`
|
||||||
|
StartTime *metav1.Time `json:"startTime,omitempty"`
|
||||||
|
Active int32 `json:"active,omitempty"`
|
||||||
|
Failed int32 `json:"failed,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RunSpec struct {
|
||||||
|
Template corev1.ObjectReference `json:"template,omitempty"`
|
||||||
|
Volumes []corev1.Volume `json:"volumes,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZServiceSpec defines the desired state of ZService
|
||||||
|
type ZServiceSpec struct {
|
||||||
|
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
|
||||||
|
// Foo is an example field of ZService. Edit zservice_types.go to remove/update
|
||||||
|
// Foo string `json:"foo,omitempty"`
|
||||||
|
Env []corev1.EnvVar `json:"env,omitempty"`
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
// Volumes []corev1.Volume `json:"volumes,omitempty"`
|
||||||
|
Services []ServiceSpec `json:"services,omitempty"`
|
||||||
|
CustomHost corev1.ObjectReference `json:"customHosts,omitempty"`
|
||||||
|
NodeSelector corev1.NodeSelector `json:"nodeSelector,omitempty"`
|
||||||
|
PodAffinity corev1.PodAffinity `json:"podAffinity,omitempty"`
|
||||||
|
PodAntiAffinity corev1.PodAntiAffinity `json:"podAntiAffinity,omitempty"`
|
||||||
|
Kind string `json:"kind,omitempty"`
|
||||||
|
Creator corev1.ObjectReference `json:"creator,omitempty"`
|
||||||
|
Project corev1.ObjectReference `json:"project,omitempty"`
|
||||||
|
SubProject string `json:"subProject,omitempty"`
|
||||||
|
RunSpec RunSpec `json:"runSpec,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZServiceStatus defines the observed state of ZService
|
||||||
|
type ZServiceStatus struct {
|
||||||
|
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
Branch string `json:"branch,omitempty"`
|
||||||
|
Target string `json:"target,omitempty"`
|
||||||
|
PodStatus PodStatusMap `json:"podStatus,omitempty"`
|
||||||
|
DeploymentStatus DeploymentStatus `json:"deploymentStatus,omitempty"`
|
||||||
|
JobStatus JobStatus `json:"jobStatus,omitempty"`
|
||||||
|
UpdatedAt *metav1.Time `json:"updatedAt,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
//+kubebuilder:subresource:status
|
||||||
|
|
||||||
|
// ZService is the Schema for the zservices API
|
||||||
|
type ZService struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec ZServiceSpec `json:"spec,omitempty"`
|
||||||
|
Status ZServiceStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// ZServiceList contains a list of ZService
|
||||||
|
type ZServiceList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []ZService `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ZService{}, &ZServiceList{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type NewClientObjectOption struct {
|
||||||
|
ZRunTemplateSpec *ZRunTemplateSpec
|
||||||
|
Registry *ZRegistry
|
||||||
|
UserSecrets []corev1.LocalObjectReference
|
||||||
|
HostAlias []corev1.HostAlias
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回子对象的namespaced name
|
||||||
|
func (zs *ZService) NamespacedNameResource() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Namespace: zs.GetNamespace(),
|
||||||
|
Name: zs.GetName(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回runTemplate的namespaced name
|
||||||
|
func (zs *ZService) NamespacedNameRunTemplate() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Namespace: zs.Spec.RunSpec.Template.Namespace,
|
||||||
|
Name: zs.Spec.RunSpec.Template.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回project的namespaced name
|
||||||
|
func (zs *ZService) NamespacedNameProject() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Namespace: zs.Spec.Project.Namespace,
|
||||||
|
Name: zs.Spec.Project.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回CustomHost的namespaced name
|
||||||
|
func (zs *ZService) NamespacedNameCustomHost() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Namespace: zs.Spec.CustomHost.Namespace,
|
||||||
|
Name: zs.Spec.CustomHost.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回user的namespaced name
|
||||||
|
func (zs *ZService) NamespacedNameUser() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Namespace: zs.Spec.Creator.Namespace,
|
||||||
|
Name: zs.Spec.Creator.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回zservice的owner reference
|
||||||
|
func (zs *ZService) Owner() metav1.OwnerReference {
|
||||||
|
bTrue := true
|
||||||
|
return metav1.OwnerReference{
|
||||||
|
Name: zs.GetName(),
|
||||||
|
APIVersion: GroupVersion.Version,
|
||||||
|
Kind: "ZService",
|
||||||
|
UID: zs.GetUID(),
|
||||||
|
Controller: &bTrue,
|
||||||
|
BlockOwnerDeletion: &bTrue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回子资源的labels
|
||||||
|
func (zs *ZService) ResourceLabels() map[string]string {
|
||||||
|
labels := make(map[string]string)
|
||||||
|
labels["zservices.zelda.io"] = zs.GetName()
|
||||||
|
labels["projects.zelda.io"] = zs.Spec.Project.Name
|
||||||
|
labels["projects.selda.io/subproject"] = zs.Spec.SubProject
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回子资源的模板的labels,这里使用不一样的label,防止重复更新状态
|
||||||
|
func (zs *ZService) ResourceTemplateLabels() map[string]string {
|
||||||
|
labels := make(map[string]string)
|
||||||
|
labels["zservices.zelda.io"] = zs.GetName()
|
||||||
|
// labels["projects.zelda.io"] = zs.Spec.Project.Name
|
||||||
|
// labels["projects.selda.io/subproject"] = zs.Spec.SubProject
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回子资源selector
|
||||||
|
func (zs *ZService) Selector() *metav1.LabelSelector {
|
||||||
|
return &metav1.LabelSelector{
|
||||||
|
MatchLabels: zs.ResourceTemplateLabels(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回项目的imagetag
|
||||||
|
func (zs *ZService) ImageTagBase() string {
|
||||||
|
return strings.Join([]string{zs.Spec.SubProject, zs.Spec.Version}, ":")
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新模板中的image为项目的image
|
||||||
|
func (zs *ZService) UpdateContainerImage(image string, contaienrs ...corev1.Container) []corev1.Container {
|
||||||
|
res := []corev1.Container{}
|
||||||
|
for _, c := range contaienrs {
|
||||||
|
if c.Image == "$PROJECT_IMAGE" {
|
||||||
|
c.Image = image
|
||||||
|
}
|
||||||
|
res = append(res, c)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
//合并环境变量
|
||||||
|
func (zs *ZService) MergeContainerEnv(containers ...corev1.Container) []corev1.Container {
|
||||||
|
res := []corev1.Container{}
|
||||||
|
for _, c := range containers {
|
||||||
|
envs := zs.Spec.Env
|
||||||
|
envs = append(envs, c.Env...)
|
||||||
|
mergedEnv := utils.MergeEnv(utils.MergeOverrideByFirst, envs)
|
||||||
|
c.Env = mergedEnv
|
||||||
|
res = append(res, c)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回image tag
|
||||||
|
func (zs *ZService) ImageTag(registry *ZRegistry) string {
|
||||||
|
image := zs.ImageTagBase()
|
||||||
|
if registry != nil {
|
||||||
|
image = registry.FullImageTag(image)
|
||||||
|
}
|
||||||
|
return image
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回pod spec
|
||||||
|
func (zs *ZService) PodSpec(option *NewClientObjectOption) corev1.PodSpec {
|
||||||
|
image := zs.ImageTag(option.Registry)
|
||||||
|
secrets := option.UserSecrets
|
||||||
|
if option.Registry != nil {
|
||||||
|
secrets = append(secrets, corev1.LocalObjectReference{
|
||||||
|
Name: option.Registry.ImagePullSecretName(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
initContainers := zs.UpdateContainerImage(image, option.ZRunTemplateSpec.InitContainers...)
|
||||||
|
containers := zs.UpdateContainerImage(image, option.ZRunTemplateSpec.Containers...)
|
||||||
|
initContainers = zs.MergeContainerEnv(initContainers...)
|
||||||
|
containers = zs.MergeContainerEnv(containers...)
|
||||||
|
|
||||||
|
spec := corev1.PodSpec{
|
||||||
|
InitContainers: initContainers,
|
||||||
|
Containers: containers,
|
||||||
|
ImagePullSecrets: secrets,
|
||||||
|
Volumes: zs.Spec.RunSpec.Volumes,
|
||||||
|
HostAliases: option.HostAlias,
|
||||||
|
}
|
||||||
|
return spec
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回pod template
|
||||||
|
func (zs *ZService) PodTemplateSpec(option *NewClientObjectOption) corev1.PodTemplateSpec {
|
||||||
|
spec := corev1.PodTemplateSpec{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: zs.ResourceTemplateLabels(),
|
||||||
|
},
|
||||||
|
Spec: zs.PodSpec(option),
|
||||||
|
}
|
||||||
|
return spec
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回pod对象
|
||||||
|
func (zs *ZService) Pod(option *NewClientObjectOption) *corev1.Pod {
|
||||||
|
pod := corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: zs.GetName(),
|
||||||
|
Namespace: zs.GetNamespace(),
|
||||||
|
OwnerReferences: []metav1.OwnerReference{
|
||||||
|
zs.Owner(),
|
||||||
|
},
|
||||||
|
Labels: zs.ResourceLabels(),
|
||||||
|
},
|
||||||
|
Spec: zs.PodSpec(option),
|
||||||
|
}
|
||||||
|
return &pod
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回deployment spec
|
||||||
|
func (zs *ZService) DeploymentSpec(option *NewClientObjectOption) appsv1.DeploymentSpec {
|
||||||
|
spec := appsv1.DeploymentSpec{
|
||||||
|
Selector: zs.Selector(),
|
||||||
|
Template: zs.PodTemplateSpec(option),
|
||||||
|
}
|
||||||
|
return spec
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回deployment
|
||||||
|
func (zs *ZService) Deployment(option *NewClientObjectOption) *appsv1.Deployment {
|
||||||
|
spec := zs.DeploymentSpec(option)
|
||||||
|
deployment := appsv1.Deployment{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: zs.GetName(),
|
||||||
|
Namespace: zs.GetNamespace(),
|
||||||
|
OwnerReferences: []metav1.OwnerReference{
|
||||||
|
zs.Owner(),
|
||||||
|
},
|
||||||
|
Labels: zs.ResourceLabels(),
|
||||||
|
},
|
||||||
|
Spec: spec,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &deployment
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回需要创建的service
|
||||||
|
func (zs *ZService) Services() []corev1.Service {
|
||||||
|
services := []corev1.Service{}
|
||||||
|
for _, svc := range zs.Spec.Services {
|
||||||
|
objectMeta := metav1.ObjectMeta{
|
||||||
|
Name: svc.Name,
|
||||||
|
Namespace: zs.GetNamespace(),
|
||||||
|
OwnerReferences: []metav1.OwnerReference{
|
||||||
|
zs.Owner(),
|
||||||
|
},
|
||||||
|
Labels: zs.ResourceLabels(),
|
||||||
|
}
|
||||||
|
service := corev1.Service{
|
||||||
|
ObjectMeta: objectMeta,
|
||||||
|
Spec: svc.ServiceSpec(zs.ResourceTemplateLabels()),
|
||||||
|
}
|
||||||
|
services = append(services, service)
|
||||||
|
}
|
||||||
|
return services
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回JobSpec
|
||||||
|
func (zs *ZService) JobSpec(option *NewClientObjectOption) batchv1.JobSpec {
|
||||||
|
spec := batchv1.JobSpec{
|
||||||
|
Selector: zs.Selector(),
|
||||||
|
Template: zs.PodTemplateSpec(option),
|
||||||
|
}
|
||||||
|
return spec
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回job
|
||||||
|
func (zs *ZService) Job(option *NewClientObjectOption) *batchv1.Job {
|
||||||
|
job := batchv1.Job{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: zs.GetName(),
|
||||||
|
Namespace: zs.GetNamespace(),
|
||||||
|
OwnerReferences: []metav1.OwnerReference{
|
||||||
|
zs.Owner(),
|
||||||
|
},
|
||||||
|
Labels: zs.ResourceLabels(),
|
||||||
|
},
|
||||||
|
Spec: zs.JobSpec(option),
|
||||||
|
}
|
||||||
|
return &job
|
||||||
|
}
|
||||||
|
|
||||||
|
//检查spec是否有变更
|
||||||
|
func (zs *ZService) IsSpecChanged() (bool, error) {
|
||||||
|
oldZService := ZService{}
|
||||||
|
latestConfiguration, ok := zs.GetAnnotations()["kubectl.kubernetes.io/last-applied-configuration"]
|
||||||
|
if !ok {
|
||||||
|
return false, fmt.Errorf("not found annotation")
|
||||||
|
}
|
||||||
|
err := json.Unmarshal([]byte(latestConfiguration), &oldZService)
|
||||||
|
if err != nil { //无法获得旧配置
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
oldString, err := json.Marshal(&oldZService.Spec)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
newString, err := json.Marshal(&zs.Spec)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if string(oldString) != string(newString) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回client object
|
||||||
|
func (zs *ZService) ClientObject(option *NewClientObjectOption) client.Object {
|
||||||
|
switch zs.Spec.Kind {
|
||||||
|
case "Deployment":
|
||||||
|
return zs.Deployment(option)
|
||||||
|
case "Job":
|
||||||
|
return zs.Job(option)
|
||||||
|
case "Pod":
|
||||||
|
return zs.Pod(option)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新状态, 更新deployment
|
||||||
|
func (zs *ZService) UpdateStatusDeployment(name string, status *appsv1.DeploymentStatus) {
|
||||||
|
if status == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
zs.Status.Target = name
|
||||||
|
zs.Status.DeploymentStatus = DeploymentStatus{
|
||||||
|
AvailableReplicas: status.AvailableReplicas,
|
||||||
|
ReadyReplicas: status.ReadyReplicas,
|
||||||
|
Replicas: status.Replicas,
|
||||||
|
UpdatedReplicas: status.UpdatedReplicas,
|
||||||
|
UnavailableReplicas: status.UnavailableReplicas,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新状态,更新job
|
||||||
|
func (zs *ZService) UpdateStatusJob(name string, status *batchv1.JobStatus) {
|
||||||
|
if status == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
zs.Status.Target = name
|
||||||
|
zs.Status.JobStatus = JobStatus{
|
||||||
|
CompletionTime: status.CompletionTime,
|
||||||
|
Succeeded: status.Succeeded,
|
||||||
|
StartTime: status.StartTime,
|
||||||
|
Failed: status.Failed,
|
||||||
|
Active: status.Active,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新状态, 更新pod
|
||||||
|
func (zs *ZService) UpdateStatusPod(name string, status *corev1.PodStatus) {
|
||||||
|
if status == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if zs.Spec.Kind == "Pod" {
|
||||||
|
zs.Status.Target = name
|
||||||
|
}
|
||||||
|
podStatus := PodStatus{
|
||||||
|
Name: name,
|
||||||
|
Phase: status.Phase,
|
||||||
|
RunAt: status.HostIP,
|
||||||
|
Message: status.Message,
|
||||||
|
}
|
||||||
|
zs.Status.PodStatus[name] = podStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新状态
|
||||||
|
func (zs *ZService) UpdateStatus(managedResource client.Object) error {
|
||||||
|
switch zs.Spec.Kind {
|
||||||
|
case "Deployment":
|
||||||
|
dp, ok := managedResource.(*appsv1.Deployment)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("object type error, it not a deployment")
|
||||||
|
}
|
||||||
|
zs.UpdateStatusDeployment(dp.GetName(), dp.Status.DeepCopy())
|
||||||
|
case "Job":
|
||||||
|
job, ok := managedResource.(*batchv1.Job)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("object type error, it not a deployment")
|
||||||
|
}
|
||||||
|
zs.UpdateStatusJob(job.GetName(), job.Status.DeepCopy())
|
||||||
|
case "Pod":
|
||||||
|
pod, ok := managedResource.(*corev1.Pod)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("object type error, it not a deployment")
|
||||||
|
}
|
||||||
|
zs.UpdateStatusPod(pod.GetName(), pod.Status.DeepCopy())
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unkown kind")
|
||||||
|
}
|
||||||
|
now := metav1.Now()
|
||||||
|
zs.Status.UpdatedAt = &now
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,223 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ycyxuehan/zelda/pkg/utils"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||||
|
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||||
|
|
||||||
|
// ZUserSpec defines the desired state of ZUser
|
||||||
|
type ZUserSpec struct {
|
||||||
|
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
|
||||||
|
// Foo is an example field of ZUser. Edit zuser_types.go to remove/update
|
||||||
|
// Foo string `json:"foo,omitempty"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
Group string `json:"group,omitempty"`
|
||||||
|
NotifyMedia string `json:"notifyMedia,omitempty"` //user接收消息的媒介
|
||||||
|
Secrets []corev1.ObjectReference `json:"secrets,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZUserStatus defines the observed state of ZUser
|
||||||
|
type ZUserStatus struct {
|
||||||
|
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||||
|
// Important: Run "make" to regenerate code after modifying this file
|
||||||
|
CreatedAt *metav1.Time `json:"createdAt,omitempty"`
|
||||||
|
Token string `json:"token,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
//+kubebuilder:subresource:status
|
||||||
|
|
||||||
|
// ZUser is the Schema for the zusers API
|
||||||
|
type ZUser struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec ZUserSpec `json:"spec,omitempty"`
|
||||||
|
Status ZUserStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//+kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// ZUserList contains a list of ZUser
|
||||||
|
type ZUserList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []ZUser `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ZUser{}, &ZUserList{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (zu *ZUser) Owner() metav1.OwnerReference {
|
||||||
|
bTrue := true
|
||||||
|
return metav1.OwnerReference{
|
||||||
|
Name: zu.GetName(),
|
||||||
|
APIVersion: GroupVersion.Version,
|
||||||
|
Kind: "ZUser",
|
||||||
|
UID: zu.GetUID(),
|
||||||
|
Controller: &bTrue,
|
||||||
|
BlockOwnerDeletion: &bTrue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (zu *ZUser) ResourceLabels() map[string]string {
|
||||||
|
labels := make(map[string]string)
|
||||||
|
labels["users.zelda.io"] = zu.GetName()
|
||||||
|
labels["groups.zelda.io"] = zu.Spec.Group
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回zgroup的namespacedname
|
||||||
|
func (zu *ZUser) NamespacedNameGroup() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Namespace: zu.GetNamespace(),
|
||||||
|
Name: zu.Spec.Group,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回zgroup的namespacedname
|
||||||
|
func (zu *ZUser) NamespacedNameServiceAccount() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Namespace: zu.GetNamespace(),
|
||||||
|
Name: zu.GetName(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回zgroup的namespacedname
|
||||||
|
func (zu *ZUser) NamespacedNameRoleBinding() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Namespace: zu.GetNamespace(),
|
||||||
|
Name: zu.GetName(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回zgroup的namespacedname
|
||||||
|
func (zu *ZUser) NamespacedNameClusterRoleBinding() types.NamespacedName {
|
||||||
|
return types.NamespacedName{
|
||||||
|
Name: zu.GetName(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回user对应的ServiceAccount
|
||||||
|
func (zu *ZUser) ServiceAccount(groupSecrets []corev1.ObjectReference) *corev1.ServiceAccount {
|
||||||
|
secrets, _ := utils.MergeObjectReferences(utils.MergeOverrideByLatest, groupSecrets, zu.Spec.Secrets) //这里忽略错误,因为mergetype不可能出错
|
||||||
|
sa := corev1.ServiceAccount{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: zu.GetName(),
|
||||||
|
Namespace: zu.GetNamespace(),
|
||||||
|
OwnerReferences: []metav1.OwnerReference{
|
||||||
|
zu.Owner(),
|
||||||
|
},
|
||||||
|
Labels: zu.ResourceLabels(),
|
||||||
|
},
|
||||||
|
Secrets: secrets,
|
||||||
|
}
|
||||||
|
return &sa
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回ServiceAccount的RoleBinding
|
||||||
|
func (zu *ZUser) RoleBinding() *rbacv1.RoleBinding {
|
||||||
|
roleBinding := rbacv1.RoleBinding{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: zu.GetName(),
|
||||||
|
Namespace: zu.GetNamespace(),
|
||||||
|
OwnerReferences: []metav1.OwnerReference{
|
||||||
|
zu.Owner(),
|
||||||
|
},
|
||||||
|
Labels: zu.ResourceLabels(),
|
||||||
|
},
|
||||||
|
Subjects: []rbacv1.Subject{
|
||||||
|
{
|
||||||
|
Kind: rbacv1.ServiceAccountKind,
|
||||||
|
Namespace: zu.GetNamespace(),
|
||||||
|
Name: zu.GetName(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RoleRef: rbacv1.RoleRef{
|
||||||
|
APIGroup: rbacv1.GroupName,
|
||||||
|
Kind: "Role",
|
||||||
|
Name: zu.Spec.Group,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &roleBinding
|
||||||
|
}
|
||||||
|
|
||||||
|
//ServiceAccount的ClusterRoleBinding
|
||||||
|
func (zu *ZUser) ClusterRoleBinding() *rbacv1.ClusterRoleBinding {
|
||||||
|
roleBinding := rbacv1.ClusterRoleBinding{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: zu.GetName(),
|
||||||
|
OwnerReferences: []metav1.OwnerReference{
|
||||||
|
zu.Owner(),
|
||||||
|
},
|
||||||
|
Labels: zu.ResourceLabels(),
|
||||||
|
},
|
||||||
|
Subjects: []rbacv1.Subject{
|
||||||
|
{
|
||||||
|
Kind: rbacv1.ServiceAccountKind,
|
||||||
|
Namespace: zu.GetNamespace(),
|
||||||
|
Name: zu.GetName(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RoleRef: rbacv1.RoleRef{
|
||||||
|
APIGroup: rbacv1.GroupName,
|
||||||
|
Kind: "ClusterRole",
|
||||||
|
Name: zu.Spec.Group,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &roleBinding
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回zuser是否有变更
|
||||||
|
func (zu *ZUser) IsSpecChanged() (bool, error) {
|
||||||
|
old := ZUser{}
|
||||||
|
latestConfiguration, ok := zu.GetAnnotations()["kubectl.kubernetes.io/last-applied-configuration"]
|
||||||
|
if !ok {
|
||||||
|
return false, fmt.Errorf("not found annotation")
|
||||||
|
}
|
||||||
|
err := json.Unmarshal([]byte(latestConfiguration), &old)
|
||||||
|
if err != nil { //无法获得旧配置
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
oldString, err := json.Marshal(&old.Spec)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
newString, err := json.Marshal(&zu.Spec)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if string(oldString) != string(newString) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
|
@ -0,0 +1,915 @@
|
||||||
|
//go:build !ignore_autogenerated
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Code generated by controller-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZBuildTemplate) DeepCopyInto(out *ZBuildTemplate) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
out.Spec = in.Spec
|
||||||
|
out.Status = in.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZBuildTemplate.
|
||||||
|
func (in *ZBuildTemplate) DeepCopy() *ZBuildTemplate {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZBuildTemplate)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZBuildTemplate) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZBuildTemplateList) DeepCopyInto(out *ZBuildTemplateList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]ZBuildTemplate, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZBuildTemplateList.
|
||||||
|
func (in *ZBuildTemplateList) DeepCopy() *ZBuildTemplateList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZBuildTemplateList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZBuildTemplateList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZBuildTemplateSpec) DeepCopyInto(out *ZBuildTemplateSpec) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZBuildTemplateSpec.
|
||||||
|
func (in *ZBuildTemplateSpec) DeepCopy() *ZBuildTemplateSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZBuildTemplateSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZBuildTemplateStatus) DeepCopyInto(out *ZBuildTemplateStatus) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZBuildTemplateStatus.
|
||||||
|
func (in *ZBuildTemplateStatus) DeepCopy() *ZBuildTemplateStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZBuildTemplateStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZBuilder) DeepCopyInto(out *ZBuilder) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
out.Spec = in.Spec
|
||||||
|
out.Status = in.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZBuilder.
|
||||||
|
func (in *ZBuilder) DeepCopy() *ZBuilder {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZBuilder)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZBuilder) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZBuilderList) DeepCopyInto(out *ZBuilderList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]ZBuilder, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZBuilderList.
|
||||||
|
func (in *ZBuilderList) DeepCopy() *ZBuilderList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZBuilderList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZBuilderList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZBuilderSpec) DeepCopyInto(out *ZBuilderSpec) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZBuilderSpec.
|
||||||
|
func (in *ZBuilderSpec) DeepCopy() *ZBuilderSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZBuilderSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZBuilderStatus) DeepCopyInto(out *ZBuilderStatus) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZBuilderStatus.
|
||||||
|
func (in *ZBuilderStatus) DeepCopy() *ZBuilderStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZBuilderStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZCustomHost) DeepCopyInto(out *ZCustomHost) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
out.Spec = in.Spec
|
||||||
|
out.Status = in.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZCustomHost.
|
||||||
|
func (in *ZCustomHost) DeepCopy() *ZCustomHost {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZCustomHost)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZCustomHost) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZCustomHostList) DeepCopyInto(out *ZCustomHostList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]ZCustomHost, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZCustomHostList.
|
||||||
|
func (in *ZCustomHostList) DeepCopy() *ZCustomHostList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZCustomHostList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZCustomHostList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZCustomHostSpec) DeepCopyInto(out *ZCustomHostSpec) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZCustomHostSpec.
|
||||||
|
func (in *ZCustomHostSpec) DeepCopy() *ZCustomHostSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZCustomHostSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZCustomHostStatus) DeepCopyInto(out *ZCustomHostStatus) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZCustomHostStatus.
|
||||||
|
func (in *ZCustomHostStatus) DeepCopy() *ZCustomHostStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZCustomHostStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZGroup) DeepCopyInto(out *ZGroup) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
out.Spec = in.Spec
|
||||||
|
out.Status = in.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZGroup.
|
||||||
|
func (in *ZGroup) DeepCopy() *ZGroup {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZGroup)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZGroup) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZGroupList) DeepCopyInto(out *ZGroupList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]ZGroup, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZGroupList.
|
||||||
|
func (in *ZGroupList) DeepCopy() *ZGroupList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZGroupList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZGroupList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZGroupSpec) DeepCopyInto(out *ZGroupSpec) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZGroupSpec.
|
||||||
|
func (in *ZGroupSpec) DeepCopy() *ZGroupSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZGroupSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZGroupStatus) DeepCopyInto(out *ZGroupStatus) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZGroupStatus.
|
||||||
|
func (in *ZGroupStatus) DeepCopy() *ZGroupStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZGroupStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZProject) DeepCopyInto(out *ZProject) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
out.Spec = in.Spec
|
||||||
|
out.Status = in.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZProject.
|
||||||
|
func (in *ZProject) DeepCopy() *ZProject {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZProject)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZProject) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZProjectList) DeepCopyInto(out *ZProjectList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]ZProject, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZProjectList.
|
||||||
|
func (in *ZProjectList) DeepCopy() *ZProjectList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZProjectList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZProjectList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZProjectSpec) DeepCopyInto(out *ZProjectSpec) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZProjectSpec.
|
||||||
|
func (in *ZProjectSpec) DeepCopy() *ZProjectSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZProjectSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZProjectStatus) DeepCopyInto(out *ZProjectStatus) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZProjectStatus.
|
||||||
|
func (in *ZProjectStatus) DeepCopy() *ZProjectStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZProjectStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZRegistry) DeepCopyInto(out *ZRegistry) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
out.Spec = in.Spec
|
||||||
|
out.Status = in.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZRegistry.
|
||||||
|
func (in *ZRegistry) DeepCopy() *ZRegistry {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZRegistry)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZRegistry) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZRegistryList) DeepCopyInto(out *ZRegistryList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]ZRegistry, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZRegistryList.
|
||||||
|
func (in *ZRegistryList) DeepCopy() *ZRegistryList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZRegistryList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZRegistryList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZRegistrySpec) DeepCopyInto(out *ZRegistrySpec) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZRegistrySpec.
|
||||||
|
func (in *ZRegistrySpec) DeepCopy() *ZRegistrySpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZRegistrySpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZRegistryStatus) DeepCopyInto(out *ZRegistryStatus) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZRegistryStatus.
|
||||||
|
func (in *ZRegistryStatus) DeepCopy() *ZRegistryStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZRegistryStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZRunTemplate) DeepCopyInto(out *ZRunTemplate) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
out.Spec = in.Spec
|
||||||
|
out.Status = in.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZRunTemplate.
|
||||||
|
func (in *ZRunTemplate) DeepCopy() *ZRunTemplate {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZRunTemplate)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZRunTemplate) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZRunTemplateList) DeepCopyInto(out *ZRunTemplateList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]ZRunTemplate, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZRunTemplateList.
|
||||||
|
func (in *ZRunTemplateList) DeepCopy() *ZRunTemplateList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZRunTemplateList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZRunTemplateList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZRunTemplateSpec) DeepCopyInto(out *ZRunTemplateSpec) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZRunTemplateSpec.
|
||||||
|
func (in *ZRunTemplateSpec) DeepCopy() *ZRunTemplateSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZRunTemplateSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZRunTemplateStatus) DeepCopyInto(out *ZRunTemplateStatus) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZRunTemplateStatus.
|
||||||
|
func (in *ZRunTemplateStatus) DeepCopy() *ZRunTemplateStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZRunTemplateStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZScript) DeepCopyInto(out *ZScript) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
out.Spec = in.Spec
|
||||||
|
out.Status = in.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZScript.
|
||||||
|
func (in *ZScript) DeepCopy() *ZScript {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZScript)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZScript) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZScriptList) DeepCopyInto(out *ZScriptList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]ZScript, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZScriptList.
|
||||||
|
func (in *ZScriptList) DeepCopy() *ZScriptList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZScriptList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZScriptList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZScriptSpec) DeepCopyInto(out *ZScriptSpec) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZScriptSpec.
|
||||||
|
func (in *ZScriptSpec) DeepCopy() *ZScriptSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZScriptSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZScriptStatus) DeepCopyInto(out *ZScriptStatus) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZScriptStatus.
|
||||||
|
func (in *ZScriptStatus) DeepCopy() *ZScriptStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZScriptStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZService) DeepCopyInto(out *ZService) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
out.Spec = in.Spec
|
||||||
|
out.Status = in.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZService.
|
||||||
|
func (in *ZService) DeepCopy() *ZService {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZService)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZService) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZServiceList) DeepCopyInto(out *ZServiceList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]ZService, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZServiceList.
|
||||||
|
func (in *ZServiceList) DeepCopy() *ZServiceList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZServiceList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZServiceList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZServiceSpec) DeepCopyInto(out *ZServiceSpec) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZServiceSpec.
|
||||||
|
func (in *ZServiceSpec) DeepCopy() *ZServiceSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZServiceSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZServiceStatus) DeepCopyInto(out *ZServiceStatus) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZServiceStatus.
|
||||||
|
func (in *ZServiceStatus) DeepCopy() *ZServiceStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZServiceStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZUser) DeepCopyInto(out *ZUser) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
out.Spec = in.Spec
|
||||||
|
out.Status = in.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZUser.
|
||||||
|
func (in *ZUser) DeepCopy() *ZUser {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZUser)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZUser) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZUserList) DeepCopyInto(out *ZUserList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]ZUser, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZUserList.
|
||||||
|
func (in *ZUserList) DeepCopy() *ZUserList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZUserList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ZUserList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZUserSpec) DeepCopyInto(out *ZUserSpec) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZUserSpec.
|
||||||
|
func (in *ZUserSpec) DeepCopy() *ZUserSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZUserSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ZUserStatus) DeepCopyInto(out *ZUserStatus) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZUserStatus.
|
||||||
|
func (in *ZUserStatus) DeepCopy() *ZUserStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ZUserStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package apiserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
zeldaiov1alpha1 "github.com/ycyxuehan/zelda/api/v1alpha1"
|
||||||
|
authapi "github.com/ycyxuehan/zelda/apiserver/auth/api"
|
||||||
|
proxyapi "github.com/ycyxuehan/zelda/apiserver/proxy/api"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
kubeclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
type APIServer struct {
|
||||||
|
client kubeclient.Client
|
||||||
|
authManager authapi.AuthManager
|
||||||
|
proxies []proxyapi.Proxy
|
||||||
|
namesapce string
|
||||||
|
zserviceHandler *ZServiceHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAPIServer(client kubeclient.Client, authManager authapi.AuthManager) *APIServer {
|
||||||
|
server := &APIServer{
|
||||||
|
client: client,
|
||||||
|
authManager: authManager,
|
||||||
|
zserviceHandler: NewZServiceHandler(client),
|
||||||
|
}
|
||||||
|
server.setNamespace()
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *APIServer) setNamespace() error {
|
||||||
|
data, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
|
||||||
|
a.namesapce = string(data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *APIServer) UseProxies(proxies ...proxyapi.Proxy) {
|
||||||
|
a.proxies = append(a.proxies, proxies...)
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置路由
|
||||||
|
func (a *APIServer) SetRoute(engine *gin.Engine) {
|
||||||
|
//添加认证接口
|
||||||
|
authGroup := engine.Group("/auth")
|
||||||
|
a.authManager.InitAuthRoute(a.IdentifyFunc(), authGroup)
|
||||||
|
//添加代理接口
|
||||||
|
for _, proxy := range a.proxies {
|
||||||
|
proxyGroup := engine.Group(proxy.Path())
|
||||||
|
proxyGroup.Use(a.authManager.MiddleWare())
|
||||||
|
proxyGroup.GET("/", proxy.Proxy())
|
||||||
|
proxyGroup.PUT("/", proxy.Proxy())
|
||||||
|
proxyGroup.POST("/", proxy.Proxy())
|
||||||
|
proxyGroup.PATCH("/", proxy.Proxy())
|
||||||
|
proxyGroup.DELETE("/", proxy.Proxy())
|
||||||
|
proxyGroup.OPTIONS("/", proxy.Proxy())
|
||||||
|
}
|
||||||
|
//添加服务接口
|
||||||
|
apiGroup := engine.Group("/api/v1alpha1")
|
||||||
|
apiGroup.Use(a.authManager.MiddleWare())
|
||||||
|
|
||||||
|
//zservice
|
||||||
|
zserviceGroup := apiGroup.Group("/zservice")
|
||||||
|
zserviceGroup.GET("/:name/restart", a.zserviceHandler.HandleRestart)
|
||||||
|
zserviceGroup.GET("/:name/start", a.zserviceHandler.HandleStart)
|
||||||
|
zserviceGroup.GET("/:name/stop", a.zserviceHandler.HandleStop)
|
||||||
|
zserviceGroup.POST("/:name/scale", a.zserviceHandler.HandleScale)
|
||||||
|
zserviceGroup.POST("/:name/version", a.zserviceHandler.HandleChangeVersion)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *APIServer) IdentifyFunc() authapi.IdentifyFunc {
|
||||||
|
return func(ar *authapi.AuthentitionRequest) (authapi.IdentifyResult, error) {
|
||||||
|
zuser := zeldaiov1alpha1.ZUser{}
|
||||||
|
err := a.client.Get(context.Background(), kubeclient.ObjectKey{Namespace: a.namesapce, Name: ar.Username}, &zuser)
|
||||||
|
if err != nil {
|
||||||
|
return authapi.IdentifyResult{}, err
|
||||||
|
}
|
||||||
|
if ar.Password != zuser.Spec.Password {
|
||||||
|
return authapi.IdentifyResult{}, fmt.Errorf("password is invalid")
|
||||||
|
}
|
||||||
|
//密码验证通过,获取kubernetes token
|
||||||
|
secret := corev1.Secret{}
|
||||||
|
err = a.client.Get(context.Background(), kubeclient.ObjectKey{Namespace: a.namesapce, Name: zuser.Status.Token}, &secret)
|
||||||
|
if err != nil {
|
||||||
|
return authapi.IdentifyResult{}, err
|
||||||
|
}
|
||||||
|
//这里处理证书和token
|
||||||
|
return authapi.IdentifyResult{KubernetesToken: secret.StringData["token"], Cert: secret.StringData["ca.crt"]}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *APIServer)Run(addr string)error{
|
||||||
|
engine := gin.Default()
|
||||||
|
a.SetRoute(engine)
|
||||||
|
return engine.Run(addr)
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import "github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
type AuthentitionRequest struct {
|
||||||
|
ClientID string `json:"clientID,omitempty"`
|
||||||
|
Username string `json:"username,omitempty"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
// Namespace string `json:"namespace,omitempty"`
|
||||||
|
Token string `json:"token,omitempty"`
|
||||||
|
Group string
|
||||||
|
KubernetesToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthentitionResponse struct {
|
||||||
|
Token string `json:"token,omitempty"`
|
||||||
|
// Username string `json:"username,omitempty"`
|
||||||
|
// Group string `json:"group,omitempty"`
|
||||||
|
Error error `json:"error,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IdentifyResult struct {
|
||||||
|
KubernetesToken string
|
||||||
|
Cert string
|
||||||
|
}
|
||||||
|
|
||||||
|
//验证账号密码的方法,这里想把这一块单独剥离出去,这样不同的auth就更加抽象化
|
||||||
|
//返回值分别是 kubernetes token,
|
||||||
|
type IdentifyFunc func(*AuthentitionRequest) (IdentifyResult, error)
|
||||||
|
|
||||||
|
type AuthManager interface {
|
||||||
|
Login(IdentifyFunc, *AuthentitionRequest) *AuthentitionResponse
|
||||||
|
Logout(*AuthentitionRequest) *AuthentitionResponse
|
||||||
|
Refresh(*AuthentitionRequest) *AuthentitionResponse
|
||||||
|
KubernetesToken(*AuthentitionRequest) (string, error)
|
||||||
|
MiddleWare() gin.HandlerFunc
|
||||||
|
InitAuthRoute(IdentifyFunc, *gin.RouterGroup)
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package jwt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/ycyxuehan/zelda/apiserver/auth/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
//登录
|
||||||
|
func (m *manager) HandlerLogin(identifyFunc api.IdentifyFunc) gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
authRequest := api.AuthentitionRequest{}
|
||||||
|
err := c.Bind(&authRequest)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, &api.AuthentitionResponse{Error: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp := m.Login(identifyFunc, &authRequest)
|
||||||
|
c.JSON(http.StatusOK, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//登出
|
||||||
|
func (m *manager) HandlerLogout() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
authRequest := api.AuthentitionRequest{}
|
||||||
|
err := c.Bind(&authRequest)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, &api.AuthentitionResponse{Error: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp := m.Logout(&authRequest)
|
||||||
|
c.JSON(http.StatusOK, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//刷新token
|
||||||
|
func (m *manager) HandlerRefreshToken() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
authRequest := api.AuthentitionRequest{}
|
||||||
|
err := c.Bind(&authRequest)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK, &api.AuthentitionResponse{Error: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp := m.Refresh(&authRequest)
|
||||||
|
c.JSON(http.StatusOK, resp)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,231 @@
|
||||||
|
package jwt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
gojwt "github.com/golang-jwt/jwt"
|
||||||
|
"github.com/ycyxuehan/zelda/apiserver/auth/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TokenClaim struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Group string `json:"group"`
|
||||||
|
gojwt.StandardClaims
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TokenClaim) Expired() bool {
|
||||||
|
return t.ExpiresAt <= time.Now().Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
type tokenCache struct {
|
||||||
|
kubernetesToken string
|
||||||
|
claim *TokenClaim
|
||||||
|
cert string
|
||||||
|
}
|
||||||
|
|
||||||
|
type manager struct {
|
||||||
|
tokenStore map[string]tokenCache
|
||||||
|
secret string
|
||||||
|
term time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewManager(secret string, term time.Duration) api.AuthManager {
|
||||||
|
m := manager{
|
||||||
|
tokenStore: make(map[string]tokenCache),
|
||||||
|
secret: secret,
|
||||||
|
term: term,
|
||||||
|
}
|
||||||
|
return &m
|
||||||
|
}
|
||||||
|
|
||||||
|
//登录
|
||||||
|
func (m *manager) Login(f api.IdentifyFunc, data *api.AuthentitionRequest) *api.AuthentitionResponse {
|
||||||
|
if _, ok := m.IsLogined(data.Username); ok {
|
||||||
|
return &api.AuthentitionResponse{Error: fmt.Errorf("user is already logined"), Code: 1000}
|
||||||
|
}
|
||||||
|
res, err := f(data)
|
||||||
|
if err != nil {
|
||||||
|
return &api.AuthentitionResponse{Error: err, Code: 1001}
|
||||||
|
}
|
||||||
|
tokenClaim, err := m.GenerateTokenClaim(data)
|
||||||
|
if err != nil {
|
||||||
|
return &api.AuthentitionResponse{Error: err, Code: 1002}
|
||||||
|
}
|
||||||
|
tokenString, err := m.GenerateToken(tokenClaim)
|
||||||
|
if err != nil {
|
||||||
|
return &api.AuthentitionResponse{Error: err, Code: 1003}
|
||||||
|
}
|
||||||
|
//存储登录状态
|
||||||
|
m.StoreLoginState(data.Username, res, tokenClaim)
|
||||||
|
|
||||||
|
return &api.AuthentitionResponse{Token: tokenString}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *manager) Logout(data *api.AuthentitionRequest) *api.AuthentitionResponse {
|
||||||
|
//解析token,确认有logout权限
|
||||||
|
claim, err := m.ParseTokenClaim(data.Token)
|
||||||
|
if err != nil {
|
||||||
|
return &api.AuthentitionResponse{Error: err, Code: 1004}
|
||||||
|
|
||||||
|
}
|
||||||
|
if c, ok := m.IsLogined(claim.Username); ok {
|
||||||
|
if claim.ExpiresAt == c.ExpiresAt {
|
||||||
|
delete(m.tokenStore, data.Username)
|
||||||
|
return &api.AuthentitionResponse{Message: "success"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &api.AuthentitionResponse{Error: fmt.Errorf("user not login or token invalid"), Code: 1005}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *manager) Refresh(data *api.AuthentitionRequest) *api.AuthentitionResponse {
|
||||||
|
cliam, err := m.ParseTokenClaim(data.Token)
|
||||||
|
if err != nil {
|
||||||
|
return &api.AuthentitionResponse{Error: err, Code: 1006}
|
||||||
|
}
|
||||||
|
//已过期
|
||||||
|
if cliam.Valid() != nil {
|
||||||
|
return &api.AuthentitionResponse{Error: fmt.Errorf("cannot use an invalid token to refresh: %v", err), Code: 1007}
|
||||||
|
|
||||||
|
}
|
||||||
|
//找不到登陆状态
|
||||||
|
if _, ok := m.IsLogined(cliam.Username); !ok {
|
||||||
|
return &api.AuthentitionResponse{Error: fmt.Errorf("token invalid, user maybe not login"), Code: 1005}
|
||||||
|
|
||||||
|
}
|
||||||
|
//重置有效期
|
||||||
|
cliam.ExpiresAt = time.Now().Add(m.term).Unix()
|
||||||
|
m.ReSetTokenClaim(cliam)
|
||||||
|
|
||||||
|
tokenStr, err := m.GenerateToken(cliam)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return &api.AuthentitionResponse{Error: err, Code: 1003}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.AuthentitionResponse{Token: tokenStr}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *manager) KubernetesToken(data *api.AuthentitionRequest) (string, error) {
|
||||||
|
if t, ok := m.tokenStore[data.Username]; ok {
|
||||||
|
return t.kubernetesToken, nil
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *manager) KubernetesCert(data *api.AuthentitionRequest) (string, error) {
|
||||||
|
if t, ok := m.tokenStore[data.Username]; ok {
|
||||||
|
return t.cert, nil
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成token claim对象
|
||||||
|
func (m *manager) GenerateTokenClaim(data *api.AuthentitionRequest) (*TokenClaim, error) {
|
||||||
|
now := time.Now()
|
||||||
|
claim := TokenClaim{
|
||||||
|
Username: data.Username,
|
||||||
|
Group: data.Group,
|
||||||
|
StandardClaims: gojwt.StandardClaims{
|
||||||
|
ExpiresAt: now.Add(m.term).Unix(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &claim, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//从string解析token claim
|
||||||
|
func (m *manager) ParseTokenClaim(token string) (*TokenClaim, error) {
|
||||||
|
tokenClaims, err := gojwt.ParseWithClaims(token, &TokenClaim{}, func(token *gojwt.Token) (interface{}, error) {
|
||||||
|
return m.secret, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if tokenClaims != nil {
|
||||||
|
if claims, ok := tokenClaims.Claims.(*TokenClaim); ok && tokenClaims.Valid {
|
||||||
|
return claims, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//从token claim 生成 string token
|
||||||
|
func (m *manager) GenerateToken(claim *TokenClaim) (string, error) {
|
||||||
|
tokenClaims := gojwt.NewWithClaims(gojwt.SigningMethodHS256, claim)
|
||||||
|
token, err := tokenClaims.SignedString(m.secret)
|
||||||
|
return token, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//存储登录状态
|
||||||
|
func (m *manager) StoreLoginState(user string, result api.IdentifyResult, claim *TokenClaim) {
|
||||||
|
//储存登录状态
|
||||||
|
t := tokenCache{
|
||||||
|
kubernetesToken: result.KubernetesToken,
|
||||||
|
claim: claim,
|
||||||
|
cert: result.Cert,
|
||||||
|
}
|
||||||
|
m.tokenStore[user] = t
|
||||||
|
}
|
||||||
|
|
||||||
|
//是否已登录
|
||||||
|
func (m *manager) IsLogined(user string) (*TokenClaim, bool) {
|
||||||
|
t, ok := m.tokenStore[user]
|
||||||
|
if ok {
|
||||||
|
return t.claim, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
//重置token状态
|
||||||
|
func (m *manager) ReSetTokenClaim(claim *TokenClaim) {
|
||||||
|
if t, ok := m.tokenStore[claim.Username]; ok {
|
||||||
|
t.claim = claim
|
||||||
|
m.tokenStore[claim.Username] = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//token是否有效
|
||||||
|
func (m *manager) TokenValid(claim *TokenClaim) bool {
|
||||||
|
if t, ok := m.tokenStore[claim.Username]; ok {
|
||||||
|
if t.claim.ExpiresAt == claim.ExpiresAt && claim.Valid() == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//中间件
|
||||||
|
func (m *manager) MiddleWare() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
tokenString := c.GetHeader("AccessToken")
|
||||||
|
if tokenString == "" {
|
||||||
|
c.AbortWithStatus(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tokenClaim, err := m.ParseTokenClaim(tokenString)
|
||||||
|
if err != nil {
|
||||||
|
c.AbortWithError(http.StatusUnauthorized, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if m.TokenValid(tokenClaim) {
|
||||||
|
c.AbortWithError(http.StatusUnauthorized, fmt.Errorf("token invalid"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t, err := m.KubernetesToken(&api.AuthentitionRequest{Username: tokenClaim.Username})
|
||||||
|
if err != nil || t == "" {
|
||||||
|
c.AbortWithError(http.StatusUnauthorized, fmt.Errorf("k8s token not found"))
|
||||||
|
}
|
||||||
|
c.Request.Header.Set("Authorization", fmt.Sprintf("bearer %s", t))
|
||||||
|
cert, _ := m.KubernetesCert(&api.AuthentitionRequest{Username: tokenClaim.Username})
|
||||||
|
c.Request.Header.Set("cert", cert)
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//初始化auth接口
|
||||||
|
func (m *manager) InitAuthRoute(identifyFunc api.IdentifyFunc, authGroup *gin.RouterGroup) {
|
||||||
|
authGroup.POST("/login", m.HandlerLogin(identifyFunc))
|
||||||
|
authGroup.POST("/logout", m.HandlerLogout())
|
||||||
|
authGroup.POST("/refresh", m.HandlerRefreshToken())
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
//这是使用官方例子改的, 试试能不能接上微信
|
||||||
|
package oauth2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-oauth2/oauth2/v4/generates"
|
||||||
|
"github.com/go-oauth2/oauth2/v4/manage"
|
||||||
|
"github.com/go-oauth2/oauth2/v4/models"
|
||||||
|
"github.com/go-oauth2/oauth2/v4/store"
|
||||||
|
"github.com/ycyxuehan/zelda/apiserver/auth/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OAuth2 struct {
|
||||||
|
oauth2Manager *manage.Manager
|
||||||
|
clientStore *store.ClientStore
|
||||||
|
id string
|
||||||
|
secret string
|
||||||
|
domain string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewManager(id, secret, domain string) (api.AuthManager, error) {
|
||||||
|
o2 := &OAuth2{
|
||||||
|
id: id,
|
||||||
|
secret: secret,
|
||||||
|
domain: domain,
|
||||||
|
}
|
||||||
|
|
||||||
|
o2.createStore()
|
||||||
|
o2.createManager()
|
||||||
|
|
||||||
|
return o2, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OAuth2) createStore() {
|
||||||
|
clientStore := store.NewClientStore()
|
||||||
|
clientStore.Set(o.id, &models.Client{
|
||||||
|
ID: o.id,
|
||||||
|
Secret: o.secret,
|
||||||
|
Domain: o.domain,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OAuth2) createManager() {
|
||||||
|
o.oauth2Manager = manage.NewDefaultManager()
|
||||||
|
o.oauth2Manager.SetAuthorizeCodeTokenCfg(manage.DefaultAuthorizeCodeTokenCfg)
|
||||||
|
|
||||||
|
// token store
|
||||||
|
o.oauth2Manager.MustTokenStorage(store.NewMemoryTokenStore())
|
||||||
|
|
||||||
|
// generate jwt access token
|
||||||
|
// manager.MapAccessGenerate(generates.NewJWTAccessGenerate("", []byte("00000000"), jwt.SigningMethodHS512))
|
||||||
|
o.oauth2Manager.MapAccessGenerate(generates.NewAccessGenerate())
|
||||||
|
o.oauth2Manager.MapClientStorage(o.clientStore)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OAuth2) Login(f api.IdentifyFunc, data *api.AuthentitionRequest) *api.AuthentitionResponse {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OAuth2) Logout(*api.AuthentitionRequest) *api.AuthentitionResponse {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OAuth2) Refresh(*api.AuthentitionRequest) *api.AuthentitionResponse {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OAuth2) KubernetesToken(*api.AuthentitionRequest) (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OAuth2) MiddleWare() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
//初始化auth接口
|
||||||
|
func (o *OAuth2) InitAuthRoute(identifyFunc api.IdentifyFunc, authGroup *gin.RouterGroup) {
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
package zbuilder
|
|
@ -0,0 +1,11 @@
|
||||||
|
package zservice
|
||||||
|
|
||||||
|
import kubeclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
|
type Controller interface {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(client kubeclient.Client) Controller {
|
||||||
|
return &ctrl{client: client}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package zservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
kubeclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ctrl struct {
|
||||||
|
client kubeclient.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ctrl) Restart(name string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ctrl) Stop(name string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ctrl) Start(name string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ctrl) Scale(name string, replicas int) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ctrl) ChangeVersion(name string, version string) error {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package zuser
|
||||||
|
|
||||||
|
import (
|
||||||
|
kubeclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ZUserController interface {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func New( clt kubeclient.Client )ZUserController{
|
||||||
|
c := &ctrl{
|
||||||
|
kubeClient: clt,
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package zuser
|
||||||
|
import(
|
||||||
|
kubeclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
|
)
|
||||||
|
type ctrl struct {
|
||||||
|
kubeClient kubeclient.Client
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package apiserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
kubeclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ZServiceHandler struct {
|
||||||
|
client kubeclient.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewZServiceHandler(client kubeclient.Client) *ZServiceHandler {
|
||||||
|
return &ZServiceHandler{client: client}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func (z *ZServiceHandler) HandleStart(c *gin.Context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZServiceHandler) HandleStop(c *gin.Context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZServiceHandler) HandleRestart(c *gin.Context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZServiceHandler) HandleScale(c *gin.Context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZServiceHandler) HandleChangeVersion(c *gin.Context) {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
HTTPS = "HTTPS"
|
||||||
|
HTTP = "HTTP"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Proxy interface {
|
||||||
|
Proxy() gin.HandlerFunc
|
||||||
|
WithCerts(...string)
|
||||||
|
Path() string
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
package kubeapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
// "encoding/base64"
|
||||||
|
// "fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/ycyxuehan/zelda/apiserver/proxy/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type kubeAPI struct {
|
||||||
|
domain string
|
||||||
|
path string
|
||||||
|
certs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewKubeAPI(domain, path string) api.Proxy {
|
||||||
|
return &kubeAPI{
|
||||||
|
path: path,
|
||||||
|
domain: domain,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kubeAPI) Proxy() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
cert := ""
|
||||||
|
director := func(req *http.Request) {
|
||||||
|
req.URL.Scheme = api.HTTPS
|
||||||
|
req.URL.Host = k.domain
|
||||||
|
req.Header.Set("Content-Type", c.GetHeader("Content-Type"))
|
||||||
|
req.Header.Set("Content-Length", c.GetHeader("Content-Length"))
|
||||||
|
// if c.Request.Method == http.MethodPost || c.Request.Method == http.MethodPatch || c.Request.Method == http.MethodPut {
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
// }
|
||||||
|
req.Host = k.domain
|
||||||
|
//watch模式需要提升协议为websocket
|
||||||
|
watch := c.Query("watch")
|
||||||
|
follow := c.Query("follow")
|
||||||
|
if watch == "true" || follow == "true" {
|
||||||
|
// fmt.Println("watch mode,允许升级为websocket")
|
||||||
|
req.Header.Set("Upgrade", "websocket")
|
||||||
|
}
|
||||||
|
//从header获取cert
|
||||||
|
cert = req.Header.Get("cert")
|
||||||
|
req.Header.Del("cert") //删除cert
|
||||||
|
}
|
||||||
|
proxy := &httputil.ReverseProxy{Director: director}
|
||||||
|
certs := x509.NewCertPool()
|
||||||
|
transport := &http.Transport{
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
DialContext: (&net.Dialer{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
DualStack: true,
|
||||||
|
}).DialContext,
|
||||||
|
ForceAttemptHTTP2: true,
|
||||||
|
MaxIdleConns: 100,
|
||||||
|
IdleConnTimeout: 90 * time.Second,
|
||||||
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
|
TLSClientConfig: &tls.Config{}, //InsecureSkipVerify: true
|
||||||
|
}
|
||||||
|
//如果有证书,加入
|
||||||
|
if ok := certs.AppendCertsFromPEM([]byte(cert)); ok {
|
||||||
|
transport.TLSClientConfig.RootCAs = certs
|
||||||
|
}
|
||||||
|
proxy.Transport = transport
|
||||||
|
proxy.ServeHTTP(c.Writer, c.Request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kubeAPI) WithCerts(certs ...string) {
|
||||||
|
k.certs = append(k.certs, certs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kubeAPI) Path() string {
|
||||||
|
return k.path
|
||||||
|
}
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 ycyxuehan.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
|
||||||
|
// to ensure that exec-entrypoint and run can make use of them.
|
||||||
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||||
|
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
|
||||||
|
|
||||||
|
zeldaiov1alpha1 "github.com/ycyxuehan/zelda/api/v1alpha1"
|
||||||
|
"github.com/ycyxuehan/zelda/apiserver"
|
||||||
|
"github.com/ycyxuehan/zelda/apiserver/auth/jwt"
|
||||||
|
"github.com/ycyxuehan/zelda/apiserver/proxy/kubeapi"
|
||||||
|
"github.com/ycyxuehan/zelda/internal/controller"
|
||||||
|
//+kubebuilder:scaffold:imports
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
scheme = runtime.NewScheme()
|
||||||
|
setupLog = ctrl.Log.WithName("setup")
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
|
||||||
|
|
||||||
|
utilruntime.Must(zeldaiov1alpha1.AddToScheme(scheme))
|
||||||
|
//+kubebuilder:scaffold:scheme
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var metricsAddr string
|
||||||
|
var enableLeaderElection bool
|
||||||
|
var probeAddr string
|
||||||
|
var apiAddr, authSecret string
|
||||||
|
var authTTL int64
|
||||||
|
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
|
||||||
|
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
|
||||||
|
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
|
||||||
|
"Enable leader election for controller manager. "+
|
||||||
|
"Enabling this will ensure there is only one active controller manager.")
|
||||||
|
flag.StringVar(&apiAddr, "api-address", ":80", "api addr to listen")
|
||||||
|
flag.StringVar(&authSecret, "auth-secret", "abcdefghigklmnop1234", "auth token encrypt secret")
|
||||||
|
flag.Int64Var(&authTTL, "auth-ttl", 86400, "token invalid time, default 86400 second")
|
||||||
|
|
||||||
|
opts := zap.Options{
|
||||||
|
Development: true,
|
||||||
|
}
|
||||||
|
opts.BindFlags(flag.CommandLine)
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
|
||||||
|
|
||||||
|
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
||||||
|
Scheme: scheme,
|
||||||
|
Metrics: metricsserver.Options{BindAddress: metricsAddr},
|
||||||
|
HealthProbeBindAddress: probeAddr,
|
||||||
|
LeaderElection: enableLeaderElection,
|
||||||
|
LeaderElectionID: "4a7792b3.zelda.io",
|
||||||
|
// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily
|
||||||
|
// when the Manager ends. This requires the binary to immediately end when the
|
||||||
|
// Manager is stopped, otherwise, this setting is unsafe. Setting this significantly
|
||||||
|
// speeds up voluntary leader transitions as the new leader don't have to wait
|
||||||
|
// LeaseDuration time first.
|
||||||
|
//
|
||||||
|
// In the default scaffold provided, the program ends immediately after
|
||||||
|
// the manager stops, so would be fine to enable this option. However,
|
||||||
|
// if you are doing or is intended to do any operation such as perform cleanups
|
||||||
|
// after the manager stops then its usage might be unsafe.
|
||||||
|
// LeaderElectionReleaseOnCancel: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
setupLog.Error(err, "unable to start manager")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = (&controller.ZProjectReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "unable to create controller", "controller", "ZProject")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err = (&controller.ZServiceReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "unable to create controller", "controller", "ZService")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err = (&controller.ZUserReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "unable to create controller", "controller", "ZUser")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err = (&controller.ZGroupReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "unable to create controller", "controller", "ZGroup")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err = (&controller.ZRegistryReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "unable to create controller", "controller", "ZRegistry")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err = (&controller.ZScriptReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "unable to create controller", "controller", "ZScript")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err = (&controller.ZBuildTemplateReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "unable to create controller", "controller", "ZBuildTemplate")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err = (&controller.ZRunTemplateReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "unable to create controller", "controller", "ZRunTemplate")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err = (&controller.ZBuilderReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "unable to create controller", "controller", "ZBuilder")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err = (&controller.ZCustomHostReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "unable to create controller", "controller", "ZCustomHost")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
//+kubebuilder:scaffold:builder
|
||||||
|
|
||||||
|
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
|
||||||
|
setupLog.Error(err, "unable to set up health check")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
|
||||||
|
setupLog.Error(err, "unable to set up ready check")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
//
|
||||||
|
setupLog.Info("starting webserver")
|
||||||
|
am := jwt.NewManager(authSecret, time.Duration(authTTL) * time.Second)
|
||||||
|
svr := apiserver.NewAPIServer(mgr.GetClient(), am)
|
||||||
|
svr.UseProxies(kubeapi.NewKubeAPI("kubernetes.default.svc", "/kubernetes"))
|
||||||
|
go svr.Run(apiAddr)
|
||||||
|
setupLog.Info("starting manager")
|
||||||
|
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
|
||||||
|
setupLog.Error(err, "problem running manager")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,203 @@
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.13.0
|
||||||
|
name: zbuilders.zelda.io
|
||||||
|
spec:
|
||||||
|
group: zelda.io
|
||||||
|
names:
|
||||||
|
kind: ZBuilder
|
||||||
|
listKind: ZBuilderList
|
||||||
|
plural: zbuilders
|
||||||
|
singular: zbuilder
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: ZBuilder is the Schema for the zbuilders API
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: ZBuilderSpec defines the desired state of ZBuilder
|
||||||
|
properties:
|
||||||
|
branch:
|
||||||
|
type: string
|
||||||
|
build:
|
||||||
|
type: boolean
|
||||||
|
commitHash:
|
||||||
|
type: string
|
||||||
|
creator:
|
||||||
|
type: string
|
||||||
|
deploy:
|
||||||
|
type: boolean
|
||||||
|
package:
|
||||||
|
type: boolean
|
||||||
|
project:
|
||||||
|
description: Foo is an example field of ZBuilder. Edit zbuilder_types.go
|
||||||
|
to remove/update Foo string `json:"foo,omitempty"`
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: API version of the referent.
|
||||||
|
type: string
|
||||||
|
fieldPath:
|
||||||
|
description: 'If referring to a piece of an object instead of
|
||||||
|
an entire object, this string should contain a valid JSON/Go
|
||||||
|
field access statement, such as desiredState.manifest.containers[2].
|
||||||
|
For example, if the object reference is to a container within
|
||||||
|
a pod, this would take on a value like: "spec.containers{name}"
|
||||||
|
(where "name" refers to the name of the container that triggered
|
||||||
|
the event) or if no container name is specified "spec.containers[2]"
|
||||||
|
(container with index 2 in this pod). This syntax is chosen
|
||||||
|
only to have some well-defined way of referencing a part of
|
||||||
|
an object. TODO: this design is not final and this field is
|
||||||
|
subject to change in the future.'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
|
||||||
|
type: string
|
||||||
|
resourceVersion:
|
||||||
|
description: 'Specific resourceVersion to which this reference
|
||||||
|
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
|
||||||
|
type: string
|
||||||
|
uid:
|
||||||
|
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
subProject:
|
||||||
|
type: string
|
||||||
|
zservice:
|
||||||
|
description: "ObjectReference contains enough information to let you
|
||||||
|
inspect or modify the referred object. --- New uses of this type
|
||||||
|
are discouraged because of difficulty describing its usage when
|
||||||
|
embedded in APIs. 1. Ignored fields. It includes many fields which
|
||||||
|
are not generally honored. For instance, ResourceVersion and FieldPath
|
||||||
|
are both very rarely valid in actual usage. 2. Invalid usage help.
|
||||||
|
\ It is impossible to add specific help for individual usage. In
|
||||||
|
most embedded usages, there are particular restrictions like, \"must
|
||||||
|
refer only to types A and B\" or \"UID not honored\" or \"name must
|
||||||
|
be restricted\". Those cannot be well described when embedded. 3.
|
||||||
|
Inconsistent validation. Because the usages are different, the
|
||||||
|
validation rules are different by usage, which makes it hard for
|
||||||
|
users to predict what will happen. 4. The fields are both imprecise
|
||||||
|
and overly precise. Kind is not a precise mapping to a URL. This
|
||||||
|
can produce ambiguity during interpretation and require a REST mapping.
|
||||||
|
\ In most cases, the dependency is on the group,resource tuple and
|
||||||
|
the version of the actual struct is irrelevant. 5. We cannot easily
|
||||||
|
change it. Because this type is embedded in many locations, updates
|
||||||
|
to this type will affect numerous schemas. Don't make new APIs
|
||||||
|
embed an underspecified API type they do not control. \n Instead
|
||||||
|
of using this type, create a locally provided and used type that
|
||||||
|
is well-focused on your reference. For example, ServiceReferences
|
||||||
|
for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
|
||||||
|
."
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: API version of the referent.
|
||||||
|
type: string
|
||||||
|
fieldPath:
|
||||||
|
description: 'If referring to a piece of an object instead of
|
||||||
|
an entire object, this string should contain a valid JSON/Go
|
||||||
|
field access statement, such as desiredState.manifest.containers[2].
|
||||||
|
For example, if the object reference is to a container within
|
||||||
|
a pod, this would take on a value like: "spec.containers{name}"
|
||||||
|
(where "name" refers to the name of the container that triggered
|
||||||
|
the event) or if no container name is specified "spec.containers[2]"
|
||||||
|
(container with index 2 in this pod). This syntax is chosen
|
||||||
|
only to have some well-defined way of referencing a part of
|
||||||
|
an object. TODO: this design is not final and this field is
|
||||||
|
subject to change in the future.'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
|
||||||
|
type: string
|
||||||
|
resourceVersion:
|
||||||
|
description: 'Specific resourceVersion to which this reference
|
||||||
|
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
|
||||||
|
type: string
|
||||||
|
uid:
|
||||||
|
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: ZBuilderStatus defines the observed state of ZBuilder
|
||||||
|
properties:
|
||||||
|
RunAt:
|
||||||
|
type: string
|
||||||
|
createdAt:
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
finishedAt:
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
phase:
|
||||||
|
type: string
|
||||||
|
reason:
|
||||||
|
type: string
|
||||||
|
steps:
|
||||||
|
description: 'INSERT ADDITIONAL STATUS FIELD - define observed state
|
||||||
|
of cluster Important: Run "make" to regenerate code after modifying
|
||||||
|
this file'
|
||||||
|
items:
|
||||||
|
description: 'EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||||
|
NOTE: json tags are required. Any new fields you add must have
|
||||||
|
json tags for the fields to be serialized. Step status'
|
||||||
|
properties:
|
||||||
|
finishedAt:
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
phase:
|
||||||
|
description: PodPhase is a label for the condition of a pod
|
||||||
|
at the current time.
|
||||||
|
type: string
|
||||||
|
ready:
|
||||||
|
type: boolean
|
||||||
|
reason:
|
||||||
|
type: string
|
||||||
|
started:
|
||||||
|
type: boolean
|
||||||
|
startedAt:
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
|
@ -0,0 +1,232 @@
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.13.0
|
||||||
|
name: zbuildtemplates.zelda.io
|
||||||
|
spec:
|
||||||
|
group: zelda.io
|
||||||
|
names:
|
||||||
|
kind: ZBuildTemplate
|
||||||
|
listKind: ZBuildTemplateList
|
||||||
|
plural: zbuildtemplates
|
||||||
|
singular: zbuildtemplate
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: ZBuildTemplate is the Schema for the zbuildtemplates API
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: ZBuildTemplateSpec defines the desired state of ZBuildTemplate
|
||||||
|
properties:
|
||||||
|
imagePullSecrets:
|
||||||
|
items:
|
||||||
|
description: LocalObjectReference contains enough information to
|
||||||
|
let you locate the referenced object inside the same namespace.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
type: array
|
||||||
|
steps:
|
||||||
|
description: Foo is an example field of ZBuildTemplate. Edit zbuildtemplate_types.go
|
||||||
|
to remove/update Foo string `json:"foo,omitempty"`
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
args:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
commands:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
env:
|
||||||
|
items:
|
||||||
|
description: EnvVar represents an environment variable present
|
||||||
|
in a Container.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: Name of the environment variable. Must be
|
||||||
|
a C_IDENTIFIER.
|
||||||
|
type: string
|
||||||
|
value:
|
||||||
|
description: 'Variable references $(VAR_NAME) are expanded
|
||||||
|
using the previously defined environment variables in
|
||||||
|
the container and any service environment variables.
|
||||||
|
If a variable cannot be resolved, the reference in the
|
||||||
|
input string will be unchanged. Double $$ are reduced
|
||||||
|
to a single $, which allows for escaping the $(VAR_NAME)
|
||||||
|
syntax: i.e. "$$(VAR_NAME)" will produce the string
|
||||||
|
literal "$(VAR_NAME)". Escaped references will never
|
||||||
|
be expanded, regardless of whether the variable exists
|
||||||
|
or not. Defaults to "".'
|
||||||
|
type: string
|
||||||
|
valueFrom:
|
||||||
|
description: Source for the environment variable's value.
|
||||||
|
Cannot be used if value is not empty.
|
||||||
|
properties:
|
||||||
|
configMapKeyRef:
|
||||||
|
description: Selects a key of a ConfigMap.
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: The key to select.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info:
|
||||||
|
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
TODO: Add other useful fields. apiVersion, kind,
|
||||||
|
uid?'
|
||||||
|
type: string
|
||||||
|
optional:
|
||||||
|
description: Specify whether the ConfigMap or
|
||||||
|
its key must be defined
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
fieldRef:
|
||||||
|
description: 'Selects a field of the pod: supports
|
||||||
|
metadata.name, metadata.namespace, `metadata.labels[''<KEY>'']`,
|
||||||
|
`metadata.annotations[''<KEY>'']`, spec.nodeName,
|
||||||
|
spec.serviceAccountName, status.hostIP, status.podIP,
|
||||||
|
status.podIPs.'
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: Version of the schema the FieldPath
|
||||||
|
is written in terms of, defaults to "v1".
|
||||||
|
type: string
|
||||||
|
fieldPath:
|
||||||
|
description: Path of the field to select in the
|
||||||
|
specified API version.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- fieldPath
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
resourceFieldRef:
|
||||||
|
description: 'Selects a resource of the container:
|
||||||
|
only resources limits and requests (limits.cpu,
|
||||||
|
limits.memory, limits.ephemeral-storage, requests.cpu,
|
||||||
|
requests.memory and requests.ephemeral-storage)
|
||||||
|
are currently supported.'
|
||||||
|
properties:
|
||||||
|
containerName:
|
||||||
|
description: 'Container name: required for volumes,
|
||||||
|
optional for env vars'
|
||||||
|
type: string
|
||||||
|
divisor:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: Specifies the output format of the
|
||||||
|
exposed resources, defaults to "1"
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
resource:
|
||||||
|
description: 'Required: resource to select'
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- resource
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
secretKeyRef:
|
||||||
|
description: Selects a key of a secret in the pod's
|
||||||
|
namespace
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: The key of the secret to select from. Must
|
||||||
|
be a valid secret key.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info:
|
||||||
|
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
TODO: Add other useful fields. apiVersion, kind,
|
||||||
|
uid?'
|
||||||
|
type: string
|
||||||
|
optional:
|
||||||
|
description: Specify whether the Secret or its
|
||||||
|
key must be defined
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
image:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
volumeMounts:
|
||||||
|
items:
|
||||||
|
description: VolumeMount describes a mounting of a Volume
|
||||||
|
within a container.
|
||||||
|
properties:
|
||||||
|
mountPath:
|
||||||
|
description: Path within the container at which the volume
|
||||||
|
should be mounted. Must not contain ':'.
|
||||||
|
type: string
|
||||||
|
mountPropagation:
|
||||||
|
description: mountPropagation determines how mounts are
|
||||||
|
propagated from the host to container and the other
|
||||||
|
way around. When not set, MountPropagationNone is used.
|
||||||
|
This field is beta in 1.10.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: This must match the Name of a Volume.
|
||||||
|
type: string
|
||||||
|
readOnly:
|
||||||
|
description: Mounted read-only if true, read-write otherwise
|
||||||
|
(false or unspecified). Defaults to false.
|
||||||
|
type: boolean
|
||||||
|
subPath:
|
||||||
|
description: Path within the volume from which the container's
|
||||||
|
volume should be mounted. Defaults to "" (volume's root).
|
||||||
|
type: string
|
||||||
|
subPathExpr:
|
||||||
|
description: Expanded path within the volume from which
|
||||||
|
the container's volume should be mounted. Behaves similarly
|
||||||
|
to SubPath but environment variable references $(VAR_NAME)
|
||||||
|
are expanded using the container's environment. Defaults
|
||||||
|
to "" (volume's root). SubPathExpr and SubPath are mutually
|
||||||
|
exclusive.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- mountPath
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: ZBuildTemplateStatus defines the observed state of ZBuildTemplate
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
|
@ -0,0 +1,62 @@
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.13.0
|
||||||
|
name: zcustomhosts.zelda.io
|
||||||
|
spec:
|
||||||
|
group: zelda.io
|
||||||
|
names:
|
||||||
|
kind: ZCustomHost
|
||||||
|
listKind: ZCustomHostList
|
||||||
|
plural: zcustomhosts
|
||||||
|
singular: zcustomhost
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: ZCustomHost is the Schema for the zcustomhosts API
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: ZCustomHostSpec defines the desired state of ZCustomHost
|
||||||
|
properties:
|
||||||
|
hostAlias:
|
||||||
|
description: Foo is an example field of ZCustomHost. Edit zcustomhost_types.go
|
||||||
|
to remove/update Foo string `json:"foo,omitempty"`
|
||||||
|
items:
|
||||||
|
description: HostAlias holds the mapping between IP and hostnames
|
||||||
|
that will be injected as an entry in the pod's hosts file.
|
||||||
|
properties:
|
||||||
|
hostnames:
|
||||||
|
description: Hostnames for the above IP address.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
ip:
|
||||||
|
description: IP address of the host file entry.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: ZCustomHostStatus defines the observed state of ZCustomHost
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
|
@ -0,0 +1,208 @@
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.13.0
|
||||||
|
name: zgroups.zelda.io
|
||||||
|
spec:
|
||||||
|
group: zelda.io
|
||||||
|
names:
|
||||||
|
kind: ZGroup
|
||||||
|
listKind: ZGroupList
|
||||||
|
plural: zgroups
|
||||||
|
singular: zgroup
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: ZGroup is the Schema for the zgroups API
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: ZGroupSpec defines the desired state of ZGroup
|
||||||
|
properties:
|
||||||
|
clusterRulers:
|
||||||
|
items:
|
||||||
|
description: PolicyRule holds information that describes a policy
|
||||||
|
rule, but does not contain information about who the rule applies
|
||||||
|
to or which namespace the rule applies to.
|
||||||
|
properties:
|
||||||
|
apiGroups:
|
||||||
|
description: APIGroups is the name of the APIGroup that contains
|
||||||
|
the resources. If multiple API groups are specified, any
|
||||||
|
action requested against one of the enumerated resources in
|
||||||
|
any API group will be allowed. "" represents the core API
|
||||||
|
group and "*" represents all API groups.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
nonResourceURLs:
|
||||||
|
description: NonResourceURLs is a set of partial urls that a
|
||||||
|
user should have access to. *s are allowed, but only as the
|
||||||
|
full, final step in the path Since non-resource URLs are not
|
||||||
|
namespaced, this field is only applicable for ClusterRoles
|
||||||
|
referenced from a ClusterRoleBinding. Rules can either apply
|
||||||
|
to API resources (such as "pods" or "secrets") or non-resource
|
||||||
|
URL paths (such as "/api"), but not both.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
resourceNames:
|
||||||
|
description: ResourceNames is an optional white list of names
|
||||||
|
that the rule applies to. An empty set means that everything
|
||||||
|
is allowed.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
resources:
|
||||||
|
description: Resources is a list of resources this rule applies
|
||||||
|
to. '*' represents all resources.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
verbs:
|
||||||
|
description: Verbs is a list of Verbs that apply to ALL the
|
||||||
|
ResourceKinds contained in this rule. '*' represents all verbs.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
required:
|
||||||
|
- verbs
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
rulers:
|
||||||
|
description: Foo is an example field of ZGroup. Edit zgroup_types.go
|
||||||
|
to remove/update Foo string `json:"foo,omitempty"`
|
||||||
|
items:
|
||||||
|
description: PolicyRule holds information that describes a policy
|
||||||
|
rule, but does not contain information about who the rule applies
|
||||||
|
to or which namespace the rule applies to.
|
||||||
|
properties:
|
||||||
|
apiGroups:
|
||||||
|
description: APIGroups is the name of the APIGroup that contains
|
||||||
|
the resources. If multiple API groups are specified, any
|
||||||
|
action requested against one of the enumerated resources in
|
||||||
|
any API group will be allowed. "" represents the core API
|
||||||
|
group and "*" represents all API groups.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
nonResourceURLs:
|
||||||
|
description: NonResourceURLs is a set of partial urls that a
|
||||||
|
user should have access to. *s are allowed, but only as the
|
||||||
|
full, final step in the path Since non-resource URLs are not
|
||||||
|
namespaced, this field is only applicable for ClusterRoles
|
||||||
|
referenced from a ClusterRoleBinding. Rules can either apply
|
||||||
|
to API resources (such as "pods" or "secrets") or non-resource
|
||||||
|
URL paths (such as "/api"), but not both.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
resourceNames:
|
||||||
|
description: ResourceNames is an optional white list of names
|
||||||
|
that the rule applies to. An empty set means that everything
|
||||||
|
is allowed.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
resources:
|
||||||
|
description: Resources is a list of resources this rule applies
|
||||||
|
to. '*' represents all resources.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
verbs:
|
||||||
|
description: Verbs is a list of Verbs that apply to ALL the
|
||||||
|
ResourceKinds contained in this rule. '*' represents all verbs.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
required:
|
||||||
|
- verbs
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
secrets:
|
||||||
|
items:
|
||||||
|
description: "ObjectReference contains enough information to let
|
||||||
|
you inspect or modify the referred object. --- New uses of this
|
||||||
|
type are discouraged because of difficulty describing its usage
|
||||||
|
when embedded in APIs. 1. Ignored fields. It includes many fields
|
||||||
|
which are not generally honored. For instance, ResourceVersion
|
||||||
|
and FieldPath are both very rarely valid in actual usage. 2. Invalid
|
||||||
|
usage help. It is impossible to add specific help for individual
|
||||||
|
usage. In most embedded usages, there are particular restrictions
|
||||||
|
like, \"must refer only to types A and B\" or \"UID not honored\"
|
||||||
|
or \"name must be restricted\". Those cannot be well described
|
||||||
|
when embedded. 3. Inconsistent validation. Because the usages
|
||||||
|
are different, the validation rules are different by usage, which
|
||||||
|
makes it hard for users to predict what will happen. 4. The fields
|
||||||
|
are both imprecise and overly precise. Kind is not a precise
|
||||||
|
mapping to a URL. This can produce ambiguity during interpretation
|
||||||
|
and require a REST mapping. In most cases, the dependency is
|
||||||
|
on the group,resource tuple and the version of the actual struct
|
||||||
|
is irrelevant. 5. We cannot easily change it. Because this type
|
||||||
|
is embedded in many locations, updates to this type will affect
|
||||||
|
numerous schemas. Don't make new APIs embed an underspecified
|
||||||
|
API type they do not control. \n Instead of using this type, create
|
||||||
|
a locally provided and used type that is well-focused on your
|
||||||
|
reference. For example, ServiceReferences for admission registration:
|
||||||
|
https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
|
||||||
|
."
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: API version of the referent.
|
||||||
|
type: string
|
||||||
|
fieldPath:
|
||||||
|
description: 'If referring to a piece of an object instead of
|
||||||
|
an entire object, this string should contain a valid JSON/Go
|
||||||
|
field access statement, such as desiredState.manifest.containers[2].
|
||||||
|
For example, if the object reference is to a container within
|
||||||
|
a pod, this would take on a value like: "spec.containers{name}"
|
||||||
|
(where "name" refers to the name of the container that triggered
|
||||||
|
the event) or if no container name is specified "spec.containers[2]"
|
||||||
|
(container with index 2 in this pod). This syntax is chosen
|
||||||
|
only to have some well-defined way of referencing a part of
|
||||||
|
an object. TODO: this design is not final and this field is
|
||||||
|
subject to change in the future.'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
|
||||||
|
type: string
|
||||||
|
resourceVersion:
|
||||||
|
description: 'Specific resourceVersion to which this reference
|
||||||
|
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
|
||||||
|
type: string
|
||||||
|
uid:
|
||||||
|
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: ZGroupStatus defines the observed state of ZGroup
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,57 @@
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.13.0
|
||||||
|
name: zregistries.zelda.io
|
||||||
|
spec:
|
||||||
|
group: zelda.io
|
||||||
|
names:
|
||||||
|
kind: ZRegistry
|
||||||
|
listKind: ZRegistryList
|
||||||
|
plural: zregistries
|
||||||
|
singular: zregistry
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: ZRegistry is the Schema for the zregistries API
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: ZRegistrySpec defines the desired state of ZRegistry
|
||||||
|
properties:
|
||||||
|
namespace:
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
portal:
|
||||||
|
type: string
|
||||||
|
server:
|
||||||
|
description: Foo is an example field of ZRegistry. Edit zregistry_types.go
|
||||||
|
to remove/update Foo string `json:"foo,omitempty"`
|
||||||
|
type: string
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: ZRegistryStatus defines the observed state of ZRegistry
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,125 @@
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.13.0
|
||||||
|
name: zusers.zelda.io
|
||||||
|
spec:
|
||||||
|
group: zelda.io
|
||||||
|
names:
|
||||||
|
kind: ZUser
|
||||||
|
listKind: ZUserList
|
||||||
|
plural: zusers
|
||||||
|
singular: zuser
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: ZUser is the Schema for the zusers API
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: ZUserSpec defines the desired state of ZUser
|
||||||
|
properties:
|
||||||
|
group:
|
||||||
|
type: string
|
||||||
|
notifyMedia:
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
description: Foo is an example field of ZUser. Edit zuser_types.go
|
||||||
|
to remove/update Foo string `json:"foo,omitempty"`
|
||||||
|
type: string
|
||||||
|
secrets:
|
||||||
|
items:
|
||||||
|
description: "ObjectReference contains enough information to let
|
||||||
|
you inspect or modify the referred object. --- New uses of this
|
||||||
|
type are discouraged because of difficulty describing its usage
|
||||||
|
when embedded in APIs. 1. Ignored fields. It includes many fields
|
||||||
|
which are not generally honored. For instance, ResourceVersion
|
||||||
|
and FieldPath are both very rarely valid in actual usage. 2. Invalid
|
||||||
|
usage help. It is impossible to add specific help for individual
|
||||||
|
usage. In most embedded usages, there are particular restrictions
|
||||||
|
like, \"must refer only to types A and B\" or \"UID not honored\"
|
||||||
|
or \"name must be restricted\". Those cannot be well described
|
||||||
|
when embedded. 3. Inconsistent validation. Because the usages
|
||||||
|
are different, the validation rules are different by usage, which
|
||||||
|
makes it hard for users to predict what will happen. 4. The fields
|
||||||
|
are both imprecise and overly precise. Kind is not a precise
|
||||||
|
mapping to a URL. This can produce ambiguity during interpretation
|
||||||
|
and require a REST mapping. In most cases, the dependency is
|
||||||
|
on the group,resource tuple and the version of the actual struct
|
||||||
|
is irrelevant. 5. We cannot easily change it. Because this type
|
||||||
|
is embedded in many locations, updates to this type will affect
|
||||||
|
numerous schemas. Don't make new APIs embed an underspecified
|
||||||
|
API type they do not control. \n Instead of using this type, create
|
||||||
|
a locally provided and used type that is well-focused on your
|
||||||
|
reference. For example, ServiceReferences for admission registration:
|
||||||
|
https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
|
||||||
|
."
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: API version of the referent.
|
||||||
|
type: string
|
||||||
|
fieldPath:
|
||||||
|
description: 'If referring to a piece of an object instead of
|
||||||
|
an entire object, this string should contain a valid JSON/Go
|
||||||
|
field access statement, such as desiredState.manifest.containers[2].
|
||||||
|
For example, if the object reference is to a container within
|
||||||
|
a pod, this would take on a value like: "spec.containers{name}"
|
||||||
|
(where "name" refers to the name of the container that triggered
|
||||||
|
the event) or if no container name is specified "spec.containers[2]"
|
||||||
|
(container with index 2 in this pod). This syntax is chosen
|
||||||
|
only to have some well-defined way of referencing a part of
|
||||||
|
an object. TODO: this design is not final and this field is
|
||||||
|
subject to change in the future.'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
|
||||||
|
type: string
|
||||||
|
resourceVersion:
|
||||||
|
description: 'Specific resourceVersion to which this reference
|
||||||
|
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
|
||||||
|
type: string
|
||||||
|
uid:
|
||||||
|
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: ZUserStatus defines the observed state of ZUser
|
||||||
|
properties:
|
||||||
|
createdAt:
|
||||||
|
description: 'INSERT ADDITIONAL STATUS FIELD - define observed state
|
||||||
|
of cluster Important: Run "make" to regenerate code after modifying
|
||||||
|
this file'
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
token:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
|
@ -0,0 +1,48 @@
|
||||||
|
# This kustomization.yaml is not intended to be run by itself,
|
||||||
|
# since it depends on service name and namespace that are out of this kustomize package.
|
||||||
|
# It should be run by config/default
|
||||||
|
resources:
|
||||||
|
- bases/zelda.io_zprojects.yaml
|
||||||
|
- bases/zelda.io_zservices.yaml
|
||||||
|
- bases/zelda.io_zusers.yaml
|
||||||
|
- bases/zelda.io_zgroups.yaml
|
||||||
|
- bases/zelda.io_zregistries.yaml
|
||||||
|
- bases/zelda.io_zscripts.yaml
|
||||||
|
- bases/zelda.io_zbuildtemplates.yaml
|
||||||
|
- bases/zelda.io_zruntemplates.yaml
|
||||||
|
- bases/zelda.io_zbuilders.yaml
|
||||||
|
- bases/zelda.io_zcustomhosts.yaml
|
||||||
|
#+kubebuilder:scaffold:crdkustomizeresource
|
||||||
|
|
||||||
|
patches:
|
||||||
|
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
|
||||||
|
# patches here are for enabling the conversion webhook for each CRD
|
||||||
|
#- path: patches/webhook_in_zprojects.yaml
|
||||||
|
#- path: patches/webhook_in_zservices.yaml
|
||||||
|
#- path: patches/webhook_in_zusers.yaml
|
||||||
|
#- path: patches/webhook_in_zgroups.yaml
|
||||||
|
#- path: patches/webhook_in_zregistries.yaml
|
||||||
|
#- path: patches/webhook_in_zscripts.yaml
|
||||||
|
#- path: patches/webhook_in_zbuildtemplates.yaml
|
||||||
|
#- path: patches/webhook_in_zruntemplates.yaml
|
||||||
|
#- path: patches/webhook_in_zbuilders.yaml
|
||||||
|
#- path: patches/webhook_in_zcustomhosts.yaml
|
||||||
|
#+kubebuilder:scaffold:crdkustomizewebhookpatch
|
||||||
|
|
||||||
|
# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
|
||||||
|
# patches here are for enabling the CA injection for each CRD
|
||||||
|
#- path: patches/cainjection_in_zprojects.yaml
|
||||||
|
#- path: patches/cainjection_in_zservices.yaml
|
||||||
|
#- path: patches/cainjection_in_zusers.yaml
|
||||||
|
#- path: patches/cainjection_in_zgroups.yaml
|
||||||
|
#- path: patches/cainjection_in_zregistries.yaml
|
||||||
|
#- path: patches/cainjection_in_zscripts.yaml
|
||||||
|
#- path: patches/cainjection_in_zbuildtemplates.yaml
|
||||||
|
#- path: patches/cainjection_in_zruntemplates.yaml
|
||||||
|
#- path: patches/cainjection_in_zbuilders.yaml
|
||||||
|
#- path: patches/cainjection_in_zcustomhosts.yaml
|
||||||
|
#+kubebuilder:scaffold:crdkustomizecainjectionpatch
|
||||||
|
|
||||||
|
# the following config is for teaching kustomize how to do kustomization for CRDs.
|
||||||
|
configurations:
|
||||||
|
- kustomizeconfig.yaml
|
|
@ -0,0 +1,19 @@
|
||||||
|
# This file is for teaching kustomize how to substitute name and namespace reference in CRD
|
||||||
|
nameReference:
|
||||||
|
- kind: Service
|
||||||
|
version: v1
|
||||||
|
fieldSpecs:
|
||||||
|
- kind: CustomResourceDefinition
|
||||||
|
version: v1
|
||||||
|
group: apiextensions.k8s.io
|
||||||
|
path: spec/conversion/webhook/clientConfig/service/name
|
||||||
|
|
||||||
|
namespace:
|
||||||
|
- kind: CustomResourceDefinition
|
||||||
|
version: v1
|
||||||
|
group: apiextensions.k8s.io
|
||||||
|
path: spec/conversion/webhook/clientConfig/service/namespace
|
||||||
|
create: false
|
||||||
|
|
||||||
|
varReference:
|
||||||
|
- path: metadata/annotations
|
|
@ -0,0 +1,7 @@
|
||||||
|
# The following patch adds a directive for certmanager to inject CA into the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
|
||||||
|
name: zbuilders.zelda.io
|
|
@ -0,0 +1,7 @@
|
||||||
|
# The following patch adds a directive for certmanager to inject CA into the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
|
||||||
|
name: zbuildtemplates.zelda.io
|
|
@ -0,0 +1,7 @@
|
||||||
|
# The following patch adds a directive for certmanager to inject CA into the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
|
||||||
|
name: zcustomhosts.zelda.io
|
|
@ -0,0 +1,7 @@
|
||||||
|
# The following patch adds a directive for certmanager to inject CA into the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
|
||||||
|
name: zgroups.zelda.io
|
|
@ -0,0 +1,7 @@
|
||||||
|
# The following patch adds a directive for certmanager to inject CA into the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
|
||||||
|
name: zprojects.zelda.io
|
|
@ -0,0 +1,7 @@
|
||||||
|
# The following patch adds a directive for certmanager to inject CA into the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
|
||||||
|
name: zregistries.zelda.io
|
|
@ -0,0 +1,7 @@
|
||||||
|
# The following patch adds a directive for certmanager to inject CA into the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
|
||||||
|
name: zruntemplates.zelda.io
|
|
@ -0,0 +1,7 @@
|
||||||
|
# The following patch adds a directive for certmanager to inject CA into the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
|
||||||
|
name: zscripts.zelda.io
|
|
@ -0,0 +1,7 @@
|
||||||
|
# The following patch adds a directive for certmanager to inject CA into the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
|
||||||
|
name: zservices.zelda.io
|
|
@ -0,0 +1,7 @@
|
||||||
|
# The following patch adds a directive for certmanager to inject CA into the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
|
||||||
|
name: zusers.zelda.io
|
|
@ -0,0 +1,16 @@
|
||||||
|
# The following patch enables a conversion webhook for the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: zbuilders.zelda.io
|
||||||
|
spec:
|
||||||
|
conversion:
|
||||||
|
strategy: Webhook
|
||||||
|
webhook:
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
namespace: system
|
||||||
|
name: webhook-service
|
||||||
|
path: /convert
|
||||||
|
conversionReviewVersions:
|
||||||
|
- v1
|
|
@ -0,0 +1,16 @@
|
||||||
|
# The following patch enables a conversion webhook for the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: zbuildtemplates.zelda.io
|
||||||
|
spec:
|
||||||
|
conversion:
|
||||||
|
strategy: Webhook
|
||||||
|
webhook:
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
namespace: system
|
||||||
|
name: webhook-service
|
||||||
|
path: /convert
|
||||||
|
conversionReviewVersions:
|
||||||
|
- v1
|
|
@ -0,0 +1,16 @@
|
||||||
|
# The following patch enables a conversion webhook for the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: zcustomhosts.zelda.io
|
||||||
|
spec:
|
||||||
|
conversion:
|
||||||
|
strategy: Webhook
|
||||||
|
webhook:
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
namespace: system
|
||||||
|
name: webhook-service
|
||||||
|
path: /convert
|
||||||
|
conversionReviewVersions:
|
||||||
|
- v1
|
|
@ -0,0 +1,16 @@
|
||||||
|
# The following patch enables a conversion webhook for the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: zgroups.zelda.io
|
||||||
|
spec:
|
||||||
|
conversion:
|
||||||
|
strategy: Webhook
|
||||||
|
webhook:
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
namespace: system
|
||||||
|
name: webhook-service
|
||||||
|
path: /convert
|
||||||
|
conversionReviewVersions:
|
||||||
|
- v1
|
|
@ -0,0 +1,16 @@
|
||||||
|
# The following patch enables a conversion webhook for the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: zprojects.zelda.io
|
||||||
|
spec:
|
||||||
|
conversion:
|
||||||
|
strategy: Webhook
|
||||||
|
webhook:
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
namespace: system
|
||||||
|
name: webhook-service
|
||||||
|
path: /convert
|
||||||
|
conversionReviewVersions:
|
||||||
|
- v1
|
|
@ -0,0 +1,16 @@
|
||||||
|
# The following patch enables a conversion webhook for the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: zregistries.zelda.io
|
||||||
|
spec:
|
||||||
|
conversion:
|
||||||
|
strategy: Webhook
|
||||||
|
webhook:
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
namespace: system
|
||||||
|
name: webhook-service
|
||||||
|
path: /convert
|
||||||
|
conversionReviewVersions:
|
||||||
|
- v1
|
|
@ -0,0 +1,16 @@
|
||||||
|
# The following patch enables a conversion webhook for the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: zruntemplates.zelda.io
|
||||||
|
spec:
|
||||||
|
conversion:
|
||||||
|
strategy: Webhook
|
||||||
|
webhook:
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
namespace: system
|
||||||
|
name: webhook-service
|
||||||
|
path: /convert
|
||||||
|
conversionReviewVersions:
|
||||||
|
- v1
|
|
@ -0,0 +1,16 @@
|
||||||
|
# The following patch enables a conversion webhook for the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: zscripts.zelda.io
|
||||||
|
spec:
|
||||||
|
conversion:
|
||||||
|
strategy: Webhook
|
||||||
|
webhook:
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
namespace: system
|
||||||
|
name: webhook-service
|
||||||
|
path: /convert
|
||||||
|
conversionReviewVersions:
|
||||||
|
- v1
|
|
@ -0,0 +1,16 @@
|
||||||
|
# The following patch enables a conversion webhook for the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: zservices.zelda.io
|
||||||
|
spec:
|
||||||
|
conversion:
|
||||||
|
strategy: Webhook
|
||||||
|
webhook:
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
namespace: system
|
||||||
|
name: webhook-service
|
||||||
|
path: /convert
|
||||||
|
conversionReviewVersions:
|
||||||
|
- v1
|
|
@ -0,0 +1,16 @@
|
||||||
|
# The following patch enables a conversion webhook for the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: zusers.zelda.io
|
||||||
|
spec:
|
||||||
|
conversion:
|
||||||
|
strategy: Webhook
|
||||||
|
webhook:
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
namespace: system
|
||||||
|
name: webhook-service
|
||||||
|
path: /convert
|
||||||
|
conversionReviewVersions:
|
||||||
|
- v1
|
|
@ -0,0 +1,144 @@
|
||||||
|
# Adds namespace to all resources.
|
||||||
|
namespace: zelda-system
|
||||||
|
|
||||||
|
# Value of this field is prepended to the
|
||||||
|
# names of all resources, e.g. a deployment named
|
||||||
|
# "wordpress" becomes "alices-wordpress".
|
||||||
|
# Note that it should also match with the prefix (text before '-') of the namespace
|
||||||
|
# field above.
|
||||||
|
namePrefix: zelda-
|
||||||
|
|
||||||
|
# Labels to add to all resources and selectors.
|
||||||
|
#labels:
|
||||||
|
#- includeSelectors: true
|
||||||
|
# pairs:
|
||||||
|
# someName: someValue
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ../crd
|
||||||
|
- ../rbac
|
||||||
|
- ../manager
|
||||||
|
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
|
||||||
|
# crd/kustomization.yaml
|
||||||
|
#- ../webhook
|
||||||
|
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
|
||||||
|
#- ../certmanager
|
||||||
|
# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
|
||||||
|
#- ../prometheus
|
||||||
|
|
||||||
|
patchesStrategicMerge:
|
||||||
|
# Protect the /metrics endpoint by putting it behind auth.
|
||||||
|
# If you want your controller-manager to expose the /metrics
|
||||||
|
# endpoint w/o any authn/z, please comment the following line.
|
||||||
|
- manager_auth_proxy_patch.yaml
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
|
||||||
|
# crd/kustomization.yaml
|
||||||
|
#- manager_webhook_patch.yaml
|
||||||
|
|
||||||
|
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
|
||||||
|
# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
|
||||||
|
# 'CERTMANAGER' needs to be enabled to use ca injection
|
||||||
|
#- webhookcainjection_patch.yaml
|
||||||
|
|
||||||
|
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
|
||||||
|
# Uncomment the following replacements to add the cert-manager CA injection annotations
|
||||||
|
#replacements:
|
||||||
|
# - source: # Add cert-manager annotation to ValidatingWebhookConfiguration, MutatingWebhookConfiguration and CRDs
|
||||||
|
# kind: Certificate
|
||||||
|
# group: cert-manager.io
|
||||||
|
# version: v1
|
||||||
|
# name: serving-cert # this name should match the one in certificate.yaml
|
||||||
|
# fieldPath: .metadata.namespace # namespace of the certificate CR
|
||||||
|
# targets:
|
||||||
|
# - select:
|
||||||
|
# kind: ValidatingWebhookConfiguration
|
||||||
|
# fieldPaths:
|
||||||
|
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
|
||||||
|
# options:
|
||||||
|
# delimiter: '/'
|
||||||
|
# index: 0
|
||||||
|
# create: true
|
||||||
|
# - select:
|
||||||
|
# kind: MutatingWebhookConfiguration
|
||||||
|
# fieldPaths:
|
||||||
|
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
|
||||||
|
# options:
|
||||||
|
# delimiter: '/'
|
||||||
|
# index: 0
|
||||||
|
# create: true
|
||||||
|
# - select:
|
||||||
|
# kind: CustomResourceDefinition
|
||||||
|
# fieldPaths:
|
||||||
|
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
|
||||||
|
# options:
|
||||||
|
# delimiter: '/'
|
||||||
|
# index: 0
|
||||||
|
# create: true
|
||||||
|
# - source:
|
||||||
|
# kind: Certificate
|
||||||
|
# group: cert-manager.io
|
||||||
|
# version: v1
|
||||||
|
# name: serving-cert # this name should match the one in certificate.yaml
|
||||||
|
# fieldPath: .metadata.name
|
||||||
|
# targets:
|
||||||
|
# - select:
|
||||||
|
# kind: ValidatingWebhookConfiguration
|
||||||
|
# fieldPaths:
|
||||||
|
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
|
||||||
|
# options:
|
||||||
|
# delimiter: '/'
|
||||||
|
# index: 1
|
||||||
|
# create: true
|
||||||
|
# - select:
|
||||||
|
# kind: MutatingWebhookConfiguration
|
||||||
|
# fieldPaths:
|
||||||
|
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
|
||||||
|
# options:
|
||||||
|
# delimiter: '/'
|
||||||
|
# index: 1
|
||||||
|
# create: true
|
||||||
|
# - select:
|
||||||
|
# kind: CustomResourceDefinition
|
||||||
|
# fieldPaths:
|
||||||
|
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
|
||||||
|
# options:
|
||||||
|
# delimiter: '/'
|
||||||
|
# index: 1
|
||||||
|
# create: true
|
||||||
|
# - source: # Add cert-manager annotation to the webhook Service
|
||||||
|
# kind: Service
|
||||||
|
# version: v1
|
||||||
|
# name: webhook-service
|
||||||
|
# fieldPath: .metadata.name # namespace of the service
|
||||||
|
# targets:
|
||||||
|
# - select:
|
||||||
|
# kind: Certificate
|
||||||
|
# group: cert-manager.io
|
||||||
|
# version: v1
|
||||||
|
# fieldPaths:
|
||||||
|
# - .spec.dnsNames.0
|
||||||
|
# - .spec.dnsNames.1
|
||||||
|
# options:
|
||||||
|
# delimiter: '.'
|
||||||
|
# index: 0
|
||||||
|
# create: true
|
||||||
|
# - source:
|
||||||
|
# kind: Service
|
||||||
|
# version: v1
|
||||||
|
# name: webhook-service
|
||||||
|
# fieldPath: .metadata.namespace # namespace of the service
|
||||||
|
# targets:
|
||||||
|
# - select:
|
||||||
|
# kind: Certificate
|
||||||
|
# group: cert-manager.io
|
||||||
|
# version: v1
|
||||||
|
# fieldPaths:
|
||||||
|
# - .spec.dnsNames.0
|
||||||
|
# - .spec.dnsNames.1
|
||||||
|
# options:
|
||||||
|
# delimiter: '.'
|
||||||
|
# index: 1
|
||||||
|
# create: true
|
|
@ -0,0 +1,39 @@
|
||||||
|
# This patch inject a sidecar container which is a HTTP proxy for the
|
||||||
|
# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews.
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: controller-manager
|
||||||
|
namespace: system
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: kube-rbac-proxy
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- "ALL"
|
||||||
|
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.14.1
|
||||||
|
args:
|
||||||
|
- "--secure-listen-address=0.0.0.0:8443"
|
||||||
|
- "--upstream=http://127.0.0.1:8080/"
|
||||||
|
- "--logtostderr=true"
|
||||||
|
- "--v=0"
|
||||||
|
ports:
|
||||||
|
- containerPort: 8443
|
||||||
|
protocol: TCP
|
||||||
|
name: https
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 128Mi
|
||||||
|
requests:
|
||||||
|
cpu: 5m
|
||||||
|
memory: 64Mi
|
||||||
|
- name: manager
|
||||||
|
args:
|
||||||
|
- "--health-probe-bind-address=:8081"
|
||||||
|
- "--metrics-bind-address=127.0.0.1:8080"
|
||||||
|
- "--leader-elect"
|
|
@ -0,0 +1,10 @@
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: controller-manager
|
||||||
|
namespace: system
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: manager
|
|
@ -0,0 +1,8 @@
|
||||||
|
resources:
|
||||||
|
- manager.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
images:
|
||||||
|
- name: controller
|
||||||
|
newName: registry.zelda.io/zelda
|
||||||
|
newTag: "0907174632"
|
|
@ -0,0 +1,118 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
app.kubernetes.io/name: namespace
|
||||||
|
app.kubernetes.io/instance: system
|
||||||
|
app.kubernetes.io/component: manager
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: system
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: controller-manager
|
||||||
|
namespace: system
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
app.kubernetes.io/name: deployment
|
||||||
|
app.kubernetes.io/instance: controller-manager
|
||||||
|
app.kubernetes.io/component: manager
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
kubectl.kubernetes.io/default-container: manager
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
spec:
|
||||||
|
# TODO(user): Uncomment the following code to configure the nodeAffinity expression
|
||||||
|
# according to the platforms which are supported by your solution.
|
||||||
|
# It is considered best practice to support multiple architectures. You can
|
||||||
|
# build your manager image using the makefile target docker-buildx.
|
||||||
|
# affinity:
|
||||||
|
# nodeAffinity:
|
||||||
|
# requiredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
# nodeSelectorTerms:
|
||||||
|
# - matchExpressions:
|
||||||
|
# - key: kubernetes.io/arch
|
||||||
|
# operator: In
|
||||||
|
# values:
|
||||||
|
# - amd64
|
||||||
|
# - arm64
|
||||||
|
# - ppc64le
|
||||||
|
# - s390x
|
||||||
|
# - key: kubernetes.io/os
|
||||||
|
# operator: In
|
||||||
|
# values:
|
||||||
|
# - linux
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
# TODO(user): For common cases that do not require escalating privileges
|
||||||
|
# it is recommended to ensure that all your Pods/Containers are restrictive.
|
||||||
|
# More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted
|
||||||
|
# Please uncomment the following code if your project does NOT have to work on old Kubernetes
|
||||||
|
# versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ).
|
||||||
|
# seccompProfile:
|
||||||
|
# type: RuntimeDefault
|
||||||
|
containers:
|
||||||
|
- command:
|
||||||
|
- /manager
|
||||||
|
args:
|
||||||
|
- --leader-elect
|
||||||
|
image: controller:latest
|
||||||
|
name: manager
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- "ALL"
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 8081
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
periodSeconds: 20
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /readyz
|
||||||
|
port: 8081
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
# TODO(user): Configure the resources accordingly based on the project requirements.
|
||||||
|
# More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 128Mi
|
||||||
|
requests:
|
||||||
|
cpu: 10m
|
||||||
|
memory: 64Mi
|
||||||
|
serviceAccountName: controller-manager
|
||||||
|
terminationGracePeriodSeconds: 10
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: zelda-manager
|
||||||
|
namespace: system
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
control-plane: controller-manager
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 80
|
||||||
|
nodePort: 30080
|
||||||
|
type: NodePort
|
|
@ -0,0 +1,2 @@
|
||||||
|
resources:
|
||||||
|
- monitor.yaml
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
# Prometheus Monitor Service (Metrics)
|
||||||
|
apiVersion: monitoring.coreos.com/v1
|
||||||
|
kind: ServiceMonitor
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
app.kubernetes.io/name: servicemonitor
|
||||||
|
app.kubernetes.io/instance: controller-manager-metrics-monitor
|
||||||
|
app.kubernetes.io/component: metrics
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: controller-manager-metrics-monitor
|
||||||
|
namespace: system
|
||||||
|
spec:
|
||||||
|
endpoints:
|
||||||
|
- path: /metrics
|
||||||
|
port: https
|
||||||
|
scheme: https
|
||||||
|
bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||||
|
tlsConfig:
|
||||||
|
insecureSkipVerify: true
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
control-plane: controller-manager
|
|
@ -0,0 +1,16 @@
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: metrics-reader
|
||||||
|
app.kubernetes.io/component: kube-rbac-proxy
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: metrics-reader
|
||||||
|
rules:
|
||||||
|
- nonResourceURLs:
|
||||||
|
- "/metrics"
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,24 @@
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: proxy-role
|
||||||
|
app.kubernetes.io/component: kube-rbac-proxy
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: proxy-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- authentication.k8s.io
|
||||||
|
resources:
|
||||||
|
- tokenreviews
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- apiGroups:
|
||||||
|
- authorization.k8s.io
|
||||||
|
resources:
|
||||||
|
- subjectaccessreviews
|
||||||
|
verbs:
|
||||||
|
- create
|
|
@ -0,0 +1,19 @@
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrolebinding
|
||||||
|
app.kubernetes.io/instance: proxy-rolebinding
|
||||||
|
app.kubernetes.io/component: kube-rbac-proxy
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: proxy-rolebinding
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: proxy-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: controller-manager
|
||||||
|
namespace: system
|
|
@ -0,0 +1,21 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
app.kubernetes.io/name: service
|
||||||
|
app.kubernetes.io/instance: controller-manager-metrics-service
|
||||||
|
app.kubernetes.io/component: kube-rbac-proxy
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: controller-manager-metrics-service
|
||||||
|
namespace: system
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: https
|
||||||
|
port: 8443
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: https
|
||||||
|
selector:
|
||||||
|
control-plane: controller-manager
|
|
@ -0,0 +1,18 @@
|
||||||
|
resources:
|
||||||
|
# All RBAC will be applied under this service account in
|
||||||
|
# the deployment namespace. You may comment out this resource
|
||||||
|
# if your manager will use a service account that exists at
|
||||||
|
# runtime. Be sure to update RoleBinding and ClusterRoleBinding
|
||||||
|
# subjects if changing service account names.
|
||||||
|
- service_account.yaml
|
||||||
|
- role.yaml
|
||||||
|
- role_binding.yaml
|
||||||
|
- leader_election_role.yaml
|
||||||
|
- leader_election_role_binding.yaml
|
||||||
|
# Comment the following 4 lines if you want to disable
|
||||||
|
# the auth proxy (https://github.com/brancz/kube-rbac-proxy)
|
||||||
|
# which protects your /metrics endpoint.
|
||||||
|
- auth_proxy_service.yaml
|
||||||
|
- auth_proxy_role.yaml
|
||||||
|
- auth_proxy_role_binding.yaml
|
||||||
|
- auth_proxy_client_clusterrole.yaml
|
|
@ -0,0 +1,44 @@
|
||||||
|
# permissions to do leader election.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: role
|
||||||
|
app.kubernetes.io/instance: leader-election-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: leader-election-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- patch
|
||||||
|
- delete
|
||||||
|
- apiGroups:
|
||||||
|
- coordination.k8s.io
|
||||||
|
resources:
|
||||||
|
- leases
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- patch
|
||||||
|
- delete
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- events
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- patch
|
|
@ -0,0 +1,19 @@
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: rolebinding
|
||||||
|
app.kubernetes.io/instance: leader-election-rolebinding
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: leader-election-rolebinding
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: leader-election-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: controller-manager
|
||||||
|
namespace: system
|
|
@ -0,0 +1,502 @@
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: manager-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- '*'
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- '*'
|
||||||
|
resources:
|
||||||
|
- pods/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- '*'
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- '*'
|
||||||
|
resources:
|
||||||
|
- secrets/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- '*'
|
||||||
|
resources:
|
||||||
|
- secrets/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- '*'
|
||||||
|
resources:
|
||||||
|
- serviceaccounts
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- '*'
|
||||||
|
resources:
|
||||||
|
- serviceaccounts/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- '*'
|
||||||
|
resources:
|
||||||
|
- serviceaccounts/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- '*'
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- '*'
|
||||||
|
resources:
|
||||||
|
- services/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- apps
|
||||||
|
resources:
|
||||||
|
- deployments
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- apps
|
||||||
|
resources:
|
||||||
|
- deployments/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- batch
|
||||||
|
resources:
|
||||||
|
- jobs
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- batch
|
||||||
|
resources:
|
||||||
|
- jobs/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io/v1
|
||||||
|
resources:
|
||||||
|
- clusterrolebindings
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io/v1
|
||||||
|
resources:
|
||||||
|
- clusterrolebindings/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io/v1
|
||||||
|
resources:
|
||||||
|
- clusterrolebindings/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io/v1
|
||||||
|
resources:
|
||||||
|
- clusterroles
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io/v1
|
||||||
|
resources:
|
||||||
|
- clusterroles/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io/v1
|
||||||
|
resources:
|
||||||
|
- clusterroles/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io/v1
|
||||||
|
resources:
|
||||||
|
- rolebindings
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io/v1
|
||||||
|
resources:
|
||||||
|
- rolebindings/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io/v1
|
||||||
|
resources:
|
||||||
|
- rolebindings/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io/v1
|
||||||
|
resources:
|
||||||
|
- roles
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io/v1
|
||||||
|
resources:
|
||||||
|
- roles/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io/v1
|
||||||
|
resources:
|
||||||
|
- roles/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuilders
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuilders/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuilders/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuildtemplates
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuildtemplates/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuildtemplates/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zcustomhosts
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zcustomhosts/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zcustomhosts/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zgroups
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zgroups/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zgroups/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zprojects
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zprojects/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zprojects/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zregistries
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zregistries/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zregistries/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zruntemplates
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zruntemplates/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zruntemplates/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zscripts
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zscripts/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zscripts/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zservices
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zservices/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zservices/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zusers
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zusers/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zusers/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
|
@ -0,0 +1,19 @@
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrolebinding
|
||||||
|
app.kubernetes.io/instance: manager-rolebinding
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: manager-rolebinding
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: manager-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: controller-manager
|
||||||
|
namespace: system
|
|
@ -0,0 +1,12 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: serviceaccount
|
||||||
|
app.kubernetes.io/instance: controller-manager-sa
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: controller-manager
|
||||||
|
namespace: system
|
|
@ -0,0 +1,31 @@
|
||||||
|
# permissions for end users to edit zbuilders.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zbuilder-editor-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zbuilder-editor-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuilders
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuilders/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,27 @@
|
||||||
|
# permissions for end users to view zbuilders.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zbuilder-viewer-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zbuilder-viewer-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuilders
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuilders/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,31 @@
|
||||||
|
# permissions for end users to edit zbuildtemplates.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zbuildtemplate-editor-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zbuildtemplate-editor-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuildtemplates
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuildtemplates/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,27 @@
|
||||||
|
# permissions for end users to view zbuildtemplates.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zbuildtemplate-viewer-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zbuildtemplate-viewer-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuildtemplates
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zbuildtemplates/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,31 @@
|
||||||
|
# permissions for end users to edit zcustomhosts.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zcustomhost-editor-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zcustomhost-editor-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zcustomhosts
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zcustomhosts/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,27 @@
|
||||||
|
# permissions for end users to view zcustomhosts.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zcustomhost-viewer-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zcustomhost-viewer-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zcustomhosts
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zcustomhosts/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,31 @@
|
||||||
|
# permissions for end users to edit zgroups.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zgroup-editor-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zgroup-editor-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zgroups
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zgroups/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,27 @@
|
||||||
|
# permissions for end users to view zgroups.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zgroup-viewer-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zgroup-viewer-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zgroups
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zgroups/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,31 @@
|
||||||
|
# permissions for end users to edit zprojects.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zproject-editor-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zproject-editor-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zprojects
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zprojects/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,27 @@
|
||||||
|
# permissions for end users to view zprojects.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zproject-viewer-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zproject-viewer-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zprojects
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zprojects/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,31 @@
|
||||||
|
# permissions for end users to edit zregistries.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zregistry-editor-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zregistry-editor-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zregistries
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zregistries/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,27 @@
|
||||||
|
# permissions for end users to view zregistries.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zregistry-viewer-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zregistry-viewer-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zregistries
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zregistries/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,31 @@
|
||||||
|
# permissions for end users to edit zruntemplates.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zruntemplate-editor-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zruntemplate-editor-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zruntemplates
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zruntemplates/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,27 @@
|
||||||
|
# permissions for end users to view zruntemplates.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zruntemplate-viewer-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zruntemplate-viewer-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zruntemplates
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zruntemplates/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,31 @@
|
||||||
|
# permissions for end users to edit zscripts.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zscript-editor-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zscript-editor-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zscripts
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zscripts/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,27 @@
|
||||||
|
# permissions for end users to view zscripts.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zscript-viewer-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zscript-viewer-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zscripts
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zscripts/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,31 @@
|
||||||
|
# permissions for end users to edit zservices.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zservice-editor-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zservice-editor-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zservices
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zservices/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,27 @@
|
||||||
|
# permissions for end users to view zservices.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zservice-viewer-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zservice-viewer-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zservices
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zservices/status
|
||||||
|
verbs:
|
||||||
|
- get
|
|
@ -0,0 +1,31 @@
|
||||||
|
# permissions for end users to edit zusers.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: clusterrole
|
||||||
|
app.kubernetes.io/instance: zuser-editor-role
|
||||||
|
app.kubernetes.io/component: rbac
|
||||||
|
app.kubernetes.io/created-by: zelda
|
||||||
|
app.kubernetes.io/part-of: zelda
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: zuser-editor-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zusers
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- zelda.io
|
||||||
|
resources:
|
||||||
|
- zusers/status
|
||||||
|
verbs:
|
||||||
|
- get
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue