Merge pull request #20 from elgnay/delete-untracked-resources

Delete untracked resources of manifest work
This commit is contained in:
OpenShift Merge Robot
2020-06-01 15:25:29 +02:00
committed by GitHub
16 changed files with 1411 additions and 99 deletions

3
go.mod
View File

@@ -6,7 +6,7 @@ require (
github.com/davecgh/go-spew v1.1.1
github.com/onsi/ginkgo v1.11.0
github.com/onsi/gomega v1.8.1
github.com/open-cluster-management/api v0.0.0-20200512175145-bed9ce79e17e
github.com/open-cluster-management/api v0.0.0-20200528225735-c85cec6fa5b0
github.com/openshift/build-machinery-go v0.0.0-20200211121458-5e3d6e570160
github.com/openshift/library-go v0.0.0-20200414135834-ccc4bb27d032
github.com/spf13/cobra v1.0.0
@@ -18,5 +18,6 @@ require (
k8s.io/component-base v0.18.2
k8s.io/klog v1.0.0
k8s.io/kubectl v0.18.2
k8s.io/utils v0.0.0-20200327001022-6496210b90e8
sigs.k8s.io/controller-runtime v0.6.0
)

4
go.sum
View File

@@ -303,8 +303,8 @@ github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34=
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/open-cluster-management/api v0.0.0-20200512175145-bed9ce79e17e h1:WIzt0Bs7g0PIrVAVSobXAbDqvC2P5VjEwFTpjB4777I=
github.com/open-cluster-management/api v0.0.0-20200512175145-bed9ce79e17e/go.mod h1:RgKeB8PJ7upe2QXy/MpCejU/xm2G6/i0Y+/itWuPugs=
github.com/open-cluster-management/api v0.0.0-20200528225735-c85cec6fa5b0 h1:NurWtcX3/i6vBL022aM+VboyWx8FpNBj7SoO/uT+k0o=
github.com/open-cluster-management/api v0.0.0-20200528225735-c85cec6fa5b0/go.mod h1:RgKeB8PJ7upe2QXy/MpCejU/xm2G6/i0Y+/itWuPugs=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.0.0-20191031171055-b133feaeeb2e/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=

View File

@@ -0,0 +1,168 @@
package deletioncontroller
import (
"context"
"fmt"
"reflect"
"sort"
"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/apimachinery/pkg/runtime/schema"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/client-go/dynamic"
"k8s.io/klog"
workv1client "github.com/open-cluster-management/api/client/work/clientset/versioned/typed/work/v1"
workinformer "github.com/open-cluster-management/api/client/work/informers/externalversions/work/v1"
worklister "github.com/open-cluster-management/api/client/work/listers/work/v1"
workapiv1 "github.com/open-cluster-management/api/work/v1"
"github.com/openshift/library-go/pkg/controller/factory"
"github.com/openshift/library-go/pkg/operator/events"
)
// StaleManifestDeletionController is to reconcile the applied resources of manifest work and
// delete any resouce which is no longer maintained by the manifest work
type StaleManifestDeletionController struct {
manifestWorkClient workv1client.ManifestWorkInterface
manifestWorkLister worklister.ManifestWorkNamespaceLister
spokeDynamicClient dynamic.Interface
}
// NewStaleManifestDeletionController returns a StaleManifestDeletionController
func NewStaleManifestDeletionController(
recorder events.Recorder,
spokeDynamicClient dynamic.Interface,
manifestWorkClient workv1client.ManifestWorkInterface,
manifestWorkInformer workinformer.ManifestWorkInformer,
manifestWorkLister worklister.ManifestWorkNamespaceLister) factory.Controller {
controller := &StaleManifestDeletionController{
manifestWorkClient: manifestWorkClient,
manifestWorkLister: manifestWorkLister,
spokeDynamicClient: spokeDynamicClient,
}
return factory.New().
WithInformersQueueKeyFunc(func(obj runtime.Object) string {
accessor, _ := meta.Accessor(obj)
return accessor.GetName()
}, manifestWorkInformer.Informer()).
WithSync(controller.sync).ToController("StaleManifestDeletionController", recorder)
}
func (m *StaleManifestDeletionController) sync(ctx context.Context, controllerContext factory.SyncContext) error {
manifestWorkName := controllerContext.QueueKey()
klog.V(4).Infof("Reconciling ManifestWork %q", manifestWorkName)
manifestWork, err := m.manifestWorkLister.Get(manifestWorkName)
if errors.IsNotFound(err) {
// work not found, could have been deleted, do nothing.
return nil
}
if err != nil {
return err
}
return m.syncManifestWork(ctx, manifestWork)
}
func (m *StaleManifestDeletionController) syncManifestWork(ctx context.Context, originalManifestWork *workapiv1.ManifestWork) error {
manifestWork := originalManifestWork.DeepCopy()
// no work to do if we're deleted
if !manifestWork.DeletionTimestamp.IsZero() {
return nil
}
// get the latest applied resources from the manifests in resource status. We get this from status instead of
// spec because manifests in spec are only resource templates, while resource status records the real resources
// maintained by the manifest work.
var appliedResources []workapiv1.AppliedManifestResourceMeta
for _, resourceStatus := range manifestWork.Status.ResourceStatus.Manifests {
gvr := schema.GroupVersionResource{Group: resourceStatus.ResourceMeta.Group, Version: resourceStatus.ResourceMeta.Version, Resource: resourceStatus.ResourceMeta.Resource}
if len(gvr.Resource) == 0 || len(gvr.Version) == 0 || len(resourceStatus.ResourceMeta.Name) == 0 {
continue
}
appliedResources = append(appliedResources, workapiv1.AppliedManifestResourceMeta{
Group: resourceStatus.ResourceMeta.Group,
Version: resourceStatus.ResourceMeta.Version,
Resource: resourceStatus.ResourceMeta.Resource,
Namespace: resourceStatus.ResourceMeta.Namespace,
Name: resourceStatus.ResourceMeta.Name,
})
}
// sort applied resources
sort.SliceStable(appliedResources, func(i, j int) bool {
switch {
case appliedResources[i].Group != appliedResources[j].Group:
return appliedResources[i].Group < appliedResources[j].Group
case appliedResources[i].Version != appliedResources[j].Version:
return appliedResources[i].Version < appliedResources[j].Version
case appliedResources[i].Resource != appliedResources[j].Resource:
return appliedResources[i].Resource < appliedResources[j].Resource
case appliedResources[i].Namespace != appliedResources[j].Namespace:
return appliedResources[i].Namespace < appliedResources[j].Namespace
default:
return appliedResources[i].Name < appliedResources[j].Name
}
})
// no work to do if applied resources are not changed
if reflect.DeepEqual(manifestWork.Status.AppliedResources, appliedResources) {
return nil
}
// delete applied resources which are no longer maintained by manifest work
noLongerMaintainedResources := findUntrackedResources(manifestWork.Status.AppliedResources, appliedResources)
if errs := m.deleteAppliedResources(noLongerMaintainedResources); len(errs) != 0 {
return utilerrors.NewAggregate(errs)
}
// update work status with latest applied resources. if this conflicts, we'll simply try again later
// for retrying update without reassessing the status can cause overwriting of valid information.
manifestWork.Status.AppliedResources = appliedResources
_, err := m.manifestWorkClient.UpdateStatus(ctx, manifestWork, metav1.UpdateOptions{})
return err
}
// deleteAppliedResources deletes all applied resources in the given resource meta array.
func (m *StaleManifestDeletionController) deleteAppliedResources(resources []workapiv1.AppliedManifestResourceMeta) []error {
var errs []error
for _, resource := range resources {
gvr := schema.GroupVersionResource{Group: resource.Group, Version: resource.Version, Resource: resource.Resource}
err := m.spokeDynamicClient.Resource(gvr).Namespace(resource.Namespace).Delete(context.TODO(), resource.Name, metav1.DeleteOptions{})
switch {
case errors.IsNotFound(err):
// no-oop
case err != nil:
errs = append(errs, fmt.Errorf("Failed to delete resource %v with key %s/%s: %w", gvr, resource.Namespace, resource.Name, err))
continue
}
klog.V(2).Infof("Successfully delete resource %v with key %s/%s", gvr, resource.Namespace, resource.Name)
}
return errs
}
// findUntrackedResources returns applied resources which are no longer tracked by manifestwork
func findUntrackedResources(appliedResources, newAppliedResources []workapiv1.AppliedManifestResourceMeta) []workapiv1.AppliedManifestResourceMeta {
var untracked []workapiv1.AppliedManifestResourceMeta
resourceIndex := map[workapiv1.AppliedManifestResourceMeta]struct{}{}
for _, resource := range newAppliedResources {
resourceIndex[resource] = struct{}{}
}
for _, resource := range appliedResources {
if _, ok := resourceIndex[resource]; !ok {
untracked = append(untracked, resource)
}
}
return untracked
}

View File

@@ -0,0 +1,189 @@
package deletioncontroller
import (
"context"
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
fakeworkclient "github.com/open-cluster-management/api/client/work/clientset/versioned/fake"
workapiv1 "github.com/open-cluster-management/api/work/v1"
"github.com/open-cluster-management/work/pkg/spoke/spoketesting"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
fakedynamic "k8s.io/client-go/dynamic/fake"
clienttesting "k8s.io/client-go/testing"
"k8s.io/utils/diff"
)
func newAppliedResource(group, version, resource, namespace, name string) workapiv1.AppliedManifestResourceMeta {
return workapiv1.AppliedManifestResourceMeta{
Group: group,
Version: version,
Resource: resource,
Namespace: namespace,
Name: name,
}
}
func newManifest(group, version, resource, namespace, name string) workapiv1.ManifestCondition {
return workapiv1.ManifestCondition{
ResourceMeta: workapiv1.ManifestResourceMeta{
Group: group,
Version: version,
Resource: resource,
Namespace: namespace,
Name: name,
},
}
}
func TestGarbageCollection(t *testing.T) {
cases := []struct {
name string
appliedResources []workapiv1.AppliedManifestResourceMeta
manifests []workapiv1.ManifestCondition
validateManifestWorkActions func(t *testing.T, actions []clienttesting.Action)
validateDynamicActions func(t *testing.T, actions []clienttesting.Action)
}{
{
name: "skip when no applied resource changed",
appliedResources: []workapiv1.AppliedManifestResourceMeta{newAppliedResource("g1", "v1", "r1", "ns1", "n1")},
manifests: []workapiv1.ManifestCondition{newManifest("g1", "v1", "r1", "ns1", "n1")},
validateManifestWorkActions: func(t *testing.T, actions []clienttesting.Action) {
if len(actions) > 0 {
t.Fatal(spew.Sdump(actions))
}
},
validateDynamicActions: func(t *testing.T, actions []clienttesting.Action) {
if len(actions) > 0 {
t.Fatal(spew.Sdump(actions))
}
},
},
{
name: "delete untracked resources",
appliedResources: []workapiv1.AppliedManifestResourceMeta{
newAppliedResource("g1", "v1", "r1", "ns1", "n1"),
newAppliedResource("g2", "v2", "r2", "ns2", "n2"),
newAppliedResource("g3", "v3", "r3", "ns3", "n3"),
newAppliedResource("g4", "v4", "r4", "ns4", "n4"),
},
manifests: []workapiv1.ManifestCondition{
newManifest("g1", "v1", "r1", "ns1", "n1"),
newManifest("g2", "v2", "r2", "ns2", "n2"),
newManifest("g5", "v5", "r5", "ns5", "n5"),
newManifest("g6", "v6", "r6", "ns6", "n6"),
},
validateManifestWorkActions: func(t *testing.T, actions []clienttesting.Action) {
if len(actions) != 1 {
t.Fatal(spew.Sdump(actions))
}
work := actions[0].(clienttesting.UpdateAction).GetObject().(*workapiv1.ManifestWork)
if !reflect.DeepEqual(work.Status.AppliedResources, []workapiv1.AppliedManifestResourceMeta{
newAppliedResource("g1", "v1", "r1", "ns1", "n1"),
newAppliedResource("g2", "v2", "r2", "ns2", "n2"),
newAppliedResource("g5", "v5", "r5", "ns5", "n5"),
newAppliedResource("g6", "v6", "r6", "ns6", "n6"),
}) {
t.Fatal(spew.Sdump(actions))
}
},
validateDynamicActions: func(t *testing.T, actions []clienttesting.Action) {
if len(actions) != 2 {
t.Fatal(spew.Sdump(actions))
}
action := actions[0].(clienttesting.DeleteAction)
resource, namespace, name := action.GetResource(), action.GetNamespace(), action.GetName()
if !reflect.DeepEqual(resource, schema.GroupVersionResource{Group: "g3", Version: "v3", Resource: "r3"}) || namespace != "ns3" || name != "n3" {
t.Fatal(spew.Sdump(actions))
}
action = actions[1].(clienttesting.DeleteAction)
resource, namespace, name = action.GetResource(), action.GetNamespace(), action.GetName()
if !reflect.DeepEqual(resource, schema.GroupVersionResource{Group: "g4", Version: "v4", Resource: "r4"}) || namespace != "ns4" || name != "n4" {
t.Fatal(spew.Sdump(actions))
}
},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
testingWork, _ := spoketesting.NewManifestWork(0)
testingWork.Status.AppliedResources = c.appliedResources
testingWork.Status.ResourceStatus.Manifests = c.manifests
fakeDynamicClient := fakedynamic.NewSimpleDynamicClient(runtime.NewScheme())
fakeClient := fakeworkclient.NewSimpleClientset(testingWork)
controller := StaleManifestDeletionController{
manifestWorkClient: fakeClient.WorkV1().ManifestWorks(testingWork.Namespace),
spokeDynamicClient: fakeDynamicClient,
}
err := controller.syncManifestWork(context.TODO(), testingWork)
if err != nil {
t.Fatal(err)
}
c.validateManifestWorkActions(t, fakeClient.Actions())
c.validateDynamicActions(t, fakeDynamicClient.Actions())
})
}
}
func TestFindUntrackedResources(t *testing.T) {
cases := []struct {
name string
appliedResources []workapiv1.AppliedManifestResourceMeta
newAppliedResources []workapiv1.AppliedManifestResourceMeta
expectedUntrackedResources []workapiv1.AppliedManifestResourceMeta
}{
{
name: "no resource untracked",
appliedResources: nil,
newAppliedResources: []workapiv1.AppliedManifestResourceMeta{
newAppliedResource("g1", "v1", "r1", "ns1", "n1"),
},
expectedUntrackedResources: nil,
},
{
name: "some of original resources untracked",
appliedResources: []workapiv1.AppliedManifestResourceMeta{
newAppliedResource("g1", "v1", "r1", "ns1", "n1"),
newAppliedResource("g2", "v2", "r2", "ns2", "n2"),
},
newAppliedResources: []workapiv1.AppliedManifestResourceMeta{
newAppliedResource("g2", "v2", "r2", "ns2", "n2"),
newAppliedResource("g3", "v3", "r3", "ns3", "n3"),
},
expectedUntrackedResources: []workapiv1.AppliedManifestResourceMeta{
newAppliedResource("g1", "v1", "r1", "ns1", "n1"),
},
},
{
name: "all original resources untracked",
appliedResources: []workapiv1.AppliedManifestResourceMeta{
newAppliedResource("g1", "v1", "r1", "ns1", "n1"),
newAppliedResource("g2", "v2", "r2", "ns2", "n2"),
},
newAppliedResources: []workapiv1.AppliedManifestResourceMeta{
newAppliedResource("g3", "v3", "r3", "ns3", "n3"),
newAppliedResource("g4", "v4", "r4", "ns4", "n4"),
},
expectedUntrackedResources: []workapiv1.AppliedManifestResourceMeta{
newAppliedResource("g1", "v1", "r1", "ns1", "n1"),
newAppliedResource("g2", "v2", "r2", "ns2", "n2"),
},
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
actual := findUntrackedResources(c.appliedResources, c.newAppliedResources)
if !reflect.DeepEqual(actual, c.expectedUntrackedResources) {
t.Errorf(diff.ObjectDiff(actual, c.expectedUntrackedResources))
}
})
}
}

