From 9daffd1e9a3e7f376b7abbaa0d76890710aae640 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Sat, 12 Mar 2022 16:33:14 -0600 Subject: [PATCH 01/23] feat(k8s): Define PipelinePodsTemplate CRD The CRD is defined under runtime/kurbernetes/apis Other pieces will be generated under runtime/kubernetes/generated --- runtime/kubernetes/apis/doc.go | 10 ++ runtime/kubernetes/apis/vela/register.go | 10 ++ runtime/kubernetes/apis/vela/v1alpha1/doc.go | 10 ++ .../kubernetes/apis/vela/v1alpha1/register.go | 44 +++++++ .../kubernetes/apis/vela/v1alpha1/types.go | 116 ++++++++++++++++++ 5 files changed, 190 insertions(+) create mode 100644 runtime/kubernetes/apis/doc.go create mode 100644 runtime/kubernetes/apis/vela/register.go create mode 100644 runtime/kubernetes/apis/vela/v1alpha1/doc.go create mode 100644 runtime/kubernetes/apis/vela/v1alpha1/register.go create mode 100644 runtime/kubernetes/apis/vela/v1alpha1/types.go diff --git a/runtime/kubernetes/apis/doc.go b/runtime/kubernetes/apis/doc.go new file mode 100644 index 00000000..e45ff9ac --- /dev/null +++ b/runtime/kubernetes/apis/doc.go @@ -0,0 +1,10 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Package apis defines the worker-config CRD and related utilities. +// +// Usage: +// +// import "github.com/go-vela/worker/runtime/kubernetes/apis" +package apis diff --git a/runtime/kubernetes/apis/vela/register.go b/runtime/kubernetes/apis/vela/register.go new file mode 100644 index 00000000..3308da51 --- /dev/null +++ b/runtime/kubernetes/apis/vela/register.go @@ -0,0 +1,10 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package vela + +// GroupName is the group name used in this package. +const ( + GroupName = "go-vela.github.io" +) diff --git a/runtime/kubernetes/apis/vela/v1alpha1/doc.go b/runtime/kubernetes/apis/vela/v1alpha1/doc.go new file mode 100644 index 00000000..d6fcc41b --- /dev/null +++ b/runtime/kubernetes/apis/vela/v1alpha1/doc.go @@ -0,0 +1,10 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Package v1alpha1 defines version 1alpha1 of the worker-config CRD. +// +// Usage: +// +// import "github.com/go-vela/worker/runtime/kubernetes/apis/v1alpha1" +package v1alpha1 diff --git a/runtime/kubernetes/apis/vela/v1alpha1/register.go b/runtime/kubernetes/apis/vela/v1alpha1/register.go new file mode 100644 index 00000000..f6ec17a4 --- /dev/null +++ b/runtime/kubernetes/apis/vela/v1alpha1/register.go @@ -0,0 +1,44 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/go-vela/worker/runtime/kubernetes/apis/vela" +) + +// SchemeGroupVersion is group version used to register these objects. +var SchemeGroupVersion = schema.GroupVersion{Group: vela.GroupName, Version: "v1alpha1"} + +// Kind takes an unqualified kind and returns a Group qualified GroupKind. +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource. +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // SchemeBuilder initializes a scheme builder. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme is a global function that registers this API group & version to a scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// addKnownTypes adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &PipelinePodsTemplate{}, + &PipelinePodsTemplateList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + + return nil +} diff --git a/runtime/kubernetes/apis/vela/v1alpha1/types.go b/runtime/kubernetes/apis/vela/v1alpha1/types.go new file mode 100644 index 00000000..56d13e25 --- /dev/null +++ b/runtime/kubernetes/apis/vela/v1alpha1/types.go @@ -0,0 +1,116 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// PipelinePodsTemplate defines the config for a given worker. +type PipelinePodsTemplate struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the PipelinePodsTemplate configuration for Vela Workers. + Spec PipelinePodsTemplateSpec `json:"spec,omitempty"` +} + +// PipelinePodsTemplateSpec configures creation of Pipeline Pods by Vela Workers. +type PipelinePodsTemplateSpec struct { + // Template defines defaults for Pipeline Pod creation in Vela Workers. + Template PipelinePodTemplate `json:"template"` +} + +// PipelinePodTemplate describes the data defaults to use when creating each pipeline pod. +type PipelinePodTemplate struct { + // Meta contains a subset of the standard object metadata (see: metav1.ObjectMeta). + Meta PipelinePodTemplateMeta `json:"metadata,omitempty"` + + // Spec contains a subset of the pod configuration options (see: v1.PodSpec). + Spec PipelinePodTemplateSpec `json:"spec,omitempty"` +} + +// PipelinePodTemplateMeta is a subset of metav1.ObjectMeta with meta defaults for pipeline pods. +type PipelinePodTemplateMeta struct { + // Labels is a key value map of strings to organize and categorize pods. + // More info: http://kubernetes.io/docs/user-guide/labels + Labels map[string]string `json:"labels,omitempty"` + + // Annotations is a key value map of strings to store additional info on pods. + // More info: http://kubernetes.io/docs/user-guide/annotations + Annotations map[string]string `json:"annotations,omitempty"` +} + +// PipelinePodTemplateSpec is (loosely) a subset of v1.PodSpec with spec defaults for pipeline pods. +type PipelinePodTemplateSpec struct { + // NodeSelector is a selector which must be true for the pipeline pod to fit on a node. + // Selector which must match a node's labels for the pod to be scheduled on that node. + // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + // +mapType=atomic + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + // Affinity specifies the pipeline pod's scheduling constraints, if any. + Affinity *v1.Affinity `json:"affinity,omitempty"` + // Affinity specifies the pipeline pod's tolerations, if any. + Tolerations []v1.Toleration `json:"tolerations,omitempty"` + + // DNSPolicy sets DNS policy for the pipeline pod. + // Defaults to "ClusterFirst". + // Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. + DNSPolicy v1.DNSPolicy `json:"dnsPolicy,omitempty"` + // DNSConfig specifies the DNS parameters of a pod. + // Parameters specified here will be merged to the generated DNS + // configuration based on DNSPolicy. + DNSConfig *v1.PodDNSConfig `json:"dnsConfig,omitempty"` + + // Container defines a limited set of defaults to apply to each PipelinePodsTemplate container. + // This is analogous to one entry in v1.PodSpec.Containers. + Container *PipelineContainer `json:"container,omitempty"` + + // SecurityContext holds pod-level security attributes and common container settings. + // Optional: Defaults to empty. See type description for default values of each field. + SecurityContext *PipelinePodSecurityContext `json:"securityContext,omitempty"` +} + +// PipelineContainer has defaults for containers in a PipelinePodsTemplate. +type PipelineContainer struct { + // SecurityContext defines the security options the container should be run with. + // If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + // More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + SecurityContext *PipelineContainerSecurityContext `json:"securityContext,omitempty"` +} + +// PipelinePodSecurityContext holds pod-level security attributes and common container settings. +type PipelinePodSecurityContext struct { + // RunAsNonRoot indicates that the container must run as a non-root user. + // If true, the Kubelet will validate the image at runtime to ensure that it + // does not run as UID 0 (root) and fail to start the container if it does. + // If unset or false, no such validation will be performed. + RunAsNonRoot *bool `json:"runAsNonRoot,omitempty"` + // Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + // sysctls (by the container runtime) might fail to launch. + // Note that this field cannot be set when spec.os.name is windows. + Sysctls []v1.Sysctl `json:"sysctls,omitempty"` +} + +// PipelineContainerSecurityContext holds container-level security configuration. +type PipelineContainerSecurityContext struct { + // Capabilities contains the capabilities to add/drop when running containers. + // Defaults to the default set of capabilities granted by the container runtime. + // Note that this field cannot be set when spec.os.name is windows. + Capabilities *v1.Capabilities `json:"capabilities,omitempty"` +} + +// PipelinePodsTemplateList is a list of Deployments. +type PipelinePodsTemplateList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata. + metav1.ListMeta `json:"metadata,omitempty"` + + // Items is the list of Deployments. + Items []PipelinePodsTemplate `json:"items"` +} From 19a183add5a2cf864aa57a326521a006724cb268 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Thu, 17 Mar 2022 21:58:36 -0500 Subject: [PATCH 02/23] chore: Add crd generation targets to Makefile uses k8s.io/code-generator and sigs.k8s.io/controller-tools --- .gitignore | 2 + Makefile | 81 ++++++++++++++++++++++++ PROJECT | 14 ++++ runtime/kubernetes/codegen/header.go.txt | 3 + 4 files changed, 100 insertions(+) create mode 100644 PROJECT create mode 100644 runtime/kubernetes/codegen/header.go.txt diff --git a/.gitignore b/.gitignore index 68b918a3..e050907a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ *.dll *.so *.dylib +# install makefile required bins in the bin/ dir +bin # Test binary, build with `go test -c` *.test diff --git a/Makefile b/Makefile index 09fa099f..06d2f890 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,14 @@ endif # create a list of linker flags for building the golang application LD_FLAGS = -X github.com/go-vela/worker/version.Commit=${GITHUB_SHA} -X github.com/go-vela/worker/version.Date=${BUILD_DATE} -X github.com/go-vela/worker/version.Tag=${GITHUB_TAG} +# Misc settings for the generating the Kubernetes CRD for the Kubernetes Runtime +K8S_CRD_OUTPUT_PKG=github.com/go-vela/worker/runtime/kubernetes/generated +K8S_CRD_INPUT_PKG=github.com/go-vela/worker/runtime/kubernetes/apis +K8S_CRD_CLIENTSET_PKG_NAME=clientset +K8S_CRD_CLIENTSET_NAME_VERSIONED=versioned +K8S_CRD_GROUP=vela +K8S_CRD_VERSION=v1alpha1 + # The `clean` target is intended to clean the workspace # and prepare the local changes for submission. # @@ -311,3 +319,76 @@ spec-version-update: # Usage: `make spec` .PHONY: spec spec: spec-gen spec-version-update spec-validate + +# The `crd-gen` target is intended to create a k8s CRD client +# for the kubernetes runtime using k8s.io/code-generator +# +# Usage: `make crd-gen` +.PHONY: crd-client-gen +crd-client-gen: controller-gen client-gen + $(eval TMP := $(shell mktemp -d)) + @echo + @echo "### Generating CRD deepcopy funcs using sig.k8s.io/controller-tools" + $(CONTROLLER_GEN) \ + object:headerFile="runtime/kubernetes/codegen/header.go.txt" \ + paths="${K8S_CRD_INPUT_PKG}/${K8S_CRD_GROUP}/${K8S_CRD_VERSION}" + @echo "### Generating CRD clientset using k8s.io/code-generator" + @echo "Generating clientset for ${K8S_CRD_GROUP}:${K8S_CRD_VERSION} at ${K8S_CRD_OUTPUT_PKG}/${K8S_CRD_CLIENTSET_PKG_NAME}" + $(CLIENT_GEN) \ + --clientset-name "${K8S_CRD_CLIENTSET_NAME_VERSIONED}" \ + --input-base "" \ + --input \ + "${K8S_CRD_INPUT_PKG}/${K8S_CRD_GROUP}/${K8S_CRD_VERSION}" \ + --output-package \ + "${K8S_CRD_OUTPUT_PKG}/${K8S_CRD_CLIENTSET_PKG_NAME}" \ + --output-base "${TMP}" \ + --go-header-file runtime/kubernetes/codegen/header.go.txt + @echo "### Copying generated files" + rm -rf runtime/kubernetes/generated/clientset + cp -r ${TMP}/github.com/go-vela/worker/runtime/kubernetes/* runtime/kubernetes/ + rm -rf $(TMP) + @echo "### CRD clientset created successfully" + +# The `crd-manifest` target will call crd-gen to create a k8s crd +# for the kubernetes runtime. +# +# Usage: `make crd` +.PHONY: crd-manifest +crd-manifest: controller-gen ## Generate CustomResourceDefinition object. + @echo + @echo "### Generating CRD manifest using sig.k8s.io/controller-tools" + @echo "Generating CRD manifest in runtime/kubernetes/generated" + $(CONTROLLER_GEN) crd paths="./..." output:crd:artifacts:config=runtime/kubernetes/generated + @echo "### CRD manifest created successfully" + +# The `crd` target will call crd-client-gen and crd-manifest +# to create a k8s CRD for the kubernetes runtime. +# +# Usage: `make crd` +.PHONY: crd +crd: crd-client-gen crd-manifest + +CONTROLLER_GEN = $(shell pwd)/bin/controller-gen +.PHONY: controller-gen +controller-gen: ## Download controller-gen locally if necessary. + $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.8.0) + +CLIENT_GEN = $(shell pwd)/bin/client-gen +.PHONY: client-gen +client-gen: ## Download client-gen locally if necessary. + $(eval K8S_LIB_VERSION := $(shell go mod graph | grep 'github.com/go-vela/worker k8s.io/client-go@' | sed 's/.*@//')) + $(call go-get-tool,$(CLIENT_GEN),k8s.io/code-generator/cmd/client-gen@$(K8S_LIB_VERSION)) + +# go-get-tool will 'go get' any package $2 and install it to $1. +PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) +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 diff --git a/PROJECT b/PROJECT new file mode 100644 index 00000000..2d44e196 --- /dev/null +++ b/PROJECT @@ -0,0 +1,14 @@ +domain: go-vela.github.io +layout: +- go.kubebuilder.io/v3 +projectName: worker +repo: github.com/go-vela/worker +resources: +- api: + crdVersion: v1 + namespaced: true + domain: go-vela.github.io + kind: PipelinePodsTemplate + path: pkg/runtime/kubernetes/apis/vela/v1alpha1 + version: v1alpha1 +version: "3" diff --git a/runtime/kubernetes/codegen/header.go.txt b/runtime/kubernetes/codegen/header.go.txt new file mode 100644 index 00000000..ca49b354 --- /dev/null +++ b/runtime/kubernetes/codegen/header.go.txt @@ -0,0 +1,3 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. From 718d9bd3fbc6d6099828bbb682743d9087babf8d Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Sat, 12 Mar 2022 16:33:14 -0600 Subject: [PATCH 03/23] chore: Generate client for PipelinePodsTemplate CRD generated under runtime/kubernetes/generated --- runtime/kubernetes/apis/vela/v1alpha1/doc.go | 4 + .../kubernetes/apis/vela/v1alpha1/types.go | 5 + .../vela/v1alpha1/zz_generated.deepcopy.go | 249 ++++++++++++++++++ .../clientset/versioned/clientset.go | 105 ++++++++ .../generated/clientset/versioned/doc.go | 8 + .../versioned/fake/clientset_generated.go | 73 +++++ .../generated/clientset/versioned/fake/doc.go | 8 + .../clientset/versioned/fake/register.go | 44 ++++ .../clientset/versioned/scheme/doc.go | 8 + .../clientset/versioned/scheme/register.go | 44 ++++ .../versioned/typed/vela/v1alpha1/doc.go | 8 + .../versioned/typed/vela/v1alpha1/fake/doc.go | 8 + .../fake/fake_pipelinepodstemplate.go | 118 +++++++++ .../vela/v1alpha1/fake/fake_vela_client.go | 28 ++ .../vela/v1alpha1/generated_expansion.go | 9 + .../vela/v1alpha1/pipelinepodstemplate.go | 166 ++++++++++++ .../typed/vela/v1alpha1/vela_client.go | 95 +++++++ 17 files changed, 980 insertions(+) create mode 100644 runtime/kubernetes/apis/vela/v1alpha1/zz_generated.deepcopy.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/clientset.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/doc.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/fake/clientset_generated.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/fake/doc.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/fake/register.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/scheme/doc.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/scheme/register.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/doc.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake/doc.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake/fake_pipelinepodstemplate.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake/fake_vela_client.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/generated_expansion.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/pipelinepodstemplate.go create mode 100644 runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/vela_client.go diff --git a/runtime/kubernetes/apis/vela/v1alpha1/doc.go b/runtime/kubernetes/apis/vela/v1alpha1/doc.go index d6fcc41b..1c293a5b 100644 --- a/runtime/kubernetes/apis/vela/v1alpha1/doc.go +++ b/runtime/kubernetes/apis/vela/v1alpha1/doc.go @@ -2,6 +2,10 @@ // // Use of this source code is governed by the LICENSE file in this repository. +// +kubebuilder:object:generate=true +// +groupName=go-vela.github.io +// +groupGoName=Vela + // Package v1alpha1 defines version 1alpha1 of the worker-config CRD. // // Usage: diff --git a/runtime/kubernetes/apis/vela/v1alpha1/types.go b/runtime/kubernetes/apis/vela/v1alpha1/types.go index 56d13e25..fb1be1e7 100644 --- a/runtime/kubernetes/apis/vela/v1alpha1/types.go +++ b/runtime/kubernetes/apis/vela/v1alpha1/types.go @@ -9,6 +9,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +// +genclient +// +kubebuilder:object:root=true + // PipelinePodsTemplate defines the config for a given worker. type PipelinePodsTemplate struct { metav1.TypeMeta `json:",inline"` @@ -105,6 +108,8 @@ type PipelineContainerSecurityContext struct { Capabilities *v1.Capabilities `json:"capabilities,omitempty"` } +// +kubebuilder:object:root=true + // PipelinePodsTemplateList is a list of Deployments. type PipelinePodsTemplateList struct { metav1.TypeMeta `json:",inline"` diff --git a/runtime/kubernetes/apis/vela/v1alpha1/zz_generated.deepcopy.go b/runtime/kubernetes/apis/vela/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000..7c29b647 --- /dev/null +++ b/runtime/kubernetes/apis/vela/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,249 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PipelineContainer) DeepCopyInto(out *PipelineContainer) { + *out = *in + if in.SecurityContext != nil { + in, out := &in.SecurityContext, &out.SecurityContext + *out = new(PipelineContainerSecurityContext) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PipelineContainer. +func (in *PipelineContainer) DeepCopy() *PipelineContainer { + if in == nil { + return nil + } + out := new(PipelineContainer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PipelineContainerSecurityContext) DeepCopyInto(out *PipelineContainerSecurityContext) { + *out = *in + if in.Capabilities != nil { + in, out := &in.Capabilities, &out.Capabilities + *out = new(v1.Capabilities) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PipelineContainerSecurityContext. +func (in *PipelineContainerSecurityContext) DeepCopy() *PipelineContainerSecurityContext { + if in == nil { + return nil + } + out := new(PipelineContainerSecurityContext) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PipelinePodSecurityContext) DeepCopyInto(out *PipelinePodSecurityContext) { + *out = *in + if in.RunAsNonRoot != nil { + in, out := &in.RunAsNonRoot, &out.RunAsNonRoot + *out = new(bool) + **out = **in + } + if in.Sysctls != nil { + in, out := &in.Sysctls, &out.Sysctls + *out = make([]v1.Sysctl, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PipelinePodSecurityContext. +func (in *PipelinePodSecurityContext) DeepCopy() *PipelinePodSecurityContext { + if in == nil { + return nil + } + out := new(PipelinePodSecurityContext) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PipelinePodTemplate) DeepCopyInto(out *PipelinePodTemplate) { + *out = *in + in.Meta.DeepCopyInto(&out.Meta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PipelinePodTemplate. +func (in *PipelinePodTemplate) DeepCopy() *PipelinePodTemplate { + if in == nil { + return nil + } + out := new(PipelinePodTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PipelinePodTemplateMeta) DeepCopyInto(out *PipelinePodTemplateMeta) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PipelinePodTemplateMeta. +func (in *PipelinePodTemplateMeta) DeepCopy() *PipelinePodTemplateMeta { + if in == nil { + return nil + } + out := new(PipelinePodTemplateMeta) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PipelinePodTemplateSpec) DeepCopyInto(out *PipelinePodTemplateSpec) { + *out = *in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(v1.Affinity) + (*in).DeepCopyInto(*out) + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.DNSConfig != nil { + in, out := &in.DNSConfig, &out.DNSConfig + *out = new(v1.PodDNSConfig) + (*in).DeepCopyInto(*out) + } + if in.Container != nil { + in, out := &in.Container, &out.Container + *out = new(PipelineContainer) + (*in).DeepCopyInto(*out) + } + if in.SecurityContext != nil { + in, out := &in.SecurityContext, &out.SecurityContext + *out = new(PipelinePodSecurityContext) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PipelinePodTemplateSpec. +func (in *PipelinePodTemplateSpec) DeepCopy() *PipelinePodTemplateSpec { + if in == nil { + return nil + } + out := new(PipelinePodTemplateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PipelinePodsTemplate) DeepCopyInto(out *PipelinePodsTemplate) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PipelinePodsTemplate. +func (in *PipelinePodsTemplate) DeepCopy() *PipelinePodsTemplate { + if in == nil { + return nil + } + out := new(PipelinePodsTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PipelinePodsTemplate) 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 *PipelinePodsTemplateList) DeepCopyInto(out *PipelinePodsTemplateList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]PipelinePodsTemplate, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PipelinePodsTemplateList. +func (in *PipelinePodsTemplateList) DeepCopy() *PipelinePodsTemplateList { + if in == nil { + return nil + } + out := new(PipelinePodsTemplateList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PipelinePodsTemplateList) 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 *PipelinePodsTemplateSpec) DeepCopyInto(out *PipelinePodsTemplateSpec) { + *out = *in + in.Template.DeepCopyInto(&out.Template) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PipelinePodsTemplateSpec. +func (in *PipelinePodsTemplateSpec) DeepCopy() *PipelinePodsTemplateSpec { + if in == nil { + return nil + } + out := new(PipelinePodsTemplateSpec) + in.DeepCopyInto(out) + return out +} diff --git a/runtime/kubernetes/generated/clientset/versioned/clientset.go b/runtime/kubernetes/generated/clientset/versioned/clientset.go new file mode 100644 index 00000000..81cbb5d4 --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/clientset.go @@ -0,0 +1,105 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +package versioned + +import ( + "fmt" + "net/http" + + velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1" + discovery "k8s.io/client-go/discovery" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + VelaV1alpha1() velav1alpha1.VelaV1alpha1Interface +} + +// Clientset contains the clients for groups. Each group has exactly one +// version included in a Clientset. +type Clientset struct { + *discovery.DiscoveryClient + velaV1alpha1 *velav1alpha1.VelaV1alpha1Client +} + +// VelaV1alpha1 retrieves the VelaV1alpha1Client +func (c *Clientset) VelaV1alpha1() velav1alpha1.VelaV1alpha1Interface { + return c.velaV1alpha1 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfig will generate a rate-limiter in configShallowCopy. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + + // share the transport between all clients + httpClient, err := rest.HTTPClientFor(&configShallowCopy) + if err != nil { + return nil, err + } + + return NewForConfigAndClient(&configShallowCopy, httpClient) +} + +// NewForConfigAndClient creates a new Clientset for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfigAndClient will generate a rate-limiter in configShallowCopy. +func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + if configShallowCopy.Burst <= 0 { + return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") + } + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + + var cs Clientset + var err error + cs.velaV1alpha1, err = velav1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + cs, err := NewForConfig(c) + if err != nil { + panic(err) + } + return cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.velaV1alpha1 = velav1alpha1.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/runtime/kubernetes/generated/clientset/versioned/doc.go b/runtime/kubernetes/generated/clientset/versioned/doc.go new file mode 100644 index 00000000..ebe2e2ee --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/doc.go @@ -0,0 +1,8 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated clientset. +package versioned diff --git a/runtime/kubernetes/generated/clientset/versioned/fake/clientset_generated.go b/runtime/kubernetes/generated/clientset/versioned/fake/clientset_generated.go new file mode 100644 index 00000000..eaaafa77 --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/fake/clientset_generated.go @@ -0,0 +1,73 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + clientset "github.com/go-vela/worker/runtime/kubernetes/generated/clientset/versioned" + velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1" + fakevelav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/discovery" + fakediscovery "k8s.io/client-go/discovery/fake" + "k8s.io/client-go/testing" +) + +// NewSimpleClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +func NewSimpleClientset(objects ...runtime.Object) *Clientset { + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{tracker: o} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.Interface. Meant to be embedded into a +// struct to get a default implementation. This makes faking out just the method +// you want to test easier. +type Clientset struct { + testing.Fake + discovery *fakediscovery.FakeDiscovery + tracker testing.ObjectTracker +} + +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} + +func (c *Clientset) Tracker() testing.ObjectTracker { + return c.tracker +} + +var ( + _ clientset.Interface = &Clientset{} + _ testing.FakeClient = &Clientset{} +) + +// VelaV1alpha1 retrieves the VelaV1alpha1Client +func (c *Clientset) VelaV1alpha1() velav1alpha1.VelaV1alpha1Interface { + return &fakevelav1alpha1.FakeVelaV1alpha1{Fake: &c.Fake} +} diff --git a/runtime/kubernetes/generated/clientset/versioned/fake/doc.go b/runtime/kubernetes/generated/clientset/versioned/fake/doc.go new file mode 100644 index 00000000..cdc483d7 --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/fake/doc.go @@ -0,0 +1,8 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated fake clientset. +package fake diff --git a/runtime/kubernetes/generated/clientset/versioned/fake/register.go b/runtime/kubernetes/generated/clientset/versioned/fake/register.go new file mode 100644 index 00000000..c8a5f06d --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/fake/register.go @@ -0,0 +1,44 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var scheme = runtime.NewScheme() +var codecs = serializer.NewCodecFactory(scheme) + +var localSchemeBuilder = runtime.SchemeBuilder{ + velav1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(scheme)) +} diff --git a/runtime/kubernetes/generated/clientset/versioned/scheme/doc.go b/runtime/kubernetes/generated/clientset/versioned/scheme/doc.go new file mode 100644 index 00000000..d7ba191f --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/scheme/doc.go @@ -0,0 +1,8 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/runtime/kubernetes/generated/clientset/versioned/scheme/register.go b/runtime/kubernetes/generated/clientset/versioned/scheme/register.go new file mode 100644 index 00000000..38f25139 --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/scheme/register.go @@ -0,0 +1,44 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +package scheme + +import ( + velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + velav1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/doc.go b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/doc.go new file mode 100644 index 00000000..fbb938d5 --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/doc.go @@ -0,0 +1,8 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake/doc.go b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake/doc.go new file mode 100644 index 00000000..df959f2f --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake/doc.go @@ -0,0 +1,8 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake/fake_pipelinepodstemplate.go b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake/fake_pipelinepodstemplate.go new file mode 100644 index 00000000..ade6f633 --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake/fake_pipelinepodstemplate.go @@ -0,0 +1,118 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakePipelinePodsTemplates implements PipelinePodsTemplateInterface +type FakePipelinePodsTemplates struct { + Fake *FakeVelaV1alpha1 + ns string +} + +var pipelinepodstemplatesResource = schema.GroupVersionResource{Group: "go-vela.github.io", Version: "v1alpha1", Resource: "pipelinepodstemplates"} + +var pipelinepodstemplatesKind = schema.GroupVersionKind{Group: "go-vela.github.io", Version: "v1alpha1", Kind: "PipelinePodsTemplate"} + +// Get takes name of the pipelinePodsTemplate, and returns the corresponding pipelinePodsTemplate object, and an error if there is any. +func (c *FakePipelinePodsTemplates) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PipelinePodsTemplate, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(pipelinepodstemplatesResource, c.ns, name), &v1alpha1.PipelinePodsTemplate{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PipelinePodsTemplate), err +} + +// List takes label and field selectors, and returns the list of PipelinePodsTemplates that match those selectors. +func (c *FakePipelinePodsTemplates) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PipelinePodsTemplateList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(pipelinepodstemplatesResource, pipelinepodstemplatesKind, c.ns, opts), &v1alpha1.PipelinePodsTemplateList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.PipelinePodsTemplateList{ListMeta: obj.(*v1alpha1.PipelinePodsTemplateList).ListMeta} + for _, item := range obj.(*v1alpha1.PipelinePodsTemplateList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested pipelinePodsTemplates. +func (c *FakePipelinePodsTemplates) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(pipelinepodstemplatesResource, c.ns, opts)) + +} + +// Create takes the representation of a pipelinePodsTemplate and creates it. Returns the server's representation of the pipelinePodsTemplate, and an error, if there is any. +func (c *FakePipelinePodsTemplates) Create(ctx context.Context, pipelinePodsTemplate *v1alpha1.PipelinePodsTemplate, opts v1.CreateOptions) (result *v1alpha1.PipelinePodsTemplate, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(pipelinepodstemplatesResource, c.ns, pipelinePodsTemplate), &v1alpha1.PipelinePodsTemplate{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PipelinePodsTemplate), err +} + +// Update takes the representation of a pipelinePodsTemplate and updates it. Returns the server's representation of the pipelinePodsTemplate, and an error, if there is any. +func (c *FakePipelinePodsTemplates) Update(ctx context.Context, pipelinePodsTemplate *v1alpha1.PipelinePodsTemplate, opts v1.UpdateOptions) (result *v1alpha1.PipelinePodsTemplate, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(pipelinepodstemplatesResource, c.ns, pipelinePodsTemplate), &v1alpha1.PipelinePodsTemplate{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PipelinePodsTemplate), err +} + +// Delete takes name of the pipelinePodsTemplate and deletes it. Returns an error if one occurs. +func (c *FakePipelinePodsTemplates) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(pipelinepodstemplatesResource, c.ns, name, opts), &v1alpha1.PipelinePodsTemplate{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakePipelinePodsTemplates) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(pipelinepodstemplatesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.PipelinePodsTemplateList{}) + return err +} + +// Patch applies the patch and returns the patched pipelinePodsTemplate. +func (c *FakePipelinePodsTemplates) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PipelinePodsTemplate, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(pipelinepodstemplatesResource, c.ns, name, pt, data, subresources...), &v1alpha1.PipelinePodsTemplate{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PipelinePodsTemplate), err +} diff --git a/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake/fake_vela_client.go b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake/fake_vela_client.go new file mode 100644 index 00000000..118423d6 --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/fake/fake_vela_client.go @@ -0,0 +1,28 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/go-vela/worker/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeVelaV1alpha1 struct { + *testing.Fake +} + +func (c *FakeVelaV1alpha1) PipelinePodsTemplates(namespace string) v1alpha1.PipelinePodsTemplateInterface { + return &FakePipelinePodsTemplates{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeVelaV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/generated_expansion.go b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/generated_expansion.go new file mode 100644 index 00000000..b1acc5a5 --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/generated_expansion.go @@ -0,0 +1,9 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type PipelinePodsTemplateExpansion interface{} diff --git a/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/pipelinepodstemplate.go b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/pipelinepodstemplate.go new file mode 100644 index 00000000..ed18f335 --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/pipelinepodstemplate.go @@ -0,0 +1,166 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" + scheme "github.com/go-vela/worker/runtime/kubernetes/generated/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// PipelinePodsTemplatesGetter has a method to return a PipelinePodsTemplateInterface. +// A group's client should implement this interface. +type PipelinePodsTemplatesGetter interface { + PipelinePodsTemplates(namespace string) PipelinePodsTemplateInterface +} + +// PipelinePodsTemplateInterface has methods to work with PipelinePodsTemplate resources. +type PipelinePodsTemplateInterface interface { + Create(ctx context.Context, pipelinePodsTemplate *v1alpha1.PipelinePodsTemplate, opts v1.CreateOptions) (*v1alpha1.PipelinePodsTemplate, error) + Update(ctx context.Context, pipelinePodsTemplate *v1alpha1.PipelinePodsTemplate, opts v1.UpdateOptions) (*v1alpha1.PipelinePodsTemplate, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.PipelinePodsTemplate, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.PipelinePodsTemplateList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PipelinePodsTemplate, err error) + PipelinePodsTemplateExpansion +} + +// pipelinePodsTemplates implements PipelinePodsTemplateInterface +type pipelinePodsTemplates struct { + client rest.Interface + ns string +} + +// newPipelinePodsTemplates returns a PipelinePodsTemplates +func newPipelinePodsTemplates(c *VelaV1alpha1Client, namespace string) *pipelinePodsTemplates { + return &pipelinePodsTemplates{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the pipelinePodsTemplate, and returns the corresponding pipelinePodsTemplate object, and an error if there is any. +func (c *pipelinePodsTemplates) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PipelinePodsTemplate, err error) { + result = &v1alpha1.PipelinePodsTemplate{} + err = c.client.Get(). + Namespace(c.ns). + Resource("pipelinepodstemplates"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of PipelinePodsTemplates that match those selectors. +func (c *pipelinePodsTemplates) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PipelinePodsTemplateList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.PipelinePodsTemplateList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("pipelinepodstemplates"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested pipelinePodsTemplates. +func (c *pipelinePodsTemplates) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("pipelinepodstemplates"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a pipelinePodsTemplate and creates it. Returns the server's representation of the pipelinePodsTemplate, and an error, if there is any. +func (c *pipelinePodsTemplates) Create(ctx context.Context, pipelinePodsTemplate *v1alpha1.PipelinePodsTemplate, opts v1.CreateOptions) (result *v1alpha1.PipelinePodsTemplate, err error) { + result = &v1alpha1.PipelinePodsTemplate{} + err = c.client.Post(). + Namespace(c.ns). + Resource("pipelinepodstemplates"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(pipelinePodsTemplate). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a pipelinePodsTemplate and updates it. Returns the server's representation of the pipelinePodsTemplate, and an error, if there is any. +func (c *pipelinePodsTemplates) Update(ctx context.Context, pipelinePodsTemplate *v1alpha1.PipelinePodsTemplate, opts v1.UpdateOptions) (result *v1alpha1.PipelinePodsTemplate, err error) { + result = &v1alpha1.PipelinePodsTemplate{} + err = c.client.Put(). + Namespace(c.ns). + Resource("pipelinepodstemplates"). + Name(pipelinePodsTemplate.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(pipelinePodsTemplate). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the pipelinePodsTemplate and deletes it. Returns an error if one occurs. +func (c *pipelinePodsTemplates) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("pipelinepodstemplates"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *pipelinePodsTemplates) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("pipelinepodstemplates"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched pipelinePodsTemplate. +func (c *pipelinePodsTemplates) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PipelinePodsTemplate, err error) { + result = &v1alpha1.PipelinePodsTemplate{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("pipelinepodstemplates"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/vela_client.go b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/vela_client.go new file mode 100644 index 00000000..425899ae --- /dev/null +++ b/runtime/kubernetes/generated/clientset/versioned/typed/vela/v1alpha1/vela_client.go @@ -0,0 +1,95 @@ +// Copyright (c) 2022 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "net/http" + + v1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" + "github.com/go-vela/worker/runtime/kubernetes/generated/clientset/versioned/scheme" + rest "k8s.io/client-go/rest" +) + +type VelaV1alpha1Interface interface { + RESTClient() rest.Interface + PipelinePodsTemplatesGetter +} + +// VelaV1alpha1Client is used to interact with features provided by the go-vela.github.io group. +type VelaV1alpha1Client struct { + restClient rest.Interface +} + +func (c *VelaV1alpha1Client) PipelinePodsTemplates(namespace string) PipelinePodsTemplateInterface { + return newPipelinePodsTemplates(c, namespace) +} + +// NewForConfig creates a new VelaV1alpha1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*VelaV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new VelaV1alpha1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*VelaV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &VelaV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new VelaV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *VelaV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new VelaV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *VelaV1alpha1Client { + return &VelaV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *VelaV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} From ed28cf6ac2e071e0f760771eea0278578c777282 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Mon, 21 Mar 2022 14:35:26 -0500 Subject: [PATCH 04/23] chore: Generate PipelinePodsTemplate CRD manifest --- runtime/kubernetes/apis/vela/v1alpha1/doc.go | 1 + .../kubernetes/apis/vela/v1alpha1/types.go | 3 + ...-vela.github.io_pipelinepodstemplates.yaml | 1148 +++++++++++++++++ 3 files changed, 1152 insertions(+) create mode 100644 runtime/kubernetes/generated/go-vela.github.io_pipelinepodstemplates.yaml diff --git a/runtime/kubernetes/apis/vela/v1alpha1/doc.go b/runtime/kubernetes/apis/vela/v1alpha1/doc.go index 1c293a5b..b0a6f8d1 100644 --- a/runtime/kubernetes/apis/vela/v1alpha1/doc.go +++ b/runtime/kubernetes/apis/vela/v1alpha1/doc.go @@ -3,6 +3,7 @@ // Use of this source code is governed by the LICENSE file in this repository. // +kubebuilder:object:generate=true +// +kubebuilder:validation:Optional // +groupName=go-vela.github.io // +groupGoName=Vela diff --git a/runtime/kubernetes/apis/vela/v1alpha1/types.go b/runtime/kubernetes/apis/vela/v1alpha1/types.go index fb1be1e7..f6f6d7b5 100644 --- a/runtime/kubernetes/apis/vela/v1alpha1/types.go +++ b/runtime/kubernetes/apis/vela/v1alpha1/types.go @@ -26,6 +26,7 @@ type PipelinePodsTemplate struct { // PipelinePodsTemplateSpec configures creation of Pipeline Pods by Vela Workers. type PipelinePodsTemplateSpec struct { // Template defines defaults for Pipeline Pod creation in Vela Workers. + // +kubebuilder:validation:Required Template PipelinePodTemplate `json:"template"` } @@ -64,6 +65,7 @@ type PipelinePodTemplateSpec struct { // DNSPolicy sets DNS policy for the pipeline pod. // Defaults to "ClusterFirst". // Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. + // +kubebuilder:validation:Enum={"ClusterFirstWithHostNet","ClusterFirst","Default","None"} DNSPolicy v1.DNSPolicy `json:"dnsPolicy,omitempty"` // DNSConfig specifies the DNS parameters of a pod. // Parameters specified here will be merged to the generated DNS @@ -117,5 +119,6 @@ type PipelinePodsTemplateList struct { metav1.ListMeta `json:"metadata,omitempty"` // Items is the list of Deployments. + // +kubebuilder:validation:Required Items []PipelinePodsTemplate `json:"items"` } diff --git a/runtime/kubernetes/generated/go-vela.github.io_pipelinepodstemplates.yaml b/runtime/kubernetes/generated/go-vela.github.io_pipelinepodstemplates.yaml new file mode 100644 index 00000000..76c68678 --- /dev/null +++ b/runtime/kubernetes/generated/go-vela.github.io_pipelinepodstemplates.yaml @@ -0,0 +1,1148 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.8.0 + creationTimestamp: null + name: pipelinepodstemplates.go-vela.github.io +spec: + group: go-vela.github.io + names: + kind: PipelinePodsTemplate + listKind: PipelinePodsTemplateList + plural: pipelinepodstemplates + singular: pipelinepodstemplate + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: PipelinePodsTemplate defines the config for a given worker. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the PipelinePodsTemplate configuration for Vela + Workers. + properties: + template: + description: Template defines defaults for Pipeline Pod creation in + Vela Workers. + properties: + metadata: + description: 'Meta contains a subset of the standard object metadata + (see: metav1.ObjectMeta).' + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is a key value map of strings to + store additional info on pods. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Labels is a key value map of strings to organize + and categorize pods. More info: http://kubernetes.io/docs/user-guide/labels' + type: object + type: object + spec: + description: 'Spec contains a subset of the pod configuration + options (see: v1.PodSpec).' + properties: + affinity: + description: Affinity specifies the pipeline pod's scheduling + constraints, if any. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + This field is beta-level and is only honored + when PodAffinityNamespaceSelector feature + is enabled. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. This + field is beta-level and is only honored when + PodAffinityNamespaceSelector feature is enabled. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + This field is beta-level and is only honored + when PodAffinityNamespaceSelector feature + is enabled. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. This + field is beta-level and is only honored when + PodAffinityNamespaceSelector feature is enabled. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + container: + description: Container defines a limited set of defaults to + apply to each PipelinePodsTemplate container. This is analogous + to one entry in v1.PodSpec.Containers. + properties: + securityContext: + description: 'SecurityContext defines the security options + the container should be run with. If set, the fields + of SecurityContext override the equivalent fields of + PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + capabilities: + description: Capabilities contains the capabilities + to add/drop when running containers. Defaults to + the default set of capabilities granted by the container + runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + type: object + type: object + dnsConfig: + description: DNSConfig specifies the DNS parameters of a pod. + Parameters specified here will be merged to the generated + DNS configuration based on DNSPolicy. + properties: + nameservers: + description: A list of DNS name server IP addresses. This + will be appended to the base nameservers generated from + DNSPolicy. Duplicated nameservers will be removed. + items: + type: string + type: array + options: + description: A list of DNS resolver options. This will + be merged with the base options generated from DNSPolicy. + Duplicated entries will be removed. Resolution options + given in Options will override those that appear in + the base DNSPolicy. + items: + description: PodDNSConfigOption defines DNS resolver + options of a pod. + properties: + name: + description: Required. + type: string + value: + type: string + type: object + type: array + searches: + description: A list of DNS search domains for host-name + lookup. This will be appended to the base search paths + generated from DNSPolicy. Duplicated search paths will + be removed. + items: + type: string + type: array + type: object + dnsPolicy: + description: DNSPolicy sets DNS policy for the pipeline pod. + Defaults to "ClusterFirst". Valid values are 'ClusterFirstWithHostNet', + 'ClusterFirst', 'Default' or 'None'. + enum: + - ClusterFirstWithHostNet + - ClusterFirst + - Default + - None + type: string + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true + for the pipeline pod to fit on a node. Selector which must + match a node''s labels for the pod to be scheduled on that + node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + x-kubernetes-map-type: atomic + securityContext: + description: 'SecurityContext holds pod-level security attributes + and common container settings. Optional: Defaults to empty. See + type description for default values of each field.' + properties: + runAsNonRoot: + description: RunAsNonRoot indicates that the container + must run as a non-root user. If true, the Kubelet will + validate the image at runtime to ensure that it does + not run as UID 0 (root) and fail to start the container + if it does. If unset or false, no such validation will + be performed. + type: boolean + sysctls: + description: Sysctls hold a list of namespaced sysctls + used for the pod. Pods with unsupported sysctls (by + the container runtime) might fail to launch. Note that + this field cannot be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be + set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + type: object + tolerations: + description: Affinity specifies the pipeline pod's tolerations, + if any. + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, + allowed values are NoSchedule, PreferNoSchedule and + NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. If the + key is empty, operator must be Exists; this combination + means to match all values and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and Equal. + Defaults to Equal. Exists is equivalent to wildcard + for value, so that a pod can tolerate all taints of + a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period + of time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the + taint forever (do not evict). Zero and negative values + will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the value should + be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + type: object + required: + - template + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] From 5dcb8a304e3c8b13f270063f1afaaee904c168a6 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Thu, 17 Mar 2022 17:07:29 -0500 Subject: [PATCH 05/23] feat(k8s): Add PipelinePodsTemplate loading opts --- cmd/vela-worker/exec.go | 2 ++ cmd/vela-worker/run.go | 2 ++ runtime/flags.go | 12 ++++++++++ runtime/kubernetes/kubernetes.go | 6 +++++ runtime/kubernetes/opts.go | 39 ++++++++++++++++++++++++++++++++ runtime/setup.go | 5 ++++ 6 files changed, 66 insertions(+) diff --git a/cmd/vela-worker/exec.go b/cmd/vela-worker/exec.go index 4f9d0c14..f369c27c 100644 --- a/cmd/vela-worker/exec.go +++ b/cmd/vela-worker/exec.go @@ -56,6 +56,8 @@ func (w *Worker) exec(index int) error { ConfigFile: w.Config.Runtime.ConfigFile, HostVolumes: w.Config.Runtime.HostVolumes, Namespace: w.Config.Runtime.Namespace, + PodsTemplateName: w.Config.Runtime.PodsTemplateName, + PodsTemplateFile: w.Config.Runtime.PodsTemplateFile, PrivilegedImages: w.Config.Runtime.PrivilegedImages, }) if err != nil { diff --git a/cmd/vela-worker/run.go b/cmd/vela-worker/run.go index 76ecb8a8..a709e27e 100644 --- a/cmd/vela-worker/run.go +++ b/cmd/vela-worker/run.go @@ -107,6 +107,8 @@ func run(c *cli.Context) error { Driver: c.String("runtime.driver"), ConfigFile: c.String("runtime.config"), Namespace: c.String("runtime.namespace"), + PodsTemplateName: c.String("runtime.pods-template-name"), + PodsTemplateFile: c.Path("runtime.pods-template-file"), HostVolumes: c.StringSlice("runtime.volumes"), PrivilegedImages: c.StringSlice("runtime.privileged-images"), }, diff --git a/runtime/flags.go b/runtime/flags.go index 9c2331b6..2d91a094 100644 --- a/runtime/flags.go +++ b/runtime/flags.go @@ -36,6 +36,18 @@ var Flags = []cli.Flag{ Name: "runtime.namespace", Usage: "namespace to use for the runtime (only used by kubernetes)", }, + &cli.StringFlag{ + EnvVars: []string{"VELA_RUNTIME_PODS_TEMPLATE_NAME", "RUNTIME_PODS_TEMPLATE_NAME"}, + FilePath: "/vela/runtime/pods-template-name", + Name: "runtime.pods-template-name", + Usage: "name of the PipelinePodsTemplate to retrieve from the runtime.namespace (only used by kubernetes)", + }, + &cli.PathFlag{ + EnvVars: []string{"VELA_RUNTIME_PODS_TEMPLATE_FILE", "RUNTIME_PODS_TEMPLATE_FILE"}, + FilePath: "/vela/runtime/pods-template-file", + Name: "runtime.pods-template-file", + Usage: "path to local fallback file containing a PipelinePodsTemplate in YAML (only used by kubernetes; only used if runtime.pods-template-name is not defined)", + }, &cli.StringSliceFlag{ EnvVars: []string{"VELA_RUNTIME_PRIVILEGED_IMAGES", "RUNTIME_PRIVILEGED_IMAGES"}, FilePath: "/vela/runtime/privileged_images", diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 99b27cf0..7c8c37c6 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -12,6 +12,8 @@ import ( "k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" + + velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" ) type config struct { @@ -23,6 +25,8 @@ type config struct { Images []string // specifies a list of host volumes to use for the Kubernetes client Volumes []string + // PipelinePodsTemplateName has the name of the PipelinePodTemplate to retrieve from the Namespace + PipelinePodsTemplateName string } type client struct { @@ -33,6 +37,8 @@ type client struct { Logger *logrus.Entry // https://pkg.go.dev/k8s.io/api/core/v1#Pod Pod *v1.Pod + // PipelinePodTemplate has default values to be used in Setup* methods + PipelinePodTemplate *velav1alpha1.PipelinePodTemplate // commonVolumeMounts includes workspace mount and any global host mounts (VELA_RUNTIME_VOLUMES) commonVolumeMounts []v1.VolumeMount // indicates when the pod has been created in kubernetes diff --git a/runtime/kubernetes/opts.go b/runtime/kubernetes/opts.go index ccfd09a6..f4ba638b 100644 --- a/runtime/kubernetes/opts.go +++ b/runtime/kubernetes/opts.go @@ -6,8 +6,12 @@ package kubernetes import ( "fmt" + "io/ioutil" + "github.com/buildkite/yaml" "github.com/sirupsen/logrus" + + velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" ) // ClientOpt represents a configuration option to initialize the runtime client for Kubernetes. @@ -69,6 +73,41 @@ func WithNamespace(namespace string) ClientOpt { } } +// WithPodsTemplate sets the PipelinePodsTemplateName or loads the PipelinePodsTemplate +// from file in the runtime client for Kubernetes. +func WithPodsTemplate(name string, path string) ClientOpt { + return func(c *client) error { + c.Logger.Trace("configuring pipeline pods template in kubernetes runtime client") + + // check if a PipelinePodsTemplate was requested + if len(name) == 0 && len(path) == 0 { + // no PipelinePodTemplate to load + return nil + } + + if len(name) == 0 { + // load the PodsTemplate from the path (must restart Worker to reload the local file) + if data, err := ioutil.ReadFile(path); err == nil { + pipelinePodsTemplate := velav1alpha1.PipelinePodsTemplate{} + + err := yaml.Unmarshal(data, pipelinePodsTemplate) + if err != nil { + return err + } + + c.PipelinePodTemplate = &pipelinePodsTemplate.Spec.Template + } + + return nil + } + + // set the runtime namespace in the kubernetes client for just-in-time retrieval + c.config.PipelinePodsTemplateName = name + + return nil + } +} + // WithPrivilegedImages sets the privileged images in the runtime client for Kubernetes. func WithPrivilegedImages(images []string) ClientOpt { return func(c *client) error { diff --git a/runtime/setup.go b/runtime/setup.go index 06a344f5..3a88c75a 100644 --- a/runtime/setup.go +++ b/runtime/setup.go @@ -32,6 +32,10 @@ type Setup struct { HostVolumes []string // specifies the namespace to use for the runtime client (only used by kubernetes) Namespace string + // specifies the name of the PipelinePodsTemplate to retrieve from the given namespace (only used by kubernetes) + PodsTemplateName string + // specifies the fallback path of a PipelinePodsTemplate in a local YAML file (only used by kubernetes; only used if PodsTemplateName not defined) + PodsTemplateFile string // specifies a list of privileged images to use for the runtime client PrivilegedImages []string } @@ -63,6 +67,7 @@ func (s *Setup) Kubernetes() (Engine, error) { kubernetes.WithConfigFile(s.ConfigFile), kubernetes.WithHostVolumes(s.HostVolumes), kubernetes.WithNamespace(s.Namespace), + kubernetes.WithPodsTemplate(s.PodsTemplateName, s.PodsTemplateFile), kubernetes.WithPrivilegedImages(s.PrivilegedImages), kubernetes.WithLogger(s.Logger), ) From 7d7f1e91374ae38ab0ad7b802ae9459894d87b42 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Thu, 17 Mar 2022 22:55:22 -0500 Subject: [PATCH 06/23] feat(k8s): Get PipelinePodsTemplate from k8s API --- runtime/kubernetes/build.go | 18 ++++++++++++++++++ runtime/kubernetes/kubernetes.go | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/runtime/kubernetes/build.go b/runtime/kubernetes/build.go index d2fa7171..9647a548 100644 --- a/runtime/kubernetes/build.go +++ b/runtime/kubernetes/build.go @@ -9,6 +9,7 @@ import ( "fmt" "github.com/go-vela/types/pipeline" + "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" "github.com/buildkite/yaml" v1 "k8s.io/api/core/v1" @@ -39,6 +40,23 @@ func (c *client) InspectBuild(ctx context.Context, b *pipeline.Build) ([]byte, e func (c *client) SetupBuild(ctx context.Context, b *pipeline.Build) error { c.Logger.Tracef("setting up for build %s", b.ID) + if c.PipelinePodTemplate == nil { + if len(c.config.PipelinePodsTemplateName) > 0 { + // nolint: contextcheck // ignore non-inherited new context + podsTemplateResponse, err := c.VelaKubernetes.VelaV1alpha1().PipelinePodsTemplates(c.config.Namespace).Get( + context.Background(), c.config.PipelinePodsTemplateName, metav1.GetOptions{}, + ) + if err != nil { + return err + } + + // save the PipelinePodTemplate to use later in SetupContainer and other Setup methods + c.PipelinePodTemplate = &podsTemplateResponse.Spec.Template + } else { + c.PipelinePodTemplate = &v1alpha1.PipelinePodTemplate{} + } + } + // create the object metadata for the pod // // https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1?tab=doc#ObjectMeta diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 7c8c37c6..4adffbb2 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -14,6 +14,7 @@ import ( "k8s.io/client-go/tools/clientcmd" velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" + velaK8sClient "github.com/go-vela/worker/runtime/kubernetes/generated/clientset/versioned" ) type config struct { @@ -33,6 +34,8 @@ type client struct { config *config // https://pkg.go.dev/k8s.io/client-go/kubernetes#Interface Kubernetes kubernetes.Interface + // VelaKubernetes is a client for custom Vela CRD-based APIs + VelaKubernetes velaK8sClient.Interface // https://pkg.go.dev/github.com/sirupsen/logrus#Entry Logger *logrus.Entry // https://pkg.go.dev/k8s.io/api/core/v1#Pod @@ -110,6 +113,15 @@ func New(opts ...ClientOpt) (*client, error) { // set the Kubernetes client in the runtime client c.Kubernetes = _kubernetes + // creates VelaKubernetes client from configuration + _velaKubernetes, err := velaK8sClient.NewForConfig(config) + if err != nil { + return nil, err + } + + // set the VelaKubernetes client in the runtime client + c.VelaKubernetes = _velaKubernetes + return c, nil } From 020421aba916a3406e372da1cd45bbf26547bcc8 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Thu, 17 Mar 2022 01:25:04 -0500 Subject: [PATCH 07/23] feat(k8s): Get defaults from PipelinePodTemplate --- runtime/kubernetes/build.go | 57 ++++++++++++++++++++++++++++++--- runtime/kubernetes/container.go | 22 +++++++++---- 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/runtime/kubernetes/build.go b/runtime/kubernetes/build.go index 9647a548..d9e1e77f 100644 --- a/runtime/kubernetes/build.go +++ b/runtime/kubernetes/build.go @@ -57,22 +57,71 @@ func (c *client) SetupBuild(ctx context.Context, b *pipeline.Build) error { } } + // These labels will be used to call k8s watch APIs. + labels := map[string]string{"pipeline": b.ID} + + if c.PipelinePodTemplate.Meta.Labels != nil { + // merge the template labels into the worker-defined labels. + for k, v := range c.PipelinePodTemplate.Meta.Labels { + // do not allow overwriting any of the worker-defined labels. + if _, ok := labels[k]; ok { + continue + } + + labels[k] = v + } + } + // create the object metadata for the pod // // https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1?tab=doc#ObjectMeta c.Pod.ObjectMeta = metav1.ObjectMeta{ - Name: b.ID, - Labels: map[string]string{"pipeline": b.ID}, + Name: b.ID, + Labels: labels, + Annotations: c.PipelinePodTemplate.Meta.Annotations, } - // TODO: Vela admin defined worker-specific: - // NodeSelector, Tolerations, Affinity, AutomountServiceAccountToken + // TODO: Vela admin defined worker-specific: AutomountServiceAccountToken + + if c.PipelinePodTemplate.Spec.NodeSelector != nil { + c.Pod.Spec.NodeSelector = c.PipelinePodTemplate.Spec.NodeSelector + } + + if c.PipelinePodTemplate.Spec.Tolerations != nil { + c.Pod.Spec.Tolerations = c.PipelinePodTemplate.Spec.Tolerations + } + + if c.PipelinePodTemplate.Spec.Affinity != nil { + c.Pod.Spec.Affinity = c.PipelinePodTemplate.Spec.Affinity + } // create the restart policy for the pod // // https://pkg.go.dev/k8s.io/api/core/v1?tab=doc#RestartPolicy c.Pod.Spec.RestartPolicy = v1.RestartPolicyNever + if len(c.PipelinePodTemplate.Spec.DNSPolicy) > 0 { + c.Pod.Spec.DNSPolicy = c.PipelinePodTemplate.Spec.DNSPolicy + } + + if c.PipelinePodTemplate.Spec.DNSConfig != nil { + c.Pod.Spec.DNSConfig = c.PipelinePodTemplate.Spec.DNSConfig + } + + if c.PipelinePodTemplate.Spec.SecurityContext != nil { + if c.Pod.Spec.SecurityContext == nil { + c.Pod.Spec.SecurityContext = &v1.PodSecurityContext{} + } + + if c.PipelinePodTemplate.Spec.SecurityContext.RunAsNonRoot != nil { + c.Pod.Spec.SecurityContext.RunAsNonRoot = c.PipelinePodTemplate.Spec.SecurityContext.RunAsNonRoot + } + + if c.PipelinePodTemplate.Spec.SecurityContext.Sysctls != nil { + c.Pod.Spec.SecurityContext.Sysctls = c.PipelinePodTemplate.Spec.SecurityContext.Sysctls + } + } + return nil } diff --git a/runtime/kubernetes/container.go b/runtime/kubernetes/container.go index d40c1a9c..7c2cc319 100644 --- a/runtime/kubernetes/container.go +++ b/runtime/kubernetes/container.go @@ -122,12 +122,13 @@ func (c *client) SetupContainer(ctx context.Context, ctn *pipeline.Container) er // the containers with the proper image. // // https://hub.docker.com/r/kubernetes/pause - Image: image.Parse("kubernetes/pause:latest"), - Env: []v1.EnvVar{}, - Stdin: false, - StdinOnce: false, - TTY: false, - WorkingDir: ctn.Directory, + Image: image.Parse("kubernetes/pause:latest"), + Env: []v1.EnvVar{}, + Stdin: false, + StdinOnce: false, + TTY: false, + WorkingDir: ctn.Directory, + SecurityContext: &v1.SecurityContext{}, } // handle the container pull policy (This cannot be updated like the image can) @@ -172,7 +173,14 @@ func (c *client) SetupContainer(ctx context.Context, ctn *pipeline.Container) er } } - // TODO: add SecurityContext options (runAsUser, runAsNonRoot, sysctls) + if c.PipelinePodTemplate != nil && c.PipelinePodTemplate.Spec.Container != nil { + securityContext := c.PipelinePodTemplate.Spec.Container.SecurityContext + + // TODO: add more SecurityContext options (runAsUser, runAsNonRoot, sysctls) + if securityContext != nil && securityContext.Capabilities != nil { + container.SecurityContext.Capabilities = securityContext.Capabilities + } + } // Executor.CreateBuild extends the environment AFTER calling Runtime.SetupBuild. // So, configure the environment as late as possible (just before pod creation). From 7c261a262645f2c64ccd75ef26a91207802c61a5 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Tue, 22 Mar 2022 19:57:15 -0500 Subject: [PATCH 08/23] chore: Add tests for runtime WithPodsTemplate opt This identified a few bugs including: - need to yaml.Unmarshall to a ptr - yaml.Unmarshall needs "Metadata" instead of "Meta" struct field --- .../kubernetes/apis/vela/v1alpha1/types.go | 4 +- .../vela/v1alpha1/zz_generated.deepcopy.go | 2 +- runtime/kubernetes/build.go | 6 +- ...-vela.github.io_pipelinepodstemplates.yaml | 4 +- runtime/kubernetes/opts.go | 2 +- runtime/kubernetes/opts_test.go | 83 +++++++++++++++++++ .../pipeline-pods-template-empty.yaml | 6 ++ .../testdata/pipeline-pods-template.yaml | 11 +++ 8 files changed, 109 insertions(+), 9 deletions(-) create mode 100644 runtime/kubernetes/testdata/pipeline-pods-template-empty.yaml create mode 100644 runtime/kubernetes/testdata/pipeline-pods-template.yaml diff --git a/runtime/kubernetes/apis/vela/v1alpha1/types.go b/runtime/kubernetes/apis/vela/v1alpha1/types.go index f6f6d7b5..36a4de38 100644 --- a/runtime/kubernetes/apis/vela/v1alpha1/types.go +++ b/runtime/kubernetes/apis/vela/v1alpha1/types.go @@ -32,8 +32,8 @@ type PipelinePodsTemplateSpec struct { // PipelinePodTemplate describes the data defaults to use when creating each pipeline pod. type PipelinePodTemplate struct { - // Meta contains a subset of the standard object metadata (see: metav1.ObjectMeta). - Meta PipelinePodTemplateMeta `json:"metadata,omitempty"` + // Metadata contains a subset of the standard object metadata (see: metav1.ObjectMeta). + Metadata PipelinePodTemplateMeta `json:"metadata,omitempty"` // Spec contains a subset of the pod configuration options (see: v1.PodSpec). Spec PipelinePodTemplateSpec `json:"spec,omitempty"` diff --git a/runtime/kubernetes/apis/vela/v1alpha1/zz_generated.deepcopy.go b/runtime/kubernetes/apis/vela/v1alpha1/zz_generated.deepcopy.go index 7c29b647..ab2a4fa1 100644 --- a/runtime/kubernetes/apis/vela/v1alpha1/zz_generated.deepcopy.go +++ b/runtime/kubernetes/apis/vela/v1alpha1/zz_generated.deepcopy.go @@ -82,7 +82,7 @@ func (in *PipelinePodSecurityContext) DeepCopy() *PipelinePodSecurityContext { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PipelinePodTemplate) DeepCopyInto(out *PipelinePodTemplate) { *out = *in - in.Meta.DeepCopyInto(&out.Meta) + in.Metadata.DeepCopyInto(&out.Metadata) in.Spec.DeepCopyInto(&out.Spec) } diff --git a/runtime/kubernetes/build.go b/runtime/kubernetes/build.go index d9e1e77f..32c44273 100644 --- a/runtime/kubernetes/build.go +++ b/runtime/kubernetes/build.go @@ -60,9 +60,9 @@ func (c *client) SetupBuild(ctx context.Context, b *pipeline.Build) error { // These labels will be used to call k8s watch APIs. labels := map[string]string{"pipeline": b.ID} - if c.PipelinePodTemplate.Meta.Labels != nil { + if c.PipelinePodTemplate.Metadata.Labels != nil { // merge the template labels into the worker-defined labels. - for k, v := range c.PipelinePodTemplate.Meta.Labels { + for k, v := range c.PipelinePodTemplate.Metadata.Labels { // do not allow overwriting any of the worker-defined labels. if _, ok := labels[k]; ok { continue @@ -78,7 +78,7 @@ func (c *client) SetupBuild(ctx context.Context, b *pipeline.Build) error { c.Pod.ObjectMeta = metav1.ObjectMeta{ Name: b.ID, Labels: labels, - Annotations: c.PipelinePodTemplate.Meta.Annotations, + Annotations: c.PipelinePodTemplate.Metadata.Annotations, } // TODO: Vela admin defined worker-specific: AutomountServiceAccountToken diff --git a/runtime/kubernetes/generated/go-vela.github.io_pipelinepodstemplates.yaml b/runtime/kubernetes/generated/go-vela.github.io_pipelinepodstemplates.yaml index 76c68678..bc938146 100644 --- a/runtime/kubernetes/generated/go-vela.github.io_pipelinepodstemplates.yaml +++ b/runtime/kubernetes/generated/go-vela.github.io_pipelinepodstemplates.yaml @@ -41,8 +41,8 @@ spec: Vela Workers. properties: metadata: - description: 'Meta contains a subset of the standard object metadata - (see: metav1.ObjectMeta).' + description: 'Metadata contains a subset of the standard object + metadata (see: metav1.ObjectMeta).' properties: annotations: additionalProperties: diff --git a/runtime/kubernetes/opts.go b/runtime/kubernetes/opts.go index f4ba638b..386b8d82 100644 --- a/runtime/kubernetes/opts.go +++ b/runtime/kubernetes/opts.go @@ -90,7 +90,7 @@ func WithPodsTemplate(name string, path string) ClientOpt { if data, err := ioutil.ReadFile(path); err == nil { pipelinePodsTemplate := velav1alpha1.PipelinePodsTemplate{} - err := yaml.Unmarshal(data, pipelinePodsTemplate) + err := yaml.Unmarshal(data, &pipelinePodsTemplate) if err != nil { return err } diff --git a/runtime/kubernetes/opts_test.go b/runtime/kubernetes/opts_test.go index aaff223d..ba7941e5 100644 --- a/runtime/kubernetes/opts_test.go +++ b/runtime/kubernetes/opts_test.go @@ -7,6 +7,8 @@ package kubernetes import ( "reflect" "testing" + + velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" ) func TestKubernetes_ClientOpt_WithConfigFile(t *testing.T) { @@ -161,3 +163,84 @@ func TestKubernetes_ClientOpt_WithPrivilegedImages(t *testing.T) { } } } + +func TestKubernetes_ClientOpt_WithPodsTemplate(t *testing.T) { + // setup tests + tests := []struct { + failure bool + podsTemplateName string + podsTemplatePath string + wantName string + wantTemplate *velav1alpha1.PipelinePodTemplate + }{ + { + failure: false, + podsTemplateName: "foo-bar-name", + podsTemplatePath: "", + wantName: "foo-bar-name", + wantTemplate: nil, + }, + { + failure: false, + podsTemplateName: "", + podsTemplatePath: "", + wantName: "", + wantTemplate: nil, + }, + { + failure: false, // ignores missing files; can be added later + podsTemplateName: "", + podsTemplatePath: "testdata/does-not-exist.yaml", + wantName: "", + wantTemplate: nil, + }, + { + failure: false, + podsTemplateName: "", + podsTemplatePath: "testdata/pipeline-pods-template-empty.yaml", + wantName: "", + wantTemplate: &velav1alpha1.PipelinePodTemplate{}, + }, + { + failure: false, + podsTemplateName: "", + podsTemplatePath: "testdata/pipeline-pods-template.yaml", + wantName: "", + wantTemplate: &velav1alpha1.PipelinePodTemplate{ + Metadata: velav1alpha1.PipelinePodTemplateMeta{ + Annotations: map[string]string{"annotation/foo": "bar"}, + Labels: map[string]string{"foo": "bar"}, + }, + }, + }, + } + + // run tests + for _, test := range tests { + _engine, err := New( + WithConfigFile("testdata/config"), + WithNamespace("foo"), + WithPodsTemplate(test.podsTemplateName, test.podsTemplatePath), + ) + + if test.failure { + if err == nil { + t.Errorf("WithPodsTemplate should have returned err") + } + + continue + } + + if err != nil { + t.Errorf("WithPodsTemplate returned err: %v", err) + } + + if !reflect.DeepEqual(_engine.config.PipelinePodsTemplateName, test.wantName) { + t.Errorf("WithPodsTemplate is %v, wantName %v", _engine.config.PipelinePodsTemplateName, test.wantName) + } + + if test.wantTemplate != nil && !reflect.DeepEqual(_engine.PipelinePodTemplate, test.wantTemplate) { + t.Errorf("WithPodsTemplate is %v, wantTemplate %v", _engine.PipelinePodTemplate, test.wantTemplate) + } + } +} diff --git a/runtime/kubernetes/testdata/pipeline-pods-template-empty.yaml b/runtime/kubernetes/testdata/pipeline-pods-template-empty.yaml new file mode 100644 index 00000000..d88e996e --- /dev/null +++ b/runtime/kubernetes/testdata/pipeline-pods-template-empty.yaml @@ -0,0 +1,6 @@ +apiVersion: "go-vela.github.io/v1alpha1" +kind: PipelinePodsTemplate +metadata: + name: pipeline-pods-template-empty +spec: + template: {} diff --git a/runtime/kubernetes/testdata/pipeline-pods-template.yaml b/runtime/kubernetes/testdata/pipeline-pods-template.yaml new file mode 100644 index 00000000..5cdd329e --- /dev/null +++ b/runtime/kubernetes/testdata/pipeline-pods-template.yaml @@ -0,0 +1,11 @@ +apiVersion: "go-vela.github.io/v1alpha1" +kind: PipelinePodsTemplate +metadata: + name: pipeline-pods-template +spec: + template: + metadata: + annotations: + annotation/foo: bar + labels: + foo: bar From f5837d7067b6fb07ef1d6f3eec662b95fb4de1a6 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Tue, 22 Mar 2022 20:06:28 -0500 Subject: [PATCH 09/23] chore: Add tests for runtime WithPodsTemplate opt (failure path) --- runtime/kubernetes/opts_test.go | 7 +++++++ .../testdata/pipeline-pods-template-malformed.yaml | 11 +++++++++++ 2 files changed, 18 insertions(+) create mode 100644 runtime/kubernetes/testdata/pipeline-pods-template-malformed.yaml diff --git a/runtime/kubernetes/opts_test.go b/runtime/kubernetes/opts_test.go index ba7941e5..56193cf2 100644 --- a/runtime/kubernetes/opts_test.go +++ b/runtime/kubernetes/opts_test.go @@ -213,6 +213,13 @@ func TestKubernetes_ClientOpt_WithPodsTemplate(t *testing.T) { }, }, }, + { + failure: true, + podsTemplateName: "", + podsTemplatePath: "testdata/pipeline-pods-template-malformed.yaml", + wantName: "", + wantTemplate: nil, + }, } // run tests diff --git a/runtime/kubernetes/testdata/pipeline-pods-template-malformed.yaml b/runtime/kubernetes/testdata/pipeline-pods-template-malformed.yaml new file mode 100644 index 00000000..79f003c4 --- /dev/null +++ b/runtime/kubernetes/testdata/pipeline-pods-template-malformed.yaml @@ -0,0 +1,11 @@ +apiVersion: "go-vela.github.io/v1alpha1" +kind: PipelinePodsTemplate +metadata: + name: pipeline-pods-template +spec: + template: + metadata: + annotations: + # annotations is a map[string]string, so this is malformed. + - name: annotation/foo + value: bar From 040cbae44f6fac4c075362007df5514893ea1da9 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Tue, 22 Mar 2022 20:36:44 -0500 Subject: [PATCH 10/23] chore: Extend k8s SetupBuild test to use WithPodsTemplate --- runtime/kubernetes/build_test.go | 35 ++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/runtime/kubernetes/build_test.go b/runtime/kubernetes/build_test.go index bec9ac11..7d72e292 100644 --- a/runtime/kubernetes/build_test.go +++ b/runtime/kubernetes/build_test.go @@ -54,29 +54,52 @@ func TestKubernetes_InspectBuild(t *testing.T) { } func TestKubernetes_SetupBuild(t *testing.T) { - // setup types - _engine, err := NewMock(&v1.Pod{}) - if err != nil { - t.Errorf("unable to create runtime engine: %v", err) - } - // setup tests tests := []struct { failure bool pipeline *pipeline.Build + opts []ClientOpt }{ { failure: false, pipeline: _stages, + opts: nil, + }, + { + failure: false, + pipeline: _steps, + opts: nil, + }, + { + failure: false, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-empty.yaml")}, }, { failure: false, pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-empty.yaml")}, + }, + { + failure: false, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template.yaml")}, + }, + { + failure: false, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template.yaml")}, }, } // run tests for _, test := range tests { + // setup types + _engine, err := NewMock(&v1.Pod{}, test.opts...) + if err != nil { + t.Errorf("unable to create runtime engine: %v", err) + } + err = _engine.SetupBuild(context.Background(), test.pipeline) // this does not test the resulting pod spec (ie no tests for ObjectMeta, RestartPolicy) From f8b4d5f35d1389b31ca14c73542bcdb6391244cb Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Tue, 22 Mar 2022 21:00:09 -0500 Subject: [PATCH 11/23] chore: Extend k8s SetupBuild test PipelinePodsTemplate missing in k8s --- runtime/kubernetes/build_test.go | 10 ++++++++++ runtime/kubernetes/kubernetes.go | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/runtime/kubernetes/build_test.go b/runtime/kubernetes/build_test.go index 7d72e292..57a51e5c 100644 --- a/runtime/kubernetes/build_test.go +++ b/runtime/kubernetes/build_test.go @@ -90,6 +90,16 @@ func TestKubernetes_SetupBuild(t *testing.T) { pipeline: _steps, opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template.yaml")}, }, + { + failure: true, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("missing-pipeline-pods-template", "")}, + }, + { + failure: true, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("missing-pipeline-pods-template", "")}, + }, } // run tests diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 4adffbb2..78744a61 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -15,6 +15,7 @@ import ( velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" velaK8sClient "github.com/go-vela/worker/runtime/kubernetes/generated/clientset/versioned" + fakeVelaK8sClient "github.com/go-vela/worker/runtime/kubernetes/generated/clientset/versioned/fake" ) type config struct { @@ -168,5 +169,8 @@ func NewMock(_pod *v1.Pod, opts ...ClientOpt) (*client, error) { // https://pkg.go.dev/k8s.io/client-go/kubernetes/fake?tab=doc#NewSimpleClientset c.Kubernetes = fake.NewSimpleClientset(c.Pod) + // set the VelaKubernetes fake client in the runtime client + c.VelaKubernetes = fakeVelaK8sClient.NewSimpleClientset() + return c, nil } From 1552e6ef4951208e0daa124370ec181d0b7d5805 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Tue, 22 Mar 2022 21:27:09 -0500 Subject: [PATCH 12/23] chore: Extend k8s SetupBuild test with mocked PipelinePodsTemplate in k8s --- runtime/kubernetes/build_test.go | 10 ++++++++++ runtime/kubernetes/kubernetes.go | 10 +++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/runtime/kubernetes/build_test.go b/runtime/kubernetes/build_test.go index 57a51e5c..4c47607e 100644 --- a/runtime/kubernetes/build_test.go +++ b/runtime/kubernetes/build_test.go @@ -90,6 +90,16 @@ func TestKubernetes_SetupBuild(t *testing.T) { pipeline: _steps, opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template.yaml")}, }, + { + failure: false, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("mock-pipeline-pods-template", "")}, + }, + { + failure: false, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("mock-pipeline-pods-template", "")}, + }, { failure: true, pipeline: _stages, diff --git a/runtime/kubernetes/kubernetes.go b/runtime/kubernetes/kubernetes.go index 78744a61..9846bbd0 100644 --- a/runtime/kubernetes/kubernetes.go +++ b/runtime/kubernetes/kubernetes.go @@ -6,6 +6,7 @@ package kubernetes import ( "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes" @@ -170,7 +171,14 @@ func NewMock(_pod *v1.Pod, opts ...ClientOpt) (*client, error) { c.Kubernetes = fake.NewSimpleClientset(c.Pod) // set the VelaKubernetes fake client in the runtime client - c.VelaKubernetes = fakeVelaK8sClient.NewSimpleClientset() + c.VelaKubernetes = fakeVelaK8sClient.NewSimpleClientset( + &velav1alpha1.PipelinePodsTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: c.config.Namespace, + Name: "mock-pipeline-pods-template", + }, + }, + ) return c, nil } From 670320289d759fc47df456de23f9fe472958f780 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Wed, 23 Mar 2022 09:06:57 -0500 Subject: [PATCH 13/23] fix(kubernetes): use sigs.k8s.io/yaml instead of buildkite/yaml --- go.mod | 4 ++-- runtime/kubernetes/build.go | 5 ++++- runtime/kubernetes/opts.go | 6 +++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index b6535e70..d0b5c7ff 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.17 require ( github.com/Masterminds/semver/v3 v3.1.1 - github.com/buildkite/yaml v0.0.0-20181016232759-0caa5f0796e3 github.com/docker/distribution v2.8.1+incompatible github.com/docker/docker v20.10.10+incompatible github.com/docker/go-units v0.4.0 @@ -23,6 +22,7 @@ require ( k8s.io/api v0.23.5 k8s.io/apimachinery v0.23.5 k8s.io/client-go v0.23.5 + sigs.k8s.io/yaml v1.2.0 ) require ( @@ -34,6 +34,7 @@ require ( github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect github.com/alicebob/miniredis/v2 v2.18.0 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/buildkite/yaml v0.0.0-20181016232759-0caa5f0796e3 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/containerd/containerd v1.4.13 // indirect github.com/coreos/go-semver v0.3.0 // indirect @@ -107,5 +108,4 @@ require ( k8s.io/utils v0.0.0-20211116205334-6203023598ed // indirect sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect - sigs.k8s.io/yaml v1.2.0 // indirect ) diff --git a/runtime/kubernetes/build.go b/runtime/kubernetes/build.go index 32c44273..66ca3cd4 100644 --- a/runtime/kubernetes/build.go +++ b/runtime/kubernetes/build.go @@ -11,9 +11,12 @@ import ( "github.com/go-vela/types/pipeline" "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" - "github.com/buildkite/yaml" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + // The k8s libraries have some quirks around yaml marshalling (see opts.go). + // So, just use the same library for all kubernetes-related YAML. + "sigs.k8s.io/yaml" ) // InspectBuild displays details about the pod for the init step. diff --git a/runtime/kubernetes/opts.go b/runtime/kubernetes/opts.go index 386b8d82..b1d302b5 100644 --- a/runtime/kubernetes/opts.go +++ b/runtime/kubernetes/opts.go @@ -8,9 +8,13 @@ import ( "fmt" "io/ioutil" - "github.com/buildkite/yaml" "github.com/sirupsen/logrus" + // The k8s libraries have some quirks around yaml marshalling. + // They use `json` instead of `yaml` to annotate their struct Tags. + // So, we need to use "sigs.k8s.io/yaml" instead of "github.com/buildkite/yaml" + "sigs.k8s.io/yaml" + velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" ) From 77ed714ff51828c65af0baae480e82ca5c6f4095 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Wed, 23 Mar 2022 09:09:51 -0500 Subject: [PATCH 14/23] feat(kubernetes): ensure local PipelinePodsTemplate YAML is valid Use yaml.UnmarshallStrict so that typos are not silently ignored. This comes from typos I made while writing the SecurityContext tests. --- runtime/kubernetes/build_test.go | 10 ++++++++ runtime/kubernetes/container_test.go | 21 ++++++++++++----- runtime/kubernetes/opts.go | 2 +- ...peline-pods-template-security-context.yaml | 23 +++++++++++++++++++ 4 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 runtime/kubernetes/testdata/pipeline-pods-template-security-context.yaml diff --git a/runtime/kubernetes/build_test.go b/runtime/kubernetes/build_test.go index 4c47607e..47f425c7 100644 --- a/runtime/kubernetes/build_test.go +++ b/runtime/kubernetes/build_test.go @@ -90,6 +90,16 @@ func TestKubernetes_SetupBuild(t *testing.T) { pipeline: _steps, opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template.yaml")}, }, + { + failure: false, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-security-context.yaml")}, + }, + { + failure: false, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-security-context.yaml")}, + }, { failure: false, pipeline: _stages, diff --git a/runtime/kubernetes/container_test.go b/runtime/kubernetes/container_test.go index 46a53950..02850cb4 100644 --- a/runtime/kubernetes/container_test.go +++ b/runtime/kubernetes/container_test.go @@ -143,20 +143,16 @@ func TestKubernetes_RunContainer(t *testing.T) { } func TestKubernetes_SetupContainer(t *testing.T) { - // setup types - _engine, err := NewMock(_pod) - if err != nil { - t.Errorf("unable to create runtime engine: %v", err) - } - // setup tests tests := []struct { failure bool container *pipeline.Container + opts []ClientOpt }{ { failure: false, container: _container, + opts: nil, }, { failure: false, @@ -171,6 +167,7 @@ func TestKubernetes_SetupContainer(t *testing.T) { Number: 2, Pull: "always", }, + opts: nil, }, { failure: false, @@ -185,11 +182,23 @@ func TestKubernetes_SetupContainer(t *testing.T) { Number: 2, Pull: "always", }, + opts: nil, + }, + { + failure: false, + container: _container, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-security-context.yaml")}, }, } // run tests for _, test := range tests { + // setup types + _engine, err := NewMock(_pod, test.opts...) + if err != nil { + t.Errorf("unable to create runtime engine: %v", err) + } + err = _engine.SetupContainer(context.Background(), test.container) // this does not test the resulting pod spec (ie no tests for ImagePullPolicy, VolumeMounts) diff --git a/runtime/kubernetes/opts.go b/runtime/kubernetes/opts.go index b1d302b5..62caa29d 100644 --- a/runtime/kubernetes/opts.go +++ b/runtime/kubernetes/opts.go @@ -94,7 +94,7 @@ func WithPodsTemplate(name string, path string) ClientOpt { if data, err := ioutil.ReadFile(path); err == nil { pipelinePodsTemplate := velav1alpha1.PipelinePodsTemplate{} - err := yaml.Unmarshal(data, &pipelinePodsTemplate) + err := yaml.UnmarshalStrict(data, &pipelinePodsTemplate) if err != nil { return err } diff --git a/runtime/kubernetes/testdata/pipeline-pods-template-security-context.yaml b/runtime/kubernetes/testdata/pipeline-pods-template-security-context.yaml new file mode 100644 index 00000000..2ba87113 --- /dev/null +++ b/runtime/kubernetes/testdata/pipeline-pods-template-security-context.yaml @@ -0,0 +1,23 @@ +apiVersion: "go-vela.github.io/v1alpha1" +kind: PipelinePodsTemplate +metadata: + name: pipeline-pods-template +spec: + template: + spec: + securityContext: + runAsNonRoot: true + sysctls: + # https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ + - name: kernel.shm_rmid_forced + value: "0" + - name: net.core.somaxconn + value: "1024" + - name: kernel.msgmax + value: "65536" + container: + securityContext: + capabilities: + # https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-capabilities-for-a-container + drop: ["ALL"] + add: ["NET_ADMIN","SYS_TIME"] From e7ca84a8def6c9b677681ee32ab1b0098146e3bb Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Wed, 23 Mar 2022 10:18:09 -0500 Subject: [PATCH 15/23] chore: test ignoring k8s labels from PipelinePodsTemplate only ignores if they are defined by the runtime itself. --- runtime/kubernetes/opts_test.go | 5 ++++- runtime/kubernetes/testdata/pipeline-pods-template.yaml | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/runtime/kubernetes/opts_test.go b/runtime/kubernetes/opts_test.go index 24375434..cf17624c 100644 --- a/runtime/kubernetes/opts_test.go +++ b/runtime/kubernetes/opts_test.go @@ -256,7 +256,10 @@ func TestKubernetes_ClientOpt_WithPodsTemplate(t *testing.T) { wantTemplate: &velav1alpha1.PipelinePodTemplate{ Metadata: velav1alpha1.PipelinePodTemplateMeta{ Annotations: map[string]string{"annotation/foo": "bar"}, - Labels: map[string]string{"foo": "bar"}, + Labels: map[string]string{ + "foo": "bar", + "pipeline": "this-is-ignored", // loaded in opts. Ignored in SetupBuild. + }, }, }, }, diff --git a/runtime/kubernetes/testdata/pipeline-pods-template.yaml b/runtime/kubernetes/testdata/pipeline-pods-template.yaml index 5cdd329e..2f628817 100644 --- a/runtime/kubernetes/testdata/pipeline-pods-template.yaml +++ b/runtime/kubernetes/testdata/pipeline-pods-template.yaml @@ -9,3 +9,5 @@ spec: annotation/foo: bar labels: foo: bar + # attempting to override worker-provided labels will be ignored. + pipeline: this-is-ignored From 3ac92fbca058e232e81e7dfb2015742fee7518e0 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Wed, 23 Mar 2022 10:30:21 -0500 Subject: [PATCH 16/23] chore: test CRD with DNS or node selection --- runtime/kubernetes/build_test.go | 20 ++++++ .../testdata/pipeline-pods-template-dns.yaml | 19 ++++++ ...pipeline-pods-template-node-selection.yaml | 64 +++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 runtime/kubernetes/testdata/pipeline-pods-template-dns.yaml create mode 100644 runtime/kubernetes/testdata/pipeline-pods-template-node-selection.yaml diff --git a/runtime/kubernetes/build_test.go b/runtime/kubernetes/build_test.go index 47f425c7..f8df90c6 100644 --- a/runtime/kubernetes/build_test.go +++ b/runtime/kubernetes/build_test.go @@ -100,6 +100,26 @@ func TestKubernetes_SetupBuild(t *testing.T) { pipeline: _steps, opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-security-context.yaml")}, }, + { + failure: false, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-node-selection.yaml")}, + }, + { + failure: false, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-node-selection.yaml")}, + }, + { + failure: false, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-dns.yaml")}, + }, + { + failure: false, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-dns.yaml")}, + }, { failure: false, pipeline: _stages, diff --git a/runtime/kubernetes/testdata/pipeline-pods-template-dns.yaml b/runtime/kubernetes/testdata/pipeline-pods-template-dns.yaml new file mode 100644 index 00000000..31194d8a --- /dev/null +++ b/runtime/kubernetes/testdata/pipeline-pods-template-dns.yaml @@ -0,0 +1,19 @@ +apiVersion: "go-vela.github.io/v1alpha1" +kind: PipelinePodsTemplate +metadata: + name: pipeline-pods-template +spec: + template: + spec: + # https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config + dnsPolicy: "None" + dnsConfig: + nameservers: + - 1.2.3.4 + searches: + - ns1.svc.cluster-domain.example + - my.dns.search.suffix + options: + - name: ndots + value: "2" + - name: edns0 diff --git a/runtime/kubernetes/testdata/pipeline-pods-template-node-selection.yaml b/runtime/kubernetes/testdata/pipeline-pods-template-node-selection.yaml new file mode 100644 index 00000000..a262548b --- /dev/null +++ b/runtime/kubernetes/testdata/pipeline-pods-template-node-selection.yaml @@ -0,0 +1,64 @@ +apiVersion: "go-vela.github.io/v1alpha1" +kind: PipelinePodsTemplate +metadata: + name: pipeline-pods-template +spec: + template: + spec: + # nodeName is not supported. Using nodeSelector or affinity should be sufficient. + # nodeName: foo-node + + # https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/#create-a-pod-that-gets-scheduled-to-your-chosen-node + nodeSelector: + disktype: ssd + + affinity: + # https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/os + operator: In + values: + - linux + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + preference: + matchExpressions: + - key: another-node-label-key + operator: In + values: + - another-node-label-value + # https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: security + operator: In + values: + - S1 + topologyKey: topology.kubernetes.io/zone + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: security + operator: In + values: + - S2 + topologyKey: topology.kubernetes.io/zone + + # https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + tolerations: + - key: "key1" + operator: "Equal" + value: "value1" + effect: "NoSchedule" + - key: "key1" + operator: "Equal" + value: "value1" + effect: "NoExecute" From 504c15f15001f6d559ede9a786e7fd8ab9f2e66a Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Wed, 23 Mar 2022 13:21:03 -0500 Subject: [PATCH 17/23] refactor(k8s): simplify setting container.SecurityContext --- runtime/kubernetes/container.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/runtime/kubernetes/container.go b/runtime/kubernetes/container.go index 7c2cc319..8d1a0e04 100644 --- a/runtime/kubernetes/container.go +++ b/runtime/kubernetes/container.go @@ -168,9 +168,7 @@ func (c *client) SetupContainer(ctx context.Context, ctn *pipeline.Container) er return err } - container.SecurityContext = &v1.SecurityContext{ - Privileged: &privileged, - } + container.SecurityContext.Privileged = &privileged } if c.PipelinePodTemplate != nil && c.PipelinePodTemplate.Spec.Container != nil { From 2574d971688dff01d478335cb8cd0f6c73b7cb93 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Wed, 23 Mar 2022 13:21:33 -0500 Subject: [PATCH 18/23] chore(kubernetes): ensure PipelinePodsTemplate contents get into Pod definition --- runtime/kubernetes/build_test.go | 286 ++++++++++++++++++++++----- runtime/kubernetes/container_test.go | 76 ++++++- 2 files changed, 302 insertions(+), 60 deletions(-) diff --git a/runtime/kubernetes/build_test.go b/runtime/kubernetes/build_test.go index f8df90c6..70ca964a 100644 --- a/runtime/kubernetes/build_test.go +++ b/runtime/kubernetes/build_test.go @@ -6,11 +6,14 @@ package kubernetes import ( "context" + "reflect" "testing" "github.com/go-vela/types/pipeline" + velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestKubernetes_InspectBuild(t *testing.T) { @@ -54,91 +57,211 @@ func TestKubernetes_InspectBuild(t *testing.T) { } func TestKubernetes_SetupBuild(t *testing.T) { + // needed to be able to make a pointers: + trueBool := true + twoString := "2" + + // testdata/pipeline-pods-template.yaml + wantFromTemplateMetadata := velav1alpha1.PipelinePodTemplateMeta{ + Annotations: map[string]string{"annotation/foo": "bar"}, + Labels: map[string]string{ + "foo": "bar", + "pipeline": _steps.ID, + }, + } + + // testdata/pipeline-pods-template-security-context.yaml + wantFromTemplateSecurityContext := velav1alpha1.PipelinePodSecurityContext{ + RunAsNonRoot: &trueBool, + Sysctls: []v1.Sysctl{ + {Name: "kernel.shm_rmid_forced", Value: "0"}, + {Name: "net.core.somaxconn", Value: "1024"}, + {Name: "kernel.msgmax", Value: "65536"}, + }, + } + + // testdata/pipeline-pods-template-node-selection.yaml + wantFromTemplateNodeSelection := velav1alpha1.PipelinePodTemplateSpec{ + NodeSelector: map[string]string{"disktype": "ssd"}, + Affinity: &v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ + NodeSelectorTerms: []v1.NodeSelectorTerm{ + {MatchExpressions: []v1.NodeSelectorRequirement{ + {Key: "kubernetes.io/os", Operator: v1.NodeSelectorOpIn, Values: []string{"linux"}}, + }}, + }, + }, + PreferredDuringSchedulingIgnoredDuringExecution: []v1.PreferredSchedulingTerm{ + {Weight: 1, Preference: v1.NodeSelectorTerm{ + MatchExpressions: []v1.NodeSelectorRequirement{ + {Key: "another-node-label-key", Operator: v1.NodeSelectorOpIn, Values: []string{"another-node-label-value"}}, + }, + }}, + }, + }, + PodAffinity: &v1.PodAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{ + { + LabelSelector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + {Key: "security", Operator: metav1.LabelSelectorOpIn, Values: []string{"S1"}}, + }, + }, + TopologyKey: "topology.kubernetes.io/zone", + }, + }, + }, + PodAntiAffinity: &v1.PodAntiAffinity{ + PreferredDuringSchedulingIgnoredDuringExecution: []v1.WeightedPodAffinityTerm{ + { + Weight: 100, + PodAffinityTerm: v1.PodAffinityTerm{ + LabelSelector: &metav1.LabelSelector{ + MatchExpressions: []metav1.LabelSelectorRequirement{ + {Key: "security", Operator: metav1.LabelSelectorOpIn, Values: []string{"S2"}}, + }, + }, + TopologyKey: "topology.kubernetes.io/zone", + }, + }, + }, + }, + }, + Tolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoExecute, + }, + }, + } + + // testdata/pipeline-pods-template-dns.yaml + wantFromTemplateDNS := velav1alpha1.PipelinePodTemplateSpec{ + DNSPolicy: v1.DNSNone, + DNSConfig: &v1.PodDNSConfig{ + Nameservers: []string{"1.2.3.4"}, + Searches: []string{ + "ns1.svc.cluster-domain.example", + "my.dns.search.suffix", + }, + Options: []v1.PodDNSConfigOption{ + {Name: "ndots", Value: &twoString}, + {Name: "edns0"}, + }, + }, + } + // setup tests tests := []struct { - failure bool - pipeline *pipeline.Build - opts []ClientOpt + failure bool + pipeline *pipeline.Build + opts []ClientOpt + wantFromTemplate interface{} }{ { - failure: false, - pipeline: _stages, - opts: nil, + failure: false, + pipeline: _stages, + opts: nil, + wantFromTemplate: nil, }, { - failure: false, - pipeline: _steps, - opts: nil, + failure: false, + pipeline: _steps, + opts: nil, + wantFromTemplate: nil, }, { - failure: false, - pipeline: _stages, - opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-empty.yaml")}, + failure: false, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-empty.yaml")}, + wantFromTemplate: nil, }, { - failure: false, - pipeline: _steps, - opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-empty.yaml")}, + failure: false, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-empty.yaml")}, + wantFromTemplate: nil, }, { - failure: false, - pipeline: _stages, - opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template.yaml")}, + failure: false, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template.yaml")}, + wantFromTemplate: wantFromTemplateMetadata, }, { - failure: false, - pipeline: _steps, - opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template.yaml")}, + failure: false, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template.yaml")}, + wantFromTemplate: wantFromTemplateMetadata, }, { - failure: false, - pipeline: _stages, - opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-security-context.yaml")}, + failure: false, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-security-context.yaml")}, + wantFromTemplate: wantFromTemplateSecurityContext, }, { - failure: false, - pipeline: _steps, - opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-security-context.yaml")}, + failure: false, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-security-context.yaml")}, + wantFromTemplate: wantFromTemplateSecurityContext, }, { - failure: false, - pipeline: _stages, - opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-node-selection.yaml")}, + failure: false, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-node-selection.yaml")}, + wantFromTemplate: wantFromTemplateNodeSelection, }, { - failure: false, - pipeline: _steps, - opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-node-selection.yaml")}, + failure: false, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-node-selection.yaml")}, + wantFromTemplate: wantFromTemplateNodeSelection, }, { - failure: false, - pipeline: _stages, - opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-dns.yaml")}, + failure: false, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-dns.yaml")}, + wantFromTemplate: wantFromTemplateDNS, }, { - failure: false, - pipeline: _steps, - opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-dns.yaml")}, + failure: false, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-dns.yaml")}, + wantFromTemplate: wantFromTemplateDNS, }, { - failure: false, - pipeline: _stages, - opts: []ClientOpt{WithPodsTemplate("mock-pipeline-pods-template", "")}, + failure: false, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("mock-pipeline-pods-template", "")}, + wantFromTemplate: nil, }, { - failure: false, - pipeline: _steps, - opts: []ClientOpt{WithPodsTemplate("mock-pipeline-pods-template", "")}, + failure: false, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("mock-pipeline-pods-template", "")}, + wantFromTemplate: nil, }, { - failure: true, - pipeline: _stages, - opts: []ClientOpt{WithPodsTemplate("missing-pipeline-pods-template", "")}, + failure: true, + pipeline: _stages, + opts: []ClientOpt{WithPodsTemplate("missing-pipeline-pods-template", "")}, + wantFromTemplate: nil, }, { - failure: true, - pipeline: _steps, - opts: []ClientOpt{WithPodsTemplate("missing-pipeline-pods-template", "")}, + failure: true, + pipeline: _steps, + opts: []ClientOpt{WithPodsTemplate("missing-pipeline-pods-template", "")}, + wantFromTemplate: nil, }, } @@ -165,6 +288,67 @@ func TestKubernetes_SetupBuild(t *testing.T) { if err != nil { t.Errorf("SetupBuild returned err: %v", err) } + + // make sure that worker-defined labels are set and cannot be overridden by PipelinePodsTemplate + if pipelineLabel, ok := _engine.Pod.ObjectMeta.Labels["pipeline"]; !ok { + t.Errorf("Pod is missing the pipeline label: %v", _engine.Pod.ObjectMeta) + } else if pipelineLabel != test.pipeline.ID { + t.Errorf("Pod's pipeline label is %v, want %v", pipelineLabel, test.pipeline.ID) + } + + switch test.wantFromTemplate.(type) { + case velav1alpha1.PipelinePodTemplateMeta: + want := test.wantFromTemplate.(velav1alpha1.PipelinePodTemplateMeta) + + // PipelinePodsTemplate defined Annotations + if want.Annotations != nil && !reflect.DeepEqual(_engine.Pod.Annotations, want.Annotations) { + t.Errorf("Pod.Annotations is %v, want %v", _engine.Pod.Annotations, want.Annotations) + } + + // PipelinePodsTemplate defined Labels + if want.Labels != nil && !reflect.DeepEqual(_engine.Pod.Labels, want.Labels) { + t.Errorf("Pod.Labels is %v, want %v", _engine.Pod.Labels, want.Labels) + } + case velav1alpha1.PipelinePodSecurityContext: + want := test.wantFromTemplate.(velav1alpha1.PipelinePodSecurityContext) + + // PipelinePodsTemplate defined SecurityContext.RunAsNonRoot + if !reflect.DeepEqual(_engine.Pod.Spec.SecurityContext.RunAsNonRoot, want.RunAsNonRoot) { + t.Errorf("Pod.SecurityContext.RunAsNonRoot is %v, want %v", _engine.Pod.Spec.SecurityContext.RunAsNonRoot, want.RunAsNonRoot) + } + + // PipelinePodsTemplate defined SecurityContext.Sysctls + if want.Sysctls != nil && !reflect.DeepEqual(_engine.Pod.Spec.SecurityContext.Sysctls, want.Sysctls) { + t.Errorf("Pod.SecurityContext.Sysctls is %v, want %v", _engine.Pod.Spec.SecurityContext.Sysctls, want.Sysctls) + } + case velav1alpha1.PipelinePodTemplateSpec: + want := test.wantFromTemplate.(velav1alpha1.PipelinePodTemplateSpec) + + // PipelinePodsTemplate defined NodeSelector + if want.NodeSelector != nil && !reflect.DeepEqual(_engine.Pod.Spec.NodeSelector, want.NodeSelector) { + t.Errorf("Pod.NodeSelector is %v, want %v", _engine.Pod.Spec.NodeSelector, want.NodeSelector) + } + + // PipelinePodsTemplate defined Affinity + if want.Affinity != nil && !reflect.DeepEqual(_engine.Pod.Spec.Affinity, want.Affinity) { + t.Errorf("Pod.Affinity is %v, want %v", _engine.Pod.Spec.Affinity, want.Affinity) + } + + // PipelinePodsTemplate defined Tolerations + if want.Tolerations != nil && !reflect.DeepEqual(_engine.Pod.Spec.Tolerations, want.Tolerations) { + t.Errorf("Pod.Tolerations is %v, want %v", _engine.Pod.Spec.Tolerations, want.Tolerations) + } + + // PipelinePodsTemplate defined DNSPolicy + if len(want.DNSPolicy) > 0 && _engine.Pod.Spec.DNSPolicy != want.DNSPolicy { + t.Errorf("Pod.DNSPolicy is %v, want %v", _engine.Pod.Spec.DNSPolicy, want.DNSPolicy) + } + + // PipelinePodsTemplate defined DNSConfig + if want.DNSConfig != nil && !reflect.DeepEqual(_engine.Pod.Spec.DNSConfig, want.DNSConfig) { + t.Errorf("Pod.DNSConfig is %v, want %v", _engine.Pod.Spec.DNSConfig, want.DNSConfig) + } + } } } diff --git a/runtime/kubernetes/container_test.go b/runtime/kubernetes/container_test.go index 02850cb4..e968e4fb 100644 --- a/runtime/kubernetes/container_test.go +++ b/runtime/kubernetes/container_test.go @@ -6,9 +6,11 @@ package kubernetes import ( "context" + "reflect" "testing" "github.com/go-vela/types/pipeline" + velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -145,14 +147,16 @@ func TestKubernetes_RunContainer(t *testing.T) { func TestKubernetes_SetupContainer(t *testing.T) { // setup tests tests := []struct { - failure bool - container *pipeline.Container - opts []ClientOpt + failure bool + container *pipeline.Container + opts []ClientOpt + wantFromTemplate interface{} }{ { - failure: false, - container: _container, - opts: nil, + failure: false, + container: _container, + opts: nil, + wantFromTemplate: nil, }, { failure: false, @@ -167,7 +171,8 @@ func TestKubernetes_SetupContainer(t *testing.T) { Number: 2, Pull: "always", }, - opts: nil, + opts: nil, + wantFromTemplate: nil, }, { failure: false, @@ -182,22 +187,59 @@ func TestKubernetes_SetupContainer(t *testing.T) { Number: 2, Pull: "always", }, - opts: nil, + opts: nil, + wantFromTemplate: nil, }, { failure: false, container: _container, opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-security-context.yaml")}, + wantFromTemplate: velav1alpha1.PipelineContainerSecurityContext{ + Capabilities: &v1.Capabilities{ + Drop: []v1.Capability{"ALL"}, + Add: []v1.Capability{"NET_ADMIN", "SYS_TIME"}, + }, + }, }, } // run tests for _, test := range tests { // setup types - _engine, err := NewMock(_pod, test.opts...) + _engine, err := NewMock(_pod.DeepCopy(), test.opts...) if err != nil { t.Errorf("unable to create runtime engine: %v", err) } + // Adjust config for containers already defined in _pod + switch test.wantFromTemplate.(type) { + case velav1alpha1.PipelineContainerSecurityContext: + want := test.wantFromTemplate.(velav1alpha1.PipelineContainerSecurityContext) + + if want.Capabilities != nil { + for i, ctn := range _engine.Pod.Spec.Containers { + if ctn.SecurityContext == nil { + _engine.Pod.Spec.Containers[i].SecurityContext = &v1.SecurityContext{} + } + _engine.Pod.Spec.Containers[i].SecurityContext.Capabilities = want.Capabilities + } + } + } + + // Adjust config for containers already defined in _pod + switch test.wantFromTemplate.(type) { + case velav1alpha1.PipelineContainerSecurityContext: + want := test.wantFromTemplate.(velav1alpha1.PipelineContainerSecurityContext) + + if want.Capabilities != nil { + for i, ctn := range _engine.Pod.Spec.Containers { + if ctn.SecurityContext == nil { + _engine.Pod.Spec.Containers[i].SecurityContext = &v1.SecurityContext{} + } + + _engine.Pod.Spec.Containers[i].SecurityContext.Capabilities = want.Capabilities + } + } + } err = _engine.SetupContainer(context.Background(), test.container) @@ -214,6 +256,22 @@ func TestKubernetes_SetupContainer(t *testing.T) { if err != nil { t.Errorf("SetupContainer returned err: %v", err) } + + switch test.wantFromTemplate.(type) { + case velav1alpha1.PipelineContainerSecurityContext: + want := test.wantFromTemplate.(velav1alpha1.PipelineContainerSecurityContext) + + // PipelinePodsTemplate defined SecurityContext.Capabilities + if want.Capabilities != nil { + for i, ctn := range _engine.Pod.Spec.Containers { + if ctn.SecurityContext == nil { + t.Errorf("Pod.Containers[%v].SecurityContext is nil", i) + } else if !reflect.DeepEqual(ctn.SecurityContext.Capabilities, want.Capabilities) { + t.Errorf("Pod.Containers[%v].SecurityContext.Capabilities is %v, want %v", i, ctn.SecurityContext.Capabilities, want.Capabilities) + } + } + } + } } } From eabfd5b090671a98b17f135a0477346103679886 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Wed, 23 Mar 2022 14:01:43 -0500 Subject: [PATCH 19/23] chore(kubernetes): test SetupContainer with privileged container --- runtime/kubernetes/container_test.go | 75 ++++++++++++---------------- 1 file changed, 33 insertions(+), 42 deletions(-) diff --git a/runtime/kubernetes/container_test.go b/runtime/kubernetes/container_test.go index e968e4fb..22a1d184 100644 --- a/runtime/kubernetes/container_test.go +++ b/runtime/kubernetes/container_test.go @@ -150,12 +150,14 @@ func TestKubernetes_SetupContainer(t *testing.T) { failure bool container *pipeline.Container opts []ClientOpt + wantPrivileged bool wantFromTemplate interface{} }{ { failure: false, container: _container, opts: nil, + wantPrivileged: false, wantFromTemplate: nil, }, { @@ -172,6 +174,7 @@ func TestKubernetes_SetupContainer(t *testing.T) { Pull: "always", }, opts: nil, + wantPrivileged: false, wantFromTemplate: nil, }, { @@ -187,13 +190,15 @@ func TestKubernetes_SetupContainer(t *testing.T) { Number: 2, Pull: "always", }, - opts: nil, + opts: []ClientOpt{WithPrivilegedImages([]string{"target/vela-docker"})}, + wantPrivileged: true, wantFromTemplate: nil, }, { - failure: false, - container: _container, - opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-security-context.yaml")}, + failure: false, + container: _container, + opts: []ClientOpt{WithPodsTemplate("", "testdata/pipeline-pods-template-security-context.yaml")}, + wantPrivileged: false, wantFromTemplate: velav1alpha1.PipelineContainerSecurityContext{ Capabilities: &v1.Capabilities{ Drop: []v1.Capability{"ALL"}, @@ -210,40 +215,10 @@ func TestKubernetes_SetupContainer(t *testing.T) { if err != nil { t.Errorf("unable to create runtime engine: %v", err) } - // Adjust config for containers already defined in _pod - switch test.wantFromTemplate.(type) { - case velav1alpha1.PipelineContainerSecurityContext: - want := test.wantFromTemplate.(velav1alpha1.PipelineContainerSecurityContext) - - if want.Capabilities != nil { - for i, ctn := range _engine.Pod.Spec.Containers { - if ctn.SecurityContext == nil { - _engine.Pod.Spec.Containers[i].SecurityContext = &v1.SecurityContext{} - } - _engine.Pod.Spec.Containers[i].SecurityContext.Capabilities = want.Capabilities - } - } - } - - // Adjust config for containers already defined in _pod - switch test.wantFromTemplate.(type) { - case velav1alpha1.PipelineContainerSecurityContext: - want := test.wantFromTemplate.(velav1alpha1.PipelineContainerSecurityContext) - - if want.Capabilities != nil { - for i, ctn := range _engine.Pod.Spec.Containers { - if ctn.SecurityContext == nil { - _engine.Pod.Spec.Containers[i].SecurityContext = &v1.SecurityContext{} - } - - _engine.Pod.Spec.Containers[i].SecurityContext.Capabilities = want.Capabilities - } - } - } - + // actually run the test err = _engine.SetupContainer(context.Background(), test.container) - // this does not test the resulting pod spec (ie no tests for ImagePullPolicy, VolumeMounts) + // this does not (yet) test everything in the resulting pod spec (ie no tests for ImagePullPolicy, VolumeMounts) if test.failure { if err == nil { @@ -257,18 +232,34 @@ func TestKubernetes_SetupContainer(t *testing.T) { t.Errorf("SetupContainer returned err: %v", err) } + // SetupContainer added the last pod so get it for inspection + i := len(_engine.Pod.Spec.Containers) - 1 + ctn := _engine.Pod.Spec.Containers[i] + + // Make sure Container has Privileged configured correctly + if test.wantPrivileged { + if ctn.SecurityContext == nil { + t.Errorf("Pod.Containers[%v].SecurityContext is nil", i) + } else if *ctn.SecurityContext.Privileged != test.wantPrivileged { + t.Errorf("Pod.Containers[%v].SecurityContext.Privileged is %v, want %v", i, *ctn.SecurityContext.Privileged, test.wantPrivileged) + } + } else { + if ctn.SecurityContext != nil && ctn.SecurityContext.Privileged != nil && *ctn.SecurityContext.Privileged != test.wantPrivileged { + t.Errorf("Pod.Containers[%v].SecurityContext.Privileged is %v, want %v", i, *ctn.SecurityContext.Privileged, test.wantPrivileged) + } + + } + switch test.wantFromTemplate.(type) { case velav1alpha1.PipelineContainerSecurityContext: want := test.wantFromTemplate.(velav1alpha1.PipelineContainerSecurityContext) // PipelinePodsTemplate defined SecurityContext.Capabilities if want.Capabilities != nil { - for i, ctn := range _engine.Pod.Spec.Containers { - if ctn.SecurityContext == nil { - t.Errorf("Pod.Containers[%v].SecurityContext is nil", i) - } else if !reflect.DeepEqual(ctn.SecurityContext.Capabilities, want.Capabilities) { - t.Errorf("Pod.Containers[%v].SecurityContext.Capabilities is %v, want %v", i, ctn.SecurityContext.Capabilities, want.Capabilities) - } + if ctn.SecurityContext == nil { + t.Errorf("Pod.Containers[%v].SecurityContext is nil", i) + } else if !reflect.DeepEqual(ctn.SecurityContext.Capabilities, want.Capabilities) { + t.Errorf("Pod.Containers[%v].SecurityContext.Capabilities is %v, want %v", i, ctn.SecurityContext.Capabilities, want.Capabilities) } } } From 2e6d35b5cb62380a48b0447c8f3880d2b7ed996b Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Wed, 23 Mar 2022 17:18:02 -0500 Subject: [PATCH 20/23] chore: satisfy lint --- runtime/docker/opts_test.go | 3 ++- runtime/kubernetes/build.go | 2 +- runtime/kubernetes/container_test.go | 1 - runtime/kubernetes/opts.go | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/runtime/docker/opts_test.go b/runtime/docker/opts_test.go index 4d1a8c35..53438714 100644 --- a/runtime/docker/opts_test.go +++ b/runtime/docker/opts_test.go @@ -5,9 +5,10 @@ package docker import ( - "github.com/sirupsen/logrus" "reflect" "testing" + + "github.com/sirupsen/logrus" ) func TestDocker_ClientOpt_WithPrivilegedImages(t *testing.T) { diff --git a/runtime/kubernetes/build.go b/runtime/kubernetes/build.go index 66ca3cd4..5023deaf 100644 --- a/runtime/kubernetes/build.go +++ b/runtime/kubernetes/build.go @@ -14,7 +14,7 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - // The k8s libraries have some quirks around yaml marshalling (see opts.go). + // The k8s libraries have some quirks around yaml marshaling (see opts.go). // So, just use the same library for all kubernetes-related YAML. "sigs.k8s.io/yaml" ) diff --git a/runtime/kubernetes/container_test.go b/runtime/kubernetes/container_test.go index 22a1d184..89cf4f15 100644 --- a/runtime/kubernetes/container_test.go +++ b/runtime/kubernetes/container_test.go @@ -247,7 +247,6 @@ func TestKubernetes_SetupContainer(t *testing.T) { if ctn.SecurityContext != nil && ctn.SecurityContext.Privileged != nil && *ctn.SecurityContext.Privileged != test.wantPrivileged { t.Errorf("Pod.Containers[%v].SecurityContext.Privileged is %v, want %v", i, *ctn.SecurityContext.Privileged, test.wantPrivileged) } - } switch test.wantFromTemplate.(type) { diff --git a/runtime/kubernetes/opts.go b/runtime/kubernetes/opts.go index 62caa29d..c562d9f1 100644 --- a/runtime/kubernetes/opts.go +++ b/runtime/kubernetes/opts.go @@ -10,9 +10,9 @@ import ( "github.com/sirupsen/logrus" - // The k8s libraries have some quirks around yaml marshalling. + // The k8s libraries have some quirks around yaml marshaling. // They use `json` instead of `yaml` to annotate their struct Tags. - // So, we need to use "sigs.k8s.io/yaml" instead of "github.com/buildkite/yaml" + // So, we need to use "sigs.k8s.io/yaml" instead of "github.com/buildkite/yaml". "sigs.k8s.io/yaml" velav1alpha1 "github.com/go-vela/worker/runtime/kubernetes/apis/vela/v1alpha1" From 060d1f8cd5747614b45b9bf87d66ff37618caa64 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Wed, 23 Mar 2022 20:03:39 -0500 Subject: [PATCH 21/23] chore: Add instructional comments with links to docs --- PROJECT | 7 +++++++ runtime/kubernetes/apis/vela/v1alpha1/types.go | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/PROJECT b/PROJECT index 2d44e196..df013502 100644 --- a/PROJECT +++ b/PROJECT @@ -1,3 +1,10 @@ +--- +# This file is used in generating code for the Kubernetes Runtime. +# Look in runtime/kubernetes/apis/ and runtime/kubernetes/generated/ +# for the code that is used or generated by the code generators. +# +# For more about this file see: +# https://book.kubebuilder.io/reference/project-config.html domain: go-vela.github.io layout: - go.kubebuilder.io/v3 diff --git a/runtime/kubernetes/apis/vela/v1alpha1/types.go b/runtime/kubernetes/apis/vela/v1alpha1/types.go index 36a4de38..d0979d9e 100644 --- a/runtime/kubernetes/apis/vela/v1alpha1/types.go +++ b/runtime/kubernetes/apis/vela/v1alpha1/types.go @@ -9,6 +9,23 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +// Important: Run "make crd" after editing this file. + +// Helpful hints on adjusting the CRD generated from these types: +// +// - Use "+kubebuilder:object" tags on top-level structs: +// https://book.kubebuilder.io/reference/markers/object.html +// +// - Some fields (list, map, or struct types) may need additional tags. +// https://book.kubebuilder.io/reference/markers/crd-processing.html +// +// - Use "+kubebuilder:validation:*" tags to add more validation rules. +// https://book.kubebuilder.io/reference/generating-crd.html#validation +// https://book.kubebuilder.io/reference/markers/crd-validation.html +// +// - Use "+kubebuilder:printercolumn:*" tags to change the "kubectl get" columns. +// https://book.kubebuilder.io/reference/generating-crd.html#additional-printer-columns + // +genclient // +kubebuilder:object:root=true From 097973a409a2e8c1ff569ce8a0423ef1f70e6459 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Mon, 4 Apr 2022 10:10:26 -0500 Subject: [PATCH 22/23] Adjust comment location --- runtime/kubernetes/apis/vela/register.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/kubernetes/apis/vela/register.go b/runtime/kubernetes/apis/vela/register.go index 3308da51..7c08bd25 100644 --- a/runtime/kubernetes/apis/vela/register.go +++ b/runtime/kubernetes/apis/vela/register.go @@ -4,7 +4,7 @@ package vela -// GroupName is the group name used in this package. const ( + // GroupName is the group name used in this package. GroupName = "go-vela.github.io" ) From 156980a0da6084cf8941374be0e6118d58f4eee8 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Wed, 6 Apr 2022 17:04:55 -0500 Subject: [PATCH 23/23] chore: update opts FilePath to use _ over - --- runtime/flags.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/flags.go b/runtime/flags.go index 2d91a094..2e01350b 100644 --- a/runtime/flags.go +++ b/runtime/flags.go @@ -38,13 +38,13 @@ var Flags = []cli.Flag{ }, &cli.StringFlag{ EnvVars: []string{"VELA_RUNTIME_PODS_TEMPLATE_NAME", "RUNTIME_PODS_TEMPLATE_NAME"}, - FilePath: "/vela/runtime/pods-template-name", + FilePath: "/vela/runtime/pods_template_name", Name: "runtime.pods-template-name", Usage: "name of the PipelinePodsTemplate to retrieve from the runtime.namespace (only used by kubernetes)", }, &cli.PathFlag{ EnvVars: []string{"VELA_RUNTIME_PODS_TEMPLATE_FILE", "RUNTIME_PODS_TEMPLATE_FILE"}, - FilePath: "/vela/runtime/pods-template-file", + FilePath: "/vela/runtime/pods_template_file", Name: "runtime.pods-template-file", Usage: "path to local fallback file containing a PipelinePodsTemplate in YAML (only used by kubernetes; only used if runtime.pods-template-name is not defined)", },