mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-05-19 23:57:57 +00:00
Merge pull request #20 from elgnay/delete-untracked-resources
Delete untracked resources of manifest work
This commit is contained in:
3
go.mod
3
go.mod
@@ -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
4
go.sum
@@ -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=
|
||||
|
||||
168
pkg/spoke/controllers/deletioncontroller/deletion_controller.go
Normal file
168
pkg/spoke/controllers/deletioncontroller/deletion_controller.go
Normal 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
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
524
vendor/github.com/open-cluster-management/api/work/v1/generated.pb.go
generated
vendored
524
vendor/github.com/open-cluster-management/api/work/v1/generated.pb.go
generated
vendored
@@ -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:])
|
||||
|
||||
34
vendor/github.com/open-cluster-management/api/work/v1/generated.proto
generated
vendored
34
vendor/github.com/open-cluster-management/api/work/v1/generated.proto
generated
vendored
@@ -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
|
||||
|
||||
34
vendor/github.com/open-cluster-management/api/work/v1/types.go
generated
vendored
34
vendor/github.com/open-cluster-management/api/work/v1/types.go
generated
vendored
@@ -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
|
||||
|
||||
21
vendor/github.com/open-cluster-management/api/work/v1/zz_generated.deepcopy.go
generated
vendored
21
vendor/github.com/open-cluster-management/api/work/v1/zz_generated.deepcopy.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
314
vendor/k8s.io/utils/diff/diff.go
generated
vendored
Normal 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
91
vendor/k8s.io/utils/field/path.go
generated
vendored
Normal 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
4
vendor/modules.txt
vendored
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user