add-default-managedclusterset-controller (#198)

Signed-off-by: ycyaoxdu <yaoyuchen0626@163.com>
This commit is contained in:
Yuchen YAO
2022-03-02 15:50:22 +08:00
committed by GitHub
parent f3b18aa211
commit 92178adbec
40 changed files with 3025 additions and 105 deletions

View File

@@ -110,6 +110,22 @@ spec:
spec:
description: Spec defines the attributes of the ManagedClusterSet
type: object
default:
clusterSelector:
selectorType: LegacyClusterSetLabel
properties:
clusterSelector:
description: ClusterSelector represents a selector of ManagedClusters
type: object
default:
selectorType: LegacyClusterSetLabel
properties:
selectorType:
description: SelectorType could only be "LegacyClusterSetLabel" now, will support more SelectorType later "LegacyClusterSetLabel" means to use label "cluster.open-cluster-management.io/clusterset:<ManagedClusterSet Name>"" to select target clusters.
type: string
default: LegacyClusterSetLabel
enum:
- LegacyClusterSetLabel
status:
description: Status represents the current status of the ManagedClusterSet
type: object

View File

@@ -61,6 +61,10 @@ spec:
crdName:
description: crdName is the name of the CRD used to configure instances of the managed add-on. This field should be configured if the add-on have a CRD that controls the configuration of the add-on.
type: string
lastObservedGeneration:
description: lastObservedGeneration is the observed generation of the custom resource for the configuration of the addon.
type: integer
format: int64
addOnMeta:
description: addOnMeta is a reference to the metadata information for the add-on. This should be same as the addOnMeta for the corresponding ClusterManagementAddOn resource.
type: object

2
go.mod
View File

@@ -19,7 +19,7 @@ require (
k8s.io/klog/v2 v2.30.0
k8s.io/kube-aggregator v0.23.0
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b
open-cluster-management.io/api v0.5.1-0.20220107041310-9303b90b6ade
open-cluster-management.io/api v0.6.1-0.20220302050849-83dafb2a3afd
sigs.k8s.io/controller-runtime v0.11.0
)

4
go.sum
View File

@@ -1266,8 +1266,8 @@ modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
open-cluster-management.io/api v0.5.1-0.20220107041310-9303b90b6ade h1:oPuNeeOub6iZFavW/iULi+ctyJsOjQE75Plmuyk9D9Y=
open-cluster-management.io/api v0.5.1-0.20220107041310-9303b90b6ade/go.mod h1:0IUTh8J+p4pv1THh1r9oO0luX9Z1FLDEAmvzW09qC0o=
open-cluster-management.io/api v0.6.1-0.20220302050849-83dafb2a3afd h1:SGi9q56/ncG2mmOFX9CDQjHHcgU7weJMc2iePGGbt9Y=
open-cluster-management.io/api v0.6.1-0.20220302050849-83dafb2a3afd/go.mod h1:0IUTh8J+p4pv1THh1r9oO0luX9Z1FLDEAmvzW09qC0o=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@@ -0,0 +1,126 @@
package managedclusterset
import (
"context"
"fmt"
"time"
"github.com/openshift/library-go/pkg/controller/factory"
"github.com/openshift/library-go/pkg/operator/events"
"k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
clustersetv1beta1 "open-cluster-management.io/api/client/cluster/clientset/versioned/typed/cluster/v1beta1"
clusterinformerv1beta1 "open-cluster-management.io/api/client/cluster/informers/externalversions/cluster/v1beta1"
clusterlisterv1beta1 "open-cluster-management.io/api/client/cluster/listers/cluster/v1beta1"
clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1"
)
const defaultManagedClusterSetName = "default"
var defaultManagedClusterSetSpec = clusterv1beta1.ManagedClusterSetSpec{
ClusterSelector: clusterv1beta1.ManagedClusterSelector{
SelectorType: clusterv1beta1.LegacyClusterSetLabel,
},
}
var defaultManagedClusterSet = &clusterv1beta1.ManagedClusterSet{
ObjectMeta: metav1.ObjectMeta{
Name: defaultManagedClusterSetName,
},
Spec: defaultManagedClusterSetSpec,
}
type defaultManagedClusterSetController struct {
clusterSetClient clustersetv1beta1.ClusterV1beta1Interface
clusterSetLister clusterlisterv1beta1.ManagedClusterSetLister
eventRecorder events.Recorder
}
func NewDefaultManagedClusterSetController(
clusterSetClient clustersetv1beta1.ClusterV1beta1Interface,
clusterSetInformer clusterinformerv1beta1.ManagedClusterSetInformer,
recorder events.Recorder) factory.Controller {
c := &defaultManagedClusterSetController{
clusterSetClient: clusterSetClient,
clusterSetLister: clusterSetInformer.Lister(),
eventRecorder: recorder.WithComponentSuffix("default-managed-cluster-set-controller"),
}
return factory.New().
WithFilteredEventsInformersQueueKeyFunc(
func(obj runtime.Object) string {
accessor, _ := meta.Accessor(obj)
return accessor.GetName()
},
func(obj interface{}) bool {
metaObj, ok := obj.(metav1.ObjectMetaAccessor)
if !ok {
return false
}
// filter clustersets except defaultManagedClusterSet.
return defaultManagedClusterSetName != metaObj.GetObjectMeta().GetName()
},
clusterSetInformer.Informer(),
).
WithSync(c.sync).
// use ResyncEvery to make sure:
// 1. create the default clusterset once controller is launched
// 2. the default clusterset be recreated once it is deleted for some reason
ResyncEvery(10*time.Second).
ToController("DefaultManagedClusterSetController", recorder)
}
func (c *defaultManagedClusterSetController) sync(ctx context.Context, syncCtx factory.SyncContext) error {
defaultClusterSetName := defaultManagedClusterSetName
klog.Infof("Reconciling DefaultManagedClusterSet")
defaultClusterSet, err := c.clusterSetLister.Get(defaultClusterSetName)
// if the defaultClusterSet not found, apply it.
if errors.IsNotFound(err) {
_, err := c.clusterSetClient.ManagedClusterSets().Create(ctx, defaultManagedClusterSet, metav1.CreateOptions{})
if err == nil {
c.eventRecorder.Eventf("DefaultManagedClusterSetCreated", "Set the DefaultManagedClusterSet name to %+v. spec to %+v", defaultClusterSetName, defaultManagedClusterSetSpec)
}
return err
} else if err != nil {
return err
}
// if defaultClusterSet is terminating, add the key to the controller queue with a second-long delay
if !defaultClusterSet.DeletionTimestamp.IsZero() {
syncCtx.Queue().AddAfter(defaultClusterSetName, 5*time.Second)
return nil
}
if err := c.syncDefaultClusterSet(ctx, defaultClusterSet); err != nil {
return fmt.Errorf("failed to sync DefaultManagedClusterSet %q: %w", defaultClusterSetName, err)
}
return nil
}
// syncDefaultClusterSet syncs default cluster set.
func (c *defaultManagedClusterSetController) syncDefaultClusterSet(ctx context.Context, originalDefaultClusterSet *clusterv1beta1.ManagedClusterSet) error {
defaultClusterSet := originalDefaultClusterSet.DeepCopy()
// if defaultClusterSet.Spec is changed, rollback the change by update it to the original value.
if !equality.Semantic.DeepEqual(defaultClusterSet.Spec, defaultManagedClusterSetSpec) {
defaultClusterSet.Spec = defaultManagedClusterSetSpec
_, err := c.clusterSetClient.ManagedClusterSets().Update(ctx, defaultClusterSet, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("failed to update status of ManagedClusterSet %q: %w", defaultClusterSet.Name, err)
}
c.eventRecorder.Eventf("DefaultManagedClusterSetSpecRollbacked", "Rollback the DefaultManagedClusterSetSpec to %+v", defaultClusterSet.Spec)
}
return nil
}

View File

@@ -0,0 +1,117 @@
package managedclusterset
import (
"context"
"testing"
"time"
"github.com/openshift/library-go/pkg/operator/events/eventstesting"
"k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
clienttesting "k8s.io/client-go/testing"
clusterfake "open-cluster-management.io/api/client/cluster/clientset/versioned/fake"
clusterinformers "open-cluster-management.io/api/client/cluster/informers/externalversions"
clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1"
testinghelpers "open-cluster-management.io/registration/pkg/helpers/testing"
)
func TestSyncDefaultClusterSet(t *testing.T) {
var editedDefaultManagedClusterSetSpec = clusterv1beta1.ManagedClusterSetSpec{
ClusterSelector: clusterv1beta1.ManagedClusterSelector{
SelectorType: "non-LegacyClusterSetLabel",
},
}
cases := []struct {
name string
existingClusterSet *clusterv1beta1.ManagedClusterSet
validateActions func(t *testing.T, actions []clienttesting.Action)
}{
{
name: "sync default cluster set",
existingClusterSet: newDefaultManagedClusterSet(defaultManagedClusterSetName, defaultManagedClusterSetSpec, false),
validateActions: func(t *testing.T, actions []clienttesting.Action) {
testinghelpers.AssertNoActions(t, actions)
},
},
{
name: "sync edited default cluster set",
existingClusterSet: newDefaultManagedClusterSet(defaultManagedClusterSetName, editedDefaultManagedClusterSetSpec, false),
validateActions: func(t *testing.T, actions []clienttesting.Action) {
testinghelpers.AssertActions(t, actions, "update")
clusterset := actions[0].(clienttesting.UpdateAction).GetObject().(*clusterv1beta1.ManagedClusterSet)
// if spec not rollbacked, error
if !equality.Semantic.DeepEqual(clusterset.Spec, defaultManagedClusterSetSpec) {
t.Errorf("Failed to rollback default managed cluster set spec after it is edited")
}
},
},
{
name: "sync deleting default cluster set",
existingClusterSet: newDefaultManagedClusterSet(defaultManagedClusterSetName, defaultManagedClusterSetSpec, true),
validateActions: func(t *testing.T, actions []clienttesting.Action) {
testinghelpers.AssertNoActions(t, actions)
},
},
{
name: "sync deleted default cluster set",
// default cluster set should be created if it is deleted.
validateActions: func(t *testing.T, actions []clienttesting.Action) {
testinghelpers.AssertActions(t, actions, "create")
clusterset := actions[0].(clienttesting.CreateAction).GetObject().(*clusterv1beta1.ManagedClusterSet)
if clusterset.ObjectMeta.Name != defaultManagedClusterSetName {
t.Errorf("Failed to create default managed cluster set")
}
},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
objects := []runtime.Object{}
if c.existingClusterSet != nil {
objects = append(objects, c.existingClusterSet)
}
clusterSetClient := clusterfake.NewSimpleClientset(objects...)
informerFactory := clusterinformers.NewSharedInformerFactory(clusterSetClient, 5*time.Minute)
if c.existingClusterSet != nil {
informerFactory.Cluster().V1beta1().ManagedClusterSets().Informer().GetStore().Add(c.existingClusterSet)
}
ctrl := defaultManagedClusterSetController{
clusterSetClient: clusterSetClient.ClusterV1beta1(),
clusterSetLister: informerFactory.Cluster().V1beta1().ManagedClusterSets().Lister(),
eventRecorder: eventstesting.NewTestingEventRecorder(t),
}
syncErr := ctrl.sync(context.TODO(), testinghelpers.NewFakeSyncContext(t, testinghelpers.TestManagedClusterName))
if syncErr != nil {
t.Errorf("unexpected err: %v", syncErr)
}
c.validateActions(t, clusterSetClient.Actions())
})
}
}
func newDefaultManagedClusterSet(name string, spec clusterv1beta1.ManagedClusterSetSpec, terminating bool) *clusterv1beta1.ManagedClusterSet {
clusterSet := &clusterv1beta1.ManagedClusterSet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: spec,
}
if terminating {
now := metav1.Now()
clusterSet.DeletionTimestamp = &now
}
return clusterSet
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"time"
"open-cluster-management.io/registration/pkg/features"
"open-cluster-management.io/registration/pkg/hub/taint"
addonclient "open-cluster-management.io/api/client/addon/clientset/versioned"
@@ -12,7 +13,6 @@ import (
clusterv1informers "open-cluster-management.io/api/client/cluster/informers/externalversions"
workv1client "open-cluster-management.io/api/client/work/clientset/versioned"
workv1informers "open-cluster-management.io/api/client/work/informers/externalversions"
"open-cluster-management.io/registration/pkg/features"
"open-cluster-management.io/registration/pkg/hub/addon"
"open-cluster-management.io/registration/pkg/hub/clusterrole"
"open-cluster-management.io/registration/pkg/hub/csr"
@@ -22,6 +22,7 @@ import (
"open-cluster-management.io/registration/pkg/hub/rbacfinalizerdeletion"
"github.com/openshift/library-go/pkg/controller/controllercmd"
"github.com/openshift/library-go/pkg/controller/factory"
kubeinformers "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
@@ -132,8 +133,13 @@ func RunControllerManager(ctx context.Context, controllerContext *controllercmd.
controllerContext.EventRecorder,
)
var defaultManagedClusterSetController factory.Controller
if features.DefaultHubMutableFeatureGate.Enabled(features.DefaultClusterSet) {
// TODO define default clusterset controller here
defaultManagedClusterSetController = managedclusterset.NewDefaultManagedClusterSetController(
clusterClient.ClusterV1beta1(),
clusterInformers.Cluster().V1beta1().ManagedClusterSets(),
controllerContext.EventRecorder,
)
}
go clusterInformers.Start(ctx.Done())
@@ -150,6 +156,9 @@ func RunControllerManager(ctx context.Context, controllerContext *controllercmd.
go clusterroleController.Run(ctx, 1)
go addOnHealthCheckController.Run(ctx, 1)
go addOnFeatureDiscoveryController.Run(ctx, 1)
if features.DefaultHubMutableFeatureGate.Enabled(features.DefaultClusterSet) {
go defaultManagedClusterSetController.Run(ctx, 1)
}
<-ctx.Done()
return nil

View File

@@ -0,0 +1,63 @@
package integration_test
import (
"context"
"fmt"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1"
)
var _ = ginkgo.Describe("DefaultManagedClusterSet", func() {
var (
defaultClusterSetName = "default"
defaultManagedClusterSetSpec = clusterv1beta1.ManagedClusterSetSpec{
ClusterSelector: clusterv1beta1.ManagedClusterSelector{
SelectorType: clusterv1beta1.LegacyClusterSetLabel,
},
}
)
ginkgo.It("should create DefaultManagedClusterSet successfully", func() {
ginkgo.By("check whether DefaultManagedClusterSet is created")
gomega.Eventually(func() error {
mcs, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), defaultClusterSetName, metav1.GetOptions{})
if err != nil {
return err
}
if mcs.ObjectMeta.Name == defaultClusterSetName && equality.Semantic.DeepEqual(mcs.Spec, defaultManagedClusterSetSpec) {
return nil
}
return fmt.Errorf("check not pass!")
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
})
ginkgo.It("should recreate DefaultManagedClusterSet successfully after deleted", func() {
ginkgo.By("delete DefaultManagedClusterSet")
err := clusterClient.ClusterV1beta1().ManagedClusterSets().Delete(context.TODO(), defaultClusterSetName, metav1.DeleteOptions{})
gomega.Expect(err).NotTo(gomega.HaveOccurred(), "try to delete DefaultManagedClusterSet error")
ginkgo.By("check whether DefaultManagedClusterSet is recreated")
gomega.Eventually(func() error {
mcs, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), defaultClusterSetName, metav1.GetOptions{})
if err != nil {
return err
}
if mcs.ObjectMeta.Name == defaultClusterSetName && equality.Semantic.DeepEqual(mcs.Spec, defaultManagedClusterSetSpec) {
return nil
}
return fmt.Errorf("check not pass!")
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
})
})

View File

@@ -25,6 +25,7 @@ import (
workclientset "open-cluster-management.io/api/client/work/clientset/versioned"
clusterv1 "open-cluster-management.io/api/cluster/v1"
"open-cluster-management.io/registration/pkg/clientcert"
"open-cluster-management.io/registration/pkg/features"
"open-cluster-management.io/registration/pkg/hub"
"open-cluster-management.io/registration/pkg/spoke"
"open-cluster-management.io/registration/pkg/spoke/addon"
@@ -150,6 +151,9 @@ var _ = ginkgo.BeforeSuite(func(done ginkgo.Done) {
err = util.PrepareSpokeAgentNamespace(kubeClient, testNamespace)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
// enable DefaultClusterSet feature gate
features.DefaultHubMutableFeatureGate.Set("DefaultClusterSet=true")
// start hub controller
go func() {
err := hub.RunControllerManager(ctx, &controllercmd.ControllerContext{

View File

@@ -6,7 +6,6 @@ import (
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/rand"

2
vendor/modules.txt vendored
View File

@@ -1180,7 +1180,7 @@ k8s.io/utils/net
k8s.io/utils/path
k8s.io/utils/pointer
k8s.io/utils/trace
# open-cluster-management.io/api v0.5.1-0.20220107041310-9303b90b6ade
# open-cluster-management.io/api v0.6.1-0.20220302050849-83dafb2a3afd
## explicit; go 1.17
open-cluster-management.io/api/addon/v1alpha1
open-cluster-management.io/api/client/addon/clientset/versioned

View File

@@ -47,6 +47,10 @@ spec:
crdName:
description: crdName is the name of the CRD used to configure instances of the managed add-on. This field should be configured if the add-on have a CRD that controls the configuration of the add-on.
type: string
lastObservedGeneration:
description: lastObservedGeneration is the observed generation of the custom resource for the configuration of the addon.
type: integer
format: int64
addOnMeta:
description: addOnMeta is a reference to the metadata information for the add-on.
type: object

View File

@@ -61,6 +61,10 @@ spec:
crdName:
description: crdName is the name of the CRD used to configure instances of the managed add-on. This field should be configured if the add-on have a CRD that controls the configuration of the add-on.
type: string
lastObservedGeneration:
description: lastObservedGeneration is the observed generation of the custom resource for the configuration of the addon.
type: integer
format: int64
addOnMeta:
description: addOnMeta is a reference to the metadata information for the add-on. This should be same as the addOnMeta for the corresponding ClusterManagementAddOn resource.
type: object

View File

@@ -66,6 +66,10 @@ type ConfigCoordinates struct {
// This field should be configured if add-on CR have a consistent name across the all of the ManagedCluster instaces.
// +optional
CRName string `json:"crName"`
// lastObservedGeneration is the observed generation of the custom resource for the configuration of the addon.
// +optional
LastObservedGeneration int64 `json:"lastObservedGeneration,omitempty"`
}
// ClusterManagementAddOnStatus represents the current status of cluster management add-on.

View File

@@ -60,9 +60,10 @@ func (ClusterManagementAddOnStatus) SwaggerDoc() map[string]string {
}
var map_ConfigCoordinates = map[string]string{
"": "ConfigCoordinates represents the information for locating the CRD and CR that configures the add-on.",
"crdName": "crdName is the name of the CRD used to configure instances of the managed add-on. This field should be configured if the add-on have a CRD that controls the configuration of the add-on.",
"crName": "crName is the name of the CR used to configure instances of the managed add-on. This field should be configured if add-on CR have a consistent name across the all of the ManagedCluster instaces.",
"": "ConfigCoordinates represents the information for locating the CRD and CR that configures the add-on.",
"crdName": "crdName is the name of the CRD used to configure instances of the managed add-on. This field should be configured if the add-on have a CRD that controls the configuration of the add-on.",
"crName": "crName is the name of the CR used to configure instances of the managed add-on. This field should be configured if add-on CR have a consistent name across the all of the ManagedCluster instaces.",
"lastObservedGeneration": "lastObservedGeneration is the observed generation of the custom resource for the configuration of the addon.",
}
func (ConfigCoordinates) SwaggerDoc() map[string]string {

View File

@@ -12,6 +12,8 @@ type ClusterV1beta1Interface interface {
RESTClient() rest.Interface
ManagedClusterSetsGetter
ManagedClusterSetBindingsGetter
PlacementsGetter
PlacementDecisionsGetter
}
// ClusterV1beta1Client is used to interact with features provided by the cluster.open-cluster-management.io group.
@@ -27,6 +29,14 @@ func (c *ClusterV1beta1Client) ManagedClusterSetBindings(namespace string) Manag
return newManagedClusterSetBindings(c, namespace)
}
func (c *ClusterV1beta1Client) Placements(namespace string) PlacementInterface {
return newPlacements(c, namespace)
}
func (c *ClusterV1beta1Client) PlacementDecisions(namespace string) PlacementDecisionInterface {
return newPlacementDecisions(c, namespace)
}
// NewForConfig creates a new ClusterV1beta1Client for the given config.
func NewForConfig(c *rest.Config) (*ClusterV1beta1Client, error) {
config := *c

View File

@@ -20,6 +20,14 @@ func (c *FakeClusterV1beta1) ManagedClusterSetBindings(namespace string) v1beta1
return &FakeManagedClusterSetBindings{c, namespace}
}
func (c *FakeClusterV1beta1) Placements(namespace string) v1beta1.PlacementInterface {
return &FakePlacements{c, namespace}
}
func (c *FakeClusterV1beta1) PlacementDecisions(namespace string) v1beta1.PlacementDecisionInterface {
return &FakePlacementDecisions{c, namespace}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeClusterV1beta1) RESTClient() rest.Interface {

View File

@@ -0,0 +1,126 @@
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
"context"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
v1beta1 "open-cluster-management.io/api/cluster/v1beta1"
)
// FakePlacements implements PlacementInterface
type FakePlacements struct {
Fake *FakeClusterV1beta1
ns string
}
var placementsResource = schema.GroupVersionResource{Group: "cluster.open-cluster-management.io", Version: "v1beta1", Resource: "placements"}
var placementsKind = schema.GroupVersionKind{Group: "cluster.open-cluster-management.io", Version: "v1beta1", Kind: "Placement"}
// Get takes name of the placement, and returns the corresponding placement object, and an error if there is any.
func (c *FakePlacements) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.Placement, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(placementsResource, c.ns, name), &v1beta1.Placement{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.Placement), err
}
// List takes label and field selectors, and returns the list of Placements that match those selectors.
func (c *FakePlacements) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.PlacementList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(placementsResource, placementsKind, c.ns, opts), &v1beta1.PlacementList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1beta1.PlacementList{ListMeta: obj.(*v1beta1.PlacementList).ListMeta}
for _, item := range obj.(*v1beta1.PlacementList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested placements.
func (c *FakePlacements) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(placementsResource, c.ns, opts))
}
// 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 *FakePlacements) Create(ctx context.Context, placement *v1beta1.Placement, opts v1.CreateOptions) (result *v1beta1.Placement, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(placementsResource, c.ns, placement), &v1beta1.Placement{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.Placement), err
}
// 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 *FakePlacements) Update(ctx context.Context, placement *v1beta1.Placement, opts v1.UpdateOptions) (result *v1beta1.Placement, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(placementsResource, c.ns, placement), &v1beta1.Placement{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.Placement), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakePlacements) UpdateStatus(ctx context.Context, placement *v1beta1.Placement, opts v1.UpdateOptions) (*v1beta1.Placement, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(placementsResource, "status", c.ns, placement), &v1beta1.Placement{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.Placement), err
}
// Delete takes name of the placement and deletes it. Returns an error if one occurs.
func (c *FakePlacements) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(placementsResource, c.ns, name), &v1beta1.Placement{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakePlacements) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(placementsResource, c.ns, listOpts)
_, err := c.Fake.Invokes(action, &v1beta1.PlacementList{})
return err
}
// Patch applies the patch and returns the patched placement.
func (c *FakePlacements) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.Placement, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(placementsResource, c.ns, name, pt, data, subresources...), &v1beta1.Placement{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.Placement), err
}

View File

@@ -0,0 +1,126 @@
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
"context"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
v1beta1 "open-cluster-management.io/api/cluster/v1beta1"
)
// FakePlacementDecisions implements PlacementDecisionInterface
type FakePlacementDecisions struct {
Fake *FakeClusterV1beta1
ns string
}
var placementdecisionsResource = schema.GroupVersionResource{Group: "cluster.open-cluster-management.io", Version: "v1beta1", Resource: "placementdecisions"}
var placementdecisionsKind = schema.GroupVersionKind{Group: "cluster.open-cluster-management.io", Version: "v1beta1", Kind: "PlacementDecision"}
// Get takes name of the placementDecision, and returns the corresponding placementDecision object, and an error if there is any.
func (c *FakePlacementDecisions) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.PlacementDecision, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(placementdecisionsResource, c.ns, name), &v1beta1.PlacementDecision{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.PlacementDecision), err
}
// List takes label and field selectors, and returns the list of PlacementDecisions that match those selectors.
func (c *FakePlacementDecisions) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.PlacementDecisionList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(placementdecisionsResource, placementdecisionsKind, c.ns, opts), &v1beta1.PlacementDecisionList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1beta1.PlacementDecisionList{ListMeta: obj.(*v1beta1.PlacementDecisionList).ListMeta}
for _, item := range obj.(*v1beta1.PlacementDecisionList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested placementDecisions.
func (c *FakePlacementDecisions) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(placementdecisionsResource, c.ns, opts))
}
// 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 *FakePlacementDecisions) Create(ctx context.Context, placementDecision *v1beta1.PlacementDecision, opts v1.CreateOptions) (result *v1beta1.PlacementDecision, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(placementdecisionsResource, c.ns, placementDecision), &v1beta1.PlacementDecision{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.PlacementDecision), err
}
// 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 *FakePlacementDecisions) Update(ctx context.Context, placementDecision *v1beta1.PlacementDecision, opts v1.UpdateOptions) (result *v1beta1.PlacementDecision, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(placementdecisionsResource, c.ns, placementDecision), &v1beta1.PlacementDecision{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.PlacementDecision), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakePlacementDecisions) UpdateStatus(ctx context.Context, placementDecision *v1beta1.PlacementDecision, opts v1.UpdateOptions) (*v1beta1.PlacementDecision, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(placementdecisionsResource, "status", c.ns, placementDecision), &v1beta1.PlacementDecision{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.PlacementDecision), err
}
// Delete takes name of the placementDecision and deletes it. Returns an error if one occurs.
func (c *FakePlacementDecisions) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(placementdecisionsResource, c.ns, name), &v1beta1.PlacementDecision{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakePlacementDecisions) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(placementdecisionsResource, c.ns, listOpts)
_, err := c.Fake.Invokes(action, &v1beta1.PlacementDecisionList{})
return err
}
// Patch applies the patch and returns the patched placementDecision.
func (c *FakePlacementDecisions) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.PlacementDecision, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(placementdecisionsResource, c.ns, name, pt, data, subresources...), &v1beta1.PlacementDecision{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.PlacementDecision), err
}

