mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-08-27 00:37:20 +00:00
feat: Collect custom resources (#447)
* feat: Collect custom resources Co-authored-by: Martin Hrabovcin<mhrabovcin@users.noreply.github.com> Co-authored-by: Andrew Reed <andrew@replicated.com>
This commit is contained in:
co-authored by
Martin Hrabovcin
Andrew Reed
parent
111396eb39
commit
cf03503216
@@ -51,6 +51,7 @@ require (
|
||||
k8s.io/cli-runtime v0.20.2
|
||||
k8s.io/client-go v0.20.2
|
||||
sigs.k8s.io/controller-runtime v0.8.3
|
||||
sigs.k8s.io/controller-tools v0.7.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
|
||||
@@ -390,6 +390,8 @@ github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoM
|
||||
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
|
||||
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
|
||||
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
|
||||
github.com/gobuffalo/flect v0.2.3 h1:f/ZukRnSNA/DUpSNDadko7Qc0PhGvsew35p/2tu+CRY=
|
||||
github.com/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
|
||||
@@ -1664,6 +1666,8 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
|
||||
sigs.k8s.io/controller-tools v0.7.0 h1:iZIz1vEcavyEfxjcTLs1WH/MPf4vhPCtTKhoHqV8/G0=
|
||||
sigs.k8s.io/controller-tools v0.7.0/go.mod h1:bpBAo0VcSDDLuWt47evLhMLPxRPxMDInTEH/YbdeMK0=
|
||||
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
||||
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
||||
sigs.k8s.io/sig-storage-lib-external-provisioner v4.0.1+incompatible/go.mod h1:qhqLyNwJC49PoUalmtzYb4s9fT8HOMBTLbTY1QoVOqI=
|
||||
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
Copyright 2019 Replicated, Inc..
|
||||
|
||||
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.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeHostCollectors implements HostCollectorInterface
|
||||
type FakeHostCollectors struct {
|
||||
Fake *FakeTroubleshootV1beta2
|
||||
ns string
|
||||
}
|
||||
|
||||
var hostcollectorsResource = schema.GroupVersionResource{Group: "troubleshoot.sh", Version: "v1beta2", Resource: "hostcollectors"}
|
||||
|
||||
var hostcollectorsKind = schema.GroupVersionKind{Group: "troubleshoot.sh", Version: "v1beta2", Kind: "HostCollector"}
|
||||
|
||||
// Get takes name of the hostCollector, and returns the corresponding hostCollector object, and an error if there is any.
|
||||
func (c *FakeHostCollectors) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.HostCollector, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(hostcollectorsResource, c.ns, name), &v1beta2.HostCollector{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta2.HostCollector), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of HostCollectors that match those selectors.
|
||||
func (c *FakeHostCollectors) List(ctx context.Context, opts v1.ListOptions) (result *v1beta2.HostCollectorList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(hostcollectorsResource, hostcollectorsKind, c.ns, opts), &v1beta2.HostCollectorList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1beta2.HostCollectorList{ListMeta: obj.(*v1beta2.HostCollectorList).ListMeta}
|
||||
for _, item := range obj.(*v1beta2.HostCollectorList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested hostCollectors.
|
||||
func (c *FakeHostCollectors) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(hostcollectorsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a hostCollector and creates it. Returns the server's representation of the hostCollector, and an error, if there is any.
|
||||
func (c *FakeHostCollectors) Create(ctx context.Context, hostCollector *v1beta2.HostCollector, opts v1.CreateOptions) (result *v1beta2.HostCollector, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(hostcollectorsResource, c.ns, hostCollector), &v1beta2.HostCollector{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta2.HostCollector), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a hostCollector and updates it. Returns the server's representation of the hostCollector, and an error, if there is any.
|
||||
func (c *FakeHostCollectors) Update(ctx context.Context, hostCollector *v1beta2.HostCollector, opts v1.UpdateOptions) (result *v1beta2.HostCollector, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(hostcollectorsResource, c.ns, hostCollector), &v1beta2.HostCollector{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta2.HostCollector), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeHostCollectors) UpdateStatus(ctx context.Context, hostCollector *v1beta2.HostCollector, opts v1.UpdateOptions) (*v1beta2.HostCollector, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(hostcollectorsResource, "status", c.ns, hostCollector), &v1beta2.HostCollector{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta2.HostCollector), err
|
||||
}
|
||||
|
||||
// Delete takes name of the hostCollector and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeHostCollectors) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(hostcollectorsResource, c.ns, name), &v1beta2.HostCollector{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeHostCollectors) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(hostcollectorsResource, c.ns, listOpts)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1beta2.HostCollectorList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched hostCollector.
|
||||
func (c *FakeHostCollectors) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta2.HostCollector, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(hostcollectorsResource, c.ns, name, pt, data, subresources...), &v1beta2.HostCollector{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta2.HostCollector), err
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
Copyright 2019 Replicated, Inc..
|
||||
|
||||
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.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeRemoteCollectors implements RemoteCollectorInterface
|
||||
type FakeRemoteCollectors struct {
|
||||
Fake *FakeTroubleshootV1beta2
|
||||
ns string
|
||||
}
|
||||
|
||||
var remotecollectorsResource = schema.GroupVersionResource{Group: "troubleshoot.sh", Version: "v1beta2", Resource: "remotecollectors"}
|
||||
|
||||
var remotecollectorsKind = schema.GroupVersionKind{Group: "troubleshoot.sh", Version: "v1beta2", Kind: "RemoteCollector"}
|
||||
|
||||
// Get takes name of the remoteCollector, and returns the corresponding remoteCollector object, and an error if there is any.
|
||||
func (c *FakeRemoteCollectors) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.RemoteCollector, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(remotecollectorsResource, c.ns, name), &v1beta2.RemoteCollector{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta2.RemoteCollector), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of RemoteCollectors that match those selectors.
|
||||
func (c *FakeRemoteCollectors) List(ctx context.Context, opts v1.ListOptions) (result *v1beta2.RemoteCollectorList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(remotecollectorsResource, remotecollectorsKind, c.ns, opts), &v1beta2.RemoteCollectorList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1beta2.RemoteCollectorList{ListMeta: obj.(*v1beta2.RemoteCollectorList).ListMeta}
|
||||
for _, item := range obj.(*v1beta2.RemoteCollectorList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested remoteCollectors.
|
||||
func (c *FakeRemoteCollectors) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(remotecollectorsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a remoteCollector and creates it. Returns the server's representation of the remoteCollector, and an error, if there is any.
|
||||
func (c *FakeRemoteCollectors) Create(ctx context.Context, remoteCollector *v1beta2.RemoteCollector, opts v1.CreateOptions) (result *v1beta2.RemoteCollector, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(remotecollectorsResource, c.ns, remoteCollector), &v1beta2.RemoteCollector{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta2.RemoteCollector), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a remoteCollector and updates it. Returns the server's representation of the remoteCollector, and an error, if there is any.
|
||||
func (c *FakeRemoteCollectors) Update(ctx context.Context, remoteCollector *v1beta2.RemoteCollector, opts v1.UpdateOptions) (result *v1beta2.RemoteCollector, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(remotecollectorsResource, c.ns, remoteCollector), &v1beta2.RemoteCollector{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta2.RemoteCollector), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeRemoteCollectors) UpdateStatus(ctx context.Context, remoteCollector *v1beta2.RemoteCollector, opts v1.UpdateOptions) (*v1beta2.RemoteCollector, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(remotecollectorsResource, "status", c.ns, remoteCollector), &v1beta2.RemoteCollector{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta2.RemoteCollector), err
|
||||
}
|
||||
|
||||
// Delete takes name of the remoteCollector and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeRemoteCollectors) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(remotecollectorsResource, c.ns, name), &v1beta2.RemoteCollector{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeRemoteCollectors) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(remotecollectorsResource, c.ns, listOpts)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1beta2.RemoteCollectorList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched remoteCollector.
|
||||
func (c *FakeRemoteCollectors) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta2.RemoteCollector, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(remotecollectorsResource, c.ns, name, pt, data, subresources...), &v1beta2.RemoteCollector{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta2.RemoteCollector), err
|
||||
}
|
||||
+8
@@ -35,6 +35,10 @@ func (c *FakeTroubleshootV1beta2) Collectors(namespace string) v1beta2.Collector
|
||||
return &FakeCollectors{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeTroubleshootV1beta2) HostCollectors(namespace string) v1beta2.HostCollectorInterface {
|
||||
return &FakeHostCollectors{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeTroubleshootV1beta2) HostPreflights(namespace string) v1beta2.HostPreflightInterface {
|
||||
return &FakeHostPreflights{c, namespace}
|
||||
}
|
||||
@@ -47,6 +51,10 @@ func (c *FakeTroubleshootV1beta2) Redactors(namespace string) v1beta2.RedactorIn
|
||||
return &FakeRedactors{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeTroubleshootV1beta2) RemoteCollectors(namespace string) v1beta2.RemoteCollectorInterface {
|
||||
return &FakeRemoteCollectors{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeTroubleshootV1beta2) SupportBundles(namespace string) v1beta2.SupportBundleInterface {
|
||||
return &FakeSupportBundles{c, namespace}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,14 @@ type AnalyzerExpansion interface{}
|
||||
|
||||
type CollectorExpansion interface{}
|
||||
|
||||
type HostCollectorExpansion interface{}
|
||||
|
||||
type HostPreflightExpansion interface{}
|
||||
|
||||
type PreflightExpansion interface{}
|
||||
|
||||
type RedactorExpansion interface{}
|
||||
|
||||
type RemoteCollectorExpansion interface{}
|
||||
|
||||
type SupportBundleExpansion interface{}
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
Copyright 2019 Replicated, Inc..
|
||||
|
||||
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.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
scheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// HostCollectorsGetter has a method to return a HostCollectorInterface.
|
||||
// A group's client should implement this interface.
|
||||
type HostCollectorsGetter interface {
|
||||
HostCollectors(namespace string) HostCollectorInterface
|
||||
}
|
||||
|
||||
// HostCollectorInterface has methods to work with HostCollector resources.
|
||||
type HostCollectorInterface interface {
|
||||
Create(ctx context.Context, hostCollector *v1beta2.HostCollector, opts v1.CreateOptions) (*v1beta2.HostCollector, error)
|
||||
Update(ctx context.Context, hostCollector *v1beta2.HostCollector, opts v1.UpdateOptions) (*v1beta2.HostCollector, error)
|
||||
UpdateStatus(ctx context.Context, hostCollector *v1beta2.HostCollector, opts v1.UpdateOptions) (*v1beta2.HostCollector, error)
|
||||
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1beta2.HostCollector, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*v1beta2.HostCollectorList, error)
|
||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta2.HostCollector, err error)
|
||||
HostCollectorExpansion
|
||||
}
|
||||
|
||||
// hostCollectors implements HostCollectorInterface
|
||||
type hostCollectors struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
// newHostCollectors returns a HostCollectors
|
||||
func newHostCollectors(c *TroubleshootV1beta2Client, namespace string) *hostCollectors {
|
||||
return &hostCollectors{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the hostCollector, and returns the corresponding hostCollector object, and an error if there is any.
|
||||
func (c *hostCollectors) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.HostCollector, err error) {
|
||||
result = &v1beta2.HostCollector{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("hostcollectors").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of HostCollectors that match those selectors.
|
||||
func (c *hostCollectors) List(ctx context.Context, opts v1.ListOptions) (result *v1beta2.HostCollectorList, err error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
result = &v1beta2.HostCollectorList{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("hostcollectors").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested hostCollectors.
|
||||
func (c *hostCollectors) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("hostcollectors").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Watch(ctx)
|
||||
}
|
||||
|
||||
// Create takes the representation of a hostCollector and creates it. Returns the server's representation of the hostCollector, and an error, if there is any.
|
||||
func (c *hostCollectors) Create(ctx context.Context, hostCollector *v1beta2.HostCollector, opts v1.CreateOptions) (result *v1beta2.HostCollector, err error) {
|
||||
result = &v1beta2.HostCollector{}
|
||||
err = c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("hostcollectors").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(hostCollector).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a hostCollector and updates it. Returns the server's representation of the hostCollector, and an error, if there is any.
|
||||
func (c *hostCollectors) Update(ctx context.Context, hostCollector *v1beta2.HostCollector, opts v1.UpdateOptions) (result *v1beta2.HostCollector, err error) {
|
||||
result = &v1beta2.HostCollector{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("hostcollectors").
|
||||
Name(hostCollector.Name).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(hostCollector).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *hostCollectors) UpdateStatus(ctx context.Context, hostCollector *v1beta2.HostCollector, opts v1.UpdateOptions) (result *v1beta2.HostCollector, err error) {
|
||||
result = &v1beta2.HostCollector{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("hostcollectors").
|
||||
Name(hostCollector.Name).
|
||||
SubResource("status").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(hostCollector).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the hostCollector and deletes it. Returns an error if one occurs.
|
||||
func (c *hostCollectors) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("hostcollectors").
|
||||
Name(name).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *hostCollectors) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
var timeout time.Duration
|
||||
if listOpts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("hostcollectors").
|
||||
VersionedParams(&listOpts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched hostCollector.
|
||||
func (c *hostCollectors) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta2.HostCollector, err error) {
|
||||
result = &v1beta2.HostCollector{}
|
||||
err = c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("hostcollectors").
|
||||
Name(name).
|
||||
SubResource(subresources...).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(data).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
Copyright 2019 Replicated, Inc..
|
||||
|
||||
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.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
scheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// RemoteCollectorsGetter has a method to return a RemoteCollectorInterface.
|
||||
// A group's client should implement this interface.
|
||||
type RemoteCollectorsGetter interface {
|
||||
RemoteCollectors(namespace string) RemoteCollectorInterface
|
||||
}
|
||||
|
||||
// RemoteCollectorInterface has methods to work with RemoteCollector resources.
|
||||
type RemoteCollectorInterface interface {
|
||||
Create(ctx context.Context, remoteCollector *v1beta2.RemoteCollector, opts v1.CreateOptions) (*v1beta2.RemoteCollector, error)
|
||||
Update(ctx context.Context, remoteCollector *v1beta2.RemoteCollector, opts v1.UpdateOptions) (*v1beta2.RemoteCollector, error)
|
||||
UpdateStatus(ctx context.Context, remoteCollector *v1beta2.RemoteCollector, opts v1.UpdateOptions) (*v1beta2.RemoteCollector, error)
|
||||
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1beta2.RemoteCollector, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*v1beta2.RemoteCollectorList, error)
|
||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta2.RemoteCollector, err error)
|
||||
RemoteCollectorExpansion
|
||||
}
|
||||
|
||||
// remoteCollectors implements RemoteCollectorInterface
|
||||
type remoteCollectors struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
// newRemoteCollectors returns a RemoteCollectors
|
||||
func newRemoteCollectors(c *TroubleshootV1beta2Client, namespace string) *remoteCollectors {
|
||||
return &remoteCollectors{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the remoteCollector, and returns the corresponding remoteCollector object, and an error if there is any.
|
||||
func (c *remoteCollectors) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.RemoteCollector, err error) {
|
||||
result = &v1beta2.RemoteCollector{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("remotecollectors").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of RemoteCollectors that match those selectors.
|
||||
func (c *remoteCollectors) List(ctx context.Context, opts v1.ListOptions) (result *v1beta2.RemoteCollectorList, err error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
result = &v1beta2.RemoteCollectorList{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("remotecollectors").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested remoteCollectors.
|
||||
func (c *remoteCollectors) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("remotecollectors").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Watch(ctx)
|
||||
}
|
||||
|
||||
// Create takes the representation of a remoteCollector and creates it. Returns the server's representation of the remoteCollector, and an error, if there is any.
|
||||
func (c *remoteCollectors) Create(ctx context.Context, remoteCollector *v1beta2.RemoteCollector, opts v1.CreateOptions) (result *v1beta2.RemoteCollector, err error) {
|
||||
result = &v1beta2.RemoteCollector{}
|
||||
err = c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("remotecollectors").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(remoteCollector).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a remoteCollector and updates it. Returns the server's representation of the remoteCollector, and an error, if there is any.
|
||||
func (c *remoteCollectors) Update(ctx context.Context, remoteCollector *v1beta2.RemoteCollector, opts v1.UpdateOptions) (result *v1beta2.RemoteCollector, err error) {
|
||||
result = &v1beta2.RemoteCollector{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("remotecollectors").
|
||||
Name(remoteCollector.Name).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(remoteCollector).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *remoteCollectors) UpdateStatus(ctx context.Context, remoteCollector *v1beta2.RemoteCollector, opts v1.UpdateOptions) (result *v1beta2.RemoteCollector, err error) {
|
||||
result = &v1beta2.RemoteCollector{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("remotecollectors").
|
||||
Name(remoteCollector.Name).
|
||||
SubResource("status").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(remoteCollector).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the remoteCollector and deletes it. Returns an error if one occurs.
|
||||
func (c *remoteCollectors) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("remotecollectors").
|
||||
Name(name).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *remoteCollectors) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
var timeout time.Duration
|
||||
if listOpts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("remotecollectors").
|
||||
VersionedParams(&listOpts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched remoteCollector.
|
||||
func (c *remoteCollectors) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta2.RemoteCollector, err error) {
|
||||
result = &v1beta2.RemoteCollector{}
|
||||
err = c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("remotecollectors").
|
||||
Name(name).
|
||||
SubResource(subresources...).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(data).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
@@ -27,9 +27,11 @@ type TroubleshootV1beta2Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
AnalyzersGetter
|
||||
CollectorsGetter
|
||||
HostCollectorsGetter
|
||||
HostPreflightsGetter
|
||||
PreflightsGetter
|
||||
RedactorsGetter
|
||||
RemoteCollectorsGetter
|
||||
SupportBundlesGetter
|
||||
}
|
||||
|
||||
@@ -46,6 +48,10 @@ func (c *TroubleshootV1beta2Client) Collectors(namespace string) CollectorInterf
|
||||
return newCollectors(c, namespace)
|
||||
}
|
||||
|
||||
func (c *TroubleshootV1beta2Client) HostCollectors(namespace string) HostCollectorInterface {
|
||||
return newHostCollectors(c, namespace)
|
||||
}
|
||||
|
||||
func (c *TroubleshootV1beta2Client) HostPreflights(namespace string) HostPreflightInterface {
|
||||
return newHostPreflights(c, namespace)
|
||||
}
|
||||
@@ -58,6 +64,10 @@ func (c *TroubleshootV1beta2Client) Redactors(namespace string) RedactorInterfac
|
||||
return newRedactors(c, namespace)
|
||||
}
|
||||
|
||||
func (c *TroubleshootV1beta2Client) RemoteCollectors(namespace string) RemoteCollectorInterface {
|
||||
return newRemoteCollectors(c, namespace)
|
||||
}
|
||||
|
||||
func (c *TroubleshootV1beta2Client) SupportBundles(namespace string) SupportBundleInterface {
|
||||
return newSupportBundles(c, namespace)
|
||||
}
|
||||
|
||||
@@ -10,12 +10,18 @@ import (
|
||||
"strings"
|
||||
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"gopkg.in/yaml.v2"
|
||||
authorizationv1 "k8s.io/api/authorization/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
apiextensionsv1clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
|
||||
apiextensionsv1beta1clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
|
||||
@@ -28,6 +34,11 @@ func ClusterResources(c *Collector, clusterResourcesCollector *troubleshootv1bet
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dynamicClient, err := dynamic.NewForConfig(c.ClientConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
output := NewResult()
|
||||
|
||||
@@ -113,6 +124,13 @@ func ClusterResources(c *Collector, clusterResourcesCollector *troubleshootv1bet
|
||||
output.SaveResult(c.BundlePath, "cluster-resources/custom-resource-definitions.json", bytes.NewBuffer(customResourceDefinitions))
|
||||
output.SaveResult(c.BundlePath, "cluster-resources/custom-resource-definitions-errors.json", marshalErrors(crdErrors))
|
||||
|
||||
// crs
|
||||
customResources, crErrors := crs(ctx, dynamicClient, client, c.ClientConfig, namespaceNames)
|
||||
for k, v := range customResources {
|
||||
output.SaveResult(c.BundlePath, fmt.Sprintf("cluster-resources/custom-resources/%v", k), bytes.NewBuffer(v))
|
||||
}
|
||||
output.SaveResult(c.BundlePath, "cluster-resources/custom-resources/custom-resources-errors.json", marshalErrors(crErrors))
|
||||
|
||||
// imagepullsecrets
|
||||
imagePullSecrets, pullSecretsErrors := imagePullSecrets(ctx, client, namespaceNames)
|
||||
for k, v := range imagePullSecrets {
|
||||
@@ -502,6 +520,216 @@ func crdsV1beta(ctx context.Context, config *rest.Config) ([]byte, []string) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func crs(ctx context.Context, dyn dynamic.Interface, client *kubernetes.Clientset, config *rest.Config, namespaces []string) (map[string][]byte, map[string]string) {
|
||||
ok, err := discovery.HasResource(client, "apiextensions.k8s.io/v1", "CustomResourceDefinition")
|
||||
if err != nil {
|
||||
return nil, map[string]string{"discover apiextensions.k8s.io/v1": err.Error()}
|
||||
}
|
||||
if ok {
|
||||
return crsV1(ctx, dyn, config, namespaces)
|
||||
}
|
||||
|
||||
return crsV1beta(ctx, dyn, config, namespaces)
|
||||
}
|
||||
|
||||
func crsV1(ctx context.Context, client dynamic.Interface, config *rest.Config, namespaces []string) (map[string][]byte, map[string]string) {
|
||||
customResources := make(map[string][]byte)
|
||||
errorList := make(map[string]string)
|
||||
|
||||
crdClient, err := apiextensionsv1clientset.NewForConfig(config)
|
||||
if err != nil {
|
||||
errorList["crdClient"] = err.Error()
|
||||
return customResources, errorList
|
||||
}
|
||||
|
||||
crds, err := crdClient.CustomResourceDefinitions().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
errorList["crdList"] = err.Error()
|
||||
return customResources, errorList
|
||||
}
|
||||
|
||||
metaAccessor := meta.NewAccessor()
|
||||
|
||||
// Loop through CRDs to fetch the CRs
|
||||
for _, crd := range crds.Items {
|
||||
// A resource that contains '/' is a subresource type and it has no
|
||||
// object instances
|
||||
if strings.ContainsAny(crd.Name, "/") {
|
||||
continue
|
||||
}
|
||||
|
||||
var version string
|
||||
if len(crd.Spec.Versions) > 0 {
|
||||
version = crd.Spec.Versions[0].Name
|
||||
}
|
||||
gvr := schema.GroupVersionResource{
|
||||
Group: crd.Spec.Group,
|
||||
Version: version,
|
||||
Resource: crd.Spec.Names.Plural,
|
||||
}
|
||||
isNamespacedResource := crd.Spec.Scope == apiextensionsv1.NamespaceScoped
|
||||
|
||||
// Fetch all resources of given type
|
||||
customResourceList, err := client.Resource(gvr).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
errorList[crd.Name] = err.Error()
|
||||
continue
|
||||
}
|
||||
|
||||
if len(customResourceList.Items) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if !isNamespacedResource {
|
||||
objects := []map[string]interface{}{}
|
||||
for _, item := range customResourceList.Items {
|
||||
objects = append(objects, item.Object)
|
||||
}
|
||||
b, err := yaml.Marshal(objects)
|
||||
if err != nil {
|
||||
errorList[crd.Name] = err.Error()
|
||||
continue
|
||||
}
|
||||
customResources[fmt.Sprintf("%s.yaml", crd.Name)] = b
|
||||
} else {
|
||||
// Group fetched resources by the namespace
|
||||
perNamespace := map[string][]map[string]interface{}{}
|
||||
errors := []string{}
|
||||
|
||||
for _, item := range customResourceList.Items {
|
||||
ns, err := metaAccessor.Namespace(&item)
|
||||
if err != nil {
|
||||
errors = append(errors, err.Error())
|
||||
continue
|
||||
}
|
||||
if perNamespace[ns] == nil {
|
||||
perNamespace[ns] = []map[string]interface{}{}
|
||||
}
|
||||
perNamespace[ns] = append(perNamespace[ns], item.Object)
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
errorList[crd.Name] = strings.Join(errors, "\n")
|
||||
}
|
||||
|
||||
// Only include resources from requested namespaces
|
||||
for _, ns := range namespaces {
|
||||
if len(perNamespace[ns]) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
namespacedName := fmt.Sprintf("%s/%s", crd.Name, ns)
|
||||
b, err := yaml.Marshal(perNamespace[ns])
|
||||
if err != nil {
|
||||
errorList[namespacedName] = err.Error()
|
||||
continue
|
||||
}
|
||||
|
||||
customResources[fmt.Sprintf("%s.yaml", namespacedName)] = b
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return customResources, errorList
|
||||
}
|
||||
|
||||
func crsV1beta(ctx context.Context, client dynamic.Interface, config *rest.Config, namespaces []string) (map[string][]byte, map[string]string) {
|
||||
customResources := make(map[string][]byte)
|
||||
errorList := make(map[string]string)
|
||||
|
||||
crdClient, err := apiextensionsv1beta1clientset.NewForConfig(config)
|
||||
if err != nil {
|
||||
errorList["crdClient"] = err.Error()
|
||||
return customResources, errorList
|
||||
}
|
||||
|
||||
crds, err := crdClient.CustomResourceDefinitions().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
errorList["crdList"] = err.Error()
|
||||
return customResources, errorList
|
||||
}
|
||||
|
||||
metaAccessor := meta.NewAccessor()
|
||||
|
||||
// Loop through CRDs to fetch the CRs
|
||||
for _, crd := range crds.Items {
|
||||
// A resource that contains '/' is a subresource type and it has no
|
||||
// object instances
|
||||
if strings.ContainsAny(crd.Name, "/") {
|
||||
continue
|
||||
}
|
||||
|
||||
gvr := schema.GroupVersionResource{
|
||||
Group: crd.Spec.Group,
|
||||
Version: crd.Spec.Version,
|
||||
Resource: crd.Spec.Names.Plural,
|
||||
}
|
||||
isNamespacedResource := crd.Spec.Scope == apiextensionsv1beta1.NamespaceScoped
|
||||
|
||||
// Fetch all resources of given type
|
||||
customResourceList, err := client.Resource(gvr).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
errorList[crd.Name] = err.Error()
|
||||
continue
|
||||
}
|
||||
|
||||
if len(customResourceList.Items) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if !isNamespacedResource {
|
||||
objects := []map[string]interface{}{}
|
||||
for _, item := range customResourceList.Items {
|
||||
objects = append(objects, item.Object)
|
||||
}
|
||||
b, err := yaml.Marshal(customResourceList.Items)
|
||||
if err != nil {
|
||||
errorList[crd.Name] = err.Error()
|
||||
continue
|
||||
}
|
||||
customResources[fmt.Sprintf("%s.yaml", crd.Name)] = b
|
||||
} else {
|
||||
// Group fetched resources by the namespace
|
||||
perNamespace := map[string][]map[string]interface{}{}
|
||||
errors := []string{}
|
||||
|
||||
for _, item := range customResourceList.Items {
|
||||
ns, err := metaAccessor.Namespace(&item)
|
||||
if err != nil {
|
||||
errors = append(errors, err.Error())
|
||||
continue
|
||||
}
|
||||
if perNamespace[ns] == nil {
|
||||
perNamespace[ns] = []map[string]interface{}{}
|
||||
}
|
||||
perNamespace[ns] = append(perNamespace[ns], item.Object)
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
errorList[crd.Name] = strings.Join(errors, "\n")
|
||||
}
|
||||
|
||||
// Only include resources from requested namespaces
|
||||
for _, ns := range namespaces {
|
||||
if len(perNamespace[ns]) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
namespacedName := fmt.Sprintf("%s/%s", crd.Name, ns)
|
||||
b, err := yaml.Marshal(perNamespace[ns])
|
||||
if err != nil {
|
||||
errorList[namespacedName] = err.Error()
|
||||
continue
|
||||
}
|
||||
|
||||
customResources[fmt.Sprintf("%s.yaml", namespacedName)] = b
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return customResources, errorList
|
||||
}
|
||||
|
||||
func imagePullSecrets(ctx context.Context, client *kubernetes.Clientset, namespaces []string) (map[string][]byte, map[string]string) {
|
||||
imagePullSecrets := make(map[string][]byte)
|
||||
errors := make(map[string]string)
|
||||
|
||||
@@ -22,7 +22,7 @@ func literalString(matchString, path, name string) Redactor {
|
||||
}
|
||||
}
|
||||
|
||||
func (r literalRedactor) Redact(input io.Reader) io.Reader {
|
||||
func (r literalRedactor) Redact(input io.Reader, path string) io.Reader {
|
||||
out, writer := io.Pipe()
|
||||
|
||||
go func() {
|
||||
|
||||
@@ -28,7 +28,7 @@ func NewMultiLineRedactor(re1, re2, maskText, path, name string, isDefault bool)
|
||||
return &MultiLineRedactor{re1: compiled1, re2: compiled2, maskText: maskText, filePath: path, redactName: name, isDefault: isDefault}, nil
|
||||
}
|
||||
|
||||
func (r *MultiLineRedactor) Redact(input io.Reader) io.Reader {
|
||||
func (r *MultiLineRedactor) Redact(input io.Reader, path string) io.Reader {
|
||||
out, writer := io.Pipe()
|
||||
go func() {
|
||||
var err error
|
||||
|
||||
+36
-2
@@ -28,7 +28,7 @@ func init() {
|
||||
}
|
||||
|
||||
type Redactor interface {
|
||||
Redact(input io.Reader) io.Reader
|
||||
Redact(input io.Reader, path string) io.Reader
|
||||
}
|
||||
|
||||
// Redactions are indexed both by the file affected and by the name of the redactor
|
||||
@@ -59,7 +59,7 @@ func Redact(input io.Reader, path string, additionalRedactors []*troubleshootv1b
|
||||
|
||||
nextReader := input
|
||||
for _, r := range redactors {
|
||||
nextReader = r.Redact(nextReader)
|
||||
nextReader = r.Redact(nextReader, path)
|
||||
}
|
||||
|
||||
return nextReader, nil
|
||||
@@ -314,6 +314,40 @@ func getRedactors(path string) ([]Redactor, error) {
|
||||
redactors = append(redactors, r)
|
||||
}
|
||||
|
||||
customResources := []struct {
|
||||
resource string
|
||||
yamlPath string
|
||||
}{
|
||||
{
|
||||
resource: "installers.cluster.kurl.sh",
|
||||
yamlPath: "*.spec.kubernetes.bootstrapToken",
|
||||
},
|
||||
{
|
||||
resource: "installers.cluster.kurl.sh",
|
||||
yamlPath: "*.spec.kubernetes.certKey",
|
||||
},
|
||||
{
|
||||
resource: "installers.cluster.kurl.sh",
|
||||
yamlPath: "*.spec.kubernetes.kubeadmToken",
|
||||
},
|
||||
}
|
||||
|
||||
uniqueCRs := map[string]bool{}
|
||||
for _, cr := range customResources {
|
||||
fileglob := fmt.Sprintf("cluster-resources/custom-resources/%s/*", cr.resource)
|
||||
redactors = append(redactors, NewYamlRedactor(cr.yamlPath, fileglob, ""))
|
||||
|
||||
// redact kubectl last applied annotation once for each resource since it contains copies of
|
||||
// redacted fields
|
||||
if !uniqueCRs[cr.resource] {
|
||||
uniqueCRs[cr.resource] = true
|
||||
redactors = append(redactors, &YamlRedactor{
|
||||
filePath: fileglob,
|
||||
maskPath: []string{"*", "metadata", "annotations", "kubectl.kubernetes.io/last-applied-configuration"},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return redactors, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1637,7 +1637,7 @@ func Test_Redactors(t *testing.T) {
|
||||
|
||||
nextReader := io.Reader(strings.NewReader(original))
|
||||
for _, r := range redactors {
|
||||
nextReader = r.Redact(nextReader)
|
||||
nextReader = r.Redact(nextReader, "")
|
||||
}
|
||||
|
||||
redacted, err := ioutil.ReadAll(nextReader)
|
||||
|
||||
@@ -23,7 +23,7 @@ func NewSingleLineRedactor(re, maskText, path, name string, isDefault bool) (*Si
|
||||
return &SingleLineRedactor{re: compiled, maskText: maskText, filePath: path, redactName: name, isDefault: isDefault}, nil
|
||||
}
|
||||
|
||||
func (r *SingleLineRedactor) Redact(input io.Reader) io.Reader {
|
||||
func (r *SingleLineRedactor) Redact(input io.Reader, path string) io.Reader {
|
||||
out, writer := io.Pipe()
|
||||
|
||||
go func() {
|
||||
|
||||
@@ -104,10 +104,11 @@ func TestNewSingleLineRedactor(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
ResetRedactionList()
|
||||
reRunner, err := NewSingleLineRedactor(tt.re, MASK_TEXT, "testfile", tt.name, false)
|
||||
req.NoError(err)
|
||||
|
||||
outReader := reRunner.Redact(bytes.NewReader([]byte(tt.inputString)))
|
||||
outReader := reRunner.Redact(bytes.NewReader([]byte(tt.inputString)), "")
|
||||
gotBytes, err := ioutil.ReadAll(outReader)
|
||||
req.NoError(err)
|
||||
req.Equal(tt.wantString, string(gotBytes))
|
||||
|
||||
+13
-1
@@ -5,9 +5,11 @@ import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/pkg/logger"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
@@ -24,7 +26,17 @@ func NewYamlRedactor(yamlPath, filePath, name string) *YamlRedactor {
|
||||
return &YamlRedactor{maskPath: pathComponents, filePath: filePath, redactName: name}
|
||||
}
|
||||
|
||||
func (r *YamlRedactor) Redact(input io.Reader) io.Reader {
|
||||
func (r *YamlRedactor) Redact(input io.Reader, path string) io.Reader {
|
||||
if r.filePath != "" {
|
||||
match, err := filepath.Match(r.filePath, path)
|
||||
if err != nil {
|
||||
logger.Printf("Failed to match %q and %q: %v", r.filePath, path, err)
|
||||
return input
|
||||
}
|
||||
if !match {
|
||||
return input
|
||||
}
|
||||
}
|
||||
reader, writer := io.Pipe()
|
||||
go func() {
|
||||
var err error
|
||||
|
||||
@@ -294,7 +294,7 @@ xyz:
|
||||
req := require.New(t)
|
||||
yamlRunner := NewYamlRedactor(strings.Join(tt.path, "."), "testfile", tt.name)
|
||||
|
||||
outReader := yamlRunner.Redact(bytes.NewReader([]byte(tt.inputString)))
|
||||
outReader := yamlRunner.Redact(bytes.NewReader([]byte(tt.inputString)), "testfile")
|
||||
gotBytes, err := ioutil.ReadAll(outReader)
|
||||
req.NoError(err)
|
||||
req.Equal(tt.wantString, string(gotBytes))
|
||||
|
||||
Reference in New Issue
Block a user