github.com/jmrodri/operator-sdk@v0.5.0/pkg/helm/release/manager_factory.go (about) 1 // Copyright 2018 The Operator-SDK Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package release 16 17 import ( 18 "fmt" 19 "strings" 20 21 "github.com/martinlindhe/base36" 22 "github.com/pborman/uuid" 23 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 26 apitypes "k8s.io/apimachinery/pkg/types" 27 clientset "k8s.io/client-go/kubernetes" 28 helmengine "k8s.io/helm/pkg/engine" 29 "k8s.io/helm/pkg/kube" 30 "k8s.io/helm/pkg/storage" 31 "k8s.io/helm/pkg/tiller" 32 "k8s.io/helm/pkg/tiller/environment" 33 34 "github.com/operator-framework/operator-sdk/pkg/helm/engine" 35 "github.com/operator-framework/operator-sdk/pkg/helm/internal/types" 36 ) 37 38 // ManagerFactory creates Managers that are specific to custom resources. It is 39 // used by the HelmOperatorReconciler during resource reconciliation, and it 40 // improves decoupling between reconciliation logic and the Helm backend 41 // components used to manage releases. 42 type ManagerFactory interface { 43 NewManager(r *unstructured.Unstructured) Manager 44 } 45 46 type managerFactory struct { 47 storageBackend *storage.Storage 48 tillerKubeClient *kube.Client 49 chartDir string 50 } 51 52 // NewManagerFactory returns a new Helm manager factory capable of installing and uninstalling releases. 53 func NewManagerFactory(storageBackend *storage.Storage, tillerKubeClient *kube.Client, chartDir string) ManagerFactory { 54 return &managerFactory{storageBackend, tillerKubeClient, chartDir} 55 } 56 57 func (f managerFactory) NewManager(r *unstructured.Unstructured) Manager { 58 return f.newManagerForCR(r) 59 } 60 61 func (f managerFactory) newManagerForCR(r *unstructured.Unstructured) Manager { 62 return &manager{ 63 storageBackend: f.storageBackend, 64 tillerKubeClient: f.tillerKubeClient, 65 chartDir: f.chartDir, 66 67 tiller: f.tillerRendererForCR(r), 68 releaseName: getReleaseName(r), 69 namespace: r.GetNamespace(), 70 71 spec: r.Object["spec"], 72 status: types.StatusFor(r), 73 } 74 } 75 76 // tillerRendererForCR creates a ReleaseServer configured with a rendering engine that adds ownerrefs to rendered assets 77 // based on the CR. 78 func (f managerFactory) tillerRendererForCR(r *unstructured.Unstructured) *tiller.ReleaseServer { 79 controllerRef := metav1.NewControllerRef(r, r.GroupVersionKind()) 80 ownerRefs := []metav1.OwnerReference{ 81 *controllerRef, 82 } 83 baseEngine := helmengine.New() 84 e := engine.NewOwnerRefEngine(baseEngine, ownerRefs) 85 var ey environment.EngineYard = map[string]environment.Engine{ 86 environment.GoTplEngine: e, 87 } 88 env := &environment.Environment{ 89 EngineYard: ey, 90 Releases: f.storageBackend, 91 KubeClient: f.tillerKubeClient, 92 } 93 kubeconfig, _ := f.tillerKubeClient.ToRESTConfig() 94 cs := clientset.NewForConfigOrDie(kubeconfig) 95 96 return tiller.NewReleaseServer(env, cs, false) 97 } 98 99 func getReleaseName(r *unstructured.Unstructured) string { 100 return fmt.Sprintf("%s-%s", r.GetName(), shortenUID(r.GetUID())) 101 } 102 103 func shortenUID(uid apitypes.UID) string { 104 u := uuid.Parse(string(uid)) 105 uidBytes, err := u.MarshalBinary() 106 if err != nil { 107 return strings.Replace(string(uid), "-", "", -1) 108 } 109 return strings.ToLower(base36.EncodeBytes(uidBytes)) 110 }