View File

@@ -5,3 +5,7 @@ package v1beta1
type ManagedClusterSetExpansion interface{}
type ManagedClusterSetBindingExpansion interface{}
type PlacementExpansion interface{}
type PlacementDecisionExpansion interface{}

View File

@@ -0,0 +1,179 @@
// Code generated by client-gen. DO NOT EDIT.
package v1beta1
import (
"context"
"time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
scheme "open-cluster-management.io/api/client/cluster/clientset/versioned/scheme"
v1beta1 "open-cluster-management.io/api/cluster/v1beta1"
)
// 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 *v1beta1.Placement, opts v1.CreateOptions) (*v1beta1.Placement, error)
Update(ctx context.Context, placement *v1beta1.Placement, opts v1.UpdateOptions) (*v1beta1.Placement, error)
UpdateStatus(ctx context.Context, placement *v1beta1.Placement, opts v1.UpdateOptions) (*v1beta1.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) (*v1beta1.Placement, error)
List(ctx context.Context, opts v1.ListOptions) (*v1beta1.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 *v1beta1.Placement, err error)
PlacementExpansion
}
// placements implements PlacementInterface
type placements struct {
client rest.Interface
ns string
}
// newPlacements returns a Placements
func newPlacements(c *ClusterV1beta1Client, 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 *v1beta1.Placement, err error) {
result = &v1beta1.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 *v1beta1.PlacementList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1beta1.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 *v1beta1.Placement, opts v1.CreateOptions) (result *v1beta1.Placement, err error) {
result = &v1beta1.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 *v1beta1.Placement, opts v1.UpdateOptions) (result *v1beta1.Placement, err error) {
result = &v1beta1.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 *v1beta1.Placement, opts v1.UpdateOptions) (result *v1beta1.Placement, err error) {
result = &v1beta1.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 *v1beta1.Placement, err error) {
result = &v1beta1.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
}

