Merge pull request #49 from qiujian16/appliedmanifestwork

Add appliedmanifestwork api
This commit is contained in:
OpenShift Merge Robot
2020-07-20 09:56:34 -04:00
committed by GitHub
29 changed files with 930 additions and 281 deletions

View File

@@ -25,6 +25,10 @@ rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles", "roles"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete", "escalate", "bind"]
# Allow the registration-operator to create crds
- apiGroups: ["apiextensions.k8s.io"]
resources: ["customresourcedefinitions"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete"]
# Allow the registration-operator to manage klusterlet apis.
- apiGroups: ["operator.open-cluster-management.io"]
resources: ["klusterlets"]

View File

@@ -122,6 +122,18 @@ spec:
- delete
- escalate
- bind
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- create
- get
- list
- update
- watch
- patch
- delete
- apiGroups:
- operator.open-cluster-management.io
resources:

2
go.mod
View File

@@ -7,7 +7,7 @@ require (
github.com/go-bindata/go-bindata v3.1.2+incompatible
github.com/onsi/ginkgo v1.11.0
github.com/onsi/gomega v1.8.1
github.com/open-cluster-management/api v0.0.0-20200629211334-8be047b65c52
github.com/open-cluster-management/api v0.0.0-20200715201722-3c3c076bf062
github.com/openshift/api v0.0.0-20200521101457-60c476765272
github.com/openshift/build-machinery-go v0.0.0-20200424080330-082bf86082cc
github.com/openshift/library-go v0.0.0-20200617154932-eaf8c138def4

4
go.sum
View File

@@ -310,8 +310,8 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34=
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/open-cluster-management/api v0.0.0-20200629211334-8be047b65c52 h1:8+Qh4L7ijoYK0wKM3Whjge53IVhL2fVWRbuUjy5kMUM=
github.com/open-cluster-management/api v0.0.0-20200629211334-8be047b65c52/go.mod h1:+vUECYB7WkfCb52r0J7rxgD1mseSGAqGi8rTLLRcbgw=
github.com/open-cluster-management/api v0.0.0-20200715201722-3c3c076bf062 h1:sYKu/XTeGrYCjO7x6/r6CfM/R8/Lr2kX7IG1DOC+wW0=
github.com/open-cluster-management/api v0.0.0-20200715201722-3c3c076bf062/go.mod h1:+vUECYB7WkfCb52r0J7rxgD1mseSGAqGi8rTLLRcbgw=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=

View File

@@ -2,10 +2,15 @@
source "$(dirname "${BASH_SOURCE}")/init.sh"
for f in $CRD_FILES
for f in $HUB_CRD_FILES
do
cp $f ./manifests/cluster-manager/
done
for f in $SPOKE_CRD_FILES
do
cp $f ./manifests/klusterlet/
done
cp $CLUSTER_MANAGER_CRD_FILE ./deploy/cluster-manager/crds/
cp $KLUSTERLET_CRD_FILE ./deploy/klusterlet/crds/

View File

@@ -4,9 +4,11 @@ set -o errexit
set -o nounset
set -o pipefail
CRD_FILES="./vendor/github.com/open-cluster-management/api/cluster/v1/*.crd.yaml
./vendor/github.com/open-cluster-management/api/work/v1/*.crd.yaml
HUB_CRD_FILES="./vendor/github.com/open-cluster-management/api/cluster/v1/*.crd.yaml
./vendor/github.com/open-cluster-management/api/work/v1/0000_00_work.open-cluster-management.io_manifestworks.crd.yaml
"
SPOKE_CRD_FILES="./vendor/github.com/open-cluster-management/api/work/v1/0000_01_work.open-cluster-management.io_appliedmanifestworks.crd.yaml"
CLUSTER_MANAGER_CRD_FILE="./vendor/github.com/open-cluster-management/api/operator/v1/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml"
KLUSTERLET_CRD_FILE="./vendor/github.com/open-cluster-management/api/operator/v1/0000_00_operator.open-cluster-management.io_klusterlets.crd.yaml"

View File

@@ -2,11 +2,16 @@
source "$(dirname "${BASH_SOURCE}")/init.sh"
for f in $CRD_FILES
for f in $HUB_CRD_FILES
do
diff -N $f ./manifests/cluster-manager/$(basename $f) || ( echo 'crd content is incorrect' && false )
done
for f in $SPOKE_CRD_FILES
do
diff -N $f ./manifests/klusterlet/$(basename $f) || ( echo 'crd content is incorrect' && false )
done
diff -N $CLUSTER_MANAGER_CRD_FILE ./deploy/cluster-manager/crds/$(basename $CLUSTER_MANAGER_CRD_FILE) || ( echo 'crd content is incorrect' && false )
diff -N $KLUSTERLET_CRD_FILE ./deploy/klusterlet/crds/$(basename $KLUSTERLET_CRD_FILE) || ( echo 'crd content is incorrect' && false )

View File

@@ -59,45 +59,6 @@ spec:
description: Status represents the current status of work
type: object
properties:
appliedResources:
description: AppliedResources represents a list of resources defined
within the manifestwork that are applied. Only resources with valid
GroupVersionResource, namespace, and name are suitable. An item in
this slice is deleted when there is no mapped manifest in manifestwork.Spec
or by finalizer. The resource relating to the item will also be removed
from managed cluster. The deleted resource may still be present until
the finalizers for that resource are finished. However, the resource
will not be undeleted, so it can be removed from this list and eventual
consistency is preserved.
type: array
items:
description: AppliedManifestResourceMeta represents the gvr, name
and namespace of a resource. Since these resources have been created,
they must have valid group, version, resource, namespace, and name.
type: object
properties:
group:
description: Group is the API Group of the kubernetes resource
type: string
name:
description: Name is the name of the kubernetes resource
type: string
namespace:
description: Name is the namespace of the kubernetes resource,
empty string indicates it is a cluster scoped resource.
type: string
resource:
description: Resource is the resource name of the kubernetes resource
type: string
uid:
description: UID is set on successful deletion of the kubernetes
resource by controller. The resource might be still visible
on the managed cluster after this field is set. It is not directly
settable by a client.
type: string
version:
description: Version is the version of the kubernetes resource
type: string
conditions:
description: 'Conditions contains the different condition statuses for
this work. Valid condition types are: 1. Applied represents workload

View File

@@ -0,0 +1,105 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
creationTimestamp: null
name: appliedmanifestworks.work.open-cluster-management.io
spec:
group: work.open-cluster-management.io
names:
kind: AppliedManifestWork
listKind: AppliedManifestWorkList
plural: appliedmanifestworks
singular: appliedmanifestwork
scope: "Cluster"
preserveUnknownFields: false
subresources:
status: {}
validation:
openAPIV3Schema:
description: AppliedManifestWork represents an applied manifestwork on managed
cluster. It is placed on managed cluster. An AppliedManifestWork links to
a manifestwork on a hub recording resources deployed in the managed cluster.
When the agent is removed from managed cluster, cluster-admin on managed cluster
can delete appliedmanifestwork to remove resources deployed by the agent.
The name of the appliedmanifestwork must be in the format of {hash of hub's
first kube-apiserver url}-{manifestwork name}
type: object
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: Spec represents the desired configuration of AppliedManifestWork
type: object
properties:
hubHash:
description: HubHash represents the hash of the first hub kube apiserver
to identify which hub this AppliedManifestWork links to.
type: string
manifestWorkName:
description: ManifestWorkName represents the name of the related manifestwork
on hub.
type: string
status:
description: Status represents the current status of AppliedManifestWork
type: object
properties:
appliedResources:
description: AppliedResources represents a list of resources defined
within the manifestwork that are applied. Only resources with valid
GroupVersionResource, namespace, and name are suitable. An item in
this slice is deleted when there is no mapped manifest in manifestwork.Spec
or by finalizer. The resource relating to the item will also be removed
from managed cluster. The deleted resource may still be present until
the finalizers for that resource are finished. However, the resource
will not be undeleted, so it can be removed from this list and eventual
consistency is preserved.
type: array
items:
description: AppliedManifestResourceMeta represents the gvr, name
and namespace of a resource. Since these resources have been created,
they must have valid group, version, resource, namespace, and name.
type: object
properties:
group:
description: Group is the API Group of the kubernetes resource
type: string
name:
description: Name is the name of the kubernetes resource
type: string
namespace:
description: Name is the namespace of the kubernetes resource,
empty string indicates it is a cluster scoped resource.
type: string
resource:
description: Resource is the resource name of the kubernetes resource
type: string
uid:
description: UID is set on successful deletion of the kubernetes
resource by controller. The resource might be still visible
on the managed cluster after this field is set. It is not directly
settable by a client.
type: string
version:
description: Version is the version of the kubernetes resource
type: string
version: v1
versions:
- name: v1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -27,3 +27,13 @@ rules:
- apiGroups: ["", "events.k8s.io"]
resources: ["events"]
verbs: ["create", "patch", "update"]
# Allow agent to managed appliedmanifestworks
- apiGroups: ["work.open-cluster-management.io"]
resources: ["appliedmanifestworks"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["work.open-cluster-management.io"]
resources: ["appliedmanifestworks/status"]
verbs: ["patch", "update"]
- apiGroups: ["work.open-cluster-management.io"]
resources: ["appliedmanifestworks/finalizers"]
verbs: ["update"]

View File

@@ -310,45 +310,6 @@ spec:
description: Status represents the current status of work
type: object
properties:
appliedResources:
description: AppliedResources represents a list of resources defined
within the manifestwork that are applied. Only resources with valid
GroupVersionResource, namespace, and name are suitable. An item in
this slice is deleted when there is no mapped manifest in manifestwork.Spec
or by finalizer. The resource relating to the item will also be removed
from managed cluster. The deleted resource may still be present until
the finalizers for that resource are finished. However, the resource
will not be undeleted, so it can be removed from this list and eventual
consistency is preserved.
type: array
items:
description: AppliedManifestResourceMeta represents the gvr, name
and namespace of a resource. Since these resources have been created,
they must have valid group, version, resource, namespace, and name.
type: object
properties:
group:
description: Group is the API Group of the kubernetes resource
type: string
name:
description: Name is the name of the kubernetes resource
type: string
namespace:
description: Name is the namespace of the kubernetes resource,
empty string indicates it is a cluster scoped resource.
type: string
resource:
description: Resource is the resource name of the kubernetes resource
type: string
uid:
description: UID is set on successful deletion of the kubernetes
resource by controller. The resource might be still visible
on the managed cluster after this field is set. It is not directly
settable by a client.
type: string
version:
description: Version is the version of the kubernetes resource
type: string
conditions:
description: 'Conditions contains the different condition statuses for
this work. Valid condition types are: 1. Applied represents workload

View File

@@ -1,5 +1,6 @@
// Code generated for package bindata by go-bindata DO NOT EDIT. (@generated)
// sources:
// manifests/klusterlet/0000_01_work.open-cluster-management.io_appliedmanifestworks.crd.yaml
// manifests/klusterlet/klusterlet-registration-clusterrole.yaml
// manifests/klusterlet/klusterlet-registration-clusterrolebinding.yaml
// manifests/klusterlet/klusterlet-registration-deployment.yaml
@@ -64,6 +65,128 @@ func (fi bindataFileInfo) Sys() interface{} {
return nil
}
var _manifestsKlusterlet0000_01_workOpenClusterManagementIo_appliedmanifestworksCrdYaml = []byte(`apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
creationTimestamp: null
name: appliedmanifestworks.work.open-cluster-management.io
spec:
group: work.open-cluster-management.io
names:
kind: AppliedManifestWork
listKind: AppliedManifestWorkList
plural: appliedmanifestworks
singular: appliedmanifestwork
scope: "Cluster"
preserveUnknownFields: false
subresources:
status: {}
validation:
openAPIV3Schema:
description: AppliedManifestWork represents an applied manifestwork on managed
cluster. It is placed on managed cluster. An AppliedManifestWork links to
a manifestwork on a hub recording resources deployed in the managed cluster.
When the agent is removed from managed cluster, cluster-admin on managed cluster
can delete appliedmanifestwork to remove resources deployed by the agent.
The name of the appliedmanifestwork must be in the format of {hash of hub's
first kube-apiserver url}-{manifestwork name}
type: object
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: Spec represents the desired configuration of AppliedManifestWork
type: object
properties:
hubHash:
description: HubHash represents the hash of the first hub kube apiserver
to identify which hub this AppliedManifestWork links to.
type: string
manifestWorkName:
description: ManifestWorkName represents the name of the related manifestwork
on hub.
type: string
status:
description: Status represents the current status of AppliedManifestWork
type: object
properties:
appliedResources:
description: AppliedResources represents a list of resources defined
within the manifestwork that are applied. Only resources with valid
GroupVersionResource, namespace, and name are suitable. An item in
this slice is deleted when there is no mapped manifest in manifestwork.Spec
or by finalizer. The resource relating to the item will also be removed
from managed cluster. The deleted resource may still be present until
the finalizers for that resource are finished. However, the resource
will not be undeleted, so it can be removed from this list and eventual
consistency is preserved.
type: array
items:
description: AppliedManifestResourceMeta represents the gvr, name
and namespace of a resource. Since these resources have been created,
they must have valid group, version, resource, namespace, and name.
type: object
properties:
group:
description: Group is the API Group of the kubernetes resource
type: string
name:
description: Name is the name of the kubernetes resource
type: string
namespace:
description: Name is the namespace of the kubernetes resource,
empty string indicates it is a cluster scoped resource.
type: string
resource:
description: Resource is the resource name of the kubernetes resource
type: string
uid:
description: UID is set on successful deletion of the kubernetes
resource by controller. The resource might be still visible
on the managed cluster after this field is set. It is not directly
settable by a client.
type: string
version:
description: Version is the version of the kubernetes resource
type: string
version: v1
versions:
- name: v1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
`)
func manifestsKlusterlet0000_01_workOpenClusterManagementIo_appliedmanifestworksCrdYamlBytes() ([]byte, error) {
return _manifestsKlusterlet0000_01_workOpenClusterManagementIo_appliedmanifestworksCrdYaml, nil
}
func manifestsKlusterlet0000_01_workOpenClusterManagementIo_appliedmanifestworksCrdYaml() (*asset, error) {
bytes, err := manifestsKlusterlet0000_01_workOpenClusterManagementIo_appliedmanifestworksCrdYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/klusterlet/0000_01_work.open-cluster-management.io_appliedmanifestworks.crd.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsKlusterletKlusterletRegistrationClusterroleYaml = []byte(`# Clusterrole for work agent in addition to admin clusterrole.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
@@ -335,6 +458,16 @@ rules:
- apiGroups: ["", "events.k8s.io"]
resources: ["events"]
verbs: ["create", "patch", "update"]
# Allow agent to managed appliedmanifestworks
- apiGroups: ["work.open-cluster-management.io"]
resources: ["appliedmanifestworks"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["work.open-cluster-management.io"]
resources: ["appliedmanifestworks/status"]
verbs: ["patch", "update"]
- apiGroups: ["work.open-cluster-management.io"]
resources: ["appliedmanifestworks/finalizers"]
verbs: ["update"]
`)
func manifestsKlusterletKlusterletWorkClusterroleYamlBytes() ([]byte, error) {
@@ -578,17 +711,18 @@ func AssetNames() []string {
// _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){
"manifests/klusterlet/klusterlet-registration-clusterrole.yaml": manifestsKlusterletKlusterletRegistrationClusterroleYaml,
"manifests/klusterlet/klusterlet-registration-clusterrolebinding.yaml": manifestsKlusterletKlusterletRegistrationClusterrolebindingYaml,
"manifests/klusterlet/klusterlet-registration-deployment.yaml": manifestsKlusterletKlusterletRegistrationDeploymentYaml,
"manifests/klusterlet/klusterlet-registration-role.yaml": manifestsKlusterletKlusterletRegistrationRoleYaml,
"manifests/klusterlet/klusterlet-registration-rolebinding.yaml": manifestsKlusterletKlusterletRegistrationRolebindingYaml,
"manifests/klusterlet/klusterlet-registration-serviceaccount.yaml": manifestsKlusterletKlusterletRegistrationServiceaccountYaml,
"manifests/klusterlet/klusterlet-work-clusterrole.yaml": manifestsKlusterletKlusterletWorkClusterroleYaml,
"manifests/klusterlet/klusterlet-work-clusterrolebinding-addition.yaml": manifestsKlusterletKlusterletWorkClusterrolebindingAdditionYaml,
"manifests/klusterlet/klusterlet-work-clusterrolebinding.yaml": manifestsKlusterletKlusterletWorkClusterrolebindingYaml,
"manifests/klusterlet/klusterlet-work-deployment.yaml": manifestsKlusterletKlusterletWorkDeploymentYaml,
"manifests/klusterlet/klusterlet-work-serviceaccount.yaml": manifestsKlusterletKlusterletWorkServiceaccountYaml,
"manifests/klusterlet/0000_01_work.open-cluster-management.io_appliedmanifestworks.crd.yaml": manifestsKlusterlet0000_01_workOpenClusterManagementIo_appliedmanifestworksCrdYaml,
"manifests/klusterlet/klusterlet-registration-clusterrole.yaml": manifestsKlusterletKlusterletRegistrationClusterroleYaml,
"manifests/klusterlet/klusterlet-registration-clusterrolebinding.yaml": manifestsKlusterletKlusterletRegistrationClusterrolebindingYaml,
"manifests/klusterlet/klusterlet-registration-deployment.yaml": manifestsKlusterletKlusterletRegistrationDeploymentYaml,
"manifests/klusterlet/klusterlet-registration-role.yaml": manifestsKlusterletKlusterletRegistrationRoleYaml,
"manifests/klusterlet/klusterlet-registration-rolebinding.yaml": manifestsKlusterletKlusterletRegistrationRolebindingYaml,
"manifests/klusterlet/klusterlet-registration-serviceaccount.yaml": manifestsKlusterletKlusterletRegistrationServiceaccountYaml,
"manifests/klusterlet/klusterlet-work-clusterrole.yaml": manifestsKlusterletKlusterletWorkClusterroleYaml,
"manifests/klusterlet/klusterlet-work-clusterrolebinding-addition.yaml": manifestsKlusterletKlusterletWorkClusterrolebindingAdditionYaml,
"manifests/klusterlet/klusterlet-work-clusterrolebinding.yaml": manifestsKlusterletKlusterletWorkClusterrolebindingYaml,
"manifests/klusterlet/klusterlet-work-deployment.yaml": manifestsKlusterletKlusterletWorkDeploymentYaml,
"manifests/klusterlet/klusterlet-work-serviceaccount.yaml": manifestsKlusterletKlusterletWorkServiceaccountYaml,
}
// AssetDir returns the file names below a certain
@@ -634,17 +768,18 @@ type bintree struct {
var _bintree = &bintree{nil, map[string]*bintree{
"manifests": {nil, map[string]*bintree{
"klusterlet": {nil, map[string]*bintree{
"klusterlet-registration-clusterrole.yaml": {manifestsKlusterletKlusterletRegistrationClusterroleYaml, map[string]*bintree{}},
"klusterlet-registration-clusterrolebinding.yaml": {manifestsKlusterletKlusterletRegistrationClusterrolebindingYaml, map[string]*bintree{}},
"klusterlet-registration-deployment.yaml": {manifestsKlusterletKlusterletRegistrationDeploymentYaml, map[string]*bintree{}},
"klusterlet-registration-role.yaml": {manifestsKlusterletKlusterletRegistrationRoleYaml, map[string]*bintree{}},
"klusterlet-registration-rolebinding.yaml": {manifestsKlusterletKlusterletRegistrationRolebindingYaml, map[string]*bintree{}},
"klusterlet-registration-serviceaccount.yaml": {manifestsKlusterletKlusterletRegistrationServiceaccountYaml, map[string]*bintree{}},
"klusterlet-work-clusterrole.yaml": {manifestsKlusterletKlusterletWorkClusterroleYaml, map[string]*bintree{}},
"klusterlet-work-clusterrolebinding-addition.yaml": {manifestsKlusterletKlusterletWorkClusterrolebindingAdditionYaml, map[string]*bintree{}},
"klusterlet-work-clusterrolebinding.yaml": {manifestsKlusterletKlusterletWorkClusterrolebindingYaml, map[string]*bintree{}},
"klusterlet-work-deployment.yaml": {manifestsKlusterletKlusterletWorkDeploymentYaml, map[string]*bintree{}},
"klusterlet-work-serviceaccount.yaml": {manifestsKlusterletKlusterletWorkServiceaccountYaml, map[string]*bintree{}},
"0000_01_work.open-cluster-management.io_appliedmanifestworks.crd.yaml": {manifestsKlusterlet0000_01_workOpenClusterManagementIo_appliedmanifestworksCrdYaml, map[string]*bintree{}},
"klusterlet-registration-clusterrole.yaml": {manifestsKlusterletKlusterletRegistrationClusterroleYaml, map[string]*bintree{}},
"klusterlet-registration-clusterrolebinding.yaml": {manifestsKlusterletKlusterletRegistrationClusterrolebindingYaml, map[string]*bintree{}},
"klusterlet-registration-deployment.yaml": {manifestsKlusterletKlusterletRegistrationDeploymentYaml, map[string]*bintree{}},
"klusterlet-registration-role.yaml": {manifestsKlusterletKlusterletRegistrationRoleYaml, map[string]*bintree{}},
"klusterlet-registration-rolebinding.yaml": {manifestsKlusterletKlusterletRegistrationRolebindingYaml, map[string]*bintree{}},
"klusterlet-registration-serviceaccount.yaml": {manifestsKlusterletKlusterletRegistrationServiceaccountYaml, map[string]*bintree{}},
"klusterlet-work-clusterrole.yaml": {manifestsKlusterletKlusterletWorkClusterroleYaml, map[string]*bintree{}},
"klusterlet-work-clusterrolebinding-addition.yaml": {manifestsKlusterletKlusterletWorkClusterrolebindingAdditionYaml, map[string]*bintree{}},
"klusterlet-work-clusterrolebinding.yaml": {manifestsKlusterletKlusterletWorkClusterrolebindingYaml, map[string]*bintree{}},
"klusterlet-work-deployment.yaml": {manifestsKlusterletKlusterletWorkDeploymentYaml, map[string]*bintree{}},
"klusterlet-work-serviceaccount.yaml": {manifestsKlusterletKlusterletWorkServiceaccountYaml, map[string]*bintree{}},
}},
}},
}}

View File

@@ -7,6 +7,7 @@ import (
"strings"
corev1 "k8s.io/api/core/v1"
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -40,6 +41,10 @@ const (
)
var (
crdStaticFiles = []string{
"manifests/klusterlet/0000_01_work.open-cluster-management.io_appliedmanifestworks.crd.yaml",
}
staticResourceFiles = []string{
"manifests/klusterlet/klusterlet-registration-serviceaccount.yaml",
"manifests/klusterlet/klusterlet-registration-clusterrole.yaml",
@@ -59,16 +64,18 @@ var (
)
type klusterletController struct {
klusterletClient operatorv1client.KlusterletInterface
klusterletLister operatorlister.KlusterletLister
kubeClient kubernetes.Interface
kubeVersion *version.Version
operatorNamespace string
klusterletClient operatorv1client.KlusterletInterface
klusterletLister operatorlister.KlusterletLister
kubeClient kubernetes.Interface
apiExtensionClient apiextensionsclient.Interface
kubeVersion *version.Version
operatorNamespace string
}
// NewKlusterletController construct klusterlet controller
func NewKlusterletController(
kubeClient kubernetes.Interface,
apiExtensionClient apiextensionsclient.Interface,
klusterletClient operatorv1client.KlusterletInterface,
klusterletInformer operatorinformer.KlusterletInformer,
secretInformer coreinformer.SecretInformer,
@@ -77,11 +84,12 @@ func NewKlusterletController(
operatorNamespace string,
recorder events.Recorder) factory.Controller {
controller := &klusterletController{
kubeClient: kubeClient,
klusterletClient: klusterletClient,
klusterletLister: klusterletInformer.Lister(),
kubeVersion: kubeVersion,
operatorNamespace: operatorNamespace,
kubeClient: kubeClient,
apiExtensionClient: apiExtensionClient,
klusterletClient: klusterletClient,
klusterletLister: klusterletInformer.Lister(),
kubeVersion: kubeVersion,
operatorNamespace: operatorNamespace,
}
return factory.New().WithSync(controller.sync).
@@ -223,13 +231,14 @@ func (n *klusterletController) sync(ctx context.Context, controllerContext facto
}
// Apply static files
appliedStaticFiles := append(crdStaticFiles, staticResourceFiles...)
resourceResults := resourceapply.ApplyDirectly(
resourceapply.NewKubeClientHolder(n.kubeClient),
resourceapply.NewKubeClientHolder(n.kubeClient).WithAPIExtensionsClient(n.apiExtensionClient),
controllerContext.Recorder(),
func(name string) ([]byte, error) {
return assets.MustCreateAssetFromTemplate(name, bindata.MustAsset(filepath.Join("", name)), config).Data, nil
},
staticResourceFiles...,
appliedStaticFiles...,
)
for _, result := range resourceResults {
@@ -358,7 +367,7 @@ func (n *klusterletController) cleanUp(ctx context.Context, controllerContext fa
err := helpers.CleanUpStaticObject(
ctx,
n.kubeClient,
nil,
n.apiExtensionClient,
nil,
func(name string) ([]byte, error) {
return assets.MustCreateAssetFromTemplate(name, bindata.MustAsset(filepath.Join("", name)), config).Data, nil

View File

@@ -13,6 +13,7 @@ import (
testinghelper "github.com/open-cluster-management/registration-operator/pkg/helpers/testing"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
fakeapiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -24,10 +25,11 @@ import (
)
type testController struct {
controller *klusterletController
kubeClient *fakekube.Clientset
operatorClient *fakeoperatorclient.Clientset
operatorStore cache.Store
controller *klusterletController
kubeClient *fakekube.Clientset
apiExtensionClient *fakeapiextensions.Clientset
operatorClient *fakeoperatorclient.Clientset
operatorStore cache.Store
}
func newSecret(name, namespace string) *corev1.Secret {
@@ -86,26 +88,29 @@ func newNamespace(name string) *corev1.Namespace {
func newTestController(klusterlet *opratorapiv1.Klusterlet, objects ...runtime.Object) *testController {
fakeKubeClient := fakekube.NewSimpleClientset(objects...)
fakeAPIExtensionClient := fakeapiextensions.NewSimpleClientset()
fakeOperatorClient := fakeoperatorclient.NewSimpleClientset(klusterlet)
operatorInformers := operatorinformers.NewSharedInformerFactory(fakeOperatorClient, 5*time.Minute)
kubeVersion, _ := version.ParseGeneric("v1.18.0")
hubController := &klusterletController{
klusterletClient: fakeOperatorClient.OperatorV1().Klusterlets(),
kubeClient: fakeKubeClient,
klusterletLister: operatorInformers.Operator().V1().Klusterlets().Lister(),
kubeVersion: kubeVersion,
operatorNamespace: "open-cluster-management",
klusterletClient: fakeOperatorClient.OperatorV1().Klusterlets(),
kubeClient: fakeKubeClient,
apiExtensionClient: fakeAPIExtensionClient,
klusterletLister: operatorInformers.Operator().V1().Klusterlets().Lister(),
kubeVersion: kubeVersion,
operatorNamespace: "open-cluster-management",
}
store := operatorInformers.Operator().V1().Klusterlets().Informer().GetStore()
store.Add(klusterlet)
return &testController{
controller: hubController,
kubeClient: fakeKubeClient,
operatorClient: fakeOperatorClient,
operatorStore: store,
controller: hubController,
kubeClient: fakeKubeClient,
apiExtensionClient: fakeAPIExtensionClient,
operatorClient: fakeOperatorClient,
operatorStore: store,
}
}
@@ -258,6 +263,18 @@ func TestSyncDeploy(t *testing.T) {
ensureObject(t, object, klusterlet)
}
apiExtenstionAction := controller.apiExtensionClient.Actions()
createCRDObjects := []runtime.Object{}
for _, action := range apiExtenstionAction {
if action.GetVerb() == "create" && action.GetResource().Resource == "customresourcedefinitions" {
object := action.(clienttesting.CreateActionImpl).Object
createCRDObjects = append(createCRDObjects, object)
}
}
if len(createCRDObjects) != 1 {
t.Errorf("Expect 1 objects created in the sync loop, actual %d", len(createCRDObjects))
}
operatorAction := controller.operatorClient.Actions()
if len(operatorAction) != 2 {
t.Errorf("Expect 2 actions in the sync loop, actual %#v", operatorAction)
@@ -296,6 +313,19 @@ func TestSyncDelete(t *testing.T) {
if len(kubeActions) != 12 {
t.Errorf("Expected 12 delete actions, but got %d", len(kubeActions))
}
deleteCRDActions := []clienttesting.DeleteActionImpl{}
crdActions := controller.apiExtensionClient.Actions()
for _, action := range crdActions {
if action.GetVerb() == "delete" {
deleteAction := action.(clienttesting.DeleteActionImpl)
deleteActions = append(deleteCRDActions, deleteAction)
}
}
if len(crdActions) != 0 {
t.Errorf("Expected 0 delete actions, but got %d", len(crdActions))
}
}
// TestGetServersFromKlusterlet tests getServersFromKlusterlet func

View File

@@ -80,6 +80,10 @@ func RunKlusterletOperator(ctx context.Context, controllerContext *controllercmd
if err != nil {
return err
}
apiExtensionClient, err := apiextensionsclient.NewForConfig(controllerContext.KubeConfig)
if err != nil {
return err
}
version, err := kubeClient.ServerVersion()
if err != nil {
return err
@@ -107,6 +111,7 @@ func RunKlusterletOperator(ctx context.Context, controllerContext *controllercmd
klusterletController := klusterletcontroller.NewKlusterletController(
kubeClient,
apiExtensionClient,
operatorClient.OperatorV1().Klusterlets(),
operatorInformer.Operator().V1().Klusterlets(),
kubeInformer.Core().V1().Secrets(),

View File

@@ -3,10 +3,13 @@ package e2e
import (
"context"
"fmt"
"k8s.io/klog"
"os"
"time"
"k8s.io/klog"
"github.com/onsi/gomega"
clusterclient "github.com/open-cluster-management/api/client/cluster/clientset/versioned"
operatorclient "github.com/open-cluster-management/api/client/operator/clientset/versioned"
workv1client "github.com/open-cluster-management/api/client/work/clientset/versioned"
@@ -24,7 +27,6 @@ import (
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/retry"
)
type Tester struct {
@@ -134,8 +136,8 @@ func (t *Tester) CreateKlusterlet(name, clusterName, agentNamespace string) (*op
Name: name,
},
Spec: operatorapiv1.KlusterletSpec{
RegistrationImagePullSpec: "quay.io/open-cluster-management/registration",
WorkImagePullSpec: "quay.io/open-cluster-management/work",
RegistrationImagePullSpec: "quay.io/open-cluster-management/registration:latest",
WorkImagePullSpec: "quay.io/open-cluster-management/work:latest",
ExternalServerURLs: []operatorapiv1.ServerURL{
{
URL: "https://localhost",
@@ -221,23 +223,20 @@ func (t *Tester) ApproveCSR(clusterName string) error {
for i := range csrs.Items {
csr := &csrs.Items[i]
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
if csr, err = csrClient.Get(context.TODO(), csr.Name, metav1.GetOptions{}); err != nil {
return err
}
if isCSRInTerminalState(&csr.Status) {
return nil
}
csr.Status.Conditions = append(csr.Status.Conditions, certificatesv1beta1.CertificateSigningRequestCondition{
Type: certificatesv1beta1.CertificateApproved,
Reason: "Approved by E2E",
Message: "Approved as part of e2e",
})
_, err = csrClient.UpdateApproval(context.TODO(), csr, metav1.UpdateOptions{})
if csr, err = csrClient.Get(context.TODO(), csr.Name, metav1.GetOptions{}); err != nil {
return err
}
if isCSRInTerminalState(&csr.Status) {
return nil
}
csr.Status.Conditions = append(csr.Status.Conditions, certificatesv1beta1.CertificateSigningRequestCondition{
Type: certificatesv1beta1.CertificateApproved,
Reason: "Approved by E2E",
Message: "Approved as part of e2e",
})
_, err = csrClient.UpdateApproval(context.TODO(), csr, metav1.UpdateOptions{})
if err != nil {
return err
}
@@ -258,19 +257,16 @@ func isCSRInTerminalState(status *certificatesv1beta1.CertificateSigningRequestS
}
func (t *Tester) AcceptsClient(clusterName string) error {
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
managedCluster, err := t.ClusterClient.ClusterV1().ManagedClusters().Get(context.TODO(),
clusterName, metav1.GetOptions{})
if err != nil {
return err
}
managedCluster.Spec.HubAcceptsClient = true
managedCluster.Spec.LeaseDurationSeconds = 5
managedCluster, err = t.ClusterClient.ClusterV1().ManagedClusters().Update(context.TODO(),
managedCluster, metav1.UpdateOptions{})
managedCluster, err := t.ClusterClient.ClusterV1().ManagedClusters().Get(context.TODO(),
clusterName, metav1.GetOptions{})
if err != nil {
return err
})
}
managedCluster.Spec.HubAcceptsClient = true
managedCluster.Spec.LeaseDurationSeconds = 5
_, err = t.ClusterClient.ClusterV1().ManagedClusters().Update(context.TODO(),
managedCluster, metav1.UpdateOptions{})
return err
}
@@ -332,41 +328,39 @@ func (t *Tester) CreateWorkOfConfigMap(name, clusterName, configMapName, configM
Create(context.TODO(), manifestWork, metav1.CreateOptions{})
}
func (t *Tester) cleanKlusterletResources(klusterletName string) error {
func (t *Tester) cleanKlusterletResources(klusterletName, clusterName string) error {
if klusterletName == "" {
return fmt.Errorf("the klusterlet name should not be null")
}
clusterName, err := t.GetClusterNameFromKlusterlet(klusterletName)
if err != nil {
return err
}
// clean the manifest works
manifestWorks, err := t.WorkClient.WorkV1().ManifestWorks(clusterName).
List(context.TODO(), metav1.ListOptions{})
if err != nil {
return err
}
for _, work := range manifestWorks.Items {
// ignore if failed to delete
_ = t.WorkClient.WorkV1().ManifestWorks(work.Namespace).
Delete(context.TODO(), work.Name, metav1.DeleteOptions{})
}
// clean the klusterlets
err = t.OperatorClient.OperatorV1().Klusterlets().Delete(context.TODO(), klusterletName, metav1.DeleteOptions{})
err := t.OperatorClient.OperatorV1().Klusterlets().Delete(context.TODO(), klusterletName, metav1.DeleteOptions{})
if err != nil {
return err
}
gomega.Eventually(func() bool {
_, err := t.OperatorClient.OperatorV1().Klusterlets().Get(context.TODO(), klusterletName, metav1.GetOptions{})
if errors.IsNotFound(err) {
return true
}
return false
}, t.EventuallyTimeout*5, t.EventuallyInterval*5).Should(gomega.BeTrue())
// clean the managed clusters
err = t.ClusterClient.ClusterV1().ManagedClusters().Delete(context.TODO(), clusterName, metav1.DeleteOptions{})
if err != nil {
return err
}
gomega.Eventually(func() bool {
_, err := t.ClusterClient.ClusterV1().ManagedClusters().Get(context.TODO(), clusterName, metav1.GetOptions{})
if errors.IsNotFound(err) {
return true
}
return false
}, t.EventuallyTimeout*5, t.EventuallyInterval*5).Should(gomega.BeTrue())
return nil
}

View File

@@ -1,9 +1,10 @@
package e2e
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestE2E(t *testing.T) {

View File

@@ -9,20 +9,22 @@ import (
)
var _ = Describe("Create klusterlet CR", func() {
var klusterletName = ""
var klusterletName string
var clusterName string
var agentNamespace string
BeforeEach(func() {
klusterletName = fmt.Sprintf("e2e-klusterlet-%s", rand.String(6))
clusterName = fmt.Sprintf("e2e-managedcluster-%s", rand.String(6))
agentNamespace = fmt.Sprintf("e2e-agent-%s", rand.String(6))
})
AfterEach(func() {
By(fmt.Sprintf("clean klusterlet %v resources after the test case", klusterletName))
t.cleanKlusterletResources(klusterletName)
t.cleanKlusterletResources(klusterletName, clusterName)
})
It("Create klusterlet CR with managed cluster name", func() {
var clusterName = fmt.Sprintf("e2e-managedcluster-%s", rand.String(6))
var agentNamespace = fmt.Sprintf("e2e-agent-%s", rand.String(6))
By(fmt.Sprintf("create klusterlet %v with managed cluster name %v", klusterletName, clusterName))
_, err := t.CreateKlusterlet(klusterletName, clusterName, agentNamespace)
Expect(err).ToNot(HaveOccurred())
@@ -50,8 +52,8 @@ var _ = Describe("Create klusterlet CR", func() {
})
It("Created klusterlet without managed cluster name", func() {
var clusterName = ""
var agentNamespace = ""
clusterName = ""
agentNamespace = ""
var err error
By(fmt.Sprintf("create klusterlet %v without managed cluster name", klusterletName))
_, err = t.CreateKlusterlet(klusterletName, clusterName, agentNamespace)

View File

@@ -3,8 +3,10 @@ package e2e
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"
"k8s.io/apimachinery/pkg/util/rand"
)
@@ -19,7 +21,7 @@ var _ = Describe("Create klusterlet and then create a configmap by manifestwork"
AfterEach(func() {
By(fmt.Sprintf("clean klusterlet %v resources after the test case", klusterletName))
t.cleanKlusterletResources(klusterletName)
t.cleanKlusterletResources(klusterletName, clusterName)
})
It("Create configmap using manifestwork and then delete klusterlet", func() {
@@ -61,36 +63,15 @@ var _ = Describe("Create klusterlet and then create a configmap by manifestwork"
return err
}, t.EventuallyTimeout*5, t.EventuallyInterval*5).Should(Succeed())
// Manifest work and ns should not be deleted after delete klusterlet
By(fmt.Sprintf("delete klusterlet %v", klusterletName))
err = t.OperatorClient.OperatorV1().Klusterlets().Delete(context.TODO(), klusterletName, metav1.DeleteOptions{})
Expect(err).NotTo(HaveOccurred())
By(fmt.Sprintf("waiting for pods in agent namespace %v to be deleted", agentNamespace))
Eventually(func() error {
pods, err := t.KubeClient.CoreV1().Pods(agentNamespace).
List(context.TODO(), metav1.ListOptions{})
if err != nil {
return err
By(fmt.Sprintf("delete manifestwork %v/%v", clusterName, workName))
err = t.WorkClient.WorkV1().ManifestWorks(clusterName).Delete(context.Background(), workName, metav1.DeleteOptions{})
Expect(err).ToNot(HaveOccurred())
Eventually(func() bool {
_, err := t.WorkClient.WorkV1().ManifestWorks(clusterName).Get(context.Background(), workName, metav1.GetOptions{})
if errors.IsNotFound(err) {
return true
}
if len(pods.Items) != 0 {
return fmt.Errorf("the pods are not deleted in ns %v", agentNamespace)
}
return nil
}, t.EventuallyTimeout*5, t.EventuallyInterval*5).Should(Succeed())
By(fmt.Sprintf("check that managed cluster namespace %v should not be deleted", clusterName))
Eventually(func() error {
_, err := t.KubeClient.CoreV1().Namespaces().
Get(context.TODO(), clusterName, metav1.GetOptions{})
return err
}, t.EventuallyTimeout, t.EventuallyInterval).Should(Succeed())
By(fmt.Sprintf("check that manifestwork %v/%v should not be deleted", clusterName, workName))
Eventually(func() error {
_, err := t.WorkClient.WorkV1().ManifestWorks(clusterName).
Get(context.TODO(), workName, metav1.GetOptions{})
return err
}, t.EventuallyTimeout, t.EventuallyInterval).Should(Succeed())
return false
}, t.EventuallyTimeout*5, t.EventuallyInterval*5).Should(BeTrue())
})
})

View File

@@ -0,0 +1,168 @@
// Code generated by client-gen. DO NOT EDIT.
package v1
import (
"context"
"time"
scheme "github.com/open-cluster-management/api/client/work/clientset/versioned/scheme"
v1 "github.com/open-cluster-management/api/work/v1"
metav1 "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"
)
// AppliedManifestWorksGetter has a method to return a AppliedManifestWorkInterface.
// A group's client should implement this interface.
type AppliedManifestWorksGetter interface {
AppliedManifestWorks() AppliedManifestWorkInterface
}
// AppliedManifestWorkInterface has methods to work with AppliedManifestWork resources.
type AppliedManifestWorkInterface interface {
Create(ctx context.Context, appliedManifestWork *v1.AppliedManifestWork, opts metav1.CreateOptions) (*v1.AppliedManifestWork, error)
Update(ctx context.Context, appliedManifestWork *v1.AppliedManifestWork, opts metav1.UpdateOptions) (*v1.AppliedManifestWork, error)
UpdateStatus(ctx context.Context, appliedManifestWork *v1.AppliedManifestWork, opts metav1.UpdateOptions) (*v1.AppliedManifestWork, error)
Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.AppliedManifestWork, error)
List(ctx context.Context, opts metav1.ListOptions) (*v1.AppliedManifestWorkList, error)
Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.AppliedManifestWork, err error)
AppliedManifestWorkExpansion
}
// appliedManifestWorks implements AppliedManifestWorkInterface
type appliedManifestWorks struct {
client rest.Interface
}
// newAppliedManifestWorks returns a AppliedManifestWorks
func newAppliedManifestWorks(c *WorkV1Client) *appliedManifestWorks {
return &appliedManifestWorks{
client: c.RESTClient(),
}
}
// Get takes name of the appliedManifestWork, and returns the corresponding appliedManifestWork object, and an error if there is any.
func (c *appliedManifestWorks) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.AppliedManifestWork, err error) {
result = &v1.AppliedManifestWork{}
err = c.client.Get().
Resource("appliedmanifestworks").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of AppliedManifestWorks that match those selectors.
func (c *appliedManifestWorks) List(ctx context.Context, opts metav1.ListOptions) (result *v1.AppliedManifestWorkList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1.AppliedManifestWorkList{}
err = c.client.Get().
Resource("appliedmanifestworks").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested appliedManifestWorks.
func (c *appliedManifestWorks) Watch(ctx context.Context, opts metav1.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("appliedmanifestworks").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a appliedManifestWork and creates it. Returns the server's representation of the appliedManifestWork, and an error, if there is any.
func (c *appliedManifestWorks) Create(ctx context.Context, appliedManifestWork *v1.AppliedManifestWork, opts metav1.CreateOptions) (result *v1.AppliedManifestWork, err error) {
result = &v1.AppliedManifestWork{}
err = c.client.Post().
Resource("appliedmanifestworks").
VersionedParams(&opts, scheme.ParameterCodec).
Body(appliedManifestWork).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a appliedManifestWork and updates it. Returns the server's representation of the appliedManifestWork, and an error, if there is any.
func (c *appliedManifestWorks) Update(ctx context.Context, appliedManifestWork *v1.AppliedManifestWork, opts metav1.UpdateOptions) (result *v1.AppliedManifestWork, err error) {
result = &v1.AppliedManifestWork{}
err = c.client.Put().
Resource("appliedmanifestworks").
Name(appliedManifestWork.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(appliedManifestWork).
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 *appliedManifestWorks) UpdateStatus(ctx context.Context, appliedManifestWork *v1.AppliedManifestWork, opts metav1.UpdateOptions) (result *v1.AppliedManifestWork, err error) {
result = &v1.AppliedManifestWork{}
err = c.client.Put().
Resource("appliedmanifestworks").
Name(appliedManifestWork.Name).
SubResource("status").
VersionedParams(&opts, scheme.ParameterCodec).
Body(appliedManifestWork).
Do(ctx).
Into(result)
return
}
// Delete takes name of the appliedManifestWork and deletes it. Returns an error if one occurs.
func (c *appliedManifestWorks) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
return c.client.Delete().
Resource("appliedmanifestworks").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *appliedManifestWorks) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Resource("appliedmanifestworks").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched appliedManifestWork.
func (c *appliedManifestWorks) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.AppliedManifestWork, err error) {
result = &v1.AppliedManifestWork{}
err = c.client.Patch(pt).
Resource("appliedmanifestworks").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}

View File

@@ -2,4 +2,6 @@
package v1
type AppliedManifestWorkExpansion interface{}
type ManifestWorkExpansion interface{}

View File

@@ -10,6 +10,7 @@ import (
type WorkV1Interface interface {
RESTClient() rest.Interface
AppliedManifestWorksGetter
ManifestWorksGetter
}
@@ -18,6 +19,10 @@ type WorkV1Client struct {
restClient rest.Interface
}
func (c *WorkV1Client) AppliedManifestWorks() AppliedManifestWorkInterface {
return newAppliedManifestWorks(c)
}
func (c *WorkV1Client) ManifestWorks(namespace string) ManifestWorkInterface {
return newManifestWorks(c, namespace)
}

View File

@@ -59,45 +59,6 @@ spec:
description: Status represents the current status of work
type: object
properties:
appliedResources:
description: AppliedResources represents a list of resources defined
within the manifestwork that are applied. Only resources with valid
GroupVersionResource, namespace, and name are suitable. An item in
this slice is deleted when there is no mapped manifest in manifestwork.Spec
or by finalizer. The resource relating to the item will also be removed
from managed cluster. The deleted resource may still be present until
the finalizers for that resource are finished. However, the resource
will not be undeleted, so it can be removed from this list and eventual
consistency is preserved.
type: array
items:
description: AppliedManifestResourceMeta represents the gvr, name
and namespace of a resource. Since these resources have been created,
they must have valid group, version, resource, namespace, and name.
type: object
properties:
group:
description: Group is the API Group of the kubernetes resource
type: string
name:
description: Name is the name of the kubernetes resource
type: string
namespace:
description: Name is the namespace of the kubernetes resource,
empty string indicates it is a cluster scoped resource.
type: string
resource:
description: Resource is the resource name of the kubernetes resource
type: string
uid:
description: UID is set on successful deletion of the kubernetes
resource by controller. The resource might be still visible
on the managed cluster after this field is set. It is not directly
settable by a client.
type: string
version:
description: Version is the version of the kubernetes resource
type: string
conditions:
description: 'Conditions contains the different condition statuses for
this work. Valid condition types are: 1. Applied represents workload

View File

@@ -0,0 +1,105 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
creationTimestamp: null
name: appliedmanifestworks.work.open-cluster-management.io
spec:
group: work.open-cluster-management.io
names:
kind: AppliedManifestWork
listKind: AppliedManifestWorkList
plural: appliedmanifestworks
singular: appliedmanifestwork
scope: "Cluster"
preserveUnknownFields: false
subresources:
status: {}
validation:
openAPIV3Schema:
description: AppliedManifestWork represents an applied manifestwork on managed
cluster. It is placed on managed cluster. An AppliedManifestWork links to
a manifestwork on a hub recording resources deployed in the managed cluster.
When the agent is removed from managed cluster, cluster-admin on managed cluster
can delete appliedmanifestwork to remove resources deployed by the agent.
The name of the appliedmanifestwork must be in the format of {hash of hub's
first kube-apiserver url}-{manifestwork name}
type: object
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: Spec represents the desired configuration of AppliedManifestWork
type: object
properties:
hubHash:
description: HubHash represents the hash of the first hub kube apiserver
to identify which hub this AppliedManifestWork links to.
type: string
manifestWorkName:
description: ManifestWorkName represents the name of the related manifestwork
on hub.
type: string
status:
description: Status represents the current status of AppliedManifestWork
type: object
properties:
appliedResources:
description: AppliedResources represents a list of resources defined
within the manifestwork that are applied. Only resources with valid
GroupVersionResource, namespace, and name are suitable. An item in
this slice is deleted when there is no mapped manifest in manifestwork.Spec
or by finalizer. The resource relating to the item will also be removed
from managed cluster. The deleted resource may still be present until
the finalizers for that resource are finished. However, the resource
will not be undeleted, so it can be removed from this list and eventual
consistency is preserved.
type: array
items:
description: AppliedManifestResourceMeta represents the gvr, name
and namespace of a resource. Since these resources have been created,
they must have valid group, version, resource, namespace, and name.
type: object
properties:
group:
description: Group is the API Group of the kubernetes resource
type: string
name:
description: Name is the name of the kubernetes resource
type: string
namespace:
description: Name is the namespace of the kubernetes resource,
empty string indicates it is a cluster scoped resource.
type: string
resource:
description: Resource is the resource name of the kubernetes resource
type: string
uid:
description: UID is set on successful deletion of the kubernetes
resource by controller. The resource might be still visible
on the managed cluster after this field is set. It is not directly
settable by a client.
type: string
version:
description: Version is the version of the kubernetes resource
type: string
version: v1
versions:
- name: v1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -32,6 +32,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(GroupVersion,
&ManifestWork{},
&ManifestWorkList{},
&AppliedManifestWork{},
&AppliedManifestWorkList{},
)
metav1.AddToGroupVersion(scheme, GroupVersion)
return nil

View File

@@ -146,15 +146,6 @@ type ManifestWorkStatus struct {
// managed cluster. The Klusterlet agent on managed cluster syncs the condition from managed to the hub.
// +optional
ResourceStatus ManifestResourceStatus `json:"resourceStatus,omitempty"`
// AppliedResources represents a list of resources defined within the manifestwork that are applied.
// Only resources with valid GroupVersionResource, namespace, and name are suitable.
// An item in this slice is deleted when there is no mapped manifest in manifestwork.Spec or by finalizer.
// The resource relating to the item will also be removed from managed cluster.
// The deleted resource may still be present until the finalizers for that resource are finished.
// However, the resource will not be undeleted, so it can be removed from this list and eventual consistency is preserved.
// +optional
AppliedResources []AppliedManifestResourceMeta `json:"appliedResources,omitempty"`
}
// ManifestResourceStatus represents the status of each resource in manifest work deployed on
@@ -231,3 +222,65 @@ type ManifestWorkList struct {
// Items is a list of manifestworks.
Items []ManifestWork `json:"items"`
}
// +genclient
// +genclient:nonNamespaced
// +kubebuilder:subresource:status
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// AppliedManifestWork represents an applied manifestwork on managed cluster. It is placed
// on managed cluster. An AppliedManifestWork links to a manifestwork on a hub recording resources
// deployed in the managed cluster.
// When the agent is removed from managed cluster, cluster-admin on managed cluster
// can delete appliedmanifestwork to remove resources deployed by the agent.
// The name of the appliedmanifestwork must be in the format of
// {hash of hub's first kube-apiserver url}-{manifestwork name}
type AppliedManifestWork struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Spec represents the desired configuration of AppliedManifestWork
Spec AppliedManifestWorkSpec `json:"spec,omitempty"`
// Status represents the current status of AppliedManifestWork
// +optional
Status AppliedManifestWorkStatus `json:"status,omitempty"`
}
// AppliedManifestWorkSpec represents the desired configuration of AppliedManifestWork
type AppliedManifestWorkSpec struct {
// HubHash represents the hash of the first hub kube apiserver to identify which hub
// this AppliedManifestWork links to.
// +required
HubHash string `json:"hubHash"`
// ManifestWorkName represents the name of the related manifestwork on hub.
// +required
ManifestWorkName string `json:"manifestWorkName"`
}
// AppliedManifestWorkStatus represents the current status of AppliedManifestWork
type AppliedManifestWorkStatus struct {
// AppliedResources represents a list of resources defined within the manifestwork that are applied.
// Only resources with valid GroupVersionResource, namespace, and name are suitable.
// An item in this slice is deleted when there is no mapped manifest in manifestwork.Spec or by finalizer.
// The resource relating to the item will also be removed from managed cluster.
// The deleted resource may still be present until the finalizers for that resource are finished.
// However, the resource will not be undeleted, so it can be removed from this list and eventual consistency is preserved.
// +optional
AppliedResources []AppliedManifestResourceMeta `json:"appliedResources,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// AppliedManifestWorkList is a collection of appliedmanifestworks.
type AppliedManifestWorkList struct {
metav1.TypeMeta `json:",inline"`
// Standard list metadata.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
// +optional
metav1.ListMeta `json:"metadata,omitempty"`
// Items is a list of appliedmanifestworks.
Items []AppliedManifestWork `json:"items"`
}

View File

@@ -24,6 +24,104 @@ func (in *AppliedManifestResourceMeta) DeepCopy() *AppliedManifestResourceMeta {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppliedManifestWork) DeepCopyInto(out *AppliedManifestWork) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppliedManifestWork.
func (in *AppliedManifestWork) DeepCopy() *AppliedManifestWork {
if in == nil {
return nil
}
out := new(AppliedManifestWork)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AppliedManifestWork) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppliedManifestWorkList) DeepCopyInto(out *AppliedManifestWorkList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]AppliedManifestWork, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppliedManifestWorkList.
func (in *AppliedManifestWorkList) DeepCopy() *AppliedManifestWorkList {
if in == nil {
return nil
}
out := new(AppliedManifestWorkList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AppliedManifestWorkList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppliedManifestWorkSpec) DeepCopyInto(out *AppliedManifestWorkSpec) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppliedManifestWorkSpec.
func (in *AppliedManifestWorkSpec) DeepCopy() *AppliedManifestWorkSpec {
if in == nil {
return nil
}
out := new(AppliedManifestWorkSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppliedManifestWorkStatus) DeepCopyInto(out *AppliedManifestWorkStatus) {
*out = *in
if in.AppliedResources != nil {
in, out := &in.AppliedResources, &out.AppliedResources
*out = make([]AppliedManifestResourceMeta, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppliedManifestWorkStatus.
func (in *AppliedManifestWorkStatus) DeepCopy() *AppliedManifestWorkStatus {
if in == nil {
return nil
}
out := new(AppliedManifestWorkStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Manifest) DeepCopyInto(out *Manifest) {
*out = *in
@@ -193,11 +291,6 @@ func (in *ManifestWorkStatus) DeepCopyInto(out *ManifestWorkStatus) {
}
}
in.ResourceStatus.DeepCopyInto(&out.ResourceStatus)
if in.AppliedResources != nil {
in, out := &in.AppliedResources, &out.AppliedResources
*out = make([]AppliedManifestResourceMeta, len(*in))
copy(*out, *in)
}
return
}

View File

@@ -25,6 +25,45 @@ func (AppliedManifestResourceMeta) SwaggerDoc() map[string]string {
return map_AppliedManifestResourceMeta
}
var map_AppliedManifestWork = map[string]string{
"": "AppliedManifestWork represents an applied manifestwork on managed cluster. It is placed on managed cluster. An AppliedManifestWork links to a manifestwork on a hub recording resources deployed in the managed cluster. When the agent is removed from managed cluster, cluster-admin on managed cluster can delete appliedmanifestwork to remove resources deployed by the agent. The name of the appliedmanifestwork must be in the format of {hash of hub's first kube-apiserver url}-{manifestwork name}",
"spec": "Spec represents the desired configuration of AppliedManifestWork",
"status": "Status represents the current status of AppliedManifestWork",
}
func (AppliedManifestWork) SwaggerDoc() map[string]string {
return map_AppliedManifestWork
}
var map_AppliedManifestWorkList = map[string]string{
"": "AppliedManifestWorkList is a collection of appliedmanifestworks.",
"metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"items": "Items is a list of appliedmanifestworks.",
}
func (AppliedManifestWorkList) SwaggerDoc() map[string]string {
return map_AppliedManifestWorkList
}
var map_AppliedManifestWorkSpec = map[string]string{
"": "AppliedManifestWorkSpec represents the desired configuration of AppliedManifestWork",
"hubHash": "HubHash represents the hash of the first hub kube apiserver to identify which hub this AppliedManifestWork links to.",
"manifestWorkName": "ManifestWorkName represents the name of the related manifestwork on hub.",
}
func (AppliedManifestWorkSpec) SwaggerDoc() map[string]string {
return map_AppliedManifestWorkSpec
}
var map_AppliedManifestWorkStatus = map[string]string{
"": "AppliedManifestWorkStatus represents the current status of AppliedManifestWork",
"appliedResources": "AppliedResources represents a list of resources defined within the manifestwork that are applied. Only resources with valid GroupVersionResource, namespace, and name are suitable. An item in this slice is deleted when there is no mapped manifest in manifestwork.Spec or by finalizer. The resource relating to the item will also be removed from managed cluster. The deleted resource may still be present until the finalizers for that resource are finished. However, the resource will not be undeleted, so it can be removed from this list and eventual consistency is preserved.",
}
func (AppliedManifestWorkStatus) SwaggerDoc() map[string]string {
return map_AppliedManifestWorkStatus
}
var map_Manifest = map[string]string{
"": "Manifest represents a resource to be deployed on managed cluster",
}
@@ -97,10 +136,9 @@ func (ManifestWorkSpec) SwaggerDoc() map[string]string {
}
var map_ManifestWorkStatus = map[string]string{
"": "ManifestWorkStatus represents the current status of managed cluster ManifestWork",
"conditions": "Conditions contains the different condition statuses for this work. Valid condition types are: 1. Applied represents workload in ManifestWork is applied successfully on managed cluster. 2. Progressing represents workload in ManifestWork is being applied on managed cluster. 3. Available represents workload in ManifestWork exists on the managed cluster. 4. Degraded represents the current state of workload does not match the desired state for a certain period.",
"resourceStatus": "ResourceStatus represents the status of each resource in manifestwork deployed on managed cluster. The Klusterlet agent on managed cluster syncs the condition from managed to the hub.",
"appliedResources": "AppliedResources represents a list of resources defined within the manifestwork that are applied. Only resources with valid GroupVersionResource, namespace, and name are suitable. An item in this slice is deleted when there is no mapped manifest in manifestwork.Spec or by finalizer. The resource relating to the item will also be removed from managed cluster. The deleted resource may still be present until the finalizers for that resource are finished. However, the resource will not be undeleted, so it can be removed from this list and eventual consistency is preserved.",
"": "ManifestWorkStatus represents the current status of managed cluster ManifestWork",
"conditions": "Conditions contains the different condition statuses for this work. Valid condition types are: 1. Applied represents workload in ManifestWork is applied successfully on managed cluster. 2. Progressing represents workload in ManifestWork is being applied on managed cluster. 3. Available represents workload in ManifestWork exists on the managed cluster. 4. Degraded represents the current state of workload does not match the desired state for a certain period.",
"resourceStatus": "ResourceStatus represents the status of each resource in manifestwork deployed on managed cluster. The Klusterlet agent on managed cluster syncs the condition from managed to the hub.",
}
func (ManifestWorkStatus) SwaggerDoc() map[string]string {

2
vendor/modules.txt vendored
View File

@@ -133,7 +133,7 @@ github.com/onsi/gomega/matchers/support/goraph/edge
github.com/onsi/gomega/matchers/support/goraph/node
github.com/onsi/gomega/matchers/support/goraph/util
github.com/onsi/gomega/types
# github.com/open-cluster-management/api v0.0.0-20200629211334-8be047b65c52
# github.com/open-cluster-management/api v0.0.0-20200715201722-3c3c076bf062
github.com/open-cluster-management/api/client/cluster/clientset/versioned
github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme
github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1