package util import ( "context" "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" ) const ( guestbookCrdJson = `{ "apiVersion": "apiextensions.k8s.io/v1", "kind": "CustomResourceDefinition", "metadata": { "name": "guestbooks.my.domain" }, "spec": { "conversion": { "strategy": "None" }, "group": "my.domain", "names": { "kind": "Guestbook", "listKind": "GuestbookList", "plural": "guestbooks", "singular": "guestbook" }, "scope": "Namespaced", "versions": [ { "name": "v1", "schema": { "openAPIV3Schema": { "description": "", "properties": { "apiVersion": { "type": "string" }, "kind": { "type": "string" }, "metadata": { "type": "object" }, "spec": { "properties": { "foo": { "type": "string" } }, "type": "object" }, "status": { "type": "object" } }, "type": "object" } }, "served": true, "storage": true, "subresources": { "status": {} } } ] } }` guestbookCrJson = `{ "apiVersion": "my.domain/v1", "kind": "Guestbook", "metadata": { "name": "guestbook1", "namespace": "default" }, "spec": { "foo": "bar" } }` deploymentJson = `{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "name": "nginx-deployment", "namespace": "default" }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": null, "labels": { "app": "nginx" } }, "spec": { "containers": [ { "image": "nginx:1.14.2", "name": "nginx", "ports": [ { "containerPort": 80, "protocol": "TCP" } ] } ] } } } }` daemonsetJson = `{ "apiVersion": "apps/v1", "kind": "DaemonSet", "metadata": { "name": "nginx-daemonset", "namespace": "default" }, "spec": { "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "labels": { "app": "nginx" } }, "spec": { "containers": [ { "image": "nginx:1.14.2", "name": "nginx", "ports": [ { "containerPort": 80, "protocol": "TCP" } ] } ] } } } }` jobJson = `{ "apiVersion": "batch/v1", "kind": "Job", "metadata": { "name": "sleep-job", "namespace": "default" }, "spec": { "parallelism": 1, "template": { "metadata": { "creationTimestamp": null, "labels": { "app": "sleep" } }, "spec": { "containers": [ { "image": "ubuntu:latest", "name": "sleep", "command": ["sleep"], "args": ["20"] } ], "restartPolicy": "Never" } } } }` ) var ( scheme = runtime.NewScheme() serviceAccountGVK = schema.GroupVersionKind{ Group: "", Version: "v1", Kind: "ServiceAccount", } serviceAccountGVR = schema.GroupVersionResource{ Group: "", Version: "v1", Resource: "serviceaccounts", } roleGVK = schema.GroupVersionKind{ Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "Role", } roleGVR = schema.GroupVersionResource{ Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "roles", } clusterRoleGVK = schema.GroupVersionKind{ Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRole", } clusterRoleGVR = schema.GroupVersionResource{ Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterroles", } roleBindingGVK = schema.GroupVersionKind{ Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "RoleBinding", } roleBindingGVR = schema.GroupVersionResource{ Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "rolebindings", } ) func init() { _ = corev1.AddToScheme(scheme) _ = rbacv1.AddToScheme(scheme) } func GuestbookCrd() (crd *unstructured.Unstructured, gvr schema.GroupVersionResource, err error) { crd, err = loadResourceFromJSON(guestbookCrdJson) gvr = schema.GroupVersionResource{Group: "apiextensions.k8s.io", Version: "v1", Resource: "customresourcedefinitions"} return crd, gvr, err } func GuestbookCr(namespace, name string) (cr *unstructured.Unstructured, gvr schema.GroupVersionResource, err error) { cr, err = loadResourceFromJSON(guestbookCrJson) if err != nil { return cr, gvr, err } cr.SetNamespace(namespace) cr.SetName(name) gvr = schema.GroupVersionResource{Group: "my.domain", Version: "v1", Resource: "guestbooks"} return cr, gvr, nil } func NewDeployment(namespace, name, sa string) (u *unstructured.Unstructured, gvr schema.GroupVersionResource, err error) { u, err = loadResourceFromJSON(deploymentJson) if err != nil { return u, gvr, err } u.SetNamespace(namespace) u.SetName(name) err = unstructured.SetNestedField(u.Object, sa, "spec", "template", "spec", "serviceAccountName") if err != nil { return u, gvr, err } gvr = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"} return u, gvr, nil } func NewDaemonSet(namespace, name string) (u *unstructured.Unstructured, gvr schema.GroupVersionResource, err error) { u, err = loadResourceFromJSON(daemonsetJson) if err != nil { return u, gvr, err } u.SetNamespace(namespace) u.SetName(name) gvr = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "daemonsets"} return u, gvr, nil } func NewJob(namespace, name, sa string) (u *unstructured.Unstructured, gvr schema.GroupVersionResource, err error) { u, err = loadResourceFromJSON(jobJson) if err != nil { return u, gvr, err } u.SetNamespace(namespace) u.SetName(name) err = unstructured.SetNestedField(u.Object, sa, "spec", "template", "spec", "serviceAccountName") if err != nil { return u, gvr, err } gvr = schema.GroupVersionResource{Group: "batch", Version: "v1", Resource: "jobs"} return u, gvr, nil } func toUnstructured(obj runtime.Object, gvk schema.GroupVersionKind, scheme *runtime.Scheme) *unstructured.Unstructured { u := &unstructured.Unstructured{} gomega.Expect(scheme.Convert(obj, u, nil)).To(gomega.Succeed()) u.SetGroupVersionKind(gvk) return u } func NewServiceAccount(namespace, name string) (*unstructured.Unstructured, schema.GroupVersionResource) { obj := &corev1.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, Name: name, }, } return toUnstructured(obj, serviceAccountGVK, scheme), serviceAccountGVR } func NewRole(namespace, name string) (*unstructured.Unstructured, schema.GroupVersionResource) { obj := &rbacv1.Role{ ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, Name: name, }, Rules: []rbacv1.PolicyRule{ { Verbs: []string{"create", "get", "list", "watch"}, APIGroups: []string{""}, Resources: []string{"configmaps"}, }, }, } return toUnstructured(obj, roleGVK, scheme), roleGVR } func NewClusterRole(namespace, name string) (*unstructured.Unstructured, schema.GroupVersionResource) { obj := &rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, Name: name, }, Rules: []rbacv1.PolicyRule{ { Verbs: []string{"create", "get", "list", "watch"}, APIGroups: []string{""}, Resources: []string{"configmaps"}, }, }, } return toUnstructured(obj, clusterRoleGVK, scheme), clusterRoleGVR } func NewRoleBinding(namespace, name, sa, role string) (*unstructured.Unstructured, schema.GroupVersionResource) { obj := &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, Name: name, }, RoleRef: rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", Kind: "Role", Name: role, }, Subjects: []rbacv1.Subject{ { Kind: rbacv1.ServiceAccountKind, Namespace: namespace, Name: sa, }, }, } return toUnstructured(obj, roleBindingGVK, scheme), roleBindingGVR } func loadResourceFromJSON(json string) (*unstructured.Unstructured, error) { obj := unstructured.Unstructured{} err := obj.UnmarshalJSON([]byte(json)) return &obj, err } func GetResource(namespace, name string, gvr schema.GroupVersionResource, dynamicClient dynamic.Interface) (*unstructured.Unstructured, error) { return dynamicClient.Resource(gvr).Namespace(namespace).Get(context.TODO(), name, metav1.GetOptions{}) }