View File

@@ -0,0 +1,179 @@
// Code generated by client-gen. DO NOT EDIT.
package v1beta1
import (
"context"
"time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
scheme "open-cluster-management.io/api/client/cluster/clientset/versioned/scheme"
v1beta1 "open-cluster-management.io/api/cluster/v1beta1"
)
// 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 *v1beta1.PlacementDecision, opts v1.CreateOptions) (*v1beta1.PlacementDecision, error)
Update(ctx context.Context, placementDecision *v1beta1.PlacementDecision, opts v1.UpdateOptions) (*v1beta1.PlacementDecision, error)
UpdateStatus(ctx context.Context, placementDecision *v1beta1.PlacementDecision, opts v1.UpdateOptions) (*v1beta1.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) (*v1beta1.PlacementDecision, error)
List(ctx context.Context, opts v1.ListOptions) (*v1beta1.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 *v1beta1.PlacementDecision, err error)
PlacementDecisionExpansion
}
// placementDecisions implements PlacementDecisionInterface
type placementDecisions struct {
client rest.Interface
ns string
}
// newPlacementDecisions returns a PlacementDecisions
func newPlacementDecisions(c *ClusterV1beta1Client, 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 *v1beta1.PlacementDecision, err error) {
result = &v1beta1.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 *v1beta1.PlacementDecisionList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1beta1.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 *v1beta1.PlacementDecision, opts v1.CreateOptions) (result *v1beta1.PlacementDecision, err error) {
result = &v1beta1.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 *v1beta1.PlacementDecision, opts v1.UpdateOptions) (result *v1beta1.PlacementDecision, err error) {
result = &v1beta1.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 *v1beta1.PlacementDecision, opts v1.UpdateOptions) (result *v1beta1.PlacementDecision, err error) {
result = &v1beta1.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 *v1beta1.PlacementDecision, err error) {
result = &v1beta1.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
}

