Skip to content
Merged
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
5 changes: 3 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ jobs:
uses: ietf-tools/semver-action@v1.5.1
with:
token: ${{ github.token }}
patchAll: true
# fall back to dev because we want to have a valid semver
branch: ${{ fromJSON('{"main":"dev"}')[github.ref_name] || github.ref_name }}
branch: ${{ fromJSON('{"main":"main"}')[github.ref_name] || github.ref_name }}
noVersionBumpBehavior: current

- name: Set OPERATOR_VERSION
Expand Down Expand Up @@ -198,7 +199,7 @@ jobs:
with:
token: ${{ github.token }}
# calculate the changelog from the last tag to the current dev state
fromTag: ${{ fromJSON('{"main":"dev"}')[github.ref_name] || github.ref_name }}
fromTag: ${{ fromJSON('{"main":"main"}')[github.ref_name] || github.ref_name }}
toTag: ${{ env.CURRENT }}
# Create a new release on GitHub with the semantic OPERATOR_VERSION number
- name: Create Release
Expand Down
13 changes: 11 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,13 @@ help: ## Display this help.
##@ Development

.PHONY: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
manifests: controller-gen enum-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(ENUM_GEN) --marshal --ptr -f api/**/enums.go
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases

.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
generate: controller-gen enum-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(ENUM_GEN) --marshal --ptr -f api/**/enums.go
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."

.PHONY: fmt
Expand Down Expand Up @@ -173,6 +175,8 @@ $(LOCALBIN):
## Tool Binaries
KUSTOMIZE ?= $(LOCALBIN)/kustomize
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
ENUM_GEN ?= $(LOCALBIN)/go-enum
ENUM_GEN_VERSION ?= latest
ENVTEST ?= $(LOCALBIN)/setup-envtest

## Tool Versions
Expand All @@ -190,6 +194,11 @@ controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessar
$(CONTROLLER_GEN): $(LOCALBIN)
test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)

.PHONY: enum-gen
enum-gen: $(ENUM_GEN) ## Download enum-gen locally if necessary.
$(ENUM_GEN): $(LOCALBIN)
test -s $(LOCALBIN)/go-enum || GOBIN=$(LOCALBIN) go install github.com/abice/go-enum@$(ENUM_GEN_VERSION)

.PHONY: envtest
envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
$(ENVTEST): $(LOCALBIN)
Expand Down
41 changes: 19 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,25 @@ ExecDAT is a tool to execute data analysis tasks on Kubernetes. It is designed t

## Getting Started

You’ll need a Kubernetes cluster to run against. See k3d for a quick way to get a local cluster up and running.
**Note:** Your controller will automatically use the current context in your kubeconfig file (i.e. whatever cluster `kubectl cluster-info` shows).
### Prerequisites

* operator-sdk
* container engine (docker, podman, ...)
* kubernetes cluster (minikube, k3d, ...)

### Test out the operator

```shell
make install
make run
```

### Run using OLM

```shell
operator-sdk olm install
operator-sdk run bundle-upgrade ghcr.io/austriandatalab/execdat-operator-bundle:v0.2.0
```

### Running on the cluster

