Skip to content

Commit

Permalink
implement hookaction type
Browse files Browse the repository at this point in the history
Signed-off-by: Ashish Amarnath <[email protected]>
  • Loading branch information
ashish-amarnath committed Jan 16, 2020
1 parent 839f8b9 commit bc71ee4
Show file tree
Hide file tree
Showing 28 changed files with 1,615 additions and 99 deletions.
3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ RUN go mod download

# Copy the go source
COPY main.go main.go
COPY api/ api/
COPY controllers/ controllers/
COPY ./ ./

# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go
Expand Down
149 changes: 90 additions & 59 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,80 +1,111 @@

# Copyright 2020 The Kubernetes Authors.
#
# 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.

.DEFAULT_GOAL:=help

REGISTRY ?= gcr.io/$(shell gcloud config get-value project)
IMAGE_NAME ?= executionhook-controller
TAG ?= dev
# Image URL to use all building/pushing image targets
IMG ?= controller:latest
CONTROLLER_IMAGE ?= $(REGISTRY)/$(IMAGE_NAME):$(TAG)
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
CRD_OPTIONS ?= "crd:trivialVersions=true"

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif
# Directories.
TOOLS_DIR := hack/tools
TOOLS_BIN_DIR := $(TOOLS_DIR)/bin

# Tool binaries.
KUSTOMIZE := $(TOOLS_BIN_DIR)/kustomize
CONTROLLER_GEN := $(TOOLS_BIN_DIR)/controller-gen

$(CONTROLLER_GEN): $(TOOLS_DIR)/go.mod
cd $(TOOLS_DIR); go build -tags=tools -o ./bin/controller-gen sigs.k8s.io/controller-tools/cmd/controller-gen

$(KUSTOMIZE): $(TOOLS_DIR)/go.mod
cd $(TOOLS_DIR); go build -tags=tools -o ./bin/kustomize sigs.k8s.io/kustomize/kustomize/v3

.PHONY: help
help: ## Display this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

.PHONY: clean-bin
clean-bin: ## Remove all generated binaries
rm -rf bin
rm -rf hack/tools/bin

.PHONY: all
all: manager

# Run tests
test: generate fmt vet manifests
go test ./... -coverprofile cover.out
.PHONY: test
test: generate fmt vet manifests ## Run tests
go test -v ./... -coverprofile cover.out

# Build manager binary
manager: generate fmt vet
.PHONY: manager
manager: generate fmt vet test ## Build manager binary
go build -o bin/manager main.go

# Run against the configured Kubernetes cluster in ~/.kube/config
run: generate fmt vet manifests
go run ./main.go

# Install CRDs into a cluster
install: manifests
kustomize build config/crd | kubectl apply -f -
.PHONY: install
install: manifests $(KUSTOMIZE) ## Install CRDs into a cluster in the current context at ~/.kube/config
$(KUSTOMIZE) build config/crd | kubectl apply -f -

# Uninstall CRDs from a cluster
uninstall: manifests
kustomize build config/crd | kubectl delete -f -
.PHONY: uninstall
uninstall: manifests $(KUSTOMIZE) ## Uninstall latest version of CRDs from a cluster in the current context at ~/.kube/config
$(KUSTOMIZE) build config/crd | kubectl delete -f -

# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
deploy: manifests
cd config/manager && kustomize edit set image controller=${IMG}
kustomize build config/default | kubectl apply -f -
.PHONY: deploy
# hacky, works for now. TODO: ashish-amarnath make this better
deploy: manifests $(KUSTOMIZE) ## Deploy controller in the configured Kubernetes cluster in ~/.kube/config
cd config/manager && ../../$(KUSTOMIZE) edit set image controller=${CONTROLLER_IMAGE}
$(KUSTOMIZE) build config/default | kubectl apply -f -

# Generate manifests e.g. CRD, RBAC etc.
manifests: controller-gen
.PHONY: manifests
manifests: $(CONTROLLER_GEN) ## Generate manifests e.g. CRD, RBAC etc.
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases

# Run go fmt against code
fmt:
fmt: ## Run go fmt against code
go fmt ./...

# Run go vet against code
vet:
vet: ## Run go vet against code
go vet ./...

# Generate code
generate: controller-gen
.PHONY: modules
modules: ## Runs go mod to ensure modules are up-to-date.
go mod tidy
cd $(TOOLS_DIR); go mod tidy

.PHONY: verify-modules
verify-modules: modules
@if !(git diff --quiet HEAD -- go.sum go.mod hack/tools/go.mod hack/tools/go.sum); then \
echo "go module files are out of date"; exit 1; \
fi

generate: $(CONTROLLER_GEN) ## Generate code
$(CONTROLLER_GEN) object:headerFile=./hack/boilerplate.go.txt paths="./..."

# Build the docker image
docker-build: test
docker build . -t ${IMG}

