Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracejob operator WIP #1

Draft
wants to merge 1 commit into
base: shopify-wip
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions operator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
bin

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Kubernetes Generated files - skip generated files, except for vendored files

!vendor/**/zz_generated.*

# editor and IDE paraphernalia
.idea
*.swp
*.swo
*~
1 change: 1 addition & 0 deletions operator/Dockerfile
112 changes: 112 additions & 0 deletions operator/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@

# Image URL to use all building/pushing image targets
IMG_REPO ?= gcr.io/shopify-docker-images/cloud/production/
IMG_SHA ?= latest
INIT_IMG ?= $(join ${IMG_REPO}, kubectl-trace-init):${IMG_SHA}
RUNNER_IMG ?= $(join ${IMG_REPO}, kubectl-trace-runner):${IMG_SHA}
OPERATOR_IMG ?= $(join ${IMG_REPO}, kubectl-trace-operator):${IMG_SHA}
DEPLOY_CONTEXT ?= $(shell kubectl config current-context 2>/dev/null)
CRD_OPTIONS ?= "crd:crdVersions=v1"

DRY_RUN ?= # set DRY_RUN=1 to output, but not apply, kustomize rendered output
GENERATE_MANIFESTS ?= # set GENERATE_MANIFESTS=1 to force rebuilding manifests

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif

kubectl-trace-controller = _output/bin/kubectl-trace-controller

all: clean ${kubectl-trace-controller}

clean:
$(RM) -R _output

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

# Build kubectl-trace-controller binary
${kubectl-trace-controller}: generate #fmt vet
CGO_ENABLED=0 go build -o $@ ./cmd/kubectl-trace-controller

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

# Install CRDs into a cluster
install: $(if $(GENERATE_MANIFESTS), manifests)
kubectl kustomize config/global $(if $(DRY_RUN), , | kubectl apply -f - --context $(DEPLOY_CONTEXT))

# Uninstall CRDs from a cluster
uninstall: $(if $(GENERATE_MANIFESTS), manifests)
kubectl kustomize config/global | kubectl delete -f - --context $(DEPLOY_CONTEXT)

# Install CRDs into a cluster
client-install: $(if $(GENERATE_MANIFESTS), manifests)
kubectl kustomize config/client $(if $(DRY_RUN), , | kubectl apply -f - --context $(DEPLOY_CONTEXT))

# Uninstall CRDs from a cluster
client-uninstall: $(if $(GENERATE_MANIFESTS), manifests)
kubectl kustomize config/client | kubectl delete -f - --context $(DEPLOY_CONTEXT)

# Install RBAC rules in the cluster
rbac-install: $(if $(GENERATE_MANIFESTS), manifests)
kubectl kustomize config/rbac $(if $(DRY_RUN), , | kubectl apply -f - --context $(DEPLOY_CONTEXT))

# Uninstall RBAC rules in the cluster
rbac-uninstall: $(if $(GENERATE_MANIFESTS), manifests)
kubectl kustomize config/rbac | kubectl delete -f - --context $(DEPLOY_CONTEXT)

# Install default CRs into a cluster
defaults-install: $(if $(GENERATE_MANIFESTS), manifests)
kubectl kustomize config/defaults $(if $(DRY_RUN), , | kubectl apply -f - --context $(DEPLOY_CONTEXT))

# Uninstall default CRs from a cluster
defaults-uninstall: $(if $(GENERATE_MANIFESTS), manifests)
kubectl kustomize config/defaults | kubectl delete -f - --context $(DEPLOY_CONTEXT)

set-revisions:
cd config/preloader && kustomize edit set image preloader=${INIT_IMG}
cd config/preloader && kustomize edit set image tracerunner=${RUNNER_IMG}
cd config/manager && kustomize edit set image controller=${OPERATOR_IMG}

# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
deploy: $(if $(GENERATE_MANIFESTS), manifests) set-revisions
kustomize build config/base $(if $(DRY_RUN), , | kubectl apply -f - --context $(DEPLOY_CONTEXT))

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

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

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

# Generate code
generate: controller-gen
$(CONTROLLER_GEN) object paths="./..."

