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:
Rishabh Bohra
2021-10-21 16:49:59 -05:00
committed by GitHub
co-authored by Martin Hrabovcin Andrew Reed
parent 111396eb39
commit cf03503216
18 changed files with 981 additions and 9 deletions
+1
View File
@@ -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 (
+4
View File
@@ -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=
@@ -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
}
@@ -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
}
@@ -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)
}
+228
View File
@@ -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)
+1 -1
View File
@@ -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() {
+1 -1
View File
@@ -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
View File
@@ -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
}
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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() {
+2 -1
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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))