# Push the docker image
docker-push:
docker push ${IMG}

# find or download controller-gen
# download controller-gen if necessary
controller-gen:
ifeq (, $(shell which controller-gen))
@{ \
set -e ;\
CONTROLLER_GEN_TMP_DIR=$$(mktemp -d) ;\
cd $$CONTROLLER_GEN_TMP_DIR ;\
go mod init tmp ;\
go get sigs.k8s.io/controller-tools/cmd/[email protected] ;\
rm -rf $$CONTROLLER_GEN_TMP_DIR ;\
}
CONTROLLER_GEN=$(GOBIN)/controller-gen
else
CONTROLLER_GEN=$(shell which controller-gen)
endif

.PHONY: verify-gen
verify-gen: generate manifests
@if !(git diff --quiet HEAD); then \
echo "generated code and manifest files are out of date, run make generate manifests"; exit 1; \
fi

.PHONY: docker-build
docker-build: test # Build the controller image
docker build . -t ${CONTROLLER_IMAGE}

.PHONY: docker-push
docker-push: docker-build # Push the controller image
docker push ${CONTROLLER_IMAGE}

3 changes: 3 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ resources:
- group: apps
kind: ExecutionHook
version: v1alpha1
- group: apps
kind: HookAction
version: v1alpha1
version: "2"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ and an `ExecutionHookController` to manage the hook's lifecycle.

## Usage

Exection Hook uses the [Kubebuilder framework](https://github.com/kubernetes-sigs/kubebuilder).
Execution Hook uses the [Kubebuilder framework](https://github.com/kubernetes-sigs/kubebuilder).
See the [Kubebuilder documentation](https://book.kubebuilder.io/introduction.html) for building, running and testing the project.

## Community, discussion, contribution, and support
Expand Down
12 changes: 8 additions & 4 deletions api/v1alpha1/executionhook_types.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -19,8 +20,9 @@ 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.
const (
ExecutionHookFinalizer = "executionhook.apps.x-k8s.io"
)

// ExecutionHookSpec defines the desired state of ExecutionHook
// HookActionName is copied to ExecutionHookSpec by the controller such as
Expand Down Expand Up @@ -91,7 +93,7 @@ type ExecutionHookStatus struct {
// information about how hook is executed in a container, including pod name,
// container name, ActionTimestamp, ActionSucceed, etc.
// +optional
HookStatuses []ContainerExecutionHookStatus `json:"containerExecutionHookStatuses,omitempty" protobuf:"bytes,1,rep,name=containerExecutionHookStatuses"`
HookStatuses []ContainerExecutionHookStatus `json:"hookStatuses,omitempty" protobuf:"bytes,1,rep,name=hookStatuses"`
}

// ContainerExecutionHookStatus represents the current state of a hook for a specific
Expand Down Expand Up @@ -152,8 +154,10 @@ const (
)

// +kubebuilder:object:root=true
// +kubebuilder:resource:path=executionhook,shortName=eh,scope=Namespaced,categories=executionhook
// +kubebuilder:subresource:status

// ExecutionHook is the Schema for the executionhooks API
// ExecutionHook is the Schema for the executionhook API
type ExecutionHook struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand Down
1 change: 1 addition & 0 deletions api/v1alpha1/groupversion_info.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
66 changes: 66 additions & 0 deletions api/v1alpha1/hookaction_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

// +kubebuilder:resource:path=hookaction,shortName=ha,scope=Namespaced,categories=hookaction
// +kubebuilder:object:root=true

// HookAction is the Schema for the hookactions API
type HookAction struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// This contains the command to run in a container.
// The command should be idempotent because the system does not guarantee exactly-once semantics.
// Any action may be triggered more than once but only the latest results will be logged in status.
// As alpha feature, only ExecAction type in Handler will be support, not the HTTPGETAction or TCPSocketAction.
// This is required.
Action corev1.Handler `json:"action"`

// ActionTimeoutSeconds defines when the execution hook controller should stop retrying.
// If execution fails, the execution hook controller will keep retrying until reaching
// ActionTimeoutSeconds. If execution still fails or hangs, execution hook controller
// stops retrying and updates executionhook status to failed.
// If controller loses its state, counter restarts. In this case, controller will retry
// for at least this long, before stopping.
// Once an action is started, controller has no way to stop it even if
// ActionTimeoutSeconds is exceeded. This simply controls if retry happens or not.
// retry is based on exponential backoff policy. If ActionTimeoutSeconds is not
// specified, it will retry until the hook object is deleted.
// +optional
ActionTimeoutSeconds int64 `json:"timeout"`
}

// +kubebuilder:object:root=true

// HookActionList contains a list of HookAction
type HookActionList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []HookAction `json:"items"`
}

func init() {
SchemeBuilder.Register(&HookAction{}, &HookActionList{})
}
59 changes: 59 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit bc71ee4

Please sign in to comment.