Expand Down Expand Up @@ -47,33 +64,13 @@ UnDeploy the controller to the cluster:
make undeploy
```

## Contributing

// TODO(user): Add detailed information on how you would like others to contribute to this project

### How it works

This project aims to follow the Kubernetes [Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)

It uses [Controllers](https://kubernetes.io/docs/concepts/architecture/controller/)
which provides a reconcile function responsible for synchronizing resources untile the desired state is reached on the cluster

### Test It Out

1. Install the CRDs into the cluster:

```sh
make install
```

2. Run your controller (this will run in the foreground, so switch to a new terminal if you want to leave it running):

```sh
make run
```

**NOTE:** You can also run this in one step by running: `make install run`

### Modifying the API definitions

If you are editing the API definitions, generate the manifests such as CRs or CRDs using:
Expand Down
3 changes: 1 addition & 2 deletions api/v1alpha1/build_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ type BuildSpec struct {

// BuildStatus defines the observed state of Build
type BuildStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
CurrentPhase *CurrentPhase `json:"currentPhase"` //TODO: add fields of status and dataurls to kubectl get outputs
}

//+kubebuilder:object:root=true
Expand Down
24 changes: 13 additions & 11 deletions api/v1alpha1/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import (
"k8s.io/utils/pointer"
)

type PodSpecData struct {
type BuildPodSpecData struct {
INIT_SH string
Dockerfile string
ImageName string
ImageTag string
}

// SetPodSpec sets the pod spec for the build
func (build *Build) SetPodSpec(podSpec *kcore.PodSpec, podSpecData PodSpecData) error {
func (build *Build) SetPodSpec(podSpec *kcore.PodSpec, buildPodSpecData BuildPodSpecData) error {

podSpec.RestartPolicy = kcore.RestartPolicyNever

Expand All @@ -27,22 +28,23 @@ func (build *Build) SetPodSpec(podSpec *kcore.PodSpec, podSpecData PodSpecData)
}
podSpec.Containers = []kcore.Container{
{
Name: "buildah",
Image: "quay.io/buildah/stable",
Command: []string{"/bin/bash", "-c", "--"},
Args: []string{"trap : TERM INT; echo \"$INIT_SH\" | bash"},
Name: "buildah",
Image: "quay.io/buildah/stable",
ImagePullPolicy: kcore.PullIfNotPresent,
Command: []string{"/bin/bash", "-c", "--"},
Args: []string{"trap : TERM INT; echo \"$INIT_SH\" | bash"},
Env: []kcore.EnvVar{
{Name: "INIT_SH", Value: podSpecData.INIT_SH},
{Name: "DOCKERFILE", Value: podSpecData.Dockerfile},
{Name: "INIT_SH", Value: buildPodSpecData.INIT_SH},
{Name: "DOCKERFILE", Value: buildPodSpecData.Dockerfile},
{Name: "BASE_IMAGE", Value: build.Spec.BaseImage},
{Name: "IMAGE_NAME", Value: podSpecData.ImageName},
// {Name: "IMAGE_TAG", Value: build.Spec.ImageTag},
{Name: "IMAGE_NAME", Value: buildPodSpecData.ImageName},
{Name: "IMAGE_TAG", Value: buildPodSpecData.ImageTag},
// {Name: "IMAGE_REGISTRY", Value: build.Spec.ImageRegistry},
// {Name: "IMAGE_REGISTRY_USER", Value: build.Spec.ImageRegistryUser},
// {Name: "IMAGE_REGISTRY_PASSWORD", Value: build.Spec.ImageRegistryPassword},
// {Name: "IMAGE_REGISTRY_INSECURE", Value: build.Spec.ImageRegistryInsecure},
// {Name: "IMAGE_REGISTRY_VERIFY_TLS", Value: build.Spec.ImageRegistryVerifyTLS},
{Name: "ENTRYPOINT", Value: build.Spec.SourceCode.Entrypoint},
{Name: "ENTRYPOINT", Value: build.Spec.SourceCode.EntryPoint},
{Name: "GIT_REPO", Value: build.Spec.SourceCode.URL},
{Name: "GIT_BRANCH", Value: build.Spec.SourceCode.Branch},
{Name: "BUILD_CMD", Value: build.Spec.SourceCode.BuildCMD},
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/enums.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package v1alpha1

// swagger:enum CurrentPhase
// ENUM(pending, building, running, buildComplete, runCompleted, failed)
type CurrentPhase string
77 changes: 77 additions & 0 deletions api/v1alpha1/enums_enum.go

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

8 changes: 4 additions & 4 deletions api/v1alpha1/generic_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ type SourceCodeSpec struct {
Dependencies DependenciesSpec `json:"dependencies,omitempty"`
DependencyCMD string `json:"dependencycmd,omitempty"`
BuildCMD string `json:"buildcmd,omitempty"`
Entrypoint string `json:"entrypoint"`
EntryPoint string `json:"entrypoint"`
}

type InputDataSpec struct {
URL string `json:"url" description:"URL of the data repo of input data"`
Type string `json:"type" description:"Type of the input data source, e.g. s3, git, http, https, etc."`
DataPath string `json:"datapath" description:"Path to the data directory with input data, has to be a unix path."`
URL string `json:"url" description:"URL of the data repo of input data"`
Type string `json:"type,omitempty" description:"Type of the input data source, e.g. s3, git, http, https, etc."`
TransformCMD string `json:"transformcmd,omitempty" description:"Command to transform the input data"`
}

type OutputDataSpec struct {
URL string `json:"url" description:"URL of the data repo of output data"`
DataPath string `json:"datapath" description:"Path to the data directory with output data, has to be a unix path."`
URL string `json:"url,omitempty" description:"URL of the data repo of output data"`
}
12 changes: 5 additions & 7 deletions api/v1alpha1/run_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,17 @@ type RunSpec struct {
// Important: Run "make" to regenerate code after modifying this file

// Foo is an example field of Run. Edit run_types.go to remove/update
Build BuildSpec `json:"build"`
OutputData OutputDataSpec `json:"outputdata"`
//+optional
InputData InputDataSpec `json:"inputdata,omitempty"`
Description string `json:"description,omitempty"`
Build BuildSpec `json:"build"`
OutputData OutputDataSpec `json:"outputdata,omitempty"`
InputData InputDataSpec `json:"inputdata,omitempty"`
Description string `json:"description,omitempty"`
}

// RunStatus defines the observed state of Run
type RunStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
CurrentPhase string `json:"currentPhase"` //TODO: add fields of status and dataurls to kubectl get outputs
Test string `json:"test"`
CurrentPhase *CurrentPhase `json:"currentPhase"` //TODO: add fields of status and dataurls to kubectl get outputs
}

//+kubebuilder:object:root=true
Expand Down
68 changes: 68 additions & 0 deletions api/v1alpha1/runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package v1alpha1

import (
kcore "k8s.io/api/core/v1"
"k8s.io/utils/pointer"
)

type RunPodSpecData struct {
INIT_SH string
ImageName string
ImageTag string
InputDataPath string
OutputDataPath string
}

// SetPodSpec sets the pod spec for the run
func (run *Run) SetPodSpec(podSpec *kcore.PodSpec, runPodSpecData RunPodSpecData) error {

podSpec.RestartPolicy = kcore.RestartPolicyNever

podSpec.Volumes = []kcore.Volume{
{
Name: "input",
VolumeSource: kcore.VolumeSource{
EmptyDir: &kcore.EmptyDirVolumeSource{},
},
},
{
Name: "output",
VolumeSource: kcore.VolumeSource{
EmptyDir: &kcore.EmptyDirVolumeSource{},
},
},
}

podSpec.Containers = []kcore.Container{
{
Name: "buildah",
Image: "harbor.caas-0013.dev.austrianopencloudcommunity.org/execdev/" + runPodSpecData.ImageName + ":" + runPodSpecData.ImageTag,
ImagePullPolicy: kcore.PullIfNotPresent,
Command: []string{"/bin/bash", "-c", "--"},
Args: []string{"trap : TERM INT; echo \"$INIT_SH\" | bash"},
TTY: true,
Stdin: true,
Env: []kcore.EnvVar{
{Name: "INIT_SH", Value: runPodSpecData.INIT_SH},
{Name: "MINIO_ENDPOINT", Value: "http://minio.single-minio.svc.cluster.local:9000"},
{Name: "MINIO_ACCESS_KEY", Value: "cache-user-1"},
{Name: "MINIO_SECRET_KEY", Value: "CACHE_USER_PASS_XYZ_123"},
{Name: "BUCKET_NAME", Value: "cache-bucket-1"},
{Name: "HOME", Value: "/tmp"},
},
SecurityContext: &kcore.SecurityContext{
RunAsUser: pointer.Int64(1000),
RunAsGroup: pointer.Int64(1000),
},
VolumeMounts: []kcore.VolumeMount{
{Name: "input", MountPath: runPodSpecData.InputDataPath},
{Name: "output", MountPath: runPodSpecData.OutputDataPath},
},
},
}
podSpec.SecurityContext = &kcore.PodSecurityContext{
RunAsUser: pointer.Int64(1000),
RunAsGroup: pointer.Int64(1000),
}
return nil
}
Loading