View File

@@ -86,8 +86,21 @@ func (m *FinalizeController) syncManifestWork(ctx context.Context, originalManif
return nil
}
var err error
// Work is deleting, we remove its related resources on spoke cluster
if errs := m.cleanupResourceOfWork(manifestWork); len(errs) != 0 {
remaining, errs := m.cleanupResourceOfWork(manifestWork)
if len(manifestWork.Status.AppliedResources) != len(remaining) {
// update the status of the manifest work accordingly
manifestWork.Status.AppliedResources = remaining
manifestWork, err = m.manifestWorkClient.UpdateStatus(ctx, manifestWork, metav1.UpdateOptions{})
if err != nil {
errs = append(errs, fmt.Errorf(
"Failed to update status of ManifestWork %s/%s: %w", manifestWork.Namespace, manifestWork.Name, err))
}
}
if len(errs) != 0 {
return utilerrors.NewAggregate(errs)
}
@@ -97,42 +110,38 @@ func (m *FinalizeController) syncManifestWork(ctx context.Context, originalManif
// compared with a case where this controller deletes it and another controller (or manifestwork) creates it.
removeFinalizer(manifestWork, manifestWorkFinalizer)
_, err := m.manifestWorkClient.Update(ctx, manifestWork, metav1.UpdateOptions{})
_, err = m.manifestWorkClient.Update(ctx, manifestWork, metav1.UpdateOptions{})
return err
}
func (m *FinalizeController) cleanupResourceOfWork(work *workapiv1.ManifestWork) []error {
func (m *FinalizeController) cleanupResourceOfWork(work *workapiv1.ManifestWork) ([]workapiv1.AppliedManifestResourceMeta, []error) {
klog.V(4).Infof("cleaning up %q", work.Name)
var remaining []workapiv1.AppliedManifestResourceMeta
errs := []error{}
// TODO this can later be based on a list of all resources created by this manifest work
// not just the resources currently managed. This overlaps with the need to remove resources we have created
// separate from the application of current resources.
for _, resourceStatus := range work.Status.ResourceStatus.Manifests {
gvr := schema.GroupVersionResource{Group: resourceStatus.ResourceMeta.Group, Version: resourceStatus.ResourceMeta.Version, Resource: resourceStatus.ResourceMeta.Resource}
if len(gvr.Resource) == 0 || len(gvr.Version) == 0 || len(resourceStatus.ResourceMeta.Name) == 0 {
// without a resource or version, the request cannot be constructed, so we must not have created this either
continue
}
// delete all applied resources which are still tracked by the manifest work
for _, appliedResource := range work.Status.AppliedResources {
gvr := schema.GroupVersionResource{Group: appliedResource.Group, Version: appliedResource.Version, Resource: appliedResource.Resource}
err := m.spokeDynamicClient.
Resource(gvr).
Namespace(resourceStatus.ResourceMeta.Namespace).
Delete(context.TODO(), resourceStatus.ResourceMeta.Name, metav1.DeleteOptions{})
Namespace(appliedResource.Namespace).
Delete(context.TODO(), appliedResource.Name, metav1.DeleteOptions{})
switch {
case errors.IsNotFound(err):
// no-oop
case err != nil:
remaining = append(remaining, appliedResource)
errs = append(errs, fmt.Errorf(
"Failed to delete resource %v with key %s/%s: %w",
gvr, resourceStatus.ResourceMeta.Namespace, resourceStatus.ResourceMeta.Name, err))
gvr, appliedResource.Namespace, appliedResource.Name, err))
continue
}
klog.Infof("Successfully delete resource %v with key %s/%s", gvr, resourceStatus.ResourceMeta.Namespace, resourceStatus.ResourceMeta.Name)
klog.Infof("Successfully delete resource %v with key %s/%s", gvr, appliedResource.Namespace, appliedResource.Name)
}
return errs
return remaining, errs
}
// removeFinalizer removes a finalizer from the list. It mutates its input.

View File

@@ -20,7 +20,7 @@ func TestFinalize(t *testing.T) {
cases := []struct {
name string
existingFinalizers []string
resourcesToRemove []workapiv1.ManifestResourceMeta
resourcesToRemove []workapiv1.AppliedManifestResourceMeta
terminated bool
validateManifestWorkActions func(t *testing.T, actions []clienttesting.Action)
@@ -59,19 +59,24 @@ func TestFinalize(t *testing.T) {
name: "delete resources",
terminated: true,
existingFinalizers: []string{"a", manifestWorkFinalizer, "b"},
resourcesToRemove: []workapiv1.ManifestResourceMeta{
resourcesToRemove: []workapiv1.AppliedManifestResourceMeta{
{Group: "g1", Version: "v1", Resource: "r1", Namespace: "", Name: "n1"},
{Group: "g2", Version: "v2", Resource: "r2", Namespace: "ns2", Name: "n2"},
{Group: "g3", Version: "v3", Resource: "r3", Namespace: "ns3", Name: "n3"},
{Group: "g4", Version: "v4", Resource: "r4", Namespace: "", Name: "n4"},
},
validateManifestWorkActions: func(t *testing.T, actions []clienttesting.Action) {
if len(actions) != 1 {
if len(actions) != 2 {
t.Fatal(spew.Sdump(actions))
}
work := actions[0].(clienttesting.UpdateAction).GetObject().(*workapiv1.ManifestWork)
if len(work.Status.AppliedResources) != 0 {
t.Fatal(spew.Sdump(actions[0]))
}
work = actions[1].(clienttesting.UpdateAction).GetObject().(*workapiv1.ManifestWork)
if !reflect.DeepEqual(work.Finalizers, []string{"a", "b"}) {
t.Fatal(spew.Sdump(actions))
t.Fatal(spew.Sdump(actions[1]))
}
},
validateDynamicActions: func(t *testing.T, actions []clienttesting.Action) {
@@ -112,7 +117,7 @@ func TestFinalize(t *testing.T) {
testingWork.DeletionTimestamp = &now
}
for _, curr := range c.resourcesToRemove {
testingWork.Status.ResourceStatus.Manifests = append(testingWork.Status.ResourceStatus.Manifests, workapiv1.ManifestCondition{ResourceMeta: curr})
testingWork.Status.AppliedResources = append(testingWork.Status.AppliedResources, curr)
}
fakeDynamicClient := fakedynamic.NewSimpleDynamicClient(runtime.NewScheme())

View File

@@ -4,9 +4,9 @@ import (
"context"
"time"
"github.com/open-cluster-management/work/pkg/spoke/controllers/manifestcontroller"
"github.com/open-cluster-management/work/pkg/spoke/controllers/deletioncontroller"
"github.com/open-cluster-management/work/pkg/spoke/controllers/finalizercontroller"
"github.com/open-cluster-management/work/pkg/spoke/controllers/manifestcontroller"
"github.com/openshift/library-go/pkg/controller/controllercmd"
"github.com/spf13/cobra"
@@ -105,9 +105,18 @@ func (o *WorkloadAgentOptions) RunWorkloadAgent(ctx context.Context, controllerC
workInformerFactory.Work().V1().ManifestWorks().Lister().ManifestWorks(o.SpokeClusterName),
)
staleManifestDeletionController := deletioncontroller.NewStaleManifestDeletionController(
controllerContext.EventRecorder,
spokeDynamicClient,
hubWorkClient.WorkV1().ManifestWorks(o.SpokeClusterName),
workInformerFactory.Work().V1().ManifestWorks(),
workInformerFactory.Work().V1().ManifestWorks().Lister().ManifestWorks(o.SpokeClusterName),
)
go workInformerFactory.Start(ctx.Done())
go addFinalizerController.Run(ctx, 1)
go finalizeController.Run(ctx, 1)
go staleManifestDeletionController.Run(ctx, 1)
go manifestWorkController.Run(ctx, 1)
<-ctx.Done()
return nil

View File

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

View File

@@ -28,10 +28,38 @@ var _ = math.Inf
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
func (m *AppliedManifestResourceMeta) Reset() { *m = AppliedManifestResourceMeta{} }
func (*AppliedManifestResourceMeta) ProtoMessage() {}
func (*AppliedManifestResourceMeta) Descriptor() ([]byte, []int) {
return fileDescriptor_97234883da270a20, []int{0}
}
func (m *AppliedManifestResourceMeta) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *AppliedManifestResourceMeta) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
func (m *AppliedManifestResourceMeta) XXX_Merge(src proto.Message) {
xxx_messageInfo_AppliedManifestResourceMeta.Merge(m, src)
}
func (m *AppliedManifestResourceMeta) XXX_Size() int {
return m.Size()
}
func (m *AppliedManifestResourceMeta) XXX_DiscardUnknown() {
xxx_messageInfo_AppliedManifestResourceMeta.DiscardUnknown(m)
}
var xxx_messageInfo_AppliedManifestResourceMeta proto.InternalMessageInfo
func (m *Manifest) Reset() { *m = Manifest{} }
func (*Manifest) ProtoMessage() {}
func (*Manifest) Descriptor() ([]byte, []int) {
return fileDescriptor_97234883da270a20, []int{0}
return fileDescriptor_97234883da270a20, []int{1}
}
func (m *Manifest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -59,7 +87,7 @@ var xxx_messageInfo_Manifest proto.InternalMessageInfo
func (m *ManifestCondition) Reset() { *m = ManifestCondition{} }
func (*ManifestCondition) ProtoMessage() {}
func (*ManifestCondition) Descriptor() ([]byte, []int) {
return fileDescriptor_97234883da270a20, []int{1}
return fileDescriptor_97234883da270a20, []int{2}
}
func (m *ManifestCondition) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -87,7 +115,7 @@ var xxx_messageInfo_ManifestCondition proto.InternalMessageInfo
func (m *ManifestResourceMeta) Reset() { *m = ManifestResourceMeta{} }
func (*ManifestResourceMeta) ProtoMessage() {}
func (*ManifestResourceMeta) Descriptor() ([]byte, []int) {
return fileDescriptor_97234883da270a20, []int{2}
return fileDescriptor_97234883da270a20, []int{3}
}
func (m *ManifestResourceMeta) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -115,7 +143,7 @@ var xxx_messageInfo_ManifestResourceMeta proto.InternalMessageInfo
func (m *ManifestResourceStatus) Reset() { *m = ManifestResourceStatus{} }
func (*ManifestResourceStatus) ProtoMessage() {}
func (*ManifestResourceStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_97234883da270a20, []int{3}
return fileDescriptor_97234883da270a20, []int{4}
}
func (m *ManifestResourceStatus) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -143,7 +171,7 @@ var xxx_messageInfo_ManifestResourceStatus proto.InternalMessageInfo
func (m *ManifestWork) Reset() { *m = ManifestWork{} }
func (*ManifestWork) ProtoMessage() {}
func (*ManifestWork) Descriptor() ([]byte, []int) {
return fileDescriptor_97234883da270a20, []int{4}
return fileDescriptor_97234883da270a20, []int{5}
}
func (m *ManifestWork) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -171,7 +199,7 @@ var xxx_messageInfo_ManifestWork proto.InternalMessageInfo
func (m *ManifestWorkList) Reset() { *m = ManifestWorkList{} }
func (*ManifestWorkList) ProtoMessage() {}
func (*ManifestWorkList) Descriptor() ([]byte, []int) {
return fileDescriptor_97234883da270a20, []int{5}
return fileDescriptor_97234883da270a20, []int{6}
}
func (m *ManifestWorkList) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -199,7 +227,7 @@ var xxx_messageInfo_ManifestWorkList proto.InternalMessageInfo
func (m *ManifestWorkSpec) Reset() { *m = ManifestWorkSpec{} }
func (*ManifestWorkSpec) ProtoMessage() {}
func (*ManifestWorkSpec) Descriptor() ([]byte, []int) {
return fileDescriptor_97234883da270a20, []int{6}
return fileDescriptor_97234883da270a20, []int{7}
}
func (m *ManifestWorkSpec) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -227,7 +255,7 @@ var xxx_messageInfo_ManifestWorkSpec proto.InternalMessageInfo
func (m *ManifestWorkStatus) Reset() { *m = ManifestWorkStatus{} }
func (*ManifestWorkStatus) ProtoMessage() {}
func (*ManifestWorkStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_97234883da270a20, []int{7}
return fileDescriptor_97234883da270a20, []int{8}
}
func (m *ManifestWorkStatus) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -255,7 +283,7 @@ var xxx_messageInfo_ManifestWorkStatus proto.InternalMessageInfo
func (m *ManifestsTemplate) Reset() { *m = ManifestsTemplate{} }
func (*ManifestsTemplate) ProtoMessage() {}
func (*ManifestsTemplate) Descriptor() ([]byte, []int) {
return fileDescriptor_97234883da270a20, []int{8}
return fileDescriptor_97234883da270a20, []int{9}
}
func (m *ManifestsTemplate) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -283,7 +311,7 @@ var xxx_messageInfo_ManifestsTemplate proto.InternalMessageInfo
func (m *StatusCondition) Reset() { *m = StatusCondition{} }
func (*StatusCondition) ProtoMessage() {}
func (*StatusCondition) Descriptor() ([]byte, []int) {
return fileDescriptor_97234883da270a20, []int{9}
return fileDescriptor_97234883da270a20, []int{10}
}
func (m *StatusCondition) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -309,6 +337,7 @@ func (m *StatusCondition) XXX_DiscardUnknown() {
var xxx_messageInfo_StatusCondition proto.InternalMessageInfo
func init() {
proto.RegisterType((*AppliedManifestResourceMeta)(nil), "github.com.open_cluster_management.api.work.v1.AppliedManifestResourceMeta")
proto.RegisterType((*Manifest)(nil), "github.com.open_cluster_management.api.work.v1.Manifest")
proto.RegisterType((*ManifestCondition)(nil), "github.com.open_cluster_management.api.work.v1.ManifestCondition")
proto.RegisterType((*ManifestResourceMeta)(nil), "github.com.open_cluster_management.api.work.v1.ManifestResourceMeta")
@@ -326,64 +355,117 @@ func init() {
}
var fileDescriptor_97234883da270a20 = []byte{
// 907 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4b, 0x6f, 0x1b, 0x45,
0x1c, 0xf7, 0x6e, 0xe3, 0xc4, 0x99, 0x98, 0xb4, 0x1d, 0x55, 0x95, 0x95, 0xc3, 0x26, 0x5a, 0x24,
0x14, 0x10, 0x99, 0x25, 0x11, 0x42, 0x3d, 0x20, 0x1e, 0x0b, 0x14, 0x21, 0x9a, 0x56, 0x9a, 0x46,
0x54, 0x42, 0x88, 0x32, 0x59, 0x4f, 0x37, 0x53, 0x7b, 0x67, 0x56, 0x33, 0x63, 0x97, 0x5c, 0x2a,
0x24, 0x24, 0xc4, 0x81, 0x03, 0xe2, 0xb3, 0xf0, 0x01, 0x38, 0xe6, 0x58, 0x89, 0x4b, 0x4f, 0x11,
0x31, 0xdf, 0x82, 0x13, 0x9a, 0xd9, 0xd9, 0x87, 0xed, 0x54, 0x4d, 0x1d, 0xa9, 0xa7, 0x64, 0xff,
0x8f, 0xdf, 0xef, 0xff, 0x1e, 0x83, 0x8f, 0x52, 0xa6, 0x8f, 0x46, 0x87, 0x28, 0x11, 0x59, 0x24,
0x72, 0xca, 0x77, 0x92, 0xe1, 0x48, 0x69, 0x2a, 0x77, 0x32, 0xc2, 0x49, 0x4a, 0x33, 0xca, 0x75,
0x44, 0x72, 0x16, 0x3d, 0x11, 0x72, 0x10, 0x8d, 0x77, 0xa3, 0x94, 0x72, 0x2a, 0x89, 0xa6, 0x7d,
0x94, 0x4b, 0xa1, 0x05, 0x44, 0xb5, 0x3f, 0x32, 0xfe, 0x0f, 0x9d, 0xff, 0xc3, 0xda, 0x1f, 0x91,
0x9c, 0x21, 0xe3, 0x8f, 0xc6, 0xbb, 0x1b, 0x3b, 0x0d, 0xbe, 0x54, 0xa4, 0x22, 0xb2, 0x30, 0x87,
0xa3, 0x47, 0xf6, 0xcb, 0x7e, 0xd8, 0xff, 0x0a, 0xf8, 0x8d, 0xf7, 0x07, 0xb7, 0x14, 0x62, 0xc2,
0x84, 0x90, 0x91, 0xe4, 0x88, 0x71, 0x2a, 0x8f, 0xa3, 0x7c, 0x90, 0x1a, 0x81, 0x8a, 0x32, 0xaa,
0xc9, 0x39, 0x41, 0x6d, 0x44, 0x2f, 0xf2, 0x92, 0x23, 0xae, 0x59, 0x46, 0xe7, 0x1c, 0x3e, 0x78,
0x99, 0x83, 0x4a, 0x8e, 0x68, 0x46, 0x66, 0xfd, 0x42, 0x05, 0x3a, 0xfb, 0x84, 0xb3, 0x47, 0x54,
0x69, 0x98, 0x82, 0xae, 0x24, 0x4f, 0xbe, 0xf8, 0x51, 0x53, 0xae, 0x98, 0xe0, 0x3d, 0x6f, 0xcb,
0xdb, 0x5e, 0xdb, 0xdb, 0x41, 0x05, 0x34, 0x6a, 0x42, 0xa3, 0x7c, 0x90, 0x22, 0x07, 0x8d, 0x70,
0xc3, 0x29, 0xbe, 0x71, 0x72, 0xba, 0xd9, 0x9a, 0x9c, 0x6e, 0x76, 0x9b, 0x52, 0x3c, 0x05, 0x1c,
0xfe, 0xea, 0x83, 0xeb, 0x25, 0xeb, 0x67, 0x82, 0xf7, 0x99, 0x66, 0x82, 0xc3, 0xa7, 0xa0, 0x2b,
0xa9, 0x12, 0x23, 0x99, 0xd0, 0x7d, 0xaa, 0x89, 0xa3, 0xff, 0xfc, 0x15, 0xfb, 0x83, 0x4a, 0x60,
0xdc, 0xc0, 0x6a, 0x44, 0xd5, 0x90, 0xe2, 0x29, 0x3e, 0xa8, 0x00, 0x48, 0xca, 0x60, 0x54, 0xcf,
0xdf, 0xba, 0xb2, 0xbd, 0xb6, 0xf7, 0xf1, 0xab, 0xb2, 0xdf, 0xd7, 0x44, 0x8f, 0x54, 0x95, 0x54,
0x0c, 0x1d, 0x31, 0xa8, 0x44, 0x0a, 0x37, 0x68, 0xc2, 0x3f, 0x7d, 0x70, 0xe3, 0xbc, 0x88, 0xe1,
0xdb, 0x60, 0x45, 0xc8, 0x3e, 0xe3, 0x64, 0x68, 0x0b, 0xd1, 0x8e, 0xaf, 0x3a, 0xa4, 0x95, 0x7b,
0x85, 0x18, 0x97, 0x7a, 0xf8, 0x26, 0x68, 0xa7, 0x52, 0x8c, 0xf2, 0x9e, 0xbf, 0xe5, 0x6d, 0xaf,
0xc6, 0x6f, 0x38, 0xc3, 0xf6, 0x97, 0x46, 0x88, 0x0b, 0x9d, 0xc1, 0x1b, 0x53, 0x69, 0xfb, 0x7a,
0xc5, 0x9a, 0x55, 0x78, 0xdf, 0x14, 0x62, 0x5c, 0xea, 0xe1, 0x16, 0x58, 0x1a, 0x30, 0xde, 0xef,
0x2d, 0x59, 0xbb, 0xae, 0xb3, 0x5b, 0xfa, 0x9a, 0xf1, 0x3e, 0xb6, 0x1a, 0xf8, 0x2e, 0xe8, 0x94,
0xa5, 0xeb, 0xb5, 0xad, 0xd5, 0x35, 0x67, 0xd5, 0x29, 0x93, 0xc0, 0x95, 0x85, 0xc1, 0xe3, 0x24,
0xa3, 0xbd, 0xe5, 0x69, 0xbc, 0xbb, 0x24, 0xa3, 0xd8, 0x6a, 0x60, 0x04, 0x56, 0xcd, 0x5f, 0x95,
0x93, 0x84, 0xf6, 0x56, 0xac, 0xd9, 0x75, 0x67, 0xb6, 0x7a, 0xb7, 0x54, 0xe0, 0xda, 0x26, 0xfc,
0xcd, 0x03, 0x37, 0x67, 0xcb, 0x56, 0x94, 0x1e, 0x4a, 0xb0, 0x9a, 0x39, 0x4d, 0xd9, 0xc5, 0x4f,
0x17, 0x9d, 0xa1, 0xba, 0x8f, 0x55, 0x38, 0xa5, 0x4a, 0xe1, 0x9a, 0x26, 0xfc, 0xcb, 0x07, 0xdd,
0x52, 0xf1, 0x40, 0xc8, 0x01, 0xfc, 0x01, 0x74, 0xcc, 0x6a, 0xf7, 0x49, 0x35, 0xc7, 0xef, 0xbd,
0x70, 0x8d, 0xcc, 0x21, 0x40, 0xc6, 0xda, 0x30, 0xdf, 0x3b, 0x7c, 0x4c, 0x13, 0x6d, 0x67, 0xb6,
0x1a, 0x9d, 0x5a, 0x86, 0x2b, 0x54, 0x78, 0x08, 0x96, 0x54, 0x4e, 0x13, 0xdb, 0xf3, 0xb5, 0xbd,
0x4f, 0x16, 0xcd, 0xd0, 0x44, 0x7b, 0x3f, 0xa7, 0x49, 0xdd, 0x16, 0xf3, 0x85, 0x2d, 0x36, 0x7c,
0x0c, 0x96, 0x95, 0x2d, 0xaa, 0x1d, 0x99, 0xb5, 0xbd, 0xf8, 0x52, 0x2c, 0x16, 0x29, 0x5e, 0x77,
0x3c, 0xcb, 0xc5, 0x37, 0x76, 0x0c, 0xe1, 0xdf, 0x1e, 0xb8, 0xd6, 0x34, 0xbf, 0xc3, 0x94, 0x86,
0xdf, 0xcd, 0x95, 0x11, 0x5d, 0xac, 0x8c, 0xc6, 0xdb, 0x16, 0xb1, 0x9a, 0xcb, 0x52, 0xd2, 0x28,
0x21, 0x01, 0x6d, 0xa6, 0x69, 0x56, 0x4e, 0xc9, 0x87, 0x97, 0xc9, 0xae, 0xde, 0xba, 0xaf, 0x0c,
0x24, 0x2e, 0x90, 0xc3, 0x9f, 0x67, 0xb2, 0x32, 0xc5, 0x85, 0x02, 0x74, 0x0c, 0xc4, 0x50, 0x90,
0xbe, 0xcb, 0x6a, 0xe1, 0x01, 0x55, 0x07, 0x34, 0xcb, 0x87, 0x44, 0xd3, 0x3a, 0xd1, 0x07, 0x0e,
0x1a, 0x57, 0x24, 0xe1, 0x1f, 0x3e, 0x80, 0xf3, 0xad, 0x98, 0x39, 0x78, 0xde, 0x6b, 0x39, 0x78,
0xf0, 0x17, 0x0f, 0xac, 0xcb, 0xa9, 0x8d, 0x75, 0x23, 0x7c, 0xfb, 0xb2, 0x87, 0xde, 0x0d, 0xd8,
0x4d, 0x17, 0xc0, 0xfa, 0xb4, 0x1c, 0xcf, 0xb0, 0x86, 0x4f, 0xeb, 0x37, 0xa8, 0xaa, 0x22, 0x64,
0xcd, 0xe3, 0x51, 0x54, 0xe4, 0xd6, 0xa2, 0x71, 0xbd, 0xe4, 0x66, 0x9c, 0xfa, 0xe0, 0xea, 0x4c,
0xf1, 0xcc, 0xa5, 0xd4, 0xc7, 0x39, 0xb5, 0x53, 0xd1, 0xb8, 0x94, 0x07, 0xc7, 0x39, 0xc5, 0x56,
0x03, 0xbf, 0xaf, 0x56, 0xb2, 0x38, 0xf6, 0xb7, 0xa7, 0xd7, 0xe9, 0xbf, 0xd3, 0xcd, 0x0b, 0xfd,
0xe0, 0x40, 0x15, 0xe7, 0xf4, 0x1a, 0xc2, 0x31, 0x80, 0x43, 0xa2, 0xf4, 0x81, 0x24, 0x5c, 0x59,
0xfd, 0x01, 0xcb, 0xa8, 0x5b, 0xff, 0x77, 0x2e, 0xb6, 0x7b, 0xc6, 0x23, 0xde, 0x70, 0x71, 0xc1,
0x3b, 0x73, 0x68, 0xf8, 0x1c, 0x06, 0xf8, 0x16, 0x58, 0x96, 0x94, 0x28, 0xc1, 0xdd, 0xab, 0x53,
0x9d, 0x09, 0x6c, 0xa5, 0xd8, 0x69, 0xcd, 0x33, 0x96, 0x51, 0xa5, 0x48, 0x5a, 0x3e, 0x3c, 0xd5,
0x33, 0xb6, 0x5f, 0x88, 0x71, 0xa9, 0x8f, 0xb7, 0x4f, 0xce, 0x82, 0xd6, 0xb3, 0xb3, 0xa0, 0xf5,
0xfc, 0x2c, 0x68, 0xfd, 0x34, 0x09, 0xbc, 0x93, 0x49, 0xe0, 0x3d, 0x9b, 0x04, 0xde, 0xf3, 0x49,
0xe0, 0xfd, 0x33, 0x09, 0xbc, 0xdf, 0xff, 0x0d, 0x5a, 0xdf, 0xfa, 0xe3, 0xdd, 0xff, 0x03, 0x00,
0x00, 0xff, 0xff, 0x49, 0x87, 0xf8, 0xee, 0x43, 0x0a, 0x00, 0x00,
// 978 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4d, 0x6f, 0x1b, 0x45,
0x18, 0xf6, 0x3a, 0x76, 0xe2, 0x4c, 0x4c, 0x9a, 0x8e, 0xaa, 0xca, 0x0a, 0xd2, 0x26, 0x5a, 0x24,
0x94, 0x22, 0x32, 0x4b, 0x22, 0x84, 0x7a, 0x40, 0x40, 0x0c, 0x14, 0xa1, 0x36, 0xad, 0x34, 0x8d,
0xa8, 0x84, 0x10, 0x65, 0xb2, 0x9e, 0x6e, 0xa6, 0xf6, 0xee, 0xac, 0x66, 0xc6, 0x2e, 0xb9, 0x54,
0x48, 0x48, 0x88, 0x03, 0x07, 0xf8, 0x13, 0xfc, 0x02, 0x7e, 0x00, 0xc7, 0x1c, 0x2b, 0x71, 0xe9,
0x29, 0x22, 0xe6, 0xce, 0x0f, 0xe0, 0x84, 0x66, 0x76, 0xf6, 0xc3, 0xeb, 0x94, 0x38, 0x8e, 0xc4,
0xc9, 0xde, 0xf7, 0xeb, 0x79, 0xe7, 0x79, 0x9f, 0x7d, 0x67, 0xc1, 0x07, 0x21, 0x53, 0x47, 0xc3,
0x43, 0x14, 0xf0, 0xc8, 0xe7, 0x09, 0x8d, 0xb7, 0x83, 0xc1, 0x50, 0x2a, 0x2a, 0xb6, 0x23, 0x12,
0x93, 0x90, 0x46, 0x34, 0x56, 0x3e, 0x49, 0x98, 0xff, 0x8c, 0x8b, 0xbe, 0x3f, 0xda, 0xf1, 0x43,
0x1a, 0x53, 0x41, 0x14, 0xed, 0xa1, 0x44, 0x70, 0xc5, 0x21, 0x2a, 0xf2, 0x91, 0xce, 0x7f, 0x6c,
0xf3, 0x1f, 0x17, 0xf9, 0x88, 0x24, 0x0c, 0xe9, 0x7c, 0x34, 0xda, 0x59, 0xdf, 0x2e, 0xe1, 0x85,
0x3c, 0xe4, 0xbe, 0x29, 0x73, 0x38, 0x7c, 0x62, 0x9e, 0xcc, 0x83, 0xf9, 0x97, 0x96, 0x5f, 0x7f,
0xb7, 0x7f, 0x5b, 0x22, 0xc6, 0x75, 0x0b, 0x11, 0x09, 0x8e, 0x58, 0x4c, 0xc5, 0xb1, 0x9f, 0xf4,
0x43, 0x6d, 0x90, 0x7e, 0x44, 0x15, 0x39, 0xa7, 0xa9, 0x75, 0xff, 0x55, 0x59, 0x62, 0x18, 0x2b,
0x16, 0xd1, 0xa9, 0x84, 0xf7, 0x2e, 0x4a, 0x90, 0xc1, 0x11, 0x8d, 0x48, 0x35, 0xcf, 0xfb, 0xdb,
0x01, 0xaf, 0xef, 0x25, 0xc9, 0x80, 0xd1, 0xde, 0x3e, 0x89, 0xd9, 0x13, 0x2a, 0x15, 0xa6, 0x92,
0x0f, 0x45, 0x40, 0xf7, 0xa9, 0x22, 0xf0, 0x0d, 0xd0, 0x0c, 0x05, 0x1f, 0x26, 0x1d, 0x67, 0xd3,
0xd9, 0x5a, 0xee, 0xbe, 0x76, 0x72, 0xba, 0x51, 0x1b, 0x9f, 0x6e, 0x34, 0x3f, 0xd3, 0x46, 0x9c,
0xfa, 0xe0, 0x2d, 0xb0, 0x34, 0xa2, 0x42, 0x32, 0x1e, 0x77, 0xea, 0x26, 0xec, 0x9a, 0x0d, 0x5b,
0xfa, 0x22, 0x35, 0xe3, 0xcc, 0x0f, 0xdf, 0x06, 0x2d, 0x61, 0xeb, 0x77, 0x16, 0x4c, 0xec, 0x9a,
0x8d, 0x6d, 0x65, 0xb8, 0x38, 0x8f, 0x80, 0x9b, 0xa0, 0x11, 0x93, 0x88, 0x76, 0x1a, 0x26, 0xb2,
0x6d, 0x23, 0x1b, 0xf7, 0x49, 0x44, 0xb1, 0xf1, 0x40, 0x1f, 0x2c, 0xeb, 0x5f, 0x99, 0x90, 0x80,
0x76, 0x9a, 0x26, 0xec, 0xba, 0x0d, 0x5b, 0xbe, 0x9f, 0x39, 0x70, 0x11, 0xe3, 0x49, 0xd0, 0xca,
0x0e, 0x0a, 0x43, 0xd0, 0x16, 0xe4, 0xd9, 0xa7, 0xdf, 0x2a, 0x1a, 0x9b, 0xe6, 0xf5, 0x19, 0x57,
0x76, 0xb7, 0x51, 0xca, 0x25, 0x2a, 0x73, 0x89, 0x92, 0x7e, 0x88, 0x2c, 0x97, 0x08, 0x97, 0x92,
0xba, 0x37, 0x2c, 0x5c, 0xbb, 0x6c, 0xc5, 0x13, 0x85, 0xbd, 0x1f, 0xeb, 0xe0, 0x7a, 0x86, 0xfa,
0x31, 0x8f, 0x7b, 0x4c, 0x69, 0x2e, 0x9e, 0x83, 0xb6, 0x28, 0x71, 0x6d, 0xe1, 0x3f, 0xb9, 0xa4,
0x20, 0xd1, 0x79, 0x73, 0x2b, 0x75, 0x55, 0xb2, 0xe2, 0x09, 0x3c, 0x28, 0x01, 0x08, 0xb2, 0x66,
0x64, 0xa7, 0xbe, 0xb9, 0xb0, 0xb5, 0xb2, 0xfb, 0xe1, 0x65, 0xd1, 0x1f, 0x2a, 0xa2, 0x86, 0x32,
0x3f, 0x54, 0x17, 0x5a, 0x60, 0x90, 0x9b, 0x24, 0x2e, 0xc1, 0x78, 0xbf, 0xd5, 0xc1, 0x8d, 0x73,
0x95, 0x76, 0x0b, 0x2c, 0x71, 0xd1, 0x63, 0x31, 0x19, 0x18, 0x22, 0x9a, 0x85, 0x88, 0x1e, 0xa4,
0x66, 0x9c, 0xf9, 0x0b, 0x51, 0xd6, 0x67, 0x13, 0xe5, 0xc2, 0x05, 0xa2, 0xdc, 0x04, 0x8d, 0x3e,
0x8b, 0x7b, 0x55, 0x99, 0xdd, 0x65, 0x71, 0x0f, 0x1b, 0xcf, 0x84, 0x6c, 0x9b, 0x33, 0xcb, 0x76,
0x71, 0x36, 0xd9, 0x2e, 0xcd, 0x20, 0xdb, 0x9f, 0x1c, 0x70, 0xb3, 0x4a, 0x5b, 0x4a, 0x3d, 0x14,
0x60, 0x39, 0xb2, 0x9e, 0x6c, 0x8a, 0x7b, 0xf3, 0x6a, 0xa8, 0x98, 0x63, 0xde, 0x4e, 0xe6, 0x92,
0xb8, 0x80, 0xf1, 0x7e, 0xaf, 0x83, 0x76, 0xe6, 0x78, 0xc4, 0x45, 0x1f, 0x7e, 0x03, 0x5a, 0x7a,
0x97, 0xf5, 0x48, 0xae, 0xe3, 0x77, 0x5e, 0xf9, 0x1a, 0xe9, 0xcd, 0x87, 0x74, 0xb4, 0x46, 0x7e,
0x70, 0xf8, 0x94, 0x06, 0xca, 0x68, 0x36, 0x97, 0x4e, 0x61, 0xc3, 0x79, 0x55, 0x78, 0x08, 0x1a,
0x32, 0xa1, 0x81, 0x99, 0xf9, 0xca, 0xee, 0x47, 0xf3, 0x9e, 0x50, 0x77, 0xfb, 0x30, 0xa1, 0x41,
0x31, 0x16, 0xfd, 0x84, 0x4d, 0x6d, 0xf8, 0x14, 0x2c, 0x4a, 0x43, 0xaa, 0x91, 0xcc, 0xca, 0x6e,
0xf7, 0x4a, 0x28, 0xa6, 0x52, 0x77, 0xd5, 0xe2, 0x2c, 0xa6, 0xcf, 0xd8, 0x22, 0x78, 0x7f, 0x38,
0x60, 0xad, 0x1c, 0x7e, 0x8f, 0x49, 0x05, 0xbf, 0x9a, 0xa2, 0x11, 0xcd, 0x46, 0xa3, 0xce, 0x36,
0x24, 0xe6, 0xba, 0xcc, 0x2c, 0x25, 0x0a, 0x09, 0x68, 0x32, 0x45, 0xa3, 0x4c, 0x25, 0xef, 0x5f,
0xe5, 0x74, 0xc5, 0x5b, 0xf7, 0xb9, 0x2e, 0x89, 0xd3, 0xca, 0xde, 0xf7, 0x95, 0x53, 0x69, 0x72,
0x21, 0x07, 0x2d, 0x5d, 0x62, 0xc0, 0x49, 0xcf, 0x9e, 0x6a, 0x6e, 0x81, 0xca, 0x03, 0x1a, 0x25,
0x03, 0xa2, 0x68, 0x71, 0xd0, 0x47, 0xb6, 0x34, 0xce, 0x41, 0xbc, 0x5f, 0x17, 0x00, 0x9c, 0x1e,
0x45, 0x65, 0xe1, 0x39, 0xff, 0xcb, 0xc2, 0x83, 0x3f, 0x38, 0x60, 0x55, 0x4c, 0xbc, 0xb1, 0x56,
0xc2, 0x77, 0xae, 0xba, 0xe8, 0xad, 0xc0, 0x6e, 0xda, 0x06, 0x56, 0x27, 0xed, 0xb8, 0x82, 0x0a,
0x7f, 0x71, 0xc0, 0x1a, 0x49, 0xaf, 0xfa, 0x2c, 0x52, 0xeb, 0x5c, 0x93, 0x70, 0xf7, 0xb2, 0xad,
0xfc, 0xc7, 0x27, 0x43, 0xb7, 0x63, 0xfb, 0x59, 0xdb, 0xab, 0x80, 0xe1, 0x29, 0x78, 0xef, 0x79,
0x71, 0x2f, 0xe6, 0x93, 0x85, 0xac, 0xbc, 0xd0, 0xd2, 0x29, 0xdd, 0x9e, 0x97, 0xab, 0x0b, 0xf6,
0xd8, 0x69, 0x1d, 0x5c, 0xab, 0x0c, 0x54, 0x6f, 0x6f, 0x75, 0x9c, 0x50, 0xfb, 0xc5, 0x93, 0xaf,
0x89, 0x83, 0xe3, 0x84, 0x62, 0xe3, 0x81, 0x5f, 0xe7, 0x6b, 0x22, 0xbd, 0x80, 0xee, 0x4c, 0xbe,
0xe2, 0xff, 0x9c, 0x6e, 0xcc, 0xf4, 0xd5, 0x87, 0x72, 0xcc, 0xc9, 0xd5, 0x00, 0x47, 0x00, 0x0e,
0x88, 0x54, 0x07, 0x82, 0xc4, 0xd2, 0xf8, 0x0f, 0x58, 0x44, 0xed, 0x4a, 0x7a, 0x6b, 0xb6, 0x7d,
0xa0, 0x33, 0xba, 0xeb, 0xb6, 0x2f, 0x78, 0x6f, 0xaa, 0x1a, 0x3e, 0x07, 0x01, 0xbe, 0x09, 0x16,
0x05, 0x25, 0x92, 0xc7, 0xf6, 0x26, 0xcc, 0x57, 0x17, 0x36, 0x56, 0x6c, 0xbd, 0xfa, 0x6a, 0x8d,
0xa8, 0x94, 0x24, 0xcc, 0x2e, 0xc3, 0xfc, 0x6a, 0xdd, 0x4f, 0xcd, 0x38, 0xf3, 0x77, 0xb7, 0x4e,
0xce, 0xdc, 0xda, 0x8b, 0x33, 0xb7, 0xf6, 0xf2, 0xcc, 0xad, 0x7d, 0x37, 0x76, 0x9d, 0x93, 0xb1,
0xeb, 0xbc, 0x18, 0xbb, 0xce, 0xcb, 0xb1, 0xeb, 0xfc, 0x39, 0x76, 0x9d, 0x9f, 0xff, 0x72, 0x6b,
0x5f, 0xd6, 0x47, 0x3b, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xad, 0x67, 0xe2, 0xf0, 0xc8, 0x0b,
0x00, 0x00,
}
func (m *AppliedManifestResourceMeta) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *AppliedManifestResourceMeta) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *AppliedManifestResourceMeta) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
i -= len(m.Namespace)
copy(dAtA[i:], m.Namespace)
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Namespace)))
i--
dAtA[i] = 0x2a
i -= len(m.Name)
copy(dAtA[i:], m.Name)
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name)))
i--
dAtA[i] = 0x22
i -= len(m.Resource)
copy(dAtA[i:], m.Resource)
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Resource)))
i--
dAtA[i] = 0x1a
i -= len(m.Version)
copy(dAtA[i:], m.Version)
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Version)))
i--
dAtA[i] = 0x12
i -= len(m.Group)
copy(dAtA[i:], m.Group)
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Group)))
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func (m *Manifest) Marshal() (dAtA []byte, err error) {
@@ -712,6 +794,20 @@ func (m *ManifestWorkStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.AppliedResources) > 0 {
for iNdEx := len(m.AppliedResources) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.AppliedResources[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenerated(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x1a
}
}
{
size, err := m.ResourceStatus.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
@@ -840,6 +936,25 @@ func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
return base
}
func (m *AppliedManifestResourceMeta) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Group)
n += 1 + l + sovGenerated(uint64(l))
l = len(m.Version)
n += 1 + l + sovGenerated(uint64(l))
l = len(m.Resource)
n += 1 + l + sovGenerated(uint64(l))
l = len(m.Name)
n += 1 + l + sovGenerated(uint64(l))
l = len(m.Namespace)
n += 1 + l + sovGenerated(uint64(l))
return n
}
func (m *Manifest) Size() (n int) {
if m == nil {
return 0
@@ -962,6 +1077,12 @@ func (m *ManifestWorkStatus) Size() (n int) {
}
l = m.ResourceStatus.Size()
n += 1 + l + sovGenerated(uint64(l))
if len(m.AppliedResources) > 0 {
for _, e := range m.AppliedResources {
l = e.Size()
n += 1 + l + sovGenerated(uint64(l))
}
}
return n
}
@@ -1005,6 +1126,20 @@ func sovGenerated(x uint64) (n int) {
func sozGenerated(x uint64) (n int) {
return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (this *AppliedManifestResourceMeta) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&AppliedManifestResourceMeta{`,
`Group:` + fmt.Sprintf("%v", this.Group) + `,`,
`Version:` + fmt.Sprintf("%v", this.Version) + `,`,
`Resource:` + fmt.Sprintf("%v", this.Resource) + `,`,
`Name:` + fmt.Sprintf("%v", this.Name) + `,`,
`Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`,
`}`,
}, "")
return s
}
func (this *Manifest) String() string {
if this == nil {
return "nil"
@@ -1109,9 +1244,15 @@ func (this *ManifestWorkStatus) String() string {
repeatedStringForConditions += strings.Replace(strings.Replace(f.String(), "StatusCondition", "StatusCondition", 1), `&`, ``, 1) + ","
}
repeatedStringForConditions += "}"
repeatedStringForAppliedResources := "[]AppliedManifestResourceMeta{"
for _, f := range this.AppliedResources {
repeatedStringForAppliedResources += strings.Replace(strings.Replace(f.String(), "AppliedManifestResourceMeta", "AppliedManifestResourceMeta", 1), `&`, ``, 1) + ","
}
repeatedStringForAppliedResources += "}"
s := strings.Join([]string{`&ManifestWorkStatus{`,
`Conditions:` + repeatedStringForConditions + `,`,
`ResourceStatus:` + strings.Replace(strings.Replace(this.ResourceStatus.String(), "ManifestResourceStatus", "ManifestResourceStatus", 1), `&`, ``, 1) + `,`,
`AppliedResources:` + repeatedStringForAppliedResources + `,`,
`}`,
}, "")
return s
@@ -1153,6 +1294,219 @@ func valueToStringGenerated(v interface{}) string {
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("*%v", pv)
}
func (m *AppliedManifestResourceMeta) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: AppliedManifestResourceMeta: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: AppliedManifestResourceMeta: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Group", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGenerated
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Group = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGenerated
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Version = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Resource", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGenerated
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Resource = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGenerated
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Name = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGenerated
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Namespace = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthGenerated
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthGenerated
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *Manifest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
@@ -2164,6 +2518,40 @@ func (m *ManifestWorkStatus) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AppliedResources", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenerated
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AppliedResources = append(m.AppliedResources, AppliedManifestResourceMeta{})
if err := m.AppliedResources[len(m.AppliedResources)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])

View File

@@ -12,6 +12,31 @@ import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
// Package-wide variables from generator "generated".
option go_package = "v1";
// AppliedManifestResourceMeta represents the gvr, name and namespace of a resource.
// Since these resources have been created, they must have valid group, version, resource, namespace, and name.
message AppliedManifestResourceMeta {
// Group is the API Group of the kubernetes resource
// +required
optional string group = 1;
// Version is the version of the kubernetes resource
// +required
optional string version = 2;
// Resource is the resource name of the kubernetes resource
// +required
optional string resource = 3;
// Name is the name of the kubernetes resource
// +required
optional string name = 4;
// Name is the namespace of the kubernetes resource, empty string indicates
// it is a cluster scoped resource.
// +required
optional string namespace = 5;
}
// Manifest represents a resource to be deployed on spoke cluster
message Manifest {
// +kubebuilder:validation:EmbeddedResource
@@ -123,6 +148,15 @@ message ManifestWorkStatus {
// spoke cluster. The agent on spoke cluster syncs the condition from spoke to the hub.
// +optional
optional ManifestResourceStatus resourceStatus = 2;
// AppliedResources represents a list of resources defined within the manifestwork that are applied.
// Only resources with valid GroupVersionResource, namespace, and name are suitable.
// An item in this slice is deleted when there is no mapped manifest in manifestwork.Spec or by finalizer.
// The resource relating to the item will also be removed from spoke cluster.
// The deleted resource may still be present until the finalizers for that resource are finished.
// However, the resource will not be undeleted, so it can be removed from this list and eventual consistency is preserved.
// +optional
repeated AppliedManifestResourceMeta appliedResources = 3;
}
// ManifestsTemplate represents the manifest workload to be deployed on spoke cluster

View File

@@ -100,6 +100,31 @@ type ManifestResourceMeta struct {
Namespace string `json:"namespace" protobuf:"bytes,7,opt,name=namespace"`
}
// AppliedManifestResourceMeta represents the gvr, name and namespace of a resource.
// Since these resources have been created, they must have valid group, version, resource, namespace, and name.
type AppliedManifestResourceMeta struct {
// Group is the API Group of the kubernetes resource
// +required
Group string `json:"group" protobuf:"bytes,1,opt,name=group"`
// Version is the version of the kubernetes resource
// +required
Version string `json:"version" protobuf:"bytes,2,opt,name=version"`
// Resource is the resource name of the kubernetes resource
// +required
Resource string `json:"resource" protobuf:"bytes,3,opt,name=resource"`
// Name is the name of the kubernetes resource
// +required
Name string `json:"name" protobuf:"bytes,4,opt,name=name"`
// Name is the namespace of the kubernetes resource, empty string indicates
// it is a cluster scoped resource.
// +required
Namespace string `json:"namespace" protobuf:"bytes,5,opt,name=namespace"`
}
// ManifestWorkStatus represents the current status of spoke manifest workload
type ManifestWorkStatus struct {
// Conditions contains the different condition statuses for this work.
@@ -115,6 +140,15 @@ type ManifestWorkStatus struct {
// spoke cluster. The agent on spoke cluster syncs the condition from spoke to the hub.
// +optional
ResourceStatus ManifestResourceStatus `json:"resourceStatus,omitempty" protobuf:"bytes,2,rep,name=resourceStatus"`
// AppliedResources represents a list of resources defined within the manifestwork that are applied.
// Only resources with valid GroupVersionResource, namespace, and name are suitable.
// An item in this slice is deleted when there is no mapped manifest in manifestwork.Spec or by finalizer.
// The resource relating to the item will also be removed from spoke cluster.
// The deleted resource may still be present until the finalizers for that resource are finished.
// However, the resource will not be undeleted, so it can be removed from this list and eventual consistency is preserved.
// +optional
AppliedResources []AppliedManifestResourceMeta `json:"appliedResources,omitempty" protobuf:"bytes,3,rep,name=appliedResources"`
}
// ManifestResourceStatus represents the status of each resource in manifest work deployed on

View File

@@ -8,6 +8,22 @@ 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 *AppliedManifestResourceMeta) DeepCopyInto(out *AppliedManifestResourceMeta) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppliedManifestResourceMeta.
func (in *AppliedManifestResourceMeta) DeepCopy() *AppliedManifestResourceMeta {
if in == nil {
return nil
}
out := new(AppliedManifestResourceMeta)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Manifest) DeepCopyInto(out *Manifest) {
*out = *in
@@ -177,6 +193,11 @@ func (in *ManifestWorkStatus) DeepCopyInto(out *ManifestWorkStatus) {
}
}
in.ResourceStatus.DeepCopyInto(&out.ResourceStatus)
if in.AppliedResources != nil {
in, out := &in.AppliedResources, &out.AppliedResources
*out = make([]AppliedManifestResourceMeta, len(*in))
copy(*out, *in)
}
return
}

View File

@@ -11,6 +11,19 @@ package v1
// Those methods can be generated by using hack/update-swagger-docs.sh
// AUTO-GENERATED FUNCTIONS START HERE
var map_AppliedManifestResourceMeta = map[string]string{
"": "AppliedManifestResourceMeta represents the gvr, name and namespace of a resource. Since these resources have been created, they must have valid group, version, resource, namespace, and name.",
"group": "Group is the API Group of the kubernetes resource",
"version": "Version is the version of the kubernetes resource",
"resource": "Resource is the resource name of the kubernetes resource",
"name": "Name is the name of the kubernetes resource",
"namespace": "Name is the namespace of the kubernetes resource, empty string indicates it is a cluster scoped resource.",
}
func (AppliedManifestResourceMeta) SwaggerDoc() map[string]string {
return map_AppliedManifestResourceMeta
}
var map_Manifest = map[string]string{
"": "Manifest represents a resource to be deployed on spoke cluster",
}
@@ -83,9 +96,10 @@ func (ManifestWorkSpec) SwaggerDoc() map[string]string {
}
var map_ManifestWorkStatus = map[string]string{
"": "ManifestWorkStatus represents the current status of spoke manifest workload",
"conditions": "Conditions contains the different condition statuses for this work. Valid condition types are: 1. Applied represents workload in ManifestWork is applied successfully on spoke cluster. 2. Progressing represents workload in ManifestWork is being applied on spoke cluster. 3. Available represents workload in ManifestWork exists on the spoke cluster. 4. Degraded represents the current state of workload does not match the desired state for a certain period.",
"resourceStatus": "ResourceStatus represents the status of each resource in manifestwork deployed on spoke cluster. The agent on spoke cluster syncs the condition from spoke to the hub.",
"": "ManifestWorkStatus represents the current status of spoke manifest workload",
"conditions": "Conditions contains the different condition statuses for this work. Valid condition types are: 1. Applied represents workload in ManifestWork is applied successfully on spoke cluster. 2. Progressing represents workload in ManifestWork is being applied on spoke cluster. 3. Available represents workload in ManifestWork exists on the spoke cluster. 4. Degraded represents the current state of workload does not match the desired state for a certain period.",
"resourceStatus": "ResourceStatus represents the status of each resource in manifestwork deployed on spoke cluster. The agent on spoke cluster syncs the condition from spoke to the hub.",
"appliedResources": "AppliedResources represents a list of resources defined within the manifestwork that are applied. Only resources with valid GroupVersionResource, namespace, and name are suitable. An item in this slice is deleted when there is no mapped manifest in manifestwork.Spec or by finalizer. The resource relating to the item will also be removed from spoke cluster. The deleted resource may still be present until the finalizers for that resource are finished. However, the resource will not be undeleted, so it can be removed from this list and eventual consistency is preserved.",
}
func (ManifestWorkStatus) SwaggerDoc() map[string]string {

314
vendor/k8s.io/utils/diff/diff.go generated vendored Normal file
View File

@@ -0,0 +1,314 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package diff
import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"sort"
"strings"
"text/tabwriter"
"github.com/davecgh/go-spew/spew"
"k8s.io/utils/field"
)
// StringDiff diffs a and b and returns a human readable diff.
func StringDiff(a, b string) string {
ba := []byte(a)
bb := []byte(b)
out := []byte{}
i := 0
for ; i < len(ba) && i < len(bb); i++ {
if ba[i] != bb[i] {
break
}
out = append(out, ba[i])
}
out = append(out, []byte("\n\nA: ")...)
out = append(out, ba[i:]...)
out = append(out, []byte("\n\nB: ")...)
out = append(out, bb[i:]...)
out = append(out, []byte("\n\n")...)
return string(out)
}
// ObjectDiff writes the two objects out as JSON and prints out the identical part of
// the objects followed by the remaining part of 'a' and finally the remaining part of 'b'.
// For debugging tests.
func ObjectDiff(a, b interface{}) string {
ab, err := json.Marshal(a)
if err != nil {
panic(fmt.Sprintf("a: %v", err))
}
bb, err := json.Marshal(b)
if err != nil {
panic(fmt.Sprintf("b: %v", err))
}
return StringDiff(string(ab), string(bb))
}
// ObjectGoPrintDiff is like ObjectDiff, but uses go-spew to print the objects,
// which shows absolutely everything by recursing into every single pointer
// (go's %#v formatters OTOH stop at a certain point). This is needed when you
// can't figure out why reflect.DeepEqual is returning false and nothing is
// showing you differences. This will.
func ObjectGoPrintDiff(a, b interface{}) string {
s := spew.ConfigState{DisableMethods: true}
return StringDiff(
s.Sprintf("%#v", a),
s.Sprintf("%#v", b),
)
}
// ObjectReflectDiff returns a diff computed through reflection, without serializing to JSON.
func ObjectReflectDiff(a, b interface{}) string {
vA, vB := reflect.ValueOf(a), reflect.ValueOf(b)
if vA.Type() != vB.Type() {
return fmt.Sprintf("type A %T and type B %T do not match", a, b)
}
diffs := objectReflectDiff(field.NewPath("object"), vA, vB)
if len(diffs) == 0 {
return "<no diffs>"
}
out := []string{""}
for _, d := range diffs {
elidedA, elidedB := limit(d.a, d.b, 80)
out = append(out,
fmt.Sprintf("%s:", d.path),
fmt.Sprintf(" a: %s", elidedA),
fmt.Sprintf(" b: %s", elidedB),
)
}
return strings.Join(out, "\n")
}
// limit:
// 1. stringifies aObj and bObj
// 2. elides identical prefixes if either is too long
// 3. elides remaining content from the end if either is too long
func limit(aObj, bObj interface{}, max int) (string, string) {
elidedPrefix := ""
elidedASuffix := ""
elidedBSuffix := ""
a, b := fmt.Sprintf("%#v", aObj), fmt.Sprintf("%#v", bObj)
if aObj != nil && bObj != nil {
if aType, bType := fmt.Sprintf("%T", aObj), fmt.Sprintf("%T", bObj); aType != bType {
a = fmt.Sprintf("%s (%s)", a, aType)
b = fmt.Sprintf("%s (%s)", b, bType)
}
}
for {
switch {
case len(a) > max && len(a) > 4 && len(b) > 4 && a[:4] == b[:4]:
// a is too long, b has data, and the first several characters are the same
elidedPrefix = "..."
a = a[2:]
b = b[2:]
case len(b) > max && len(b) > 4 && len(a) > 4 && a[:4] == b[:4]:
// b is too long, a has data, and the first several characters are the same
elidedPrefix = "..."
a = a[2:]
b = b[2:]
case len(a) > max:
a = a[:max]
elidedASuffix = "..."
case len(b) > max:
b = b[:max]
elidedBSuffix = "..."
default:
// both are short enough
return elidedPrefix + a + elidedASuffix, elidedPrefix + b + elidedBSuffix
}
}
}
func public(s string) bool {
if len(s) == 0 {
return false
}
return s[:1] == strings.ToUpper(s[:1])
}
type diff struct {
path *field.Path
a, b interface{}
}
type orderedDiffs []diff
func (d orderedDiffs) Len() int { return len(d) }
func (d orderedDiffs) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
func (d orderedDiffs) Less(i, j int) bool {
a, b := d[i].path.String(), d[j].path.String()
if a < b {
return true
}
return false
}
func objectReflectDiff(path *field.Path, a, b reflect.Value) []diff {
switch a.Type().Kind() {
case reflect.Struct:
var changes []diff
for i := 0; i < a.Type().NumField(); i++ {
if !public(a.Type().Field(i).Name) {
if reflect.DeepEqual(a.Interface(), b.Interface()) {
continue
}
return []diff{{path: path, a: fmt.Sprintf("%#v", a), b: fmt.Sprintf("%#v", b)}}
}
if sub := objectReflectDiff(path.Child(a.Type().Field(i).Name), a.Field(i), b.Field(i)); len(sub) > 0 {
changes = append(changes, sub...)
}
}
return changes
case reflect.Ptr, reflect.Interface:
if a.IsNil() || b.IsNil() {
switch {
case a.IsNil() && b.IsNil():
return nil
case a.IsNil():
return []diff{{path: path, a: nil, b: b.Interface()}}
default:
return []diff{{path: path, a: a.Interface(), b: nil}}
}
}
return objectReflectDiff(path, a.Elem(), b.Elem())
case reflect.Chan:
if !reflect.DeepEqual(a.Interface(), b.Interface()) {
return []diff{{path: path, a: a.Interface(), b: b.Interface()}}
}
return nil
case reflect.Slice:
lA, lB := a.Len(), b.Len()
l := lA
if lB < lA {
l = lB
}
if lA == lB && lA == 0 {
if a.IsNil() != b.IsNil() {
return []diff{{path: path, a: a.Interface(), b: b.Interface()}}
}
return nil
}
var diffs []diff
for i := 0; i < l; i++ {
if !reflect.DeepEqual(a.Index(i), b.Index(i)) {
diffs = append(diffs, objectReflectDiff(path.Index(i), a.Index(i), b.Index(i))...)
}
}
for i := l; i < lA; i++ {
diffs = append(diffs, diff{path: path.Index(i), a: a.Index(i), b: nil})
}
for i := l; i < lB; i++ {
diffs = append(diffs, diff{path: path.Index(i), a: nil, b: b.Index(i)})
}
return diffs
case reflect.Map:
if reflect.DeepEqual(a.Interface(), b.Interface()) {
return nil
}
aKeys := make(map[interface{}]interface{})
for _, key := range a.MapKeys() {
aKeys[key.Interface()] = a.MapIndex(key).Interface()
}
var missing []diff
for _, key := range b.MapKeys() {
if _, ok := aKeys[key.Interface()]; ok {
delete(aKeys, key.Interface())
if reflect.DeepEqual(a.MapIndex(key).Interface(), b.MapIndex(key).Interface()) {
continue
}
missing = append(missing, objectReflectDiff(path.Key(fmt.Sprintf("%s", key.Interface())), a.MapIndex(key), b.MapIndex(key))...)
continue
}
missing = append(missing, diff{path: path.Key(fmt.Sprintf("%s", key.Interface())), a: nil, b: b.MapIndex(key).Interface()})
}
for key, value := range aKeys {
missing = append(missing, diff{path: path.Key(fmt.Sprintf("%s", key)), a: value, b: nil})
}
if len(missing) == 0 {
missing = append(missing, diff{path: path, a: a.Interface(), b: b.Interface()})
}
sort.Sort(orderedDiffs(missing))
return missing
default:
if reflect.DeepEqual(a.Interface(), b.Interface()) {
return nil
}
if !a.CanInterface() {
return []diff{{path: path, a: fmt.Sprintf("%#v", a), b: fmt.Sprintf("%#v", b)}}
}
return []diff{{path: path, a: a.Interface(), b: b.Interface()}}
}
}
// ObjectGoPrintSideBySide prints a and b as textual dumps side by side,
// enabling easy visual scanning for mismatches.
func ObjectGoPrintSideBySide(a, b interface{}) string {
s := spew.ConfigState{
Indent: " ",
// Extra deep spew.
DisableMethods: true,
}
sA := s.Sdump(a)
sB := s.Sdump(b)
linesA := strings.Split(sA, "\n")
linesB := strings.Split(sB, "\n")
width := 0
for _, s := range linesA {
l := len(s)
if l > width {
width = l
}
}
for _, s := range linesB {
l := len(s)
if l > width {
width = l
}
}
buf := &bytes.Buffer{}
w := tabwriter.NewWriter(buf, width, 0, 1, ' ', 0)
max := len(linesA)
if len(linesB) > max {
max = len(linesB)
}
for i := 0; i < max; i++ {
var a, b string
if i < len(linesA) {
a = linesA[i]
}
if i < len(linesB) {
b = linesB[i]
}
fmt.Fprintf(w, "%s\t%s\n", a, b)
}
w.Flush()
return buf.String()
}

91
vendor/k8s.io/utils/field/path.go generated vendored Normal file
View File

@@ -0,0 +1,91 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package field
import (
"bytes"
"fmt"
"strconv"
)
// Path represents the path from some root to a particular field.
type Path struct {
name string // the name of this field or "" if this is an index
index string // if name == "", this is a subscript (index or map key) of the previous element
parent *Path // nil if this is the root element
}
// NewPath creates a root Path object.
func NewPath(name string, moreNames ...string) *Path {
r := &Path{name: name, parent: nil}
for _, anotherName := range moreNames {
r = &Path{name: anotherName, parent: r}
}
return r
}
// Root returns the root element of this Path.
func (p *Path) Root() *Path {
for ; p.parent != nil; p = p.parent {
// Do nothing.
}
return p
}
// Child creates a new Path that is a child of the method receiver.
func (p *Path) Child(name string, moreNames ...string) *Path {
r := NewPath(name, moreNames...)
r.Root().parent = p
return r
}
// Index indicates that the previous Path is to be subscripted by an int.
// This sets the same underlying value as Key.
func (p *Path) Index(index int) *Path {
return &Path{index: strconv.Itoa(index), parent: p}
}
// Key indicates that the previous Path is to be subscripted by a string.
// This sets the same underlying value as Index.
func (p *Path) Key(key string) *Path {
return &Path{index: key, parent: p}
}
// String produces a string representation of the Path.
func (p *Path) String() string {
// make a slice to iterate
elems := []*Path{}
for ; p != nil; p = p.parent {
elems = append(elems, p)
}
// iterate, but it has to be backwards
buf := bytes.NewBuffer(nil)
for i := range elems {
p := elems[len(elems)-1-i]
if p.parent != nil && len(p.name) > 0 {
// This is either the root or it is a subscript.
buf.WriteString(".")
}
if len(p.name) > 0 {
buf.WriteString(p.name)
} else {
fmt.Fprintf(buf, "[%s]", p.index)
}
}
return buf.String()
}

4
vendor/modules.txt vendored
View File

@@ -130,7 +130,7 @@ github.com/onsi/gomega/matchers/support/goraph/edge
github.com/onsi/gomega/matchers/support/goraph/node
github.com/onsi/gomega/matchers/support/goraph/util
github.com/onsi/gomega/types
# github.com/open-cluster-management/api v0.0.0-20200512175145-bed9ce79e17e
# github.com/open-cluster-management/api v0.0.0-20200528225735-c85cec6fa5b0
github.com/open-cluster-management/api/client/work/clientset/versioned
github.com/open-cluster-management/api/client/work/clientset/versioned/fake
github.com/open-cluster-management/api/client/work/clientset/versioned/scheme
@@ -853,6 +853,8 @@ k8s.io/kube-openapi/pkg/util/proto
k8s.io/kubectl/pkg/scheme
# k8s.io/utils v0.0.0-20200327001022-6496210b90e8
k8s.io/utils/buffer
k8s.io/utils/diff
k8s.io/utils/field
k8s.io/utils/integer
k8s.io/utils/net
k8s.io/utils/path