diff --git a/Makefile b/Makefile index 2588f3bf..92f4d321 100644 --- a/Makefile +++ b/Makefile @@ -158,6 +158,7 @@ generate: controller-gen client-gen --input-base github.com/replicatedhq/troubleshoot/pkg/apis \ --input troubleshoot/v1beta1 \ --input troubleshoot/v1beta2 \ + --input troubleshoot/v1beta3 \ --go-header-file ./hack/boilerplate.go.txt cp -r troubleshootclientset pkg/client rm -rf troubleshootclientset diff --git a/pkg/apis/troubleshoot/v1beta2/collector_shared.go b/pkg/apis/troubleshoot/v1beta2/collector_shared.go index d8e4bd74..e5dfda2c 100644 --- a/pkg/apis/troubleshoot/v1beta2/collector_shared.go +++ b/pkg/apis/troubleshoot/v1beta2/collector_shared.go @@ -318,37 +318,43 @@ type Etcd struct { Image string `json:"image" yaml:"image"` } +type SupportBundleMetadata struct { + CollectorMeta `json:",inline" yaml:",inline"` + Namespace string `json:"namespace" yaml:"namespace"` +} + type Collect struct { - ClusterInfo *ClusterInfo `json:"clusterInfo,omitempty" yaml:"clusterInfo,omitempty"` - ClusterResources *ClusterResources `json:"clusterResources,omitempty" yaml:"clusterResources,omitempty"` - Secret *Secret `json:"secret,omitempty" yaml:"secret,omitempty"` - CustomMetrics *CustomMetrics `json:"customMetrics,omitempty" yaml:"customMetrics,omitempty"` - ConfigMap *ConfigMap `json:"configMap,omitempty" yaml:"configMap,omitempty"` - Logs *Logs `json:"logs,omitempty" yaml:"logs,omitempty"` - Run *Run `json:"run,omitempty" yaml:"run,omitempty"` - RunPod *RunPod `json:"runPod,omitempty" yaml:"runPod,omitempty"` - RunDaemonSet *RunDaemonSet `json:"runDaemonSet,omitempty" yaml:"runDaemonSet,omitempty"` - Exec *Exec `json:"exec,omitempty" yaml:"exec,omitempty"` - Data *Data `json:"data,omitempty" yaml:"data,omitempty"` - Copy *Copy `json:"copy,omitempty" yaml:"copy,omitempty"` - CopyFromHost *CopyFromHost `json:"copyFromHost,omitempty" yaml:"copyFromHost,omitempty"` - HTTP *HTTP `json:"http,omitempty" yaml:"http,omitempty"` - Postgres *Database `json:"postgres,omitempty" yaml:"postgres,omitempty"` - Mssql *Database `json:"mssql,omitempty" yaml:"mssql,omitempty"` - Mysql *Database `json:"mysql,omitempty" yaml:"mysql,omitempty"` - Redis *Database `json:"redis,omitempty" yaml:"redis,omitempty"` - Collectd *Collectd `json:"collectd,omitempty" yaml:"collectd,omitempty"` - Ceph *Ceph `json:"ceph,omitempty" yaml:"ceph,omitempty"` - Longhorn *Longhorn `json:"longhorn,omitempty" yaml:"longhorn,omitempty"` - RegistryImages *RegistryImages `json:"registryImages,omitempty" yaml:"registryImages,omitempty"` - Sysctl *Sysctl `json:"sysctl,omitempty" yaml:"sysctl,omitempty"` - Certificates *Certificates `json:"certificates,omitempty" yaml:"certificates,omitempty"` - Helm *Helm `json:"helm,omitempty" yaml:"helm,omitempty"` - Goldpinger *Goldpinger `json:"goldpinger,omitempty" yaml:"goldpinger,omitempty"` - Sonobuoy *Sonobuoy `json:"sonobuoy,omitempty" yaml:"sonobuoy,omitempty"` - NodeMetrics *NodeMetrics `json:"nodeMetrics,omitempty" yaml:"nodeMetrics,omitempty"` - DNS *DNS `json:"dns,omitempty" yaml:"dns,omitempty"` - Etcd *Etcd `json:"etcd,omitempty" yaml:"etcd,omitempty"` + ClusterInfo *ClusterInfo `json:"clusterInfo,omitempty" yaml:"clusterInfo,omitempty"` + ClusterResources *ClusterResources `json:"clusterResources,omitempty" yaml:"clusterResources,omitempty"` + Secret *Secret `json:"secret,omitempty" yaml:"secret,omitempty"` + CustomMetrics *CustomMetrics `json:"customMetrics,omitempty" yaml:"customMetrics,omitempty"` + ConfigMap *ConfigMap `json:"configMap,omitempty" yaml:"configMap,omitempty"` + Logs *Logs `json:"logs,omitempty" yaml:"logs,omitempty"` + Run *Run `json:"run,omitempty" yaml:"run,omitempty"` + RunPod *RunPod `json:"runPod,omitempty" yaml:"runPod,omitempty"` + RunDaemonSet *RunDaemonSet `json:"runDaemonSet,omitempty" yaml:"runDaemonSet,omitempty"` + Exec *Exec `json:"exec,omitempty" yaml:"exec,omitempty"` + Data *Data `json:"data,omitempty" yaml:"data,omitempty"` + Copy *Copy `json:"copy,omitempty" yaml:"copy,omitempty"` + CopyFromHost *CopyFromHost `json:"copyFromHost,omitempty" yaml:"copyFromHost,omitempty"` + HTTP *HTTP `json:"http,omitempty" yaml:"http,omitempty"` + Postgres *Database `json:"postgres,omitempty" yaml:"postgres,omitempty"` + Mssql *Database `json:"mssql,omitempty" yaml:"mssql,omitempty"` + Mysql *Database `json:"mysql,omitempty" yaml:"mysql,omitempty"` + Redis *Database `json:"redis,omitempty" yaml:"redis,omitempty"` + Collectd *Collectd `json:"collectd,omitempty" yaml:"collectd,omitempty"` + Ceph *Ceph `json:"ceph,omitempty" yaml:"ceph,omitempty"` + Longhorn *Longhorn `json:"longhorn,omitempty" yaml:"longhorn,omitempty"` + RegistryImages *RegistryImages `json:"registryImages,omitempty" yaml:"registryImages,omitempty"` + Sysctl *Sysctl `json:"sysctl,omitempty" yaml:"sysctl,omitempty"` + Certificates *Certificates `json:"certificates,omitempty" yaml:"certificates,omitempty"` + Helm *Helm `json:"helm,omitempty" yaml:"helm,omitempty"` + Goldpinger *Goldpinger `json:"goldpinger,omitempty" yaml:"goldpinger,omitempty"` + Sonobuoy *Sonobuoy `json:"sonobuoy,omitempty" yaml:"sonobuoy,omitempty"` + NodeMetrics *NodeMetrics `json:"nodeMetrics,omitempty" yaml:"nodeMetrics,omitempty"` + DNS *DNS `json:"dns,omitempty" yaml:"dns,omitempty"` + Etcd *Etcd `json:"etcd,omitempty" yaml:"etcd,omitempty"` + SupportBundleMetadata *SupportBundleMetadata `json:"supportBundleMetadata,omitempty" yaml:"supportBundleMetadata,omitempty"` } func (c *Collect) AccessReviewSpecs(overrideNS string) []authorizationv1.SelfSubjectAccessReviewSpec { @@ -568,6 +574,19 @@ func (c *Collect) AccessReviewSpecs(overrideNS string) []authorizationv1.SelfSub }) } else if c.Sysctl != nil { // TODO + } else if c.SupportBundleMetadata != nil { + result = append(result, authorizationv1.SelfSubjectAccessReviewSpec{ + ResourceAttributes: &authorizationv1.ResourceAttributes{ + Namespace: pickNamespaceOrDefault(c.SupportBundleMetadata.Namespace, overrideNS), + Verb: "get", + Group: "", + Version: "", + Resource: "secrets", + Subresource: "", + Name: "replicated-support-metadata", + }, + NonResourceAttributes: nil, + }) } return result @@ -671,6 +690,10 @@ func (c *Collect) GetName() string { collector = "certificates" name = c.Certificates.CollectorName } + if c.SupportBundleMetadata != nil { + collector = "support-bundle-metadata" + name = c.SupportBundleMetadata.CollectorName + } if collector == "" { return "" diff --git a/pkg/apis/troubleshoot/v1beta2/zz_generated.deepcopy.go b/pkg/apis/troubleshoot/v1beta2/zz_generated.deepcopy.go index fc3bfaad..98ed2100 100644 --- a/pkg/apis/troubleshoot/v1beta2/zz_generated.deepcopy.go +++ b/pkg/apis/troubleshoot/v1beta2/zz_generated.deepcopy.go @@ -985,6 +985,11 @@ func (in *Collect) DeepCopyInto(out *Collect) { *out = new(Etcd) (*in).DeepCopyInto(*out) } + if in.SupportBundleMetadata != nil { + in, out := &in.SupportBundleMetadata, &out.SupportBundleMetadata + *out = new(SupportBundleMetadata) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Collect. @@ -4943,6 +4948,22 @@ func (in *SupportBundleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SupportBundleMetadata) DeepCopyInto(out *SupportBundleMetadata) { + *out = *in + in.CollectorMeta.DeepCopyInto(&out.CollectorMeta) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SupportBundleMetadata. +func (in *SupportBundleMetadata) DeepCopy() *SupportBundleMetadata { + if in == nil { + return nil + } + out := new(SupportBundleMetadata) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SupportBundleSpec) DeepCopyInto(out *SupportBundleSpec) { *out = *in diff --git a/pkg/client/troubleshootclientset/clientset.go b/pkg/client/troubleshootclientset/clientset.go index bf001de9..5b4bafd4 100644 --- a/pkg/client/troubleshootclientset/clientset.go +++ b/pkg/client/troubleshootclientset/clientset.go @@ -23,6 +23,7 @@ import ( troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta1" troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta2" + troubleshootv1beta3 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" @@ -32,6 +33,7 @@ type Interface interface { Discovery() discovery.DiscoveryInterface TroubleshootV1beta1() troubleshootv1beta1.TroubleshootV1beta1Interface TroubleshootV1beta2() troubleshootv1beta2.TroubleshootV1beta2Interface + TroubleshootV1beta3() troubleshootv1beta3.TroubleshootV1beta3Interface } // Clientset contains the clients for groups. @@ -39,6 +41,7 @@ type Clientset struct { *discovery.DiscoveryClient troubleshootV1beta1 *troubleshootv1beta1.TroubleshootV1beta1Client troubleshootV1beta2 *troubleshootv1beta2.TroubleshootV1beta2Client + troubleshootV1beta3 *troubleshootv1beta3.TroubleshootV1beta3Client } // TroubleshootV1beta1 retrieves the TroubleshootV1beta1Client @@ -51,6 +54,11 @@ func (c *Clientset) TroubleshootV1beta2() troubleshootv1beta2.TroubleshootV1beta return c.troubleshootV1beta2 } +// TroubleshootV1beta3 retrieves the TroubleshootV1beta3Client +func (c *Clientset) TroubleshootV1beta3() troubleshootv1beta3.TroubleshootV1beta3Interface { + return c.troubleshootV1beta3 +} + // Discovery retrieves the DiscoveryClient func (c *Clientset) Discovery() discovery.DiscoveryInterface { if c == nil { @@ -103,6 +111,10 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, if err != nil { return nil, err } + cs.troubleshootV1beta3, err = troubleshootv1beta3.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) if err != nil { @@ -126,6 +138,7 @@ func New(c rest.Interface) *Clientset { var cs Clientset cs.troubleshootV1beta1 = troubleshootv1beta1.New(c) cs.troubleshootV1beta2 = troubleshootv1beta2.New(c) + cs.troubleshootV1beta3 = troubleshootv1beta3.New(c) cs.DiscoveryClient = discovery.NewDiscoveryClient(c) return &cs diff --git a/pkg/client/troubleshootclientset/fake/clientset_generated.go b/pkg/client/troubleshootclientset/fake/clientset_generated.go index 0e4af614..9cd91352 100644 --- a/pkg/client/troubleshootclientset/fake/clientset_generated.go +++ b/pkg/client/troubleshootclientset/fake/clientset_generated.go @@ -23,6 +23,8 @@ import ( faketroubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta1/fake" troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta2" faketroubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta2/fake" + troubleshootv1beta3 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3" + faketroubleshootv1beta3 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/fake" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" @@ -98,3 +100,8 @@ func (c *Clientset) TroubleshootV1beta1() troubleshootv1beta1.TroubleshootV1beta func (c *Clientset) TroubleshootV1beta2() troubleshootv1beta2.TroubleshootV1beta2Interface { return &faketroubleshootv1beta2.FakeTroubleshootV1beta2{Fake: &c.Fake} } + +// TroubleshootV1beta3 retrieves the TroubleshootV1beta3Client +func (c *Clientset) TroubleshootV1beta3() troubleshootv1beta3.TroubleshootV1beta3Interface { + return &faketroubleshootv1beta3.FakeTroubleshootV1beta3{Fake: &c.Fake} +} diff --git a/pkg/client/troubleshootclientset/fake/register.go b/pkg/client/troubleshootclientset/fake/register.go index 8e4e1730..9f4ecbf1 100644 --- a/pkg/client/troubleshootclientset/fake/register.go +++ b/pkg/client/troubleshootclientset/fake/register.go @@ -20,6 +20,7 @@ package fake import ( troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2" + troubleshootv1beta3 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta3" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -33,6 +34,7 @@ var codecs = serializer.NewCodecFactory(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ troubleshootv1beta1.AddToScheme, troubleshootv1beta2.AddToScheme, + troubleshootv1beta3.AddToScheme, } // AddToScheme adds all types of this clientset into the given scheme. This allows composition diff --git a/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/doc.go b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/doc.go new file mode 100644 index 00000000..e5bd273a --- /dev/null +++ b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/doc.go @@ -0,0 +1,19 @@ +/* +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. + +// This package has the automatically generated typed clients. +package v1beta3 diff --git a/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/fake/doc.go b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/fake/doc.go new file mode 100644 index 00000000..0767328a --- /dev/null +++ b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/fake/doc.go @@ -0,0 +1,19 @@ +/* +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 has the automatically generated clients. +package fake diff --git a/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/fake/fake_supportbundle.go b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/fake/fake_supportbundle.go new file mode 100644 index 00000000..48dca9fb --- /dev/null +++ b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/fake/fake_supportbundle.go @@ -0,0 +1,51 @@ +/* +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 ( + v1beta3 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta3" + troubleshootv1beta3 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3" + gentype "k8s.io/client-go/gentype" +) + +// fakeSupportBundles implements SupportBundleInterface +type fakeSupportBundles struct { + *gentype.FakeClientWithList[*v1beta3.SupportBundle, *v1beta3.SupportBundleList] + Fake *FakeTroubleshootV1beta3 +} + +func newFakeSupportBundles(fake *FakeTroubleshootV1beta3, namespace string) troubleshootv1beta3.SupportBundleInterface { + return &fakeSupportBundles{ + gentype.NewFakeClientWithList[*v1beta3.SupportBundle, *v1beta3.SupportBundleList]( + fake.Fake, + namespace, + v1beta3.SchemeGroupVersion.WithResource("supportbundles"), + v1beta3.SchemeGroupVersion.WithKind("SupportBundle"), + func() *v1beta3.SupportBundle { return &v1beta3.SupportBundle{} }, + func() *v1beta3.SupportBundleList { return &v1beta3.SupportBundleList{} }, + func(dst, src *v1beta3.SupportBundleList) { dst.ListMeta = src.ListMeta }, + func(list *v1beta3.SupportBundleList) []*v1beta3.SupportBundle { + return gentype.ToPointerSlice(list.Items) + }, + func(list *v1beta3.SupportBundleList, items []*v1beta3.SupportBundle) { + list.Items = gentype.FromPointerSlice(items) + }, + ), + fake, + } +} diff --git a/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/fake/fake_troubleshoot_client.go b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/fake/fake_troubleshoot_client.go new file mode 100644 index 00000000..a051e588 --- /dev/null +++ b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/fake/fake_troubleshoot_client.go @@ -0,0 +1,39 @@ +/* +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 ( + v1beta3 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeTroubleshootV1beta3 struct { + *testing.Fake +} + +func (c *FakeTroubleshootV1beta3) SupportBundles(namespace string) v1beta3.SupportBundleInterface { + return newFakeSupportBundles(c, namespace) +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeTroubleshootV1beta3) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/generated_expansion.go b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/generated_expansion.go new file mode 100644 index 00000000..520943ba --- /dev/null +++ b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/generated_expansion.go @@ -0,0 +1,20 @@ +/* +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 v1beta3 + +type SupportBundleExpansion interface{} diff --git a/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/supportbundle.go b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/supportbundle.go new file mode 100644 index 00000000..c7ed62fd --- /dev/null +++ b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/supportbundle.go @@ -0,0 +1,69 @@ +/* +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 v1beta3 + +import ( + context "context" + + troubleshootv1beta3 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta3" + 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" + gentype "k8s.io/client-go/gentype" +) + +// SupportBundlesGetter has a method to return a SupportBundleInterface. +// A group's client should implement this interface. +type SupportBundlesGetter interface { + SupportBundles(namespace string) SupportBundleInterface +} + +// SupportBundleInterface has methods to work with SupportBundle resources. +type SupportBundleInterface interface { + Create(ctx context.Context, supportBundle *troubleshootv1beta3.SupportBundle, opts v1.CreateOptions) (*troubleshootv1beta3.SupportBundle, error) + Update(ctx context.Context, supportBundle *troubleshootv1beta3.SupportBundle, opts v1.UpdateOptions) (*troubleshootv1beta3.SupportBundle, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, supportBundle *troubleshootv1beta3.SupportBundle, opts v1.UpdateOptions) (*troubleshootv1beta3.SupportBundle, 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) (*troubleshootv1beta3.SupportBundle, error) + List(ctx context.Context, opts v1.ListOptions) (*troubleshootv1beta3.SupportBundleList, 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 *troubleshootv1beta3.SupportBundle, err error) + SupportBundleExpansion +} + +// supportBundles implements SupportBundleInterface +type supportBundles struct { + *gentype.ClientWithList[*troubleshootv1beta3.SupportBundle, *troubleshootv1beta3.SupportBundleList] +} + +// newSupportBundles returns a SupportBundles +func newSupportBundles(c *TroubleshootV1beta3Client, namespace string) *supportBundles { + return &supportBundles{ + gentype.NewClientWithList[*troubleshootv1beta3.SupportBundle, *troubleshootv1beta3.SupportBundleList]( + "supportbundles", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *troubleshootv1beta3.SupportBundle { return &troubleshootv1beta3.SupportBundle{} }, + func() *troubleshootv1beta3.SupportBundleList { return &troubleshootv1beta3.SupportBundleList{} }, + ), + } +} diff --git a/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/troubleshoot_client.go b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/troubleshoot_client.go new file mode 100644 index 00000000..3756e820 --- /dev/null +++ b/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta3/troubleshoot_client.go @@ -0,0 +1,100 @@ +/* +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 v1beta3 + +import ( + http "net/http" + + troubleshootv1beta3 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta3" + scheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme" + rest "k8s.io/client-go/rest" +) + +type TroubleshootV1beta3Interface interface { + RESTClient() rest.Interface + SupportBundlesGetter +} + +// TroubleshootV1beta3Client is used to interact with features provided by the troubleshoot.sh group. +type TroubleshootV1beta3Client struct { + restClient rest.Interface +} + +func (c *TroubleshootV1beta3Client) SupportBundles(namespace string) SupportBundleInterface { + return newSupportBundles(c, namespace) +} + +// NewForConfig creates a new TroubleshootV1beta3Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*TroubleshootV1beta3Client, error) { + config := *c + setConfigDefaults(&config) + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new TroubleshootV1beta3Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*TroubleshootV1beta3Client, error) { + config := *c + setConfigDefaults(&config) + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &TroubleshootV1beta3Client{client}, nil +} + +// NewForConfigOrDie creates a new TroubleshootV1beta3Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *TroubleshootV1beta3Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new TroubleshootV1beta3Client for the given RESTClient. +func New(c rest.Interface) *TroubleshootV1beta3Client { + return &TroubleshootV1beta3Client{c} +} + +func setConfigDefaults(config *rest.Config) { + gv := troubleshootv1beta3.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *TroubleshootV1beta3Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/collect/collector.go b/pkg/collect/collector.go index b8ccbf63..01922efb 100644 --- a/pkg/collect/collector.go +++ b/pkg/collect/collector.go @@ -128,6 +128,8 @@ func GetCollector(collector *troubleshootv1beta2.Collect, bundlePath string, nam return &CollectDNS{collector.DNS, bundlePath, namespace, clientConfig, client, ctx, RBACErrors}, true case collector.Etcd != nil: return &CollectEtcd{collector.Etcd, bundlePath, clientConfig, client, ctx, RBACErrors}, true + case collector.SupportBundleMetadata != nil: + return &CollectSupportBundleMetadata{collector.SupportBundleMetadata, bundlePath, namespace, clientConfig, client, ctx, RBACErrors}, true default: return nil, false } @@ -223,6 +225,9 @@ func getCollectorName(c interface{}) string { collector = "dns" case *CollectEtcd: collector = "etcd" + case *CollectSupportBundleMetadata: + collector = "support-bundle-metadata" + name = v.Collector.CollectorName default: collector = "" } diff --git a/pkg/collect/support_bundle_metadata.go b/pkg/collect/support_bundle_metadata.go new file mode 100644 index 00000000..d185b3a0 --- /dev/null +++ b/pkg/collect/support_bundle_metadata.go @@ -0,0 +1,54 @@ +package collect + +import ( + "bytes" + "context" + "encoding/json" + + "github.com/pkg/errors" + troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +type CollectSupportBundleMetadata struct { + Collector *troubleshootv1beta2.SupportBundleMetadata + BundlePath string + Namespace string + ClientConfig *rest.Config + Client kubernetes.Interface + Context context.Context + RBACErrors +} + +func (c *CollectSupportBundleMetadata) Title() string { + return getCollectorName(c) +} + +func (c *CollectSupportBundleMetadata) IsExcluded() (bool, error) { + return isExcluded(c.Collector.Exclude) +} + +func (c *CollectSupportBundleMetadata) Collect(progressChan chan<- interface{}) (CollectorResult, error) { + output := NewResult() + + const secretName = "replicated-support-metadata" + secret, err := c.Client.CoreV1().Secrets(c.Collector.Namespace).Get(c.Context, secretName, metav1.GetOptions{}) + if err != nil { + return output, errors.Wrapf(err, "failed to get secret %s/%s", c.Collector.Namespace, secretName) + } + + metadata := make(map[string]string) + for k, v := range secret.Data { + metadata[k] = string(v) + } + + b, err := json.MarshalIndent(metadata, "", " ") + if err != nil { + return output, errors.Wrap(err, "failed to marshal metadata") + } + + output.SaveResult(c.BundlePath, "metadata/cluster.json", bytes.NewBuffer(b)) + return output, nil +} diff --git a/pkg/collect/support_bundle_metadata_test.go b/pkg/collect/support_bundle_metadata_test.go new file mode 100644 index 00000000..3555571a --- /dev/null +++ b/pkg/collect/support_bundle_metadata_test.go @@ -0,0 +1,94 @@ +package collect + +import ( + "context" + "testing" + + troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + testclient "k8s.io/client-go/kubernetes/fake" +) + +func TestCollectSupportBundleMetadata(t *testing.T) { + tests := []struct { + name string + collector *troubleshootv1beta2.SupportBundleMetadata + mockSecrets []corev1.Secret + want CollectorResult + wantErr bool + }{ + { + name: "reads all data fields from secret", + collector: &troubleshootv1beta2.SupportBundleMetadata{ + Namespace: "test-ns", + }, + mockSecrets: []corev1.Secret{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "replicated-support-metadata", + Namespace: "test-ns", + }, + Data: map[string][]byte{ + "mykey": []byte("myvalue"), + "myversion": []byte("1.0.0-example"), + "numCrashes": []byte("57"), + }, + }, + }, + want: CollectorResult{ + "metadata/cluster.json": mustJSONMarshalIndent(t, map[string]string{ + "mykey": "myvalue", + "myversion": "1.0.0-example", + "numCrashes": "57", + }), + }, + }, + { + name: "empty data map", + collector: &troubleshootv1beta2.SupportBundleMetadata{ + Namespace: "test-ns", + }, + mockSecrets: []corev1.Secret{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "replicated-support-metadata", + Namespace: "test-ns", + }, + Data: map[string][]byte{}, + }, + }, + want: CollectorResult{ + "metadata/cluster.json": mustJSONMarshalIndent(t, map[string]string{}), + }, + }, + { + name: "secret not found returns error", + collector: &troubleshootv1beta2.SupportBundleMetadata{ + Namespace: "test-ns", + }, + mockSecrets: []corev1.Secret{}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + client := testclient.NewSimpleClientset() + for _, secret := range tt.mockSecrets { + _, err := client.CoreV1().Secrets(secret.Namespace).Create(ctx, &secret, metav1.CreateOptions{}) + require.NoError(t, err) + } + c := &CollectSupportBundleMetadata{tt.collector, "", "", nil, client, ctx, nil} + got, err := c.Collect(nil) + if tt.wantErr { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, got) + } + }) + } +} diff --git a/test/e2e/support-bundle/support_bundle_metadata_e2e_test.go b/test/e2e/support-bundle/support_bundle_metadata_e2e_test.go new file mode 100644 index 00000000..e09db86c --- /dev/null +++ b/test/e2e/support-bundle/support_bundle_metadata_e2e_test.go @@ -0,0 +1,105 @@ +package e2e + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" +) + +var metadataSpecTemplate = ` +apiVersion: troubleshoot.sh/v1beta2 +kind: SupportBundle +metadata: + name: metadata-test +spec: + collectors: + - clusterResources: + exclude: true + - clusterInfo: + exclude: true + - supportBundleMetadata: + namespace: $NAMESPACE +` + +func TestSupportBundleMetadata(t *testing.T) { + secretName := "replicated-support-metadata" + expectedData := map[string]string{ + "appVersion": "1.2.3", + "environment": "staging", + "clusterID": "abc-123", + } + + feature := features.New("Support Bundle Metadata Collector"). + Setup(func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: c.Namespace(), + }, + Data: make(map[string][]byte), + } + for k, v := range expectedData { + secret.Data[k] = []byte(v) + } + + client, err := c.NewClient() + if err != nil { + t.Fatal(err) + } + if err = client.Resources().Create(ctx, secret); err != nil { + t.Fatal(err) + } + return ctx + }). + Assess("check metadata/cluster.json contents", func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context { + var out bytes.Buffer + + namespace := c.Namespace() + supportBundleName := "metadata-test" + spec := strings.ReplaceAll(metadataSpecTemplate, "$NAMESPACE", namespace) + specPath := filepath.Join(t.TempDir(), "supportBundleMetadata.yaml") + + err := os.WriteFile(specPath, []byte(spec), 0644) + require.NoError(t, err) + + tarPath := fmt.Sprintf("%s.tar.gz", supportBundleName) + cmd := exec.CommandContext(ctx, sbBinary(), specPath, "--interactive=false", fmt.Sprintf("-o=%s", supportBundleName)) + cmd.Stdout = &out + err = cmd.Run() + if err != nil { + t.Fatal(err) + } + + defer func() { + err := os.Remove(tarPath) + if err != nil { + t.Fatal("Error removing file:", err) + } + }() + + metadataJSON, err := readFileFromTar(tarPath, fmt.Sprintf("%s/metadata/cluster.json", supportBundleName)) + require.NoError(t, err) + + var result map[string]string + err = json.Unmarshal(metadataJSON, &result) + require.NoError(t, err) + + assert.Equal(t, expectedData, result) + + return ctx + }).Feature() + testenv.Test(t, feature) +}