View File

@@ -12,6 +12,10 @@ type Interface interface {
ManagedClusterSets() ManagedClusterSetInformer
// ManagedClusterSetBindings returns a ManagedClusterSetBindingInformer.
ManagedClusterSetBindings() ManagedClusterSetBindingInformer
// Placements returns a PlacementInformer.
Placements() PlacementInformer
// PlacementDecisions returns a PlacementDecisionInformer.
PlacementDecisions() PlacementDecisionInformer
}
type version struct {
@@ -34,3 +38,13 @@ func (v *version) ManagedClusterSets() ManagedClusterSetInformer {
func (v *version) ManagedClusterSetBindings() ManagedClusterSetBindingInformer {
return &managedClusterSetBindingInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}
// Placements returns a PlacementInformer.
func (v *version) Placements() PlacementInformer {
return &placementInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}
// PlacementDecisions returns a PlacementDecisionInformer.
func (v *version) PlacementDecisions() PlacementDecisionInformer {
return &placementDecisionInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}

View File

@@ -0,0 +1,74 @@
// Code generated by informer-gen. DO NOT EDIT.
package v1beta1
import (
"context"
time "time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
versioned "open-cluster-management.io/api/client/cluster/clientset/versioned"
internalinterfaces "open-cluster-management.io/api/client/cluster/informers/externalversions/internalinterfaces"
v1beta1 "open-cluster-management.io/api/client/cluster/listers/cluster/v1beta1"
clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1"
)
// PlacementInformer provides access to a shared informer and lister for
// Placements.
type PlacementInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1beta1.PlacementLister
}
type placementInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewPlacementInformer constructs a new informer for Placement type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewPlacementInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredPlacementInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredPlacementInformer constructs a new informer for Placement type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredPlacementInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.ClusterV1beta1().Placements(namespace).List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.ClusterV1beta1().Placements(namespace).Watch(context.TODO(), options)
},
},
&clusterv1beta1.Placement{},
resyncPeriod,
indexers,
)
}
func (f *placementInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredPlacementInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *placementInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&clusterv1beta1.Placement{}, f.defaultInformer)
}
func (f *placementInformer) Lister() v1beta1.PlacementLister {
return v1beta1.NewPlacementLister(f.Informer().GetIndexer())
}

View File

@@ -0,0 +1,74 @@
// Code generated by informer-gen. DO NOT EDIT.
package v1beta1
import (
"context"
time "time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
versioned "open-cluster-management.io/api/client/cluster/clientset/versioned"
internalinterfaces "open-cluster-management.io/api/client/cluster/informers/externalversions/internalinterfaces"
v1beta1 "open-cluster-management.io/api/client/cluster/listers/cluster/v1beta1"
clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1"
)
// PlacementDecisionInformer provides access to a shared informer and lister for
// PlacementDecisions.
type PlacementDecisionInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1beta1.PlacementDecisionLister
}
type placementDecisionInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewPlacementDecisionInformer constructs a new informer for PlacementDecision type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewPlacementDecisionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredPlacementDecisionInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredPlacementDecisionInformer constructs a new informer for PlacementDecision type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredPlacementDecisionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.ClusterV1beta1().PlacementDecisions(namespace).List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.ClusterV1beta1().PlacementDecisions(namespace).Watch(context.TODO(), options)
},
},
&clusterv1beta1.PlacementDecision{},
resyncPeriod,
indexers,
)
}
func (f *placementDecisionInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredPlacementDecisionInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *placementDecisionInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&clusterv1beta1.PlacementDecision{}, f.defaultInformer)
}
func (f *placementDecisionInformer) Lister() v1beta1.PlacementDecisionLister {
return v1beta1.NewPlacementDecisionLister(f.Informer().GetIndexer())
}

View File

@@ -61,6 +61,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
return &genericInformer{resource: resource.GroupResource(), informer: f.Cluster().V1beta1().ManagedClusterSets().Informer()}, nil
case v1beta1.SchemeGroupVersion.WithResource("managedclustersetbindings"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Cluster().V1beta1().ManagedClusterSetBindings().Informer()}, nil
case v1beta1.SchemeGroupVersion.WithResource("placements"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Cluster().V1beta1().Placements().Informer()}, nil
case v1beta1.SchemeGroupVersion.WithResource("placementdecisions"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Cluster().V1beta1().PlacementDecisions().Informer()}, nil
}

View File

@@ -13,3 +13,19 @@ type ManagedClusterSetBindingListerExpansion interface{}
// ManagedClusterSetBindingNamespaceListerExpansion allows custom methods to be added to
// ManagedClusterSetBindingNamespaceLister.
type ManagedClusterSetBindingNamespaceListerExpansion interface{}
// PlacementListerExpansion allows custom methods to be added to
// PlacementLister.
type PlacementListerExpansion interface{}
// PlacementNamespaceListerExpansion allows custom methods to be added to
// PlacementNamespaceLister.
type PlacementNamespaceListerExpansion interface{}
// PlacementDecisionListerExpansion allows custom methods to be added to
// PlacementDecisionLister.
type PlacementDecisionListerExpansion interface{}
// PlacementDecisionNamespaceListerExpansion allows custom methods to be added to
// PlacementDecisionNamespaceLister.
type PlacementDecisionNamespaceListerExpansion interface{}

