You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@submarine.apache.org by ka...@apache.org on 2021/04/29 05:12:47 UTC
[submarine] branch master updated: SUBMARINE-805. Install local
traefik chart via helm golang API
This is an automated email from the ASF dual-hosted git repository.
kaihsun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/submarine.git
The following commit(s) were added to refs/heads/master by this push:
new da51236 SUBMARINE-805. Install local traefik chart via helm golang API
da51236 is described below
commit da51236071a7f30c38c7a05d91a019054d44631f
Author: kevin85421 <b0...@ntu.edu.tw>
AuthorDate: Thu Apr 29 13:12:38 2021 +0800
SUBMARINE-805. Install local traefik chart via helm golang API
### What is this PR for?
Install local traefik chart via Helm golang API.
traefik chart: https://github.com/apache/submarine/tree/master/helm-charts/submarine/charts/traefik
Helm golang API: https://github.com/apache/submarine/blob/master/submarine-cloud-v2/pkg/helm/helm.go
### What type of PR is it?
[Feature]
### Todos
* port-forwarding via client-go
### What is the Jira issue?
https://issues.apache.org/jira/projects/SUBMARINE/issues/SUBMARINE-805?filter=allissues#
### How should this be tested?
```
# initialization
# Step1: Register Custom Resource Definition
kubectl apply -f artifacts/examples/crd.yaml
# Step2: Create a Custom Resource
kubectl apply -f artifacts/examples/example-submarine.yaml
# Step3-1: helm
cd submarine
helm install submarine ./helm-charts/submarine
kubectl port-forward --address 0.0.0.0 service/traefik 32080:80
# Step3-2: in-cluster
cd submarine/submarine-cloud-v2
eval $(minikube docker-env)
make image
kubectl apply -f artifacts/examples/submarine-operator-service-account.yaml
kubectl apply -f artifacts/examples/submarine-operator.yaml
kubectl port-forward --address 0.0.0.0 service/traefik 32080:80
# Step3-3: out-of-cluster
go build -o submarine-operator
./submarine-operator
kubectl port-forward --address 0.0.0.0 service/traefik 32080:80
# Step4: Check 127.0.0.1:32080 in web browser
#. Username: admin / Password: admin
```
### Screenshots (if appropriate)
https://user-images.githubusercontent.com/20109646/116415503-10663480-a86c-11eb-8fff-199cc69d31c7.mov
### Questions:
* Do the license files need updating? No
* Are there breaking changes for older versions? No
* Does this need new documentation? No
---
.gitignore | 1 +
submarine-cloud-v2/Dockerfile | 4 +
submarine-cloud-v2/Makefile | 7 +-
.../submarine-operator-service-account.yaml | 19 +++-
submarine-cloud-v2/controller.go | 29 ++++++
submarine-cloud-v2/pkg/helm/helm.go | 113 ++++++++++++++++++++-
6 files changed, 166 insertions(+), 7 deletions(-)
diff --git a/.gitignore b/.gitignore
index 25e6577..7629275 100644
--- a/.gitignore
+++ b/.gitignore
@@ -88,6 +88,7 @@ submarine-security/spark-security/derby.log
# submarine-cloud-v2
submarine-cloud-v2/vendor/*
submarine-cloud-v2/submarine-operator
+submarine-cloud-v2/charts/*
# vscode file
.project
diff --git a/submarine-cloud-v2/Dockerfile b/submarine-cloud-v2/Dockerfile
index cb67e2c..a4097aa 100644
--- a/submarine-cloud-v2/Dockerfile
+++ b/submarine-cloud-v2/Dockerfile
@@ -16,6 +16,8 @@
FROM ubuntu:18.04
MAINTAINER Apache Software Foundation <de...@submarine.apache.org>
+WORKDIR /usr/src
+
RUN apt-get update &&\
apt-get install -y wget vim git
@@ -27,5 +29,7 @@ ENV PATH=$PATH:$GOPATH:$GOBIN:$GOROOT/bin
RUN wget https://dl.google.com/go/go1.16.2.linux-amd64.tar.gz &&\
tar -C /usr/local -xzf go1.16.2.linux-amd64.tar.gz
+ADD charts/ /usr/src/charts
+
ADD submarine-operator /usr/src
CMD ["/usr/src/submarine-operator", "-incluster=true"]
diff --git a/submarine-cloud-v2/Makefile b/submarine-cloud-v2/Makefile
index d9db13a..d6e4a4c 100644
--- a/submarine-cloud-v2/Makefile
+++ b/submarine-cloud-v2/Makefile
@@ -17,8 +17,11 @@
all: # The default target
+charts:
+ cp -r ../helm-charts/submarine/charts .
+
.PHONY: all
-all:
+all: charts
go build -o submarine-operator
.PHONY: api
@@ -27,7 +30,7 @@ api:
echo "Verifying API..."; ./verify-codegen.sh
.PHONY: image
-image:
+image: charts
GOOS=linux go build -o submarine-operator
docker build -t submarine-operator .
go build -o submarine-operator
diff --git a/submarine-cloud-v2/artifacts/examples/submarine-operator-service-account.yaml b/submarine-cloud-v2/artifacts/examples/submarine-operator-service-account.yaml
index cf73d2a..08d047e 100644
--- a/submarine-cloud-v2/artifacts/examples/submarine-operator-service-account.yaml
+++ b/submarine-cloud-v2/artifacts/examples/submarine-operator-service-account.yaml
@@ -27,6 +27,18 @@ rules:
verbs:
- "*"
- apiGroups:
+ - traefik.containo.us
+ resources:
+ - ingressroutes
+ - ingressroutetcps
+ - ingressrouteudps
+ - middlewares
+ - tlsoptions
+ - tlsstores
+ - traefikservices
+ verbs:
+ - "*"
+ - apiGroups:
- ""
resources:
- pods
@@ -60,6 +72,12 @@ rules:
- clusterrolebindings
verbs:
- "*"
+ - apiGroups:
+ - apiextensions.k8s.io
+ resources:
+ - customresourcedefinitions
+ verbs:
+ - "*"
---
apiVersion: v1
kind: ServiceAccount
@@ -79,4 +97,3 @@ subjects:
- kind: ServiceAccount
name: submarine-operator
namespace: default
-
diff --git a/submarine-cloud-v2/controller.go b/submarine-cloud-v2/controller.go
index 316cf56..96fdac2 100644
--- a/submarine-cloud-v2/controller.go
+++ b/submarine-cloud-v2/controller.go
@@ -53,6 +53,7 @@ import (
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/workqueue"
"k8s.io/klog/v2"
+ "submarine-cloud-v2/pkg/helm"
)
const controllerAgentName = "submarine-controller"
@@ -707,6 +708,31 @@ func (c *Controller) newSubmarineDatabase(namespace string, spec *v1alpha1.Subma
return nil
}
+// subcharts: https://github.com/apache/submarine/tree/master/helm-charts/submarine/charts
+
+func (c *Controller) newSubCharts(namespace string) error {
+ // Install traefik
+ // Reference: https://github.com/apache/submarine/tree/master/helm-charts/submarine/charts/traefik
+
+ if !helm.CheckRelease("traefik", namespace) {
+ klog.Info("[Helm] Install Traefik")
+ helm.HelmInstallLocalChart(
+ "traefik",
+ "charts/traefik",
+ "traefik",
+ namespace,
+ map[string]string{},
+ )
+ }
+
+ // TODO: maintain "error"
+ // TODO: (sample-controller) controller.go:287 ~ 293
+ // TODO: port-forward
+ // kubectl port-forward --address 0.0.0.0 service/traefik 32080:80
+
+ return nil
+}
+
// syncHandler compares the actual state with the desired, and attempts to
// converge the two. It then updates the Status block of the Foo resource
// with the current status of the resource.
@@ -766,6 +792,9 @@ func (c *Controller) syncHandler(key string) error {
return err
}
+ // Install subcharts
+ c.newSubCharts(namespace)
+
return nil
}
diff --git a/submarine-cloud-v2/pkg/helm/helm.go b/submarine-cloud-v2/pkg/helm/helm.go
index 4c14ff8..3961e00 100644
--- a/submarine-cloud-v2/pkg/helm/helm.go
+++ b/submarine-cloud-v2/pkg/helm/helm.go
@@ -41,10 +41,11 @@ import (
"helm.sh/helm/v3/pkg/downloader"
"helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/repo"
+ "helm.sh/helm/v3/pkg/storage/driver"
"helm.sh/helm/v3/pkg/strvals"
)
-func HelmInstall(url string, repoName string, chartName string, releaseName string, namespace string, args map[string]string) (*action.Configuration){
+func HelmInstall(url string, repoName string, chartName string, releaseName string, namespace string, args map[string]string) *action.Configuration {
var settings *cli.EnvSettings
os.Setenv("HELM_NAMESPACE", namespace)
settings = cli.New()
@@ -57,6 +58,15 @@ func HelmInstall(url string, repoName string, chartName string, releaseName stri
return cfg
}
+func HelmInstallLocalChart(chartName string, chartPath string, releaseName string, namespace string, args map[string]string) *action.Configuration {
+ var settings *cli.EnvSettings
+ os.Setenv("HELM_NAMESPACE", namespace)
+ settings = cli.New()
+ // Install charts
+ cfg := InstallLocalChart(releaseName, chartName, chartPath, args, settings)
+ return cfg
+}
+
func HelmUninstall(releaseName string, cfg *action.Configuration) error {
uninstall := action.NewUninstall(cfg)
_, err := uninstall.Run(releaseName)
@@ -158,19 +168,20 @@ func RepoUpdate(settings *cli.EnvSettings) {
}
// InstallChart
-func InstallChart(name, repo, chart string, args map[string]string, settings *cli.EnvSettings) (*action.Configuration) {
+func InstallChart(releaseName string, repo string, chart string, args map[string]string, settings *cli.EnvSettings) *action.Configuration {
actionConfig := new(action.Configuration)
debug("KUBECONFIG: %s", settings.KubeConfig)
if err := actionConfig.Init(settings.RESTClientGetter(), settings.Namespace(), os.Getenv("HELM_DRIVER"), debug); err != nil {
log.Fatal(err)
}
+
client := action.NewInstall(actionConfig)
if client.Version == "" && client.Devel {
client.Version = ">0.0.0-0"
}
- //name, chart, err := client.NameAndChart(args)
- client.ReleaseName = name
+
+ client.ReleaseName = releaseName
cp, err := client.ChartPathOptions.LocateChart(fmt.Sprintf("%s/%s", repo, chart), settings)
if err != nil {
log.Fatal(err)
@@ -234,6 +245,100 @@ func InstallChart(name, repo, chart string, args map[string]string, settings *cl
return actionConfig
}
+// InstallChart
+func InstallLocalChart(releaseName string, chart string, chartPath string, args map[string]string, settings *cli.EnvSettings) *action.Configuration {
+ actionConfig := new(action.Configuration)
+ if err := actionConfig.Init(settings.RESTClientGetter(), settings.Namespace(), os.Getenv("HELM_DRIVER"), debug); err != nil {
+ log.Fatal(err)
+ }
+
+ client := action.NewInstall(actionConfig)
+
+ if client.Version == "" && client.Devel {
+ client.Version = ">0.0.0-0"
+ }
+
+ client.ReleaseName = releaseName
+
+ debug("CHART PATH: %s\n", chartPath)
+
+ p := getter.All(settings)
+ valueOpts := &values.Options{}
+ vals, err := valueOpts.MergeValues(p)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Add args
+ if err := strvals.ParseInto(args["set"], vals); err != nil {
+ log.Fatal(errors.Wrap(err, "failed parsing --set data"))
+ }
+
+ // Check chart dependencies to make sure all are present in /charts
+ chartRequested, err := loader.Load(chartPath)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ validInstallableChart, err := isChartInstallable(chartRequested)
+ if !validInstallableChart {
+ log.Fatal(err)
+ }
+
+ if req := chartRequested.Metadata.Dependencies; req != nil {
+ // If CheckDependencies returns an error, we have unfulfilled dependencies.
+ // As of Helm 2.4.0, this is treated as a stopping condition:
+ // https://github.com/helm/helm/issues/2209
+ if err := action.CheckDependencies(chartRequested, req); err != nil {
+ if client.DependencyUpdate {
+ man := &downloader.Manager{
+ Out: os.Stdout,
+ ChartPath: chartPath,
+ Keyring: client.ChartPathOptions.Keyring,
+ SkipUpdate: false,
+ Getters: p,
+ RepositoryConfig: settings.RepositoryConfig,
+ RepositoryCache: settings.RepositoryCache,
+ }
+ if err := man.Update(); err != nil {
+ log.Fatal(err)
+ }
+ } else {
+ log.Fatal(err)
+ }
+ }
+ }
+
+ client.Namespace = settings.Namespace()
+ release, err := client.Run(chartRequested, vals)
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Println(release.Manifest)
+ return actionConfig
+}
+
+func CheckRelease(releaseName string, namespace string) bool {
+ debug("[CheckRelease] %s %s\n", releaseName, namespace)
+ var settings *cli.EnvSettings
+ os.Setenv("HELM_NAMESPACE", namespace)
+ settings = cli.New()
+
+ actionConfig := new(action.Configuration)
+ if err := actionConfig.Init(settings.RESTClientGetter(), settings.Namespace(), os.Getenv("HELM_DRIVER"), debug); err != nil {
+ log.Fatal(err)
+ }
+
+ histClient := action.NewHistory(actionConfig)
+ if _, err := histClient.Run(releaseName); err == driver.ErrReleaseNotFound {
+ debug(" The release %s does not exist.\n", releaseName)
+ return false
+ }
+
+ debug(" The release %s exists.\n", releaseName)
+ return true
+}
+
func isChartInstallable(ch *chart.Chart) (bool, error) {
switch ch.Metadata.Type {
case "", "application":
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@submarine.apache.org
For additional commands, e-mail: dev-help@submarine.apache.org