Merge pull request #510 from jenkinsci/operator-sdk-1.3.0
#494 Upgrade to Operator sdk 1.3.0
This commit is contained in:
commit
3dab502234
|
|
@ -0,0 +1,5 @@
|
||||||
|
# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file
|
||||||
|
# Ignore all files which are not go type
|
||||||
|
!**/*.go
|
||||||
|
!**/*.mod
|
||||||
|
!**/*.sum
|
||||||
|
|
@ -23,9 +23,6 @@ jobs:
|
||||||
echo "MINIKUBE_WANTUPDATENOTIFICATION=false" >> $GITHUB_ENV
|
echo "MINIKUBE_WANTUPDATENOTIFICATION=false" >> $GITHUB_ENV
|
||||||
echo "MINIKUBE_WANTREPORTERRORPROMPT=false" >> $GITHUB_ENV
|
echo "MINIKUBE_WANTREPORTERRORPROMPT=false" >> $GITHUB_ENV
|
||||||
echo "GO_VERSION=v$(sed -n 's/GO_VERSION=//p' config.base.env)" >> $GITHUB_ENV
|
echo "GO_VERSION=v$(sed -n 's/GO_VERSION=//p' config.base.env)" >> $GITHUB_ENV
|
||||||
echo "MINIKUBE_VERSION=v$(sed -n 's/MINIKUBE_VERSION=//p' config.minikube.env)" >> $GITHUB_ENV
|
|
||||||
echo "OPERATOR_SDK_VERSION=v$(sed -n 's/OPERATOR_SDK_VERSION=//p' config.base.env)" >> $GITHUB_ENV
|
|
||||||
echo "MINIKUBE_KUBERNETES_VERSION=$(sed -n 's/MINIKUBE_KUBERNETES_VERSION=//p' config.minikube.env)" >> $GITHUB_ENV
|
|
||||||
echo "HELM_VERSION=v$(sed -n 's/HELM_VERSION=//p' config.base.env)" >> $GITHUB_ENV
|
echo "HELM_VERSION=v$(sed -n 's/HELM_VERSION=//p' config.base.env)" >> $GITHUB_ENV
|
||||||
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
echo "GOPATH=/home/runner/go" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
|
@ -44,17 +41,12 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install socat
|
sudo apt-get install socat
|
||||||
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/$MINIKUBE_KUBERNETES_VERSION/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
|
|
||||||
curl -Lo minikube https://storage.googleapis.com/minikube/releases/$MINIKUBE_VERSION/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
|
|
||||||
curl -Lo operator-sdk https://github.com/operator-framework/operator-sdk/releases/download/$OPERATOR_SDK_VERSION/operator-sdk-$OPERATOR_SDK_VERSION-x86_64-linux-gnu && chmod +x operator-sdk && sudo mv operator-sdk /usr/local/bin/
|
|
||||||
curl -Lo helm.tar.gz https://get.helm.sh/helm-$HELM_VERSION-linux-amd64.tar.gz && tar xzfv helm.tar.gz && sudo mv linux-amd64/helm /usr/local/bin/
|
|
||||||
sudo mkdir -p $HOME/.kube $HOME/.minikube
|
sudo mkdir -p $HOME/.kube $HOME/.minikube
|
||||||
touch KUBECONFIG
|
|
||||||
sudo minikube start --vm-driver=none --kubernetes-version=$MINIKUBE_KUBERNETES_VERSION
|
|
||||||
sudo chown -R $USER $HOME/.kube $HOME/.minikube
|
sudo chown -R $USER $HOME/.kube $HOME/.minikube
|
||||||
|
make minikube-start MINIKUBE_DRIVER='docker' CPUS_NUMBER=2
|
||||||
|
|
||||||
- name: Jenkins Operator - e2e
|
- name: Jenkins Operator - e2e
|
||||||
run: make build e2e
|
run: |
|
||||||
|
make e2e E2E_TEST_ARGS='-ginkgo.v'
|
||||||
|
|
||||||
- name: Jenkins Operator Helm Chart - e2e
|
#TODO Helm e2e test
|
||||||
run: make e2e BUILDTAGS=Helm E2E_TEST_SELECTOR='^.*Helm.*$'
|
|
||||||
|
|
@ -88,3 +88,6 @@ tags
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
### IntelliJ IDEA ###
|
||||||
*.iml
|
*.iml
|
||||||
|
|
||||||
|
bin
|
||||||
|
testbin/*
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
ARG GO_VERSION
|
||||||
|
|
||||||
|
# Build the manager binary
|
||||||
|
FROM golang:$GO_VERSION as builder
|
||||||
|
ARG CTIMEVAR
|
||||||
|
|
||||||
|
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
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
# Copy the go source
|
||||||
|
COPY api/ api/
|
||||||
|
COPY controllers/ controllers/
|
||||||
|
COPY internal/ internal/
|
||||||
|
COPY pkg/ pkg/
|
||||||
|
COPY version/ version/
|
||||||
|
COPY main.go main.go
|
||||||
|
|
||||||
|
# Build
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -ldflags "-w $CTIMEVAR" -o manager 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"]
|
||||||
300
Makefile
300
Makefile
|
|
@ -1,74 +1,4 @@
|
||||||
# Set POSIX sh for maximum interoperability
|
include variables.mk
|
||||||
SHELL := /bin/sh
|
|
||||||
PATH := $(GOPATH)/bin:$(PATH)
|
|
||||||
|
|
||||||
OSFLAG :=
|
|
||||||
ifeq ($(OS),Windows_NT)
|
|
||||||
OSFLAG = WIN32
|
|
||||||
else
|
|
||||||
UNAME_S := $(shell uname -s)
|
|
||||||
ifeq ($(UNAME_S),Linux)
|
|
||||||
OSFLAG = LINUX
|
|
||||||
endif
|
|
||||||
ifeq ($(UNAME_S),Darwin)
|
|
||||||
OSFLAG = OSX
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
include config.base.env
|
|
||||||
|
|
||||||
# Import config
|
|
||||||
# You can change the default config with `make config="config_special.env" build`
|
|
||||||
config ?= config.minikube.env
|
|
||||||
include $(config)
|
|
||||||
|
|
||||||
# Set an output prefix, which is the local directory if not specified
|
|
||||||
PREFIX?=$(shell pwd)
|
|
||||||
|
|
||||||
VERSION := $(shell cat VERSION.txt)
|
|
||||||
GITCOMMIT := $(shell git rev-parse --short HEAD)
|
|
||||||
GITBRANCH := $(shell git rev-parse --abbrev-ref HEAD)
|
|
||||||
GITUNTRACKEDCHANGES := $(shell git status --porcelain --untracked-files=no)
|
|
||||||
GITIGNOREDBUTTRACKEDCHANGES := $(shell git ls-files -i --exclude-standard)
|
|
||||||
ifneq ($(GITUNTRACKEDCHANGES),)
|
|
||||||
GITCOMMIT := $(GITCOMMIT)-dirty
|
|
||||||
endif
|
|
||||||
ifneq ($(GITIGNOREDBUTTRACKEDCHANGES),)
|
|
||||||
GITCOMMIT := $(GITCOMMIT)-dirty
|
|
||||||
endif
|
|
||||||
|
|
||||||
VERSION_TAG := $(VERSION)
|
|
||||||
LATEST_TAG := latest
|
|
||||||
BUILD_TAG := $(GITBRANCH)-$(GITCOMMIT)
|
|
||||||
|
|
||||||
BUILD_PATH := ./cmd/manager
|
|
||||||
|
|
||||||
# CONTAINER_RUNTIME_COMMAND is Container Runtime - it could be docker or podman
|
|
||||||
CONTAINER_RUNTIME_COMMAND := docker
|
|
||||||
|
|
||||||
# Set any default go build tags
|
|
||||||
BUILDTAGS :=
|
|
||||||
|
|
||||||
# Set the build dir, where built cross-compiled binaries will be output
|
|
||||||
BUILDDIR := ${PREFIX}/cross
|
|
||||||
|
|
||||||
CTIMEVAR=-X $(PKG)/version.GitCommit=$(GITCOMMIT) -X $(PKG)/version.Version=$(VERSION)
|
|
||||||
GO_LDFLAGS=-ldflags "-w $(CTIMEVAR)"
|
|
||||||
GO_LDFLAGS_STATIC=-ldflags "-w $(CTIMEVAR) -extldflags -static"
|
|
||||||
|
|
||||||
# List the GOOS and GOARCH to build
|
|
||||||
GOOSARCHES = linux/amd64
|
|
||||||
|
|
||||||
PACKAGES = $(shell go list -f '{{.ImportPath}}/' ./... | grep -v vendor)
|
|
||||||
PACKAGES_FOR_UNIT_TESTS = $(shell go list -f '{{.ImportPath}}/' ./... | grep -v vendor | grep -v e2e)
|
|
||||||
|
|
||||||
# Run all the e2e tests by default
|
|
||||||
E2E_TEST_SELECTOR ?= .*
|
|
||||||
|
|
||||||
JENKINS_API_HOSTNAME := $(shell $(JENKINS_API_HOSTNAME_COMMAND) 2> /dev/null || echo "" )
|
|
||||||
OPERATOR_ARGS ?= --jenkins-api-hostname=$(JENKINS_API_HOSTNAME) --jenkins-api-port=$(JENKINS_API_PORT) --jenkins-api-use-nodeport=$(JENKINS_API_USE_NODEPORT) --cluster-domain=$(CLUSTER_DOMAIN) $(OPERATOR_EXTRA_ARGS)
|
|
||||||
|
|
||||||
.DEFAULT_GOAL := help
|
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: status checkmake clean build verify install container-runtime-build container-runtime-images ## Build the image
|
all: status checkmake clean build verify install container-runtime-build container-runtime-images ## Build the image
|
||||||
|
|
@ -121,7 +51,7 @@ build: deepcopy-gen $(NAME) ## Builds a dynamic executable or package
|
||||||
.PHONY: $(NAME)
|
.PHONY: $(NAME)
|
||||||
$(NAME): $(wildcard *.go) $(wildcard */*.go) VERSION.txt
|
$(NAME): $(wildcard *.go) $(wildcard */*.go) VERSION.txt
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
CGO_ENABLED=0 go build -tags "$(BUILDTAGS)" ${GO_LDFLAGS} -o build/_output/bin/jenkins-operator $(BUILD_PATH)
|
CGO_ENABLED=0 go build -tags "$(BUILDTAGS)" ${GO_LDFLAGS} -o bin/manager $(BUILD_PATH)
|
||||||
|
|
||||||
.PHONY: static
|
.PHONY: static
|
||||||
static: ## Builds a static executable
|
static: ## Builds a static executable
|
||||||
|
|
@ -136,22 +66,22 @@ fmt: ## Verifies all files have been `gofmt`ed
|
||||||
@go fmt $(PACKAGES)
|
@go fmt $(PACKAGES)
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
HAS_GOLINT := $(shell which golangci-lint)
|
HAS_GOLINT := $(shell which $(PROJECT_DIR)/bin/golangci-lint)
|
||||||
lint: ## Verifies `golint` passes
|
lint: ## Verifies `golint` passes
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
ifndef HAS_GOLINT
|
ifndef HAS_GOLINT
|
||||||
go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.26.0
|
$(call go-get-tool,$(PROJECT_DIR)/bin/golangci-lint,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.26.0)
|
||||||
endif
|
endif
|
||||||
@golangci-lint run
|
@bin/golangci-lint run
|
||||||
|
|
||||||
.PHONY: goimports
|
.PHONY: goimports
|
||||||
HAS_GOIMPORTS := $(shell which goimports)
|
HAS_GOIMPORTS := $(shell which $(PROJECT_DIR)/bin/goimports)
|
||||||
goimports: ## Verifies `goimports` passes
|
goimports: ## Verifies `goimports` passes
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
ifndef HAS_GOIMPORTS
|
ifndef HAS_GOIMPORTS
|
||||||
go get -u golang.org/x/tools/cmd/goimports
|
$(call go-get-tool,$(PROJECT_DIR)/bin/goimports,golang.org/x/tools/cmd/goimports@v0.1.0)
|
||||||
endif
|
endif
|
||||||
@goimports -l -e $(shell find . -type f -name '*.go' -not -path "./vendor/*")
|
@bin/goimports -l -e $(shell find . -type f -name '*.go' -not -path "./vendor/*")
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: ## Runs the go tests
|
test: ## Runs the go tests
|
||||||
|
|
@ -159,47 +89,10 @@ test: ## Runs the go tests
|
||||||
@RUNNING_TESTS=1 go test -tags "$(BUILDTAGS) cgo" $(PACKAGES_FOR_UNIT_TESTS)
|
@RUNNING_TESTS=1 go test -tags "$(BUILDTAGS) cgo" $(PACKAGES_FOR_UNIT_TESTS)
|
||||||
|
|
||||||
.PHONY: e2e
|
.PHONY: e2e
|
||||||
CURRENT_DIRECTORY := $(shell pwd)
|
e2e: deepcopy-gen ## Runs e2e tests, you can use EXTRA_ARGS
|
||||||
e2e: container-runtime-build ## Runs e2e tests, you can use EXTRA_ARGS
|
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
@echo "Docker image: $(DOCKER_REGISTRY):$(GITCOMMIT)"
|
|
||||||
ifeq ($(KUBERNETES_PROVIDER),minikube)
|
|
||||||
kubectl config use-context $(KUBECTL_CONTEXT)
|
|
||||||
endif
|
|
||||||
ifeq ($(KUBERNETES_PROVIDER),crc)
|
|
||||||
oc project $(CRC_OC_PROJECT)
|
|
||||||
endif
|
|
||||||
cp deploy/service_account.yaml deploy/namespace-init.yaml
|
|
||||||
cat deploy/role.yaml >> deploy/namespace-init.yaml
|
|
||||||
cat deploy/role_binding.yaml >> deploy/namespace-init.yaml
|
|
||||||
cat deploy/operator.yaml >> deploy/namespace-init.yaml
|
|
||||||
ifeq ($(OSFLAG), LINUX)
|
|
||||||
ifeq ($(IMAGE_PULL_MODE), remote)
|
|
||||||
sed -i 's|\(image:\).*|\1 $(DOCKER_ORGANIZATION)/$(DOCKER_REGISTRY):$(GITCOMMIT)|g' deploy/namespace-init.yaml
|
|
||||||
sed -i 's|\(imagePullPolicy\): IfNotPresent|\1: Always|g' deploy/namespace-init.yaml
|
|
||||||
else
|
|
||||||
sed -i 's|\(image:\).*|\1 $(DOCKER_REGISTRY):$(GITCOMMIT)|g' deploy/namespace-init.yaml
|
|
||||||
endif
|
|
||||||
ifeq ($(KUBERNETES_PROVIDER),minikube)
|
|
||||||
sed -i 's|\(imagePullPolicy\): IfNotPresent|\1: Never|g' deploy/namespace-init.yaml
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(OSFLAG), OSX)
|
|
||||||
ifeq ($(IMAGE_PULL_MODE), remote)
|
|
||||||
sed -i '' 's|\(image:\).*|\1 $(DOCKER_ORGANIZATION)/$(DOCKER_REGISTRY):$(GITCOMMIT)|g' deploy/namespace-init.yaml
|
|
||||||
sed -i '' 's|\(imagePullPolicy\): IfNotPresent|\1: Always|g' deploy/namespace-init.yaml
|
|
||||||
else
|
|
||||||
sed -i '' 's|\(image:\).*|\1 $(DOCKER_REGISTRY):$(GITCOMMIT)|g' deploy/namespace-init.yaml
|
|
||||||
endif
|
|
||||||
ifeq ($(KUBERNETES_PROVIDER),minikube)
|
|
||||||
sed -i '' 's|\(imagePullPolicy\): IfNotPresent|\1: Never|g' deploy/namespace-init.yaml
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
RUNNING_TESTS=1 go test -parallel=1 "./test/e2e/" -tags "$(BUILDTAGS) cgo" -v -timeout 60m -run "$(E2E_TEST_SELECTOR)" \
|
RUNNING_TESTS=1 go test -parallel=1 "./test/e2e/" -tags "$(BUILDTAGS) cgo" -v -timeout 60m -run "$(E2E_TEST_SELECTOR)" \
|
||||||
-root=$(CURRENT_DIRECTORY) -kubeconfig=$(HOME)/.kube/config -globalMan deploy/crds/jenkins_$(API_VERSION)_jenkins_crd.yaml \
|
-jenkins-api-hostname=$(JENKINS_API_HOSTNAME) -jenkins-api-port=$(JENKINS_API_PORT) -jenkins-api-use-nodeport=$(JENKINS_API_USE_NODEPORT) $(E2E_TEST_ARGS)
|
||||||
-namespacedMan deploy/namespace-init.yaml $(TEST_ARGS)
|
|
||||||
|
|
||||||
.PHONY: vet
|
.PHONY: vet
|
||||||
vet: ## Verifies `go vet` passes
|
vet: ## Verifies `go vet` passes
|
||||||
|
|
@ -207,17 +100,18 @@ vet: ## Verifies `go vet` passes
|
||||||
@go vet $(PACKAGES)
|
@go vet $(PACKAGES)
|
||||||
|
|
||||||
.PHONY: staticcheck
|
.PHONY: staticcheck
|
||||||
HAS_STATICCHECK := $(shell which staticcheck)
|
HAS_STATICCHECK := $(shell which $(PROJECT_DIR)/bin/staticcheck)
|
||||||
PLATFORM = $(shell echo $(UNAME_S) | tr A-Z a-z)
|
|
||||||
staticcheck: ## Verifies `staticcheck` passes
|
staticcheck: ## Verifies `staticcheck` passes
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
ifndef HAS_STATICCHECK
|
ifndef HAS_STATICCHECK
|
||||||
wget -O staticcheck_$(PLATFORM)_amd64.tar.gz https://github.com/dominikh/go-tools/releases/download/2020.1.3/staticcheck_$(PLATFORM)_amd64.tar.gz
|
$(eval TMP_DIR := $(shell mktemp -d))
|
||||||
tar zxvf staticcheck_$(PLATFORM)_amd64.tar.gz
|
wget -O $(TMP_DIR)/staticcheck_$(PLATFORM)_amd64.tar.gz https://github.com/dominikh/go-tools/releases/download/2020.1.3/staticcheck_$(PLATFORM)_amd64.tar.gz
|
||||||
mkdir -p $(GOPATH)/bin
|
tar zxvf $(TMP_DIR)/staticcheck_$(PLATFORM)_amd64.tar.gz -C $(TMP_DIR)
|
||||||
mv staticcheck/staticcheck $(GOPATH)/bin
|
mkdir -p $(PROJECT_DIR)/bin
|
||||||
|
mv $(TMP_DIR)/staticcheck/staticcheck $(PROJECT_DIR)/bin
|
||||||
|
rm -rf $(TMP_DIR)
|
||||||
endif
|
endif
|
||||||
@staticcheck $(PACKAGES)
|
@$(PROJECT_DIR)/bin/staticcheck $(PACKAGES)
|
||||||
|
|
||||||
.PHONY: cover
|
.PHONY: cover
|
||||||
cover: ## Runs go test with coverage
|
cover: ## Runs go test with coverage
|
||||||
|
|
@ -242,7 +136,7 @@ install: ## Installs the executable
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: export WATCH_NAMESPACE = $(NAMESPACE)
|
run: export WATCH_NAMESPACE = $(NAMESPACE)
|
||||||
run: export OPERATOR_NAME = $(NAME)
|
run: export OPERATOR_NAME = $(NAME)
|
||||||
run: build ## Run the executable, you can use EXTRA_ARGS
|
run: fmt vet manifests install-crds build ## Run the executable, you can use EXTRA_ARGS
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
ifeq ($(KUBERNETES_PROVIDER),minikube)
|
ifeq ($(KUBERNETES_PROVIDER),minikube)
|
||||||
kubectl config use-context $(KUBECTL_CONTEXT)
|
kubectl config use-context $(KUBECTL_CONTEXT)
|
||||||
|
|
@ -250,10 +144,8 @@ endif
|
||||||
ifeq ($(KUBERNETES_PROVIDER),crc)
|
ifeq ($(KUBERNETES_PROVIDER),crc)
|
||||||
oc project $(CRC_OC_PROJECT)
|
oc project $(CRC_OC_PROJECT)
|
||||||
endif
|
endif
|
||||||
kubectl apply -f deploy/crds/jenkins_$(API_VERSION)_jenkins_crd.yaml
|
|
||||||
kubectl apply -f deploy/crds/jenkins_$(API_VERSION)_jenkinsimage_crd.yaml
|
|
||||||
@echo "Watching '$(WATCH_NAMESPACE)' namespace"
|
@echo "Watching '$(WATCH_NAMESPACE)' namespace"
|
||||||
build/_output/bin/jenkins-operator $(OPERATOR_ARGS)
|
bin/manager $(OPERATOR_ARGS)
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean: ## Cleanup any build binaries or packages
|
clean: ## Cleanup any build binaries or packages
|
||||||
|
|
@ -309,13 +201,13 @@ container-runtime-login: ## Log in into the Docker repository
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
|
|
||||||
.PHONY: container-runtime-build
|
.PHONY: container-runtime-build
|
||||||
container-runtime-build: check-env ## Build the container
|
container-runtime-build: check-env deepcopy-gen ## Build the container
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
$(CONTAINER_RUNTIME_COMMAND) build \
|
$(CONTAINER_RUNTIME_COMMAND) build \
|
||||||
--build-arg GO_VERSION=$(GO_VERSION) \
|
--build-arg GO_VERSION=$(GO_VERSION) \
|
||||||
--build-arg OPERATOR_SDK_VERSION=$(OPERATOR_SDK_VERSION) \
|
--build-arg CTIMEVAR="$(CTIMEVAR)" \
|
||||||
-t $(DOCKER_REGISTRY):$(GITCOMMIT) . \
|
-t $(DOCKER_REGISTRY):$(GITCOMMIT) . \
|
||||||
--file build/Dockerfile $(CONTAINER_RUNTIME_EXTRA_ARGS)
|
--file Dockerfile $(CONTAINER_RUNTIME_EXTRA_ARGS)
|
||||||
|
|
||||||
.PHONY: container-runtime-images
|
.PHONY: container-runtime-images
|
||||||
container-runtime-images: ## List all local containers
|
container-runtime-images: ## List all local containers
|
||||||
|
|
@ -368,27 +260,18 @@ container-runtime-run: ## Run the container in docker, you can use EXTRA_ARGS
|
||||||
.PHONY: minikube-run
|
.PHONY: minikube-run
|
||||||
minikube-run: export WATCH_NAMESPACE = $(NAMESPACE)
|
minikube-run: export WATCH_NAMESPACE = $(NAMESPACE)
|
||||||
minikube-run: export OPERATOR_NAME = $(NAME)
|
minikube-run: export OPERATOR_NAME = $(NAME)
|
||||||
minikube-run: minikube-start ## Run the operator locally and use minikube as Kubernetes cluster, you can use OPERATOR_ARGS
|
minikube-run: minikube-start run ## Run the operator locally and use minikube as Kubernetes cluster, you can use OPERATOR_ARGS
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
kubectl config use-context minikube
|
|
||||||
kubectl apply -f deploy/crds/jenkins_$(API_VERSION)_jenkins_crd.yaml
|
|
||||||
@echo "Watching '$(WATCH_NAMESPACE)' namespace"
|
|
||||||
build/_output/bin/jenkins-operator $(OPERATOR_ARGS)
|
|
||||||
|
|
||||||
.PHONY: crc-run
|
.PHONY: crc-run
|
||||||
crc-run: export WATCH_NAMESPACE = $(NAMESPACE)
|
crc-run: export WATCH_NAMESPACE = $(NAMESPACE)
|
||||||
crc-run: export OPERATOR_NAME = $(NAME)
|
crc-run: export OPERATOR_NAME = $(NAME)
|
||||||
crc-run: crc-start ## Run the operator locally and use CodeReady Containers as Kubernetes cluster, you can use OPERATOR_ARGS
|
crc-run: crc-start run ## Run the operator locally and use CodeReady Containers as Kubernetes cluster, you can use OPERATOR_ARGS
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
oc project $(CRC_OC_PROJECT)
|
|
||||||
kubectl apply -f deploy/crds/jenkins_$(API_VERSION)_jenkins_crd.yaml
|
|
||||||
@echo "Watching '$(WATCH_NAMESPACE)' namespace"
|
|
||||||
build/_output/bin/jenkins-operator $(OPERATOR_ARGS)
|
|
||||||
|
|
||||||
.PHONY: deepcopy-gen
|
.PHONY: deepcopy-gen
|
||||||
deepcopy-gen: ## Generate deepcopy golang code
|
deepcopy-gen: generate ## Generate deepcopy golang code
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
operator-sdk generate k8s
|
|
||||||
|
|
||||||
.PHONY: scheme-doc-gen
|
.PHONY: scheme-doc-gen
|
||||||
HAS_GEN_CRD_API_REFERENCE_DOCS := $(shell ls gen-crd-api-reference-docs 2> /dev/null)
|
HAS_GEN_CRD_API_REFERENCE_DOCS := $(shell ls gen-crd-api-reference-docs 2> /dev/null)
|
||||||
|
|
@ -400,7 +283,7 @@ ifndef HAS_GEN_CRD_API_REFERENCE_DOCS
|
||||||
@tar -C $(GEN_CRD_API) -zxf $(GEN_CRD_API)_linux_amd64.tar.gz
|
@tar -C $(GEN_CRD_API) -zxf $(GEN_CRD_API)_linux_amd64.tar.gz
|
||||||
@rm $(GEN_CRD_API)_linux_amd64.tar.gz
|
@rm $(GEN_CRD_API)_linux_amd64.tar.gz
|
||||||
endif
|
endif
|
||||||
$(GEN_CRD_API)/$(GEN_CRD_API) -config gen-crd-api-config.json -api-dir github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/$(API_VERSION) -template-dir $(GEN_CRD_API)/template -out-file documentation/$(VERSION)/jenkins-$(API_VERSION)-scheme.md
|
$(GEN_CRD_API)/$(GEN_CRD_API) -config gen-crd-api-config.json -api-dir $(PKG)/api/$(API_VERSION) -template-dir $(GEN_CRD_API)/template -out-file documentation/$(VERSION)/jenkins-$(API_VERSION)-scheme.md
|
||||||
|
|
||||||
.PHONY: check-minikube
|
.PHONY: check-minikube
|
||||||
check-minikube: ## Checks if KUBERNETES_PROVIDER is set to minikube
|
check-minikube: ## Checks if KUBERNETES_PROVIDER is set to minikube
|
||||||
|
|
@ -418,23 +301,41 @@ ifneq ($(KUBERNETES_PROVIDER),crc)
|
||||||
$(error KUBERNETES_PROVIDER not set to 'crc')
|
$(error KUBERNETES_PROVIDER not set to 'crc')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: minikube-start
|
.PHONY: minikube
|
||||||
minikube-start: check-minikube ## Start minikube
|
HAS_MINIKUBE := $(shell which $(PROJECT_DIR)/bin/minikube)
|
||||||
|
minikube: ## Download minikube if it's not present
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
@minikube status && exit 0 || \
|
ifndef HAS_MINIKUBE
|
||||||
minikube start --kubernetes-version $(MINIKUBE_KUBERNETES_VERSION) --dns-domain=$(CLUSTER_DOMAIN) --extra-config=kubelet.cluster-domain=$(CLUSTER_DOMAIN) --vm-driver=$(MINIKUBE_DRIVER) --memory 4096 --cpus 3
|
mkdir -p $(PROJECT_DIR)/bin
|
||||||
|
wget -O $(PROJECT_DIR)/bin/minikube https://github.com/kubernetes/minikube/releases/download/v$(MINIKUBE_VERSION)/minikube-$(PLATFORM)-amd64
|
||||||
|
chmod +x $(PROJECT_DIR)/bin/minikube
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: minikube-start
|
||||||
|
minikube-start: minikube check-minikube ## Start minikube
|
||||||
|
@echo "+ $@"
|
||||||
|
bin/minikube status && exit 0 || \
|
||||||
|
bin/minikube start --kubernetes-version $(MINIKUBE_KUBERNETES_VERSION) --dns-domain=$(CLUSTER_DOMAIN) --extra-config=kubelet.cluster-domain=$(CLUSTER_DOMAIN) --driver=$(MINIKUBE_DRIVER) --memory 4096 --cpus $(CPUS_NUMBER)
|
||||||
|
|
||||||
.PHONY: crc-start
|
.PHONY: crc-start
|
||||||
crc-start: check-crc ## Start CodeReady Containers Kubernetes cluster
|
crc-start: check-crc ## Start CodeReady Containers Kubernetes cluster
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
crc start
|
crc start
|
||||||
|
|
||||||
|
.PHONY: sembump
|
||||||
|
HAS_SEMBUMP := $(shell which $(PROJECT_DIR)/bin/sembump)
|
||||||
|
sembump: # Download sembump locally if necessary
|
||||||
|
@echo "+ $@"
|
||||||
|
ifndef HAS_SEMBUMP
|
||||||
|
wget -O $(PROJECT_DIR)/bin/sembump https://github.com/justintout/sembump/releases/download/v0.1.0/sembump-$(PLATFORM)-amd64
|
||||||
|
chmod +x $(PROJECT_DIR)/bin/sembump
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: bump-version
|
.PHONY: bump-version
|
||||||
BUMP := patch
|
BUMP := patch
|
||||||
bump-version: ## Bump the version in the version file. Set BUMP to [ patch | major | minor ]
|
bump-version: sembump ## Bump the version in the version file. Set BUMP to [ patch | major | minor ]
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
#@go get -u github.com/jessfraz/junk/sembump # update sembump tool FIXME
|
$(eval NEW_VERSION=$(shell bin/sembump --kind $(BUMP) $(VERSION)))
|
||||||
$(eval NEW_VERSION=$(shell sembump --kind $(BUMP) $(VERSION)))
|
|
||||||
@echo "Bumping VERSION.txt from $(VERSION) to $(NEW_VERSION)"
|
@echo "Bumping VERSION.txt from $(VERSION) to $(NEW_VERSION)"
|
||||||
echo $(NEW_VERSION) > VERSION.txt
|
echo $(NEW_VERSION) > VERSION.txt
|
||||||
@echo "Updating version from $(VERSION) to $(NEW_VERSION) in README.md"
|
@echo "Updating version from $(VERSION) to $(NEW_VERSION) in README.md"
|
||||||
|
|
@ -493,8 +394,101 @@ helm-deploy: helm-package
|
||||||
helm repo index chart/ --url https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/chart/jenkins-operator/
|
helm repo index chart/ --url https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/chart/jenkins-operator/
|
||||||
cd chart/ && mv jenkins-operator-*.tgz jenkins-operator
|
cd chart/ && mv jenkins-operator-*.tgz jenkins-operator
|
||||||
|
|
||||||
|
# Download hugo locally if necessary
|
||||||
|
HUGO = $(shell pwd)/bin/hugo
|
||||||
|
hugo:
|
||||||
|
$(call go-get-tool,$(HUGO),github.com/gohugoio/hugo@v0.62.2)
|
||||||
|
|
||||||
.PHONY: generate-docs
|
.PHONY: generate-docs
|
||||||
generate-docs: ## Re-generate docs directory from the website directory
|
generate-docs: hugo ## Re-generate docs directory from the website directory
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
rm -rf docs || echo "Cannot remove docs dir, ignoring"
|
rm -rf docs || echo "Cannot remove docs dir, ignoring"
|
||||||
hugo -s website -d ../docs
|
bin/hugo -s website -d ../docs
|
||||||
|
|
||||||
|
.PHONY: all-in-one-build
|
||||||
|
FILENAME := config/all_in_one_$(API_VERSION).yaml
|
||||||
|
all-in-one-build: ## Re-generate all-in-one yaml
|
||||||
|
@echo "+ $@"
|
||||||
|
> $(FILENAME)
|
||||||
|
cat config/rbac/leader_election_role.yaml >> $(FILENAME)
|
||||||
|
cat config/rbac/leader_election_role_binding.yaml >> $(FILENAME)
|
||||||
|
cat config/rbac/role.yaml >> $(FILENAME)
|
||||||
|
cat config/rbac/role_binding.yaml >> $(FILENAME)
|
||||||
|
cat config/manager/manager.yaml >> $(FILENAME)
|
||||||
|
|
||||||
|
##################### FROM OPERATOR SDK ########################
|
||||||
|
# Install CRDs into a cluster
|
||||||
|
install-crds: manifests kustomize
|
||||||
|
$(KUSTOMIZE) build config/crd | kubectl apply -f -
|
||||||
|
|
||||||
|
# Uninstall CRDs from a cluster
|
||||||
|
uninstall-crds: manifests kustomize
|
||||||
|
$(KUSTOMIZE) build config/crd | kubectl delete -f -
|
||||||
|
|
||||||
|
# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
|
||||||
|
deploy: manifests kustomize
|
||||||
|
cd config/manager && $(KUSTOMIZE) edit set image controller=$(DOCKER_REGISTRY):$(GITCOMMIT)
|
||||||
|
$(KUSTOMIZE) build config/default | kubectl apply -f -
|
||||||
|
|
||||||
|
# UnDeploy controller from the configured Kubernetes cluster in ~/.kube/config
|
||||||
|
undeploy:
|
||||||
|
$(KUSTOMIZE) build config/default | kubectl delete -f -
|
||||||
|
|
||||||
|
# Generate manifests e.g. CRD, RBAC etc.
|
||||||
|
manifests: controller-gen all-in-one-build
|
||||||
|
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
|
||||||
|
|
||||||
|
# Generate code
|
||||||
|
generate: controller-gen
|
||||||
|
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
|
||||||
|
|
||||||
|
# Download controller-gen locally if necessary
|
||||||
|
CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
|
||||||
|
controller-gen:
|
||||||
|
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.4.1)
|
||||||
|
|
||||||
|
# Download kustomize locally if necessary
|
||||||
|
KUSTOMIZE = $(shell pwd)/bin/kustomize
|
||||||
|
kustomize:
|
||||||
|
$(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v3@v3.8.7)
|
||||||
|
|
||||||
|
# go-get-tool will 'go get' any package $2 and install it to $1.
|
||||||
|
define go-get-tool
|
||||||
|
@[ -f $(1) ] || { \
|
||||||
|
set -e ;\
|
||||||
|
TMP_DIR=$$(mktemp -d) ;\
|
||||||
|
cd $$TMP_DIR ;\
|
||||||
|
go mod init tmp ;\
|
||||||
|
echo "Downloading $(2)" ;\
|
||||||
|
GOBIN=$(PROJECT_DIR)/bin go get $(2) ;\
|
||||||
|
rm -rf $$TMP_DIR ;\
|
||||||
|
}
|
||||||
|
endef
|
||||||
|
|
||||||
|
.PHONY: operator-sdk
|
||||||
|
HAS_OPERATOR_SDK := $(shell which $(PROJECT_DIR)/bin/operator-sdk)
|
||||||
|
operator-sdk: # Download operator-sdk locally if necessary
|
||||||
|
@echo "+ $@"
|
||||||
|
ifndef HAS_OPERATOR_SDK
|
||||||
|
wget -O $(PROJECT_DIR)/bin/operator-sdk https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/operator-sdk_$(PLATFORM)_amd64
|
||||||
|
chmod +x $(PROJECT_DIR)/bin/operator-sdk
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Generate bundle manifests and metadata, then validate generated files.
|
||||||
|
.PHONY: bundle
|
||||||
|
bundle: manifests operator-sdk kustomize
|
||||||
|
bin/operator-sdk generate kustomize manifests -q
|
||||||
|
cd config/manager && $(KUSTOMIZE) edit set image controller=$(DOCKER_ORGANIZATION)/$(DOCKER_REGISTRY):$(VERSION_TAG)
|
||||||
|
$(KUSTOMIZE) build config/manifests | bin/operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)
|
||||||
|
bin/operator-sdk bundle validate ./bundle
|
||||||
|
|
||||||
|
# Build the bundle image.
|
||||||
|
.PHONY: bundle-build
|
||||||
|
bundle-build:
|
||||||
|
docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) .
|
||||||
|
|
||||||
|
# Download kubebuilder
|
||||||
|
kubebuilder:
|
||||||
|
mkdir -p ${ENVTEST_ASSETS_DIR}
|
||||||
|
test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.7.0/hack/setup-envtest.sh
|
||||||
|
source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR);
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
domain: jenkins.io
|
||||||
|
layout: go.kubebuilder.io/v3
|
||||||
|
projectName: jenkins-operator
|
||||||
|
repo: github.com/jenkinsci/kubernetes-operator
|
||||||
|
resources:
|
||||||
|
- crdVersion: v1
|
||||||
|
group: jenkins.io
|
||||||
|
kind: Jenkins
|
||||||
|
version: v1alpha2
|
||||||
|
version: 3-alpha
|
||||||
|
plugins:
|
||||||
|
manifests.sdk.operatorframework.io/v2: {}
|
||||||
|
scorecard.sdk.operatorframework.io/v2: {}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// Package v1alpha2 contains API Schema definitions for the jenkins.io v1alpha2 API group
|
// Package v1alpha2 contains API Schema definitions for the jenkins.io v1alpha2 API group
|
||||||
// +k8s:deepcopy-gen=package,register
|
// +k8s:deepcopy-gen=package,register
|
||||||
|
// +kubebuilder:object:generate=true
|
||||||
// +groupName=jenkins.io
|
// +groupName=jenkins.io
|
||||||
package v1alpha2
|
package v1alpha2
|
||||||
|
|
@ -6,7 +6,7 @@ import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JenkinsSpec defines the desired state of the Jenkins.
|
// JenkinsSpec defines the desired state of Jenkins
|
||||||
// +k8s:openapi-gen=true
|
// +k8s:openapi-gen=true
|
||||||
type JenkinsSpec struct {
|
type JenkinsSpec struct {
|
||||||
// Master represents Jenkins master pod properties and Jenkins plugins.
|
// Master represents Jenkins master pod properties and Jenkins plugins.
|
||||||
|
|
@ -264,14 +264,6 @@ type JenkinsMaster struct {
|
||||||
// +optional
|
// +optional
|
||||||
Annotations map[string]string `json:"annotations,omitempty"`
|
Annotations map[string]string `json:"annotations,omitempty"`
|
||||||
|
|
||||||
// Annotations is an unstructured key value map stored with a resource that may be
|
|
||||||
// set by external tools to store and retrieve arbitrary metadata. They are not
|
|
||||||
// queryable and should be preserved when modifying objects.
|
|
||||||
// More info: http://kubernetes.io/docs/user-guide/annotations
|
|
||||||
// Deprecated: will be removed in the future, please use Annotations(annotations)
|
|
||||||
// +optional
|
|
||||||
AnnotationsDeprecated map[string]string `json:"masterAnnotations,omitempty"`
|
|
||||||
|
|
||||||
// Map of string keys and values that can be used to organize and categorize
|
// Map of string keys and values that can be used to organize and categorize
|
||||||
// (scope and select) objects. May match selectors of replication controllers
|
// (scope and select) objects. May match selectors of replication controllers
|
||||||
// and services.
|
// and services.
|
||||||
|
|
@ -489,12 +481,13 @@ type JenkinsStatus struct {
|
||||||
AppliedGroovyScripts []AppliedGroovyScript `json:"appliedGroovyScripts,omitempty"`
|
AppliedGroovyScripts []AppliedGroovyScript `json:"appliedGroovyScripts,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
// +kubebuilder:subresource:status
|
||||||
// +genclient
|
// +genclient
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
// Jenkins is the Schema for the jenkins API
|
// Jenkins is the Schema for the jenkins API
|
||||||
// +k8s:openapi-gen=true
|
// +k8s:openapi-gen=true
|
||||||
// +kubebuilder:subresource:status
|
|
||||||
type Jenkins struct {
|
type Jenkins struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
@ -506,9 +499,10 @@ type Jenkins struct {
|
||||||
Status JenkinsStatus `json:"status,omitempty"`
|
Status JenkinsStatus `json:"status,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
// JenkinsList contains a list of Jenkins.
|
// JenkinsList contains a list of Jenkins
|
||||||
type JenkinsList struct {
|
type JenkinsList struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
metav1.ListMeta `json:"metadata,omitempty"`
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
|
@ -15,11 +15,17 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// GroupVersion is group version used to register these objects
|
||||||
|
GroupVersion = schema.GroupVersion{Group: "jenkins.io", Version: "v1alpha2"}
|
||||||
|
|
||||||
// SchemeGroupVersion is group version used to register these objects
|
// SchemeGroupVersion is group version used to register these objects
|
||||||
SchemeGroupVersion = schema.GroupVersion{Group: "jenkins.io", Version: "v1alpha2"}
|
SchemeGroupVersion = schema.GroupVersion{Group: "jenkins.io", Version: "v1alpha2"}
|
||||||
|
|
||||||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
|
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
|
||||||
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
|
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
|
||||||
|
|
||||||
|
// AddToScheme adds the types in this group-version to the given scheme.
|
||||||
|
AddToScheme = SchemeBuilder.AddToScheme
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetObjectKind returns Jenkins object kind
|
// GetObjectKind returns Jenkins object kind
|
||||||
|
|
@ -47,5 +53,4 @@ func JenkinsTypeMeta() metav1.TypeMeta {
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
SchemeBuilder.Register(&Jenkins{}, &JenkinsList{})
|
SchemeBuilder.Register(&Jenkins{}, &JenkinsList{})
|
||||||
SchemeBuilder.Register(&JenkinsImage{}, &JenkinsImageList{})
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,11 +1,27 @@
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
// Code generated by operator-sdk. DO NOT EDIT.
|
/*
|
||||||
|
Copyright 2021.
|
||||||
|
|
||||||
|
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 v1alpha2
|
package v1alpha2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
v1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
@ -13,7 +29,6 @@ import (
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *AppliedGroovyScript) DeepCopyInto(out *AppliedGroovyScript) {
|
func (in *AppliedGroovyScript) DeepCopyInto(out *AppliedGroovyScript) {
|
||||||
*out = *in
|
*out = *in
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppliedGroovyScript.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppliedGroovyScript.
|
||||||
|
|
@ -30,7 +45,6 @@ func (in *AppliedGroovyScript) DeepCopy() *AppliedGroovyScript {
|
||||||
func (in *Backup) DeepCopyInto(out *Backup) {
|
func (in *Backup) DeepCopyInto(out *Backup) {
|
||||||
*out = *in
|
*out = *in
|
||||||
in.Action.DeepCopyInto(&out.Action)
|
in.Action.DeepCopyInto(&out.Action)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backup.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backup.
|
||||||
|
|
@ -46,7 +60,6 @@ func (in *Backup) DeepCopy() *Backup {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ConfigMapRef) DeepCopyInto(out *ConfigMapRef) {
|
func (in *ConfigMapRef) DeepCopyInto(out *ConfigMapRef) {
|
||||||
*out = *in
|
*out = *in
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapRef.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapRef.
|
||||||
|
|
@ -63,7 +76,6 @@ func (in *ConfigMapRef) DeepCopy() *ConfigMapRef {
|
||||||
func (in *ConfigurationAsCode) DeepCopyInto(out *ConfigurationAsCode) {
|
func (in *ConfigurationAsCode) DeepCopyInto(out *ConfigurationAsCode) {
|
||||||
*out = *in
|
*out = *in
|
||||||
in.Customization.DeepCopyInto(&out.Customization)
|
in.Customization.DeepCopyInto(&out.Customization)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationAsCode.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationAsCode.
|
||||||
|
|
@ -92,51 +104,50 @@ func (in *Container) DeepCopyInto(out *Container) {
|
||||||
}
|
}
|
||||||
if in.Ports != nil {
|
if in.Ports != nil {
|
||||||
in, out := &in.Ports, &out.Ports
|
in, out := &in.Ports, &out.Ports
|
||||||
*out = make([]v1.ContainerPort, len(*in))
|
*out = make([]corev1.ContainerPort, len(*in))
|
||||||
copy(*out, *in)
|
copy(*out, *in)
|
||||||
}
|
}
|
||||||
if in.EnvFrom != nil {
|
if in.EnvFrom != nil {
|
||||||
in, out := &in.EnvFrom, &out.EnvFrom
|
in, out := &in.EnvFrom, &out.EnvFrom
|
||||||
*out = make([]v1.EnvFromSource, len(*in))
|
*out = make([]corev1.EnvFromSource, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if in.Env != nil {
|
if in.Env != nil {
|
||||||
in, out := &in.Env, &out.Env
|
in, out := &in.Env, &out.Env
|
||||||
*out = make([]v1.EnvVar, len(*in))
|
*out = make([]corev1.EnvVar, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if in.VolumeMounts != nil {
|
if in.VolumeMounts != nil {
|
||||||
in, out := &in.VolumeMounts, &out.VolumeMounts
|
in, out := &in.VolumeMounts, &out.VolumeMounts
|
||||||
*out = make([]v1.VolumeMount, len(*in))
|
*out = make([]corev1.VolumeMount, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if in.LivenessProbe != nil {
|
if in.LivenessProbe != nil {
|
||||||
in, out := &in.LivenessProbe, &out.LivenessProbe
|
in, out := &in.LivenessProbe, &out.LivenessProbe
|
||||||
*out = new(v1.Probe)
|
*out = new(corev1.Probe)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.ReadinessProbe != nil {
|
if in.ReadinessProbe != nil {
|
||||||
in, out := &in.ReadinessProbe, &out.ReadinessProbe
|
in, out := &in.ReadinessProbe, &out.ReadinessProbe
|
||||||
*out = new(v1.Probe)
|
*out = new(corev1.Probe)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.Lifecycle != nil {
|
if in.Lifecycle != nil {
|
||||||
in, out := &in.Lifecycle, &out.Lifecycle
|
in, out := &in.Lifecycle, &out.Lifecycle
|
||||||
*out = new(v1.Lifecycle)
|
*out = new(corev1.Lifecycle)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.SecurityContext != nil {
|
if in.SecurityContext != nil {
|
||||||
in, out := &in.SecurityContext, &out.SecurityContext
|
in, out := &in.SecurityContext, &out.SecurityContext
|
||||||
*out = new(v1.SecurityContext)
|
*out = new(corev1.SecurityContext)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Container.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Container.
|
||||||
|
|
@ -158,7 +169,6 @@ func (in *Customization) DeepCopyInto(out *Customization) {
|
||||||
*out = make([]ConfigMapRef, len(*in))
|
*out = make([]ConfigMapRef, len(*in))
|
||||||
copy(*out, *in)
|
copy(*out, *in)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Customization.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Customization.
|
||||||
|
|
@ -175,7 +185,6 @@ func (in *Customization) DeepCopy() *Customization {
|
||||||
func (in *GroovyScripts) DeepCopyInto(out *GroovyScripts) {
|
func (in *GroovyScripts) DeepCopyInto(out *GroovyScripts) {
|
||||||
*out = *in
|
*out = *in
|
||||||
in.Customization.DeepCopyInto(&out.Customization)
|
in.Customization.DeepCopyInto(&out.Customization)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroovyScripts.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroovyScripts.
|
||||||
|
|
@ -193,10 +202,9 @@ func (in *Handler) DeepCopyInto(out *Handler) {
|
||||||
*out = *in
|
*out = *in
|
||||||
if in.Exec != nil {
|
if in.Exec != nil {
|
||||||
in, out := &in.Exec, &out.Exec
|
in, out := &in.Exec, &out.Exec
|
||||||
*out = new(v1.ExecAction)
|
*out = new(corev1.ExecAction)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Handler.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Handler.
|
||||||
|
|
@ -209,22 +217,6 @@ func (in *Handler) DeepCopy() *Handler {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *Image) DeepCopyInto(out *Image) {
|
|
||||||
*out = *in
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Image.
|
|
||||||
func (in *Image) DeepCopy() *Image {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(Image)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *Jenkins) DeepCopyInto(out *Jenkins) {
|
func (in *Jenkins) DeepCopyInto(out *Jenkins) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
|
@ -232,7 +224,6 @@ func (in *Jenkins) DeepCopyInto(out *Jenkins) {
|
||||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
in.Spec.DeepCopyInto(&out.Spec)
|
in.Spec.DeepCopyInto(&out.Spec)
|
||||||
in.Status.DeepCopyInto(&out.Status)
|
in.Status.DeepCopyInto(&out.Status)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Jenkins.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Jenkins.
|
||||||
|
|
@ -256,7 +247,6 @@ func (in *Jenkins) DeepCopyObject() runtime.Object {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *JenkinsAPISettings) DeepCopyInto(out *JenkinsAPISettings) {
|
func (in *JenkinsAPISettings) DeepCopyInto(out *JenkinsAPISettings) {
|
||||||
*out = *in
|
*out = *in
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsAPISettings.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsAPISettings.
|
||||||
|
|
@ -269,110 +259,6 @@ func (in *JenkinsAPISettings) DeepCopy() *JenkinsAPISettings {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *JenkinsImage) DeepCopyInto(out *JenkinsImage) {
|
|
||||||
*out = *in
|
|
||||||
out.TypeMeta = in.TypeMeta
|
|
||||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
|
||||||
in.Spec.DeepCopyInto(&out.Spec)
|
|
||||||
in.Status.DeepCopyInto(&out.Status)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsImage.
|
|
||||||
func (in *JenkinsImage) DeepCopy() *JenkinsImage {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(JenkinsImage)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
|
||||||
func (in *JenkinsImage) 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 *JenkinsImageList) DeepCopyInto(out *JenkinsImageList) {
|
|
||||||
*out = *in
|
|
||||||
out.TypeMeta = in.TypeMeta
|
|
||||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
|
||||||
if in.Items != nil {
|
|
||||||
in, out := &in.Items, &out.Items
|
|
||||||
*out = make([]JenkinsImage, len(*in))
|
|
||||||
for i := range *in {
|
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsImageList.
|
|
||||||
func (in *JenkinsImageList) DeepCopy() *JenkinsImageList {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(JenkinsImageList)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
|
||||||
func (in *JenkinsImageList) 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 *JenkinsImageSpec) DeepCopyInto(out *JenkinsImageSpec) {
|
|
||||||
*out = *in
|
|
||||||
out.BaseImage = in.BaseImage
|
|
||||||
if in.Plugins != nil {
|
|
||||||
in, out := &in.Plugins, &out.Plugins
|
|
||||||
*out = make([]JenkinsPlugin, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsImageSpec.
|
|
||||||
func (in *JenkinsImageSpec) DeepCopy() *JenkinsImageSpec {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(JenkinsImageSpec)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *JenkinsImageStatus) DeepCopyInto(out *JenkinsImageStatus) {
|
|
||||||
*out = *in
|
|
||||||
if in.InstalledPlugins != nil {
|
|
||||||
in, out := &in.InstalledPlugins, &out.InstalledPlugins
|
|
||||||
*out = make([]JenkinsPlugin, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsImageStatus.
|
|
||||||
func (in *JenkinsImageStatus) DeepCopy() *JenkinsImageStatus {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(JenkinsImageStatus)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *JenkinsList) DeepCopyInto(out *JenkinsList) {
|
func (in *JenkinsList) DeepCopyInto(out *JenkinsList) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
|
@ -385,7 +271,6 @@ func (in *JenkinsList) DeepCopyInto(out *JenkinsList) {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsList.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsList.
|
||||||
|
|
@ -416,13 +301,6 @@ func (in *JenkinsMaster) DeepCopyInto(out *JenkinsMaster) {
|
||||||
(*out)[key] = val
|
(*out)[key] = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if in.AnnotationsDeprecated != nil {
|
|
||||||
in, out := &in.AnnotationsDeprecated, &out.AnnotationsDeprecated
|
|
||||||
*out = make(map[string]string, len(*in))
|
|
||||||
for key, val := range *in {
|
|
||||||
(*out)[key] = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if in.Labels != nil {
|
if in.Labels != nil {
|
||||||
in, out := &in.Labels, &out.Labels
|
in, out := &in.Labels, &out.Labels
|
||||||
*out = make(map[string]string, len(*in))
|
*out = make(map[string]string, len(*in))
|
||||||
|
|
@ -439,7 +317,7 @@ func (in *JenkinsMaster) DeepCopyInto(out *JenkinsMaster) {
|
||||||
}
|
}
|
||||||
if in.SecurityContext != nil {
|
if in.SecurityContext != nil {
|
||||||
in, out := &in.SecurityContext, &out.SecurityContext
|
in, out := &in.SecurityContext, &out.SecurityContext
|
||||||
*out = new(v1.PodSecurityContext)
|
*out = new(corev1.PodSecurityContext)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.Containers != nil {
|
if in.Containers != nil {
|
||||||
|
|
@ -451,19 +329,19 @@ func (in *JenkinsMaster) DeepCopyInto(out *JenkinsMaster) {
|
||||||
}
|
}
|
||||||
if in.ImagePullSecrets != nil {
|
if in.ImagePullSecrets != nil {
|
||||||
in, out := &in.ImagePullSecrets, &out.ImagePullSecrets
|
in, out := &in.ImagePullSecrets, &out.ImagePullSecrets
|
||||||
*out = make([]v1.LocalObjectReference, len(*in))
|
*out = make([]corev1.LocalObjectReference, len(*in))
|
||||||
copy(*out, *in)
|
copy(*out, *in)
|
||||||
}
|
}
|
||||||
if in.Volumes != nil {
|
if in.Volumes != nil {
|
||||||
in, out := &in.Volumes, &out.Volumes
|
in, out := &in.Volumes, &out.Volumes
|
||||||
*out = make([]v1.Volume, len(*in))
|
*out = make([]corev1.Volume, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if in.Tolerations != nil {
|
if in.Tolerations != nil {
|
||||||
in, out := &in.Tolerations, &out.Tolerations
|
in, out := &in.Tolerations, &out.Tolerations
|
||||||
*out = make([]v1.Toleration, len(*in))
|
*out = make([]corev1.Toleration, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
|
|
@ -478,7 +356,6 @@ func (in *JenkinsMaster) DeepCopyInto(out *JenkinsMaster) {
|
||||||
*out = make([]Plugin, len(*in))
|
*out = make([]Plugin, len(*in))
|
||||||
copy(*out, *in)
|
copy(*out, *in)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsMaster.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsMaster.
|
||||||
|
|
@ -491,22 +368,6 @@ func (in *JenkinsMaster) DeepCopy() *JenkinsMaster {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *JenkinsPlugin) DeepCopyInto(out *JenkinsPlugin) {
|
|
||||||
*out = *in
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsPlugin.
|
|
||||||
func (in *JenkinsPlugin) DeepCopy() *JenkinsPlugin {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(JenkinsPlugin)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *JenkinsSpec) DeepCopyInto(out *JenkinsSpec) {
|
func (in *JenkinsSpec) DeepCopyInto(out *JenkinsSpec) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
|
@ -536,7 +397,6 @@ func (in *JenkinsSpec) DeepCopyInto(out *JenkinsSpec) {
|
||||||
}
|
}
|
||||||
in.ServiceAccount.DeepCopyInto(&out.ServiceAccount)
|
in.ServiceAccount.DeepCopyInto(&out.ServiceAccount)
|
||||||
out.JenkinsAPISettings = in.JenkinsAPISettings
|
out.JenkinsAPISettings = in.JenkinsAPISettings
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsSpec.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsSpec.
|
||||||
|
|
@ -574,7 +434,6 @@ func (in *JenkinsStatus) DeepCopyInto(out *JenkinsStatus) {
|
||||||
*out = make([]AppliedGroovyScript, len(*in))
|
*out = make([]AppliedGroovyScript, len(*in))
|
||||||
copy(*out, *in)
|
copy(*out, *in)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsStatus.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsStatus.
|
||||||
|
|
@ -591,7 +450,6 @@ func (in *JenkinsStatus) DeepCopy() *JenkinsStatus {
|
||||||
func (in *Mailgun) DeepCopyInto(out *Mailgun) {
|
func (in *Mailgun) DeepCopyInto(out *Mailgun) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.APIKeySecretKeySelector = in.APIKeySecretKeySelector
|
out.APIKeySecretKeySelector = in.APIKeySecretKeySelector
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Mailgun.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Mailgun.
|
||||||
|
|
@ -608,7 +466,6 @@ func (in *Mailgun) DeepCopy() *Mailgun {
|
||||||
func (in *MicrosoftTeams) DeepCopyInto(out *MicrosoftTeams) {
|
func (in *MicrosoftTeams) DeepCopyInto(out *MicrosoftTeams) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.WebHookURLSecretKeySelector = in.WebHookURLSecretKeySelector
|
out.WebHookURLSecretKeySelector = in.WebHookURLSecretKeySelector
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MicrosoftTeams.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MicrosoftTeams.
|
||||||
|
|
@ -644,7 +501,6 @@ func (in *Notification) DeepCopyInto(out *Notification) {
|
||||||
*out = new(SMTP)
|
*out = new(SMTP)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Notification.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Notification.
|
||||||
|
|
@ -660,7 +516,6 @@ func (in *Notification) DeepCopy() *Notification {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *Plugin) DeepCopyInto(out *Plugin) {
|
func (in *Plugin) DeepCopyInto(out *Plugin) {
|
||||||
*out = *in
|
*out = *in
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Plugin.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Plugin.
|
||||||
|
|
@ -678,7 +533,6 @@ func (in *Restore) DeepCopyInto(out *Restore) {
|
||||||
*out = *in
|
*out = *in
|
||||||
in.Action.DeepCopyInto(&out.Action)
|
in.Action.DeepCopyInto(&out.Action)
|
||||||
in.GetLatestAction.DeepCopyInto(&out.GetLatestAction)
|
in.GetLatestAction.DeepCopyInto(&out.GetLatestAction)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Restore.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Restore.
|
||||||
|
|
@ -696,7 +550,6 @@ func (in *SMTP) DeepCopyInto(out *SMTP) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.UsernameSecretKeySelector = in.UsernameSecretKeySelector
|
out.UsernameSecretKeySelector = in.UsernameSecretKeySelector
|
||||||
out.PasswordSecretKeySelector = in.PasswordSecretKeySelector
|
out.PasswordSecretKeySelector = in.PasswordSecretKeySelector
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SMTP.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SMTP.
|
||||||
|
|
@ -713,7 +566,6 @@ func (in *SMTP) DeepCopy() *SMTP {
|
||||||
func (in *SecretKeySelector) DeepCopyInto(out *SecretKeySelector) {
|
func (in *SecretKeySelector) DeepCopyInto(out *SecretKeySelector) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.LocalObjectReference = in.LocalObjectReference
|
out.LocalObjectReference = in.LocalObjectReference
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretKeySelector.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretKeySelector.
|
||||||
|
|
@ -729,7 +581,6 @@ func (in *SecretKeySelector) DeepCopy() *SecretKeySelector {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *SecretRef) DeepCopyInto(out *SecretRef) {
|
func (in *SecretRef) DeepCopyInto(out *SecretRef) {
|
||||||
*out = *in
|
*out = *in
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretRef.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretRef.
|
||||||
|
|
@ -745,7 +596,6 @@ func (in *SecretRef) DeepCopy() *SecretRef {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *SeedJob) DeepCopyInto(out *SeedJob) {
|
func (in *SeedJob) DeepCopyInto(out *SeedJob) {
|
||||||
*out = *in
|
*out = *in
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SeedJob.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SeedJob.
|
||||||
|
|
@ -780,7 +630,6 @@ func (in *Service) DeepCopyInto(out *Service) {
|
||||||
*out = make([]string, len(*in))
|
*out = make([]string, len(*in))
|
||||||
copy(*out, *in)
|
copy(*out, *in)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Service.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Service.
|
||||||
|
|
@ -803,7 +652,6 @@ func (in *ServiceAccount) DeepCopyInto(out *ServiceAccount) {
|
||||||
(*out)[key] = val
|
(*out)[key] = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccount.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccount.
|
||||||
|
|
@ -820,7 +668,6 @@ func (in *ServiceAccount) DeepCopy() *ServiceAccount {
|
||||||
func (in *Slack) DeepCopyInto(out *Slack) {
|
func (in *Slack) DeepCopyInto(out *Slack) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.WebHookURLSecretKeySelector = in.WebHookURLSecretKeySelector
|
out.WebHookURLSecretKeySelector = in.WebHookURLSecretKeySelector
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Slack.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Slack.
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
ARG GO_VERSION
|
|
||||||
|
|
||||||
# build stage
|
|
||||||
FROM golang:$GO_VERSION-alpine3.11 AS build-stage
|
|
||||||
ARG OPERATOR_SDK_VERSION
|
|
||||||
ENV GO111MODULE=on
|
|
||||||
RUN apk --no-cache add git curl make \
|
|
||||||
&& curl -L https://github.com/operator-framework/operator-sdk/releases/download/v$OPERATOR_SDK_VERSION/operator-sdk-v$OPERATOR_SDK_VERSION-x86_64-linux-gnu -o /usr/local/bin/operator-sdk \
|
|
||||||
&& chmod +x /usr/local/bin/operator-sdk
|
|
||||||
ADD . /kubernetes-operator
|
|
||||||
|
|
||||||
RUN cd /kubernetes-operator && make build
|
|
||||||
|
|
||||||
# run stage
|
|
||||||
FROM alpine:3.10
|
|
||||||
|
|
||||||
USER nobody
|
|
||||||
|
|
||||||
COPY --from=build-stage /kubernetes-operator/build/_output/bin/jenkins-operator /usr/local/bin/jenkins-operator
|
|
||||||
|
|
||||||
CMD [ "/usr/local/bin/jenkins-operator" ]
|
|
||||||
|
|
@ -1,277 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkinsimage"
|
|
||||||
|
|
||||||
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
|
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/client"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/event"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications"
|
|
||||||
e "github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/version"
|
|
||||||
|
|
||||||
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
|
|
||||||
kubemetrics "github.com/operator-framework/operator-sdk/pkg/kube-metrics"
|
|
||||||
"github.com/operator-framework/operator-sdk/pkg/leader"
|
|
||||||
"github.com/operator-framework/operator-sdk/pkg/log/zap"
|
|
||||||
"github.com/operator-framework/operator-sdk/pkg/metrics"
|
|
||||||
sdkVersion "github.com/operator-framework/operator-sdk/version"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
v1 "k8s.io/api/core/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
|
||||||
"k8s.io/client-go/kubernetes"
|
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
|
||||||
"k8s.io/client-go/rest"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client/config"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Change below variables to serve metrics on different host or port.
|
|
||||||
var (
|
|
||||||
metricsHost = "0.0.0.0"
|
|
||||||
metricsPort int32 = 8383
|
|
||||||
operatorMetricsPort int32 = 8686
|
|
||||||
)
|
|
||||||
|
|
||||||
var logger = log.Log.WithName("cmd")
|
|
||||||
|
|
||||||
func printInfo() {
|
|
||||||
logger.Info(fmt.Sprintf("Version: %s", version.Version))
|
|
||||||
logger.Info(fmt.Sprintf("Git commit: %s", version.GitCommit))
|
|
||||||
logger.Info(fmt.Sprintf("Go Version: %s", runtime.Version()))
|
|
||||||
logger.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH))
|
|
||||||
logger.Info(fmt.Sprintf("operator-sdk Version: %v", sdkVersion.Version))
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Add the zap logger flag set to the CLI. The flag set must
|
|
||||||
// be added before calling pflag.Parse().
|
|
||||||
pflag.CommandLine.AddFlagSet(zap.FlagSet())
|
|
||||||
|
|
||||||
// Add flags registered by imported packages (e.g. glog and
|
|
||||||
// controller-runtime)
|
|
||||||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
|
||||||
|
|
||||||
hostname := pflag.String("jenkins-api-hostname", "", "Hostname or IP of Jenkins API. It can be service name, node IP or localhost.")
|
|
||||||
port := pflag.Int("jenkins-api-port", 0, "The port on which Jenkins API is running. Note: If you want to use nodePort don't set this setting and --jenkins-api-use-nodeport must be true.")
|
|
||||||
useNodePort := pflag.Bool("jenkins-api-use-nodeport", false, "Connect to Jenkins API using the service nodePort instead of service port. If you want to set this as true - don't set --jenkins-api-port.")
|
|
||||||
debug := pflag.Bool("debug", false, "Set log level to debug")
|
|
||||||
kubernetesClusterDomain := pflag.String("cluster-domain", "cluster.local", "Use custom domain name instead of 'cluster.local'.")
|
|
||||||
pflag.Parse()
|
|
||||||
|
|
||||||
log.SetupLogger(*debug)
|
|
||||||
printInfo()
|
|
||||||
|
|
||||||
namespace, err := k8sutil.GetWatchNamespace()
|
|
||||||
if err != nil {
|
|
||||||
fatal(errors.Wrap(err, "failed to get watch namespace"), *debug)
|
|
||||||
}
|
|
||||||
logger.Info(fmt.Sprintf("Watch namespace: %v", namespace))
|
|
||||||
|
|
||||||
// get a config to talk to the apiserver
|
|
||||||
cfg, err := config.GetConfig()
|
|
||||||
if err != nil {
|
|
||||||
fatal(errors.Wrap(err, "failed to get config"), *debug)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := context.TODO()
|
|
||||||
|
|
||||||
// Become the leader before proceeding
|
|
||||||
err = leader.Become(ctx, "jenkins-operator-lock")
|
|
||||||
if err != nil {
|
|
||||||
fatal(errors.Wrap(err, "failed to become leader"), *debug)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new Cmd to provide shared dependencies and start components
|
|
||||||
mgr, err := manager.New(cfg, manager.Options{
|
|
||||||
Namespace: namespace,
|
|
||||||
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
fatal(errors.Wrap(err, "failed to create manager"), *debug)
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Info("Registering Components.")
|
|
||||||
|
|
||||||
// setup Scheme for all resources
|
|
||||||
if err := apis.AddToScheme(mgr.GetScheme()); err != nil {
|
|
||||||
fatal(errors.Wrap(err, "failed to setup scheme"), *debug)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup events
|
|
||||||
events, err := event.New(cfg, constants.OperatorName)
|
|
||||||
if err != nil {
|
|
||||||
fatal(errors.Wrap(err, "failed to create manager"), *debug)
|
|
||||||
}
|
|
||||||
|
|
||||||
clientSet, err := kubernetes.NewForConfig(cfg)
|
|
||||||
if err != nil {
|
|
||||||
fatal(errors.Wrap(err, "failed to create Kubernetes client set"), *debug)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resources.IsRouteAPIAvailable(clientSet) {
|
|
||||||
logger.Info("Route API found: Route creation will be performed")
|
|
||||||
}
|
|
||||||
c := make(chan e.Event)
|
|
||||||
go notifications.Listen(c, events, mgr.GetClient())
|
|
||||||
|
|
||||||
// validate jenkins API connection
|
|
||||||
jenkinsAPIConnectionSettings := client.JenkinsAPIConnectionSettings{Hostname: *hostname, Port: *port, UseNodePort: *useNodePort}
|
|
||||||
if err := jenkinsAPIConnectionSettings.Validate(); err != nil {
|
|
||||||
fatal(errors.Wrap(err, "invalid command line parameters"), *debug)
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate kubernetes cluster domain
|
|
||||||
if *kubernetesClusterDomain == "" {
|
|
||||||
fatal(errors.Wrap(err, "Kubernetes cluster domain can't be empty"), *debug)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup Jenkins controller
|
|
||||||
if err := jenkins.Add(mgr, jenkinsAPIConnectionSettings, *kubernetesClusterDomain, *clientSet, *cfg, &c); err != nil {
|
|
||||||
fatal(errors.Wrap(err, "failed to setup controllers"), *debug)
|
|
||||||
}
|
|
||||||
// setup JenkinsImage controller
|
|
||||||
if err = jenkinsimage.Add(mgr); err != nil {
|
|
||||||
fatal(errors.Wrap(err, "failed to setup controllers"), *debug)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = serveCRMetrics(cfg); err != nil {
|
|
||||||
logger.V(log.VWarn).Info("Could not generate and serve custom resource metrics", "error", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to the below struct any other metrics ports you want to expose.
|
|
||||||
servicePorts := []v1.ServicePort{
|
|
||||||
{Port: metricsPort, Name: metrics.OperatorPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: metricsPort}},
|
|
||||||
{Port: operatorMetricsPort, Name: metrics.CRPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: operatorMetricsPort}},
|
|
||||||
}
|
|
||||||
// Create Service object to expose the metrics port(s).
|
|
||||||
service, err := metrics.CreateMetricsService(ctx, cfg, servicePorts)
|
|
||||||
if err != nil {
|
|
||||||
logger.V(log.VWarn).Info("Could not create metrics Service", "error", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateServiceMonitors will automatically create the prometheus-operator ServiceMonitor resources
|
|
||||||
// necessary to configure Prometheus to scrape metrics from this operator.
|
|
||||||
services := []*v1.Service{service}
|
|
||||||
_, err = metrics.CreateServiceMonitors(cfg, namespace, services)
|
|
||||||
if err != nil {
|
|
||||||
logger.V(log.VWarn).Info("Could not create ServiceMonitor object", "error", err.Error())
|
|
||||||
// If this operator is deployed to a cluster without the prometheus-operator running, it will return
|
|
||||||
// ErrServiceMonitorNotPresent, which can be used to safely skip ServiceMonitor creation.
|
|
||||||
if err == metrics.ErrServiceMonitorNotPresent {
|
|
||||||
logger.V(log.VWarn).Info("Install prometheus-operator in your cluster to create ServiceMonitor objects", "error", err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Info("Starting the Cmd.")
|
|
||||||
|
|
||||||
// start the Cmd
|
|
||||||
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
|
|
||||||
fatal(errors.Wrap(err, "failed to start cmd"), *debug)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// serveCRMetrics gets the Operator/CustomResource GVKs and generates metrics based on those types.
|
|
||||||
// It serves those metrics on "http://metricsHost:operatorMetricsPort".
|
|
||||||
func serveCRMetrics(cfg *rest.Config) error {
|
|
||||||
// Below function returns filtered operator/CustomResource specific GVKs.
|
|
||||||
// For more control override the below GVK list with your own custom logic.
|
|
||||||
gvks, err := k8sutil.GetGVKsFromAddToScheme(apis.AddToScheme)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// We perform our custom GKV filtering on top of the one performed
|
|
||||||
// by operator-sdk code
|
|
||||||
filteredGVK := filterGKVsFromAddToScheme(gvks)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Get the namespace the operator is currently deployed in.
|
|
||||||
operatorNs, err := k8sutil.GetOperatorNamespace()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// To generate metrics in other namespaces, add the values below.
|
|
||||||
ns := []string{operatorNs}
|
|
||||||
// Generate and serve custom resource specific metrics.
|
|
||||||
return kubemetrics.GenerateAndServeCRMetrics(cfg, ns, filteredGVK, metricsHost, operatorMetricsPort)
|
|
||||||
}
|
|
||||||
|
|
||||||
func filterGKVsFromAddToScheme(gvks []schema.GroupVersionKind) []schema.GroupVersionKind {
|
|
||||||
// We use gkvFilters to filter from the existing GKVs defined in the used
|
|
||||||
// runtime.Schema for the operator. The reason for that is that
|
|
||||||
// kube-metrics tries to list all of the defined Kinds in the schemas
|
|
||||||
// that are passed, including Kinds that the operator doesn't use and
|
|
||||||
// thus the role used the operator doesn't have them set and we don't want
|
|
||||||
// to set as they are not used by the operator.
|
|
||||||
// For the fields that the filters have we have defined the value '*' to
|
|
||||||
// specify any will be a match (accepted)
|
|
||||||
matchAnyValue := "*"
|
|
||||||
gvkFilters := []schema.GroupVersionKind{
|
|
||||||
// Kubernetes Resources
|
|
||||||
{Kind: "PersistentVolumeClaim", Version: matchAnyValue},
|
|
||||||
{Kind: "ServiceAccount", Version: matchAnyValue},
|
|
||||||
{Kind: "Secret", Version: matchAnyValue},
|
|
||||||
{Kind: "Pod", Version: matchAnyValue},
|
|
||||||
{Kind: "ConfigMap", Version: matchAnyValue},
|
|
||||||
{Kind: "Service", Version: matchAnyValue},
|
|
||||||
{Group: "apps", Kind: "Deployment", Version: matchAnyValue},
|
|
||||||
// Openshift Resources
|
|
||||||
{Group: "route.openshift.io", Kind: "Route", Version: matchAnyValue},
|
|
||||||
{Group: "image.openshift.io", Kind: "ImageStream", Version: matchAnyValue},
|
|
||||||
// Custom Resources
|
|
||||||
{Group: "jenkins.io", Kind: "Jenkins", Version: matchAnyValue},
|
|
||||||
{Group: "jenkins.io", Kind: "JenkinsImage", Version: matchAnyValue},
|
|
||||||
}
|
|
||||||
|
|
||||||
ownGVKs := []schema.GroupVersionKind{}
|
|
||||||
for _, gvk := range gvks {
|
|
||||||
for _, gvkFilter := range gvkFilters {
|
|
||||||
match := true
|
|
||||||
if gvkFilter.Kind == matchAnyValue && gvkFilter.Group == matchAnyValue && gvkFilter.Version == matchAnyValue {
|
|
||||||
logger.V(1).Info("gvkFilter should at least have one of its fields defined. Skipping...")
|
|
||||||
match = false
|
|
||||||
} else {
|
|
||||||
if gvkFilter.Kind != matchAnyValue && gvkFilter.Kind != gvk.Kind {
|
|
||||||
match = false
|
|
||||||
}
|
|
||||||
if gvkFilter.Group != matchAnyValue && gvkFilter.Group != gvk.Group {
|
|
||||||
match = false
|
|
||||||
}
|
|
||||||
if gvkFilter.Version != matchAnyValue && gvkFilter.Version != gvk.Version {
|
|
||||||
match = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if match {
|
|
||||||
ownGVKs = append(ownGVKs, gvk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ownGVKs
|
|
||||||
}
|
|
||||||
|
|
||||||
func fatal(err error, debug bool) {
|
|
||||||
if debug {
|
|
||||||
logger.Error(nil, fmt.Sprintf("%+v", err))
|
|
||||||
} else {
|
|
||||||
logger.Error(nil, fmt.Sprintf("%s", err))
|
|
||||||
}
|
|
||||||
os.Exit(-1)
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# Setup variables for the Makefile
|
# Setup variables for the Makefile
|
||||||
NAME=kubernetes-operator
|
NAME=kubernetes-operator
|
||||||
OPERATOR_SDK_VERSION=0.17.0
|
OPERATOR_SDK_VERSION=1.3.0
|
||||||
GO_VERSION=1.14.2
|
GO_VERSION=1.15.6
|
||||||
PKG=github.com/jenkinsci/kubernetes-operator
|
PKG=github.com/jenkinsci/kubernetes-operator
|
||||||
DOCKER_ORGANIZATION=virtuslab
|
DOCKER_ORGANIZATION=virtuslab
|
||||||
DOCKER_REGISTRY=jenkins-operator
|
DOCKER_REGISTRY=jenkins-operator
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ KUBERNETES_PROVIDER=minikube
|
||||||
|
|
||||||
MINIKUBE_KUBERNETES_VERSION=v1.17.4
|
MINIKUBE_KUBERNETES_VERSION=v1.17.4
|
||||||
MINIKUBE_DRIVER=virtualbox
|
MINIKUBE_DRIVER=virtualbox
|
||||||
MINIKUBE_VERSION=1.4.0
|
MINIKUBE_VERSION=1.17.1
|
||||||
KUBECTL_CONTEXT=minikube
|
KUBECTL_CONTEXT=minikube
|
||||||
|
|
||||||
JENKINS_API_HOSTNAME_COMMAND=minikube ip
|
JENKINS_API_HOSTNAME_COMMAND=bin/minikube ip
|
||||||
JENKINS_API_PORT=0
|
JENKINS_API_PORT=0
|
||||||
JENKINS_API_USE_NODEPORT=true
|
JENKINS_API_USE_NODEPORT=true
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,227 @@
|
||||||
|
---
|
||||||
|
# permissions to do leader election.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: leader-election-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
- coordination.k8s.io
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
- leases
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- patch
|
||||||
|
- delete
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- events
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- patch
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: leader-election-rolebinding
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: leader-election-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: default
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
name: manager-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
- configmaps
|
||||||
|
- secrets
|
||||||
|
- serviceaccounts
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- apps
|
||||||
|
resources:
|
||||||
|
- deployments
|
||||||
|
- daemonsets
|
||||||
|
- replicasets
|
||||||
|
- statefulsets
|
||||||
|
verbs:
|
||||||
|
- '*'
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io
|
||||||
|
resources:
|
||||||
|
- roles
|
||||||
|
- rolebindings
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods/portforward
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods/log
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
- pods/exec
|
||||||
|
verbs:
|
||||||
|
- "*"
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- events
|
||||||
|
verbs:
|
||||||
|
- watch
|
||||||
|
- list
|
||||||
|
- create
|
||||||
|
- patch
|
||||||
|
- apiGroups:
|
||||||
|
- apps
|
||||||
|
resourceNames:
|
||||||
|
- jenkins-operator
|
||||||
|
resources:
|
||||||
|
- deployments/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- jenkins.io
|
||||||
|
resources:
|
||||||
|
- '*'
|
||||||
|
verbs:
|
||||||
|
- '*'
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- persistentvolumeclaims
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- "route.openshift.io"
|
||||||
|
resources:
|
||||||
|
- routes
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- "image.openshift.io"
|
||||||
|
resources:
|
||||||
|
- imagestreams
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- "build.openshift.io"
|
||||||
|
resources:
|
||||||
|
- builds
|
||||||
|
- buildconfigs
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: manager-rolebinding
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: manager-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: default
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: jenkins-operator
|
||||||
|
namespace: default
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 65532
|
||||||
|
containers:
|
||||||
|
- command:
|
||||||
|
- /manager
|
||||||
|
args:
|
||||||
|
- --leader-elect
|
||||||
|
image: virtuslab/jenkins-operator:v0.5.0
|
||||||
|
name: jenkins-operator
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 8081
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
periodSeconds: 20
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /readyz
|
||||||
|
port: 8081
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 30Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 20Mi
|
||||||
|
env:
|
||||||
|
- name: WATCH_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
terminationGracePeriodSeconds: 10
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
# The following manifests contain a self-signed issuer CR and a certificate CR.
|
||||||
|
# More document can be found at https://docs.cert-manager.io
|
||||||
|
# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes.
|
||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: Issuer
|
||||||
|
metadata:
|
||||||
|
name: selfsigned-issuer
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
selfSigned: {}
|
||||||
|
---
|
||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: Certificate
|
||||||
|
metadata:
|
||||||
|
name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
# $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize
|
||||||
|
dnsNames:
|
||||||
|
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc
|
||||||
|
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local
|
||||||
|
issuerRef:
|
||||||
|
kind: Issuer
|
||||||
|
name: selfsigned-issuer
|
||||||
|
secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
resources:
|
||||||
|
- certificate.yaml
|
||||||
|
|
||||||
|
configurations:
|
||||||
|
- kustomizeconfig.yaml
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
# This configuration is for teaching kustomize how to update name ref and var substitution
|
||||||
|
nameReference:
|
||||||
|
- kind: Issuer
|
||||||
|
group: cert-manager.io
|
||||||
|
fieldSpecs:
|
||||||
|
- kind: Certificate
|
||||||
|
group: cert-manager.io
|
||||||
|
path: spec/issuerRef/name
|
||||||
|
|
||||||
|
varReference:
|
||||||
|
- kind: Certificate
|
||||||
|
group: cert-manager.io
|
||||||
|
path: spec/commonName
|
||||||
|
- kind: Certificate
|
||||||
|
group: cert-manager.io
|
||||||
|
path: spec/dnsNames
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,21 @@
|
||||||
|
# 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/jenkins.io_jenkins.yaml
|
||||||
|
# +kubebuilder:scaffold:crdkustomizeresource
|
||||||
|
|
||||||
|
patchesStrategicMerge:
|
||||||
|
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
|
||||||
|
# patches here are for enabling the conversion webhook for each CRD
|
||||||
|
#- patches/webhook_in_jenkins.yaml
|
||||||
|
# +kubebuilder:scaffold:crdkustomizewebhookpatch
|
||||||
|
|
||||||
|
# [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix.
|
||||||
|
# patches here are for enabling the CA injection for each CRD
|
||||||
|
#- patches/cainjection_in_jenkins.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: jenkins.jenkins.io
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
# The following patch enables a conversion webhook for the CRD
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: jenkins.jenkins.io
|
||||||
|
spec:
|
||||||
|
conversion:
|
||||||
|
strategy: Webhook
|
||||||
|
webhook:
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
namespace: default
|
||||||
|
name: webhook-service
|
||||||
|
path: /convert
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
# Adds namespace to all resources.
|
||||||
|
namespace: jenkins-operator
|
||||||
|
|
||||||
|
# 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: jenkins-operator-
|
||||||
|
|
||||||
|
# Labels to add to all resources and selectors.
|
||||||
|
#commonLabels:
|
||||||
|
# someName: someValue
|
||||||
|
|
||||||
|
bases:
|
||||||
|
- ../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
|
||||||
|
|
||||||
|
# Mount the controller config file for loading manager configurations
|
||||||
|
# through a ComponentConfig type
|
||||||
|
#- manager_config_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
|
||||||
|
|
||||||
|
# the following config is for teaching kustomize how to do var substitution
|
||||||
|
vars:
|
||||||
|
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
|
||||||
|
#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
|
||||||
|
# objref:
|
||||||
|
# kind: Certificate
|
||||||
|
# group: cert-manager.io
|
||||||
|
# version: v1
|
||||||
|
# name: serving-cert # this name should match the one in certificate.yaml
|
||||||
|
# fieldref:
|
||||||
|
# fieldpath: metadata.namespace
|
||||||
|
#- name: CERTIFICATE_NAME
|
||||||
|
# objref:
|
||||||
|
# kind: Certificate
|
||||||
|
# group: cert-manager.io
|
||||||
|
# version: v1
|
||||||
|
# name: serving-cert # this name should match the one in certificate.yaml
|
||||||
|
#- name: SERVICE_NAMESPACE # namespace of the service
|
||||||
|
# objref:
|
||||||
|
# kind: Service
|
||||||
|
# version: v1
|
||||||
|
# name: webhook-service
|
||||||
|
# fieldref:
|
||||||
|
# fieldpath: metadata.namespace
|
||||||
|
#- name: SERVICE_NAME
|
||||||
|
# objref:
|
||||||
|
# kind: Service
|
||||||
|
# version: v1
|
||||||
|
# name: webhook-service
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
# 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: default
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: kube-rbac-proxy
|
||||||
|
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0
|
||||||
|
args:
|
||||||
|
- "--secure-listen-address=0.0.0.0:8443"
|
||||||
|
- "--upstream=http://127.0.0.1:8080/"
|
||||||
|
- "--logtostderr=true"
|
||||||
|
- "--v=10"
|
||||||
|
ports:
|
||||||
|
- containerPort: 8443
|
||||||
|
name: https
|
||||||
|
- name: manager
|
||||||
|
args:
|
||||||
|
- "--health-probe-bind-address=:8081"
|
||||||
|
- "--metrics-bind-address=127.0.0.1:8080"
|
||||||
|
- "--leader-elect"
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: controller-manager
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: manager
|
||||||
|
args:
|
||||||
|
- "--config=controller_manager_config.yaml"
|
||||||
|
volumeMounts:
|
||||||
|
- name: manager-config
|
||||||
|
mountPath: /controller_manager_config.yaml
|
||||||
|
subPath: controller_manager_config.yaml
|
||||||
|
volumes:
|
||||||
|
- name: manager-config
|
||||||
|
configMap:
|
||||||
|
name: manager-config
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
apiVersion: controller-runtime.sigs.k8s.io/v1alpha1
|
||||||
|
kind: ControllerManagerConfig
|
||||||
|
health:
|
||||||
|
healthProbeBindAddress: :8081
|
||||||
|
metrics:
|
||||||
|
bindAddress: 127.0.0.1:8080
|
||||||
|
webhook:
|
||||||
|
port: 9443
|
||||||
|
leaderElection:
|
||||||
|
leaderElect: true
|
||||||
|
resourceName: 9cf053ac.jenkins.io
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
resources:
|
||||||
|
- manager.yaml
|
||||||
|
|
||||||
|
generatorOptions:
|
||||||
|
disableNameSuffixHash: true
|
||||||
|
|
||||||
|
configMapGenerator:
|
||||||
|
- files:
|
||||||
|
- controller_manager_config.yaml
|
||||||
|
name: manager-config
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
images:
|
||||||
|
- name: controller
|
||||||
|
newName: controller
|
||||||
|
newTag: latest
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: jenkins-operator
|
||||||
|
namespace: default
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 65532
|
||||||
|
containers:
|
||||||
|
- command:
|
||||||
|
- /manager
|
||||||
|
args:
|
||||||
|
- --leader-elect
|
||||||
|
image: virtuslab/jenkins-operator:v0.5.0
|
||||||
|
name: jenkins-operator
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 8081
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
periodSeconds: 20
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /readyz
|
||||||
|
port: 8081
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 30Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 20Mi
|
||||||
|
env:
|
||||||
|
- name: WATCH_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
terminationGracePeriodSeconds: 10
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
resources:
|
||||||
|
- monitor.yaml
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
# Prometheus Monitor Service (Metrics)
|
||||||
|
apiVersion: monitoring.coreos.com/v1
|
||||||
|
kind: ServiceMonitor
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
name: controller-manager-metrics-monitor
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
endpoints:
|
||||||
|
- path: /metrics
|
||||||
|
port: https
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: metrics-reader
|
||||||
|
rules:
|
||||||
|
- nonResourceURLs: ["/metrics"]
|
||||||
|
verbs: ["get"]
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: proxy-role
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["authentication.k8s.io"]
|
||||||
|
resources:
|
||||||
|
- tokenreviews
|
||||||
|
verbs: ["create"]
|
||||||
|
- apiGroups: ["authorization.k8s.io"]
|
||||||
|
resources:
|
||||||
|
- subjectaccessreviews
|
||||||
|
verbs: ["create"]
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: proxy-rolebinding
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: proxy-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: default
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
control-plane: controller-manager
|
||||||
|
name: controller-manager-metrics-service
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: https
|
||||||
|
port: 8443
|
||||||
|
targetPort: https
|
||||||
|
selector:
|
||||||
|
control-plane: controller-manager
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
# permissions for end users to edit jenkins.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: jenkins-editor-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- jenkins.io
|
||||||
|
resources:
|
||||||
|
- jenkins
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- jenkins.io
|
||||||
|
resources:
|
||||||
|
- jenkins/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# permissions for end users to view jenkins.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: jenkins-viewer-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- jenkins.io
|
||||||
|
resources:
|
||||||
|
- jenkins
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- jenkins.io
|
||||||
|
resources:
|
||||||
|
- jenkins/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
resources:
|
||||||
|
- 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,28 @@
|
||||||
|
---
|
||||||
|
# permissions to do leader election.
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: leader-election-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
- coordination.k8s.io
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
- leases
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- patch
|
||||||
|
- delete
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- events
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- patch
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: leader-election-rolebinding
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: leader-election-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: default
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
name: manager-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
- configmaps
|
||||||
|
- secrets
|
||||||
|
- serviceaccounts
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- apps
|
||||||
|
resources:
|
||||||
|
- deployments
|
||||||
|
- daemonsets
|
||||||
|
- replicasets
|
||||||
|
- statefulsets
|
||||||
|
verbs:
|
||||||
|
- '*'
|
||||||
|
- apiGroups:
|
||||||
|
- rbac.authorization.k8s.io
|
||||||
|
resources:
|
||||||
|
- roles
|
||||||
|
- rolebindings
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods/portforward
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods/log
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
- pods/exec
|
||||||
|
verbs:
|
||||||
|
- "*"
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- events
|
||||||
|
verbs:
|
||||||
|
- watch
|
||||||
|
- list
|
||||||
|
- create
|
||||||
|
- patch
|
||||||
|
- apiGroups:
|
||||||
|
- apps
|
||||||
|
resourceNames:
|
||||||
|
- jenkins-operator
|
||||||
|
resources:
|
||||||
|
- deployments/finalizers
|
||||||
|
verbs:
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- jenkins.io
|
||||||
|
resources:
|
||||||
|
- '*'
|
||||||
|
verbs:
|
||||||
|
- '*'
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- persistentvolumeclaims
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- "route.openshift.io"
|
||||||
|
resources:
|
||||||
|
- routes
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- "image.openshift.io"
|
||||||
|
resources:
|
||||||
|
- imagestreams
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- "build.openshift.io"
|
||||||
|
resources:
|
||||||
|
- builds
|
||||||
|
- buildconfigs
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: manager-rolebinding
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: manager-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: default
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
apiVersion: jenkins.io/v1alpha2
|
||||||
|
kind: Jenkins
|
||||||
|
metadata:
|
||||||
|
name: example
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
configurationAsCode:
|
||||||
|
configurations: []
|
||||||
|
secret:
|
||||||
|
name: ""
|
||||||
|
groovyScripts:
|
||||||
|
configurations: []
|
||||||
|
secret:
|
||||||
|
name: ""
|
||||||
|
jenkinsAPISettings:
|
||||||
|
authorizationStrategy: createUser
|
||||||
|
master:
|
||||||
|
disableCSRFProtection: false
|
||||||
|
containers:
|
||||||
|
- name: jenkins-master
|
||||||
|
image: jenkins/jenkins:2.263.3-lts-alpine
|
||||||
|
imagePullPolicy: Always
|
||||||
|
livenessProbe:
|
||||||
|
failureThreshold: 12
|
||||||
|
httpGet:
|
||||||
|
path: /login
|
||||||
|
port: http
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 100
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 5
|
||||||
|
readinessProbe:
|
||||||
|
failureThreshold: 10
|
||||||
|
httpGet:
|
||||||
|
path: /login
|
||||||
|
port: http
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 80
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 1
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 1500m
|
||||||
|
memory: 3Gi
|
||||||
|
requests:
|
||||||
|
cpu: "1"
|
||||||
|
memory: 500Mi
|
||||||
|
seedJobs:
|
||||||
|
- id: jenkins-operator
|
||||||
|
targets: "cicd/jobs/*.jenkins"
|
||||||
|
description: "Jenkins Operator repository"
|
||||||
|
repositoryBranch: master
|
||||||
|
repositoryUrl: https://github.com/jenkinsci/kubernetes-operator.git
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
## Append samples you want in your CSV to this file as resources ##
|
||||||
|
resources:
|
||||||
|
- jenkins.io_v1alpha2_jenkins.yaml
|
||||||
|
# +kubebuilder:scaffold:manifestskustomizesamples
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
apiVersion: scorecard.operatorframework.io/v1alpha3
|
||||||
|
kind: Configuration
|
||||||
|
metadata:
|
||||||
|
name: config
|
||||||
|
stages:
|
||||||
|
- parallel: true
|
||||||
|
tests: []
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
resources:
|
||||||
|
- bases/config.yaml
|
||||||
|
patchesJson6902:
|
||||||
|
- path: patches/basic.config.yaml
|
||||||
|
target:
|
||||||
|
group: scorecard.operatorframework.io
|
||||||
|
version: v1alpha3
|
||||||
|
kind: Configuration
|
||||||
|
name: config
|
||||||
|
- path: patches/olm.config.yaml
|
||||||
|
target:
|
||||||
|
group: scorecard.operatorframework.io
|
||||||
|
version: v1alpha3
|
||||||
|
kind: Configuration
|
||||||
|
name: config
|
||||||
|
# +kubebuilder:scaffold:patchesJson6902
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
- op: add
|
||||||
|
path: /stages/0/tests/-
|
||||||
|
value:
|
||||||
|
entrypoint:
|
||||||
|
- scorecard-test
|
||||||
|
- basic-check-spec
|
||||||
|
image: quay.io/operator-framework/scorecard-test:v1.3.0
|
||||||
|
labels:
|
||||||
|
suite: basic
|
||||||
|
test: basic-check-spec-test
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
- op: add
|
||||||
|
path: /stages/0/tests/-
|
||||||
|
value:
|
||||||
|
entrypoint:
|
||||||
|
- scorecard-test
|
||||||
|
- olm-bundle-validation
|
||||||
|
image: quay.io/operator-framework/scorecard-test:v1.3.0
|
||||||
|
labels:
|
||||||
|
suite: olm
|
||||||
|
test: olm-bundle-validation-test
|
||||||
|
- op: add
|
||||||
|
path: /stages/0/tests/-
|
||||||
|
value:
|
||||||
|
entrypoint:
|
||||||
|
- scorecard-test
|
||||||
|
- olm-crds-have-validation
|
||||||
|
image: quay.io/operator-framework/scorecard-test:v1.3.0
|
||||||
|
labels:
|
||||||
|
suite: olm
|
||||||
|
test: olm-crds-have-validation-test
|
||||||
|
- op: add
|
||||||
|
path: /stages/0/tests/-
|
||||||
|
value:
|
||||||
|
entrypoint:
|
||||||
|
- scorecard-test
|
||||||
|
- olm-crds-have-resources
|
||||||
|
image: quay.io/operator-framework/scorecard-test:v1.3.0
|
||||||
|
labels:
|
||||||
|
suite: olm
|
||||||
|
test: olm-crds-have-resources-test
|
||||||
|
- op: add
|
||||||
|
path: /stages/0/tests/-
|
||||||
|
value:
|
||||||
|
entrypoint:
|
||||||
|
- scorecard-test
|
||||||
|
- olm-spec-descriptors
|
||||||
|
image: quay.io/operator-framework/scorecard-test:v1.3.0
|
||||||
|
labels:
|
||||||
|
suite: olm
|
||||||
|
test: olm-spec-descriptors-test
|
||||||
|
- op: add
|
||||||
|
path: /stages/0/tests/-
|
||||||
|
value:
|
||||||
|
entrypoint:
|
||||||
|
- scorecard-test
|
||||||
|
- olm-status-descriptors
|
||||||
|
image: quay.io/operator-framework/scorecard-test:v1.3.0
|
||||||
|
labels:
|
||||||
|
suite: olm
|
||||||
|
test: olm-status-descriptors-test
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package jenkins
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
||||||
|
|
||||||
|
|
@ -20,14 +20,14 @@ import (
|
||||||
type enqueueRequestForJenkins struct{}
|
type enqueueRequestForJenkins struct{}
|
||||||
|
|
||||||
func (e *enqueueRequestForJenkins) Create(evt event.CreateEvent, q workqueue.RateLimitingInterface) {
|
func (e *enqueueRequestForJenkins) Create(evt event.CreateEvent, q workqueue.RateLimitingInterface) {
|
||||||
if req := e.getOwnerReconcileRequests(evt.Meta); req != nil {
|
if req := e.getOwnerReconcileRequests(evt.Object); req != nil {
|
||||||
q.Add(*req)
|
q.Add(*req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *enqueueRequestForJenkins) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
|
func (e *enqueueRequestForJenkins) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
|
||||||
req1 := e.getOwnerReconcileRequests(evt.MetaOld)
|
req1 := e.getOwnerReconcileRequests(evt.ObjectOld)
|
||||||
req2 := e.getOwnerReconcileRequests(evt.MetaNew)
|
req2 := e.getOwnerReconcileRequests(evt.ObjectNew)
|
||||||
|
|
||||||
if req1 != nil || req2 != nil {
|
if req1 != nil || req2 != nil {
|
||||||
jenkinsName := "unknown"
|
jenkinsName := "unknown"
|
||||||
|
|
@ -39,7 +39,7 @@ func (e *enqueueRequestForJenkins) Update(evt event.UpdateEvent, q workqueue.Rat
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Log.WithValues("cr", jenkinsName).Info(
|
log.Log.WithValues("cr", jenkinsName).Info(
|
||||||
fmt.Sprintf("%T/%s has been updated", evt.ObjectNew, evt.MetaNew.GetName()))
|
fmt.Sprintf("%T/%s has been updated", evt.ObjectNew, evt.ObjectNew.GetName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if req1 != nil {
|
if req1 != nil {
|
||||||
|
|
@ -52,13 +52,13 @@ func (e *enqueueRequestForJenkins) Update(evt event.UpdateEvent, q workqueue.Rat
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *enqueueRequestForJenkins) Delete(evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
|
func (e *enqueueRequestForJenkins) Delete(evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
|
||||||
if req := e.getOwnerReconcileRequests(evt.Meta); req != nil {
|
if req := e.getOwnerReconcileRequests(evt.Object); req != nil {
|
||||||
q.Add(*req)
|
q.Add(*req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *enqueueRequestForJenkins) Generic(evt event.GenericEvent, q workqueue.RateLimitingInterface) {
|
func (e *enqueueRequestForJenkins) Generic(evt event.GenericEvent, q workqueue.RateLimitingInterface) {
|
||||||
if req := e.getOwnerReconcileRequests(evt.Meta); req != nil {
|
if req := e.getOwnerReconcileRequests(evt.Object); req != nil {
|
||||||
q.Add(*req)
|
q.Add(*req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -85,8 +85,8 @@ func (e *jenkinsDecorator) Create(evt event.CreateEvent, q workqueue.RateLimitin
|
||||||
|
|
||||||
func (e *jenkinsDecorator) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
|
func (e *jenkinsDecorator) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) {
|
||||||
if !reflect.DeepEqual(evt.ObjectOld.(*v1alpha2.Jenkins).Spec, evt.ObjectNew.(*v1alpha2.Jenkins).Spec) {
|
if !reflect.DeepEqual(evt.ObjectOld.(*v1alpha2.Jenkins).Spec, evt.ObjectNew.(*v1alpha2.Jenkins).Spec) {
|
||||||
log.Log.WithValues("cr", evt.MetaNew.GetName()).Info(
|
log.Log.WithValues("cr", evt.ObjectNew.GetName()).Info(
|
||||||
fmt.Sprintf("%T/%s has been updated", evt.ObjectNew, evt.MetaNew.GetName()))
|
fmt.Sprintf("%T/%s has been updated", evt.ObjectNew, evt.ObjectNew.GetName()))
|
||||||
}
|
}
|
||||||
e.handler.Update(evt, q)
|
e.handler.Update(evt, q)
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,20 @@
|
||||||
package jenkins
|
/*
|
||||||
|
Copyright 2021.
|
||||||
|
|
||||||
|
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 controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
@ -7,8 +23,9 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/user"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/user"
|
||||||
|
|
@ -17,15 +34,17 @@ import (
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/reason"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/reason"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/plugins"
|
"github.com/jenkinsci/kubernetes-operator/pkg/plugins"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/controller"
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||||
)
|
)
|
||||||
|
|
@ -37,7 +56,6 @@ type reconcileError struct {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
APIVersion = "core/v1"
|
APIVersion = "core/v1"
|
||||||
PodKind = "Pod"
|
|
||||||
SecretKind = "Secret"
|
SecretKind = "Secret"
|
||||||
ConfigMapKind = "ConfigMap"
|
ConfigMapKind = "ConfigMap"
|
||||||
containerProbeURI = "login"
|
containerProbeURI = "login"
|
||||||
|
|
@ -46,66 +64,59 @@ const (
|
||||||
|
|
||||||
var reconcileErrors = map[string]reconcileError{}
|
var reconcileErrors = map[string]reconcileError{}
|
||||||
var logx = log.Log
|
var logx = log.Log
|
||||||
var _ reconcile.Reconciler = &ReconcileJenkins{}
|
|
||||||
|
|
||||||
// Add creates a newReconcilierConfiguration Jenkins Controller and adds it to the Manager. The Manager will set fields on the Controller
|
// JenkinsReconciler reconciles a Jenkins object
|
||||||
// and Start it when the Manager is Started.
|
type JenkinsReconciler struct {
|
||||||
func Add(mgr manager.Manager, jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings, kubernetesClusterDomain string, clientSet kubernetes.Clientset, config rest.Config, notificationEvents *chan event.Event) error {
|
Client client.Client
|
||||||
reconciler := newReconciler(mgr, jenkinsAPIConnectionSettings, kubernetesClusterDomain, clientSet, config, notificationEvents)
|
Scheme *runtime.Scheme
|
||||||
return add(mgr, reconciler)
|
JenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings
|
||||||
|
ClientSet kubernetes.Clientset
|
||||||
|
Config rest.Config
|
||||||
|
NotificationEvents *chan event.Event
|
||||||
|
KubernetesClusterDomain string
|
||||||
}
|
}
|
||||||
|
|
||||||
// add adds a newReconcilierConfiguration Controller to mgr with r as the reconcile.Reconciler.
|
// SetupWithManager sets up the controller with the Manager.
|
||||||
func add(mgr manager.Manager, r reconcile.Reconciler) error {
|
func (r *JenkinsReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||||
// Create a newReconcilierConfiguration controller
|
|
||||||
c, err := controller.New("jenkins-controller", mgr, controller.Options{Reconciler: r})
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch for changes to primary resource Jenkins
|
|
||||||
decorator := jenkinsDecorator{handler: &handler.EnqueueRequestForObject{}}
|
|
||||||
err = c.Watch(&source.Kind{Type: &v1alpha2.Jenkins{}}, &decorator)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch for changes to secondary resource Pods and requeue the owner Jenkins
|
|
||||||
|
|
||||||
podResource := &source.Kind{Type: &corev1.Pod{TypeMeta: metav1.TypeMeta{APIVersion: APIVersion, Kind: PodKind}}}
|
|
||||||
err = c.Watch(podResource, &handler.EnqueueRequestForOwner{
|
|
||||||
IsController: true,
|
|
||||||
OwnerType: &v1alpha2.Jenkins{},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
secretResource := &source.Kind{Type: &corev1.Secret{TypeMeta: metav1.TypeMeta{APIVersion: APIVersion, Kind: SecretKind}}}
|
|
||||||
err = c.Watch(secretResource, &handler.EnqueueRequestForOwner{
|
|
||||||
IsController: true,
|
|
||||||
OwnerType: &v1alpha2.Jenkins{},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
jenkinsHandler := &enqueueRequestForJenkins{}
|
jenkinsHandler := &enqueueRequestForJenkins{}
|
||||||
err = c.Watch(secretResource, jenkinsHandler)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
configMapResource := &source.Kind{Type: &corev1.ConfigMap{TypeMeta: metav1.TypeMeta{APIVersion: APIVersion, Kind: ConfigMapKind}}}
|
configMapResource := &source.Kind{Type: &corev1.ConfigMap{TypeMeta: metav1.TypeMeta{APIVersion: APIVersion, Kind: ConfigMapKind}}}
|
||||||
err = c.Watch(configMapResource, jenkinsHandler)
|
secretResource := &source.Kind{Type: &corev1.Secret{TypeMeta: metav1.TypeMeta{APIVersion: APIVersion, Kind: SecretKind}}}
|
||||||
if err != nil {
|
decorator := jenkinsDecorator{handler: &handler.EnqueueRequestForObject{}}
|
||||||
return errors.WithStack(err)
|
return ctrl.NewControllerManagedBy(mgr).
|
||||||
}
|
For(&v1alpha2.Jenkins{}).
|
||||||
return nil
|
Owns(&corev1.Pod{}).
|
||||||
|
Owns(&corev1.Secret{}).
|
||||||
|
Owns(&corev1.ConfigMap{}).
|
||||||
|
Watches(secretResource, jenkinsHandler).
|
||||||
|
Watches(configMapResource, jenkinsHandler).
|
||||||
|
Watches(&source.Kind{Type: &v1alpha2.Jenkins{}}, &decorator).
|
||||||
|
Complete(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reconcile it's a main reconciliation loop which maintain desired state based on Jenkins.Spec.
|
func (r *JenkinsReconciler) newJenkinsReconcilier(jenkins *v1alpha2.Jenkins) configuration.Configuration {
|
||||||
func (r *ReconcileJenkins) Reconcile(request reconcile.Request) (reconcile.Result, error) {
|
config := configuration.Configuration{
|
||||||
|
Client: r.Client,
|
||||||
|
ClientSet: r.ClientSet,
|
||||||
|
Notifications: r.NotificationEvents,
|
||||||
|
Jenkins: jenkins,
|
||||||
|
Scheme: r.Scheme,
|
||||||
|
Config: &r.Config,
|
||||||
|
JenkinsAPIConnectionSettings: r.JenkinsAPIConnectionSettings,
|
||||||
|
KubernetesClusterDomain: r.KubernetesClusterDomain,
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:rbac:groups=jenkins.io,resources=jenkins,verbs=get;list;watch;create;update;patch;delete
|
||||||
|
// +kubebuilder:rbac:groups=jenkins.io,resources=jenkins/status,verbs=get;update;patch
|
||||||
|
// +kubebuilder:rbac:groups=jenkins.io,resources=jenkins/finalizers,verbs=update
|
||||||
|
// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;create;update;patch;delete
|
||||||
|
// +kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch
|
||||||
|
// +kubebuilder:rbac:groups=v1,resources=secrets,verbs=get;list;watch
|
||||||
|
|
||||||
|
// For more details, check Reconcile and its Result here:
|
||||||
|
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.7.0/pkg/reconcile
|
||||||
|
func (r *JenkinsReconciler) Reconcile(_ context.Context, request ctrl.Request) (ctrl.Result, error) {
|
||||||
reconcileFailLimit := uint64(10)
|
reconcileFailLimit := uint64(10)
|
||||||
logger := logx.WithValues("cr", request.Name)
|
logger := logx.WithValues("cr", request.Name)
|
||||||
logger.V(log.VDebug).Info("Reconciling Jenkins")
|
logger.V(log.VDebug).Info("Reconciling Jenkins")
|
||||||
|
|
@ -131,18 +142,18 @@ func (r *ReconcileJenkins) Reconcile(request reconcile.Request) (reconcile.Resul
|
||||||
reconcileErrors[request.Name] = lastErrors
|
reconcileErrors[request.Name] = lastErrors
|
||||||
if lastErrors.counter >= reconcileFailLimit {
|
if lastErrors.counter >= reconcileFailLimit {
|
||||||
if log.Debug {
|
if log.Debug {
|
||||||
logger.V(log.VWarn).Info(fmt.Sprintf("Reconcile loop failed %d times with the same error, giving up: %+v", reconcileFailLimit, err))
|
logger.V(log.VWarn).Info(fmt.Sprintf("Reconcile loop failed %d times with the same errors, giving up: %+v", reconcileFailLimit, err))
|
||||||
} else {
|
} else {
|
||||||
logger.V(log.VWarn).Info(fmt.Sprintf("Reconcile loop failed %d times with the same error, giving up: %s", reconcileFailLimit, err))
|
logger.V(log.VWarn).Info(fmt.Sprintf("Reconcile loop failed %d times with the same errors, giving up: %s", reconcileFailLimit, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
*r.notificationEvents <- event.Event{
|
*r.NotificationEvents <- event.Event{
|
||||||
Jenkins: *jenkins,
|
Jenkins: *jenkins,
|
||||||
Phase: event.PhaseBase,
|
Phase: event.PhaseBase,
|
||||||
Level: v1alpha2.NotificationLevelWarning,
|
Level: v1alpha2.NotificationLevelWarning,
|
||||||
Reason: reason.NewReconcileLoopFailed(
|
Reason: reason.NewReconcileLoopFailed(
|
||||||
reason.OperatorSource,
|
reason.OperatorSource,
|
||||||
[]string{fmt.Sprintf("Reconcile loop failed %d times with the same error, giving up: %s", reconcileFailLimit, err)},
|
[]string{fmt.Sprintf("Reconcile loop failed %d times with the same errors, giving up: %s", reconcileFailLimit, err)},
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
return reconcile.Result{Requeue: false}, nil
|
return reconcile.Result{Requeue: false}, nil
|
||||||
|
|
@ -155,7 +166,7 @@ func (r *ReconcileJenkins) Reconcile(request reconcile.Request) (reconcile.Resul
|
||||||
}
|
}
|
||||||
|
|
||||||
if groovyErr, ok := err.(*jenkinsclient.GroovyScriptExecutionFailed); ok {
|
if groovyErr, ok := err.(*jenkinsclient.GroovyScriptExecutionFailed); ok {
|
||||||
*r.notificationEvents <- event.Event{
|
*r.NotificationEvents <- event.Event{
|
||||||
Jenkins: *jenkins,
|
Jenkins: *jenkins,
|
||||||
Phase: event.PhaseBase,
|
Phase: event.PhaseBase,
|
||||||
Level: v1alpha2.NotificationLevelWarning,
|
Level: v1alpha2.NotificationLevelWarning,
|
||||||
|
|
@ -175,12 +186,12 @@ func (r *ReconcileJenkins) Reconcile(request reconcile.Request) (reconcile.Resul
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkins) reconcile(request reconcile.Request) (reconcile.Result, *v1alpha2.Jenkins, error) {
|
func (r *JenkinsReconciler) reconcile(request reconcile.Request) (reconcile.Result, *v1alpha2.Jenkins, error) {
|
||||||
logger := logx.WithValues("cr", request.Name)
|
logger := logx.WithValues("cr", request.Name)
|
||||||
// Fetch the Jenkins instance
|
// Fetch the Jenkins instance
|
||||||
jenkins := &v1alpha2.Jenkins{}
|
jenkins := &v1alpha2.Jenkins{}
|
||||||
var err error
|
var err error
|
||||||
err = r.client.Get(context.TODO(), request.NamespacedName, jenkins)
|
err = r.Client.Get(context.TODO(), request.NamespacedName, jenkins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if apierrors.IsNotFound(err) {
|
if apierrors.IsNotFound(err) {
|
||||||
// Request object not found, could have been deleted after reconcile request.
|
// Request object not found, could have been deleted after reconcile request.
|
||||||
|
|
@ -200,17 +211,9 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request) (reconcile.Resul
|
||||||
return reconcile.Result{Requeue: true}, jenkins, nil
|
return reconcile.Result{Requeue: true}, jenkins, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
requeue, err = r.handleDeprecatedData(jenkins)
|
config := r.newJenkinsReconcilier(jenkins)
|
||||||
if err != nil {
|
|
||||||
return reconcile.Result{}, jenkins, err
|
|
||||||
}
|
|
||||||
if requeue {
|
|
||||||
return reconcile.Result{Requeue: true}, jenkins, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
config := r.newReconcilierConfiguration(jenkins)
|
|
||||||
// Reconcile base configuration
|
// Reconcile base configuration
|
||||||
baseConfiguration := base.New(config, r.jenkinsAPIConnectionSettings)
|
baseConfiguration := base.New(config, r.JenkinsAPIConnectionSettings)
|
||||||
|
|
||||||
var baseMessages []string
|
var baseMessages []string
|
||||||
baseMessages, err = baseConfiguration.Validate(jenkins)
|
baseMessages, err = baseConfiguration.Validate(jenkins)
|
||||||
|
|
@ -219,7 +222,7 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request) (reconcile.Resul
|
||||||
}
|
}
|
||||||
if len(baseMessages) > 0 {
|
if len(baseMessages) > 0 {
|
||||||
message := "Validation of base configuration failed, please correct Jenkins CR."
|
message := "Validation of base configuration failed, please correct Jenkins CR."
|
||||||
*r.notificationEvents <- event.Event{
|
*r.NotificationEvents <- event.Event{
|
||||||
Jenkins: *jenkins,
|
Jenkins: *jenkins,
|
||||||
Phase: event.PhaseBase,
|
Phase: event.PhaseBase,
|
||||||
Level: v1alpha2.NotificationLevelWarning,
|
Level: v1alpha2.NotificationLevelWarning,
|
||||||
|
|
@ -248,14 +251,14 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request) (reconcile.Resul
|
||||||
if jenkins.Status.BaseConfigurationCompletedTime == nil {
|
if jenkins.Status.BaseConfigurationCompletedTime == nil {
|
||||||
now := metav1.Now()
|
now := metav1.Now()
|
||||||
jenkins.Status.BaseConfigurationCompletedTime = &now
|
jenkins.Status.BaseConfigurationCompletedTime = &now
|
||||||
err = r.client.Update(context.TODO(), jenkins)
|
err = r.Client.Status().Update(context.TODO(), jenkins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reconcile.Result{}, jenkins, errors.WithStack(err)
|
return reconcile.Result{}, jenkins, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
message := fmt.Sprintf("Base configuration phase is complete, took %s",
|
message := fmt.Sprintf("Base configuration phase is complete, took %s",
|
||||||
jenkins.Status.BaseConfigurationCompletedTime.Sub(jenkins.Status.ProvisionStartTime.Time))
|
jenkins.Status.BaseConfigurationCompletedTime.Sub(jenkins.Status.ProvisionStartTime.Time))
|
||||||
*r.notificationEvents <- event.Event{
|
*r.NotificationEvents <- event.Event{
|
||||||
Jenkins: *jenkins,
|
Jenkins: *jenkins,
|
||||||
Phase: event.PhaseBase,
|
Phase: event.PhaseBase,
|
||||||
Level: v1alpha2.NotificationLevelInfo,
|
Level: v1alpha2.NotificationLevelInfo,
|
||||||
|
|
@ -274,7 +277,7 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request) (reconcile.Resul
|
||||||
}
|
}
|
||||||
if len(messages) > 0 {
|
if len(messages) > 0 {
|
||||||
message := "Validation of user configuration failed, please correct Jenkins CR"
|
message := "Validation of user configuration failed, please correct Jenkins CR"
|
||||||
*r.notificationEvents <- event.Event{
|
*r.NotificationEvents <- event.Event{
|
||||||
Jenkins: *jenkins,
|
Jenkins: *jenkins,
|
||||||
Phase: event.PhaseUser,
|
Phase: event.PhaseUser,
|
||||||
Level: v1alpha2.NotificationLevelWarning,
|
Level: v1alpha2.NotificationLevelWarning,
|
||||||
|
|
@ -309,13 +312,13 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request) (reconcile.Resul
|
||||||
if jenkins.Status.UserConfigurationCompletedTime == nil {
|
if jenkins.Status.UserConfigurationCompletedTime == nil {
|
||||||
now := metav1.Now()
|
now := metav1.Now()
|
||||||
jenkins.Status.UserConfigurationCompletedTime = &now
|
jenkins.Status.UserConfigurationCompletedTime = &now
|
||||||
err = r.client.Update(context.TODO(), jenkins)
|
err = r.Client.Status().Update(context.TODO(), jenkins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reconcile.Result{}, jenkins, errors.WithStack(err)
|
return reconcile.Result{}, jenkins, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
message := fmt.Sprintf("User configuration phase is complete, took %s",
|
message := fmt.Sprintf("User configuration phase is complete, took %s",
|
||||||
jenkins.Status.UserConfigurationCompletedTime.Sub(jenkins.Status.ProvisionStartTime.Time))
|
jenkins.Status.UserConfigurationCompletedTime.Sub(jenkins.Status.ProvisionStartTime.Time))
|
||||||
*r.notificationEvents <- event.Event{
|
*r.NotificationEvents <- event.Event{
|
||||||
Jenkins: *jenkins,
|
Jenkins: *jenkins,
|
||||||
Phase: event.PhaseUser,
|
Phase: event.PhaseUser,
|
||||||
Level: v1alpha2.NotificationLevelInfo,
|
Level: v1alpha2.NotificationLevelInfo,
|
||||||
|
|
@ -326,7 +329,7 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request) (reconcile.Resul
|
||||||
return reconcile.Result{}, jenkins, nil
|
return reconcile.Result{}, jenkins, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkins) setDefaults(jenkins *v1alpha2.Jenkins) (requeue bool, err error) {
|
func (r *JenkinsReconciler) setDefaults(jenkins *v1alpha2.Jenkins) (requeue bool, err error) {
|
||||||
changed := false
|
changed := false
|
||||||
logger := logx.WithValues("cr", jenkins.Name)
|
logger := logx.WithValues("cr", jenkins.Name)
|
||||||
|
|
||||||
|
|
@ -356,7 +359,7 @@ func (r *ReconcileJenkins) setDefaults(jenkins *v1alpha2.Jenkins) (requeue bool,
|
||||||
if jenkinsContainer.ReadinessProbe == nil {
|
if jenkinsContainer.ReadinessProbe == nil {
|
||||||
logger.Info("Setting default Jenkins readinessProbe")
|
logger.Info("Setting default Jenkins readinessProbe")
|
||||||
changed = true
|
changed = true
|
||||||
jenkinsContainer.ReadinessProbe = resources.NewSimpleProbe(containerProbeURI, containerProbePortName, corev1.URISchemeHTTP, 30)
|
jenkinsContainer.ReadinessProbe = resources.NewProbe(containerProbeURI, containerProbePortName, corev1.URISchemeHTTP, 60, 1, 10)
|
||||||
}
|
}
|
||||||
if jenkinsContainer.LivenessProbe == nil {
|
if jenkinsContainer.LivenessProbe == nil {
|
||||||
logger.Info("Setting default Jenkins livenessProbe")
|
logger.Info("Setting default Jenkins livenessProbe")
|
||||||
|
|
@ -390,7 +393,7 @@ func (r *ReconcileJenkins) setDefaults(jenkins *v1alpha2.Jenkins) (requeue bool,
|
||||||
logger.Info("Setting default Jenkins master service")
|
logger.Info("Setting default Jenkins master service")
|
||||||
changed = true
|
changed = true
|
||||||
var serviceType = corev1.ServiceTypeClusterIP
|
var serviceType = corev1.ServiceTypeClusterIP
|
||||||
if r.jenkinsAPIConnectionSettings.UseNodePort {
|
if r.JenkinsAPIConnectionSettings.UseNodePort {
|
||||||
serviceType = corev1.ServiceTypeNodePort
|
serviceType = corev1.ServiceTypeNodePort
|
||||||
}
|
}
|
||||||
jenkins.Spec.Service = v1alpha2.Service{
|
jenkins.Spec.Service = v1alpha2.Service{
|
||||||
|
|
@ -441,7 +444,7 @@ func (r *ReconcileJenkins) setDefaults(jenkins *v1alpha2.Jenkins) (requeue bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
if changed {
|
if changed {
|
||||||
return changed, errors.WithStack(r.client.Update(context.TODO(), jenkins))
|
return changed, errors.WithStack(r.Client.Update(context.TODO(), jenkins))
|
||||||
}
|
}
|
||||||
return changed, nil
|
return changed, nil
|
||||||
}
|
}
|
||||||
|
|
@ -455,7 +458,7 @@ func isJavaOpsVariableNotSet(container v1alpha2.Container) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkins) setDefaultsForContainer(jenkins *v1alpha2.Jenkins, containerName string, containerIndex int) bool {
|
func (r *JenkinsReconciler) setDefaultsForContainer(jenkins *v1alpha2.Jenkins, containerName string, containerIndex int) bool {
|
||||||
changed := false
|
changed := false
|
||||||
logger := logx.WithValues("cr", jenkins.Name, "container", containerName)
|
logger := logx.WithValues("cr", jenkins.Name, "container", containerName)
|
||||||
|
|
||||||
|
|
@ -482,18 +485,3 @@ func basePlugins() (result []v1alpha2.Plugin) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkins) handleDeprecatedData(jenkins *v1alpha2.Jenkins) (requeue bool, err error) {
|
|
||||||
changed := false
|
|
||||||
logger := logx.WithValues("cr", jenkins.Name)
|
|
||||||
if len(jenkins.Spec.Master.AnnotationsDeprecated) > 0 {
|
|
||||||
changed = true
|
|
||||||
jenkins.Spec.Master.Annotations = jenkins.Spec.Master.AnnotationsDeprecated
|
|
||||||
jenkins.Spec.Master.AnnotationsDeprecated = map[string]string{}
|
|
||||||
logger.V(log.VWarn).Info("spec.master.masterAnnotations is deprecated, the annotations have been moved to spec.master.annotations")
|
|
||||||
}
|
|
||||||
if changed {
|
|
||||||
return changed, errors.WithStack(r.client.Update(context.TODO(), jenkins))
|
|
||||||
}
|
|
||||||
return changed, nil
|
|
||||||
}
|
|
||||||
82
go.mod
82
go.mod
|
|
@ -1,75 +1,29 @@
|
||||||
module github.com/jenkinsci/kubernetes-operator
|
module github.com/jenkinsci/kubernetes-operator
|
||||||
|
|
||||||
go 1.13
|
go 1.15
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bndr/gojenkins v0.0.0-20181125150310-de43c03cf849
|
github.com/bndr/gojenkins v1.0.1
|
||||||
github.com/docker/distribution v2.7.1+incompatible
|
github.com/docker/distribution v2.7.1+incompatible
|
||||||
github.com/elazarl/goproxy v0.0.0-20190711103511-473e67f1d7d2 // indirect
|
|
||||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 // indirect
|
|
||||||
github.com/emersion/go-sasl v0.0.0-20190817083125-240c8404624e // indirect
|
|
||||||
github.com/emersion/go-smtp v0.11.2
|
github.com/emersion/go-smtp v0.11.2
|
||||||
github.com/go-logr/logr v0.1.0
|
github.com/go-logr/logr v0.3.0
|
||||||
github.com/go-logr/zapr v0.1.1
|
github.com/go-logr/zapr v0.2.0
|
||||||
github.com/go-openapi/spec v0.19.4
|
github.com/golang/mock v1.4.1
|
||||||
github.com/golang/mock v1.3.1
|
github.com/mailgun/mailgun-go/v3 v3.6.4
|
||||||
github.com/golangci/golangci-lint v1.26.0 // indirect
|
github.com/onsi/ginkgo v1.14.1
|
||||||
github.com/mailgun/mailgun-go/v3 v3.6.0
|
github.com/onsi/gomega v1.10.2
|
||||||
github.com/openshift/api v3.9.1-0.20190924102528-32369d4db2ad+incompatible
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/operator-framework/operator-sdk v0.17.0
|
github.com/openshift/api v3.9.0+incompatible
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/robfig/cron v1.2.0
|
github.com/robfig/cron v1.2.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/stretchr/testify v1.6.1
|
||||||
github.com/stretchr/testify v1.5.1
|
go.uber.org/zap v1.15.0
|
||||||
go.uber.org/zap v1.14.1
|
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
|
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b
|
|
||||||
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8 // indirect
|
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
k8s.io/api v0.17.4
|
k8s.io/api v0.20.2
|
||||||
k8s.io/apimachinery v0.17.4
|
k8s.io/apimachinery v0.20.2
|
||||||
k8s.io/cli-runtime v0.17.4
|
k8s.io/cli-runtime v0.20.2
|
||||||
k8s.io/client-go v12.0.0+incompatible
|
k8s.io/client-go v0.20.2
|
||||||
k8s.io/code-generator v0.17.4
|
k8s.io/utils v0.0.0-20201110183641-67b214c5f920
|
||||||
k8s.io/gengo v0.0.0-20191010091904-7fa3014cb28f
|
sigs.k8s.io/controller-runtime v0.7.0
|
||||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
|
|
||||||
k8s.io/utils v0.0.0-20190801114015-581e00157fb1
|
|
||||||
sigs.k8s.io/controller-runtime v0.5.2
|
|
||||||
sigs.k8s.io/controller-tools v0.2.8
|
|
||||||
)
|
|
||||||
|
|
||||||
// Pinned to kubernetes-1.16.2
|
|
||||||
replace (
|
|
||||||
github.com/Azure/go-autorest => github.com/Azure/go-autorest v12.2.0+incompatible
|
|
||||||
k8s.io/api => k8s.io/api v0.0.0-20191016110408-35e52d86657a
|
|
||||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20191016113550-5357c4baaf65
|
|
||||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8
|
|
||||||
k8s.io/apiserver => k8s.io/apiserver v0.0.0-20191016112112-5190913f932d
|
|
||||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20191016114015-74ad18325ed5
|
|
||||||
k8s.io/client-go => k8s.io/client-go v0.0.0-20191016111102-bec269661e48
|
|
||||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.0.0-20191016115326-20453efc2458
|
|
||||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.0.0-20191016115129-c07a134afb42
|
|
||||||
k8s.io/component-base => k8s.io/component-base v0.0.0-20191016111319-039242c015a9
|
|
||||||
k8s.io/cri-api => k8s.io/cri-api v0.0.0-20190828162817-608eb1dad4ac
|
|
||||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.0.0-20191016115521-756ffa5af0bd
|
|
||||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.0.0-20191016112429-9587704a8ad4
|
|
||||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.0.0-20191016114939-2b2b218dc1df
|
|
||||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.0.0-20191016114407-2e83b6f20229
|
|
||||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.0.0-20191016114748-65049c67a58b
|
|
||||||
k8s.io/kubectl => k8s.io/kubectl v0.0.0-20191016120415-2ed914427d51
|
|
||||||
k8s.io/kubelet => k8s.io/kubelet v0.0.0-20191016114556-7841ed97f1b2
|
|
||||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.0.0-20191016115753-cf0698c3a16b
|
|
||||||
k8s.io/metrics => k8s.io/metrics v0.0.0-20191016113814-3b1a734dba6e
|
|
||||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.0.0-20191016112829-06bb3c9d77c9
|
|
||||||
)
|
|
||||||
|
|
||||||
replace (
|
|
||||||
github.com/coreos/prometheus-operator => github.com/coreos/prometheus-operator v0.35.1
|
|
||||||
github.com/docker/docker => github.com/moby/moby v0.7.3-0.20190826074503-38ab9da00309
|
|
||||||
github.com/operator-framework/operator-sdk => github.com/operator-framework/operator-sdk v0.17.0
|
|
||||||
k8s.io/code-generator => k8s.io/code-generator v0.0.0-20181117043124-c2090bec4d9b
|
|
||||||
k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20180711000925-0cf8f7e6ed1d
|
|
||||||
sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.4.0
|
|
||||||
sigs.k8s.io/controller-tools => sigs.k8s.io/controller-tools v0.1.11-0.20190411181648-9d55346c2bde
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021.
|
||||||
|
|
||||||
|
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,193 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021.
|
||||||
|
|
||||||
|
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"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
r "runtime"
|
||||||
|
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/controllers"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/event"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications"
|
||||||
|
e "github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/version"
|
||||||
|
|
||||||
|
routev1 "github.com/openshift/api/route/v1"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client/config"
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||||
|
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||||
|
// +kubebuilder:scaffold:imports
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
metricsHost = "0.0.0.0"
|
||||||
|
metricsPort int32 = 8383
|
||||||
|
scheme = runtime.NewScheme()
|
||||||
|
logger = logf.Log.WithName("cmd")
|
||||||
|
)
|
||||||
|
|
||||||
|
func printInfo() {
|
||||||
|
logger.Info(fmt.Sprintf("Version: %s", version.Version))
|
||||||
|
logger.Info(fmt.Sprintf("Git commit: %s", version.GitCommit))
|
||||||
|
logger.Info(fmt.Sprintf("Go Version: %s", r.Version()))
|
||||||
|
logger.Info(fmt.Sprintf("Go OS/Arch: %s/%s", r.GOOS, r.GOARCH))
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
|
||||||
|
utilruntime.Must(v1alpha2.AddToScheme(scheme))
|
||||||
|
utilruntime.Must(routev1.AddToScheme(scheme))
|
||||||
|
utilruntime.Must(corev1.AddToScheme(scheme))
|
||||||
|
// +kubebuilder:scaffold:scheme
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var metricsAddr string
|
||||||
|
var enableLeaderElection bool
|
||||||
|
var probeAddr string
|
||||||
|
|
||||||
|
isRunningInCluster, err := resources.IsRunningInCluster()
|
||||||
|
if err != nil {
|
||||||
|
fatal(errors.Wrap(err, "failed to get watch namespace"), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
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", isRunningInCluster, "Enable leader election for controller manager. "+
|
||||||
|
"Enabling this will ensure there is only one active controller manager.")
|
||||||
|
hostname := flag.String("jenkins-api-hostname", "", "Hostname or IP of Jenkins API. It can be service name, node IP or localhost.")
|
||||||
|
port := flag.Int("jenkins-api-port", 0, "The port on which Jenkins API is running. Note: If you want to use nodePort don't set this setting and --jenkins-api-use-nodeport must be true.")
|
||||||
|
useNodePort := flag.Bool("jenkins-api-use-nodeport", false, "Connect to Jenkins API using the service nodePort instead of service port. If you want to set this as true - don't set --jenkins-api-port.")
|
||||||
|
kubernetesClusterDomain := flag.String("cluster-domain", "cluster.local", "Use custom domain name instead of 'cluster.local'.")
|
||||||
|
opts := zap.Options{
|
||||||
|
Development: true,
|
||||||
|
}
|
||||||
|
opts.BindFlags(flag.CommandLine)
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
debug := &opts.Development
|
||||||
|
log.Debug = *debug
|
||||||
|
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
|
||||||
|
printInfo()
|
||||||
|
|
||||||
|
namespace, found := os.LookupEnv("WATCH_NAMESPACE")
|
||||||
|
if !found {
|
||||||
|
fatal(errors.New("failed to get watch namespace, please set up WATCH_NAMESPACE environment variable"), *debug)
|
||||||
|
}
|
||||||
|
logger.Info(fmt.Sprintf("Watch namespace: %v", namespace))
|
||||||
|
|
||||||
|
// get a config to talk to the API server
|
||||||
|
cfg, err := config.GetConfig()
|
||||||
|
if err != nil {
|
||||||
|
fatal(errors.Wrap(err, "failed to get config"), *debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
||||||
|
Scheme: scheme,
|
||||||
|
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
|
||||||
|
Port: 9443,
|
||||||
|
HealthProbeBindAddress: probeAddr,
|
||||||
|
LeaderElection: enableLeaderElection,
|
||||||
|
LeaderElectionID: "c674355f.jenkins.io",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fatal(errors.Wrap(err, "unable to start manager"), *debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup events
|
||||||
|
events, err := event.New(cfg, constants.OperatorName)
|
||||||
|
if err != nil {
|
||||||
|
fatal(errors.Wrap(err, "failed to setup events"), *debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Setup controller
|
||||||
|
clientSet, err := kubernetes.NewForConfig(cfg)
|
||||||
|
if err != nil {
|
||||||
|
fatal(errors.Wrap(err, "failed to create Kubernetes client set"), *debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resources.IsRouteAPIAvailable(clientSet) {
|
||||||
|
logger.Info("Route API found: Route creation will be performed")
|
||||||
|
}
|
||||||
|
notificationEvents := make(chan e.Event)
|
||||||
|
go notifications.Listen(notificationEvents, events, mgr.GetClient())
|
||||||
|
|
||||||
|
// validate jenkins API connection
|
||||||
|
jenkinsAPIConnectionSettings := client.JenkinsAPIConnectionSettings{Hostname: *hostname, Port: *port, UseNodePort: *useNodePort}
|
||||||
|
if err := jenkinsAPIConnectionSettings.Validate(); err != nil {
|
||||||
|
fatal(errors.Wrap(err, "invalid command line parameters"), *debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate kubernetes cluster domain
|
||||||
|
if *kubernetesClusterDomain == "" {
|
||||||
|
fatal(errors.Wrap(err, "Kubernetes cluster domain can't be empty"), *debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = (&controllers.JenkinsReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
JenkinsAPIConnectionSettings: jenkinsAPIConnectionSettings,
|
||||||
|
ClientSet: *clientSet,
|
||||||
|
Config: *cfg,
|
||||||
|
NotificationEvents: ¬ificationEvents,
|
||||||
|
KubernetesClusterDomain: *kubernetesClusterDomain,
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
fatal(errors.Wrap(err, "unable to create Jenkins controller"), *debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:scaffold:builder
|
||||||
|
|
||||||
|
if err := mgr.AddHealthzCheck("health", healthz.Ping); err != nil {
|
||||||
|
fatal(errors.Wrap(err, "unable to set up health check"), *debug)
|
||||||
|
}
|
||||||
|
if err := mgr.AddReadyzCheck("check", healthz.Ping); err != nil {
|
||||||
|
fatal(errors.Wrap(err, "unable to set up ready check"), *debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("starting manager")
|
||||||
|
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
|
||||||
|
fatal(errors.Wrap(err, "problem running manager"), *debug)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fatal(err error, debug bool) {
|
||||||
|
if debug {
|
||||||
|
logger.Error(nil, fmt.Sprintf("%+v", err))
|
||||||
|
} else {
|
||||||
|
logger.Error(nil, fmt.Sprintf("%s", err))
|
||||||
|
}
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package apis
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
|
||||||
routev1 "github.com/openshift/api/route/v1"
|
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AddToSchemes may be used to add all resources defined in the project to a Scheme.
|
|
||||||
var AddToSchemes runtime.SchemeBuilder
|
|
||||||
|
|
||||||
// AddToScheme adds all Resources to the Scheme.
|
|
||||||
func AddToScheme(s *runtime.Scheme) error {
|
|
||||||
return AddToSchemes.AddToScheme(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
|
|
||||||
AddToSchemes = append(AddToSchemes, v1alpha2.SchemeBuilder.AddToScheme)
|
|
||||||
AddToSchemes = append(AddToSchemes, routev1.Install)
|
|
||||||
AddToSchemes = append(AddToSchemes, appsv1.AddToScheme)
|
|
||||||
}
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
package v1alpha2
|
|
||||||
|
|
||||||
import (
|
|
||||||
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.
|
|
||||||
|
|
||||||
// JenkinsImageSpec defines the desired state of JenkinsImage
|
|
||||||
type JenkinsImageSpec struct {
|
|
||||||
BaseImage Image `json:"image"`
|
|
||||||
Plugins []JenkinsPlugin `json:"plugins"` // Plugins list
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defines Jenkins Plugin structure
|
|
||||||
type JenkinsPlugin struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Version string `json:"version,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defines Jenkins Plugin structure
|
|
||||||
type Image struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Tag string `json:"version,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// JenkinsImageStatus defines the observed state of JenkinsImage
|
|
||||||
type JenkinsImageStatus struct {
|
|
||||||
Image string `json:"image,omitempty"`
|
|
||||||
MD5Sum string `json:"md5sum,omitempty"`
|
|
||||||
InstalledPlugins []JenkinsPlugin `json:"installedPlugins,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
|
||||||
|
|
||||||
// JenkinsImage is the Schema for the jenkinsimages API
|
|
||||||
// +kubebuilder:subresource:status
|
|
||||||
// +kubebuilder:resource:path=jenkinsimages,scope=Namespaced
|
|
||||||
type JenkinsImage struct {
|
|
||||||
metav1.TypeMeta `json:",inline"`
|
|
||||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
|
||||||
Spec JenkinsImageSpec `json:"spec,omitempty"`
|
|
||||||
Status JenkinsImageStatus `json:"status,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
|
||||||
|
|
||||||
// JenkinsImageList contains a list of JenkinsImage
|
|
||||||
type JenkinsImageList struct {
|
|
||||||
metav1.TypeMeta `json:",inline"`
|
|
||||||
metav1.ListMeta `json:"metadata,omitempty"`
|
|
||||||
Items []JenkinsImage `json:"items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
SchemeBuilder.Register(&JenkinsImage{}, &JenkinsImageList{})
|
|
||||||
}
|
|
||||||
|
|
@ -1,275 +0,0 @@
|
||||||
// +build !ignore_autogenerated
|
|
||||||
|
|
||||||
// This file was autogenerated by openapi-gen. Do not edit it manually!
|
|
||||||
|
|
||||||
package v1alpha2
|
|
||||||
|
|
||||||
import (
|
|
||||||
spec "github.com/go-openapi/spec"
|
|
||||||
common "k8s.io/kube-openapi/pkg/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
|
|
||||||
return map[string]common.OpenAPIDefinition{
|
|
||||||
"github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Jenkins": schema_pkg_apis_jenkins_v1alpha2_Jenkins(ref),
|
|
||||||
"github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.JenkinsSpec": schema_pkg_apis_jenkins_v1alpha2_JenkinsSpec(ref),
|
|
||||||
"github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.JenkinsStatus": schema_pkg_apis_jenkins_v1alpha2_JenkinsStatus(ref),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func schema_pkg_apis_jenkins_v1alpha2_Jenkins(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
|
||||||
return common.OpenAPIDefinition{
|
|
||||||
Schema: spec.Schema{
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "Jenkins is the Schema for the jenkins API",
|
|
||||||
Type: []string{"object"},
|
|
||||||
Properties: map[string]spec.Schema{
|
|
||||||
"kind": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
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{"string"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"apiVersion": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
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{"string"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"spec": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "Spec defines the desired state of the Jenkins",
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.JenkinsSpec"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"status": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "Status defines the observed state of Jenkins",
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.JenkinsStatus"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Dependencies: []string{
|
|
||||||
"github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.JenkinsSpec", "github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.JenkinsStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func schema_pkg_apis_jenkins_v1alpha2_JenkinsSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
|
||||||
return common.OpenAPIDefinition{
|
|
||||||
Schema: spec.Schema{
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "JenkinsSpec defines the desired state of the Jenkins",
|
|
||||||
Type: []string{"object"},
|
|
||||||
Properties: map[string]spec.Schema{
|
|
||||||
"master": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "Master represents Jenkins master pod properties and Jenkins plugins. Every single change here requires a pod restart.",
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.JenkinsMaster"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"seedJobs": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "SeedJobs defines list of Jenkins Seed Job configurations More info: https://github.com/jenkinsci/kubernetes-operator/blob/master/docs/getting-started.md#configure-seed-jobs-and-pipelines",
|
|
||||||
Type: []string{"array"},
|
|
||||||
Items: &spec.SchemaOrArray{
|
|
||||||
Schema: &spec.Schema{
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.SeedJob"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"notifications": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "Notifications defines list of a services which are used to inform about Jenkins status Can be used to integrate chat services like Slack, Microsoft Teams or Mailgun",
|
|
||||||
Type: []string{"array"},
|
|
||||||
Items: &spec.SchemaOrArray{
|
|
||||||
Schema: &spec.Schema{
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Notification"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"service": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "Service is Kubernetes service of Jenkins master HTTP pod Defaults to : port: 8080 type: ClusterIP",
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Service"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"slaveService": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "Service is Kubernetes service of Jenkins slave pods Defaults to : port: 50000 type: ClusterIP",
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Service"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"backup": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "Backup defines configuration of Jenkins backup More info: https://github.com/jenkinsci/kubernetes-operator/blob/master/docs/getting-started.md#configure-backup-and-restore",
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Backup"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"restore": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "Backup defines configuration of Jenkins backup restore More info: https://github.com/jenkinsci/kubernetes-operator/blob/master/docs/getting-started.md#configure-backup-and-restore",
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Restore"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"groovyScripts": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "GroovyScripts defines configuration of Jenkins customization via groovy scripts",
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.GroovyScripts"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"configurationAsCode": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "ConfigurationAsCode defines configuration of Jenkins customization via Configuration as Code Jenkins plugin",
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.ConfigurationAsCode"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"roles": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "Roles defines list of extra RBAC roles for the Jenkins Master pod service account",
|
|
||||||
Type: []string{"array"},
|
|
||||||
Items: &spec.SchemaOrArray{
|
|
||||||
Schema: &spec.Schema{
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Ref: ref("k8s.io/api/rbac/v1.RoleRef"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"serviceAccount": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "ServiceAccount defines Jenkins master service account attributes",
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.ServiceAccount"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"jenkinsAPISettings": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "JenkinsAPISettings defines configuration used by the operator to gain admin access to the Jenkins API",
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.JenkinsAPISettings"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Required: []string{"master", "jenkinsAPISettings"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Dependencies: []string{
|
|
||||||
"github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Backup", "github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.ConfigurationAsCode", "github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.GroovyScripts", "github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.JenkinsAPISettings", "github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.JenkinsMaster", "github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Notification", "github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Restore", "github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.SeedJob", "github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Service", "github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.ServiceAccount", "k8s.io/api/rbac/v1.RoleRef"},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func schema_pkg_apis_jenkins_v1alpha2_JenkinsStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
|
||||||
return common.OpenAPIDefinition{
|
|
||||||
Schema: spec.Schema{
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "JenkinsStatus defines the observed state of Jenkins",
|
|
||||||
Type: []string{"object"},
|
|
||||||
Properties: map[string]spec.Schema{
|
|
||||||
"operatorVersion": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "OperatorVersion is the operator version which manages this CR",
|
|
||||||
Type: []string{"string"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"provisionStartTime": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "ProvisionStartTime is a time when Jenkins master pod has been created",
|
|
||||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"baseConfigurationCompletedTime": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "BaseConfigurationCompletedTime is a time when Jenkins base configuration phase has been completed",
|
|
||||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"userConfigurationCompletedTime": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "UserConfigurationCompletedTime is a time when Jenkins user configuration phase has been completed",
|
|
||||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"restoredBackup": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "RestoredBackup is the restored backup number after Jenkins master pod restart",
|
|
||||||
Type: []string{"integer"},
|
|
||||||
Format: "int64",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"lastBackup": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "LastBackup is the latest backup number",
|
|
||||||
Type: []string{"integer"},
|
|
||||||
Format: "int64",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"pendingBackup": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "PendingBackup is the pending backup number",
|
|
||||||
Type: []string{"integer"},
|
|
||||||
Format: "int64",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"backupDoneBeforePodDeletion": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "BackupDoneBeforePodDeletion tells if backup before pod deletion has been made",
|
|
||||||
Type: []string{"boolean"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"userAndPasswordHash": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "UserAndPasswordHash is a SHA256 hash made from user and password",
|
|
||||||
Type: []string{"string"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"createdSeedJobs": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "CreatedSeedJobs contains list of seed job id already created in Jenkins",
|
|
||||||
Type: []string{"array"},
|
|
||||||
Items: &spec.SchemaOrArray{
|
|
||||||
Schema: &spec.Schema{
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Type: []string{"string"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"appliedGroovyScripts": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "AppliedGroovyScripts is a list with all applied groovy scripts in Jenkins by the operator",
|
|
||||||
Type: []string{"array"},
|
|
||||||
Items: &spec.SchemaOrArray{
|
|
||||||
Schema: &spec.Schema{
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Ref: ref("github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.AppliedGroovyScript"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Dependencies: []string{
|
|
||||||
"github.com/kubernetes-operator/pkg/apis/jenkins/v1alpha2.AppliedGroovyScript", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
|
|
@ -132,7 +132,7 @@ func (bar *BackupAndRestore) Restore(jenkinsClient jenkinsclient.Jenkins) error
|
||||||
bar.logger.V(log.VDebug).Info("Skipping restore backup")
|
bar.logger.V(log.VDebug).Info("Skipping restore backup")
|
||||||
if jenkins.Status.PendingBackup == 0 {
|
if jenkins.Status.PendingBackup == 0 {
|
||||||
jenkins.Status.PendingBackup = 1
|
jenkins.Status.PendingBackup = 1
|
||||||
return bar.Client.Update(context.TODO(), jenkins)
|
return bar.Client.Status().Update(context.TODO(), jenkins)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -152,7 +152,7 @@ func (bar *BackupAndRestore) Restore(jenkinsClient jenkinsclient.Jenkins) error
|
||||||
bar.logger.V(log.VDebug).Info("Skipping restore backup, get latest action returned -1")
|
bar.logger.V(log.VDebug).Info("Skipping restore backup, get latest action returned -1")
|
||||||
jenkins.Status.LastBackup = 0
|
jenkins.Status.LastBackup = 0
|
||||||
jenkins.Status.PendingBackup = 1
|
jenkins.Status.PendingBackup = 1
|
||||||
return bar.Client.Update(context.TODO(), jenkins)
|
return bar.Client.Status().Update(context.TODO(), jenkins)
|
||||||
}
|
}
|
||||||
|
|
||||||
backupNumber, err = strconv.ParseUint(backupNumberString, 10, 64)
|
backupNumber, err = strconv.ParseUint(backupNumberString, 10, 64)
|
||||||
|
|
@ -180,11 +180,25 @@ func (bar *BackupAndRestore) Restore(jenkinsClient jenkinsclient.Jenkins) error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
//TODO fix me because we're doing two saves unatomically
|
||||||
jenkins.Spec.Restore.RecoveryOnce = 0
|
jenkins.Spec.Restore.RecoveryOnce = 0
|
||||||
|
err = bar.Client.Update(context.TODO(), jenkins)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
key := types.NamespacedName{
|
||||||
|
Namespace: jenkins.Namespace,
|
||||||
|
Name: jenkins.Name,
|
||||||
|
}
|
||||||
|
err = bar.Client.Get(context.TODO(), key, jenkins)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
bar.Configuration.Jenkins = jenkins
|
||||||
|
|
||||||
jenkins.Status.RestoredBackup = backupNumber
|
jenkins.Status.RestoredBackup = backupNumber
|
||||||
jenkins.Status.PendingBackup = backupNumber + 1
|
jenkins.Status.PendingBackup = backupNumber + 1
|
||||||
return bar.Client.Update(context.TODO(), jenkins)
|
return bar.Client.Status().Update(context.TODO(), jenkins)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
@ -216,7 +230,7 @@ func (bar *BackupAndRestore) Backup(setBackupDoneBeforePodDeletion bool) error {
|
||||||
jenkins.Status.LastBackup = backupNumber
|
jenkins.Status.LastBackup = backupNumber
|
||||||
jenkins.Status.PendingBackup = backupNumber
|
jenkins.Status.PendingBackup = backupNumber
|
||||||
jenkins.Status.BackupDoneBeforePodDeletion = setBackupDoneBeforePodDeletion
|
jenkins.Status.BackupDoneBeforePodDeletion = setBackupDoneBeforePodDeletion
|
||||||
return bar.Client.Update(context.TODO(), jenkins)
|
return bar.Client.Status().Update(context.TODO(), jenkins)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
@ -234,7 +248,7 @@ func triggerBackup(ticker *time.Ticker, k8sClient k8s.Client, logger logr.Logger
|
||||||
}
|
}
|
||||||
if jenkins.Status.LastBackup == jenkins.Status.PendingBackup {
|
if jenkins.Status.LastBackup == jenkins.Status.PendingBackup {
|
||||||
jenkins.Status.PendingBackup++
|
jenkins.Status.PendingBackup++
|
||||||
err = k8sClient.Update(context.TODO(), jenkins)
|
err = k8sClient.Status().Update(context.TODO(), jenkins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.V(log.VWarn).Info(fmt.Sprintf("backup trigger, error when updating CR: %s", err))
|
logger.V(log.VWarn).Info(fmt.Sprintf("backup trigger, error when updating CR: %s", err))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) createScriptsConfigMap(meta metav1.ObjectMeta) error {
|
func (r *JenkinsBaseConfigurationReconciler) createScriptsConfigMap(meta metav1.ObjectMeta) error {
|
||||||
configMap, err := resources.NewScriptsConfigMap(meta, r.Configuration.Jenkins)
|
configMap, err := resources.NewScriptsConfigMap(meta, r.Configuration.Jenkins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -15,7 +15,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createScriptsConfigMap(meta metav1.O
|
||||||
return stackerr.WithStack(r.CreateOrUpdateResource(configMap))
|
return stackerr.WithStack(r.CreateOrUpdateResource(configMap))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) createInitConfigurationConfigMap(meta metav1.ObjectMeta) error {
|
func (r *JenkinsBaseConfigurationReconciler) createInitConfigurationConfigMap(meta metav1.ObjectMeta) error {
|
||||||
configMap, err := resources.NewInitConfigurationConfigMap(meta, r.Configuration.Jenkins)
|
configMap, err := resources.NewInitConfigurationConfigMap(meta, r.Configuration.Jenkins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -23,7 +23,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createInitConfigurationConfigMap(met
|
||||||
return stackerr.WithStack(r.CreateOrUpdateResource(configMap))
|
return stackerr.WithStack(r.CreateOrUpdateResource(configMap))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) createBaseConfigurationConfigMap(meta metav1.ObjectMeta) error {
|
func (r *JenkinsBaseConfigurationReconciler) createBaseConfigurationConfigMap(meta metav1.ObjectMeta) error {
|
||||||
configMap, err := resources.NewBaseConfigurationConfigMap(meta, r.Configuration.Jenkins, r.KubernetesClusterDomain)
|
configMap, err := resources.NewBaseConfigurationConfigMap(meta, r.Configuration.Jenkins, r.KubernetesClusterDomain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) compareContainers(expected corev1.Container, actual corev1.Container) (messages []string, verbose []string) {
|
func (r *JenkinsBaseConfigurationReconciler) compareContainers(expected corev1.Container, actual corev1.Container) (messages []string, verbose []string) {
|
||||||
if !reflect.DeepEqual(expected.Args, actual.Args) {
|
if !reflect.DeepEqual(expected.Args, actual.Args) {
|
||||||
messages = append(messages, "Arguments have changed")
|
messages = append(messages, "Arguments have changed")
|
||||||
verbose = append(verbose, fmt.Sprintf("Arguments have changed to '%+v' in container '%s'", expected.Args, expected.Name))
|
verbose = append(verbose, fmt.Sprintf("Arguments have changed to '%+v' in container '%s'", expected.Args, expected.Name))
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/reason"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/reason"
|
||||||
|
|
@ -16,7 +16,7 @@ import (
|
||||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsDeployment(meta metav1.ObjectMeta) (reconcile.Result, error) {
|
func (r *JenkinsBaseConfigurationReconciler) ensureJenkinsDeployment(meta metav1.ObjectMeta) (reconcile.Result, error) {
|
||||||
userAndPasswordHash, err := r.calculateUserAndPasswordHash()
|
userAndPasswordHash, err := r.calculateUserAndPasswordHash()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reconcile.Result{}, err
|
return reconcile.Result{}, err
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package base
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
|
|
||||||
stackerr "github.com/pkg/errors"
|
stackerr "github.com/pkg/errors"
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) addLabelForWatchesResources(customization v1alpha2.Customization) error {
|
func (r *JenkinsBaseConfigurationReconciler) addLabelForWatchesResources(customization v1alpha2.Customization) error {
|
||||||
labelsForWatchedResources := resources.BuildLabelsForWatchedResources(*r.Configuration.Jenkins)
|
labelsForWatchedResources := resources.BuildLabelsForWatchedResources(*r.Configuration.Jenkins)
|
||||||
|
|
||||||
if len(customization.Secret.Name) > 0 {
|
if len(customization.Secret.Name) > 0 {
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,16 @@ package base
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/plugins"
|
|
||||||
|
|
||||||
"github.com/bndr/gojenkins"
|
"github.com/bndr/gojenkins"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/plugins"
|
||||||
stackerr "github.com/pkg/errors"
|
stackerr "github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) verifyPlugins(jenkinsClient jenkinsclient.Jenkins) (bool, error) {
|
func (r *JenkinsBaseConfigurationReconciler) verifyPlugins(jenkinsClient jenkinsclient.Jenkins) (bool, error) {
|
||||||
allPluginsInJenkins, err := jenkinsClient.GetPlugins(fetchAllPlugins)
|
allPluginsInJenkins, err := jenkinsClient.GetPlugins(fetchAllPlugins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, stackerr.WithStack(err)
|
return false, stackerr.WithStack(err)
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/backuprestore"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/backuprestore"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/reason"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/reason"
|
||||||
"github.com/jenkinsci/kubernetes-operator/version"
|
"github.com/jenkinsci/kubernetes-operator/version"
|
||||||
|
|
@ -20,7 +19,7 @@ import (
|
||||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) checkForPodRecreation(currentJenkinsMasterPod corev1.Pod, userAndPasswordHash string) reason.Reason {
|
func (r *JenkinsBaseConfigurationReconciler) checkForPodRecreation(currentJenkinsMasterPod corev1.Pod, userAndPasswordHash string) reason.Reason {
|
||||||
var messages []string
|
var messages []string
|
||||||
var verbose []string
|
var verbose []string
|
||||||
|
|
||||||
|
|
@ -52,7 +51,14 @@ func (r *ReconcileJenkinsBaseConfiguration) checkForPodRecreation(currentJenkins
|
||||||
r.Configuration.Jenkins.Status.OperatorVersion, version.Version))
|
r.Configuration.Jenkins.Status.OperatorVersion, version.Version))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(r.Configuration.Jenkins.Spec.Master.SecurityContext, currentJenkinsMasterPod.Spec.SecurityContext) {
|
//FIXME too hacky
|
||||||
|
var jenkinsSecurityContext *corev1.PodSecurityContext
|
||||||
|
if r.Configuration.Jenkins.Spec.Master.SecurityContext == nil {
|
||||||
|
jenkinsSecurityContext = &corev1.PodSecurityContext{}
|
||||||
|
} else {
|
||||||
|
jenkinsSecurityContext = r.Configuration.Jenkins.Spec.Master.SecurityContext
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(jenkinsSecurityContext, currentJenkinsMasterPod.Spec.SecurityContext) {
|
||||||
messages = append(messages, "Jenkins pod security context has changed")
|
messages = append(messages, "Jenkins pod security context has changed")
|
||||||
verbose = append(verbose, fmt.Sprintf("Jenkins pod security context has changed, actual '%+v' required '%+v'",
|
verbose = append(verbose, fmt.Sprintf("Jenkins pod security context has changed, actual '%+v' required '%+v'",
|
||||||
currentJenkinsMasterPod.Spec.SecurityContext, r.Configuration.Jenkins.Spec.Master.SecurityContext))
|
currentJenkinsMasterPod.Spec.SecurityContext, r.Configuration.Jenkins.Spec.Master.SecurityContext))
|
||||||
|
|
@ -140,7 +146,7 @@ func (r *ReconcileJenkinsBaseConfiguration) checkForPodRecreation(currentJenkins
|
||||||
return reason.NewPodRestart(reason.OperatorSource, messages, verbose...)
|
return reason.NewPodRestart(reason.OperatorSource, messages, verbose...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsMasterPod(meta metav1.ObjectMeta) (reconcile.Result, error) {
|
func (r *JenkinsBaseConfigurationReconciler) ensureJenkinsMasterPod(meta metav1.ObjectMeta) (reconcile.Result, error) {
|
||||||
userAndPasswordHash, err := r.calculateUserAndPasswordHash()
|
userAndPasswordHash, err := r.calculateUserAndPasswordHash()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reconcile.Result{}, err
|
return reconcile.Result{}, err
|
||||||
|
|
@ -162,13 +168,6 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsMasterPod(meta metav1.O
|
||||||
return reconcile.Result{}, stackerr.WithStack(err)
|
return reconcile.Result{}, stackerr.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
currentJenkinsMasterPod, err := r.waitUntilCreateJenkinsMasterPod()
|
|
||||||
if err == nil {
|
|
||||||
r.handleAdmissionControllerChanges(currentJenkinsMasterPod)
|
|
||||||
} else {
|
|
||||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("waitUntilCreateJenkinsMasterPod has failed: %s", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
now := metav1.Now()
|
now := metav1.Now()
|
||||||
r.Configuration.Jenkins.Status = v1alpha2.JenkinsStatus{
|
r.Configuration.Jenkins.Status = v1alpha2.JenkinsStatus{
|
||||||
OperatorVersion: version.Version,
|
OperatorVersion: version.Version,
|
||||||
|
|
@ -177,7 +176,7 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsMasterPod(meta metav1.O
|
||||||
PendingBackup: r.Configuration.Jenkins.Status.LastBackup,
|
PendingBackup: r.Configuration.Jenkins.Status.LastBackup,
|
||||||
UserAndPasswordHash: userAndPasswordHash,
|
UserAndPasswordHash: userAndPasswordHash,
|
||||||
}
|
}
|
||||||
return reconcile.Result{Requeue: true}, r.Client.Update(context.TODO(), r.Configuration.Jenkins)
|
return reconcile.Result{Requeue: true}, r.Client.Status().Update(context.TODO(), r.Configuration.Jenkins)
|
||||||
} else if err != nil && !apierrors.IsNotFound(err) {
|
} else if err != nil && !apierrors.IsNotFound(err) {
|
||||||
return reconcile.Result{}, stackerr.WithStack(err)
|
return reconcile.Result{}, stackerr.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,12 @@ import (
|
||||||
|
|
||||||
stackerr "github.com/pkg/errors"
|
stackerr "github.com/pkg/errors"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) createRBAC(meta metav1.ObjectMeta) error {
|
func (r *JenkinsBaseConfigurationReconciler) createRBAC(meta metav1.ObjectMeta) error {
|
||||||
err := r.createServiceAccount(meta)
|
err := r.createServiceAccount(meta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -38,13 +39,16 @@ func (r *ReconcileJenkinsBaseConfiguration) createRBAC(meta metav1.ObjectMeta) e
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) ensureExtraRBAC(meta metav1.ObjectMeta) error {
|
func (r *JenkinsBaseConfigurationReconciler) ensureExtraRBAC(meta metav1.ObjectMeta) error {
|
||||||
var err error
|
var err error
|
||||||
var name string
|
var name string
|
||||||
for _, roleRef := range r.Configuration.Jenkins.Spec.Roles {
|
for _, roleRef := range r.Configuration.Jenkins.Spec.Roles {
|
||||||
name = getExtraRoleBindingName(meta.Name, roleRef)
|
name = getExtraRoleBindingName(meta.Name, roleRef)
|
||||||
roleBinding := resources.NewRoleBinding(name, meta.Namespace, meta.Name, roleRef)
|
roleBinding := resources.NewRoleBinding(name, meta.Namespace, meta.Name, roleRef)
|
||||||
err = r.CreateOrUpdateResource(roleBinding)
|
err := r.Client.Create(context.TODO(), roleBinding)
|
||||||
|
if err != nil && errors.IsAlreadyExists(err) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return stackerr.WithStack(err)
|
return stackerr.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,14 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/bndr/gojenkins"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/golang/mock/gomock"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/client"
|
"github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
||||||
|
|
||||||
|
"github.com/bndr/gojenkins"
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
|
@ -161,12 +162,12 @@ func TestCompareVolumes(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReconcileJenkinsBaseConfiguration_verifyPlugins(t *testing.T) {
|
func TestJenkinsBaseConfigurationReconciler_verifyPlugins(t *testing.T) {
|
||||||
log.SetupLogger(true)
|
log.SetupLogger(true)
|
||||||
|
|
||||||
t.Run("happy, empty base and user plugins", func(t *testing.T) {
|
t.Run("happy, empty base and user plugins", func(t *testing.T) {
|
||||||
jenkins := &v1alpha2.Jenkins{}
|
jenkins := &v1alpha2.Jenkins{}
|
||||||
r := ReconcileJenkinsBaseConfiguration{
|
r := JenkinsBaseConfigurationReconciler{
|
||||||
logger: log.Log,
|
logger: log.Log,
|
||||||
Configuration: configuration.Configuration{
|
Configuration: configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
|
|
@ -194,7 +195,7 @@ func TestReconcileJenkinsBaseConfiguration_verifyPlugins(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r := ReconcileJenkinsBaseConfiguration{
|
r := JenkinsBaseConfigurationReconciler{
|
||||||
logger: log.Log,
|
logger: log.Log,
|
||||||
Configuration: configuration.Configuration{
|
Configuration: configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
|
|
@ -238,7 +239,7 @@ func TestReconcileJenkinsBaseConfiguration_verifyPlugins(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r := ReconcileJenkinsBaseConfiguration{
|
r := JenkinsBaseConfigurationReconciler{
|
||||||
logger: log.Log,
|
logger: log.Log,
|
||||||
Configuration: configuration.Configuration{
|
Configuration: configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
|
|
@ -275,7 +276,7 @@ func TestReconcileJenkinsBaseConfiguration_verifyPlugins(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r := ReconcileJenkinsBaseConfiguration{
|
r := JenkinsBaseConfigurationReconciler{
|
||||||
logger: log.Log,
|
logger: log.Log,
|
||||||
Configuration: configuration.Configuration{
|
Configuration: configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
|
|
@ -312,7 +313,7 @@ func TestReconcileJenkinsBaseConfiguration_verifyPlugins(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r := ReconcileJenkinsBaseConfiguration{
|
r := JenkinsBaseConfigurationReconciler{
|
||||||
logger: log.Log,
|
logger: log.Log,
|
||||||
Configuration: configuration.Configuration{
|
Configuration: configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
|
|
@ -349,7 +350,7 @@ func TestReconcileJenkinsBaseConfiguration_verifyPlugins(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r := ReconcileJenkinsBaseConfiguration{
|
r := JenkinsBaseConfigurationReconciler{
|
||||||
logger: log.Log,
|
logger: log.Log,
|
||||||
Configuration: configuration.Configuration{
|
Configuration: configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
|
|
@ -386,7 +387,7 @@ func TestReconcileJenkinsBaseConfiguration_verifyPlugins(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r := ReconcileJenkinsBaseConfiguration{
|
r := JenkinsBaseConfigurationReconciler{
|
||||||
logger: log.Log,
|
logger: log.Log,
|
||||||
Configuration: configuration.Configuration{
|
Configuration: configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
|
|
@ -415,7 +416,7 @@ func TestReconcileJenkinsBaseConfiguration_verifyPlugins(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r := ReconcileJenkinsBaseConfiguration{
|
r := JenkinsBaseConfigurationReconciler{
|
||||||
logger: log.Log,
|
logger: log.Log,
|
||||||
Configuration: configuration.Configuration{
|
Configuration: configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
|
|
@ -618,7 +619,7 @@ func TestEnsureExtraRBAC(t *testing.T) {
|
||||||
|
|
||||||
t.Run("empty", func(t *testing.T) {
|
t.Run("empty", func(t *testing.T) {
|
||||||
// given
|
// given
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -654,7 +655,7 @@ func TestEnsureExtraRBAC(t *testing.T) {
|
||||||
clusterRoleKind := "ClusterRole"
|
clusterRoleKind := "ClusterRole"
|
||||||
t.Run("one extra", func(t *testing.T) {
|
t.Run("one extra", func(t *testing.T) {
|
||||||
// given
|
// given
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -695,7 +696,7 @@ func TestEnsureExtraRBAC(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("two extra", func(t *testing.T) {
|
t.Run("two extra", func(t *testing.T) {
|
||||||
// given
|
// given
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -743,7 +744,7 @@ func TestEnsureExtraRBAC(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("delete one extra", func(t *testing.T) {
|
t.Run("delete one extra", func(t *testing.T) {
|
||||||
// given
|
// given
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -801,8 +802,8 @@ func TestEnsureExtraRBAC(t *testing.T) {
|
||||||
roleBindings, err := fetchAllRoleBindings(fakeClient)
|
roleBindings, err := fetchAllRoleBindings(fakeClient)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 3, len(roleBindings.Items))
|
assert.Equal(t, 3, len(roleBindings.Items))
|
||||||
assert.Equal(t, metaObject.Name, roleBindings.Items[1].Name)
|
assert.Equal(t, metaObject.Name, roleBindings.Items[0].Name)
|
||||||
assert.Equal(t, jenkins.Spec.Roles[0], roleBindings.Items[2].RoleRef)
|
assert.Equal(t, jenkins.Spec.Roles[0], roleBindings.Items[1].RoleRef)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
|
|
@ -33,15 +33,15 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReconcileJenkinsBaseConfiguration defines values required for Jenkins base configuration.
|
// ReconcileJenkinsBaseConfiguration defines values required for Jenkins base configuration.
|
||||||
type ReconcileJenkinsBaseConfiguration struct {
|
type JenkinsBaseConfigurationReconciler struct {
|
||||||
configuration.Configuration
|
configuration.Configuration
|
||||||
logger logr.Logger
|
logger logr.Logger
|
||||||
jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings
|
jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
// New create structure which takes care of base configuration
|
// New create structure which takes care of base configuration
|
||||||
func New(config configuration.Configuration, jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings) *ReconcileJenkinsBaseConfiguration {
|
func New(config configuration.Configuration, jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings) *JenkinsBaseConfigurationReconciler {
|
||||||
return &ReconcileJenkinsBaseConfiguration{
|
return &JenkinsBaseConfigurationReconciler{
|
||||||
Configuration: config,
|
Configuration: config,
|
||||||
logger: log.Log.WithValues("cr", config.Jenkins.Name),
|
logger: log.Log.WithValues("cr", config.Jenkins.Name),
|
||||||
jenkinsAPIConnectionSettings: jenkinsAPIConnectionSettings,
|
jenkinsAPIConnectionSettings: jenkinsAPIConnectionSettings,
|
||||||
|
|
@ -49,7 +49,7 @@ func New(config configuration.Configuration, jenkinsAPIConnectionSettings jenkin
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reconcile takes care of base configuration.
|
// Reconcile takes care of base configuration.
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (reconcile.Result, jenkinsclient.Jenkins, error) {
|
func (r *JenkinsBaseConfigurationReconciler) Reconcile() (reconcile.Result, jenkinsclient.Jenkins, error) {
|
||||||
metaObject := resources.NewResourceObjectMeta(r.Configuration.Jenkins)
|
metaObject := resources.NewResourceObjectMeta(r.Configuration.Jenkins)
|
||||||
|
|
||||||
// Create Necessary Resources
|
// Create Necessary Resources
|
||||||
|
|
@ -134,7 +134,7 @@ func useDeploymentForJenkinsMaster(jenkins *v1alpha2.Jenkins) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) ensureResourcesRequiredForJenkinsPod(metaObject metav1.ObjectMeta) error {
|
func (r *JenkinsBaseConfigurationReconciler) ensureResourcesRequiredForJenkinsPod(metaObject metav1.ObjectMeta) error {
|
||||||
if err := r.createOperatorCredentialsSecret(metaObject); err != nil {
|
if err := r.createOperatorCredentialsSecret(metaObject); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -197,7 +197,7 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureResourcesRequiredForJenkinsPod
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) createOperatorCredentialsSecret(meta metav1.ObjectMeta) error {
|
func (r *JenkinsBaseConfigurationReconciler) createOperatorCredentialsSecret(meta metav1.ObjectMeta) error {
|
||||||
found := &corev1.Secret{}
|
found := &corev1.Secret{}
|
||||||
err := r.Configuration.Client.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.Configuration.Jenkins), Namespace: r.Configuration.Jenkins.ObjectMeta.Namespace}, found)
|
err := r.Configuration.Client.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.Configuration.Jenkins), Namespace: r.Configuration.Jenkins.ObjectMeta.Namespace}, found)
|
||||||
|
|
||||||
|
|
@ -214,7 +214,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createOperatorCredentialsSecret(meta
|
||||||
return stackerr.WithStack(r.UpdateResource(resources.NewOperatorCredentialsSecret(meta, r.Configuration.Jenkins)))
|
return stackerr.WithStack(r.UpdateResource(resources.NewOperatorCredentialsSecret(meta, r.Configuration.Jenkins)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) calculateUserAndPasswordHash() (string, error) {
|
func (r *JenkinsBaseConfigurationReconciler) calculateUserAndPasswordHash() (string, error) {
|
||||||
credentialsSecret := &corev1.Secret{}
|
credentialsSecret := &corev1.Secret{}
|
||||||
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.Configuration.Jenkins), Namespace: r.Configuration.Jenkins.ObjectMeta.Namespace}, credentialsSecret)
|
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.Configuration.Jenkins), Namespace: r.Configuration.Jenkins.ObjectMeta.Namespace}, credentialsSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -222,8 +222,14 @@ func (r *ReconcileJenkinsBaseConfiguration) calculateUserAndPasswordHash() (stri
|
||||||
}
|
}
|
||||||
|
|
||||||
hash := sha256.New()
|
hash := sha256.New()
|
||||||
hash.Write(credentialsSecret.Data[resources.OperatorCredentialsSecretUserNameKey])
|
_, err = hash.Write(credentialsSecret.Data[resources.OperatorCredentialsSecretUserNameKey])
|
||||||
hash.Write(credentialsSecret.Data[resources.OperatorCredentialsSecretPasswordKey])
|
if err != nil {
|
||||||
|
return "", stackerr.WithStack(err)
|
||||||
|
}
|
||||||
|
_, err = hash.Write(credentialsSecret.Data[resources.OperatorCredentialsSecretPasswordKey])
|
||||||
|
if err != nil {
|
||||||
|
return "", stackerr.WithStack(err)
|
||||||
|
}
|
||||||
return base64.StdEncoding.EncodeToString(hash.Sum(nil)), nil
|
return base64.StdEncoding.EncodeToString(hash.Sum(nil)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -282,7 +288,7 @@ func CompareContainerVolumeMounts(expected corev1.Container, actual corev1.Conta
|
||||||
}
|
}
|
||||||
|
|
||||||
// compareVolumes returns true if Jenkins pod and Jenkins CR volumes are the same
|
// compareVolumes returns true if Jenkins pod and Jenkins CR volumes are the same
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) compareVolumes(actualPod corev1.Pod) bool {
|
func (r *JenkinsBaseConfigurationReconciler) compareVolumes(actualPod corev1.Pod) bool {
|
||||||
var withoutServiceAccount []corev1.Volume
|
var withoutServiceAccount []corev1.Volume
|
||||||
for _, volume := range actualPod.Spec.Volumes {
|
for _, volume := range actualPod.Spec.Volumes {
|
||||||
if !strings.HasPrefix(volume.Name, actualPod.Spec.ServiceAccountName) {
|
if !strings.HasPrefix(volume.Name, actualPod.Spec.ServiceAccountName) {
|
||||||
|
|
@ -296,7 +302,7 @@ func (r *ReconcileJenkinsBaseConfiguration) compareVolumes(actualPod corev1.Pod)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) detectJenkinsMasterPodStartingIssues() (stopReconcileLoop bool, err error) {
|
func (r *JenkinsBaseConfigurationReconciler) detectJenkinsMasterPodStartingIssues() (stopReconcileLoop bool, err error) {
|
||||||
jenkinsMasterPod, err := r.Configuration.GetJenkinsMasterPod()
|
jenkinsMasterPod, err := r.Configuration.GetJenkinsMasterPod()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
@ -330,7 +336,7 @@ func (r *ReconcileJenkinsBaseConfiguration) detectJenkinsMasterPodStartingIssues
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) filterEvents(source corev1.EventList, jenkinsMasterPod corev1.Pod) []string {
|
func (r *JenkinsBaseConfigurationReconciler) filterEvents(source corev1.EventList, jenkinsMasterPod corev1.Pod) []string {
|
||||||
events := []string{}
|
events := []string{}
|
||||||
for _, eventItem := range source.Items {
|
for _, eventItem := range source.Items {
|
||||||
if r.Configuration.Jenkins.Status.ProvisionStartTime.UTC().After(eventItem.LastTimestamp.UTC()) {
|
if r.Configuration.Jenkins.Status.ProvisionStartTime.UTC().After(eventItem.LastTimestamp.UTC()) {
|
||||||
|
|
@ -347,7 +353,7 @@ func (r *ReconcileJenkinsBaseConfiguration) filterEvents(source corev1.EventList
|
||||||
return events
|
return events
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) waitForJenkins() (reconcile.Result, error) {
|
func (r *JenkinsBaseConfigurationReconciler) waitForJenkins() (reconcile.Result, error) {
|
||||||
jenkinsMasterPod, err := r.Configuration.GetJenkinsMasterPod()
|
jenkinsMasterPod, err := r.Configuration.GetJenkinsMasterPod()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reconcile.Result{}, err
|
return reconcile.Result{}, err
|
||||||
|
|
@ -388,7 +394,7 @@ func (r *ReconcileJenkinsBaseConfiguration) waitForJenkins() (reconcile.Result,
|
||||||
return reconcile.Result{}, nil
|
return reconcile.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) ensureBaseConfiguration(jenkinsClient jenkinsclient.Jenkins) (reconcile.Result, error) {
|
func (r *JenkinsBaseConfigurationReconciler) ensureBaseConfiguration(jenkinsClient jenkinsclient.Jenkins) (reconcile.Result, error) {
|
||||||
customization := v1alpha2.GroovyScripts{
|
customization := v1alpha2.GroovyScripts{
|
||||||
Customization: v1alpha2.Customization{
|
Customization: v1alpha2.Customization{
|
||||||
Secret: v1alpha2.SecretRef{Name: ""},
|
Secret: v1alpha2.SecretRef{Name: ""},
|
||||||
|
|
@ -403,30 +409,3 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureBaseConfiguration(jenkinsClien
|
||||||
})
|
})
|
||||||
return reconcile.Result{Requeue: requeue}, err
|
return reconcile.Result{Requeue: requeue}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) waitUntilCreateJenkinsMasterPod() (currentJenkinsMasterPod *corev1.Pod, err error) {
|
|
||||||
currentJenkinsMasterPod, err = r.Configuration.GetJenkinsMasterPod()
|
|
||||||
for {
|
|
||||||
if err != nil && !apierrors.IsNotFound(err) {
|
|
||||||
return nil, stackerr.WithStack(err)
|
|
||||||
} else if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
currentJenkinsMasterPod, err = r.Configuration.GetJenkinsMasterPod()
|
|
||||||
time.Sleep(time.Millisecond * 10)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) handleAdmissionControllerChanges(currentJenkinsMasterPod *corev1.Pod) {
|
|
||||||
if !reflect.DeepEqual(r.Configuration.Jenkins.Spec.Master.SecurityContext, currentJenkinsMasterPod.Spec.SecurityContext) {
|
|
||||||
r.Configuration.Jenkins.Spec.Master.SecurityContext = currentJenkinsMasterPod.Spec.SecurityContext
|
|
||||||
r.logger.Info(fmt.Sprintf("The Admission controller has changed the Jenkins master pod spec.securityContext, changing the Jenkinc CR spec.master.securityContext to '%+v'", currentJenkinsMasterPod.Spec.SecurityContext))
|
|
||||||
}
|
|
||||||
for i, container := range r.Configuration.Jenkins.Spec.Master.Containers {
|
|
||||||
if !reflect.DeepEqual(container.SecurityContext, currentJenkinsMasterPod.Spec.Containers[i].SecurityContext) {
|
|
||||||
r.Configuration.Jenkins.Spec.Master.Containers[i].SecurityContext = currentJenkinsMasterPod.Spec.Containers[i].SecurityContext
|
|
||||||
r.logger.Info(fmt.Sprintf("The Admission controller has changed the securityContext, changing the Jenkins CR spec.master.containers[%s].securityContext to '+%v'", container.Name, currentJenkinsMasterPod.Spec.Containers[i].SecurityContext))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,7 +3,7 @@ package resources
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
package resources
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
jenkinsv1alpha2 "github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
NameWithSuffixFormat = "%s-%s"
|
|
||||||
PluginDefinitionFormat = "%s:%s"
|
|
||||||
BuilderDockerfileArg = "--dockerfile=/workspace/dockerfile/Dockerfile"
|
|
||||||
BuilderContextDirArg = "--context=dir://workspace/"
|
|
||||||
BuilderPushArg = "--no-push"
|
|
||||||
BuilderDigestFileArg = "--digest-file=/dev/termination-log"
|
|
||||||
BuilderSuffix = "builder"
|
|
||||||
DockerfileStorageSuffix = "dockerfile-storage"
|
|
||||||
DockerfileNameSuffix = "dockerfile"
|
|
||||||
JenkinsImageBuilderImage = "gcr.io/kaniko-project/executor:latest"
|
|
||||||
JenkinsImageBuilderName = "jenkins-image-builder"
|
|
||||||
JenkinsImageDefaultBaseImage = "jenkins/jenkins:lts"
|
|
||||||
DockerfileName = "Dockerfile"
|
|
||||||
DockerfileTemplate = `FROM %s
|
|
||||||
RUN curl -o /tmp/install-plugins.sh https://raw.githubusercontent.com/jenkinsci/docker/master/install-plugins.sh
|
|
||||||
RUN chmod +x /tmp/install-plugins.sh
|
|
||||||
RUN install-plugins.sh %s `
|
|
||||||
)
|
|
||||||
|
|
||||||
var log = logf.Log.WithName("controller_jenkinsimage")
|
|
||||||
|
|
||||||
// NewBuilderPod returns a busybox pod with the same name/namespace as the cr.
|
|
||||||
func NewBuilderPod(cr *jenkinsv1alpha2.JenkinsImage) *corev1.Pod {
|
|
||||||
name := fmt.Sprintf(NameWithSuffixFormat, cr.Name, BuilderSuffix)
|
|
||||||
args := []string{BuilderDockerfileArg, BuilderContextDirArg, BuilderPushArg, BuilderDigestFileArg}
|
|
||||||
volumes := getVolumes(cr)
|
|
||||||
volumeMounts := getVolumesMounts(cr)
|
|
||||||
p := &corev1.Pod{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: name,
|
|
||||||
Namespace: cr.Namespace,
|
|
||||||
},
|
|
||||||
Spec: corev1.PodSpec{
|
|
||||||
RestartPolicy: corev1.RestartPolicyNever,
|
|
||||||
Containers: []corev1.Container{
|
|
||||||
{
|
|
||||||
Name: JenkinsImageBuilderName,
|
|
||||||
Image: JenkinsImageBuilderImage,
|
|
||||||
Args: args,
|
|
||||||
VolumeMounts: volumeMounts,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Volumes: volumes,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDockerfileConfigMap returns a busybox pod with the same name/namespace as the cr.
|
|
||||||
func NewDockerfileConfigMap(cr *jenkinsv1alpha2.JenkinsImage) *corev1.ConfigMap {
|
|
||||||
dockerfileContent := fmt.Sprintf(DockerfileTemplate, getDefaultedBaseImage(cr), getPluginsList(cr))
|
|
||||||
name := fmt.Sprintf(NameWithSuffixFormat, cr.Name, DockerfileNameSuffix)
|
|
||||||
data := map[string]string{DockerfileName: dockerfileContent}
|
|
||||||
dockerfile := &corev1.ConfigMap{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: name,
|
|
||||||
Namespace: cr.Namespace,
|
|
||||||
},
|
|
||||||
Data: data,
|
|
||||||
}
|
|
||||||
return dockerfile
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPluginsList(cr *jenkinsv1alpha2.JenkinsImage) string {
|
|
||||||
logger := log.WithName("jenkinsimage_getPluginsList")
|
|
||||||
plugins := ""
|
|
||||||
for _, v := range cr.Spec.Plugins {
|
|
||||||
plugins += fmt.Sprintf(PluginDefinitionFormat, v.Name, v.Version) + " "
|
|
||||||
logger.Info(fmt.Sprintf("Adding plugin %s:%s ", v.Name, v.Version))
|
|
||||||
}
|
|
||||||
return plugins
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDefaultedBaseImage(cr *jenkinsv1alpha2.JenkinsImage) string {
|
|
||||||
if len(cr.Spec.BaseImage.Name) != 0 {
|
|
||||||
return cr.Spec.BaseImage.Name
|
|
||||||
}
|
|
||||||
return JenkinsImageDefaultBaseImage
|
|
||||||
}
|
|
||||||
|
|
||||||
func getVolumes(cr *jenkinsv1alpha2.JenkinsImage) []corev1.Volume {
|
|
||||||
name := fmt.Sprintf(NameWithSuffixFormat, cr.Name, DockerfileStorageSuffix)
|
|
||||||
storage := corev1.Volume{
|
|
||||||
Name: name,
|
|
||||||
VolumeSource: corev1.VolumeSource{
|
|
||||||
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
name = fmt.Sprintf(NameWithSuffixFormat, cr.Name, DockerfileNameSuffix)
|
|
||||||
config := corev1.Volume{
|
|
||||||
Name: name,
|
|
||||||
VolumeSource: corev1.VolumeSource{
|
|
||||||
ConfigMap: &corev1.ConfigMapVolumeSource{
|
|
||||||
LocalObjectReference: corev1.LocalObjectReference{Name: name},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
volumes := []corev1.Volume{storage, config}
|
|
||||||
return volumes
|
|
||||||
}
|
|
||||||
|
|
||||||
func getVolumesMounts(cr *jenkinsv1alpha2.JenkinsImage) []corev1.VolumeMount {
|
|
||||||
name := fmt.Sprintf(NameWithSuffixFormat, cr.Name, DockerfileStorageSuffix)
|
|
||||||
storage := corev1.VolumeMount{
|
|
||||||
Name: name,
|
|
||||||
MountPath: "/workspace",
|
|
||||||
}
|
|
||||||
name = fmt.Sprintf(NameWithSuffixFormat, cr.Name, DockerfileNameSuffix)
|
|
||||||
config := corev1.VolumeMount{
|
|
||||||
Name: name,
|
|
||||||
MountPath: "/workspace/dockerfile",
|
|
||||||
}
|
|
||||||
volumeMounts := []corev1.VolumeMount{storage, config}
|
|
||||||
return volumeMounts
|
|
||||||
}
|
|
||||||
|
|
@ -3,7 +3,7 @@ package resources
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
|
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/internal/render"
|
"github.com/jenkinsci/kubernetes-operator/internal/render"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package resources
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package resources
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ package resources
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewSimpleProbe(uri string, port string, scheme corev1.URIScheme, initialDelaySeconds int32) *corev1.Probe {
|
func NewProbe(uri string, port string, scheme corev1.URIScheme, initialDelaySeconds, timeoutSeconds, failureThreshold int32) *corev1.Probe {
|
||||||
return &corev1.Probe{
|
return &corev1.Probe{
|
||||||
Handler: corev1.Handler{
|
Handler: corev1.Handler{
|
||||||
HTTPGet: &corev1.HTTPGetAction{
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
|
|
@ -15,12 +15,9 @@ func NewSimpleProbe(uri string, port string, scheme corev1.URIScheme, initialDel
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
InitialDelaySeconds: initialDelaySeconds,
|
InitialDelaySeconds: initialDelaySeconds,
|
||||||
|
TimeoutSeconds: timeoutSeconds,
|
||||||
|
FailureThreshold: failureThreshold,
|
||||||
|
SuccessThreshold: int32(1),
|
||||||
|
PeriodSeconds: int32(1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProbe(uri string, port string, scheme corev1.URIScheme, initialDelaySeconds, timeoutSeconds, failureThreshold int32) *corev1.Probe {
|
|
||||||
p := NewSimpleProbe(uri, port, scheme, initialDelaySeconds)
|
|
||||||
p.TimeoutSeconds = timeoutSeconds
|
|
||||||
p.FailureThreshold = failureThreshold
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ package resources
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
routev1 "github.com/openshift/api/route/v1"
|
routev1 "github.com/openshift/api/route/v1"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
"k8s.io/client-go/discovery"
|
"k8s.io/client-go/discovery"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
)
|
)
|
||||||
|
|
||||||
//RouteKind the kind name for route
|
|
||||||
const RouteKind = "Route"
|
|
||||||
|
|
||||||
var isRouteAPIAvailable = false
|
var isRouteAPIAvailable = false
|
||||||
var routeAPIChecked = false
|
var routeAPIChecked = false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/internal/render"
|
"github.com/jenkinsci/kubernetes-operator/internal/render"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,16 @@ package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||||
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
|
|
||||||
stackerr "github.com/pkg/errors"
|
|
||||||
|
|
||||||
|
stackerr "github.com/pkg/errors"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//ServiceKind the kind name for Service
|
//ServiceKind the kind name for Service
|
||||||
|
|
@ -71,7 +70,7 @@ func GetJenkinsSlavesServiceFQDN(jenkins *v1alpha2.Jenkins, kubernetesClusterDom
|
||||||
|
|
||||||
// GetClusterDomain returns Kubernetes cluster domain, default to "cluster.local"
|
// GetClusterDomain returns Kubernetes cluster domain, default to "cluster.local"
|
||||||
func getClusterDomain(kubernetesClusterDomain string) (string, error) {
|
func getClusterDomain(kubernetesClusterDomain string) (string, error) {
|
||||||
isRunningInCluster, err := isRunningInCluster()
|
isRunningInCluster, err := IsRunningInCluster()
|
||||||
if !isRunningInCluster {
|
if !isRunningInCluster {
|
||||||
return kubernetesClusterDomain, nil
|
return kubernetesClusterDomain, nil
|
||||||
}
|
}
|
||||||
|
|
@ -93,13 +92,13 @@ func getClusterDomain(kubernetesClusterDomain string) (string, error) {
|
||||||
return kubernetesClusterDomain, nil
|
return kubernetesClusterDomain, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isRunningInCluster() (bool, error) {
|
func IsRunningInCluster() (bool, error) {
|
||||||
_, err := k8sutil.GetOperatorNamespace()
|
const inClusterNamespacePath = "/var/run/secrets/kubernetes.io/serviceaccount/namespace"
|
||||||
if err != nil {
|
_, err := os.Stat(inClusterNamespacePath)
|
||||||
if err == k8sutil.ErrNoNamespace || err == k8sutil.ErrRunLocal {
|
if os.IsNotExist(err) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
} else if err == nil {
|
||||||
return false, stackerr.WithStack(err)
|
return true, nil
|
||||||
}
|
}
|
||||||
return true, nil
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,19 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
|
|
||||||
routev1 "github.com/openshift/api/route/v1"
|
routev1 "github.com/openshift/api/route/v1"
|
||||||
stackerr "github.com/pkg/errors"
|
stackerr "github.com/pkg/errors"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// createRoute takes the ServiceName and Creates the Route based on it
|
// createRoute takes the ServiceName and Creates the Route based on it
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) createRoute(meta metav1.ObjectMeta, serviceName string, config *v1alpha2.Jenkins) error {
|
func (r *JenkinsBaseConfigurationReconciler) createRoute(meta metav1.ObjectMeta, serviceName string, config *v1alpha2.Jenkins) error {
|
||||||
route := routev1.Route{}
|
route := routev1.Route{}
|
||||||
name := fmt.Sprintf("jenkins-%s", config.ObjectMeta.Name)
|
name := fmt.Sprintf("jenkins-%s", config.ObjectMeta.Name)
|
||||||
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: meta.Namespace}, &route)
|
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: meta.Namespace}, &route)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package base
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
|
|
||||||
stackerr "github.com/pkg/errors"
|
stackerr "github.com/pkg/errors"
|
||||||
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) createService(meta metav1.ObjectMeta, name string, config v1alpha2.Service, targetPort int32) error {
|
func (r *JenkinsBaseConfigurationReconciler) createService(meta metav1.ObjectMeta, name string, config v1alpha2.Service, targetPort int32) error {
|
||||||
service := corev1.Service{}
|
service := corev1.Service{}
|
||||||
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: meta.Namespace}, &service)
|
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: meta.Namespace}, &service)
|
||||||
if err != nil && apierrors.IsNotFound(err) {
|
if err != nil && apierrors.IsNotFound(err) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) createServiceAccount(meta metav1.ObjectMeta) error {
|
func (r *JenkinsBaseConfigurationReconciler) createServiceAccount(meta metav1.ObjectMeta) error {
|
||||||
serviceAccount := &corev1.ServiceAccount{}
|
serviceAccount := &corev1.ServiceAccount{}
|
||||||
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: meta.Name, Namespace: meta.Namespace}, serviceAccount)
|
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: meta.Name, Namespace: meta.Namespace}, serviceAccount)
|
||||||
annotations := r.Configuration.Jenkins.Spec.ServiceAccount.Annotations
|
annotations := r.Configuration.Jenkins.Spec.ServiceAccount.Annotations
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
"github.com/jenkinsci/kubernetes-operator/pkg/constants"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/plugins"
|
"github.com/jenkinsci/kubernetes-operator/pkg/plugins"
|
||||||
|
|
@ -23,7 +23,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Validate validates Jenkins CR Spec.master section
|
// Validate validates Jenkins CR Spec.master section
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) Validate(jenkins *v1alpha2.Jenkins) ([]string, error) {
|
func (r *JenkinsBaseConfigurationReconciler) Validate(jenkins *v1alpha2.Jenkins) ([]string, error) {
|
||||||
var messages []string
|
var messages []string
|
||||||
|
|
||||||
if msg := r.validateReservedVolumes(); len(msg) > 0 {
|
if msg := r.validateReservedVolumes(); len(msg) > 0 {
|
||||||
|
|
@ -70,7 +70,7 @@ func (r *ReconcileJenkinsBaseConfiguration) Validate(jenkins *v1alpha2.Jenkins)
|
||||||
return messages, nil
|
return messages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validateJenkinsMasterContainerCommand() []string {
|
func (r *JenkinsBaseConfigurationReconciler) validateJenkinsMasterContainerCommand() []string {
|
||||||
masterContainer := r.Configuration.GetJenkinsMasterContainer()
|
masterContainer := r.Configuration.GetJenkinsMasterContainer()
|
||||||
if masterContainer == nil {
|
if masterContainer == nil {
|
||||||
return []string{}
|
return []string{}
|
||||||
|
|
@ -102,7 +102,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateJenkinsMasterContainerComman
|
||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validateImagePullSecrets() ([]string, error) {
|
func (r *JenkinsBaseConfigurationReconciler) validateImagePullSecrets() ([]string, error) {
|
||||||
var messages []string
|
var messages []string
|
||||||
for _, sr := range r.Configuration.Jenkins.Spec.Master.ImagePullSecrets {
|
for _, sr := range r.Configuration.Jenkins.Spec.Master.ImagePullSecrets {
|
||||||
msg, err := r.validateImagePullSecret(sr.Name)
|
msg, err := r.validateImagePullSecret(sr.Name)
|
||||||
|
|
@ -116,7 +116,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateImagePullSecrets() ([]string
|
||||||
return messages, nil
|
return messages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validateImagePullSecret(secretName string) ([]string, error) {
|
func (r *JenkinsBaseConfigurationReconciler) validateImagePullSecret(secretName string) ([]string, error) {
|
||||||
var messages []string
|
var messages []string
|
||||||
secret := &corev1.Secret{}
|
secret := &corev1.Secret{}
|
||||||
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: secretName, Namespace: r.Configuration.Jenkins.ObjectMeta.Namespace}, secret)
|
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: secretName, Namespace: r.Configuration.Jenkins.ObjectMeta.Namespace}, secret)
|
||||||
|
|
@ -142,7 +142,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateImagePullSecret(secretName s
|
||||||
return messages, nil
|
return messages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validateVolumes() ([]string, error) {
|
func (r *JenkinsBaseConfigurationReconciler) validateVolumes() ([]string, error) {
|
||||||
var messages []string
|
var messages []string
|
||||||
for _, volume := range r.Configuration.Jenkins.Spec.Master.Volumes {
|
for _, volume := range r.Configuration.Jenkins.Spec.Master.Volumes {
|
||||||
switch {
|
switch {
|
||||||
|
|
@ -170,7 +170,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateVolumes() ([]string, error)
|
||||||
return messages, nil
|
return messages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validatePersistentVolumeClaim(volume corev1.Volume) ([]string, error) {
|
func (r *JenkinsBaseConfigurationReconciler) validatePersistentVolumeClaim(volume corev1.Volume) ([]string, error) {
|
||||||
var messages []string
|
var messages []string
|
||||||
|
|
||||||
pvc := &corev1.PersistentVolumeClaim{}
|
pvc := &corev1.PersistentVolumeClaim{}
|
||||||
|
|
@ -184,7 +184,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validatePersistentVolumeClaim(volume
|
||||||
return messages, nil
|
return messages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validateConfigMapVolume(volume corev1.Volume) ([]string, error) {
|
func (r *JenkinsBaseConfigurationReconciler) validateConfigMapVolume(volume corev1.Volume) ([]string, error) {
|
||||||
var messages []string
|
var messages []string
|
||||||
if volume.ConfigMap.Optional != nil && *volume.ConfigMap.Optional {
|
if volume.ConfigMap.Optional != nil && *volume.ConfigMap.Optional {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
@ -201,7 +201,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateConfigMapVolume(volume corev
|
||||||
return messages, nil
|
return messages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validateSecretVolume(volume corev1.Volume) ([]string, error) {
|
func (r *JenkinsBaseConfigurationReconciler) validateSecretVolume(volume corev1.Volume) ([]string, error) {
|
||||||
var messages []string
|
var messages []string
|
||||||
if volume.Secret.Optional != nil && *volume.Secret.Optional {
|
if volume.Secret.Optional != nil && *volume.Secret.Optional {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
@ -218,7 +218,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateSecretVolume(volume corev1.V
|
||||||
return messages, nil
|
return messages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validateReservedVolumes() []string {
|
func (r *JenkinsBaseConfigurationReconciler) validateReservedVolumes() []string {
|
||||||
var messages []string
|
var messages []string
|
||||||
|
|
||||||
for _, baseVolume := range resources.GetJenkinsMasterPodBaseVolumes(r.Configuration.Jenkins) {
|
for _, baseVolume := range resources.GetJenkinsMasterPodBaseVolumes(r.Configuration.Jenkins) {
|
||||||
|
|
@ -232,7 +232,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateReservedVolumes() []string {
|
||||||
return messages
|
return messages
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validateContainer(container v1alpha2.Container) []string {
|
func (r *JenkinsBaseConfigurationReconciler) validateContainer(container v1alpha2.Container) []string {
|
||||||
var messages []string
|
var messages []string
|
||||||
if container.Image == "" {
|
if container.Image == "" {
|
||||||
messages = append(messages, "Image not set")
|
messages = append(messages, "Image not set")
|
||||||
|
|
@ -253,7 +253,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateContainer(container v1alpha2
|
||||||
return messages
|
return messages
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validateContainerVolumeMounts(container v1alpha2.Container) []string {
|
func (r *JenkinsBaseConfigurationReconciler) validateContainerVolumeMounts(container v1alpha2.Container) []string {
|
||||||
var messages []string
|
var messages []string
|
||||||
allVolumes := append(resources.GetJenkinsMasterPodBaseVolumes(r.Configuration.Jenkins), r.Configuration.Jenkins.Spec.Master.Volumes...)
|
allVolumes := append(resources.GetJenkinsMasterPodBaseVolumes(r.Configuration.Jenkins), r.Configuration.Jenkins.Spec.Master.Volumes...)
|
||||||
|
|
||||||
|
|
@ -277,7 +277,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateContainerVolumeMounts(contai
|
||||||
return messages
|
return messages
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validateJenkinsMasterPodEnvs() []string {
|
func (r *JenkinsBaseConfigurationReconciler) validateJenkinsMasterPodEnvs() []string {
|
||||||
var messages []string
|
var messages []string
|
||||||
baseEnvs := resources.GetJenkinsMasterContainerBaseEnvs(r.Configuration.Jenkins)
|
baseEnvs := resources.GetJenkinsMasterContainerBaseEnvs(r.Configuration.Jenkins)
|
||||||
baseEnvNames := map[string]string{}
|
baseEnvNames := map[string]string{}
|
||||||
|
|
@ -316,7 +316,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateJenkinsMasterPodEnvs() []str
|
||||||
return messages
|
return messages
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validatePlugins(requiredBasePlugins []plugins.Plugin, basePlugins, userPlugins []v1alpha2.Plugin) []string {
|
func (r *JenkinsBaseConfigurationReconciler) validatePlugins(requiredBasePlugins []plugins.Plugin, basePlugins, userPlugins []v1alpha2.Plugin) []string {
|
||||||
var messages []string
|
var messages []string
|
||||||
allPlugins := map[plugins.Plugin][]plugins.Plugin{}
|
allPlugins := map[plugins.Plugin][]plugins.Plugin{}
|
||||||
|
|
||||||
|
|
@ -353,7 +353,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validatePlugins(requiredBasePlugins
|
||||||
return messages
|
return messages
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) verifyBasePlugins(requiredBasePlugins []plugins.Plugin, basePlugins []v1alpha2.Plugin) []string {
|
func (r *JenkinsBaseConfigurationReconciler) verifyBasePlugins(requiredBasePlugins []plugins.Plugin, basePlugins []v1alpha2.Plugin) []string {
|
||||||
var messages []string
|
var messages []string
|
||||||
|
|
||||||
for _, requiredBasePlugin := range requiredBasePlugins {
|
for _, requiredBasePlugin := range requiredBasePlugins {
|
||||||
|
|
@ -372,7 +372,7 @@ func (r *ReconcileJenkinsBaseConfiguration) verifyBasePlugins(requiredBasePlugin
|
||||||
return messages
|
return messages
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) validateCustomization(customization v1alpha2.Customization, name string) ([]string, error) {
|
func (r *JenkinsBaseConfigurationReconciler) validateCustomization(customization v1alpha2.Customization, name string) ([]string, error) {
|
||||||
var messages []string
|
var messages []string
|
||||||
if len(customization.Secret.Name) == 0 && len(customization.Configurations) == 0 {
|
if len(customization.Secret.Name) == 0 && len(customization.Configurations) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/client"
|
"github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
|
|
@ -161,7 +161,7 @@ func TestReconcileJenkinsBaseConfiguration_validateImagePullSecrets(t *testing.T
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -187,7 +187,7 @@ func TestReconcileJenkinsBaseConfiguration_validateImagePullSecrets(t *testing.T
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
baseReconcileLoop := New(configuration.Configuration{
|
baseReconcileLoop := New(configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -221,7 +221,7 @@ func TestReconcileJenkinsBaseConfiguration_validateImagePullSecrets(t *testing.T
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -257,7 +257,7 @@ func TestReconcileJenkinsBaseConfiguration_validateImagePullSecrets(t *testing.T
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -293,7 +293,7 @@ func TestReconcileJenkinsBaseConfiguration_validateImagePullSecrets(t *testing.T
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -329,7 +329,7 @@ func TestReconcileJenkinsBaseConfiguration_validateImagePullSecrets(t *testing.T
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -569,7 +569,7 @@ func TestValidateConfigMapVolume(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
baseReconcileLoop := New(configuration.Configuration{
|
baseReconcileLoop := New(configuration.Configuration{
|
||||||
Jenkins: &v1alpha2.Jenkins{ObjectMeta: metav1.ObjectMeta{Name: "example"}},
|
Jenkins: &v1alpha2.Jenkins{ObjectMeta: metav1.ObjectMeta{Name: "example"}},
|
||||||
|
|
@ -596,7 +596,7 @@ func TestValidateConfigMapVolume(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), &configMap)
|
err := fakeClient.Create(context.TODO(), &configMap)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
baseReconcileLoop := New(configuration.Configuration{
|
baseReconcileLoop := New(configuration.Configuration{
|
||||||
|
|
@ -624,7 +624,7 @@ func TestValidateConfigMapVolume(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
baseReconcileLoop := New(configuration.Configuration{
|
baseReconcileLoop := New(configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
|
|
@ -634,7 +634,7 @@ func TestValidateConfigMapVolume(t *testing.T) {
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, got, []string{"ConfigMap 'configmap-name' not found for volume '{volume-name {nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil &ConfigMapVolumeSource{LocalObjectReference:LocalObjectReference{Name:configmap-name,},Items:[]KeyToPath{},DefaultMode:nil,Optional:*false,} nil nil nil nil nil nil nil nil nil}}'"})
|
assert.Equal(t, got, []string{"ConfigMap 'configmap-name' not found for volume '{volume-name {nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil &ConfigMapVolumeSource{LocalObjectReference:LocalObjectReference{Name:configmap-name,},Items:[]KeyToPath{},DefaultMode:nil,Optional:*false,} nil nil nil nil nil nil nil nil nil nil}}'"})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -649,7 +649,7 @@ func TestValidateSecretVolume(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
baseReconcileLoop := New(configuration.Configuration{
|
baseReconcileLoop := New(configuration.Configuration{
|
||||||
Jenkins: &v1alpha2.Jenkins{ObjectMeta: metav1.ObjectMeta{Name: "example"}},
|
Jenkins: &v1alpha2.Jenkins{ObjectMeta: metav1.ObjectMeta{Name: "example"}},
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -673,7 +673,7 @@ func TestValidateSecretVolume(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), &secret)
|
err := fakeClient.Create(context.TODO(), &secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
baseReconcileLoop := New(configuration.Configuration{
|
baseReconcileLoop := New(configuration.Configuration{
|
||||||
|
|
@ -699,7 +699,7 @@ func TestValidateSecretVolume(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
baseReconcileLoop := New(configuration.Configuration{
|
baseReconcileLoop := New(configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
|
|
@ -708,7 +708,7 @@ func TestValidateSecretVolume(t *testing.T) {
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, got, []string{"Secret 'secret-name' not found for volume '{volume-name {nil nil nil nil nil &SecretVolumeSource{SecretName:secret-name,Items:[]KeyToPath{},DefaultMode:nil,Optional:*false,} nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil}}'"})
|
assert.Equal(t, got, []string{"Secret 'secret-name' not found for volume '{volume-name {nil nil nil nil nil &SecretVolumeSource{SecretName:secret-name,Items:[]KeyToPath{},DefaultMode:nil,Optional:*false,} nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil}}'"})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -722,7 +722,7 @@ func TestValidateCustomization(t *testing.T) {
|
||||||
}
|
}
|
||||||
t.Run("empty", func(t *testing.T) {
|
t.Run("empty", func(t *testing.T) {
|
||||||
customization := v1alpha2.Customization{}
|
customization := v1alpha2.Customization{}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
baseReconcileLoop := New(configuration.Configuration{
|
baseReconcileLoop := New(configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -744,7 +744,7 @@ func TestValidateCustomization(t *testing.T) {
|
||||||
Namespace: defaultNamespace,
|
Namespace: defaultNamespace,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
baseReconcileLoop := New(configuration.Configuration{
|
baseReconcileLoop := New(configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -775,7 +775,7 @@ func TestValidateCustomization(t *testing.T) {
|
||||||
Namespace: defaultNamespace,
|
Namespace: defaultNamespace,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
baseReconcileLoop := New(configuration.Configuration{
|
baseReconcileLoop := New(configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -802,7 +802,7 @@ func TestValidateCustomization(t *testing.T) {
|
||||||
Namespace: defaultNamespace,
|
Namespace: defaultNamespace,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
baseReconcileLoop := New(configuration.Configuration{
|
baseReconcileLoop := New(configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -827,7 +827,7 @@ func TestValidateCustomization(t *testing.T) {
|
||||||
Namespace: defaultNamespace,
|
Namespace: defaultNamespace,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
baseReconcileLoop := New(configuration.Configuration{
|
baseReconcileLoop := New(configuration.Configuration{
|
||||||
Jenkins: jenkins,
|
Jenkins: jenkins,
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,9 @@ package configuration
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
||||||
|
|
@ -89,7 +88,7 @@ func (c *Configuration) IsJenkinsTerminating(pod corev1.Pod) bool {
|
||||||
|
|
||||||
// CreateResource is creating kubernetes resource and references it to Jenkins CR
|
// CreateResource is creating kubernetes resource and references it to Jenkins CR
|
||||||
func (c *Configuration) CreateResource(obj metav1.Object) error {
|
func (c *Configuration) CreateResource(obj metav1.Object) error {
|
||||||
runtimeObj, ok := obj.(runtime.Object)
|
clientObj, ok := obj.(client.Object)
|
||||||
if !ok {
|
if !ok {
|
||||||
return stackerr.Errorf("is not a %T a runtime.Object", obj)
|
return stackerr.Errorf("is not a %T a runtime.Object", obj)
|
||||||
}
|
}
|
||||||
|
|
@ -99,25 +98,25 @@ func (c *Configuration) CreateResource(obj metav1.Object) error {
|
||||||
return stackerr.WithStack(err)
|
return stackerr.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Client.Create(context.TODO(), runtimeObj) // don't wrap error
|
return c.Client.Create(context.TODO(), clientObj) // don't wrap error
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateResource is updating kubernetes resource and references it to Jenkins CR.
|
// UpdateResource is updating kubernetes resource and references it to Jenkins CR.
|
||||||
func (c *Configuration) UpdateResource(obj metav1.Object) error {
|
func (c *Configuration) UpdateResource(obj metav1.Object) error {
|
||||||
runtimeObj, ok := obj.(runtime.Object)
|
clientObj, ok := obj.(client.Object)
|
||||||
if !ok {
|
if !ok {
|
||||||
return stackerr.Errorf("is not a %T a runtime.Object", obj)
|
return stackerr.Errorf("is not a %T a runtime.Object", obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set Jenkins instance as the owner and controller, don't check error(can be already set)
|
// set Jenkins instance as the owner and controller, don't check errors(can be already set)
|
||||||
_ = controllerutil.SetControllerReference(c.Jenkins, obj, c.Scheme)
|
_ = controllerutil.SetControllerReference(c.Jenkins, obj, c.Scheme)
|
||||||
|
|
||||||
return c.Client.Update(context.TODO(), runtimeObj) // don't wrap error
|
return c.Client.Update(context.TODO(), clientObj) // don't wrap error
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateOrUpdateResource is creating or updating kubernetes resource and references it to Jenkins CR.
|
// CreateOrUpdateResource is creating or updating kubernetes resource and references it to Jenkins CR.
|
||||||
func (c *Configuration) CreateOrUpdateResource(obj metav1.Object) error {
|
func (c *Configuration) CreateOrUpdateResource(obj metav1.Object) error {
|
||||||
runtimeObj, ok := obj.(runtime.Object)
|
clientObj, ok := obj.(client.Object)
|
||||||
if !ok {
|
if !ok {
|
||||||
return stackerr.Errorf("is not a %T a runtime.Object", obj)
|
return stackerr.Errorf("is not a %T a runtime.Object", obj)
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +124,7 @@ func (c *Configuration) CreateOrUpdateResource(obj metav1.Object) error {
|
||||||
// set Jenkins instance as the owner and controller, don't check error(can be already set)
|
// set Jenkins instance as the owner and controller, don't check error(can be already set)
|
||||||
_ = controllerutil.SetControllerReference(c.Jenkins, obj, c.Scheme)
|
_ = controllerutil.SetControllerReference(c.Jenkins, obj, c.Scheme)
|
||||||
|
|
||||||
err := c.Client.Create(context.TODO(), runtimeObj)
|
err := c.Client.Create(context.TODO(), clientObj)
|
||||||
if err != nil && errors.IsAlreadyExists(err) {
|
if err != nil && errors.IsAlreadyExists(err) {
|
||||||
return c.UpdateResource(obj)
|
return c.UpdateResource(obj)
|
||||||
} else if err != nil && !errors.IsAlreadyExists(err) {
|
} else if err != nil && !errors.IsAlreadyExists(err) {
|
||||||
|
|
@ -202,7 +201,7 @@ func (c *Configuration) getJenkinsAPIUrl() (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
jenkinsURL := c.JenkinsAPIConnectionSettings.BuildJenkinsAPIUrl(service.Name, service.Namespace, service.Spec.Ports[0].Port, service.Spec.Ports[0].NodePort)
|
jenkinsURL := c.JenkinsAPIConnectionSettings.BuildJenkinsAPIUrl(service.Name, service.Namespace, service.Spec.Ports[0].Port, service.Spec.Ports[0].NodePort)
|
||||||
if prefix, ok := GetJenkinsOpts(*c.Jenkins)["prefix"]; ok {
|
if prefix, ok := resources.GetJenkinsOpts(*c.Jenkins)["prefix"]; ok {
|
||||||
jenkinsURL += prefix
|
jenkinsURL += prefix
|
||||||
}
|
}
|
||||||
return jenkinsURL, nil
|
return jenkinsURL, nil
|
||||||
|
|
@ -278,29 +277,3 @@ func (c *Configuration) GetJenkinsClientFromSecret() (jenkinsclient.Jenkins, err
|
||||||
string(credentialsSecret.Data[resources.OperatorCredentialsSecretUserNameKey]),
|
string(credentialsSecret.Data[resources.OperatorCredentialsSecretUserNameKey]),
|
||||||
string(credentialsSecret.Data[resources.OperatorCredentialsSecretTokenKey]))
|
string(credentialsSecret.Data[resources.OperatorCredentialsSecretTokenKey]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetJenkinsOpts gets JENKINS_OPTS env parameter, parses it's values and returns it as a map`
|
|
||||||
func GetJenkinsOpts(jenkins v1alpha2.Jenkins) map[string]string {
|
|
||||||
envs := jenkins.Spec.Master.Containers[0].Env
|
|
||||||
jenkinsOpts := make(map[string]string)
|
|
||||||
|
|
||||||
for key, value := range envs {
|
|
||||||
if value.Name == "JENKINS_OPTS" {
|
|
||||||
jenkinsOptsEnv := envs[key]
|
|
||||||
jenkinsOptsWithDashes := jenkinsOptsEnv.Value
|
|
||||||
if len(jenkinsOptsWithDashes) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
jenkinsOptsWithEqOperators := strings.Split(jenkinsOptsWithDashes, " ")
|
|
||||||
|
|
||||||
for _, vx := range jenkinsOptsWithEqOperators {
|
|
||||||
opt := strings.Split(vx, "=")
|
|
||||||
jenkinsOpts[strings.ReplaceAll(opt[0], "--", "")] = opt[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return jenkinsOpts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/groovy"
|
"github.com/jenkinsci/kubernetes-operator/pkg/groovy"
|
||||||
|
|
@ -31,7 +31,7 @@ func New(jenkinsClient jenkinsclient.Jenkins, k8sClient k8s.Client, jenkins *v1a
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure configures Jenkins with help Configuration as a code plugin
|
// Ensure configures Jenkins with help Configuration as a code plugin
|
||||||
func (c *configurationAsCode) Ensure(jenkins *v1alpha2.Jenkins) (requeue bool, err error) {
|
func (c *configurationAsCode) Ensure(_ *v1alpha2.Jenkins) (requeue bool, err error) {
|
||||||
requeue, err = c.groovyClient.WaitForSecretSynchronization(resources.ConfigurationAsCodeSecretVolumePath)
|
requeue, err = c.groovyClient.WaitForSecretSynchronization(resources.ConfigurationAsCodeSecretVolumePath)
|
||||||
if err != nil || requeue {
|
if err != nil || requeue {
|
||||||
return requeue, err
|
return requeue, err
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,7 @@ package user
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
|
||||||
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/backuprestore"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/backuprestore"
|
||||||
|
|
@ -14,6 +12,8 @@ import (
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/user/seedjobs"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/user/seedjobs"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/groovy"
|
"github.com/jenkinsci/kubernetes-operator/pkg/groovy"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,8 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/internal/render"
|
"github.com/jenkinsci/kubernetes-operator/internal/render"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
|
||||||
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
|
|
@ -18,6 +17,8 @@ import (
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/groovy"
|
"github.com/jenkinsci/kubernetes-operator/pkg/groovy"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/reason"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/reason"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
stackerr "github.com/pkg/errors"
|
stackerr "github.com/pkg/errors"
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
|
@ -228,7 +229,7 @@ func (s *seedJobs) EnsureSeedJobs(jenkins *v1alpha2.Jenkins) (done bool, err err
|
||||||
seedJobIDs := s.getAllSeedJobIDs(*jenkins)
|
seedJobIDs := s.getAllSeedJobIDs(*jenkins)
|
||||||
if !reflect.DeepEqual(seedJobIDs, jenkins.Status.CreatedSeedJobs) {
|
if !reflect.DeepEqual(seedJobIDs, jenkins.Status.CreatedSeedJobs) {
|
||||||
jenkins.Status.CreatedSeedJobs = seedJobIDs
|
jenkins.Status.CreatedSeedJobs = seedJobIDs
|
||||||
return false, stackerr.WithStack(s.Client.Update(context.TODO(), jenkins))
|
return false, stackerr.WithStack(s.Client.Status().Update(context.TODO(), jenkins))
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
|
|
@ -267,8 +268,15 @@ func (s *seedJobs) createJobs(jenkins *v1alpha2.Jenkins) (requeue bool, err erro
|
||||||
}
|
}
|
||||||
|
|
||||||
hash := sha256.New()
|
hash := sha256.New()
|
||||||
hash.Write([]byte(groovyScript))
|
_, err = hash.Write([]byte(groovyScript))
|
||||||
hash.Write([]byte(credentialValue))
|
if err != nil {
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
_, err = hash.Write([]byte(credentialValue))
|
||||||
|
if err != nil {
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
|
||||||
requeue, err := groovyClient.EnsureSingle(seedJob.ID, fmt.Sprintf("%s.groovy", seedJob.ID), base64.URLEncoding.EncodeToString(hash.Sum(nil)), groovyScript)
|
requeue, err := groovyClient.EnsureSingle(seedJob.ID, fmt.Sprintf("%s.groovy", seedJob.ID), base64.URLEncoding.EncodeToString(hash.Sum(nil)), groovyScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, err
|
return true, err
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
|
||||||
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
||||||
|
|
@ -16,6 +14,7 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
|
@ -74,7 +73,7 @@ func TestEnsureSeedJobs(t *testing.T) {
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
jenkinsClient := jenkinsclient.NewMockJenkins(ctrl)
|
jenkinsClient := jenkinsclient.NewMockJenkins(ctrl)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -126,7 +125,7 @@ func TestEnsureSeedJobs(t *testing.T) {
|
||||||
jenkins.Spec.SeedJobs = []v1alpha2.SeedJob{}
|
jenkins.Spec.SeedJobs = []v1alpha2.SeedJob{}
|
||||||
|
|
||||||
jenkinsClient := jenkinsclient.NewMockJenkins(ctrl)
|
jenkinsClient := jenkinsclient.NewMockJenkins(ctrl)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -174,7 +173,7 @@ func TestCreateAgent(t *testing.T) {
|
||||||
jenkins := jenkinsCustomResource()
|
jenkins := jenkinsCustomResource()
|
||||||
|
|
||||||
jenkinsClient := jenkinsclient.NewMockJenkins(ctrl)
|
jenkinsClient := jenkinsclient.NewMockJenkins(ctrl)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
|
|
||||||
stackerr "github.com/pkg/errors"
|
stackerr "github.com/pkg/errors"
|
||||||
"github.com/robfig/cron"
|
"github.com/robfig/cron"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
@ -57,6 +57,10 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
Name: "deploy-keys",
|
Name: "deploy-keys",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
}
|
}
|
||||||
|
jenkinsObjectMeta := metav1.ObjectMeta{
|
||||||
|
Name: "cr",
|
||||||
|
Namespace: "default",
|
||||||
|
}
|
||||||
t.Run("Valid with public repository and without private key", func(t *testing.T) {
|
t.Run("Valid with public repository and without private key", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
Spec: v1alpha2.JenkinsSpec{
|
Spec: v1alpha2.JenkinsSpec{
|
||||||
|
|
@ -73,7 +77,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -102,7 +106,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -120,6 +124,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Valid with private key and secret", func(t *testing.T) {
|
t.Run("Valid with private key and secret", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
ObjectMeta: jenkinsObjectMeta,
|
||||||
Spec: v1alpha2.JenkinsSpec{
|
Spec: v1alpha2.JenkinsSpec{
|
||||||
SeedJobs: []v1alpha2.SeedJob{
|
SeedJobs: []v1alpha2.SeedJob{
|
||||||
{
|
{
|
||||||
|
|
@ -141,7 +146,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
PrivateKeySecretKey: []byte(fakePrivateKey),
|
PrivateKeySecretKey: []byte(fakePrivateKey),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -160,6 +165,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Invalid private key in secret", func(t *testing.T) {
|
t.Run("Invalid private key in secret", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
ObjectMeta: jenkinsObjectMeta,
|
||||||
Spec: v1alpha2.JenkinsSpec{
|
Spec: v1alpha2.JenkinsSpec{
|
||||||
SeedJobs: []v1alpha2.SeedJob{
|
SeedJobs: []v1alpha2.SeedJob{
|
||||||
{
|
{
|
||||||
|
|
@ -181,7 +187,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
PrivateKeySecretKey: []byte(fakeInvalidPrivateKey),
|
PrivateKeySecretKey: []byte(fakeInvalidPrivateKey),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -201,6 +207,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Invalid with PrivateKey and empty Secret data", func(t *testing.T) {
|
t.Run("Invalid with PrivateKey and empty Secret data", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
ObjectMeta: jenkinsObjectMeta,
|
||||||
Spec: v1alpha2.JenkinsSpec{
|
Spec: v1alpha2.JenkinsSpec{
|
||||||
SeedJobs: []v1alpha2.SeedJob{
|
SeedJobs: []v1alpha2.SeedJob{
|
||||||
{
|
{
|
||||||
|
|
@ -222,7 +229,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
PrivateKeySecretKey: []byte(""),
|
PrivateKeySecretKey: []byte(""),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -256,7 +263,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -286,7 +293,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -316,7 +323,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -346,7 +353,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -364,6 +371,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Valid with username and password", func(t *testing.T) {
|
t.Run("Valid with username and password", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
ObjectMeta: jenkinsObjectMeta,
|
||||||
Spec: v1alpha2.JenkinsSpec{
|
Spec: v1alpha2.JenkinsSpec{
|
||||||
SeedJobs: []v1alpha2.SeedJob{
|
SeedJobs: []v1alpha2.SeedJob{
|
||||||
{
|
{
|
||||||
|
|
@ -385,7 +393,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
PasswordSecretKey: []byte("some-password"),
|
PasswordSecretKey: []byte("some-password"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -404,6 +412,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Invalid with empty username", func(t *testing.T) {
|
t.Run("Invalid with empty username", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
ObjectMeta: jenkinsObjectMeta,
|
||||||
Spec: v1alpha2.JenkinsSpec{
|
Spec: v1alpha2.JenkinsSpec{
|
||||||
SeedJobs: []v1alpha2.SeedJob{
|
SeedJobs: []v1alpha2.SeedJob{
|
||||||
{
|
{
|
||||||
|
|
@ -425,7 +434,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
PasswordSecretKey: []byte("some-password"),
|
PasswordSecretKey: []byte("some-password"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -445,6 +454,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Invalid with empty password", func(t *testing.T) {
|
t.Run("Invalid with empty password", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
ObjectMeta: jenkinsObjectMeta,
|
||||||
Spec: v1alpha2.JenkinsSpec{
|
Spec: v1alpha2.JenkinsSpec{
|
||||||
SeedJobs: []v1alpha2.SeedJob{
|
SeedJobs: []v1alpha2.SeedJob{
|
||||||
{
|
{
|
||||||
|
|
@ -466,7 +476,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
PasswordSecretKey: []byte(""),
|
PasswordSecretKey: []byte(""),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -486,6 +496,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Invalid without username", func(t *testing.T) {
|
t.Run("Invalid without username", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
ObjectMeta: jenkinsObjectMeta,
|
||||||
Spec: v1alpha2.JenkinsSpec{
|
Spec: v1alpha2.JenkinsSpec{
|
||||||
SeedJobs: []v1alpha2.SeedJob{
|
SeedJobs: []v1alpha2.SeedJob{
|
||||||
{
|
{
|
||||||
|
|
@ -506,7 +517,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
PasswordSecretKey: []byte("some-password"),
|
PasswordSecretKey: []byte("some-password"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -526,6 +537,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Invalid without password", func(t *testing.T) {
|
t.Run("Invalid without password", func(t *testing.T) {
|
||||||
jenkins := v1alpha2.Jenkins{
|
jenkins := v1alpha2.Jenkins{
|
||||||
|
ObjectMeta: jenkinsObjectMeta,
|
||||||
Spec: v1alpha2.JenkinsSpec{
|
Spec: v1alpha2.JenkinsSpec{
|
||||||
SeedJobs: []v1alpha2.SeedJob{
|
SeedJobs: []v1alpha2.SeedJob{
|
||||||
{
|
{
|
||||||
|
|
@ -546,7 +558,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
UsernameSecretKey: []byte("some-username"),
|
UsernameSecretKey: []byte("some-username"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err := fakeClient.Create(context.TODO(), secret)
|
err := fakeClient.Create(context.TODO(), secret)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -581,7 +593,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -615,7 +627,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -647,7 +659,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -685,7 +697,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -717,7 +729,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
@ -755,7 +767,7 @@ func TestValidateSeedJobs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
|
|
||||||
config := configuration.Configuration{
|
config := configuration.Configuration{
|
||||||
Client: fakeClient,
|
Client: fakeClient,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/backuprestore"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/backuprestore"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/user/seedjobs"
|
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/user/seedjobs"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
package jenkins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
|
||||||
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration"
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/client-go/kubernetes"
|
|
||||||
"k8s.io/client-go/rest"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ReconcileJenkins reconciles a Jenkins object.
|
|
||||||
type ReconcileJenkins struct {
|
|
||||||
client client.Client
|
|
||||||
scheme *runtime.Scheme
|
|
||||||
jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings
|
|
||||||
clientSet kubernetes.Clientset
|
|
||||||
config rest.Config
|
|
||||||
notificationEvents *chan event.Event
|
|
||||||
KubernetesClusterDomain string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ReconcileJenkins) newReconcilierConfiguration(jenkins *v1alpha2.Jenkins) configuration.Configuration {
|
|
||||||
config := configuration.Configuration{
|
|
||||||
Client: r.client,
|
|
||||||
ClientSet: r.clientSet,
|
|
||||||
Notifications: r.notificationEvents,
|
|
||||||
Jenkins: jenkins,
|
|
||||||
Scheme: r.scheme,
|
|
||||||
Config: &r.config,
|
|
||||||
JenkinsAPIConnectionSettings: r.jenkinsAPIConnectionSettings,
|
|
||||||
KubernetesClusterDomain: r.KubernetesClusterDomain,
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
// newReconciler returns a newReconcilierConfiguration reconcile.Reconciler.
|
|
||||||
func newReconciler(mgr manager.Manager, jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings, kubernetesClusterDomain string, clientSet kubernetes.Clientset, config rest.Config, notificationEvents *chan event.Event) reconcile.Reconciler {
|
|
||||||
return &ReconcileJenkins{
|
|
||||||
client: mgr.GetClient(),
|
|
||||||
scheme: mgr.GetScheme(),
|
|
||||||
jenkinsAPIConnectionSettings: jenkinsAPIConnectionSettings,
|
|
||||||
clientSet: clientSet,
|
|
||||||
config: config,
|
|
||||||
notificationEvents: notificationEvents,
|
|
||||||
KubernetesClusterDomain: kubernetesClusterDomain,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
package jenkinsimage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
jenkinsv1alpha2 "github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/controller"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
|
||||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
|
||||||
)
|
|
||||||
|
|
||||||
var log = logf.Log.WithName("controller_jenkinsimage")
|
|
||||||
|
|
||||||
// Add creates a new JenkinsImage Controller and adds it to the Manager. The Manager will set fields on the Controller
|
|
||||||
// and Start it when the Manager is Started.
|
|
||||||
func Add(mgr manager.Manager) error {
|
|
||||||
r := &ReconcileJenkinsImage{client: mgr.GetClient(), scheme: mgr.GetScheme()}
|
|
||||||
return add(mgr, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// add adds a new Controller to mgr with r as the reconcile.Reconciler
|
|
||||||
func add(mgr manager.Manager, r reconcile.Reconciler) error {
|
|
||||||
// Create a new controller
|
|
||||||
c, err := controller.New("jenkinsimage-controller", mgr, controller.Options{Reconciler: r})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch for changes to primary resource JenkinsImage
|
|
||||||
eventHandlerForObject := &handler.EnqueueRequestForObject{}
|
|
||||||
src := &source.Kind{Type: &jenkinsv1alpha2.JenkinsImage{}}
|
|
||||||
err = c.Watch(src, eventHandlerForObject)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch for changes to secondary resource Pods and requeue the owner JenkinsImage
|
|
||||||
eventHandlerForOwner := &handler.EnqueueRequestForOwner{
|
|
||||||
IsController: true,
|
|
||||||
OwnerType: &jenkinsv1alpha2.JenkinsImage{},
|
|
||||||
}
|
|
||||||
err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, eventHandlerForOwner)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
// Watch for changes to secondary ConfigMap and requeue the owner JenkinsImage
|
|
||||||
err = c.Watch(&source.Kind{Type: &corev1.ConfigMap{}}, eventHandlerForOwner)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// blank assignment to verify that ReconcileJenkinsImage implements reconcile.Reconciler
|
|
||||||
var _ reconcile.Reconciler = &ReconcileJenkinsImage{}
|
|
||||||
|
|
||||||
// ReconcileJenkinsImage reconciles a JenkinsImage object
|
|
||||||
type ReconcileJenkinsImage struct {
|
|
||||||
// This client, initialized using mgr.Client() above, is a split client
|
|
||||||
// that reads objects from the cache and writes to the apiserver
|
|
||||||
client client.Client
|
|
||||||
scheme *runtime.Scheme
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reconcile reads that state of the cluster for a JenkinsImage object and makes changes based on the state read
|
|
||||||
// and what is in the JenkinsImage.Spec
|
|
||||||
// The Controller will requeue the Request to be processed again if the returned error is non-nil or
|
|
||||||
// Result.Requeue is true, otherwise upon completion it will remove the work from the queue.
|
|
||||||
func (r *ReconcileJenkinsImage) Reconcile(request reconcile.Request) (reconcile.Result, error) {
|
|
||||||
reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
|
|
||||||
reqLogger.Info("Reconciling JenkinsImage")
|
|
||||||
|
|
||||||
// Fetch the JenkinsImage instance
|
|
||||||
instance := &jenkinsv1alpha2.JenkinsImage{}
|
|
||||||
err := r.client.Get(context.TODO(), request.NamespacedName, instance)
|
|
||||||
if err != nil {
|
|
||||||
if apierrors.IsNotFound(err) {
|
|
||||||
// Request object not found, could have been deleted after reconcile request.
|
|
||||||
// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
|
|
||||||
// Return and don't requeue
|
|
||||||
return reconcile.Result{}, nil
|
|
||||||
}
|
|
||||||
// Error reading the object - requeue the request.
|
|
||||||
return reconcile.Result{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define a new ConfigMap containing the Dockerfile used to build the image
|
|
||||||
dockerfile := resources.NewDockerfileConfigMap(instance)
|
|
||||||
// Set JenkinsImage instance as the owner and controller
|
|
||||||
if err := controllerutil.SetControllerReference(instance, dockerfile, r.scheme); err != nil {
|
|
||||||
return reconcile.Result{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if this ConfigMap already exists
|
|
||||||
foundConfigMap := &corev1.ConfigMap{}
|
|
||||||
err = r.client.Get(context.TODO(), types.NamespacedName{Name: dockerfile.Name, Namespace: dockerfile.Namespace}, foundConfigMap)
|
|
||||||
if err != nil && apierrors.IsNotFound(err) {
|
|
||||||
reqLogger.Info("Creating a new ConfigMap", "ConfigMap.Namespace", dockerfile.Namespace, "ConfigMap.Name", dockerfile.Name)
|
|
||||||
err = r.client.Create(context.TODO(), dockerfile)
|
|
||||||
if err != nil {
|
|
||||||
return reconcile.Result{}, err
|
|
||||||
}
|
|
||||||
// ConfigMap created successfully - don't requeue
|
|
||||||
return reconcile.Result{}, nil
|
|
||||||
} else if err != nil {
|
|
||||||
return reconcile.Result{}, err
|
|
||||||
}
|
|
||||||
// ConfigMap already exists - don't requeue
|
|
||||||
reqLogger.Info("Skip reconcile: ConfigMap already exists", "ConfigMap.Namespace", foundConfigMap.Namespace, "ConfigMap.Name", foundConfigMap.Name)
|
|
||||||
|
|
||||||
// Define a new Pod object
|
|
||||||
pod := resources.NewBuilderPod(instance)
|
|
||||||
// Set JenkinsImage instance as the owner and controller
|
|
||||||
if err := controllerutil.SetControllerReference(instance, pod, r.scheme); err != nil {
|
|
||||||
return reconcile.Result{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if this Pod already exists
|
|
||||||
foundPod := &corev1.Pod{}
|
|
||||||
err = r.client.Get(context.TODO(), types.NamespacedName{Name: pod.Name, Namespace: pod.Namespace}, foundPod)
|
|
||||||
if err != nil && apierrors.IsNotFound(err) {
|
|
||||||
reqLogger.Info("Creating a new Pod", "Pod.Namespace", pod.Namespace, "Pod.Name", pod.Name)
|
|
||||||
err = r.client.Create(context.TODO(), pod)
|
|
||||||
if err != nil {
|
|
||||||
return reconcile.Result{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pod created successfully - don't requeue
|
|
||||||
return reconcile.Result{}, nil
|
|
||||||
} else if err != nil {
|
|
||||||
return reconcile.Result{}, err
|
|
||||||
}
|
|
||||||
// Pod already exists - don't requeue
|
|
||||||
reqLogger.Info("Skip reconcile: Pod already exists", "Pod.Namespace", foundPod.Namespace, "Pod.Name", foundPod.Name)
|
|
||||||
|
|
||||||
return reconcile.Result{}, nil
|
|
||||||
}
|
|
||||||
|
|
@ -54,7 +54,6 @@ func initializeEventRecorder(config *rest.Config, component string) (record.Even
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
eventBroadcaster := record.NewBroadcaster()
|
eventBroadcaster := record.NewBroadcaster()
|
||||||
//eventBroadcaster.StartLogging(glog.Infof) TODO integrate with proper logger
|
|
||||||
eventBroadcaster.StartRecordingToSink(
|
eventBroadcaster.StartRecordingToSink(
|
||||||
&typedcorev1.EventSinkImpl{
|
&typedcorev1.EventSinkImpl{
|
||||||
Interface: client.CoreV1().Events("")})
|
Interface: client.CoreV1().Events("")})
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ func (g *Groovy) EnsureSingle(source, name, hash, groovyScript string) (requeue
|
||||||
|
|
||||||
g.jenkins.Status.AppliedGroovyScripts = appliedGroovyScripts
|
g.jenkins.Status.AppliedGroovyScripts = appliedGroovyScripts
|
||||||
|
|
||||||
return true, g.k8sClient.Update(context.TODO(), g.jenkins)
|
return true, g.k8sClient.Status().Update(context.TODO(), g.jenkins)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitForSecretSynchronization runs groovy script which waits to synchronize secrets in pod by k8s
|
// WaitForSecretSynchronization runs groovy script which waits to synchronize secrets in pod by k8s
|
||||||
|
|
@ -96,7 +96,10 @@ func (g *Groovy) WaitForSecretSynchronization(secretsPath string) (requeue bool,
|
||||||
for secretKey, secretValue := range secret.Data {
|
for secretKey, secretValue := range secret.Data {
|
||||||
toCalculate[secretKey] = string(secretValue)
|
toCalculate[secretKey] = string(secretValue)
|
||||||
}
|
}
|
||||||
hash := g.calculateHash(toCalculate)
|
hash, err := g.calculateHash(toCalculate)
|
||||||
|
if err != nil {
|
||||||
|
return true, errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
name := "synchronizing-secret.groovy"
|
name := "synchronizing-secret.groovy"
|
||||||
if g.isGroovyScriptAlreadyApplied(g.customization.Secret.Name, name, hash) {
|
if g.isGroovyScriptAlreadyApplied(g.customization.Secret.Name, name, hash) {
|
||||||
|
|
@ -137,7 +140,10 @@ func (g *Groovy) Ensure(filter func(name string) bool, updateGroovyScript func(g
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
hash := g.calculateCustomizationHash(*secret, name, groovyScript)
|
hash, err := g.calculateCustomizationHash(*secret, name, groovyScript)
|
||||||
|
if err != nil {
|
||||||
|
return true, errors.WithStack(err)
|
||||||
|
}
|
||||||
if g.isGroovyScriptAlreadyApplied(configMap.Name, name, hash) {
|
if g.isGroovyScriptAlreadyApplied(configMap.Name, name, hash) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -153,7 +159,7 @@ func (g *Groovy) Ensure(filter func(name string) bool, updateGroovyScript func(g
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Groovy) calculateCustomizationHash(secret corev1.Secret, key, groovyScript string) string {
|
func (g *Groovy) calculateCustomizationHash(secret corev1.Secret, key, groovyScript string) (string, error) {
|
||||||
toCalculate := map[string]string{}
|
toCalculate := map[string]string{}
|
||||||
for secretKey, secretValue := range secret.Data {
|
for secretKey, secretValue := range secret.Data {
|
||||||
toCalculate[secretKey] = string(secretValue)
|
toCalculate[secretKey] = string(secretValue)
|
||||||
|
|
@ -173,7 +179,7 @@ func (g *Groovy) isGroovyScriptAlreadyApplied(source, name, hash string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Groovy) calculateHash(data map[string]string) string {
|
func (g *Groovy) calculateHash(data map[string]string) (string, error) {
|
||||||
hash := sha256.New()
|
hash := sha256.New()
|
||||||
|
|
||||||
var keys []string
|
var keys []string
|
||||||
|
|
@ -182,10 +188,16 @@ func (g *Groovy) calculateHash(data map[string]string) string {
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
hash.Write([]byte(key))
|
_, err := hash.Write([]byte(key))
|
||||||
hash.Write([]byte(data[key]))
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
_, err = hash.Write([]byte(data[key]))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return base64.StdEncoding.EncodeToString(hash.Sum(nil))
|
return base64.StdEncoding.EncodeToString(hash.Sum(nil)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddSecretsLoaderToGroovyScript modify groovy scripts to load Kubernetes secrets into groovy map
|
// AddSecretsLoaderToGroovyScript modify groovy scripts to load Kubernetes secrets into groovy map
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
|
@ -43,7 +43,7 @@ func TestGroovy_EnsureSingle(t *testing.T) {
|
||||||
}
|
}
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err = fakeClient.Create(ctx, jenkins)
|
err = fakeClient.Create(ctx, jenkins)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -89,7 +89,7 @@ func TestGroovy_EnsureSingle(t *testing.T) {
|
||||||
}
|
}
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err = fakeClient.Create(ctx, jenkins)
|
err = fakeClient.Create(ctx, jenkins)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -125,7 +125,7 @@ func TestGroovy_EnsureSingle(t *testing.T) {
|
||||||
}
|
}
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err = fakeClient.Create(ctx, jenkins)
|
err = fakeClient.Create(ctx, jenkins)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -197,7 +197,7 @@ func TestGroovy_EnsureSingle(t *testing.T) {
|
||||||
}
|
}
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err = fakeClient.Create(ctx, jenkins)
|
err = fakeClient.Create(ctx, jenkins)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -257,7 +257,7 @@ func TestGroovy_EnsureSingle(t *testing.T) {
|
||||||
}
|
}
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err = fakeClient.Create(ctx, jenkins)
|
err = fakeClient.Create(ctx, jenkins)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -289,7 +289,7 @@ func TestGroovy_EnsureSingle(t *testing.T) {
|
||||||
}
|
}
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err = fakeClient.Create(ctx, jenkins)
|
err = fakeClient.Create(ctx, jenkins)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -323,7 +323,7 @@ func TestGroovy_EnsureSingle(t *testing.T) {
|
||||||
}
|
}
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err = fakeClient.Create(ctx, jenkins)
|
err = fakeClient.Create(ctx, jenkins)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
@ -392,7 +392,7 @@ func TestGroovy_Ensure(t *testing.T) {
|
||||||
}
|
}
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err = fakeClient.Create(ctx, jenkins)
|
err = fakeClient.Create(ctx, jenkins)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = fakeClient.Create(ctx, configMap)
|
err = fakeClient.Create(ctx, configMap)
|
||||||
|
|
@ -452,7 +452,7 @@ func TestGroovy_Ensure(t *testing.T) {
|
||||||
}
|
}
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err = fakeClient.Create(ctx, jenkins)
|
err = fakeClient.Create(ctx, jenkins)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = fakeClient.Create(ctx, configMap)
|
err = fakeClient.Create(ctx, configMap)
|
||||||
|
|
@ -511,7 +511,7 @@ func TestGroovy_Ensure(t *testing.T) {
|
||||||
}
|
}
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err = fakeClient.Create(ctx, jenkins)
|
err = fakeClient.Create(ctx, jenkins)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = fakeClient.Create(ctx, configMap)
|
err = fakeClient.Create(ctx, configMap)
|
||||||
|
|
@ -577,7 +577,7 @@ func TestGroovy_Ensure(t *testing.T) {
|
||||||
}
|
}
|
||||||
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
err := v1alpha2.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fakeClient := fake.NewFakeClient()
|
fakeClient := fake.NewClientBuilder().Build()
|
||||||
err = fakeClient.Create(ctx, jenkins)
|
err = fakeClient.Create(ctx, jenkins)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = fakeClient.Create(ctx, secret)
|
err = fakeClient.Create(ctx, secret)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package event
|
package event
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/reason"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/reason"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -28,7 +28,4 @@ const (
|
||||||
|
|
||||||
// PhaseUser is user-defined configuration of Jenkins
|
// PhaseUser is user-defined configuration of Jenkins
|
||||||
PhaseUser Phase = "user"
|
PhaseUser Phase = "user"
|
||||||
|
|
||||||
// PhaseUnknown is untraceable type of configuration
|
|
||||||
PhaseUnknown Phase = "unknown"
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/api/v1alpha2"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/event"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/provider"
|
"github.com/jenkinsci/kubernetes-operator/pkg/notifications/provider"
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue