Merge pull request #118 from elgnay/upgrade-clustermanager-crd

upgrade ClusterManager crd to support placement
This commit is contained in:
OpenShift Merge Robot
2021-05-11 23:48:47 -04:00
committed by GitHub
23 changed files with 1351 additions and 11 deletions
@@ -37,14 +37,21 @@ spec:
that govern registration and work distribution for attached Klusterlets.
type: object
properties:
placementImagePullSpec:
description: PlacementImagePullSpec represents the desired image configuration
of placement controller/webhook installed on hub.
type: string
default: quay.io/open-cluster-management/placement
registrationImagePullSpec:
description: RegistrationImagePullSpec represents the desired image
of registration controller/webhook installed on hub.
type: string
default: quay.io/open-cluster-management/registration
workImagePullSpec:
description: WorkImagePullSpec represents the desired image configuration
of work controller/webhook installed on hub.
type: string
default: quay.io/open-cluster-management/work
status:
description: Status represents the current status of controllers that
govern the lifecycle of managed clusters.
@@ -28,10 +28,16 @@ spec:
spec:
description: Spec represents a desired deployment configuration of controllers that govern registration and work distribution for attached Klusterlets.
properties:
placementImagePullSpec:
default: quay.io/open-cluster-management/placement
description: PlacementImagePullSpec represents the desired image configuration of placement controller/webhook installed on hub.
type: string
registrationImagePullSpec:
default: quay.io/open-cluster-management/registration
description: RegistrationImagePullSpec represents the desired image of registration controller/webhook installed on hub.
type: string
workImagePullSpec:
default: quay.io/open-cluster-management/work
description: WorkImagePullSpec represents the desired image configuration of work controller/webhook installed on hub.
type: string
type: object
+1 -1
View File
@@ -9,7 +9,7 @@ require (
github.com/go-bindata/go-bindata v3.1.2+incompatible
github.com/onsi/ginkgo v1.14.0
github.com/onsi/gomega v1.10.1
github.com/open-cluster-management/api v0.0.0-20210409125704-06f2aec1a73f
github.com/open-cluster-management/api v0.0.0-20210511122802-f38973154cbd
github.com/openshift/api v0.0.0-20210331193751-3acddb19d360
github.com/openshift/build-machinery-go v0.0.0-20210209125900-0da259a2c359
github.com/openshift/client-go v0.0.0-20210331195552-cf6c2669e01f
+2 -2
View File
@@ -418,8 +418,8 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/open-cluster-management/api v0.0.0-20210409125704-06f2aec1a73f h1:s6z3k0jV0ccoYDPJWMSqVNevO1UoQLYb8f7dYFALSNk=
github.com/open-cluster-management/api v0.0.0-20210409125704-06f2aec1a73f/go.mod h1:ot+A1DWq+v1IV+e1S7nhIteYAmNByFgtazvzpoeAfRQ=
github.com/open-cluster-management/api v0.0.0-20210511122802-f38973154cbd h1:/cigzPZOt3UYfDv5Nc7jvc1ydZDXESmi1/2P60HR3kc=
github.com/open-cluster-management/api v0.0.0-20210511122802-f38973154cbd/go.mod h1:ot+A1DWq+v1IV+e1S7nhIteYAmNByFgtazvzpoeAfRQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/openshift/api v0.0.0-20210331162552-3e31249e6a55/go.mod h1:dZ4kytOo3svxJHNYd0J55hwe/6IQG5gAUHUE0F3Jkio=
@@ -19,7 +19,8 @@ spec:
claims ClusterClaims with well known names include, 1. id.k8s.io, it contains
a unique identifier for the cluster. 2. clusterset.k8s.io, it contains
an identifier that relates the cluster to the ClusterSet in which it
belongs.
belongs. ClusterClaims created on a managed cluster will be collected and
saved into the status of the corresponding ManagedCluster on hub.
type: object
properties:
apiVersion:
@@ -17,6 +17,8 @@ spec:
claims ClusterClaims with well known names include, 1. id.k8s.io, it contains
a unique identifier for the cluster. 2. clusterset.k8s.io, it contains an
identifier that relates the cluster to the ClusterSet in which it belongs.
ClusterClaims created on a managed cluster will be collected and saved into
the status of the corresponding ManagedCluster on hub.
type: object
properties:
apiVersion:
+4 -1
View File
@@ -211,7 +211,8 @@ spec:
claims ClusterClaims with well known names include, 1. id.k8s.io, it contains
a unique identifier for the cluster. 2. clusterset.k8s.io, it contains
an identifier that relates the cluster to the ClusterSet in which it
belongs.
belongs. ClusterClaims created on a managed cluster will be collected and
saved into the status of the corresponding ManagedCluster on hub.
type: object
properties:
apiVersion:
@@ -402,6 +403,8 @@ spec:
claims ClusterClaims with well known names include, 1. id.k8s.io, it contains
a unique identifier for the cluster. 2. clusterset.k8s.io, it contains an
identifier that relates the cluster to the ClusterSet in which it belongs.
ClusterClaims created on a managed cluster will be collected and saved into
the status of the corresponding ManagedCluster on hub.
type: object
properties:
apiVersion:
@@ -13,6 +13,8 @@ type ClusterV1alpha1Interface interface {
ClusterClaimsGetter
ManagedClusterSetsGetter
ManagedClusterSetBindingsGetter
PlacementsGetter
PlacementDecisionsGetter
}
// ClusterV1alpha1Client is used to interact with features provided by the cluster.open-cluster-management.io group.
@@ -32,6 +34,14 @@ func (c *ClusterV1alpha1Client) ManagedClusterSetBindings(namespace string) Mana
return newManagedClusterSetBindings(c, namespace)
}
func (c *ClusterV1alpha1Client) Placements(namespace string) PlacementInterface {
return newPlacements(c, namespace)
}
func (c *ClusterV1alpha1Client) PlacementDecisions(namespace string) PlacementDecisionInterface {
return newPlacementDecisions(c, namespace)
}
// NewForConfig creates a new ClusterV1alpha1Client for the given config.
func NewForConfig(c *rest.Config) (*ClusterV1alpha1Client, error) {
config := *c
@@ -7,3 +7,7 @@ type ClusterClaimExpansion interface{}
type ManagedClusterSetExpansion interface{}
type ManagedClusterSetBindingExpansion interface{}
type PlacementExpansion interface{}
type PlacementDecisionExpansion interface{}
@@ -0,0 +1,179 @@
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
"time"
scheme "github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme"
v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1"
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"
)
// PlacementsGetter has a method to return a PlacementInterface.
// A group's client should implement this interface.
type PlacementsGetter interface {
Placements(namespace string) PlacementInterface
}
// PlacementInterface has methods to work with Placement resources.
type PlacementInterface interface {
Create(ctx context.Context, placement *v1alpha1.Placement, opts v1.CreateOptions) (*v1alpha1.Placement, error)
Update(ctx context.Context, placement *v1alpha1.Placement, opts v1.UpdateOptions) (*v1alpha1.Placement, error)
UpdateStatus(ctx context.Context, placement *v1alpha1.Placement, opts v1.UpdateOptions) (*v1alpha1.Placement, 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) (*v1alpha1.Placement, error)
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.PlacementList, 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 *v1alpha1.Placement, err error)
PlacementExpansion
}
// placements implements PlacementInterface
type placements struct {
client rest.Interface
ns string
}
// newPlacements returns a Placements
func newPlacements(c *ClusterV1alpha1Client, namespace string) *placements {
return &placements{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the placement, and returns the corresponding placement object, and an error if there is any.
func (c *placements) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.Placement, err error) {
result = &v1alpha1.Placement{}
err = c.client.Get().
Namespace(c.ns).
Resource("placements").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of Placements that match those selectors.
func (c *placements) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PlacementList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha1.PlacementList{}
err = c.client.Get().
Namespace(c.ns).
Resource("placements").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested placements.
func (c *placements) 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().
Namespace(c.ns).
Resource("placements").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a placement and creates it. Returns the server's representation of the placement, and an error, if there is any.
func (c *placements) Create(ctx context.Context, placement *v1alpha1.Placement, opts v1.CreateOptions) (result *v1alpha1.Placement, err error) {
result = &v1alpha1.Placement{}
err = c.client.Post().
Namespace(c.ns).
Resource("placements").
VersionedParams(&opts, scheme.ParameterCodec).
Body(placement).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a placement and updates it. Returns the server's representation of the placement, and an error, if there is any.
func (c *placements) Update(ctx context.Context, placement *v1alpha1.Placement, opts v1.UpdateOptions) (result *v1alpha1.Placement, err error) {
result = &v1alpha1.Placement{}
err = c.client.Put().
Namespace(c.ns).
Resource("placements").
Name(placement.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(placement).
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 *placements) UpdateStatus(ctx context.Context, placement *v1alpha1.Placement, opts v1.UpdateOptions) (result *v1alpha1.Placement, err error) {
result = &v1alpha1.Placement{}
err = c.client.Put().
Namespace(c.ns).
Resource("placements").
Name(placement.Name).
SubResource("status").
VersionedParams(&opts, scheme.ParameterCodec).
Body(placement).
Do(ctx).
Into(result)
return
}
// Delete takes name of the placement and deletes it. Returns an error if one occurs.
func (c *placements) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("placements").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *placements) 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().
Namespace(c.ns).
Resource("placements").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched placement.
func (c *placements) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.Placement, err error) {
result = &v1alpha1.Placement{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("placements").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}
@@ -0,0 +1,179 @@
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
"time"
scheme "github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme"
v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1"
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"
)
// PlacementDecisionsGetter has a method to return a PlacementDecisionInterface.
// A group's client should implement this interface.
type PlacementDecisionsGetter interface {
PlacementDecisions(namespace string) PlacementDecisionInterface
}
// PlacementDecisionInterface has methods to work with PlacementDecision resources.
type PlacementDecisionInterface interface {
Create(ctx context.Context, placementDecision *v1alpha1.PlacementDecision, opts v1.CreateOptions) (*v1alpha1.PlacementDecision, error)
Update(ctx context.Context, placementDecision *v1alpha1.PlacementDecision, opts v1.UpdateOptions) (*v1alpha1.PlacementDecision, error)
UpdateStatus(ctx context.Context, placementDecision *v1alpha1.PlacementDecision, opts v1.UpdateOptions) (*v1alpha1.PlacementDecision, 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) (*v1alpha1.PlacementDecision, error)
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.PlacementDecisionList, 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 *v1alpha1.PlacementDecision, err error)
PlacementDecisionExpansion
}
// placementDecisions implements PlacementDecisionInterface
type placementDecisions struct {
client rest.Interface
ns string
}
// newPlacementDecisions returns a PlacementDecisions
func newPlacementDecisions(c *ClusterV1alpha1Client, namespace string) *placementDecisions {
return &placementDecisions{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the placementDecision, and returns the corresponding placementDecision object, and an error if there is any.
func (c *placementDecisions) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PlacementDecision, err error) {
result = &v1alpha1.PlacementDecision{}
err = c.client.Get().
Namespace(c.ns).
Resource("placementdecisions").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of PlacementDecisions that match those selectors.
func (c *placementDecisions) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PlacementDecisionList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha1.PlacementDecisionList{}
err = c.client.Get().
Namespace(c.ns).
Resource("placementdecisions").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested placementDecisions.
func (c *placementDecisions) 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().
Namespace(c.ns).
Resource("placementdecisions").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a placementDecision and creates it. Returns the server's representation of the placementDecision, and an error, if there is any.
func (c *placementDecisions) Create(ctx context.Context, placementDecision *v1alpha1.PlacementDecision, opts v1.CreateOptions) (result *v1alpha1.PlacementDecision, err error) {
result = &v1alpha1.PlacementDecision{}
err = c.client.Post().
Namespace(c.ns).
Resource("placementdecisions").
VersionedParams(&opts, scheme.ParameterCodec).
Body(placementDecision).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a placementDecision and updates it. Returns the server's representation of the placementDecision, and an error, if there is any.
func (c *placementDecisions) Update(ctx context.Context, placementDecision *v1alpha1.PlacementDecision, opts v1.UpdateOptions) (result *v1alpha1.PlacementDecision, err error) {
result = &v1alpha1.PlacementDecision{}
err = c.client.Put().
Namespace(c.ns).
Resource("placementdecisions").
Name(placementDecision.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(placementDecision).
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 *placementDecisions) UpdateStatus(ctx context.Context, placementDecision *v1alpha1.PlacementDecision, opts v1.UpdateOptions) (result *v1alpha1.PlacementDecision, err error) {
result = &v1alpha1.PlacementDecision{}
err = c.client.Put().
Namespace(c.ns).
Resource("placementdecisions").
Name(placementDecision.Name).
SubResource("status").
VersionedParams(&opts, scheme.ParameterCodec).
Body(placementDecision).
Do(ctx).
Into(result)
return
}
// Delete takes name of the placementDecision and deletes it. Returns an error if one occurs.
func (c *placementDecisions) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("placementdecisions").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *placementDecisions) 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().
Namespace(c.ns).
Resource("placementdecisions").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched placementDecision.
func (c *placementDecisions) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PlacementDecision, err error) {
result = &v1alpha1.PlacementDecision{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("placementdecisions").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}
@@ -19,7 +19,8 @@ spec:
claims ClusterClaims with well known names include, 1. id.k8s.io, it contains
a unique identifier for the cluster. 2. clusterset.k8s.io, it contains
an identifier that relates the cluster to the ClusterSet in which it
belongs.
belongs. ClusterClaims created on a managed cluster will be collected and
saved into the status of the corresponding ManagedCluster on hub.
type: object
properties:
apiVersion:
@@ -0,0 +1,274 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: placements.cluster.open-cluster-management.io
spec:
group: cluster.open-cluster-management.io
names:
kind: Placement
listKind: PlacementList
plural: placements
singular: placement
scope: Namespaced
preserveUnknownFields: false
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: "Placement defines a rule to select a set of ManagedClusters
from the ManagedClusterSets bound to the placement namespace. \n Here is
how the placement policy combines with other selection methods to determine
a matching list of ManagedClusters: 1) Kubernetes clusters are registered
with hub as cluster-scoped ManagedClusters; 2) ManagedClusters are organized
into cluster-scoped ManagedClusterSets; 3) ManagedClusterSets are bound
to workload namespaces; 4) Namespace-scoped Placements specify a slice of
ManagedClusterSets which select a working set of potential ManagedClusters;
5) Then Placements subselect from that working set using label/claim selection.
\n No ManagedCluster will be selected if no ManagedClusterSet is bound to
the placement namespace. User is able to bind a ManagedClusterSet to a namespace
by creating a ManagedClusterSetBinding in that namespace if they have a
RBAC rule to CREATE on the virtual subresource of `managedclustersets/bind`.
\n A slice of PlacementDecisions with label cluster.open-cluster-management.io/placement={placement
name} will be created to represent the ManagedClusters selected by this
placement. \n If a ManagedCluster is selected and added into the PlacementDecisions,
other components may apply workload on it; once it is removed from the PlacementDecisions,
the workload applied on this ManagedCluster should be evicted accordingly."
type: object
required:
- spec
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 defines the attributes of Placement.
type: object
properties:
clusterSets:
description: ClusterSets represent the ManagedClusterSets from which
the ManagedClusters are selected. If the slice is empty, ManagedClusters
will be selected from the ManagedClusterSets bound to the placement
namespace, otherwise ManagedClusters will be selected from the intersection
of this slice and the ManagedClusterSets bound to the placement
namespace.
type: array
items:
type: string
numberOfClusters:
description: NumberOfClusters represents the desired number of ManagedClusters
to be selected which meet the placement requirements. 1) If not
specified, all ManagedClusters which meet the placement requirements
(including ClusterSets, and Predicates) will be selected; 2)
Otherwise if the nubmer of ManagedClusters meet the placement requirements
is larger than NumberOfClusters, a random subset with desired
number of ManagedClusters will be selected; 3) If the nubmer of
ManagedClusters meet the placement requirements is equal to NumberOfClusters, all
of them will be selected; 4) If the nubmer of ManagedClusters meet
the placement requirements is less than NumberOfClusters, all
of them will be selected, and the status of condition `PlacementConditionSatisfied`
will be set to false;
type: integer
format: int32
predicates:
description: Predicates represent a slice of predicates to select
ManagedClusters. The predicates are ORed.
type: array
items:
description: ClusterPredicate represents a predicate to select ManagedClusters.
type: object
properties:
requiredClusterSelector:
description: RequiredClusterSelector represents a selector of
ManagedClusters by label and claim. If specified, 1) Any ManagedCluster,
which does not match the selector, should not be selected
by this ClusterPredicate; 2) If a selected ManagedCluster
(of this ClusterPredicate) ceases to match the selector (e.g.
due to an update) of any ClusterPredicate, it will be eventually
removed from the placement decisions; 3) If a ManagedCluster
(not selected previously) starts to match the selector, it
will either be selected or at least has a chance to be
selected (when NumberOfClusters is specified);
type: object
properties:
claimSelector:
description: ClaimSelector represents a selector of ManagedClusters
by clusterClaims in status
type: object
properties:
matchExpressions:
description: matchExpressions is a list of cluster claim
selector requirements. The requirements are ANDed.
type: array
items:
description: A label selector requirement is a selector
that contains values, a key, and an operator that
relates the key and values.
type: object
required:
- key
- operator
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In,
NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values.
If the operator is In or NotIn, the values array
must be non-empty. If the operator is Exists
or DoesNotExist, the values array must be empty.
This array is replaced during a strategic merge
patch.
type: array
items:
type: string
labelSelector:
description: LabelSelector represents a selector of ManagedClusters
by label
type: object
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
type: array
items:
description: A label selector requirement is a selector
that contains values, a key, and an operator that
relates the key and values.
type: object
required:
- key
- operator
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In,
NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values.
If the operator is In or NotIn, the values array
must be non-empty. If the operator is Exists
or DoesNotExist, the values array must be empty.
This array is replaced during a strategic merge
patch.
type: array
items:
type: string
matchLabels:
description: matchLabels is a map of {key,value} pairs.
A single {key,value} in the matchLabels map is equivalent
to an element of matchExpressions, whose key field
is "key", the operator is "In", and the values array
contains only "value". The requirements are ANDed.
type: object
additionalProperties:
type: string
status:
description: Status represents the current status of the Placement
type: object
properties:
conditions:
description: Conditions contains the different condition statuses
for this Placement.
type: array
items:
description: "Condition contains details for one aspect of the current
state of this API Resource. --- This struct is intended for direct
use as an array at the field path .status.conditions. For example,
type FooStatus struct{ // Represents the observations of a
foo's current state. // Known .status.conditions.type are:
\"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type
\ // +patchStrategy=merge // +listType=map // +listMapKey=type
\ Conditions []metav1.Condition `json:\"conditions,omitempty\"
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`
\n // other fields }"
type: object
required:
- lastTransitionTime
- message
- reason
- status
- type
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
type: string
format: date-time
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
type: string
maxLength: 32768
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
type: integer
format: int64
minimum: 0
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
This field may not be empty.
type: string
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
status:
description: status of the condition, one of True, False, Unknown.
type: string
enum:
- "True"
- "False"
- Unknown
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
type: string
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
numberOfSelectedClusters:
description: NumberOfSelectedClusters represents the number of selected
ManagedClusters
type: integer
format: int32
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
@@ -0,0 +1,76 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: placementdecisions.cluster.open-cluster-management.io
spec:
group: cluster.open-cluster-management.io
names:
kind: PlacementDecision
listKind: PlacementDecisionList
plural: placementdecisions
singular: placementdecision
scope: Namespaced
preserveUnknownFields: false
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: "PlacementDecision indicates a decision from a placement PlacementDecision
should has a label cluster.open-cluster-management.io/placement={placement
name} to reference a certain placement. \n If a placement has spec.numberOfClusters
specified, the total number of decisions contained in status.decisions of
PlacementDecisions should always be NumberOfClusters; otherwise, the total
number of decisions should be the number of ManagedClusters which match
the placement requirements. \n Some of the decisions might be empty when
there are no enough ManagedClusters meet the placement requirements."
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
status:
description: Status represents the current status of the PlacementDecision
type: object
required:
- decisions
properties:
decisions:
description: Decisions is a slice of decisions according to a placement
The number of decisions should not be larger than 100
type: array
items:
description: ClusterDecision represents a decision from a placement
An empty ClusterDecision indicates it is not scheduled yet.
type: object
required:
- clusterName
- reason
properties:
clusterName:
description: ClusterName is the name of the ManagedCluster.
If it is not empty, its value should be unique cross all placement
decisions for the Placement.
type: string
reason:
description: Reason represents the reason why the ManagedCluster
is selected.
type: string
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
@@ -17,6 +17,8 @@ spec:
claims ClusterClaims with well known names include, 1. id.k8s.io, it contains
a unique identifier for the cluster. 2. clusterset.k8s.io, it contains an
identifier that relates the cluster to the ClusterSet in which it belongs.
ClusterClaims created on a managed cluster will be collected and saved into
the status of the corresponding ManagedCluster on hub.
type: object
properties:
apiVersion:
@@ -36,6 +36,10 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&ManagedClusterSetBindingList{},
&ClusterClaim{},
&ClusterClaimList{},
&Placement{},
&PlacementList{},
&PlacementDecision{},
&PlacementDecisionList{},
)
metav1.AddToGroupVersion(scheme, GroupVersion)
return nil
+199
View File
@@ -115,6 +115,8 @@ type ManagedClusterSetBindingList struct {
// 1. id.k8s.io, it contains a unique identifier for the cluster.
// 2. clusterset.k8s.io, it contains an identifier that relates the cluster
// to the ClusterSet in which it belongs.
// ClusterClaims created on a managed cluster will be collected and saved into
// the status of the corresponding ManagedCluster on hub.
type ClusterClaim struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
@@ -157,3 +159,200 @@ var ReservedClusterClaimNames = [...]string{
// product name, like OpenShift, Anthos, EKS and GKE
"product.open-cluster-management.io",
}
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:resource:scope="Namespaced"
// +kubebuilder:subresource:status
// Placement defines a rule to select a set of ManagedClusters from the ManagedClusterSets bound
// to the placement namespace.
//
// Here is how the placement policy combines with other selection methods to determine a matching
// list of ManagedClusters:
// 1) Kubernetes clusters are registered with hub as cluster-scoped ManagedClusters;
// 2) ManagedClusters are organized into cluster-scoped ManagedClusterSets;
// 3) ManagedClusterSets are bound to workload namespaces;
// 4) Namespace-scoped Placements specify a slice of ManagedClusterSets which select a working set
// of potential ManagedClusters;
// 5) Then Placements subselect from that working set using label/claim selection.
//
// No ManagedCluster will be selected if no ManagedClusterSet is bound to the placement
// namespace. User is able to bind a ManagedClusterSet to a namespace by creating a
// ManagedClusterSetBinding in that namespace if they have a RBAC rule to CREATE on the virtual
// subresource of `managedclustersets/bind`.
//
// A slice of PlacementDecisions with label cluster.open-cluster-management.io/placement={placement name}
// will be created to represent the ManagedClusters selected by this placement.
//
// If a ManagedCluster is selected and added into the PlacementDecisions, other components may
// apply workload on it; once it is removed from the PlacementDecisions, the workload applied on
// this ManagedCluster should be evicted accordingly.
type Placement struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Spec defines the attributes of Placement.
// +kubebuilder:validation:Required
// +required
Spec PlacementSpec `json:"spec"`
// Status represents the current status of the Placement
// +optional
Status PlacementStatus `json:"status,omitempty"`
}
// PlacementSpec defines the attributes of Placement.
// An empty PlacementSpec selects all ManagedClusters from the ManagedClusterSets bound to
// the placement namespace. The containing fields are ANDed.
type PlacementSpec struct {
// ClusterSets represent the ManagedClusterSets from which the ManagedClusters are selected.
// If the slice is empty, ManagedClusters will be selected from the ManagedClusterSets bound to the placement
// namespace, otherwise ManagedClusters will be selected from the intersection of this slice and the
// ManagedClusterSets bound to the placement namespace.
// +optional
ClusterSets []string `json:"clusterSets,omitempty"`
// NumberOfClusters represents the desired number of ManagedClusters to be selected which meet the
// placement requirements.
// 1) If not specified, all ManagedClusters which meet the placement requirements (including ClusterSets,
// and Predicates) will be selected;
// 2) Otherwise if the nubmer of ManagedClusters meet the placement requirements is larger than
// NumberOfClusters, a random subset with desired number of ManagedClusters will be selected;
// 3) If the nubmer of ManagedClusters meet the placement requirements is equal to NumberOfClusters,
// all of them will be selected;
// 4) If the nubmer of ManagedClusters meet the placement requirements is less than NumberOfClusters,
// all of them will be selected, and the status of condition `PlacementConditionSatisfied` will be
// set to false;
// +optional
NumberOfClusters *int32 `json:"numberOfClusters,omitempty"`
// Predicates represent a slice of predicates to select ManagedClusters. The predicates are ORed.
// +optional
Predicates []ClusterPredicate `json:"predicates,omitempty"`
}
// ClusterPredicate represents a predicate to select ManagedClusters.
type ClusterPredicate struct {
// RequiredClusterSelector represents a selector of ManagedClusters by label and claim. If specified,
// 1) Any ManagedCluster, which does not match the selector, should not be selected by this ClusterPredicate;
// 2) If a selected ManagedCluster (of this ClusterPredicate) ceases to match the selector (e.g. due to
// an update) of any ClusterPredicate, it will be eventually removed from the placement decisions;
// 3) If a ManagedCluster (not selected previously) starts to match the selector, it will either
// be selected or at least has a chance to be selected (when NumberOfClusters is specified);
// +optional
RequiredClusterSelector ClusterSelector `json:"requiredClusterSelector,omitempty"`
}
// ClusterSelector represents the AND of the containing selectors. An empty cluster selector matches all objects.
// A null cluster selector matches no objects.
type ClusterSelector struct {
// LabelSelector represents a selector of ManagedClusters by label
// +optional
LabelSelector metav1.LabelSelector `json:"labelSelector,omitempty"`
// ClaimSelector represents a selector of ManagedClusters by clusterClaims in status
// +optional
ClaimSelector ClusterClaimSelector `json:"claimSelector,omitempty"`
}
// ClusterClaimSelector is a claim query over a set of ManagedClusters. An empty cluster claim
// selector matches all objects. A null cluster claim selector matches no objects.
type ClusterClaimSelector struct {
// matchExpressions is a list of cluster claim selector requirements. The requirements are ANDed.
// +optional
MatchExpressions []metav1.LabelSelectorRequirement `json:"matchExpressions,omitempty"`
}
type PlacementStatus struct {
// NumberOfSelectedClusters represents the number of selected ManagedClusters
// +optional
NumberOfSelectedClusters int32 `json:"numberOfSelectedClusters"`
// Conditions contains the different condition statuses for this Placement.
// +optional
Conditions []metav1.Condition `json:"conditions"`
}
const (
// PlacementConditionSatisfied means Placement requirements are satisfied.
// A placement is not satisfied only if there is empty ClusterDecision in the status.decisions
// of PlacementDecisions.
PlacementConditionSatisfied string = "PlacementSatisfied"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// PlacementList is a collection of Placements.
type PlacementList 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 Placements.
Items []Placement `json:"items"`
}
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:resource:scope="Namespaced"
// +kubebuilder:subresource:status
// PlacementDecision indicates a decision from a placement
// PlacementDecision should has a label cluster.open-cluster-management.io/placement={placement name}
// to reference a certain placement.
//
// If a placement has spec.numberOfClusters specified, the total number of decisions contained in
// status.decisions of PlacementDecisions should always be NumberOfClusters; otherwise, the total
// number of decisions should be the number of ManagedClusters which match the placement requirements.
//
// Some of the decisions might be empty when there are no enough ManagedClusters meet the placement
// requirements.
type PlacementDecision struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Status represents the current status of the PlacementDecision
// +optional
Status PlacementDecisionStatus `json:"status,omitempty"`
}
// PlacementDecisionStatus represents the current status of the PlacementDecision.
type PlacementDecisionStatus struct {
// Decisions is a slice of decisions according to a placement
// The number of decisions should not be larger than 100
// +kubebuilder:validation:Required
// +required
Decisions []ClusterDecision `json:"decisions"`
}
// ClusterDecision represents a decision from a placement
// An empty ClusterDecision indicates it is not scheduled yet.
type ClusterDecision struct {
// ClusterName is the name of the ManagedCluster. If it is not empty, its value should be unique cross all
// placement decisions for the Placement.
// +kubebuilder:validation:Required
// +required
ClusterName string `json:"clusterName"`
// Reason represents the reason why the ManagedCluster is selected.
// +kubebuilder:validation:Required
// +required
Reason string `json:"reason"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ClusterDecisionList is a collection of PlacementDecision.
type PlacementDecisionList 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 PlacementDecision.
Items []PlacementDecision `json:"items"`
}
@@ -69,6 +69,29 @@ func (in *ClusterClaimList) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterClaimSelector) DeepCopyInto(out *ClusterClaimSelector) {
*out = *in
if in.MatchExpressions != nil {
in, out := &in.MatchExpressions, &out.MatchExpressions
*out = make([]v1.LabelSelectorRequirement, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterClaimSelector.
func (in *ClusterClaimSelector) DeepCopy() *ClusterClaimSelector {
if in == nil {
return nil
}
out := new(ClusterClaimSelector)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterClaimSpec) DeepCopyInto(out *ClusterClaimSpec) {
*out = *in
@@ -85,6 +108,57 @@ func (in *ClusterClaimSpec) DeepCopy() *ClusterClaimSpec {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterDecision) DeepCopyInto(out *ClusterDecision) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterDecision.
func (in *ClusterDecision) DeepCopy() *ClusterDecision {
if in == nil {
return nil
}
out := new(ClusterDecision)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterPredicate) DeepCopyInto(out *ClusterPredicate) {
*out = *in
in.RequiredClusterSelector.DeepCopyInto(&out.RequiredClusterSelector)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPredicate.
func (in *ClusterPredicate) DeepCopy() *ClusterPredicate {
if in == nil {
return nil
}
out := new(ClusterPredicate)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterSelector) DeepCopyInto(out *ClusterSelector) {
*out = *in
in.LabelSelector.DeepCopyInto(&out.LabelSelector)
in.ClaimSelector.DeepCopyInto(&out.ClaimSelector)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSelector.
func (in *ClusterSelector) DeepCopy() *ClusterSelector {
if in == nil {
return nil
}
out := new(ClusterSelector)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManagedClusterSet) DeepCopyInto(out *ManagedClusterSet) {
*out = *in
@@ -260,3 +334,201 @@ func (in *ManagedClusterSetStatus) DeepCopy() *ManagedClusterSetStatus {
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Placement) DeepCopyInto(out *Placement) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Placement.
func (in *Placement) DeepCopy() *Placement {
if in == nil {
return nil
}
out := new(Placement)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Placement) 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 *PlacementDecision) DeepCopyInto(out *PlacementDecision) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementDecision.
func (in *PlacementDecision) DeepCopy() *PlacementDecision {
if in == nil {
return nil
}
out := new(PlacementDecision)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PlacementDecision) 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 *PlacementDecisionList) DeepCopyInto(out *PlacementDecisionList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]PlacementDecision, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementDecisionList.
func (in *PlacementDecisionList) DeepCopy() *PlacementDecisionList {
if in == nil {
return nil
}
out := new(PlacementDecisionList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PlacementDecisionList) 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 *PlacementDecisionStatus) DeepCopyInto(out *PlacementDecisionStatus) {
*out = *in
if in.Decisions != nil {
in, out := &in.Decisions, &out.Decisions
*out = make([]ClusterDecision, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementDecisionStatus.
func (in *PlacementDecisionStatus) DeepCopy() *PlacementDecisionStatus {
if in == nil {
return nil
}
out := new(PlacementDecisionStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PlacementList) DeepCopyInto(out *PlacementList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Placement, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementList.
func (in *PlacementList) DeepCopy() *PlacementList {
if in == nil {
return nil
}
out := new(PlacementList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PlacementList) 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 *PlacementSpec) DeepCopyInto(out *PlacementSpec) {
*out = *in
if in.ClusterSets != nil {
in, out := &in.ClusterSets, &out.ClusterSets
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.NumberOfClusters != nil {
in, out := &in.NumberOfClusters, &out.NumberOfClusters
*out = new(int32)
**out = **in
}
if in.Predicates != nil {
in, out := &in.Predicates, &out.Predicates
*out = make([]ClusterPredicate, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementSpec.
func (in *PlacementSpec) DeepCopy() *PlacementSpec {
if in == nil {
return nil
}
out := new(PlacementSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PlacementStatus) DeepCopyInto(out *PlacementStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]v1.Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementStatus.
func (in *PlacementStatus) DeepCopy() *PlacementStatus {
if in == nil {
return nil
}
out := new(PlacementStatus)
in.DeepCopyInto(out)
return out
}
@@ -12,7 +12,7 @@ package v1alpha1
// AUTO-GENERATED FUNCTIONS START HERE
var map_ClusterClaim = map[string]string{
"": "ClusterClaim represents cluster information that a managed cluster claims ClusterClaims with well known names include,\n 1. id.k8s.io, it contains a unique identifier for the cluster.\n 2. clusterset.k8s.io, it contains an identifier that relates the cluster\n to the ClusterSet in which it belongs.",
"": "ClusterClaim represents cluster information that a managed cluster claims ClusterClaims with well known names include,\n 1. id.k8s.io, it contains a unique identifier for the cluster.\n 2. clusterset.k8s.io, it contains an identifier that relates the cluster\n to the ClusterSet in which it belongs.\nClusterClaims created on a managed cluster will be collected and saved into the status of the corresponding ManagedCluster on hub.",
"spec": "Spec defines the attributes of the ClusterClaim.",
}
@@ -30,6 +30,15 @@ func (ClusterClaimList) SwaggerDoc() map[string]string {
return map_ClusterClaimList
}
var map_ClusterClaimSelector = map[string]string{
"": "ClusterClaimSelector is a claim query over a set of ManagedClusters. An empty cluster claim selector matches all objects. A null cluster claim selector matches no objects.",
"matchExpressions": "matchExpressions is a list of cluster claim selector requirements. The requirements are ANDed.",
}
func (ClusterClaimSelector) SwaggerDoc() map[string]string {
return map_ClusterClaimSelector
}
var map_ClusterClaimSpec = map[string]string{
"value": "Value is a claim-dependent string",
}
@@ -38,6 +47,35 @@ func (ClusterClaimSpec) SwaggerDoc() map[string]string {
return map_ClusterClaimSpec
}
var map_ClusterDecision = map[string]string{
"": "ClusterDecision represents a decision from a placement An empty ClusterDecision indicates it is not scheduled yet.",
"clusterName": "ClusterName is the name of the ManagedCluster. If it is not empty, its value should be unique cross all placement decisions for the Placement.",
"reason": "Reason represents the reason why the ManagedCluster is selected.",
}
func (ClusterDecision) SwaggerDoc() map[string]string {
return map_ClusterDecision
}
var map_ClusterPredicate = map[string]string{
"": "ClusterPredicate represents a predicate to select ManagedClusters.",
"requiredClusterSelector": "RequiredClusterSelector represents a selector of ManagedClusters by label and claim. If specified, 1) Any ManagedCluster, which does not match the selector, should not be selected by this ClusterPredicate; 2) If a selected ManagedCluster (of this ClusterPredicate) ceases to match the selector (e.g. due to\n an update) of any ClusterPredicate, it will be eventually removed from the placement decisions;\n3) If a ManagedCluster (not selected previously) starts to match the selector, it will either\n be selected or at least has a chance to be selected (when NumberOfClusters is specified);",
}
func (ClusterPredicate) SwaggerDoc() map[string]string {
return map_ClusterPredicate
}
var map_ClusterSelector = map[string]string{
"": "ClusterSelector represents the AND of the containing selectors. An empty cluster selector matches all objects. A null cluster selector matches no objects.",
"labelSelector": "LabelSelector represents a selector of ManagedClusters by label",
"claimSelector": "ClaimSelector represents a selector of ManagedClusters by clusterClaims in status",
}
func (ClusterSelector) SwaggerDoc() map[string]string {
return map_ClusterSelector
}
var map_ManagedClusterSet = map[string]string{
"": "ManagedClusterSet defines a group of ManagedClusters that user's workload can run on. A workload can be defined to deployed on a ManagedClusterSet, which mean:\n 1. The workload can run on any ManagedCluster in the ManagedClusterSet\n 2. The workload cannot run on any ManagedCluster outside the ManagedClusterSet\n 3. The service exposed by the workload can be shared in any ManagedCluster in the ManagedClusterSet\n\nIn order to assign a ManagedCluster to a certian ManagedClusterSet, add a label with name `cluster.open-cluster-management.io/clusterset` on the ManagedCluster to refers to the ManagedClusterSet. User is not allow to add/remove this label on a ManagedCluster unless they have a RBAC rule to CREATE on a virtual subresource of managedclustersets/join. In order to update this label, user must have the permission on both the old and new ManagedClusterSet.",
"spec": "Spec defines the attributes of the ManagedClusterSet",
@@ -103,4 +141,72 @@ func (ManagedClusterSetStatus) SwaggerDoc() map[string]string {
return map_ManagedClusterSetStatus
}
var map_Placement = map[string]string{
"": "Placement defines a rule to select a set of ManagedClusters from the ManagedClusterSets bound to the placement namespace.\n\nHere is how the placement policy combines with other selection methods to determine a matching list of ManagedClusters: 1) Kubernetes clusters are registered with hub as cluster-scoped ManagedClusters; 2) ManagedClusters are organized into cluster-scoped ManagedClusterSets; 3) ManagedClusterSets are bound to workload namespaces; 4) Namespace-scoped Placements specify a slice of ManagedClusterSets which select a working set\n of potential ManagedClusters;\n5) Then Placements subselect from that working set using label/claim selection.\n\nNo ManagedCluster will be selected if no ManagedClusterSet is bound to the placement namespace. User is able to bind a ManagedClusterSet to a namespace by creating a ManagedClusterSetBinding in that namespace if they have a RBAC rule to CREATE on the virtual subresource of `managedclustersets/bind`.\n\nA slice of PlacementDecisions with label cluster.open-cluster-management.io/placement={placement name} will be created to represent the ManagedClusters selected by this placement.\n\nIf a ManagedCluster is selected and added into the PlacementDecisions, other components may apply workload on it; once it is removed from the PlacementDecisions, the workload applied on this ManagedCluster should be evicted accordingly.",
"spec": "Spec defines the attributes of Placement.",
"status": "Status represents the current status of the Placement",
}
func (Placement) SwaggerDoc() map[string]string {
return map_Placement
}
var map_PlacementDecision = map[string]string{
"": "PlacementDecision indicates a decision from a placement PlacementDecision should has a label cluster.open-cluster-management.io/placement={placement name} to reference a certain placement.\n\nIf a placement has spec.numberOfClusters specified, the total number of decisions contained in status.decisions of PlacementDecisions should always be NumberOfClusters; otherwise, the total number of decisions should be the number of ManagedClusters which match the placement requirements.\n\nSome of the decisions might be empty when there are no enough ManagedClusters meet the placement requirements.",
"status": "Status represents the current status of the PlacementDecision",
}
func (PlacementDecision) SwaggerDoc() map[string]string {
return map_PlacementDecision
}
var map_PlacementDecisionList = map[string]string{
"": "ClusterDecisionList is a collection of PlacementDecision.",
"metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"items": "Items is a list of PlacementDecision.",
}
func (PlacementDecisionList) SwaggerDoc() map[string]string {
return map_PlacementDecisionList
}
var map_PlacementDecisionStatus = map[string]string{
"": "PlacementDecisionStatus represents the current status of the PlacementDecision.",
"decisions": "Decisions is a slice of decisions according to a placement The number of decisions should not be larger than 100",
}
func (PlacementDecisionStatus) SwaggerDoc() map[string]string {
return map_PlacementDecisionStatus
}
var map_PlacementList = map[string]string{
"": "PlacementList is a collection of Placements.",
"metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"items": "Items is a list of Placements.",
}
func (PlacementList) SwaggerDoc() map[string]string {
return map_PlacementList
}
var map_PlacementSpec = map[string]string{
"": "PlacementSpec defines the attributes of Placement. An empty PlacementSpec selects all ManagedClusters from the ManagedClusterSets bound to the placement namespace. The containing fields are ANDed.",
"clusterSets": "ClusterSets represent the ManagedClusterSets from which the ManagedClusters are selected. If the slice is empty, ManagedClusters will be selected from the ManagedClusterSets bound to the placement namespace, otherwise ManagedClusters will be selected from the intersection of this slice and the ManagedClusterSets bound to the placement namespace.",
"numberOfClusters": "NumberOfClusters represents the desired number of ManagedClusters to be selected which meet the placement requirements. 1) If not specified, all ManagedClusters which meet the placement requirements (including ClusterSets,\n and Predicates) will be selected;\n2) Otherwise if the nubmer of ManagedClusters meet the placement requirements is larger than\n NumberOfClusters, a random subset with desired number of ManagedClusters will be selected;\n3) If the nubmer of ManagedClusters meet the placement requirements is equal to NumberOfClusters,\n all of them will be selected;\n4) If the nubmer of ManagedClusters meet the placement requirements is less than NumberOfClusters,\n all of them will be selected, and the status of condition `PlacementConditionSatisfied` will be\n set to false;",
"predicates": "Predicates represent a slice of predicates to select ManagedClusters. The predicates are ORed.",
}
func (PlacementSpec) SwaggerDoc() map[string]string {
return map_PlacementSpec
}
var map_PlacementStatus = map[string]string{
"numberOfSelectedClusters": "NumberOfSelectedClusters represents the number of selected ManagedClusters",
"conditions": "Conditions contains the different condition statuses for this Placement.",
}
func (PlacementStatus) SwaggerDoc() map[string]string {
return map_PlacementStatus
}
// AUTO-GENERATED FUNCTIONS END HERE
@@ -37,14 +37,21 @@ spec:
that govern registration and work distribution for attached Klusterlets.
type: object
properties:
placementImagePullSpec:
description: PlacementImagePullSpec represents the desired image configuration
of placement controller/webhook installed on hub.
type: string
default: quay.io/open-cluster-management/placement
registrationImagePullSpec:
description: RegistrationImagePullSpec represents the desired image
of registration controller/webhook installed on hub.
type: string
default: quay.io/open-cluster-management/registration
workImagePullSpec:
description: WorkImagePullSpec represents the desired image configuration
of work controller/webhook installed on hub.
type: string
default: quay.io/open-cluster-management/work
status:
description: Status represents the current status of controllers that
govern the lifecycle of managed clusters.
+10 -3
View File
@@ -27,12 +27,19 @@ type ClusterManager struct {
// ClusterManagerSpec represents a desired deployment configuration of controllers that govern registration and work distribution for attached Klusterlets.
type ClusterManagerSpec struct {
// RegistrationImagePullSpec represents the desired image of registration controller/webhook installed on hub.
// +required
RegistrationImagePullSpec string `json:"registrationImagePullSpec"`
// +optional
// +kubebuilder:default=quay.io/open-cluster-management/registration
RegistrationImagePullSpec string `json:"registrationImagePullSpec,omitempty"`
// WorkImagePullSpec represents the desired image configuration of work controller/webhook installed on hub.
// +required
// +optional
// +kubebuilder:default=quay.io/open-cluster-management/work
WorkImagePullSpec string `json:"workImagePullSpec,omitempty"`
// PlacementImagePullSpec represents the desired image configuration of placement controller/webhook installed on hub.
// +optional
// +kubebuilder:default=quay.io/open-cluster-management/placement
PlacementImagePullSpec string `json:"placementImagePullSpec,omitempty"`
}
// ClusterManagerStatus represents the current status of the registration and work distribution controllers running on the hub.
@@ -35,6 +35,7 @@ var map_ClusterManagerSpec = map[string]string{
"": "ClusterManagerSpec represents a desired deployment configuration of controllers that govern registration and work distribution for attached Klusterlets.",
"registrationImagePullSpec": "RegistrationImagePullSpec represents the desired image of registration controller/webhook installed on hub.",
"workImagePullSpec": "WorkImagePullSpec represents the desired image configuration of work controller/webhook installed on hub.",
"placementImagePullSpec": "PlacementImagePullSpec represents the desired image configuration of placement controller/webhook installed on hub.",
}
func (ClusterManagerSpec) SwaggerDoc() map[string]string {
+1 -1
View File
@@ -138,7 +138,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-20210409125704-06f2aec1a73f
# github.com/open-cluster-management/api v0.0.0-20210511122802-f38973154cbd
## explicit
github.com/open-cluster-management/api/addon/v1alpha1
github.com/open-cluster-management/api/client/addon/clientset/versioned