View File

@@ -0,0 +1,83 @@
// Code generated by lister-gen. DO NOT EDIT.
package v1beta1
import (
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
v1beta1 "open-cluster-management.io/api/cluster/v1beta1"
)
// PlacementLister helps list Placements.
// All objects returned here must be treated as read-only.
type PlacementLister interface {
// List lists all Placements in the indexer.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v1beta1.Placement, err error)
// Placements returns an object that can list and get Placements.
Placements(namespace string) PlacementNamespaceLister
PlacementListerExpansion
}
// placementLister implements the PlacementLister interface.
type placementLister struct {
indexer cache.Indexer
}
// NewPlacementLister returns a new PlacementLister.
func NewPlacementLister(indexer cache.Indexer) PlacementLister {
return &placementLister{indexer: indexer}
}
// List lists all Placements in the indexer.
func (s *placementLister) List(selector labels.Selector) (ret []*v1beta1.Placement, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1beta1.Placement))
})
return ret, err
}
// Placements returns an object that can list and get Placements.
func (s *placementLister) Placements(namespace string) PlacementNamespaceLister {
return placementNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// PlacementNamespaceLister helps list and get Placements.
// All objects returned here must be treated as read-only.
type PlacementNamespaceLister interface {
// List lists all Placements in the indexer for a given namespace.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v1beta1.Placement, err error)
// Get retrieves the Placement from the indexer for a given namespace and name.
// Objects returned here must be treated as read-only.
Get(name string) (*v1beta1.Placement, error)
PlacementNamespaceListerExpansion
}
// placementNamespaceLister implements the PlacementNamespaceLister
// interface.
type placementNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all Placements in the indexer for a given namespace.
func (s placementNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.Placement, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1beta1.Placement))
})
return ret, err
}
// Get retrieves the Placement from the indexer for a given namespace and name.
func (s placementNamespaceLister) Get(name string) (*v1beta1.Placement, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1beta1.Resource("placement"), name)
}
return obj.(*v1beta1.Placement), nil
}

View File

@@ -0,0 +1,83 @@
// Code generated by lister-gen. DO NOT EDIT.
package v1beta1
import (
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
v1beta1 "open-cluster-management.io/api/cluster/v1beta1"
)
// PlacementDecisionLister helps list PlacementDecisions.
// All objects returned here must be treated as read-only.
type PlacementDecisionLister interface {
// List lists all PlacementDecisions in the indexer.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v1beta1.PlacementDecision, err error)
// PlacementDecisions returns an object that can list and get PlacementDecisions.
PlacementDecisions(namespace string) PlacementDecisionNamespaceLister
PlacementDecisionListerExpansion
}
// placementDecisionLister implements the PlacementDecisionLister interface.
type placementDecisionLister struct {
indexer cache.Indexer
}
// NewPlacementDecisionLister returns a new PlacementDecisionLister.
func NewPlacementDecisionLister(indexer cache.Indexer) PlacementDecisionLister {
return &placementDecisionLister{indexer: indexer}
}
// List lists all PlacementDecisions in the indexer.
func (s *placementDecisionLister) List(selector labels.Selector) (ret []*v1beta1.PlacementDecision, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1beta1.PlacementDecision))
})
return ret, err
}
// PlacementDecisions returns an object that can list and get PlacementDecisions.
func (s *placementDecisionLister) PlacementDecisions(namespace string) PlacementDecisionNamespaceLister {
return placementDecisionNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// PlacementDecisionNamespaceLister helps list and get PlacementDecisions.
// All objects returned here must be treated as read-only.
type PlacementDecisionNamespaceLister interface {
// List lists all PlacementDecisions in the indexer for a given namespace.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v1beta1.PlacementDecision, err error)
// Get retrieves the PlacementDecision from the indexer for a given namespace and name.
// Objects returned here must be treated as read-only.
Get(name string) (*v1beta1.PlacementDecision, error)
PlacementDecisionNamespaceListerExpansion
}
// placementDecisionNamespaceLister implements the PlacementDecisionNamespaceLister
// interface.
type placementDecisionNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all PlacementDecisions in the indexer for a given namespace.
func (s placementDecisionNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.PlacementDecision, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1beta1.PlacementDecision))
})
return ret, err
}
// Get retrieves the PlacementDecision from the indexer for a given namespace and name.
func (s placementDecisionNamespaceLister) Get(name string) (*v1beta1.PlacementDecision, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1beta1.Resource("placementdecision"), name)
}
return obj.(*v1beta1.PlacementDecision), nil
}

View File

@@ -1,4 +1,4 @@
apiVersion: apiextensions.k8s.io/v1beta1
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: addonplacementscores.cluster.open-cluster-management.io
@@ -11,103 +11,102 @@ spec:
singular: addonplacementscore
preserveUnknownFields: false
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: AddOnPlacementScore represents a bundle of scores of one managed cluster, which could be used by placement. AddOnPlacementScore is a namespace scoped resource. The namespace of the resource is the cluster namespace.
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 status of the AddOnPlacementScore.
type: object
properties:
conditions:
description: Conditions contain the different condition statuses for this AddOnPlacementScore.
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])$
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
scores:
description: Scores contain a list of score name and value of this managed cluster.
type: array
items:
description: AddOnPlacementScoreItem represents the score name and value.
type: object
required:
- name
- value
properties:
name:
description: Name is the name of the score
type: string
value:
description: Value is the value of the score. The score range is from -100 to 100.
type: integer
format: int32
maximum: 100
minimum: -100
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
validUntil:
description: ValidUntil defines the valid time of the scores. After this time, the scores are considered to be invalid by placement. nil means never expire. The controller owning this resource should keep the scores up-to-date.
type: string
format: date-time
version: v1alpha1
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: AddOnPlacementScore represents a bundle of scores of one managed cluster, which could be used by placement. AddOnPlacementScore is a namespace scoped resource. The namespace of the resource is the cluster namespace.
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 status of the AddOnPlacementScore.
type: object
properties:
conditions:
description: Conditions contain the different condition statuses for this AddOnPlacementScore.
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])$
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
scores:
description: Scores contain a list of score name and value of this managed cluster.
type: array
items:
description: AddOnPlacementScoreItem represents the score name and value.
type: object
required:
- name
- value
properties:
name:
description: Name is the name of the score
type: string
value:
description: Value is the value of the score. The score range is from -100 to 100.
type: integer
format: int32
maximum: 100
minimum: -100
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
validUntil:
description: ValidUntil defines the valid time of the scores. After this time, the scores are considered to be invalid by placement. nil means never expire. The controller owning this resource should keep the scores up-to-date.
type: string
format: date-time
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""

View File

