mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-08-23 22:26:49 +00:00
@@ -84,7 +84,7 @@ deploy-hub: install-olm munge-hub-csv
|
||||
sed -e "s,quay.io/open-cluster-management/registration,$(REGISTRATION_IMAGE)," deploy/nucleus-hub/crds/nucleus_open-cluster-management_hubcores.cr.yaml | $(KUBECTL) apply -f -
|
||||
|
||||
clean-hub: ensure-operator-sdk
|
||||
$(KUBECTL) delete -f deploy/nucleus-hub/crds/nucleus_open-cluster-management_hubcores.cr.yaml
|
||||
$(KUBECTL) delete -f deploy/nucleus-hub/crds/nucleus_open-cluster-management_hubcores.cr.yaml --ignore-not-found
|
||||
$(OPERATOR_SDK) cleanup --olm --operator-namespace open-cluster-management --operator-version 0.1.0 --manifests deploy/nucleus-hub/olm-catalog/nucleus-hub --olm-namespace $(OLM_NAMESPACE)
|
||||
|
||||
cluster-ip:
|
||||
@@ -110,7 +110,7 @@ deploy-spoke: install-olm munge-spoke-csv bootstrap-secret
|
||||
sed -e "s,quay.io/open-cluster-management/registration,$(REGISTRATION_IMAGE)," -e "s,quay.io/open-cluster-management/work,$(WORK_IMAGE)," deploy/nucleus-spoke/crds/nucleus_open-cluster-management_spokecores.cr.yaml | $(KUBECTL) apply -f -
|
||||
|
||||
clean-spoke: ensure-operator-sdk
|
||||
$(KUBECTL) delete -f deploy/nucleus-spoke/crds/nucleus_open-cluster-management_spokecores.cr.yaml
|
||||
$(KUBECTL) delete -f deploy/nucleus-spoke/crds/nucleus_open-cluster-management_spokecores.cr.yaml --ignore-not-found
|
||||
$(OPERATOR_SDK) cleanup --olm --operator-namespace open-cluster-management --operator-version 0.1.0 --manifests deploy/nucleus-spoke/olm-catalog/nucleus-spoke --olm-namespace $(OLM_NAMESPACE)
|
||||
|
||||
ensure-operator-sdk:
|
||||
|
||||
@@ -5,7 +5,7 @@ metadata:
|
||||
rules:
|
||||
# Allow nucleus to create workload
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps", "namespaces", "serviceaccounts"]
|
||||
resources: ["configmaps", "namespaces", "serviceaccounts", "services", "secrets"]
|
||||
verbs: ["create", "get", "list", "update", "watch", "patch", "delete"]
|
||||
- apiGroups: ["authorization.k8s.io"]
|
||||
resources: ["subjectaccessreviews"]
|
||||
@@ -26,6 +26,14 @@ rules:
|
||||
- apiGroups: ["apiextensions.k8s.io"]
|
||||
resources: ["customresourcedefinitions"]
|
||||
verbs: ["create", "get", "list", "update", "watch", "patch", "delete"]
|
||||
# Allow nucleus to create apiservice
|
||||
- apiGroups: ["apiregistration.k8s.io"]
|
||||
resources: ["apiservices"]
|
||||
verbs: ["create", "get", "list", "update", "watch", "patch", "delete"]
|
||||
# Allow nucleus to create validatingwebhookconfigurration
|
||||
- apiGroups: ["admissionregistration.k8s.io"]
|
||||
resources: ["validatingwebhookconfigurations"]
|
||||
verbs: ["create", "get", "list", "update", "watch", "patch", "delete"]
|
||||
# Allow nuclues to manage nucleus apis.
|
||||
- apiGroups: ["nucleus.open-cluster-management.io"]
|
||||
resources: ["hubcores"]
|
||||
|
||||
+26
@@ -39,6 +39,8 @@ spec:
|
||||
- configmaps
|
||||
- namespaces
|
||||
- serviceaccounts
|
||||
- services
|
||||
- secrets
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
@@ -114,6 +116,30 @@ spec:
|
||||
- watch
|
||||
- patch
|
||||
- delete
|
||||
- apiGroups:
|
||||
- apiregistration.k8s.io
|
||||
resources:
|
||||
- apiservices
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- update
|
||||
- watch
|
||||
- patch
|
||||
- delete
|
||||
- apiGroups:
|
||||
- admissionregistration.k8s.io
|
||||
resources:
|
||||
- validatingwebhookconfigurations
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- update
|
||||
- watch
|
||||
- patch
|
||||
- delete
|
||||
- apiGroups:
|
||||
- nucleus.open-cluster-management.io
|
||||
resources:
|
||||
|
||||
+1
@@ -66,6 +66,7 @@ spec:
|
||||
resources:
|
||||
- namespaces
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
|
||||
@@ -19,5 +19,6 @@ require (
|
||||
k8s.io/client-go v0.18.2
|
||||
k8s.io/component-base v0.18.2
|
||||
k8s.io/klog v1.0.0
|
||||
k8s.io/kube-aggregator v0.18.0
|
||||
sigs.k8s.io/controller-runtime v0.6.0
|
||||
)
|
||||
|
||||
@@ -78,6 +78,7 @@ github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/libnetwork v0.0.0-20190731215715-7f13a5c99f4b/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
@@ -276,6 +277,7 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
name: {{ .HubCoreName }}-sa
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}-registration-controller
|
||||
rules:
|
||||
# Allow hub to monitor and update status of csr
|
||||
- apiGroups: ["certificates.k8s.io"]
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}-registration-controller
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}-registration-controller
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
name: {{ .HubCoreName }}-registration-controller-sa
|
||||
@@ -1,23 +1,23 @@
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: {{ .HubCoreName }}-controller
|
||||
name: {{ .HubCoreName }}-registration-controller
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
labels:
|
||||
app: nucleushub-controller
|
||||
app: nucleushub-registration-controller
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nucleushub-controller
|
||||
app: nucleushub-registration-controller
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nucleushub-controller
|
||||
app: nucleushub-registration-controller
|
||||
spec:
|
||||
serviceAccountName: {{ .HubCoreName }}-sa
|
||||
serviceAccountName: {{ .HubCoreName }}-registration-controller-sa
|
||||
containers:
|
||||
- name: hub-controller
|
||||
- name: hub-registration-controller
|
||||
image: {{ .RegistrationImage }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
@@ -0,0 +1,5 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ .HubCoreName }}-registration-controller-sa
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: apiregistration.k8s.io/v1
|
||||
kind: APIService
|
||||
metadata:
|
||||
name: v1.admission.cluster.open-cluster-management.io
|
||||
spec:
|
||||
group: admission.cluster.open-cluster-management.io
|
||||
version: v1
|
||||
service:
|
||||
name: {{ .HubCoreWebhookRegistrationService }}
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
caBundle: {{ .RegistrationAPIServiceCABundle }}
|
||||
groupPriorityMinimum: 10000
|
||||
versionPriority: 20
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}-registration-webhook
|
||||
rules:
|
||||
# Allow spokecluster admission to get/list/watch configmaps
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
# Allow spokecluster admission to create subjectaccessreviews
|
||||
- apiGroups: ["authorization.k8s.io"]
|
||||
resources: ["subjectaccessreviews"]
|
||||
verbs: ["create"]
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}-registration-webhook
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{ .HubCoreName }}-registration-webhook
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ .HubCoreName }}-registration-webhook-sa
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
@@ -0,0 +1,50 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .HubCoreName }}-registration-webhook
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
labels:
|
||||
app: {{ .HubCoreName }}-registration-webhook
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ .HubCoreName }}-registration-webhook
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ .HubCoreName }}-registration-webhook
|
||||
spec:
|
||||
serviceAccountName: {{ .HubCoreName }}-registration-webhook-sa
|
||||
containers:
|
||||
- name: {{ .HubCoreName }}-registration-webhook-sa
|
||||
image: {{ .RegistrationImage }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- "/registration"
|
||||
- "webhook"
|
||||
- "--secure-port=6443"
|
||||
- "--tls-cert-file=/serving-cert/tls.crt"
|
||||
- "--tls-private-key-file=/serving-cert/tls.key"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
scheme: HTTPS
|
||||
port: 6443
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
scheme: HTTPS
|
||||
port: 6443
|
||||
initialDelaySeconds: 2
|
||||
volumeMounts:
|
||||
- name: webhook-secret
|
||||
mountPath: "/serving-cert"
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: webhook-secret
|
||||
secret:
|
||||
secretName: {{ .HubCoreWebhookSecret }}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ .HubCoreWebhookSecret }}
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
data:
|
||||
tls.crt: {{ .RegistrationServingCert }}
|
||||
tls.key: {{ .RegistrationServingKey }}
|
||||
ca.crt: {{ .RegistrationAPIServiceCABundle }}
|
||||
type: Opaque
|
||||
@@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .HubCoreWebhookRegistrationService }}
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
spec:
|
||||
selector:
|
||||
app: {{ .HubCoreName }}-registration-webhook
|
||||
ports:
|
||||
- port: 443
|
||||
targetPort: 6443
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ .HubCoreName }}-sa
|
||||
name: {{ .HubCoreName }}-registration-webhook-sa
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
@@ -0,0 +1,26 @@
|
||||
apiVersion: admissionregistration.k8s.io/v1
|
||||
kind: ValidatingWebhookConfiguration
|
||||
metadata:
|
||||
name: spokeclustervalidators.admission.cluster.open-cluster-management.io
|
||||
webhooks:
|
||||
- name: spokeclustervalidators.admission.cluster.open-cluster-management.io
|
||||
failurePolicy: Fail
|
||||
clientConfig:
|
||||
service:
|
||||
# reach the webhook via the registered aggregated API
|
||||
namespace: default
|
||||
name: kubernetes
|
||||
path: /apis/admission.cluster.open-cluster-management.io/v1/spokeclustervalidators
|
||||
rules:
|
||||
- operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
apiGroups:
|
||||
- cluster.open-cluster-management.io
|
||||
apiVersions:
|
||||
- "*"
|
||||
resources:
|
||||
- spokeclusters
|
||||
admissionReviewVersions: ["v1beta1"]
|
||||
sideEffects: None
|
||||
timeoutSeconds: 3
|
||||
+142
-5
@@ -7,6 +7,8 @@ import (
|
||||
|
||||
nucleusv1client "github.com/open-cluster-management/api/client/nucleus/clientset/versioned/typed/nucleus/v1"
|
||||
nucleusapiv1 "github.com/open-cluster-management/api/nucleus/v1"
|
||||
admissionv1 "k8s.io/api/admissionregistration/v1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
@@ -16,10 +18,33 @@ import (
|
||||
"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"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
admissionclient "k8s.io/client-go/kubernetes/typed/admissionregistration/v1"
|
||||
"k8s.io/client-go/util/retry"
|
||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||
apiregistrationclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1"
|
||||
|
||||
"github.com/openshift/api"
|
||||
"github.com/openshift/library-go/pkg/operator/events"
|
||||
"github.com/openshift/library-go/pkg/operator/resource/resourceapply"
|
||||
"github.com/openshift/library-go/pkg/operator/resource/resourcemerge"
|
||||
)
|
||||
|
||||
var (
|
||||
genericScheme = runtime.NewScheme()
|
||||
genericCodecs = serializer.NewCodecFactory(genericScheme)
|
||||
genericCodec = genericCodecs.UniversalDeserializer()
|
||||
)
|
||||
|
||||
func init() {
|
||||
utilruntime.Must(api.InstallKube(genericScheme))
|
||||
utilruntime.Must(apiextensionsv1beta1.AddToScheme(genericScheme))
|
||||
utilruntime.Must(apiregistrationv1.AddToScheme(genericScheme))
|
||||
utilruntime.Must(admissionv1.AddToScheme(genericScheme))
|
||||
}
|
||||
|
||||
func IsConditionTrue(condition *nucleusapiv1.StatusCondition) bool {
|
||||
if condition == nil {
|
||||
return false
|
||||
@@ -159,9 +184,18 @@ func UpdateNucleusSpokeConditionFn(conds ...nucleusapiv1.StatusCondition) Update
|
||||
func CleanUpStaticObject(
|
||||
ctx context.Context,
|
||||
client kubernetes.Interface,
|
||||
apiextensionclient apiextensionsclient.Interface,
|
||||
object runtime.Object) error {
|
||||
var err error
|
||||
apiExtensionClient apiextensionsclient.Interface,
|
||||
apiRegistrationClient apiregistrationclient.APIServicesGetter,
|
||||
manifests resourceapply.AssetFunc,
|
||||
file string) error {
|
||||
objectRaw, err := manifests(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
object, _, err := genericCodec.Decode(objectRaw, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch t := object.(type) {
|
||||
case *corev1.Namespace:
|
||||
err = client.CoreV1().Namespaces().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
@@ -182,9 +216,13 @@ func CleanUpStaticObject(
|
||||
case *rbacv1.RoleBinding:
|
||||
err = client.RbacV1().RoleBindings(t.Namespace).Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
case *apiextensionsv1.CustomResourceDefinition:
|
||||
err = apiextensionclient.ApiextensionsV1().CustomResourceDefinitions().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
err = apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
case *apiextensionsv1beta1.CustomResourceDefinition:
|
||||
err = apiextensionclient.ApiextensionsV1beta1().CustomResourceDefinitions().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
case *apiregistrationv1.APIService:
|
||||
err = apiRegistrationClient.APIServices().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
case *admissionv1.ValidatingWebhookConfiguration:
|
||||
err = client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Delete(ctx, t.Name, metav1.DeleteOptions{})
|
||||
default:
|
||||
err = fmt.Errorf("unhandled type %T", object)
|
||||
}
|
||||
@@ -193,3 +231,102 @@ func CleanUpStaticObject(
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func ApplyValidatingWebhookConfiguration(
|
||||
client admissionclient.ValidatingWebhookConfigurationsGetter,
|
||||
required *admissionv1.ValidatingWebhookConfiguration) (*admissionv1.ValidatingWebhookConfiguration, bool, error) {
|
||||
existing, err := client.ValidatingWebhookConfigurations().Get(context.TODO(), required.Name, metav1.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
actual, err := client.ValidatingWebhookConfigurations().Create(context.TODO(), required, metav1.CreateOptions{})
|
||||
return actual, true, err
|
||||
}
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
modified := resourcemerge.BoolPtr(false)
|
||||
existingCopy := existing.DeepCopy()
|
||||
resourcemerge.EnsureObjectMeta(modified, &existingCopy.ObjectMeta, required.ObjectMeta)
|
||||
if !equality.Semantic.DeepEqual(existingCopy.Webhooks, required.Webhooks) {
|
||||
*modified = true
|
||||
existing.Webhooks = required.Webhooks
|
||||
}
|
||||
if !*modified {
|
||||
return existing, false, nil
|
||||
}
|
||||
|
||||
actual, err := client.ValidatingWebhookConfigurations().Update(context.TODO(), existingCopy, metav1.UpdateOptions{})
|
||||
return actual, true, err
|
||||
}
|
||||
|
||||
func ApplyDeployment(
|
||||
client kubernetes.Interface, generation int64, manifests resourceapply.AssetFunc, recorder events.Recorder, file string) (int64, error) {
|
||||
deploymentBytes, err := manifests(file)
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
deployment, _, err := genericCodec.Decode(deploymentBytes, nil, nil)
|
||||
if err != nil {
|
||||
return generation, fmt.Errorf("%q: %v", file, err)
|
||||
}
|
||||
updatedDeployment, updated, err := resourceapply.ApplyDeployment(
|
||||
client.AppsV1(),
|
||||
recorder,
|
||||
deployment.(*appsv1.Deployment), generation, false)
|
||||
if err != nil {
|
||||
return generation, fmt.Errorf("%q (%T): %v", file, deployment, err)
|
||||
}
|
||||
|
||||
if updated {
|
||||
generation = updatedDeployment.ObjectMeta.Generation
|
||||
}
|
||||
|
||||
return generation, nil
|
||||
}
|
||||
|
||||
func ApplyDirectly(
|
||||
client kubernetes.Interface,
|
||||
apiExtensionClient apiextensionsclient.Interface,
|
||||
apiRegistrationClient apiregistrationclient.APIServicesGetter,
|
||||
recorder events.Recorder,
|
||||
manifests resourceapply.AssetFunc,
|
||||
files ...string) []resourceapply.ApplyResult {
|
||||
ret := []resourceapply.ApplyResult{}
|
||||
genericApplyFiles := []string{}
|
||||
for _, file := range files {
|
||||
result := resourceapply.ApplyResult{File: file}
|
||||
objBytes, err := manifests(file)
|
||||
if err != nil {
|
||||
result.Error = fmt.Errorf("missing %q: %v", file, err)
|
||||
ret = append(ret, result)
|
||||
continue
|
||||
}
|
||||
requiredObj, _, err := genericCodec.Decode(objBytes, nil, nil)
|
||||
if err != nil {
|
||||
result.Error = fmt.Errorf("cannot decode %q: %v", file, err)
|
||||
ret = append(ret, result)
|
||||
continue
|
||||
}
|
||||
result.Type = fmt.Sprintf("%T", requiredObj)
|
||||
switch t := requiredObj.(type) {
|
||||
case *admissionv1.ValidatingWebhookConfiguration:
|
||||
result.Result, result.Changed, result.Error = ApplyValidatingWebhookConfiguration(
|
||||
client.AdmissionregistrationV1(), t)
|
||||
case *apiregistrationv1.APIService:
|
||||
result.Result, result.Changed, result.Error = resourceapply.ApplyAPIService(apiRegistrationClient, recorder, t)
|
||||
default:
|
||||
genericApplyFiles = append(genericApplyFiles, file)
|
||||
}
|
||||
}
|
||||
|
||||
clientHolder := resourceapply.NewKubeClientHolder(client).WithAPIExtensionsClient(apiExtensionClient)
|
||||
applyResults := resourceapply.ApplyDirectly(
|
||||
clientHolder,
|
||||
recorder,
|
||||
manifests,
|
||||
genericApplyFiles...,
|
||||
)
|
||||
|
||||
ret = append(ret, applyResults...)
|
||||
return ret
|
||||
}
|
||||
|
||||
+227
-9
@@ -2,14 +2,24 @@ package helpers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
nucleusfake "github.com/open-cluster-management/api/client/nucleus/clientset/versioned/fake"
|
||||
nucleusapiv1 "github.com/open-cluster-management/api/nucleus/v1"
|
||||
"github.com/openshift/library-go/pkg/operator/events/eventstesting"
|
||||
operatorhelpers "github.com/openshift/library-go/pkg/operator/v1helpers"
|
||||
admissionv1 "k8s.io/api/admissionregistration/v1"
|
||||
fakeapiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
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/util/diff"
|
||||
fakekube "k8s.io/client-go/kubernetes/fake"
|
||||
fakeapiregistration "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake"
|
||||
)
|
||||
|
||||
func TestUpdateStatusCondition(t *testing.T) {
|
||||
@@ -21,14 +31,14 @@ func TestUpdateStatusCondition(t *testing.T) {
|
||||
name string
|
||||
startingConditions []nucleusapiv1.StatusCondition
|
||||
newCondition nucleusapiv1.StatusCondition
|
||||
expextedUpdated bool
|
||||
expectedUpdated bool
|
||||
expectedConditions []nucleusapiv1.StatusCondition
|
||||
}{
|
||||
{
|
||||
name: "add to empty",
|
||||
startingConditions: []nucleusapiv1.StatusCondition{},
|
||||
newCondition: newCondition("test", "True", "my-reason", "my-message", nil),
|
||||
expextedUpdated: true,
|
||||
expectedUpdated: true,
|
||||
expectedConditions: []nucleusapiv1.StatusCondition{newCondition("test", "True", "my-reason", "my-message", nil)},
|
||||
},
|
||||
{
|
||||
@@ -37,7 +47,7 @@ func TestUpdateStatusCondition(t *testing.T) {
|
||||
newCondition("two", "True", "my-reason", "my-message", nil),
|
||||
},
|
||||
newCondition: newCondition("one", "True", "my-reason", "my-message", nil),
|
||||
expextedUpdated: true,
|
||||
expectedUpdated: true,
|
||||
expectedConditions: []nucleusapiv1.StatusCondition{
|
||||
newCondition("two", "True", "my-reason", "my-message", nil),
|
||||
newCondition("one", "True", "my-reason", "my-message", nil),
|
||||
@@ -50,7 +60,7 @@ func TestUpdateStatusCondition(t *testing.T) {
|
||||
newCondition("one", "True", "my-reason", "my-message", nil),
|
||||
},
|
||||
newCondition: newCondition("one", "False", "my-different-reason", "my-othermessage", nil),
|
||||
expextedUpdated: true,
|
||||
expectedUpdated: true,
|
||||
expectedConditions: []nucleusapiv1.StatusCondition{
|
||||
newCondition("two", "True", "my-reason", "my-message", nil),
|
||||
newCondition("one", "False", "my-different-reason", "my-othermessage", nil),
|
||||
@@ -63,7 +73,7 @@ func TestUpdateStatusCondition(t *testing.T) {
|
||||
newCondition("one", "True", "my-reason", "my-message", &beforeish),
|
||||
},
|
||||
newCondition: newCondition("one", "True", "my-reason", "my-message", &afterish),
|
||||
expextedUpdated: false,
|
||||
expectedUpdated: false,
|
||||
expectedConditions: []nucleusapiv1.StatusCondition{
|
||||
newCondition("two", "True", "my-reason", "my-message", nil),
|
||||
newCondition("one", "True", "my-reason", "my-message", &beforeish),
|
||||
@@ -97,8 +107,8 @@ func TestUpdateStatusCondition(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("unexpected err: %v", err)
|
||||
}
|
||||
if updated != c.expextedUpdated {
|
||||
t.Errorf("expected %t, but %t", c.expextedUpdated, updated)
|
||||
if updated != c.expectedUpdated {
|
||||
t.Errorf("expected %t, but %t", c.expectedUpdated, updated)
|
||||
}
|
||||
|
||||
spokestatus, updated, err := UpdateNucleusSpokeStatus(
|
||||
@@ -110,8 +120,8 @@ func TestUpdateStatusCondition(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("unexpected err: %v", err)
|
||||
}
|
||||
if updated != c.expextedUpdated {
|
||||
t.Errorf("expected %t, but %t", c.expextedUpdated, updated)
|
||||
if updated != c.expectedUpdated {
|
||||
t.Errorf("expected %t, but %t", c.expectedUpdated, updated)
|
||||
}
|
||||
|
||||
for i := range c.expectedConditions {
|
||||
@@ -148,3 +158,211 @@ func newCondition(name, status, reason, message string, lastTransition *metav1.T
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func newValidatingWebhookConfiguration(name, svc, svcNameSpace string) *admissionv1.ValidatingWebhookConfiguration {
|
||||
return &admissionv1.ValidatingWebhookConfiguration{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Webhooks: []admissionv1.ValidatingWebhook{
|
||||
{
|
||||
ClientConfig: admissionv1.WebhookClientConfig{
|
||||
Service: &admissionv1.ServiceReference{
|
||||
Name: svc,
|
||||
Namespace: svcNameSpace,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newUnstructured(
|
||||
apiVersion, kind, namespace, name string, content map[string]interface{}) *unstructured.Unstructured {
|
||||
object := &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": apiVersion,
|
||||
"kind": kind,
|
||||
"metadata": map[string]interface{}{
|
||||
"namespace": namespace,
|
||||
"name": name,
|
||||
},
|
||||
},
|
||||
}
|
||||
for key, val := range content {
|
||||
object.Object[key] = val
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func TestApplyValidatingWebhookConfiguration(t *testing.T) {
|
||||
testcase := []struct {
|
||||
name string
|
||||
existing []runtime.Object
|
||||
expected *admissionv1.ValidatingWebhookConfiguration
|
||||
expectUpdated bool
|
||||
}{
|
||||
{
|
||||
name: "Create a new configuration",
|
||||
expectUpdated: true,
|
||||
existing: []runtime.Object{},
|
||||
expected: newValidatingWebhookConfiguration("test", "svc1", "svc1"),
|
||||
},
|
||||
{
|
||||
name: "update an existing configuration",
|
||||
expectUpdated: true,
|
||||
existing: []runtime.Object{newValidatingWebhookConfiguration("test", "svc1", "svc1")},
|
||||
expected: newValidatingWebhookConfiguration("test", "svc2", "svc2"),
|
||||
},
|
||||
{
|
||||
name: "skip update",
|
||||
expectUpdated: false,
|
||||
existing: []runtime.Object{newValidatingWebhookConfiguration("test", "svc1", "svc1")},
|
||||
expected: newValidatingWebhookConfiguration("test", "svc1", "svc1"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range testcase {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
fakeKubeClient := fakekube.NewSimpleClientset(c.existing...)
|
||||
_, updated, err := ApplyValidatingWebhookConfiguration(fakeKubeClient.AdmissionregistrationV1(), c.expected)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error when applying: %v", err)
|
||||
}
|
||||
|
||||
if updated != c.expectUpdated {
|
||||
t.Errorf("Expect update is %t, but got %t", c.expectUpdated, updated)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyDirectly(t *testing.T) {
|
||||
testcase := []struct {
|
||||
name string
|
||||
applyFiles map[string]runtime.Object
|
||||
applyFileNames []string
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "Apply webhooks & apiservice & secret",
|
||||
applyFiles: map[string]runtime.Object{
|
||||
"webhooks": newUnstructured("admissionregistration.k8s.io/v1", "ValidatingWebhookConfiguration", "", "", map[string]interface{}{"webhooks": []interface{}{}}),
|
||||
"apiservice": newUnstructured("apiregistration.k8s.io/v1", "APIService", "", "", map[string]interface{}{"spec": map[string]interface{}{"service": map[string]string{"name": "svc1", "namespace": "svc1"}}}),
|
||||
"secret": newUnstructured("v1", "Secret", "ns1", "n1", map[string]interface{}{"data": map[string]interface{}{"key1": []byte("key1")}}),
|
||||
},
|
||||
applyFileNames: []string{"webhooks", "apiservice", "secret"},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Apply unhandled object",
|
||||
applyFiles: map[string]runtime.Object{
|
||||
"kind1": newUnstructured("v1", "Kind1", "ns1", "n1", map[string]interface{}{"spec": map[string]interface{}{"key1": []byte("key1")}}),
|
||||
},
|
||||
applyFileNames: []string{"kind1"},
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range testcase {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
fakeKubeClient := fakekube.NewSimpleClientset()
|
||||
fakeResgistrationClient := fakeapiregistration.NewSimpleClientset()
|
||||
fakeExtensionClient := fakeapiextensions.NewSimpleClientset()
|
||||
results := ApplyDirectly(
|
||||
fakeKubeClient, fakeExtensionClient, fakeResgistrationClient.ApiregistrationV1(),
|
||||
eventstesting.NewTestingEventRecorder(t),
|
||||
func(name string) ([]byte, error) {
|
||||
if c.applyFiles[name] == nil {
|
||||
return nil, fmt.Errorf("Failed to find file")
|
||||
}
|
||||
|
||||
return json.Marshal(c.applyFiles[name])
|
||||
},
|
||||
c.applyFileNames...,
|
||||
)
|
||||
aggregatedErr := []error{}
|
||||
for _, r := range results {
|
||||
if r.Error != nil {
|
||||
aggregatedErr = append(aggregatedErr, r.Error)
|
||||
}
|
||||
}
|
||||
|
||||
if len(aggregatedErr) == 0 && c.expectErr {
|
||||
t.Errorf("Expect an apply error")
|
||||
}
|
||||
if len(aggregatedErr) != 0 && !c.expectErr {
|
||||
t.Errorf("Expect no apply error, %v", operatorhelpers.NewMultiLineAggregate(aggregatedErr))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteStaticObject(t *testing.T) {
|
||||
applyFiles := map[string]runtime.Object{
|
||||
"webhooks": newUnstructured("admissionregistration.k8s.io/v1", "ValidatingWebhookConfiguration", "", "", map[string]interface{}{"webhooks": []interface{}{}}),
|
||||
"apiservice": newUnstructured("apiregistration.k8s.io/v1", "APIService", "", "", map[string]interface{}{"spec": map[string]interface{}{"service": map[string]string{"name": "svc1", "namespace": "svc1"}}}),
|
||||
"secret": newUnstructured("v1", "Secret", "ns1", "n1", map[string]interface{}{"data": map[string]interface{}{"key1": []byte("key1")}}),
|
||||
"crd": newUnstructured("apiextensions.k8s.io/v1beta1", "CustomResourceDefinition", "", "", map[string]interface{}{}),
|
||||
"kind1": newUnstructured("v1", "Kind1", "ns1", "n1", map[string]interface{}{"spec": map[string]interface{}{"key1": []byte("key1")}}),
|
||||
}
|
||||
testcase := []struct {
|
||||
name string
|
||||
applyFileName string
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "Delete webhooks",
|
||||
applyFileName: "webhooks",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Delete apiservice",
|
||||
applyFileName: "apiservice",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Delete secret",
|
||||
applyFileName: "secret",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Delete crd",
|
||||
applyFileName: "crd",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Delete unhandled object",
|
||||
applyFileName: "kind1",
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range testcase {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
fakeKubeClient := fakekube.NewSimpleClientset()
|
||||
fakeResgistrationClient := fakeapiregistration.NewSimpleClientset()
|
||||
fakeExtensionClient := fakeapiextensions.NewSimpleClientset()
|
||||
err := CleanUpStaticObject(
|
||||
context.TODO(),
|
||||
fakeKubeClient, fakeExtensionClient, fakeResgistrationClient.ApiregistrationV1(),
|
||||
func(name string) ([]byte, error) {
|
||||
if applyFiles[name] == nil {
|
||||
return nil, fmt.Errorf("Failed to find file")
|
||||
}
|
||||
|
||||
return json.Marshal(applyFiles[name])
|
||||
},
|
||||
c.applyFileName,
|
||||
)
|
||||
|
||||
if err == nil && c.expectErr {
|
||||
t.Errorf("Expect an apply error")
|
||||
}
|
||||
if err != nil && !c.expectErr {
|
||||
t.Errorf("Expect no apply error, %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,19 @@
|
||||
// sources:
|
||||
// manifests/hub/0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml
|
||||
// manifests/hub/0000_00_work.open-cluster-management.io_manifestworks.crd.yaml
|
||||
// manifests/hub/hub-clusterrole.yaml
|
||||
// manifests/hub/hub-clusterrolebinding.yaml
|
||||
// manifests/hub/hub-deployment.yaml
|
||||
// manifests/hub/hub-namespace.yaml
|
||||
// manifests/hub/hub-serviceaccount.yaml
|
||||
// manifests/hub/hub-registration-clusterrole.yaml
|
||||
// manifests/hub/hub-registration-clusterrolebinding.yaml
|
||||
// manifests/hub/hub-registration-deployment.yaml
|
||||
// manifests/hub/hub-registration-serviceaccount.yaml
|
||||
// manifests/hub/hub-registration-webhook-apiservice.yaml
|
||||
// manifests/hub/hub-registration-webhook-clusterrole.yaml
|
||||
// manifests/hub/hub-registration-webhook-clusterrolebinding.yaml
|
||||
// manifests/hub/hub-registration-webhook-deployment.yaml
|
||||
// manifests/hub/hub-registration-webhook-secret.yaml
|
||||
// manifests/hub/hub-registration-webhook-service.yaml
|
||||
// manifests/hub/hub-registration-webhook-serviceaccount.yaml
|
||||
// manifests/hub/hub-registration-webhook-validatingconfiguration.yaml
|
||||
// DO NOT EDIT!
|
||||
|
||||
package bindata
|
||||
@@ -411,10 +419,31 @@ func manifestsHub0000_00_workOpenClusterManagementIo_manifestworksCrdYaml() (*as
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubClusterroleYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
|
||||
var _manifestsHubHubNamespaceYaml = []byte(`apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: {{ .HubCoreNamespace }}
|
||||
`)
|
||||
|
||||
func manifestsHubHubNamespaceYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubNamespaceYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubNamespaceYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubNamespaceYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-namespace.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubRegistrationClusterroleYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}-registration-controller
|
||||
rules:
|
||||
# Allow hub to monitor and update status of csr
|
||||
- apiGroups: ["certificates.k8s.io"]
|
||||
@@ -449,70 +478,70 @@ rules:
|
||||
verbs: ["update", "patch"]
|
||||
`)
|
||||
|
||||
func manifestsHubHubClusterroleYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubClusterroleYaml, nil
|
||||
func manifestsHubHubRegistrationClusterroleYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubRegistrationClusterroleYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubClusterroleYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubClusterroleYamlBytes()
|
||||
func manifestsHubHubRegistrationClusterroleYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubRegistrationClusterroleYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-clusterrole.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-registration-clusterrole.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
|
||||
var _manifestsHubHubRegistrationClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}-registration-controller
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}-registration-controller
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
name: {{ .HubCoreName }}-sa
|
||||
name: {{ .HubCoreName }}-registration-controller-sa
|
||||
`)
|
||||
|
||||
func manifestsHubHubClusterrolebindingYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubClusterrolebindingYaml, nil
|
||||
func manifestsHubHubRegistrationClusterrolebindingYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubRegistrationClusterrolebindingYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubClusterrolebindingYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubClusterrolebindingYamlBytes()
|
||||
func manifestsHubHubRegistrationClusterrolebindingYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubRegistrationClusterrolebindingYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-registration-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubDeploymentYaml = []byte(`kind: Deployment
|
||||
var _manifestsHubHubRegistrationDeploymentYaml = []byte(`kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: {{ .HubCoreName }}-controller
|
||||
name: {{ .HubCoreName }}-registration-controller
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
labels:
|
||||
app: nucleushub-controller
|
||||
app: nucleushub-registration-controller
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nucleushub-controller
|
||||
app: nucleushub-registration-controller
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nucleushub-controller
|
||||
app: nucleushub-registration-controller
|
||||
spec:
|
||||
serviceAccountName: {{ .HubCoreName }}-sa
|
||||
serviceAccountName: {{ .HubCoreName }}-registration-controller-sa
|
||||
containers:
|
||||
- name: hub-controller
|
||||
- name: hub-registration-controller
|
||||
image: {{ .RegistrationImage }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
@@ -533,60 +562,315 @@ spec:
|
||||
initialDelaySeconds: 2
|
||||
`)
|
||||
|
||||
func manifestsHubHubDeploymentYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubDeploymentYaml, nil
|
||||
func manifestsHubHubRegistrationDeploymentYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubRegistrationDeploymentYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubDeploymentYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubDeploymentYamlBytes()
|
||||
func manifestsHubHubRegistrationDeploymentYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubRegistrationDeploymentYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-registration-deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubNamespaceYaml = []byte(`apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: {{ .HubCoreNamespace }}
|
||||
`)
|
||||
|
||||
func manifestsHubHubNamespaceYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubNamespaceYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubNamespaceYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubNamespaceYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-namespace.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubServiceaccountYaml = []byte(`apiVersion: v1
|
||||
var _manifestsHubHubRegistrationServiceaccountYaml = []byte(`apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ .HubCoreName }}-sa
|
||||
name: {{ .HubCoreName }}-registration-controller-sa
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
`)
|
||||
|
||||
func manifestsHubHubServiceaccountYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubServiceaccountYaml, nil
|
||||
func manifestsHubHubRegistrationServiceaccountYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubRegistrationServiceaccountYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubServiceaccountYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubServiceaccountYamlBytes()
|
||||
func manifestsHubHubRegistrationServiceaccountYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubRegistrationServiceaccountYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-registration-serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubRegistrationWebhookApiserviceYaml = []byte(`apiVersion: apiregistration.k8s.io/v1
|
||||
kind: APIService
|
||||
metadata:
|
||||
name: v1.admission.cluster.open-cluster-management.io
|
||||
spec:
|
||||
group: admission.cluster.open-cluster-management.io
|
||||
version: v1
|
||||
service:
|
||||
name: {{ .HubCoreWebhookRegistrationService }}
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
caBundle: {{ .RegistrationAPIServiceCABundle }}
|
||||
groupPriorityMinimum: 10000
|
||||
versionPriority: 20
|
||||
`)
|
||||
|
||||
func manifestsHubHubRegistrationWebhookApiserviceYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubRegistrationWebhookApiserviceYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubRegistrationWebhookApiserviceYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubRegistrationWebhookApiserviceYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-apiservice.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubRegistrationWebhookClusterroleYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}-registration-webhook
|
||||
rules:
|
||||
# Allow spokecluster admission to get/list/watch configmaps
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
# Allow spokecluster admission to create subjectaccessreviews
|
||||
- apiGroups: ["authorization.k8s.io"]
|
||||
resources: ["subjectaccessreviews"]
|
||||
verbs: ["create"]
|
||||
`)
|
||||
|
||||
func manifestsHubHubRegistrationWebhookClusterroleYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubRegistrationWebhookClusterroleYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubRegistrationWebhookClusterroleYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubRegistrationWebhookClusterroleYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-clusterrole.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubRegistrationWebhookClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: system:open-cluster-management:{{ .HubCoreName }}-registration-webhook
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{ .HubCoreName }}-registration-webhook
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ .HubCoreName }}-registration-webhook-sa
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
`)
|
||||
|
||||
func manifestsHubHubRegistrationWebhookClusterrolebindingYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubRegistrationWebhookClusterrolebindingYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubRegistrationWebhookClusterrolebindingYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubRegistrationWebhookClusterrolebindingYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubRegistrationWebhookDeploymentYaml = []byte(`apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .HubCoreName }}-registration-webhook
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
labels:
|
||||
app: {{ .HubCoreName }}-registration-webhook
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ .HubCoreName }}-registration-webhook
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ .HubCoreName }}-registration-webhook
|
||||
spec:
|
||||
serviceAccountName: {{ .HubCoreName }}-registration-webhook-sa
|
||||
containers:
|
||||
- name: {{ .HubCoreName }}-registration-webhook-sa
|
||||
image: {{ .RegistrationImage }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- "/registration"
|
||||
- "webhook"
|
||||
- "--secure-port=6443"
|
||||
- "--tls-cert-file=/serving-cert/tls.crt"
|
||||
- "--tls-private-key-file=/serving-cert/tls.key"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
scheme: HTTPS
|
||||
port: 6443
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
scheme: HTTPS
|
||||
port: 6443
|
||||
initialDelaySeconds: 2
|
||||
volumeMounts:
|
||||
- name: webhook-secret
|
||||
mountPath: "/serving-cert"
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: webhook-secret
|
||||
secret:
|
||||
secretName: {{ .HubCoreWebhookSecret }}
|
||||
|
||||
`)
|
||||
|
||||
func manifestsHubHubRegistrationWebhookDeploymentYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubRegistrationWebhookDeploymentYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubRegistrationWebhookDeploymentYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubRegistrationWebhookDeploymentYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubRegistrationWebhookSecretYaml = []byte(`apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ .HubCoreWebhookSecret }}
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
data:
|
||||
tls.crt: {{ .RegistrationServingCert }}
|
||||
tls.key: {{ .RegistrationServingKey }}
|
||||
ca.crt: {{ .RegistrationAPIServiceCABundle }}
|
||||
type: Opaque
|
||||
`)
|
||||
|
||||
func manifestsHubHubRegistrationWebhookSecretYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubRegistrationWebhookSecretYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubRegistrationWebhookSecretYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubRegistrationWebhookSecretYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-secret.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubRegistrationWebhookServiceYaml = []byte(`apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .HubCoreWebhookRegistrationService }}
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
spec:
|
||||
selector:
|
||||
app: {{ .HubCoreName }}-registration-webhook
|
||||
ports:
|
||||
- port: 443
|
||||
targetPort: 6443
|
||||
`)
|
||||
|
||||
func manifestsHubHubRegistrationWebhookServiceYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubRegistrationWebhookServiceYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubRegistrationWebhookServiceYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubRegistrationWebhookServiceYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-service.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubRegistrationWebhookServiceaccountYaml = []byte(`apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ .HubCoreName }}-registration-webhook-sa
|
||||
namespace: {{ .HubCoreNamespace }}
|
||||
`)
|
||||
|
||||
func manifestsHubHubRegistrationWebhookServiceaccountYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubRegistrationWebhookServiceaccountYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubRegistrationWebhookServiceaccountYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubRegistrationWebhookServiceaccountYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _manifestsHubHubRegistrationWebhookValidatingconfigurationYaml = []byte(`apiVersion: admissionregistration.k8s.io/v1
|
||||
kind: ValidatingWebhookConfiguration
|
||||
metadata:
|
||||
name: spokeclustervalidators.admission.cluster.open-cluster-management.io
|
||||
webhooks:
|
||||
- name: spokeclustervalidators.admission.cluster.open-cluster-management.io
|
||||
failurePolicy: Fail
|
||||
clientConfig:
|
||||
service:
|
||||
# reach the webhook via the registered aggregated API
|
||||
namespace: default
|
||||
name: kubernetes
|
||||
path: /apis/admission.cluster.open-cluster-management.io/v1/spokeclustervalidators
|
||||
rules:
|
||||
- operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
apiGroups:
|
||||
- cluster.open-cluster-management.io
|
||||
apiVersions:
|
||||
- "*"
|
||||
resources:
|
||||
- spokeclusters
|
||||
admissionReviewVersions: ["v1beta1"]
|
||||
sideEffects: None
|
||||
timeoutSeconds: 3
|
||||
`)
|
||||
|
||||
func manifestsHubHubRegistrationWebhookValidatingconfigurationYamlBytes() ([]byte, error) {
|
||||
return _manifestsHubHubRegistrationWebhookValidatingconfigurationYaml, nil
|
||||
}
|
||||
|
||||
func manifestsHubHubRegistrationWebhookValidatingconfigurationYaml() (*asset, error) {
|
||||
bytes, err := manifestsHubHubRegistrationWebhookValidatingconfigurationYamlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-validatingconfiguration.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -645,11 +929,19 @@ func AssetNames() []string {
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"manifests/hub/0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml": manifestsHub0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYaml,
|
||||
"manifests/hub/0000_00_work.open-cluster-management.io_manifestworks.crd.yaml": manifestsHub0000_00_workOpenClusterManagementIo_manifestworksCrdYaml,
|
||||
"manifests/hub/hub-clusterrole.yaml": manifestsHubHubClusterroleYaml,
|
||||
"manifests/hub/hub-clusterrolebinding.yaml": manifestsHubHubClusterrolebindingYaml,
|
||||
"manifests/hub/hub-deployment.yaml": manifestsHubHubDeploymentYaml,
|
||||
"manifests/hub/hub-namespace.yaml": manifestsHubHubNamespaceYaml,
|
||||
"manifests/hub/hub-serviceaccount.yaml": manifestsHubHubServiceaccountYaml,
|
||||
"manifests/hub/hub-registration-clusterrole.yaml": manifestsHubHubRegistrationClusterroleYaml,
|
||||
"manifests/hub/hub-registration-clusterrolebinding.yaml": manifestsHubHubRegistrationClusterrolebindingYaml,
|
||||
"manifests/hub/hub-registration-deployment.yaml": manifestsHubHubRegistrationDeploymentYaml,
|
||||
"manifests/hub/hub-registration-serviceaccount.yaml": manifestsHubHubRegistrationServiceaccountYaml,
|
||||
"manifests/hub/hub-registration-webhook-apiservice.yaml": manifestsHubHubRegistrationWebhookApiserviceYaml,
|
||||
"manifests/hub/hub-registration-webhook-clusterrole.yaml": manifestsHubHubRegistrationWebhookClusterroleYaml,
|
||||
"manifests/hub/hub-registration-webhook-clusterrolebinding.yaml": manifestsHubHubRegistrationWebhookClusterrolebindingYaml,
|
||||
"manifests/hub/hub-registration-webhook-deployment.yaml": manifestsHubHubRegistrationWebhookDeploymentYaml,
|
||||
"manifests/hub/hub-registration-webhook-secret.yaml": manifestsHubHubRegistrationWebhookSecretYaml,
|
||||
"manifests/hub/hub-registration-webhook-service.yaml": manifestsHubHubRegistrationWebhookServiceYaml,
|
||||
"manifests/hub/hub-registration-webhook-serviceaccount.yaml": manifestsHubHubRegistrationWebhookServiceaccountYaml,
|
||||
"manifests/hub/hub-registration-webhook-validatingconfiguration.yaml": manifestsHubHubRegistrationWebhookValidatingconfigurationYaml,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
@@ -697,11 +989,19 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"hub": {nil, map[string]*bintree{
|
||||
"0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml": {manifestsHub0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYaml, map[string]*bintree{}},
|
||||
"0000_00_work.open-cluster-management.io_manifestworks.crd.yaml": {manifestsHub0000_00_workOpenClusterManagementIo_manifestworksCrdYaml, map[string]*bintree{}},
|
||||
"hub-clusterrole.yaml": {manifestsHubHubClusterroleYaml, map[string]*bintree{}},
|
||||
"hub-clusterrolebinding.yaml": {manifestsHubHubClusterrolebindingYaml, map[string]*bintree{}},
|
||||
"hub-deployment.yaml": {manifestsHubHubDeploymentYaml, map[string]*bintree{}},
|
||||
"hub-namespace.yaml": {manifestsHubHubNamespaceYaml, map[string]*bintree{}},
|
||||
"hub-serviceaccount.yaml": {manifestsHubHubServiceaccountYaml, map[string]*bintree{}},
|
||||
"hub-namespace.yaml": {manifestsHubHubNamespaceYaml, map[string]*bintree{}},
|
||||
"hub-registration-clusterrole.yaml": {manifestsHubHubRegistrationClusterroleYaml, map[string]*bintree{}},
|
||||
"hub-registration-clusterrolebinding.yaml": {manifestsHubHubRegistrationClusterrolebindingYaml, map[string]*bintree{}},
|
||||
"hub-registration-deployment.yaml": {manifestsHubHubRegistrationDeploymentYaml, map[string]*bintree{}},
|
||||
"hub-registration-serviceaccount.yaml": {manifestsHubHubRegistrationServiceaccountYaml, map[string]*bintree{}},
|
||||
"hub-registration-webhook-apiservice.yaml": {manifestsHubHubRegistrationWebhookApiserviceYaml, map[string]*bintree{}},
|
||||
"hub-registration-webhook-clusterrole.yaml": {manifestsHubHubRegistrationWebhookClusterroleYaml, map[string]*bintree{}},
|
||||
"hub-registration-webhook-clusterrolebinding.yaml": {manifestsHubHubRegistrationWebhookClusterrolebindingYaml, map[string]*bintree{}},
|
||||
"hub-registration-webhook-deployment.yaml": {manifestsHubHubRegistrationWebhookDeploymentYaml, map[string]*bintree{}},
|
||||
"hub-registration-webhook-secret.yaml": {manifestsHubHubRegistrationWebhookSecretYaml, map[string]*bintree{}},
|
||||
"hub-registration-webhook-service.yaml": {manifestsHubHubRegistrationWebhookServiceYaml, map[string]*bintree{}},
|
||||
"hub-registration-webhook-serviceaccount.yaml": {manifestsHubHubRegistrationWebhookServiceaccountYaml, map[string]*bintree{}},
|
||||
"hub-registration-webhook-validatingconfiguration.yaml": {manifestsHubHubRegistrationWebhookValidatingconfigurationYaml, map[string]*bintree{}},
|
||||
}},
|
||||
}},
|
||||
}}
|
||||
|
||||
+128
-85
@@ -2,25 +2,23 @@ package hub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog"
|
||||
apiregistrationclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1"
|
||||
|
||||
"github.com/openshift/api"
|
||||
"github.com/openshift/library-go/pkg/assets"
|
||||
"github.com/openshift/library-go/pkg/controller/factory"
|
||||
"github.com/openshift/library-go/pkg/crypto"
|
||||
"github.com/openshift/library-go/pkg/operator/events"
|
||||
"github.com/openshift/library-go/pkg/operator/resource/resourceapply"
|
||||
operatorhelpers "github.com/openshift/library-go/pkg/operator/v1helpers"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -34,56 +32,64 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
genericScheme = runtime.NewScheme()
|
||||
genericCodecs = serializer.NewCodecFactory(genericScheme)
|
||||
genericCodec = genericCodecs.UniversalDeserializer()
|
||||
crdNames = []string{
|
||||
crdNames = []string{
|
||||
"manifestworks.work.open-cluster-management.io",
|
||||
"spokeclusters.cluster.open-cluster-management.io",
|
||||
}
|
||||
staticResourceFiles = []string{
|
||||
"manifests/hub/0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml",
|
||||
"manifests/hub/0000_00_work.open-cluster-management.io_manifestworks.crd.yaml",
|
||||
"manifests/hub/hub-clusterrole.yaml",
|
||||
"manifests/hub/hub-clusterrolebinding.yaml",
|
||||
"manifests/hub/hub-registration-clusterrole.yaml",
|
||||
"manifests/hub/hub-registration-clusterrolebinding.yaml",
|
||||
"manifests/hub/hub-namespace.yaml",
|
||||
"manifests/hub/hub-serviceaccount.yaml",
|
||||
"manifests/hub/hub-registration-serviceaccount.yaml",
|
||||
"manifests/hub/hub-registration-webhook-clusterrole.yaml",
|
||||
"manifests/hub/hub-registration-webhook-clusterrolebinding.yaml",
|
||||
"manifests/hub/hub-registration-webhook-service.yaml",
|
||||
"manifests/hub/hub-registration-webhook-serviceaccount.yaml",
|
||||
"manifests/hub/hub-registration-webhook-apiservice.yaml",
|
||||
"manifests/hub/hub-registration-webhook-secret.yaml",
|
||||
"manifests/hub/hub-registration-webhook-validatingconfiguration.yaml",
|
||||
}
|
||||
|
||||
deploymentFiles = []string{
|
||||
"manifests/hub/hub-registration-deployment.yaml",
|
||||
"manifests/hub/hub-registration-webhook-deployment.yaml",
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
nucleusHubFinalizer = "nucleus.open-cluster-management.io/hub-core-cleanup"
|
||||
nucluesHubCoreNamespace = "open-cluster-management-hub"
|
||||
hubCoreApplied = "Applied"
|
||||
hubCoreAvailable = "Available"
|
||||
nucleusHubFinalizer = "nucleus.open-cluster-management.io/hub-core-cleanup"
|
||||
nucleusHubCoreNamespace = "open-cluster-management-hub"
|
||||
nucleusHubCoreWebhookSecret = "webhook-serving-cert"
|
||||
hubCoreApplied = "Applied"
|
||||
hubCoreAvailable = "Available"
|
||||
)
|
||||
|
||||
func init() {
|
||||
utilruntime.Must(api.InstallKube(genericScheme))
|
||||
utilruntime.Must(apiextensionsv1beta1.AddToScheme(genericScheme))
|
||||
}
|
||||
|
||||
type nucleusHubController struct {
|
||||
nucleusClient nucleusv1client.HubCoreInterface
|
||||
nucleusLister nucleuslister.HubCoreLister
|
||||
kubeClient kubernetes.Interface
|
||||
apiExtensionClient apiextensionsclient.Interface
|
||||
currentHubDeploymentGeneration int64
|
||||
nucleusClient nucleusv1client.HubCoreInterface
|
||||
nucleusLister nucleuslister.HubCoreLister
|
||||
kubeClient kubernetes.Interface
|
||||
apiExtensionClient apiextensionsclient.Interface
|
||||
apiRegistrationClient apiregistrationclient.APIServicesGetter
|
||||
currentGeneration []int64
|
||||
}
|
||||
|
||||
// NewNucleusHubController construct nucleus hub controller
|
||||
func NewNucleusHubController(
|
||||
kubeClient kubernetes.Interface,
|
||||
apiExtensionClient apiextensionsclient.Interface,
|
||||
apiRegistrationClient apiregistrationclient.APIServicesGetter,
|
||||
nucleusClient nucleusv1client.HubCoreInterface,
|
||||
nucleusInformer nucleusinformer.HubCoreInformer,
|
||||
recorder events.Recorder) factory.Controller {
|
||||
controller := &nucleusHubController{
|
||||
kubeClient: kubeClient,
|
||||
apiExtensionClient: apiExtensionClient,
|
||||
nucleusClient: nucleusClient,
|
||||
nucleusLister: nucleusInformer.Lister(),
|
||||
currentHubDeploymentGeneration: 0,
|
||||
kubeClient: kubeClient,
|
||||
apiExtensionClient: apiExtensionClient,
|
||||
apiRegistrationClient: apiRegistrationClient,
|
||||
nucleusClient: nucleusClient,
|
||||
nucleusLister: nucleusInformer.Lister(),
|
||||
currentGeneration: make([]int64, len(deploymentFiles)),
|
||||
}
|
||||
|
||||
return factory.New().WithSync(controller.sync).
|
||||
@@ -97,9 +103,14 @@ func NewNucleusHubController(
|
||||
|
||||
// hubConfig is used to render the template of hub manifests
|
||||
type hubConfig struct {
|
||||
HubCoreName string
|
||||
HubCoreNamespace string
|
||||
RegistrationImage string
|
||||
HubCoreName string
|
||||
HubCoreNamespace string
|
||||
RegistrationImage string
|
||||
HubCoreWebhookSecret string
|
||||
HubCoreWebhookRegistrationService string
|
||||
RegistrationAPIServiceCABundle string
|
||||
RegistrationServingCert string
|
||||
RegistrationServingKey string
|
||||
}
|
||||
|
||||
func (n *nucleusHubController) sync(ctx context.Context, controllerContext factory.SyncContext) error {
|
||||
@@ -117,9 +128,11 @@ func (n *nucleusHubController) sync(ctx context.Context, controllerContext facto
|
||||
hubCore = hubCore.DeepCopy()
|
||||
|
||||
config := hubConfig{
|
||||
HubCoreName: hubCore.Name,
|
||||
HubCoreNamespace: nucluesHubCoreNamespace,
|
||||
RegistrationImage: hubCore.Spec.RegistrationImagePullSpec,
|
||||
HubCoreName: hubCore.Name,
|
||||
HubCoreNamespace: nucleusHubCoreNamespace,
|
||||
RegistrationImage: hubCore.Spec.RegistrationImagePullSpec,
|
||||
HubCoreWebhookSecret: nucleusHubCoreWebhookSecret,
|
||||
HubCoreWebhookRegistrationService: fmt.Sprintf("%s-registration-webhook", hubCore.Name),
|
||||
}
|
||||
|
||||
// Update finalizer at first
|
||||
@@ -146,10 +159,20 @@ func (n *nucleusHubController) sync(ctx context.Context, controllerContext facto
|
||||
return n.removeWorkFinalizer(ctx, hubCore)
|
||||
}
|
||||
|
||||
clientHolder := resourceapply.NewKubeClientHolder(n.kubeClient).WithAPIExtensionsClient(n.apiExtensionClient)
|
||||
ca, cert, key, err := n.ensureServingCertAndCA(
|
||||
ctx, config.HubCoreNamespace, config.HubCoreWebhookSecret, config.HubCoreWebhookRegistrationService)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.RegistrationAPIServiceCABundle = base64.StdEncoding.EncodeToString(ca)
|
||||
config.RegistrationServingCert = base64.StdEncoding.EncodeToString(cert)
|
||||
config.RegistrationServingKey = base64.StdEncoding.EncodeToString(key)
|
||||
|
||||
// Apply static files
|
||||
resourceResults := resourceapply.ApplyDirectly(
|
||||
clientHolder,
|
||||
resourceResults := helpers.ApplyDirectly(
|
||||
n.kubeClient,
|
||||
n.apiExtensionClient,
|
||||
n.apiRegistrationClient,
|
||||
controllerContext.Recorder(),
|
||||
func(name string) ([]byte, error) {
|
||||
return assets.MustCreateAssetFromTemplate(name, bindata.MustAsset(filepath.Join("", name)), config).Data, nil
|
||||
@@ -164,9 +187,19 @@ func (n *nucleusHubController) sync(ctx context.Context, controllerContext facto
|
||||
}
|
||||
|
||||
// Render deployment manifest and apply
|
||||
err = n.applyDeployment(config, controllerContext)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
for index, file := range deploymentFiles {
|
||||
currentGeneration, err := helpers.ApplyDeployment(
|
||||
n.kubeClient,
|
||||
n.currentGeneration[index],
|
||||
func(name string) ([]byte, error) {
|
||||
return assets.MustCreateAssetFromTemplate(name, bindata.MustAsset(filepath.Join("", name)), config).Data, nil
|
||||
},
|
||||
controllerContext.Recorder(),
|
||||
file)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
n.currentGeneration[index] = currentGeneration
|
||||
}
|
||||
|
||||
conditions := &hubCore.Status.Conditions
|
||||
@@ -197,32 +230,6 @@ func (n *nucleusHubController) sync(ctx context.Context, controllerContext facto
|
||||
return operatorhelpers.NewMultiLineAggregate(errs)
|
||||
}
|
||||
|
||||
func (n *nucleusHubController) applyDeployment(config hubConfig, controllerContext factory.SyncContext) error {
|
||||
deploymentFile := "manifests/hub/hub-deployment.yaml"
|
||||
deploymentRaw := assets.MustCreateAssetFromTemplate(
|
||||
deploymentFile,
|
||||
bindata.MustAsset(filepath.Join("", deploymentFile)), config).Data
|
||||
deployment, _, err := genericCodec.Decode(deploymentRaw, nil, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%q: %v", deploymentFile, err)
|
||||
}
|
||||
updatedDeployment, updated, err := resourceapply.ApplyDeployment(
|
||||
n.kubeClient.AppsV1(),
|
||||
controllerContext.Recorder(),
|
||||
deployment.(*appsv1.Deployment), n.currentHubDeploymentGeneration, false)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to apply hub deployment manifest: %v", err)
|
||||
return fmt.Errorf("%q (%T): %v", deploymentFile, deployment, err)
|
||||
}
|
||||
|
||||
// Record the generation, so the deployment is only updated when generation is changed.
|
||||
if updated {
|
||||
n.currentHubDeploymentGeneration = updatedDeployment.ObjectMeta.Generation
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *nucleusHubController) removeWorkFinalizer(ctx context.Context, deploy *nucleusapiv1.HubCore) error {
|
||||
copiedFinalizers := []string{}
|
||||
for i := range deploy.Finalizers {
|
||||
@@ -264,6 +271,48 @@ func (n *nucleusHubController) removeCRD(ctx context.Context, name string) error
|
||||
return fmt.Errorf("CRD %s is still being deleted", name)
|
||||
}
|
||||
|
||||
// ensureServingCertAndCA generates self signed CA and server key/cert for webhook server.
|
||||
// TODO consider ca/cert renewal
|
||||
func (n *nucleusHubController) ensureServingCertAndCA(
|
||||
ctx context.Context, namespace, secretName, svcName string) ([]byte, []byte, []byte, error) {
|
||||
secret, err := n.kubeClient.CoreV1().Secrets(namespace).Get(ctx, secretName, metav1.GetOptions{})
|
||||
switch {
|
||||
case err != nil && !errors.IsNotFound(err):
|
||||
return nil, nil, nil, err
|
||||
case err == nil:
|
||||
if secret.Data["ca.crt"] != nil && secret.Data["tls.crt"] != nil && secret.Data["tls.key"] != nil {
|
||||
return secret.Data["ca.crt"], secret.Data["tls.crt"], secret.Data["tls.key"], nil
|
||||
}
|
||||
}
|
||||
|
||||
caConfig, err := crypto.MakeSelfSignedCAConfig("nucleus-webhook", 365)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
ca := &crypto.CA{
|
||||
SerialGenerator: &crypto.RandomSerialGenerator{},
|
||||
Config: caConfig,
|
||||
}
|
||||
|
||||
hostName := fmt.Sprintf("%s.%s.svc", svcName, namespace)
|
||||
server, err := ca.MakeServerCert(sets.NewString(hostName), 365)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
caData, _, err := caConfig.GetPEMBytes()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
certData, keyData, err := server.GetPEMBytes()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return caData, certData, keyData, nil
|
||||
}
|
||||
|
||||
func (n *nucleusHubController) cleanUp(
|
||||
ctx context.Context, controllerContext factory.SyncContext, config hubConfig) error {
|
||||
// Remove crd
|
||||
@@ -275,24 +324,18 @@ func (n *nucleusHubController) cleanUp(
|
||||
controllerContext.Recorder().Eventf("CRDDeleted", "crd %s is deleted", name)
|
||||
}
|
||||
|
||||
// Remove deployment
|
||||
deploymentName := fmt.Sprintf("%s-controller", config.HubCoreName)
|
||||
err := n.kubeClient.AppsV1().Deployments(config.HubCoreNamespace).Delete(ctx, deploymentName, metav1.DeleteOptions{})
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
controllerContext.Recorder().Eventf("DeploymentDeleted", "deployment %s is deleted", deploymentName)
|
||||
|
||||
// Remove Static files
|
||||
for _, file := range staticResourceFiles {
|
||||
objectRaw := assets.MustCreateAssetFromTemplate(
|
||||
err := helpers.CleanUpStaticObject(
|
||||
ctx,
|
||||
n.kubeClient,
|
||||
n.apiExtensionClient,
|
||||
n.apiRegistrationClient,
|
||||
func(name string) ([]byte, error) {
|
||||
return assets.MustCreateAssetFromTemplate(name, bindata.MustAsset(filepath.Join("", name)), config).Data, nil
|
||||
},
|
||||
file,
|
||||
bindata.MustAsset(filepath.Join("", file)), config).Data
|
||||
object, _, err := genericCodec.Decode(objectRaw, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = helpers.CleanUpStaticObject(ctx, n.kubeClient, n.apiExtensionClient, object)
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package hub
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -18,17 +19,20 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
fakekube "k8s.io/client-go/kubernetes/fake"
|
||||
clienttesting "k8s.io/client-go/testing"
|
||||
"k8s.io/client-go/util/cert"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
fakeapiregistration "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake"
|
||||
|
||||
"github.com/openshift/library-go/pkg/operator/events"
|
||||
"github.com/openshift/library-go/pkg/operator/events/eventstesting"
|
||||
)
|
||||
|
||||
type testController struct {
|
||||
controller *nucleusHubController
|
||||
kubeClient *fakekube.Clientset
|
||||
apiExtensionClient *fakeapiextensions.Clientset
|
||||
nucleusClient *fakenucleusclient.Clientset
|
||||
controller *nucleusHubController
|
||||
kubeClient *fakekube.Clientset
|
||||
apiExtensionClient *fakeapiextensions.Clientset
|
||||
apiRegistrationClient *fakeapiregistration.Clientset
|
||||
nucleusClient *fakenucleusclient.Clientset
|
||||
}
|
||||
|
||||
type fakeSyncContext struct {
|
||||
@@ -66,8 +70,9 @@ func newTestController(hubcore *nucleusapiv1.HubCore) *testController {
|
||||
nucleusInformers := nucleusinformers.NewSharedInformerFactory(fakeNucleusClient, 5*time.Minute)
|
||||
|
||||
hubController := &nucleusHubController{
|
||||
nucleusClient: fakeNucleusClient.NucleusV1().HubCores(),
|
||||
nucleusLister: nucleusInformers.Nucleus().V1().HubCores().Lister(),
|
||||
nucleusClient: fakeNucleusClient.NucleusV1().HubCores(),
|
||||
nucleusLister: nucleusInformers.Nucleus().V1().HubCores().Lister(),
|
||||
currentGeneration: make([]int64, len(deploymentFiles)),
|
||||
}
|
||||
|
||||
store := nucleusInformers.Nucleus().V1().HubCores().Informer().GetStore()
|
||||
@@ -93,12 +98,25 @@ func (t *testController) withCRDObject(objects ...runtime.Object) *testControlle
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *testController) withAPIServiceObject(objects ...runtime.Object) *testController {
|
||||
fakeAPIRegistrationClient := fakeapiregistration.NewSimpleClientset(objects...)
|
||||
t.controller.apiRegistrationClient = fakeAPIRegistrationClient.ApiregistrationV1()
|
||||
t.apiRegistrationClient = fakeAPIRegistrationClient
|
||||
return t
|
||||
}
|
||||
|
||||
func assertAction(t *testing.T, actual clienttesting.Action, expected string) {
|
||||
if actual.GetVerb() != expected {
|
||||
t.Errorf("expected %s action but got: %#v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func assertEqualNumber(t *testing.T, actual, expected int) {
|
||||
if actual != expected {
|
||||
t.Errorf("expected %d number of actions but got: %d", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func assertCondition(t *testing.T, actual runtime.Object, expectedCondition string, expectedStatus metav1.ConditionStatus) {
|
||||
hubCore := actual.(*nucleusapiv1.HubCore)
|
||||
conditions := hubCore.Status.Conditions
|
||||
@@ -132,11 +150,8 @@ func ensureObject(t *testing.T, object runtime.Object, hubCore *nucleusapiv1.Hub
|
||||
|
||||
switch o := object.(type) {
|
||||
case *corev1.Namespace:
|
||||
ensureNameNamespace(t, access.GetName(), "", nucluesHubCoreNamespace, "")
|
||||
case *corev1.ServiceAccount:
|
||||
ensureNameNamespace(t, access.GetName(), access.GetNamespace(), fmt.Sprintf("%s-sa", hubCore.Name), nucluesHubCoreNamespace)
|
||||
ensureNameNamespace(t, access.GetName(), "", nucleusHubCoreNamespace, "")
|
||||
case *appsv1.Deployment:
|
||||
ensureNameNamespace(t, access.GetName(), access.GetNamespace(), fmt.Sprintf("%s-controller", hubCore.Name), nucluesHubCoreNamespace)
|
||||
if hubCore.Spec.RegistrationImagePullSpec != o.Spec.Template.Spec.Containers[0].Image {
|
||||
t.Errorf("Image does not match to the expected.")
|
||||
}
|
||||
@@ -146,7 +161,7 @@ func ensureObject(t *testing.T, object runtime.Object, hubCore *nucleusapiv1.Hub
|
||||
// TestSyncDeploy tests sync manifests of hub component
|
||||
func TestSyncDeploy(t *testing.T) {
|
||||
hubCore := newHubCore("testhub")
|
||||
controller := newTestController(hubCore).withCRDObject().withKubeObject()
|
||||
controller := newTestController(hubCore).withCRDObject().withKubeObject().withAPIServiceObject()
|
||||
syncContext := newFakeSyncContext(t, "testhub")
|
||||
|
||||
err := controller.controller.sync(nil, syncContext)
|
||||
@@ -154,28 +169,45 @@ func TestSyncDeploy(t *testing.T) {
|
||||
t.Errorf("Expected non error when sync, %v", err)
|
||||
}
|
||||
|
||||
createObjects := []runtime.Object{}
|
||||
createKubeObjects := []runtime.Object{}
|
||||
kubeActions := controller.kubeClient.Actions()
|
||||
for _, action := range kubeActions {
|
||||
if action.GetVerb() == "create" {
|
||||
object := action.(clienttesting.CreateActionImpl).Object
|
||||
createObjects = append(createObjects, object)
|
||||
createKubeObjects = append(createKubeObjects, object)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if resources are created as expected
|
||||
if len(createObjects) != 5 {
|
||||
t.Errorf("Expect 5 objects created in the sync loop, actual %q", len(createObjects))
|
||||
}
|
||||
for _, object := range createObjects {
|
||||
assertEqualNumber(t, len(createKubeObjects), 12)
|
||||
for _, object := range createKubeObjects {
|
||||
ensureObject(t, object, hubCore)
|
||||
}
|
||||
|
||||
nucleusAction := controller.nucleusClient.Actions()
|
||||
if len(nucleusAction) != 2 {
|
||||
t.Errorf("Expect 2 actions in the sync loop")
|
||||
createCRDObjects := []runtime.Object{}
|
||||
crdActions := controller.apiExtensionClient.Actions()
|
||||
for _, action := range crdActions {
|
||||
if action.GetVerb() == "create" {
|
||||
object := action.(clienttesting.CreateActionImpl).Object
|
||||
createCRDObjects = append(createCRDObjects, object)
|
||||
}
|
||||
}
|
||||
// Check if resources are created as expected
|
||||
assertEqualNumber(t, len(createCRDObjects), 2)
|
||||
|
||||
createAPIServiceObjects := []runtime.Object{}
|
||||
apiServiceActions := controller.apiRegistrationClient.Actions()
|
||||
for _, action := range apiServiceActions {
|
||||
if action.GetVerb() == "create" {
|
||||
object := action.(clienttesting.CreateActionImpl).Object
|
||||
createAPIServiceObjects = append(createAPIServiceObjects, object)
|
||||
}
|
||||
}
|
||||
// Check if resources are created as expected
|
||||
assertEqualNumber(t, len(createAPIServiceObjects), 1)
|
||||
|
||||
nucleusAction := controller.nucleusClient.Actions()
|
||||
assertEqualNumber(t, len(nucleusAction), 2)
|
||||
assertAction(t, nucleusAction[1], "update")
|
||||
assertCondition(t, nucleusAction[1].(clienttesting.UpdateActionImpl).Object, hubCoreApplied, metav1.ConditionTrue)
|
||||
}
|
||||
@@ -185,7 +217,7 @@ func TestSyncDelete(t *testing.T) {
|
||||
hubCore := newHubCore("testhub")
|
||||
now := metav1.Now()
|
||||
hubCore.ObjectMeta.SetDeletionTimestamp(&now)
|
||||
controller := newTestController(hubCore).withCRDObject().withKubeObject()
|
||||
controller := newTestController(hubCore).withCRDObject().withKubeObject().withAPIServiceObject()
|
||||
syncContext := newFakeSyncContext(t, "testhub")
|
||||
|
||||
err := controller.controller.sync(nil, syncContext)
|
||||
@@ -193,27 +225,42 @@ func TestSyncDelete(t *testing.T) {
|
||||
t.Errorf("Expected non error when sync, %v", err)
|
||||
}
|
||||
|
||||
deleteActions := []clienttesting.DeleteActionImpl{}
|
||||
deleteKubeActions := []clienttesting.DeleteActionImpl{}
|
||||
kubeActions := controller.kubeClient.Actions()
|
||||
for _, action := range kubeActions {
|
||||
if action.GetVerb() == "delete" {
|
||||
deleteAction := action.(clienttesting.DeleteActionImpl)
|
||||
deleteActions = append(deleteActions, deleteAction)
|
||||
deleteKubeAction := action.(clienttesting.DeleteActionImpl)
|
||||
deleteKubeActions = append(deleteKubeActions, deleteKubeAction)
|
||||
}
|
||||
}
|
||||
assertEqualNumber(t, len(deleteKubeActions), 10)
|
||||
|
||||
for _, action := range deleteActions {
|
||||
deleteCRDActions := []clienttesting.DeleteActionImpl{}
|
||||
crdActions := controller.apiExtensionClient.Actions()
|
||||
for _, action := range crdActions {
|
||||
if action.GetVerb() == "delete" {
|
||||
deleteCRDAction := action.(clienttesting.DeleteActionImpl)
|
||||
deleteCRDActions = append(deleteCRDActions, deleteCRDAction)
|
||||
}
|
||||
}
|
||||
// Check if resources are created as expected
|
||||
assertEqualNumber(t, len(deleteCRDActions), 4)
|
||||
|
||||
deleteAPIServiceActions := []clienttesting.DeleteActionImpl{}
|
||||
apiServiceActions := controller.apiRegistrationClient.Actions()
|
||||
for _, action := range apiServiceActions {
|
||||
if action.GetVerb() == "delete" {
|
||||
deleteAPIServiceAction := action.(clienttesting.DeleteActionImpl)
|
||||
deleteAPIServiceActions = append(deleteAPIServiceActions, deleteAPIServiceAction)
|
||||
}
|
||||
}
|
||||
// Check if resources are created as expected
|
||||
assertEqualNumber(t, len(deleteAPIServiceActions), 1)
|
||||
|
||||
for _, action := range deleteKubeActions {
|
||||
switch action.Resource.Resource {
|
||||
case "clusterroles":
|
||||
ensureNameNamespace(t, action.Name, "", fmt.Sprintf("system:open-cluster-management:%s", hubCore.Name), "")
|
||||
case "clusterrolebindings":
|
||||
ensureNameNamespace(t, action.Name, "", fmt.Sprintf("system:open-cluster-management:%s", hubCore.Name), "")
|
||||
case "namespaces":
|
||||
ensureNameNamespace(t, action.Name, "", nucluesHubCoreNamespace, "")
|
||||
case "serviceaccounts":
|
||||
ensureNameNamespace(t, action.Name, action.Namespace, fmt.Sprintf("%s-sa", hubCore.Name), nucluesHubCoreNamespace)
|
||||
case "deployments":
|
||||
ensureNameNamespace(t, action.Name, action.Namespace, fmt.Sprintf("%s-controller", hubCore.Name), nucluesHubCoreNamespace)
|
||||
ensureNameNamespace(t, action.Name, "", nucleusHubCoreNamespace, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,7 +275,7 @@ func TestDeleteCRD(t *testing.T) {
|
||||
Name: crdNames[0],
|
||||
},
|
||||
}
|
||||
controller := newTestController(hubCore).withCRDObject(crd).withKubeObject()
|
||||
controller := newTestController(hubCore).withCRDObject(crd).withKubeObject().withAPIServiceObject()
|
||||
|
||||
// Return crd with the first get, and return not found with the 2nd get
|
||||
getCount := 0
|
||||
@@ -252,3 +299,45 @@ func TestDeleteCRD(t *testing.T) {
|
||||
t.Errorf("Expected no error when sync: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureServingCertAndCA(t *testing.T) {
|
||||
hubCore := newHubCore("testhub")
|
||||
controller := newTestController(hubCore).withCRDObject().withKubeObject().withAPIServiceObject()
|
||||
ca, certificate, key, err := controller.controller.ensureServingCertAndCA(context.TODO(), "ns1", "kubeconfig", "webhook")
|
||||
if err != nil {
|
||||
t.Errorf("Expect no error when generating serving cert: %v", err)
|
||||
}
|
||||
certs, err := cert.ParseCertsPEM(certificate)
|
||||
if err != nil {
|
||||
t.Errorf("Expect no error when parsing cert")
|
||||
}
|
||||
if len(certs) != 2 {
|
||||
t.Errorf("Expect 2 cert is parsed, actual %d", len(certs))
|
||||
}
|
||||
for _, cert := range certs {
|
||||
if cert.Subject.CommonName != "webhook.ns1.svc" && cert.Subject.CommonName != "nucleus-webhook" {
|
||||
t.Errorf("Common name in cert is not correct, actual %s", cert.Subject.CommonName)
|
||||
}
|
||||
}
|
||||
|
||||
secret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "kubeconfig",
|
||||
Namespace: "ns1",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"ca.crt": ca,
|
||||
"tls.crt": certificate,
|
||||
"tls.key": key,
|
||||
},
|
||||
}
|
||||
controller = newTestController(hubCore).withCRDObject().withKubeObject(secret).withAPIServiceObject()
|
||||
actualCA, actualCert, actualKey, err := controller.controller.ensureServingCertAndCA(context.TODO(), "ns1", "kubeconfig", "webhook")
|
||||
if err != nil {
|
||||
t.Errorf("Expect no error when generating serving cert: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(ca, actualCA) || !reflect.DeepEqual(certificate, actualCert) || !reflect.DeepEqual(key, actualKey) {
|
||||
t.Errorf("Expect the cert/key/ca is obtained from secret")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
apiregistrationclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||
|
||||
"github.com/openshift/library-go/pkg/controller/controllercmd"
|
||||
|
||||
@@ -26,6 +27,10 @@ func RunNucleusHubOperator(ctx context.Context, controllerContext *controllercmd
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
apiRegistrationClient, err := apiregistrationclient.NewForConfig(controllerContext.KubeConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Build nucleus client and informer
|
||||
nucleusClient, err := nucleusclient.NewForConfig(controllerContext.KubeConfig)
|
||||
@@ -37,6 +42,7 @@ func RunNucleusHubOperator(ctx context.Context, controllerContext *controllercmd
|
||||
hubcontroller := hub.NewNucleusHubController(
|
||||
kubeClient,
|
||||
apiExtensionClient,
|
||||
apiRegistrationClient.ApiregistrationV1(),
|
||||
nucleusClient.NucleusV1().HubCores(),
|
||||
nucleusInformer.Nucleus().V1().HubCores(),
|
||||
controllerContext.EventRecorder)
|
||||
|
||||
@@ -6,20 +6,16 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog"
|
||||
|
||||
"github.com/openshift/api"
|
||||
"github.com/openshift/library-go/pkg/controller/factory"
|
||||
"github.com/openshift/library-go/pkg/operator/events"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
|
||||
"github.com/openshift/library-go/pkg/assets"
|
||||
"github.com/openshift/library-go/pkg/operator/resource/resourceapply"
|
||||
@@ -43,9 +39,6 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
genericScheme = runtime.NewScheme()
|
||||
genericCodecs = serializer.NewCodecFactory(genericScheme)
|
||||
genericCodec = genericCodecs.UniversalDeserializer()
|
||||
staticResourceFiles = []string{
|
||||
"manifests/spoke/spoke-registration-serviceaccount.yaml",
|
||||
"manifests/spoke/spoke-registration-clusterrole.yaml",
|
||||
@@ -67,10 +60,6 @@ type nucleusSpokeController struct {
|
||||
workGeneration int64
|
||||
}
|
||||
|
||||
func init() {
|
||||
utilruntime.Must(api.InstallKube(genericScheme))
|
||||
}
|
||||
|
||||
// NewNucleusSpokeController construct nucleus spoke controller
|
||||
func NewNucleusSpokeController(
|
||||
kubeClient kubernetes.Interface,
|
||||
@@ -244,7 +233,14 @@ func (n *nucleusSpokeController) sync(ctx context.Context, controllerContext fac
|
||||
}
|
||||
|
||||
// Deploy registration agent
|
||||
generation, err := n.applyDeployment(config, "manifests/spoke/spoke-registration-deployment.yaml", n.registrationGeneration, controllerContext)
|
||||
generation, err := helpers.ApplyDeployment(
|
||||
n.kubeClient,
|
||||
n.registrationGeneration,
|
||||
func(name string) ([]byte, error) {
|
||||
return assets.MustCreateAssetFromTemplate(name, bindata.MustAsset(filepath.Join("", name)), config).Data, nil
|
||||
},
|
||||
controllerContext.Recorder(),
|
||||
"manifests/spoke/spoke-registration-deployment.yaml")
|
||||
if err != nil {
|
||||
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
|
||||
Type: spokeCoreApplied, Status: metav1.ConditionFalse, Reason: "SpokeCoreApplyFailed",
|
||||
@@ -256,8 +252,14 @@ func (n *nucleusSpokeController) sync(ctx context.Context, controllerContext fac
|
||||
n.registrationGeneration = generation
|
||||
|
||||
// Deploy work agent
|
||||
generation, err = n.applyDeployment(
|
||||
config, "manifests/spoke/spoke-work-deployment.yaml", n.workGeneration, controllerContext)
|
||||
generation, err = helpers.ApplyDeployment(
|
||||
n.kubeClient,
|
||||
n.workGeneration,
|
||||
func(name string) ([]byte, error) {
|
||||
return assets.MustCreateAssetFromTemplate(name, bindata.MustAsset(filepath.Join("", name)), config).Data, nil
|
||||
},
|
||||
controllerContext.Recorder(),
|
||||
"manifests/spoke/spoke-work-deployment.yaml")
|
||||
if err != nil {
|
||||
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
|
||||
Type: spokeCoreApplied, Status: metav1.ConditionFalse, Reason: "SpokeCoreApplyFailed",
|
||||
@@ -309,32 +311,6 @@ func (n *nucleusSpokeController) sync(ctx context.Context, controllerContext fac
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *nucleusSpokeController) applyDeployment(
|
||||
config spokeConfig, file string, generation int64, controllerContext factory.SyncContext) (int64, error) {
|
||||
deploymentRaw := assets.MustCreateAssetFromTemplate(
|
||||
file,
|
||||
bindata.MustAsset(filepath.Join("", file)), config).Data
|
||||
deployment, _, err := genericCodec.Decode(deploymentRaw, nil, nil)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("%q: %v", file, err)
|
||||
}
|
||||
updatedDeployment, updated, err := resourceapply.ApplyDeployment(
|
||||
n.kubeClient.AppsV1(),
|
||||
controllerContext.Recorder(),
|
||||
deployment.(*appsv1.Deployment), generation, false)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to apply hub deployment manifest: %v", err)
|
||||
return 0, fmt.Errorf("%q (%T): %v", file, deployment, err)
|
||||
}
|
||||
|
||||
// Record the generation, so the deployment is only updated when generation is changed.
|
||||
if updated {
|
||||
generation = updatedDeployment.ObjectMeta.Generation
|
||||
}
|
||||
|
||||
return generation, nil
|
||||
}
|
||||
|
||||
func (n *nucleusSpokeController) cleanUp(ctx context.Context, controllerContext factory.SyncContext, config spokeConfig) error {
|
||||
// Remove deployment
|
||||
registrationDeployment := fmt.Sprintf("%s-registration-agent", config.SpokeCoreName)
|
||||
@@ -358,14 +334,16 @@ func (n *nucleusSpokeController) cleanUp(ctx context.Context, controllerContext
|
||||
|
||||
// Remove Static files
|
||||
for _, file := range staticResourceFiles {
|
||||
objectRaw := assets.MustCreateAssetFromTemplate(
|
||||
err := helpers.CleanUpStaticObject(
|
||||
ctx,
|
||||
n.kubeClient,
|
||||
nil,
|
||||
nil,
|
||||
func(name string) ([]byte, error) {
|
||||
return assets.MustCreateAssetFromTemplate(name, bindata.MustAsset(filepath.Join("", name)), config).Data, nil
|
||||
},
|
||||
file,
|
||||
bindata.MustAsset(filepath.Join("", file)), config).Data
|
||||
object, _, err := genericCodec.Decode(objectRaw, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = helpers.CleanUpStaticObject(ctx, n.kubeClient, nil, object)
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
"github.com/onsi/gomega"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/openshift/library-go/pkg/controller/controllercmd"
|
||||
|
||||
"github.com/open-cluster-management/nucleus/pkg/operators"
|
||||
"github.com/open-cluster-management/nucleus/test/integration/util"
|
||||
|
||||
nucleusapiv1 "github.com/open-cluster-management/api/nucleus/v1"
|
||||
)
|
||||
|
||||
func startHubOperator(ctx context.Context) {
|
||||
err := operators.RunNucleusHubOperator(ctx, &controllercmd.ControllerContext{
|
||||
KubeConfig: restConfig,
|
||||
EventRecorder: util.NewIntegrationTestEventRecorder("integration"),
|
||||
})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
}
|
||||
|
||||
var _ = ginkgo.Describe("HubCore", func() {
|
||||
var cancel context.CancelFunc
|
||||
var err error
|
||||
var hubCoreName string
|
||||
var hubRegistrationClusterRole string
|
||||
var hubWebhookClusterRole string
|
||||
var hubRegistrationSA string
|
||||
var hubWebhookSA string
|
||||
var hubRegistrationDeployment string
|
||||
var hubWebhookDeployment string
|
||||
var webhookSecret string
|
||||
var validtingWebhook string
|
||||
|
||||
ginkgo.BeforeEach(func() {
|
||||
var ctx context.Context
|
||||
ctx, cancel = context.WithCancel(context.Background())
|
||||
go startHubOperator(ctx)
|
||||
})
|
||||
|
||||
ginkgo.JustBeforeEach(func() {
|
||||
hubcore := &nucleusapiv1.HubCore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: hubCoreName,
|
||||
},
|
||||
Spec: nucleusapiv1.HubCoreSpec{
|
||||
RegistrationImagePullSpec: "quay.io/open-cluster-management/registration",
|
||||
},
|
||||
}
|
||||
hubcore, err = nucleusClient.NucleusV1().HubCores().Create(context.Background(), hubcore, metav1.CreateOptions{})
|
||||
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
||||
})
|
||||
|
||||
ginkgo.AfterEach(func() {
|
||||
if cancel != nil {
|
||||
cancel()
|
||||
}
|
||||
})
|
||||
|
||||
ginkgo.Context("Deploy and clean hub component", func() {
|
||||
ginkgo.BeforeEach(func() {
|
||||
hubCoreName = "hub"
|
||||
hubRegistrationClusterRole = fmt.Sprintf("system:open-cluster-management:%s-registration-controller", hubCoreName)
|
||||
hubWebhookClusterRole = fmt.Sprintf("system:open-cluster-management:%s-registration-webhook", hubCoreName)
|
||||
hubRegistrationSA = fmt.Sprintf("%s-registration-controller-sa", hubCoreName)
|
||||
hubWebhookSA = fmt.Sprintf("%s-registration-webhook-sa", hubCoreName)
|
||||
hubRegistrationDeployment = fmt.Sprintf("%s-registration-controller", hubCoreName)
|
||||
hubWebhookDeployment = fmt.Sprintf("%s-registration-webhook", hubCoreName)
|
||||
webhookSecret = "webhook-serving-cert"
|
||||
validtingWebhook = "spokeclustervalidators.admission.cluster.open-cluster-management.io"
|
||||
})
|
||||
|
||||
ginkgo.It("should have expected resource created successfully", func() {
|
||||
// Check namespace
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.CoreV1().Namespaces().Get(context.Background(), hubNamespace, metav1.GetOptions{}); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
|
||||
// Check clusterrole/clusterrolebinding
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.RbacV1().ClusterRoles().Get(context.Background(), hubRegistrationClusterRole, metav1.GetOptions{}); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.RbacV1().ClusterRoles().Get(context.Background(), hubWebhookClusterRole, metav1.GetOptions{}); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.RbacV1().ClusterRoleBindings().Get(context.Background(), hubRegistrationClusterRole, metav1.GetOptions{}); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.RbacV1().ClusterRoleBindings().Get(context.Background(), hubWebhookClusterRole, metav1.GetOptions{}); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
|
||||
// Check service account
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.CoreV1().ServiceAccounts(hubNamespace).Get(context.Background(), hubRegistrationSA, metav1.GetOptions{}); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.CoreV1().ServiceAccounts(hubNamespace).Get(context.Background(), hubWebhookSA, metav1.GetOptions{}); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
|
||||
// Check deployment
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.AppsV1().Deployments(hubNamespace).Get(context.Background(), hubRegistrationDeployment, metav1.GetOptions{}); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.AppsV1().Deployments(hubNamespace).Get(context.Background(), hubWebhookDeployment, metav1.GetOptions{}); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
|
||||
// Check service
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.CoreV1().Services(hubNamespace).Get(context.Background(), hubWebhookDeployment, metav1.GetOptions{}); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
|
||||
// Check webhook secret
|
||||
gomega.Eventually(func() bool {
|
||||
s, err := kubeClient.CoreV1().Secrets(hubNamespace).Get(context.Background(), webhookSecret, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if s.Data == nil || s.Data["ca.crt"] == nil || s.Data["tls.crt"] == nil || s.Data["tls.key"] == nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
|
||||
// Check validating webhook
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.Background(), validtingWebhook, metav1.GetOptions{}); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
|
||||
err := nucleusClient.NucleusV1().HubCores().Delete(context.Background(), hubCoreName, metav1.DeleteOptions{})
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
|
||||
// Check namespace deletion
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.CoreV1().Namespaces().Get(context.Background(), hubNamespace, metav1.GetOptions{}); errors.IsNotFound(err) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
|
||||
// Check clusterrole/clusterrolebinding deletion
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.RbacV1().ClusterRoles().Get(context.Background(), hubRegistrationClusterRole, metav1.GetOptions{}); errors.IsNotFound(err) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.RbacV1().ClusterRoles().Get(context.Background(), hubWebhookClusterRole, metav1.GetOptions{}); errors.IsNotFound(err) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.RbacV1().ClusterRoleBindings().Get(context.Background(), hubRegistrationClusterRole, metav1.GetOptions{}); errors.IsNotFound(err) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.RbacV1().ClusterRoleBindings().Get(context.Background(), hubWebhookClusterRole, metav1.GetOptions{}); errors.IsNotFound(err) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
|
||||
// Check validating webhook deletion
|
||||
gomega.Eventually(func() bool {
|
||||
if _, err := kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.Background(), validtingWebhook, metav1.GetOptions{}); errors.IsNotFound(err) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
package integration_test
|
||||
package integration
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
@@ -7,12 +7,15 @@ import (
|
||||
"github.com/onsi/ginkgo"
|
||||
"github.com/onsi/gomega"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/envtest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/envtest/printer"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
nucleusclient "github.com/open-cluster-management/api/client/nucleus/clientset/versioned"
|
||||
)
|
||||
|
||||
func TestIntegration(t *testing.T) {
|
||||
@@ -20,10 +23,21 @@ func TestIntegration(t *testing.T) {
|
||||
ginkgo.RunSpecsWithDefaultAndCustomReporters(t, "Integration Suite", []ginkgo.Reporter{printer.NewlineReporter{}})
|
||||
}
|
||||
|
||||
const (
|
||||
eventuallyTimeout = 30 // seconds
|
||||
eventuallyInterval = 1 // seconds
|
||||
hubNamespace = "open-cluster-management-hub"
|
||||
spokeNamespace = "open-cluster-management-spoke"
|
||||
)
|
||||
|
||||
var testEnv *envtest.Environment
|
||||
|
||||
var kubeClient kubernetes.Interface
|
||||
|
||||
var restConfig *rest.Config
|
||||
|
||||
var nucleusClient nucleusclient.Interface
|
||||
|
||||
var _ = ginkgo.BeforeSuite(func(done ginkgo.Done) {
|
||||
logf.SetLogger(zap.LoggerTo(ginkgo.GinkgoWriter, true))
|
||||
|
||||
@@ -46,6 +60,11 @@ var _ = ginkgo.BeforeSuite(func(done ginkgo.Done) {
|
||||
kubeClient, err = kubernetes.NewForConfig(cfg)
|
||||
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
||||
gomega.Expect(kubeClient).ToNot(gomega.BeNil())
|
||||
nucleusClient, err = nucleusclient.NewForConfig(cfg)
|
||||
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
||||
gomega.Expect(kubeClient).ToNot(gomega.BeNil())
|
||||
|
||||
restConfig = cfg
|
||||
|
||||
close(done)
|
||||
}, 60)
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
|
||||
"github.com/openshift/library-go/pkg/operator/events"
|
||||
)
|
||||
|
||||
func NewIntegrationTestEventRecorder(componet string) events.Recorder {
|
||||
return &IntegrationTestEventRecorder{component: componet}
|
||||
}
|
||||
|
||||
type IntegrationTestEventRecorder struct {
|
||||
component string
|
||||
}
|
||||
|
||||
func (r *IntegrationTestEventRecorder) ComponentName() string {
|
||||
return r.component
|
||||
}
|
||||
|
||||
func (r *IntegrationTestEventRecorder) ForComponent(c string) events.Recorder {
|
||||
return &IntegrationTestEventRecorder{component: c}
|
||||
}
|
||||
|
||||
func (r *IntegrationTestEventRecorder) WithComponentSuffix(suffix string) events.Recorder {
|
||||
return r.ForComponent(fmt.Sprintf("%s-%s", r.ComponentName(), suffix))
|
||||
}
|
||||
|
||||
func (r *IntegrationTestEventRecorder) Event(reason, message string) {
|
||||
fmt.Fprintf(ginkgo.GinkgoWriter, "Event: [%s] %v: %v \n", r.component, reason, message)
|
||||
}
|
||||
|
||||
func (r *IntegrationTestEventRecorder) Eventf(reason, messageFmt string, args ...interface{}) {
|
||||
r.Event(reason, fmt.Sprintf(messageFmt, args...))
|
||||
}
|
||||
|
||||
func (r *IntegrationTestEventRecorder) Warning(reason, message string) {
|
||||
fmt.Fprintf(ginkgo.GinkgoWriter, "Warning: [%s] %v: %v \n", r.component, reason, message)
|
||||
}
|
||||
|
||||
func (r *IntegrationTestEventRecorder) Warningf(reason, messageFmt string, args ...interface{}) {
|
||||
r.Warning(reason, fmt.Sprintf(messageFmt, args...))
|
||||
}
|
||||
Generated
Vendored
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package clientset
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
discovery "k8s.io/client-go/discovery"
|
||||
rest "k8s.io/client-go/rest"
|
||||
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1"
|
||||
apiregistrationv1beta1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
ApiregistrationV1beta1() apiregistrationv1beta1.ApiregistrationV1beta1Interface
|
||||
ApiregistrationV1() apiregistrationv1.ApiregistrationV1Interface
|
||||
}
|
||||
|
||||
// Clientset contains the clients for groups. Each group has exactly one
|
||||
// version included in a Clientset.
|
||||
type Clientset struct {
|
||||
*discovery.DiscoveryClient
|
||||
apiregistrationV1beta1 *apiregistrationv1beta1.ApiregistrationV1beta1Client
|
||||
apiregistrationV1 *apiregistrationv1.ApiregistrationV1Client
|
||||
}
|
||||
|
||||
// ApiregistrationV1beta1 retrieves the ApiregistrationV1beta1Client
|
||||
func (c *Clientset) ApiregistrationV1beta1() apiregistrationv1beta1.ApiregistrationV1beta1Interface {
|
||||
return c.apiregistrationV1beta1
|
||||
}
|
||||
|
||||
// ApiregistrationV1 retrieves the ApiregistrationV1Client
|
||||
func (c *Clientset) ApiregistrationV1() apiregistrationv1.ApiregistrationV1Interface {
|
||||
return c.apiregistrationV1
|
||||
}
|
||||
|
||||
// Discovery retrieves the DiscoveryClient
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.DiscoveryClient
|
||||
}
|
||||
|
||||
// NewForConfig creates a new Clientset for the given config.
|
||||
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
||||
// NewForConfig will generate a rate-limiter in configShallowCopy.
|
||||
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||
if configShallowCopy.Burst <= 0 {
|
||||
return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
|
||||
}
|
||||
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||
}
|
||||
var cs Clientset
|
||||
var err error
|
||||
cs.apiregistrationV1beta1, err = apiregistrationv1beta1.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cs.apiregistrationV1, err = apiregistrationv1.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cs, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new Clientset for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
var cs Clientset
|
||||
cs.apiregistrationV1beta1 = apiregistrationv1beta1.NewForConfigOrDie(c)
|
||||
cs.apiregistrationV1 = apiregistrationv1.NewForConfigOrDie(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
|
||||
return &cs
|
||||
}
|
||||
|
||||
// New creates a new Clientset for the given RESTClient.
|
||||
func New(c rest.Interface) *Clientset {
|
||||
var cs Clientset
|
||||
cs.apiregistrationV1beta1 = apiregistrationv1beta1.New(c)
|
||||
cs.apiregistrationV1 = apiregistrationv1.New(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
|
||||
return &cs
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated clientset.
|
||||
package clientset
|
||||
Generated
Vendored
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
"k8s.io/client-go/testing"
|
||||
clientset "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1"
|
||||
fakeapiregistrationv1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake"
|
||||
apiregistrationv1beta1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1"
|
||||
fakeapiregistrationv1beta1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake"
|
||||
)
|
||||
|
||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
|
||||
// without applying any validations and/or defaults. It shouldn't be considered a replacement
|
||||
// for a real clientset and is mostly useful in simple unit tests.
|
||||
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
||||
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||
for _, obj := range objects {
|
||||
if err := o.Add(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cs := &Clientset{tracker: o}
|
||||
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
|
||||
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||
gvr := action.GetResource()
|
||||
ns := action.GetNamespace()
|
||||
watch, err := o.Watch(gvr, ns)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, watch, nil
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// Clientset implements clientset.Interface. Meant to be embedded into a
|
||||
// struct to get a default implementation. This makes faking out just the method
|
||||
// you want to test easier.
|
||||
type Clientset struct {
|
||||
testing.Fake
|
||||
discovery *fakediscovery.FakeDiscovery
|
||||
tracker testing.ObjectTracker
|
||||
}
|
||||
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
return c.discovery
|
||||
}
|
||||
|
||||
func (c *Clientset) Tracker() testing.ObjectTracker {
|
||||
return c.tracker
|
||||
}
|
||||
|
||||
var _ clientset.Interface = &Clientset{}
|
||||
|
||||
// ApiregistrationV1beta1 retrieves the ApiregistrationV1beta1Client
|
||||
func (c *Clientset) ApiregistrationV1beta1() apiregistrationv1beta1.ApiregistrationV1beta1Interface {
|
||||
return &fakeapiregistrationv1beta1.FakeApiregistrationV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// ApiregistrationV1 retrieves the ApiregistrationV1Client
|
||||
func (c *Clientset) ApiregistrationV1() apiregistrationv1.ApiregistrationV1Interface {
|
||||
return &fakeapiregistrationv1.FakeApiregistrationV1{Fake: &c.Fake}
|
||||
}
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated fake clientset.
|
||||
package fake
|
||||
Generated
Vendored
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||
apiregistrationv1beta1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
|
||||
)
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
var codecs = serializer.NewCodecFactory(scheme)
|
||||
var parameterCodec = runtime.NewParameterCodec(scheme)
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
apiregistrationv1beta1.AddToScheme,
|
||||
apiregistrationv1.AddToScheme,
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
var AddToScheme = localSchemeBuilder.AddToScheme
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
utilruntime.Must(AddToScheme(scheme))
|
||||
}
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
Generated
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
v1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1"
|
||||
)
|
||||
|
||||
type FakeApiregistrationV1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeApiregistrationV1) APIServices() v1.APIServiceInterface {
|
||||
return &FakeAPIServices{c}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeApiregistrationV1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
Generated
Vendored
+133
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||
)
|
||||
|
||||
// FakeAPIServices implements APIServiceInterface
|
||||
type FakeAPIServices struct {
|
||||
Fake *FakeApiregistrationV1
|
||||
}
|
||||
|
||||
var apiservicesResource = schema.GroupVersionResource{Group: "apiregistration.k8s.io", Version: "v1", Resource: "apiservices"}
|
||||
|
||||
var apiservicesKind = schema.GroupVersionKind{Group: "apiregistration.k8s.io", Version: "v1", Kind: "APIService"}
|
||||
|
||||
// Get takes name of the aPIService, and returns the corresponding aPIService object, and an error if there is any.
|
||||
func (c *FakeAPIServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *apiregistrationv1.APIService, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(apiservicesResource, name), &apiregistrationv1.APIService{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apiregistrationv1.APIService), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of APIServices that match those selectors.
|
||||
func (c *FakeAPIServices) List(ctx context.Context, opts v1.ListOptions) (result *apiregistrationv1.APIServiceList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(apiservicesResource, apiservicesKind, opts), &apiregistrationv1.APIServiceList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &apiregistrationv1.APIServiceList{ListMeta: obj.(*apiregistrationv1.APIServiceList).ListMeta}
|
||||
for _, item := range obj.(*apiregistrationv1.APIServiceList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested aPIServices.
|
||||
func (c *FakeAPIServices) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(apiservicesResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a aPIService and creates it. Returns the server's representation of the aPIService, and an error, if there is any.
|
||||
func (c *FakeAPIServices) Create(ctx context.Context, aPIService *apiregistrationv1.APIService, opts v1.CreateOptions) (result *apiregistrationv1.APIService, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(apiservicesResource, aPIService), &apiregistrationv1.APIService{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apiregistrationv1.APIService), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a aPIService and updates it. Returns the server's representation of the aPIService, and an error, if there is any.
|
||||
func (c *FakeAPIServices) Update(ctx context.Context, aPIService *apiregistrationv1.APIService, opts v1.UpdateOptions) (result *apiregistrationv1.APIService, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(apiservicesResource, aPIService), &apiregistrationv1.APIService{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apiregistrationv1.APIService), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeAPIServices) UpdateStatus(ctx context.Context, aPIService *apiregistrationv1.APIService, opts v1.UpdateOptions) (*apiregistrationv1.APIService, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateSubresourceAction(apiservicesResource, "status", aPIService), &apiregistrationv1.APIService{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apiregistrationv1.APIService), err
|
||||
}
|
||||
|
||||
// Delete takes name of the aPIService and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeAPIServices) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(apiservicesResource, name), &apiregistrationv1.APIService{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeAPIServices) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(apiservicesResource, listOpts)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &apiregistrationv1.APIServiceList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched aPIService.
|
||||
func (c *FakeAPIServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *apiregistrationv1.APIService, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(apiservicesResource, name, pt, data, subresources...), &apiregistrationv1.APIService{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apiregistrationv1.APIService), err
|
||||
}
|
||||
Generated
Vendored
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
rest "k8s.io/client-go/rest"
|
||||
v1beta1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
|
||||
"k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
)
|
||||
|
||||
type ApiregistrationV1beta1Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
APIServicesGetter
|
||||
}
|
||||
|
||||
// ApiregistrationV1beta1Client is used to interact with features provided by the apiregistration.k8s.io group.
|
||||
type ApiregistrationV1beta1Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
func (c *ApiregistrationV1beta1Client) APIServices() APIServiceInterface {
|
||||
return newAPIServices(c)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new ApiregistrationV1beta1Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*ApiregistrationV1beta1Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ApiregistrationV1beta1Client{client}, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new ApiregistrationV1beta1Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *ApiregistrationV1beta1Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// New creates a new ApiregistrationV1beta1Client for the given RESTClient.
|
||||
func New(c rest.Interface) *ApiregistrationV1beta1Client {
|
||||
return &ApiregistrationV1beta1Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1beta1.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *ApiregistrationV1beta1Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
||||
Generated
Vendored
+184
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
v1beta1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
|
||||
scheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
)
|
||||
|
||||
// APIServicesGetter has a method to return a APIServiceInterface.
|
||||
// A group's client should implement this interface.
|
||||
type APIServicesGetter interface {
|
||||
APIServices() APIServiceInterface
|
||||
}
|
||||
|
||||
// APIServiceInterface has methods to work with APIService resources.
|
||||
type APIServiceInterface interface {
|
||||
Create(ctx context.Context, aPIService *v1beta1.APIService, opts v1.CreateOptions) (*v1beta1.APIService, error)
|
||||
Update(ctx context.Context, aPIService *v1beta1.APIService, opts v1.UpdateOptions) (*v1beta1.APIService, error)
|
||||
UpdateStatus(ctx context.Context, aPIService *v1beta1.APIService, opts v1.UpdateOptions) (*v1beta1.APIService, error)
|
||||
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1beta1.APIService, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*v1beta1.APIServiceList, error)
|
||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.APIService, err error)
|
||||
APIServiceExpansion
|
||||
}
|
||||
|
||||
// aPIServices implements APIServiceInterface
|
||||
type aPIServices struct {
|
||||
client rest.Interface
|
||||
}
|
||||
|
||||
// newAPIServices returns a APIServices
|
||||
func newAPIServices(c *ApiregistrationV1beta1Client) *aPIServices {
|
||||
return &aPIServices{
|
||||
client: c.RESTClient(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the aPIService, and returns the corresponding aPIService object, and an error if there is any.
|
||||
func (c *aPIServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.APIService, err error) {
|
||||
result = &v1beta1.APIService{}
|
||||
err = c.client.Get().
|
||||
Resource("apiservices").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of APIServices that match those selectors.
|
||||
func (c *aPIServices) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.APIServiceList, err error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
result = &v1beta1.APIServiceList{}
|
||||
err = c.client.Get().
|
||||
Resource("apiservices").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested aPIServices.
|
||||
func (c *aPIServices) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Resource("apiservices").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Watch(ctx)
|
||||
}
|
||||
|
||||
// Create takes the representation of a aPIService and creates it. Returns the server's representation of the aPIService, and an error, if there is any.
|
||||
func (c *aPIServices) Create(ctx context.Context, aPIService *v1beta1.APIService, opts v1.CreateOptions) (result *v1beta1.APIService, err error) {
|
||||
result = &v1beta1.APIService{}
|
||||
err = c.client.Post().
|
||||
Resource("apiservices").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(aPIService).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a aPIService and updates it. Returns the server's representation of the aPIService, and an error, if there is any.
|
||||
func (c *aPIServices) Update(ctx context.Context, aPIService *v1beta1.APIService, opts v1.UpdateOptions) (result *v1beta1.APIService, err error) {
|
||||
result = &v1beta1.APIService{}
|
||||
err = c.client.Put().
|
||||
Resource("apiservices").
|
||||
Name(aPIService.Name).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(aPIService).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *aPIServices) UpdateStatus(ctx context.Context, aPIService *v1beta1.APIService, opts v1.UpdateOptions) (result *v1beta1.APIService, err error) {
|
||||
result = &v1beta1.APIService{}
|
||||
err = c.client.Put().
|
||||
Resource("apiservices").
|
||||
Name(aPIService.Name).
|
||||
SubResource("status").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(aPIService).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the aPIService and deletes it. Returns an error if one occurs.
|
||||
func (c *aPIServices) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Resource("apiservices").
|
||||
Name(name).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *aPIServices) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
var timeout time.Duration
|
||||
if listOpts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
return c.client.Delete().
|
||||
Resource("apiservices").
|
||||
VersionedParams(&listOpts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched aPIService.
|
||||
func (c *aPIServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.APIService, err error) {
|
||||
result = &v1beta1.APIService{}
|
||||
err = c.client.Patch(pt).
|
||||
Resource("apiservices").
|
||||
Name(name).
|
||||
SubResource(subresources...).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(data).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated typed clients.
|
||||
package v1beta1
|
||||
Generated
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
Generated
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
v1beta1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1"
|
||||
)
|
||||
|
||||
type FakeApiregistrationV1beta1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeApiregistrationV1beta1) APIServices() v1beta1.APIServiceInterface {
|
||||
return &FakeAPIServices{c}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeApiregistrationV1beta1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
Generated
Vendored
+133
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
v1beta1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
|
||||
)
|
||||
|
||||
// FakeAPIServices implements APIServiceInterface
|
||||
type FakeAPIServices struct {
|
||||
Fake *FakeApiregistrationV1beta1
|
||||
}
|
||||
|
||||
var apiservicesResource = schema.GroupVersionResource{Group: "apiregistration.k8s.io", Version: "v1beta1", Resource: "apiservices"}
|
||||
|
||||
var apiservicesKind = schema.GroupVersionKind{Group: "apiregistration.k8s.io", Version: "v1beta1", Kind: "APIService"}
|
||||
|
||||
// Get takes name of the aPIService, and returns the corresponding aPIService object, and an error if there is any.
|
||||
func (c *FakeAPIServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.APIService, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(apiservicesResource, name), &v1beta1.APIService{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.APIService), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of APIServices that match those selectors.
|
||||
func (c *FakeAPIServices) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.APIServiceList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(apiservicesResource, apiservicesKind, opts), &v1beta1.APIServiceList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1beta1.APIServiceList{ListMeta: obj.(*v1beta1.APIServiceList).ListMeta}
|
||||
for _, item := range obj.(*v1beta1.APIServiceList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested aPIServices.
|
||||
func (c *FakeAPIServices) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(apiservicesResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a aPIService and creates it. Returns the server's representation of the aPIService, and an error, if there is any.
|
||||
func (c *FakeAPIServices) Create(ctx context.Context, aPIService *v1beta1.APIService, opts v1.CreateOptions) (result *v1beta1.APIService, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(apiservicesResource, aPIService), &v1beta1.APIService{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.APIService), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a aPIService and updates it. Returns the server's representation of the aPIService, and an error, if there is any.
|
||||
func (c *FakeAPIServices) Update(ctx context.Context, aPIService *v1beta1.APIService, opts v1.UpdateOptions) (result *v1beta1.APIService, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(apiservicesResource, aPIService), &v1beta1.APIService{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.APIService), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeAPIServices) UpdateStatus(ctx context.Context, aPIService *v1beta1.APIService, opts v1.UpdateOptions) (*v1beta1.APIService, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateSubresourceAction(apiservicesResource, "status", aPIService), &v1beta1.APIService{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.APIService), err
|
||||
}
|
||||
|
||||
// Delete takes name of the aPIService and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeAPIServices) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(apiservicesResource, name), &v1beta1.APIService{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeAPIServices) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(apiservicesResource, listOpts)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1beta1.APIServiceList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched aPIService.
|
||||
func (c *FakeAPIServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.APIService, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(apiservicesResource, name, pt, data, subresources...), &v1beta1.APIService{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.APIService), err
|
||||
}
|
||||
Generated
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
type APIServiceExpansion interface{}
|
||||
Vendored
+5
@@ -846,8 +846,13 @@ k8s.io/klog
|
||||
k8s.io/kube-aggregator/pkg/apis/apiregistration
|
||||
k8s.io/kube-aggregator/pkg/apis/apiregistration/v1
|
||||
k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1
|
||||
k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset
|
||||
k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake
|
||||
k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme
|
||||
k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1
|
||||
k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake
|
||||
k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1
|
||||
k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake
|
||||
# k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c
|
||||
k8s.io/kube-openapi/pkg/builder
|
||||
k8s.io/kube-openapi/pkg/common
|
||||
|
||||
Reference in New Issue
Block a user