# find or download controller-gen
# download controller-gen if necessary
controller-gen:
ifeq (, $(shell which controller-gen))
@{ \
set -e ;\
CONTROLLER_GEN_TMP_DIR=$$(mktemp -d) ;\
cd $$CONTROLLER_GEN_TMP_DIR ;\
go mod init tmp ;\
go get sigs.k8s.io/controller-tools/cmd/[email protected] ;\
rm -rf $$CONTROLLER_GEN_TMP_DIR ;\
}
CONTROLLER_GEN=$(GOBIN)/controller-gen
else
CONTROLLER_GEN=$(shell which controller-gen)
endif
10 changes: 10 additions & 0 deletions operator/PROJECT
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
domain: iovisor.org
repo: github.com/iovisor/kubectl-trace/operator
resources:
- group: trace
kind: TraceJob
version: v1
- group: trace
kind: TraceJobGC
version: v1alpha1
version: "2"
36 changes: 36 additions & 0 deletions operator/api/v1alpha1/groupversion_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*


Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package v1alpha1 contains API Schema definitions for the trace v1alpha1 API group
// +kubebuilder:object:generate=true
// +groupName=trace.iovisor.org
package v1alpha1

import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)

var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "trace.iovisor.org", Version: "v1alpha1"}

// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}

// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)
64 changes: 64 additions & 0 deletions operator/api/v1alpha1/status_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package v1alpha1

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

type ConditionType string
type ConditionStatus string

var (
ConditionStatusTrue ConditionStatus = "True"
ConditionStatusFalse ConditionStatus = "False"
ConditionStatusUnknown ConditionStatus = "Unknown"
)

var (
ConditionTypeRunning ConditionType = "Running"
ConditionTypeSuccess ConditionType = "Succeeded"
ConditionTypeFailed ConditionType = "Failed"
ConditionTypeInvalid ConditionType = "Invalid"
)

type StatusCondition struct {
Type ConditionType `json:"type"`

// Status of the condition, one of True, False, Unknown.
Status ConditionStatus `json:"status"`
// +optional
LastProbeTime metav1.Time `json:"lastProbeTime,omitempty"`
// +optional
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
// +optional
Reason string `json:"reason,omitempty"`
// +optional
Message string `json:"message,omitempty"`
}

func SetCondition(conds *[]StatusCondition, targetCond *StatusCondition) {
var outCond *StatusCondition

for i, cond := range *conds {
if cond.Type == targetCond.Type {
outCond = &(*conds)[i]
break
}
}

if outCond == nil {
*conds = append(*conds, *targetCond)
outCond = &(*conds)[len(*conds)-1]
outCond.LastTransitionTime = metav1.Now()
} else {
lastStatus := outCond.Status
lastTrans := outCond.LastTransitionTime
*outCond = *targetCond
if outCond.Status != lastStatus {
outCond.LastTransitionTime = metav1.Now()
} else {
outCond.LastTransitionTime = lastTrans
}
}

outCond.LastProbeTime = metav1.Now()
}
89 changes: 89 additions & 0 deletions operator/api/v1alpha1/tracejob_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*


Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

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

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

// TODO: Make the Spec immutable (guard it with a admission controller)
// TODO: add defaulting / validations
// TOOD: for defaulting? GA in 1.17 for basic functionality from controller-tools. before that it requires admission controller.

// TraceJobSpec defines the desired state of TraceJob
type TraceJobSpec struct {
TargetNamespace string `json:"targetNamespace"`

Resource string `json:"resource"` // conceptually arg[0]
Container string `json:"container,omitempty"` // conceptually arg[1] / "-c"

// +kubebuilder:validation:Enum=bpftrace;bcc;fake;rbspy
Tracer string `json:"tracer,omitempty"`
Selector string `json:"selector,omitempty"`

// +kubebuilder:default=stdout
// +kubebuilder:validation:Pattern=`^(gs:\/\/.+)|(stdout)$`
Output string `json:"output,omitempty"`

Program string `json:"program,omitempty"`
ProgramArgs []string `json:"programArgs,omitempty"`
ImageNameTag string `json:"imageNameTag,omitempty"`
InitImageNameTag string `json:"initImageNameTag,omitempty"`
FetchHeaders bool `json:"fetchHeaders,omitempty"`
GoogleAppSecret string `json:"googleAppSecret,omitempty"`

// +kubebuilder:default=3600
Deadline int64 `json:"deadline,omitempty"`

// +kubebuilder:default=30
DeadlineGracePeriod int64 `json:"deadlineGracePeriod,omitempty"`
}

// TraceJobStatus defines the observed state of TraceJob
type TraceJobStatus struct {
ArtifactPath string `json:"artifactPath,omitempty"`
JobName string `json:"jobName,omitempty"`
Conditions []StatusCondition `json:"conditions,omitempty"`
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

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

Spec TraceJobSpec `json:"spec,omitempty"`
Status TraceJobStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

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

func init() {
SchemeBuilder.Register(&TraceJob{}, &TraceJobList{})
}
Loading