@@ -440,6 +440,8 @@ const (
// A placement is not satisfied only if there is empty ClusterDecision in the status.decisions
// of PlacementDecisions.
PlacementConditionSatisfied string = "PlacementSatisfied"
// PlacementConditionMisconfigured means Placement configuration is incorrect.
PlacementConditionMisconfigured string = "PlacementMisconfigured"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

View File

@@ -110,6 +110,22 @@ spec:
spec:
description: Spec defines the attributes of the ManagedClusterSet
type: object
default:
clusterSelector:
selectorType: LegacyClusterSetLabel
properties:
clusterSelector:
description: ClusterSelector represents a selector of ManagedClusters
type: object
default:
selectorType: LegacyClusterSetLabel
properties:
selectorType:
description: SelectorType could only be "LegacyClusterSetLabel" now, will support more SelectorType later "LegacyClusterSetLabel" means to use label "cluster.open-cluster-management.io/clusterset:<ManagedClusterSet Name>"" to select target clusters.
type: string
default: LegacyClusterSetLabel
enum:
- LegacyClusterSetLabel
status:
description: Status represents the current status of the ManagedClusterSet
type: object

View File

@@ -0,0 +1,511 @@
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:
- additionalPrinterColumns:
- jsonPath: .status.conditions[?(@.type=="PlacementSatisfied")].status
name: Succeeded
type: string
- jsonPath: .status.conditions[?(@.type=="PlacementSatisfied")].reason
name: Reason
type: string
- jsonPath: .status.numberOfSelectedClusters
name: SelectedClusters
type: integer
name: v1alpha1
deprecated: true
deprecationWarning: "cluster.open-cluster-management.io/v1alpha1 Placement is deprecated; use cluster.open-cluster-management.io/v1beta1 Placement"
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
prioritizerPolicy:
description: PrioritizerPolicy defines the policy of the prioritizers. If this field is unset, then default prioritizer mode and configurations are used. Referring to PrioritizerPolicy to see more description about Mode and Configurations.
type: object
properties:
configurations:
type: array
items:
description: PrioritizerConfig represents the configuration of prioritizer
type: object
properties:
name:
description: 'Name will be removed in v1beta1 and replaced by ScoreCoordinate.BuiltIn. If both Name and ScoreCoordinate.BuiltIn are defined, will use the value in ScoreCoordinate.BuiltIn. Name is the name of a prioritizer. Below are the valid names: 1) Balance: balance the decisions among the clusters. 2) Steady: ensure the existing decision is stabilized. 3) ResourceAllocatableCPU & ResourceAllocatableMemory: sort clusters based on the allocatable.'
type: string
scoreCoordinate:
description: ScoreCoordinate represents the configuration of the prioritizer and score source.
type: object
required:
- type
properties:
addOn:
description: When type is "AddOn", AddOn defines the resource name and score name.
type: object
required:
- resourceName
- scoreName
properties:
resourceName:
description: ResourceName defines the resource name of the AddOnPlacementScore. The placement prioritizer selects AddOnPlacementScore CR by this name.
type: string
scoreName:
description: ScoreName defines the score name inside AddOnPlacementScore. AddOnPlacementScore contains a list of score name and score value, ScoreName specify the score to be used by the prioritizer.
type: string
builtIn:
description: 'BuiltIn defines the name of a BuiltIn prioritizer. Below are the valid BuiltIn prioritizer names. 1) Balance: balance the decisions among the clusters. 2) Steady: ensure the existing decision is stabilized. 3) ResourceAllocatableCPU & ResourceAllocatableMemory: sort clusters based on the allocatable.'
type: string
type:
description: Type defines the type of the prioritizer score. Type is either "BuiltIn", "AddOn" or "", where "" is "BuiltIn" by default. When the type is "BuiltIn", need to specify a BuiltIn prioritizer name in BuiltIn. When the type is "AddOn", need to configure the score source in AddOn.
type: string
default: BuiltIn
enum:
- BuiltIn
- AddOn
weight:
description: Weight defines the weight of the prioritizer score. The value must be ranged in [-10,10]. Each prioritizer will calculate an integer score of a cluster in the range of [-100, 100]. The final score of a cluster will be sum(weight * prioritizer_score). A higher weight indicates that the prioritizer weights more in the cluster selection, while 0 weight indicates that the prioritizer is disabled. A negative weight indicates wants to select the last ones.
type: integer
format: int32
default: 1
maximum: 10
minimum: -10
mode:
description: Mode is either Exact, Additive, "" where "" is Additive by default. In Additive mode, any prioritizer not explicitly enumerated is enabled in its default Configurations, in which Steady and Balance prioritizers have the weight of 1 while other prioritizers have the weight of 0. Additive doesn't require configuring all prioritizers. The default Configurations may change in the future, and additional prioritization will happen. In Exact mode, any prioritizer not explicitly enumerated is weighted as zero. Exact requires knowing the full set of prioritizers you want, but avoids behavior changes between releases.
type: string
default: Additive
tolerations:
description: Tolerations are applied to placements, and allow (but do not require) the managed clusters with certain taints to be selected by placements with matching tolerations.
type: array
items:
description: Toleration represents the toleration object that can be attached to a placement. The placement this Toleration is attached to tolerates any taint that matches the triple <key,value,effect> using the matching operator <operator>.
type: object
properties:
effect:
description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSelect, PreferNoSelect and NoSelectIfNew.
type: string
enum:
- NoSelect
- PreferNoSelect
- NoSelectIfNew
key:
description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys.
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])$
operator:
description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a placement can tolerate all taints of a particular category.
type: string
default: Equal
tolerationSeconds:
description: TolerationSeconds represents the period of time the toleration (which must be of effect NoSelect/PreferNoSelect, otherwise this field is ignored) tolerates the taint. The default value is nil, which indicates it tolerates the taint forever. The start time of counting the TolerationSeconds should be the TimeAdded in Taint, not the cluster scheduled time or TolerationSeconds added time.
type: integer
format: int64
value:
description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string.
type: string
maxLength: 1024
status:
description: Status represents the current status of the Placement
type: object
properties:
conditions:
description: Conditions contains the different condition status 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: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .status.conditions[?(@.type=="PlacementSatisfied")].status
name: Succeeded
type: string
- jsonPath: .status.conditions[?(@.type=="PlacementSatisfied")].reason
name: Reason
type: string
- jsonPath: .status.numberOfSelectedClusters
name: SelectedClusters
type: integer
name: v1beta1
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
prioritizerPolicy:
description: PrioritizerPolicy defines the policy of the prioritizers. If this field is unset, then default prioritizer mode and configurations are used. Referring to PrioritizerPolicy to see more description about Mode and Configurations.
type: object
properties:
configurations:
type: array
items:
description: PrioritizerConfig represents the configuration of prioritizer
type: object
required:
- scoreCoordinate
properties:
scoreCoordinate:
description: ScoreCoordinate represents the configuration of the prioritizer and score source.
type: object
required:
- type
properties:
addOn:
description: When type is "AddOn", AddOn defines the resource name and score name.
type: object
required:
- resourceName
- scoreName
properties:
resourceName:
description: ResourceName defines the resource name of the AddOnPlacementScore. The placement prioritizer selects AddOnPlacementScore CR by this name.
type: string
scoreName:
description: ScoreName defines the score name inside AddOnPlacementScore. AddOnPlacementScore contains a list of score name and score value, ScoreName specify the score to be used by the prioritizer.
type: string
builtIn:
description: 'BuiltIn defines the name of a BuiltIn prioritizer. Below are the valid BuiltIn prioritizer names. 1) Balance: balance the decisions among the clusters. 2) Steady: ensure the existing decision is stabilized. 3) ResourceAllocatableCPU & ResourceAllocatableMemory: sort clusters based on the allocatable.'
type: string
type:
description: Type defines the type of the prioritizer score. Type is either "BuiltIn", "AddOn" or "", where "" is "BuiltIn" by default. When the type is "BuiltIn", need to specify a BuiltIn prioritizer name in BuiltIn. When the type is "AddOn", need to configure the score source in AddOn.
type: string
default: BuiltIn
enum:
- BuiltIn
- AddOn
weight:
description: Weight defines the weight of the prioritizer score. The value must be ranged in [-10,10]. Each prioritizer will calculate an integer score of a cluster in the range of [-100, 100]. The final score of a cluster will be sum(weight * prioritizer_score). A higher weight indicates that the prioritizer weights more in the cluster selection, while 0 weight indicates that the prioritizer is disabled. A negative weight indicates wants to select the last ones.
type: integer
format: int32
default: 1
maximum: 10
minimum: -10
mode:
description: Mode is either Exact, Additive, "" where "" is Additive by default. In Additive mode, any prioritizer not explicitly enumerated is enabled in its default Configurations, in which Steady and Balance prioritizers have the weight of 1 while other prioritizers have the weight of 0. Additive doesn't require configuring all prioritizers. The default Configurations may change in the future, and additional prioritization will happen. In Exact mode, any prioritizer not explicitly enumerated is weighted as zero. Exact requires knowing the full set of prioritizers you want, but avoids behavior changes between releases.
type: string
default: Additive
tolerations:
description: Tolerations are applied to placements, and allow (but do not require) the managed clusters with certain taints to be selected by placements with matching tolerations.
type: array
items:
description: Toleration represents the toleration object that can be attached to a placement. The placement this Toleration is attached to tolerates any taint that matches the triple <key,value,effect> using the matching operator <operator>.
type: object
properties:
effect:
description: Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSelect, PreferNoSelect and NoSelectIfNew.
type: string
enum:
- NoSelect
- PreferNoSelect
- NoSelectIfNew
key:
description: Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys.
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])$
operator:
description: Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a placement can tolerate all taints of a particular category.
type: string
default: Equal
tolerationSeconds:
description: TolerationSeconds represents the period of time the toleration (which must be of effect NoSelect/PreferNoSelect, otherwise this field is ignored) tolerates the taint. The default value is nil, which indicates it tolerates the taint forever. The start time of counting the TolerationSeconds should be the TimeAdded in Taint, not the cluster scheduled time or TolerationSeconds added time.
type: integer
format: int64
value:
description: Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string.
type: string
maxLength: 1024
status:
description: Status represents the current status of the Placement
type: object
properties:
conditions:
description: Conditions contains the different condition status 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: []

View File

@@ -0,0 +1,102 @@
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
deprecated: true
deprecationWarning: "cluster.open-cluster-management.io/v1alpha1 PlacementDecision is deprecated; use cluster.open-cluster-management.io/v1beta1 PlacementDecision"
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: false
subresources:
status: {}
- name: v1beta1
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: []

View File

@@ -34,6 +34,10 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&ManagedClusterSetList{},
&ManagedClusterSetBinding{},
&ManagedClusterSetBindingList{},
&Placement{},
&PlacementList{},
&PlacementDecision{},
&PlacementDecisionList{},
)
metav1.AddToGroupVersion(scheme, GroupVersion)
return nil

View File

