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