Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distribute CRDs using helm chart #1244

Merged
merged 10 commits into from
Mar 8, 2022
1 change: 1 addition & 0 deletions helm/kanister-operator/crds/actionset.yaml
1 change: 1 addition & 0 deletions helm/kanister-operator/crds/blueprint.yaml
1 change: 1 addition & 0 deletions helm/kanister-operator/crds/profile.yaml
3 changes: 3 additions & 0 deletions helm/kanister-operator/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ spec:
volumeMounts:
- name: webhook-certs
mountPath: /var/run/webhook/serving-cert
env:
- name: CREATEORUPDATE_CRDS
ihcsim marked this conversation as resolved.
Show resolved Hide resolved
value: {{ .Values.controller.updateCRDs | quote }}
{{- if .Values.resources }}
resources:
{{ toYaml .Values.resources | indent 12 }}
Expand Down
2 changes: 2 additions & 0 deletions helm/kanister-operator/templates/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ rules:
- events
verbs:
- create
{{- if .Values.controller.updateCRDs }}
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- "*"
{{- end }}
- apiGroups:
- snapshot.storage.k8s.io
resources:
Expand Down
4 changes: 4 additions & 0 deletions helm/kanister-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ serviceAccount:
controller:
service:
port: 443
# updateCRDs specifies if kanister controller should create/update the CRDs
# false : CRDs would be created by helm
# true : CRDs would be created by kanister controller
updateCRDs: true
resources:
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
package customresource

const actionsetCRD = `
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
Expand Down Expand Up @@ -252,4 +249,3 @@ status:
plural: ""
conditions: []
storedVersions: []
`
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
package customresource

const blueprintCRD = `
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
Expand Down Expand Up @@ -107,4 +104,3 @@ status:
plural: ""
conditions: []
storedVersions: []
`
32 changes: 15 additions & 17 deletions pkg/customresource/customresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,16 @@ import (
"time"

"github.com/Masterminds/semver"
"github.com/pkg/errors"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apimachinery/pkg/api/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"

"github.com/kanisterio/kanister/pkg/consts"

// importing go check to bypass the testing flags
_ "gopkg.in/check.v1"
)
Expand Down Expand Up @@ -114,15 +113,21 @@ func decodeSpecIntoObject(spec []byte, intoObj runtime.Object) error {
}

func createCRD(context Context, resource CustomResource) error {
crd, err := getCRDFromSpec(specFromResName(resource.Name))
c, err := rawCRDFromFile(fmt.Sprintf("%s.yaml", resource.Name))
if err != nil {
return errors.Wrap(err, "Getting raw CRD from CRD manifests")
}

crd, err := getCRDFromSpec(c)
if err != nil {
return err
return errors.Wrap(err, "Getting CRD object from CRD bytes")
}

ctx := contextpkg.Background()
_, err = context.APIExtensionClientset.ApiextensionsV1().CustomResourceDefinitions().Create(ctx, crd, metav1.CreateOptions{})
if err != nil {
if !errors.IsAlreadyExists(err) {
return fmt.Errorf("failed to create %s CRD. %+v", resource.Name, err)
if !apierrors.IsAlreadyExists(err) {
return errors.Errorf("Failed to create %s CRD. %+v", resource.Name, err)
ihcsim marked this conversation as resolved.
Show resolved Hide resolved
}

// if CRD already exists, get the resource version and create the CRD with that resource version
Expand All @@ -140,16 +145,9 @@ func createCRD(context Context, resource CustomResource) error {
return nil
}

func specFromResName(name string) []byte {
switch name {
case consts.ActionSetResourceName:
return []byte(actionsetCRD)
case consts.BlueprintResourceName:
return []byte(blueprintCRD)
case consts.ProfileResourceName:
return []byte(profileCRD)
}
return nil
func rawCRDFromFile(path string) ([]byte, error) {
// yamls is the variable that has embeded custom resource manifest. More at `embed.go`
return yamls.ReadFile(path)
}

func waitForCRDInit(context Context, resource CustomResource) error {
Expand Down
16 changes: 16 additions & 0 deletions pkg/customresource/embed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package customresource

import "embed"

// embed.go embeds the CRD yamls (actionset, profile, blueprint) with the
// controller binary so that we can read these manifests in runtime.

// We need these manfiests at two places, at `pkg/customresource/` and at
// `helm/kanister-operator/crds`. To make sure we are not duplicating the
// things we have original files at `pkg/customresource` and have soft links
// at `helm/kanister-operator/crds`.

//go:embed actionset.yaml
//go:embed blueprint.yaml
//go:embed profile.yaml
var yamls embed.FS
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
package customresource

const profileCRD = `
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
Expand Down Expand Up @@ -174,4 +171,3 @@ status:
plural: ""
conditions: []
storedVersions: []
`
31 changes: 27 additions & 4 deletions pkg/kancontroller/kancontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,24 @@ import (
"fmt"
"os"
"os/signal"
"strconv"
"syscall"

"k8s.io/client-go/rest"

"github.com/kanisterio/kanister/pkg/controller"
"github.com/kanisterio/kanister/pkg/field"
_ "github.com/kanisterio/kanister/pkg/function"
"github.com/kanisterio/kanister/pkg/handler"
"github.com/kanisterio/kanister/pkg/kube"
"github.com/kanisterio/kanister/pkg/log"
"github.com/kanisterio/kanister/pkg/resource"
)

const (
createOrUpdateCRDEnvVar = "CREATEORUPDATE_CRDS"
)

func Execute() {
ctx := context.Background()
// Initialize the clients.
Expand Down Expand Up @@ -73,10 +79,12 @@ func Execute() {
}()
}

// Make sure the CRD's exist.
if err := resource.CreateCustomResources(ctx, config); err != nil {
log.WithError(err).Print("Failed to create CustomResources.")
return
// CRDs should only be created/updated if the env var CREATEORUPDATE_CRDS is set to true
if createOrUpdateCRDs() {
if err := resource.CreateCustomResources(ctx, config); err != nil {
log.WithError(err).Print("Failed to create CustomResources.")
return
}
}

ns, err := kube.GetControllerNamespace()
Expand Down Expand Up @@ -112,3 +120,18 @@ func isCACertMounted() bool {

return true
}

func createOrUpdateCRDs() bool {
createOrUpdateCRD := os.Getenv(createOrUpdateCRDEnvVar)
if createOrUpdateCRD == "" {
return true
}

c, err := strconv.ParseBool(createOrUpdateCRD)
if err != nil {
log.Print("environment variable", field.M{"CREATEORUPDATE_CRDS": createOrUpdateCRD})
return true
}

return c
}