@@ -29,6 +29,7 @@ type ManagedClusterSet struct {
metav1.ObjectMeta `json:"metadata,omitempty"`
// Spec defines the attributes of the ManagedClusterSet
// +kubebuilder:default={clusterSelector: {selectorType: LegacyClusterSetLabel}}
Spec ManagedClusterSetSpec `json:"spec"`
// Status represents the current status of the ManagedClusterSet
@@ -38,8 +39,28 @@ type ManagedClusterSet struct {
// ManagedClusterSetSpec describes the attributes of the ManagedClusterSet
type ManagedClusterSetSpec struct {
// ClusterSelector represents a selector of ManagedClusters
// +optional
// +kubebuilder:default:={selectorType: LegacyClusterSetLabel}
ClusterSelector ManagedClusterSelector `json:"clusterSelector,omitempty"`
}
// ManagedClusterSelector represents a selector of ManagedClusters
type ManagedClusterSelector struct {
// SelectorType could only be "LegacyClusterSetLabel" now, will support more SelectorType later
// "LegacyClusterSetLabel" means to use label "cluster.open-cluster-management.io/clusterset:<ManagedClusterSet Name>"" to select target clusters.
// +kubebuilder:validation:Enum=LegacyClusterSetLabel
// +kubebuilder:default:=LegacyClusterSetLabel
// +required
SelectorType SelectorType `json:"selectorType,omitempty"`
}
type SelectorType string
const (
LegacyClusterSetLabel SelectorType = "LegacyClusterSetLabel"
)
// ManagedClusterSetStatus represents the current status of the ManagedClusterSet.
type ManagedClusterSetStatus struct {
// Conditions contains the different condition statuses for this ManagedClusterSet.

View File

@@ -0,0 +1,294 @@
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "open-cluster-management.io/api/cluster/v1"
)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:resource:scope="Namespaced"
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Succeeded",type="string",JSONPath=".status.conditions[?(@.type==\"PlacementSatisfied\")].status"
// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.conditions[?(@.type==\"PlacementSatisfied\")].reason"
// +kubebuilder:printcolumn:name="SelectedClusters",type="integer",JSONPath=".status.numberOfSelectedClusters"
// 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"`
// PrioritizerPolicy defines the policy of the prioritizers.
// If this field is unset, then default prioritizer mode and configurations are used.
// Referring to PrioritizerPolicy to see more description about Mode and Configurations.
// +optional
PrioritizerPolicy PrioritizerPolicy `json:"prioritizerPolicy"`
// Tolerations are applied to placements, and allow (but do not require) the managed clusters with
// certain taints to be selected by placements with matching tolerations.
// +optional
Tolerations []Toleration `json:"tolerations,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"`
}
// PrioritizerPolicy represents the policy of prioritizer
type PrioritizerPolicy struct {
// Mode is either Exact, Additive, "" where "" is Additive by default.
// In Additive mode, any prioritizer not explicitly enumerated is enabled in its default Configurations,
// in which Steady and Balance prioritizers have the weight of 1 while other prioritizers have the weight of 0.
// Additive doesn't require configuring all prioritizers. The default Configurations may change in the future,
// and additional prioritization will happen.
// In Exact mode, any prioritizer not explicitly enumerated is weighted as zero.
// Exact requires knowing the full set of prioritizers you want, but avoids behavior changes between releases.
// +kubebuilder:default:=Additive
// +optional
Mode PrioritizerPolicyModeType `json:"mode,omitempty"`
// +optional
Configurations []PrioritizerConfig `json:"configurations,omitempty"`
}
// PrioritizerPolicyModeType represents the type of PrioritizerPolicy.Mode
type PrioritizerPolicyModeType string
const (
// Valid PrioritizerPolicyModeType value is Exact, Additive.
PrioritizerPolicyModeAdditive PrioritizerPolicyModeType = "Additive"
PrioritizerPolicyModeExact PrioritizerPolicyModeType = "Exact"
)
// PrioritizerConfig represents the configuration of prioritizer
type PrioritizerConfig struct {
// ScoreCoordinate represents the configuration of the prioritizer and score source.
// +kubebuilder:validation:Required
// +required
ScoreCoordinate *ScoreCoordinate `json:"scoreCoordinate,omitempty"`
// Weight defines the weight of the prioritizer score. The value must be ranged in [-10,10].
// Each prioritizer will calculate an integer score of a cluster in the range of [-100, 100].
// The final score of a cluster will be sum(weight * prioritizer_score).
// A higher weight indicates that the prioritizer weights more in the cluster selection,
// while 0 weight indicates that the prioritizer is disabled. A negative weight indicates
// wants to select the last ones.
// +kubebuilder:validation:Minimum:=-10
// +kubebuilder:validation:Maximum:=10
// +kubebuilder:default:=1
// +optional
Weight int32 `json:"weight,omitempty"`
}
// ScoreCoordinate represents the configuration of the score type and score source
type ScoreCoordinate struct {
// Type defines the type of the prioritizer score.
// Type is either "BuiltIn", "AddOn" or "", where "" is "BuiltIn" by default.
// When the type is "BuiltIn", need to specify a BuiltIn prioritizer name in BuiltIn.
// When the type is "AddOn", need to configure the score source in AddOn.
// +kubebuilder:validation:Required
// +kubebuilder:validation:Enum=BuiltIn;AddOn
// +kubebuilder:default:=BuiltIn
// +required
Type string `json:"type,omitempty"`
// BuiltIn defines the name of a BuiltIn prioritizer. Below are the valid BuiltIn prioritizer names.
// 1) Balance: balance the decisions among the clusters.
// 2) Steady: ensure the existing decision is stabilized.
// 3) ResourceAllocatableCPU & ResourceAllocatableMemory: sort clusters based on the allocatable.
// +optional
BuiltIn string `json:"builtIn,omitempty"`
// When type is "AddOn", AddOn defines the resource name and score name.
// +optional
AddOn *AddOnScore `json:"addOn,omitempty"`
}
const (
// Valid ScoreCoordinate type is BuiltIn, AddOn.
ScoreCoordinateTypeBuiltIn string = "BuiltIn"
ScoreCoordinateTypeAddOn string = "AddOn"
)
// AddOnScore represents the configuration of the addon score source.
type AddOnScore struct {
// ResourceName defines the resource name of the AddOnPlacementScore.
// The placement prioritizer selects AddOnPlacementScore CR by this name.
// +kubebuilder:validation:Required
// +required
ResourceName string `json:"resourceName"`
// ScoreName defines the score name inside AddOnPlacementScore.
// AddOnPlacementScore contains a list of score name and score value, ScoreName specify the score to be used by
// the prioritizer.
// +kubebuilder:validation:Required
// +required
ScoreName string `json:"scoreName"`
}
// Toleration represents the toleration object that can be attached to a placement.
// The placement this Toleration is attached to tolerates any taint that matches
// the triple <key,value,effect> using the matching operator <operator>.
type Toleration struct {
// Key is the taint key that the toleration applies to. Empty means match all taint keys.
// If the key is empty, operator must be Exists; this combination means to match all values and all keys.
// +kubebuilder:validation: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])$`
// +kubebuilder:validation:MaxLength=316
// +optional
Key string `json:"key,omitempty"`
// Operator represents a key's relationship to the value.
// Valid operators are Exists and Equal. Defaults to Equal.
// Exists is equivalent to wildcard for value, so that a placement can
// tolerate all taints of a particular category.
// +kubebuilder:default:="Equal"
// +optional
Operator TolerationOperator `json:"operator,omitempty"`
// Value is the taint value the toleration matches to.
// If the operator is Exists, the value should be empty, otherwise just a regular string.
// +kubebuilder:validation:MaxLength=1024
// +optional
Value string `json:"value,omitempty"`
// Effect indicates the taint effect to match. Empty means match all taint effects.
// When specified, allowed values are NoSelect, PreferNoSelect and NoSelectIfNew.
// +kubebuilder:validation:Enum:=NoSelect;PreferNoSelect;NoSelectIfNew
// +optional
Effect v1.TaintEffect `json:"effect,omitempty"`
// TolerationSeconds represents the period of time the toleration (which must be of effect
// NoSelect/PreferNoSelect, otherwise this field is ignored) tolerates the taint.
// The default value is nil, which indicates it tolerates the taint forever.
// The start time of counting the TolerationSeconds should be the TimeAdded in Taint, not the cluster
// scheduled time or TolerationSeconds added time.
// +optional
TolerationSeconds *int64 `json:"tolerationSeconds,omitempty"`
}
// TolerationOperator is the set of operators that can be used in a toleration.
type TolerationOperator string
// These are valid values for TolerationOperator
const (
TolerationOpExists TolerationOperator = "Exists"
TolerationOpEqual TolerationOperator = "Equal"
)
type PlacementStatus struct {
// NumberOfSelectedClusters represents the number of selected ManagedClusters
// +optional
NumberOfSelectedClusters int32 `json:"numberOfSelectedClusters"`
// Conditions contains the different condition status 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"
// PlacementConditionMisconfigured means Placement configuration is incorrect.
PlacementConditionMisconfigured string = "PlacementMisconfigured"
)
// +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"`
}

View File

@@ -0,0 +1,70 @@
package v1beta1
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
// +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"`
}
//The placementDecsion label name holding the placement name
const (
PlacementLabel string = "cluster.open-cluster-management.io/placement"
)
// 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"`
}

