appmanager: fix tar support, auto-create namespace
diff --git a/appmanager/cmd/main.go b/appmanager/cmd/main.go
index 5fa297f..dd42825 100644
--- a/appmanager/cmd/main.go
+++ b/appmanager/cmd/main.go
@@ -1,18 +1,28 @@
package main
import (
+ "context"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
+ "syscall"
"github.com/golang/glog"
+ "github.com/google/uuid"
+ apiv1 "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/client-go/kubernetes"
+ corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
+ "k8s.io/client-go/rest"
+ "k8s.io/client-go/tools/clientcmd"
app "github.com/giolekva/pcloud/appmanager"
)
+var kubeconfig = flag.String("kubeconfig", "", "Absolute path to the kubeconfig file.")
var port = flag.Int("port", 1234, "Port to listen on.")
var apiAddr = flag.String("api_addr", "", "PCloud API service address.")
@@ -30,7 +40,11 @@
</html>
`
-func helmHandler(w http.ResponseWriter, r *http.Request) {
+type handler struct {
+ nsClient corev1.NamespaceInterface
+}
+
+func (hn *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
_, err := io.WriteString(w, helmUploadPage)
if err != nil {
@@ -44,7 +58,18 @@
return
}
defer file.Close()
- p := "/tmp/" + handler.Filename
+ tmp := uuid.New().String()
+ if tmp == "" {
+ http.Error(w, "Could not generate temp dir", http.StatusInternalServerError)
+ return
+ }
+ p := "/tmp/" + tmp
+ // TODO(giolekva): defer rmdir
+ if err := syscall.Mkdir(p, 0777); err != nil {
+ http.Error(w, "Could not create temp dir", http.StatusInternalServerError)
+ return
+ }
+ p += "/" + handler.Filename
f, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
fmt.Println(err)
@@ -56,7 +81,7 @@
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- if err = installHelmChart(p); err != nil {
+ if err = installHelmChart(p, hn.nsClient); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
@@ -64,25 +89,59 @@
}
}
-func installHelmChart(path string) error {
- h, err := app.HelmChartFromDir("/Users/lekva/dev/go/src/github.com/giolekva/pcloud/apps/rpuppy/chart")
+func installHelmChart(path string, nsClient corev1.NamespaceInterface) error {
+ h, err := app.HelmChartFromTar(path)
if err != nil {
return err
}
- err = app.InstallSchema(h.Schema, *apiAddr)
- if err != nil {
+ if err = app.InstallSchema(h.Schema, *apiAddr); err != nil {
return err
}
glog.Infof("Installed schema: %s", h.Schema)
- err = h.Install(
+ namespace := fmt.Sprintf("app-%s", h.Name)
+ if err = createNamespace(nsClient, namespace); err != nil {
+ return err
+ }
+ glog.Infof("Created namespaces: %s", namespace)
+ if err = h.Install(
"/usr/local/bin/helm",
- map[string]string{})
+ map[string]string{}); err != nil {
+ return err
+ }
+ glog.Info("Installed")
+ return nil
+}
+
+func createNamespace(nsClient corev1.NamespaceInterface, name string) error {
+ _, err := nsClient.Create(
+ context.TODO(),
+ &apiv1.Namespace{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: name}},
+ metav1.CreateOptions{})
return err
}
+func getKubeConfig() (*rest.Config, error) {
+ if *kubeconfig != "" {
+ return clientcmd.BuildConfigFromFlags("", *kubeconfig)
+ } else {
+ return rest.InClusterConfig()
+ }
+}
+
func main() {
flag.Parse()
- http.HandleFunc("/", helmHandler)
+ config, err := getKubeConfig()
+ if err != nil {
+ glog.Fatalf("Could not initialize Kubeconfig: %v", err)
+ }
+ clientset, err := kubernetes.NewForConfig(config)
+ if err != nil {
+ glog.Fatalf("Could not create Kubernetes API client: %v", err)
+ }
+ namespaces := clientset.CoreV1().Namespaces()
+ http.Handle("/", &handler{namespaces})
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", *port), nil))
}