Skip to content

Commit

Permalink
Initial draft for theia-controller (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
eterna2 committed Apr 28, 2020
1 parent 9cdcb97 commit ce5f032
Show file tree
Hide file tree
Showing 54 changed files with 21,421 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@

# Dependency directories (remove the comment below to include it)
# vendor/

# tmp
tmp/
28 changes: 28 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Build the manager binary
FROM golang:1.13 as builder

WORKDIR /workspace
# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN go mod download

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

# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go

# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
FROM gcr.io/distroless/static:nonroot
WORKDIR /
COPY --from=builder /workspace/manager .
USER nonroot:nonroot

ENTRYPOINT ["/manager"]
80 changes: 80 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@

# Image URL to use all building/pushing image targets
IMG ?= controller:latest
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
CRD_OPTIONS ?= "crd:trivialVersions=true"

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

all: manager

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

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

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

# Install CRDs into a cluster
install: manifests
kustomize build config/crd | kubectl apply -f -

# Uninstall CRDs from a cluster
uninstall: manifests
kustomize build config/crd | kubectl delete -f -

# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
deploy: manifests
cd config/manager && kustomize edit set image controller=${IMG}
kustomize build config/default | kubectl apply -f -

# Generate manifests e.g. CRD, RBAC etc.
manifests: controller-gen
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook 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:headerFile="hack/boilerplate.go.txt" paths="./..."

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

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

# find or download controller-gen
# download controller-gen if necessary
controller-gen:
ifeq (, $(shell which controller-gen))
@{ \
set -e ;\
CONTROLLER_GEN_TMP_DIR=$$(mktemp -d) ;\
cd $$CONTROLLER_GEN_TMP_DIR ;\
go mod init tmp ;\
go get sigs.k8s.io/controller-tools/cmd/[email protected] ;\
rm -rf $$CONTROLLER_GEN_TMP_DIR ;\
}
CONTROLLER_GEN=$(GOBIN)/controller-gen
else
CONTROLLER_GEN=$(shell which controller-gen)
endif
6 changes: 6 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
repo: theia-controller
resources:
- group: e2.fyi
kind: Theia
version: v1alpha1
version: "2"
53 changes: 51 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,51 @@
# theias-controller
kubernetes CRD controller to manage theias (vscode alternative) - imagine jupyterhub.
# theia-controller

kubernetes CRD controller to manage theia (vscode alternative) - imagine jupyterhub.

> Referenced mostly from
>
> - https://book.kubebuilder.io
> - https://github.com/kubeflow/kubeflow/tree/master/components/notebook-controller
## TODOs

- Add a react UI to list, stop, and start `theia` instances
- (stretch-goal) Add authentications, etc, and integrate with Kubeflow

## Docker

See https://hub.docker.com/r/e2fyi/theia-controller

## Developer notes

### Generate/update codes and CRD manifest

```bash
make generate
make manifest
```

### Kustomize

`kubebuilder` requires `kustomize` `v3.1.0+`. `kubectl` is currently still on `v2`, so you will need to download `kustomize` binary from their site.

Deploying `theia-controller`

```bash
# create and deploy the basic controller
kustomize build manifest/kustomize/base > manifest/generated/theia-controller.yaml
kubectl apply -f manifest/generated/theia-controller.yaml

# create and deploy the controller with istio integration
kustomize build manifest/kustomize/istio > manifest/generated/theia-controller-istio.yaml
kubectl apply -f manifest/generated/theia-controller-istio.yaml
```

Creating a `theia` statefulset

```bash
# deploys a theia CR
kubectl apply -f manifest/examples
```

If `istio` is deployed in the cluster, you can access the `theia` webapp via the route `http://<istio-gateway-hostname>/theia/<namespace>/<cr-name>` (e.g. `http://x.x.x.x/theia/default/my-theia`).
36 changes: 36 additions & 0 deletions 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 e2.fyi v1alpha1 API group
// +kubebuilder:object:generate=true
// +groupName=e2.fyi
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: "e2.fyi", 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
)
91 changes: 91 additions & 0 deletions api/v1alpha1/theias_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

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

// 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.

// TheiaSpec defines the desired state of Theia
type TheiaSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

Template TheiaTemplateSpec `json:"template,omitempty"`
}

// TheiaTemplateSpec defines the pod spec for the Theia
type TheiaTemplateSpec struct {
metav1.ObjectMeta `json:"metadata,omitempty"`
corev1.PersistentVolumeClaimSpec `json:"pvc,omitempty"`
Spec corev1.PodSpec `json:"spec,omitempty"`
}

// TheiaStatus defines the observed state of Theia
type TheiaStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Conditions is an array of current conditions
Conditions []TheiaCondition `json:"conditions"`
// ReadyReplicas is the number of Pods created by the StatefulSet controller that have a Ready Condition.
ReadyReplicas int32 `json:"readyReplicas"`
// ContainerState is the state of underlying container.
ContainerState corev1.ContainerState `json:"containerState"`
}

// TheiaCondition defines the conditions of Theia status
type TheiaCondition struct {
// Type is the type of the condition. Possible values are Running|Waiting|Terminated
Type string `json:"type"`
// Last time we probed the condition.
// +optional
LastProbeTime metav1.Time `json:"lastProbeTime,omitempty"`
// (brief) reason the container is in the current state
// +optional
Reason string `json:"reason,omitempty"`
// Message regarding why the container is in the current state.
// +optional
Message string `json:"message,omitempty"`
}

// +kubebuilder:object:root=true

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

Spec TheiaSpec `json:"spec,omitempty"`
Status TheiaStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

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

func init() {
SchemeBuilder.Register(&Theia{}, &TheiaList{})
}
Loading

0 comments on commit ce5f032

Please sign in to comment.