View File

@@ -10,6 +10,112 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AddOnScore) DeepCopyInto(out *AddOnScore) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddOnScore.
func (in *AddOnScore) DeepCopy() *AddOnScore {
if in == nil {
return nil
}
out := new(AddOnScore)
in.DeepCopyInto(out)
return out
}
// 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 *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 *ManagedClusterSelector) DeepCopyInto(out *ManagedClusterSelector) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterSelector.
func (in *ManagedClusterSelector) DeepCopy() *ManagedClusterSelector {
if in == nil {
return nil
}
out := new(ManagedClusterSelector)
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
@@ -150,6 +256,7 @@ func (in *ManagedClusterSetList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManagedClusterSetSpec) DeepCopyInto(out *ManagedClusterSetSpec) {
*out = *in
out.ClusterSelector = in.ClusterSelector
return
}
@@ -185,3 +292,295 @@ 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])
}
}
in.PrioritizerPolicy.DeepCopyInto(&out.PrioritizerPolicy)
if in.Tolerations != nil {
in, out := &in.Tolerations, &out.Tolerations
*out = make([]Toleration, 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
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PrioritizerConfig) DeepCopyInto(out *PrioritizerConfig) {
*out = *in
if in.ScoreCoordinate != nil {
in, out := &in.ScoreCoordinate, &out.ScoreCoordinate
*out = new(ScoreCoordinate)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrioritizerConfig.
func (in *PrioritizerConfig) DeepCopy() *PrioritizerConfig {
if in == nil {
return nil
}
out := new(PrioritizerConfig)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PrioritizerPolicy) DeepCopyInto(out *PrioritizerPolicy) {
*out = *in
if in.Configurations != nil {
in, out := &in.Configurations, &out.Configurations
*out = make([]PrioritizerConfig, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrioritizerPolicy.
func (in *PrioritizerPolicy) DeepCopy() *PrioritizerPolicy {
if in == nil {
return nil
}
out := new(PrioritizerPolicy)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ScoreCoordinate) DeepCopyInto(out *ScoreCoordinate) {
*out = *in
if in.AddOn != nil {
in, out := &in.AddOn, &out.AddOn
*out = new(AddOnScore)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScoreCoordinate.
func (in *ScoreCoordinate) DeepCopy() *ScoreCoordinate {
if in == nil {
return nil
}
out := new(ScoreCoordinate)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Toleration) DeepCopyInto(out *Toleration) {
*out = *in
if in.TolerationSeconds != nil {
in, out := &in.TolerationSeconds, &out.TolerationSeconds
*out = new(int64)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Toleration.
func (in *Toleration) DeepCopy() *Toleration {
if in == nil {
return nil
}
out := new(Toleration)
in.DeepCopyInto(out)
return out
}

View File

@@ -11,6 +11,15 @@ package v1beta1
// Those methods can be generated by using hack/update-swagger-docs.sh
// AUTO-GENERATED FUNCTIONS START HERE
var map_ManagedClusterSelector = map[string]string{
"": "ManagedClusterSelector represents a selector of ManagedClusters",
"selectorType": "SelectorType could only be \"LegacyClusterSetLabel\" now, will support more SelectorType later \"LegacyClusterSetLabel\" means to use label \"cluster.open-cluster-management.io/clusterset:<ManagedClusterSet Name>\"\" to select target clusters.",
}
func (ManagedClusterSelector) SwaggerDoc() map[string]string {
return map_ManagedClusterSelector
}
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",
@@ -32,7 +41,8 @@ func (ManagedClusterSetList) SwaggerDoc() map[string]string {
}
var map_ManagedClusterSetSpec = map[string]string{
"": "ManagedClusterSetSpec describes the attributes of the ManagedClusterSet",
"": "ManagedClusterSetSpec describes the attributes of the ManagedClusterSet",
"clusterSelector": "ClusterSelector represents a selector of ManagedClusters",
}
func (ManagedClusterSetSpec) SwaggerDoc() map[string]string {
@@ -76,4 +86,165 @@ func (ManagedClusterSetBindingSpec) SwaggerDoc() map[string]string {
return map_ManagedClusterSetBindingSpec
}
var map_AddOnScore = map[string]string{
"": "AddOnScore represents the configuration of the addon score source.",
"resourceName": "ResourceName defines the resource name of the AddOnPlacementScore. The placement prioritizer selects AddOnPlacementScore CR by this name.",
"scoreName": "ScoreName defines the score name inside AddOnPlacementScore. AddOnPlacementScore contains a list of score name and score value, ScoreName specify the score to be used by the prioritizer.",
}
func (AddOnScore) SwaggerDoc() map[string]string {
return map_AddOnScore
}
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_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_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_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.",
"prioritizerPolicy": "PrioritizerPolicy defines the policy of the prioritizers. If this field is unset, then default prioritizer mode and configurations are used. Referring to PrioritizerPolicy to see more description about Mode and Configurations.",
"tolerations": "Tolerations are applied to placements, and allow (but do not require) the managed clusters with certain taints to be selected by placements with matching tolerations.",
}
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 status for this Placement.",
}
func (PlacementStatus) SwaggerDoc() map[string]string {
return map_PlacementStatus
}
var map_PrioritizerConfig = map[string]string{
"": "PrioritizerConfig represents the configuration of prioritizer",
"scoreCoordinate": "ScoreCoordinate represents the configuration of the prioritizer and score source.",
"weight": "Weight defines the weight of the prioritizer score. The value must be ranged in [-10,10]. Each prioritizer will calculate an integer score of a cluster in the range of [-100, 100]. The final score of a cluster will be sum(weight * prioritizer_score). A higher weight indicates that the prioritizer weights more in the cluster selection, while 0 weight indicates that the prioritizer is disabled. A negative weight indicates wants to select the last ones.",
}
func (PrioritizerConfig) SwaggerDoc() map[string]string {
return map_PrioritizerConfig
}
var map_PrioritizerPolicy = map[string]string{
"": "PrioritizerPolicy represents the policy of prioritizer",
"mode": "Mode is either Exact, Additive, \"\" where \"\" is Additive by default. In Additive mode, any prioritizer not explicitly enumerated is enabled in its default Configurations, in which Steady and Balance prioritizers have the weight of 1 while other prioritizers have the weight of 0. Additive doesn't require configuring all prioritizers. The default Configurations may change in the future, and additional prioritization will happen. In Exact mode, any prioritizer not explicitly enumerated is weighted as zero. Exact requires knowing the full set of prioritizers you want, but avoids behavior changes between releases.",
}
func (PrioritizerPolicy) SwaggerDoc() map[string]string {
return map_PrioritizerPolicy
}
var map_ScoreCoordinate = map[string]string{
"": "ScoreCoordinate represents the configuration of the score type and score source",
"type": "Type defines the type of the prioritizer score. Type is either \"BuiltIn\", \"AddOn\" or \"\", where \"\" is \"BuiltIn\" by default. When the type is \"BuiltIn\", need to specify a BuiltIn prioritizer name in BuiltIn. When the type is \"AddOn\", need to configure the score source in AddOn.",
"builtIn": "BuiltIn defines the name of a BuiltIn prioritizer. Below are the valid BuiltIn prioritizer names. 1) Balance: balance the decisions among the clusters. 2) Steady: ensure the existing decision is stabilized. 3) ResourceAllocatableCPU & ResourceAllocatableMemory: sort clusters based on the allocatable.",
"addOn": "When type is \"AddOn\", AddOn defines the resource name and score name.",
}
func (ScoreCoordinate) SwaggerDoc() map[string]string {
return map_ScoreCoordinate
}
var map_Toleration = map[string]string{
"": "Toleration represents the toleration object that can be attached to a placement. The placement this Toleration is attached to tolerates any taint that matches the triple <key,value,effect> using the matching operator <operator>.",
"key": "Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys.",
"operator": "Operator represents a key's relationship to the value. Valid operators are Exists and Equal. Defaults to Equal. Exists is equivalent to wildcard for value, so that a placement can tolerate all taints of a particular category.",
"value": "Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string.",
"effect": "Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSelect, PreferNoSelect and NoSelectIfNew.",
"tolerationSeconds": "TolerationSeconds represents the period of time the toleration (which must be of effect NoSelect/PreferNoSelect, otherwise this field is ignored) tolerates the taint. The default value is nil, which indicates it tolerates the taint forever. The start time of counting the TolerationSeconds should be the TimeAdded in Taint, not the cluster scheduled time or TolerationSeconds added time.",
}
func (Toleration) SwaggerDoc() map[string]string {
return map_Toleration
}
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_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
}
// AUTO-GENERATED FUNCTIONS END HERE