diff --git a/cmd/kubectl-mongodb/LICENSE-THIRD-PARTY b/cmd/kubectl-mongodb/LICENSE-THIRD-PARTY index cf62e700a..a26fad89b 100644 --- a/cmd/kubectl-mongodb/LICENSE-THIRD-PARTY +++ b/cmd/kubectl-mongodb/LICENSE-THIRD-PARTY @@ -11,16 +11,13 @@ github.com/golang/protobuf,v1.5.4,https://github.com/golang/protobuf/blob/v1.5.4 github.com/google/gnostic-models,v0.6.8,https://github.com/google/gnostic-models/blob/v0.6.8/LICENSE,Apache-2.0 github.com/google/gofuzz,v1.2.0,https://github.com/google/gofuzz/blob/v1.2.0/LICENSE,Apache-2.0 github.com/google/uuid,v1.6.0,https://github.com/google/uuid/blob/v1.6.0/LICENSE,BSD-3-Clause -github.com/gorilla/websocket,v1.5.0,https://github.com/gorilla/websocket/blob/v1.5.0/LICENSE,BSD-2-Clause github.com/imdario/mergo,v0.3.15,https://github.com/imdario/mergo/blob/v0.3.15/LICENSE,BSD-3-Clause github.com/josharian/intern,v1.0.0,https://github.com/josharian/intern/blob/v1.0.0/license.md,MIT github.com/json-iterator/go,v1.1.12,https://github.com/json-iterator/go/blob/v1.1.12/LICENSE,MIT github.com/mailru/easyjson,v0.7.7,https://github.com/mailru/easyjson/blob/v0.7.7/LICENSE,MIT -github.com/moby/spdystream,v0.2.0,https://github.com/moby/spdystream/blob/v0.2.0/LICENSE,Apache-2.0 github.com/modern-go/concurrent,v0.0.0-20180306012644-bacd9c7ef1dd,https://github.com/modern-go/concurrent/blob/bacd9c7ef1dd/LICENSE,Apache-2.0 github.com/modern-go/reflect2,v1.0.2,https://github.com/modern-go/reflect2/blob/v1.0.2/LICENSE,Apache-2.0 github.com/munnerz/goautoneg,v0.0.0-20191010083416-a7dc8b61c822,https://github.com/munnerz/goautoneg/blob/a7dc8b61c822/LICENSE,BSD-3-Clause -github.com/mxk/go-flowrate/flowrate,v0.0.0-20140419014527-cca7078d478f,https://github.com/mxk/go-flowrate/blob/cca7078d478f/LICENSE,BSD-3-Clause github.com/spf13/cobra,v1.7.0,https://github.com/spf13/cobra/blob/v1.7.0/LICENSE.txt,Apache-2.0 github.com/spf13/pflag,v1.0.5,https://github.com/spf13/pflag/blob/v1.0.5/LICENSE,BSD-3-Clause go.yaml.in/yaml/v2,v2.4.2,https://github.com/yaml/go-yaml/blob/v2.4.2/LICENSE,Apache-2.0 @@ -30,7 +27,7 @@ gopkg.in/yaml.v2,v2.4.0,https://github.com/go-yaml/yaml/blob/v2.4.0/LICENSE,Apac gopkg.in/yaml.v3,v3.0.1,https://github.com/go-yaml/yaml/blob/v3.0.1/LICENSE,MIT k8s.io/api,v0.30.10,https://github.com/kubernetes/api/blob/v0.30.10/LICENSE,Apache-2.0 k8s.io/apimachinery/pkg,v0.30.10,https://github.com/kubernetes/apimachinery/blob/v0.30.10/LICENSE,Apache-2.0 -k8s.io/apimachinery/third_party/forked/golang,v0.30.10,https://github.com/kubernetes/apimachinery/blob/v0.30.10/third_party/forked/golang/LICENSE,BSD-3-Clause +k8s.io/apimachinery/third_party/forked/golang/reflect,v0.30.10,https://github.com/kubernetes/apimachinery/blob/v0.30.10/third_party/forked/golang/LICENSE,BSD-3-Clause k8s.io/client-go,v0.30.10,https://github.com/kubernetes/client-go/blob/v0.30.10/LICENSE,Apache-2.0 k8s.io/klog/v2,v2.130.1,https://github.com/kubernetes/klog/blob/v2.130.1/LICENSE,Apache-2.0 k8s.io/kube-openapi/pkg,v0.0.0-20240228011516-70dd3763d340,https://github.com/kubernetes/kube-openapi/blob/70dd3763d340/LICENSE,Apache-2.0 diff --git a/cmd/kubectl-mongodb/debug/debug.go b/cmd/kubectl-mongodb/debug/debug.go deleted file mode 100644 index d3bce21fb..000000000 --- a/cmd/kubectl-mongodb/debug/debug.go +++ /dev/null @@ -1,136 +0,0 @@ -package debug - -import ( - "fmt" - "os" - "strings" - - "github.com/spf13/cobra" - "k8s.io/client-go/tools/clientcmd" - - "github.com/mongodb/mongodb-kubernetes/pkg/kubectl-mongodb/common" - "github.com/mongodb/mongodb-kubernetes/pkg/kubectl-mongodb/debug" -) - -type Flags struct { - common.Flags - Anonymize bool - UseOwnerRef bool -} - -func (f *Flags) ParseDebugFlags() error { - if len(common.MemberClusters) > 0 { - f.MemberClusters = strings.Split(common.MemberClusters, ",") - } - - configFilePath := common.LoadKubeConfigFilePath() - kubeconfig, err := clientcmd.LoadFromFile(configFilePath) - if err != nil { - return fmt.Errorf("error loading kubeconfig file '%s': %s", configFilePath, err) - } - if len(f.CentralCluster) == 0 { - f.CentralCluster = kubeconfig.CurrentContext - f.CentralClusterNamespace = kubeconfig.Contexts[kubeconfig.CurrentContext].Namespace - } - - return nil -} - -var debugFlags = &Flags{} - -func init() { - DebugCmd.Flags().StringVar(&common.MemberClusters, "member-clusters", "", "Comma separated list of member clusters. [optional]") - DebugCmd.Flags().StringVar(&debugFlags.CentralCluster, "central-cluster", "", "The central cluster the operator will be deployed in. [optional]") - DebugCmd.Flags().StringVar(&debugFlags.MemberClusterNamespace, "member-cluster-namespace", "", "The namespace the member cluster resources will be deployed to. [optional]") - DebugCmd.Flags().StringVar(&debugFlags.CentralClusterNamespace, "central-cluster-namespace", "", "The namespace the Operator will be deployed to. [optional]") - DebugCmd.Flags().StringVar(&common.MemberClustersApiServers, "member-clusters-api-servers", "", "Comma separated list of api servers addresses. [optional, default will take addresses from KUBECONFIG env var]") - DebugCmd.Flags().BoolVar(&debugFlags.Anonymize, "anonymize", true, "True if anonymization should be turned on") - DebugCmd.Flags().BoolVar(&debugFlags.UseOwnerRef, "ownerRef", false, "True if the collection should be made with owner references (consider turning it on after CLOUDP-176772 is fixed)") -} - -var DebugCmd = &cobra.Command{ - Use: "debug", - Short: "Downloads all resources required for debugging and stores them into the disk", - Long: `'debug' downloads all resources required for debugging and stores them into the disk. - -Example: - -kubectl-mongodb debug -kubectl-mongodb debug setup --central-cluster="operator-cluster" --member-clusters="cluster-1,cluster-2,cluster-3" --member-cluster-namespace=mongodb --central-cluster-namespace=mongodb - -`, - Run: func(cmd *cobra.Command, args []string) { - err := debugFlags.ParseDebugFlags() - if err != nil { - fmt.Printf("error parsing flags: %s\n", err) - os.Exit(1) - } - clientMap, err := common.CreateClientMap(debugFlags.MemberClusters, debugFlags.CentralCluster, common.LoadKubeConfigFilePath(), common.GetKubernetesClient) - if err != nil { - fmt.Printf("failed to create clientset map: %s", err) - os.Exit(1) - } - - var collectors []debug.Collector - collectors = append(collectors, &debug.StatefulSetCollector{}) - collectors = append(collectors, &debug.ConfigMapCollector{}) - collectors = append(collectors, &debug.SecretCollector{}) - collectors = append(collectors, &debug.ServiceAccountCollector{}) - collectors = append(collectors, &debug.RolesCollector{}) - collectors = append(collectors, &debug.RolesBindingsCollector{}) - collectors = append(collectors, &debug.MongoDBCollector{}) - collectors = append(collectors, &debug.MongoDBMultiClusterCollector{}) - collectors = append(collectors, &debug.MongoDBUserCollector{}) - collectors = append(collectors, &debug.OpsManagerCollector{}) - collectors = append(collectors, &debug.MongoDBCommunityCollector{}) - collectors = append(collectors, &debug.EventsCollector{}) - collectors = append(collectors, &debug.LogsCollector{}) - collectors = append(collectors, &debug.AgentHealthFileCollector{}) - - var anonymizer debug.Anonymizer - if debugFlags.Anonymize { - anonymizer = &debug.SensitiveDataAnonymizer{} - } else { - anonymizer = &debug.NoOpAnonymizer{} - } - - var filter debug.Filter - - if debugFlags.UseOwnerRef { - filter = &debug.WithOwningReference{} - } else { - filter = &debug.AcceptAllFilter{} - } - - var collectionResults []debug.CollectionResult - - collectionResults = append(collectionResults, debug.Collect(cmd.Context(), clientMap[debugFlags.CentralCluster], debugFlags.CentralCluster, debugFlags.CentralClusterNamespace, filter, collectors, anonymizer)) - - if len(debugFlags.MemberClusters) > 0 { - for i := range debugFlags.MemberClusters { - collectionResults = append(collectionResults, debug.Collect(cmd.Context(), clientMap[debugFlags.MemberClusters[i]], debugFlags.MemberClusters[i], debugFlags.MemberClusterNamespace, filter, collectors, anonymizer)) - } - } - - fmt.Printf("==== Report ====\n\n") - fmt.Printf("Anonymisation: %v\n", debugFlags.Anonymize) - fmt.Printf("Following owner refs: %v\n", debugFlags.UseOwnerRef) - fmt.Printf("Collected data from %d clusters\n", len(collectionResults)) - fmt.Printf("\n\n==== Collected Data ====\n\n") - - storeDirectory, err := debug.DebugDirectory() - if err != nil { - fmt.Printf("failed to obtain directory for collecting the results: %v", err) - os.Exit(1) - } - - if len(collectionResults) > 0 { - directoryName, compressedFileName, err := debug.WriteToFile(storeDirectory, collectionResults...) - if err != nil { - panic(err) - } - fmt.Printf("Debug data file (compressed): %v\n", compressedFileName) - fmt.Printf("Debug data directory: %v\n", directoryName) - } - }, -} diff --git a/cmd/kubectl-mongodb/root/root.go b/cmd/kubectl-mongodb/root/root.go index 429cccc0e..2ac5f4b6a 100644 --- a/cmd/kubectl-mongodb/root/root.go +++ b/cmd/kubectl-mongodb/root/root.go @@ -9,7 +9,6 @@ import ( "github.com/spf13/cobra" - cmddebug "github.com/mongodb/mongodb-kubernetes/cmd/kubectl-mongodb/debug" "github.com/mongodb/mongodb-kubernetes/cmd/kubectl-mongodb/multicluster" "github.com/mongodb/mongodb-kubernetes/cmd/kubectl-mongodb/utils" ) @@ -25,7 +24,6 @@ of MongoDB resources in your kubernetes cluster. func init() { rootCmd.AddCommand(multicluster.MulticlusterCmd) - rootCmd.AddCommand(cmddebug.DebugCmd) } // Execute adds all child commands to the root command and sets flags appropriately. diff --git a/go.sum b/go.sum index b0c020ed4..cb2a27f2f 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,6 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -104,8 +102,6 @@ github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVH github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= -github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= @@ -117,17 +113,14 @@ github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9 github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I= github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= -github.com/hashicorp/vault/api v1.16.0 h1:nbEYGJiAPGzT9U4oWgaaB0g+Rj8E59QuHKyA5LhwQN4= -github.com/hashicorp/vault/api v1.16.0/go.mod h1:KhuUhzOD8lDSk29AtzNjgAu2kxRA9jL9NAbkFlqvkBA= github.com/hashicorp/vault/api v1.20.0 h1:KQMHElgudOsr+IbJgmbjHnCTxEpKs9LnozA1D3nozU4= github.com/hashicorp/vault/api v1.20.0/go.mod h1:GZ4pcjfzoOWpkJ3ijHNpEoAxKEsBJnVljyTe3jM2Sms= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= @@ -211,8 +204,6 @@ github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkB github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk= -github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= @@ -259,8 +250,6 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.mongodb.org/atlas v0.38.0 h1:zfwymq20GqivGwxPZfypfUDry+WwMGVui97z1d8V4bU= go.mongodb.org/atlas v0.38.0/go.mod h1:DJYtM+vsEpPEMSkQzJnFHrT0sP7ev6cseZc/GGjJYG8= -go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ= -go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= @@ -287,12 +276,12 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= +go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= @@ -300,8 +289,7 @@ golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2F golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -311,8 +299,6 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= @@ -322,8 +308,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -350,8 +334,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= @@ -362,8 +344,7 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -433,7 +414,5 @@ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMm sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= diff --git a/pkg/kubectl-mongodb/debug/anonymize.go b/pkg/kubectl-mongodb/debug/anonymize.go deleted file mode 100644 index f1f2005bd..000000000 --- a/pkg/kubectl-mongodb/debug/anonymize.go +++ /dev/null @@ -1,30 +0,0 @@ -package debug - -import v1 "k8s.io/api/core/v1" - -const ( - MASKED_TEXT = "***MASKED***" -) - -type Anonymizer interface { - AnonymizeSecret(secret *v1.Secret) *v1.Secret -} - -var _ Anonymizer = &NoOpAnonymizer{} - -type NoOpAnonymizer struct{} - -func (n *NoOpAnonymizer) AnonymizeSecret(secret *v1.Secret) *v1.Secret { - return secret -} - -var _ Anonymizer = &SensitiveDataAnonymizer{} - -type SensitiveDataAnonymizer struct{} - -func (n *SensitiveDataAnonymizer) AnonymizeSecret(secret *v1.Secret) *v1.Secret { - for key := range secret.Data { - secret.Data[key] = []byte(MASKED_TEXT) - } - return secret -} diff --git a/pkg/kubectl-mongodb/debug/anonymize_test.go b/pkg/kubectl-mongodb/debug/anonymize_test.go deleted file mode 100644 index 2746a164d..000000000 --- a/pkg/kubectl-mongodb/debug/anonymize_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package debug - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - v1 "k8s.io/api/core/v1" -) - -func TestNoOpAnonymizer_AnonymizeSecret(t *testing.T) { - // given - text := "test" - anonymizer := NoOpAnonymizer{} - - // when - result := anonymizer.AnonymizeSecret(&v1.Secret{ - Data: map[string][]byte{ - text: []byte(text), - }, - }) - - // then - assert.Equal(t, text, string(result.Data[text])) -} - -func TestSensitiveDataAnonymizer_AnonymizeSecret(t *testing.T) { - // given - text := "test" - anonymizer := SensitiveDataAnonymizer{} - - // when - result := anonymizer.AnonymizeSecret(&v1.Secret{ - Data: map[string][]byte{ - text: []byte(text), - }, - }) - - // then - assert.Equal(t, MASKED_TEXT, string(result.Data[text])) -} diff --git a/pkg/kubectl-mongodb/debug/collectors.go b/pkg/kubectl-mongodb/debug/collectors.go deleted file mode 100644 index 3221975f9..000000000 --- a/pkg/kubectl-mongodb/debug/collectors.go +++ /dev/null @@ -1,377 +0,0 @@ -package debug - -import ( - "bufio" - "bytes" - "context" - "fmt" - "strings" - - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/remotecommand" - "k8s.io/utils/ptr" - - corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/mongodb/mongodb-kubernetes/pkg/kubectl-mongodb/common" -) - -var ( - // TODO: Report a bug on inconsistent naming (plural vs singular). - MongoDBCommunityGVR = schema.GroupVersionResource{Group: "mongodbcommunity.mongodb.com", Version: "v1", Resource: "mongodbcommunity"} - MongoDBGVR = schema.GroupVersionResource{Group: "mongodb.com", Version: "v1", Resource: "mongodb"} - MongoDBMultiClusterGVR = schema.GroupVersionResource{Group: "mongodb.com", Version: "v1", Resource: "mongodbmulticlusters"} - MongoDBUsersGVR = schema.GroupVersionResource{Group: "mongodb.com", Version: "v1", Resource: "mongodbusers"} - OpsManagerSchemeGVR = schema.GroupVersionResource{Group: "mongodb.com", Version: "v1", Resource: "opsmanagers"} -) - -const ( - redColor = "\033[31m" - resetColor = "\033[0m" -) - -type Filter interface { - Accept(object runtime.Object) bool -} - -var _ Filter = &AcceptAllFilter{} - -type AcceptAllFilter struct{} - -func (a *AcceptAllFilter) Accept(_ runtime.Object) bool { - return true -} - -var _ Filter = &WithOwningReference{} - -type WithOwningReference struct{} - -func (a *WithOwningReference) Accept(object runtime.Object) bool { - typeAccessor, err := meta.Accessor(object) - if err != nil { - return true - } - - for _, or := range typeAccessor.GetOwnerReferences() { - if strings.Contains(strings.ToLower(or.Kind), "mongo") { - return true - } - } - return false -} - -type RawFile struct { - Name string - ContainerName string - content []byte -} - -type Collector interface { - Collect(context.Context, common.KubeClient, string, Filter, Anonymizer) ([]runtime.Object, []RawFile, error) -} - -var _ Collector = &StatefulSetCollector{} - -type StatefulSetCollector struct{} - -func (s *StatefulSetCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, _ Anonymizer) ([]runtime.Object, []RawFile, error) { - return genericCollect(ctx, kubeClient, namespace, filter, func(ctx context.Context, kubeClient common.KubeClient, namespace string) (runtime.Object, error) { - return kubeClient.AppsV1().StatefulSets(namespace).List(ctx, v1.ListOptions{}) - }) -} - -var _ Collector = &ConfigMapCollector{} - -type ConfigMapCollector struct{} - -func (s *ConfigMapCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, _ Anonymizer) ([]runtime.Object, []RawFile, error) { - return genericCollect(ctx, kubeClient, namespace, filter, func(ctx context.Context, kubeClient common.KubeClient, namespace string) (runtime.Object, error) { - return kubeClient.CoreV1().ConfigMaps(namespace).List(ctx, v1.ListOptions{}) - }) -} - -var _ Collector = &SecretCollector{} - -type SecretCollector struct{} - -func (s *SecretCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, anonymizer Anonymizer) ([]runtime.Object, []RawFile, error) { - var ret []runtime.Object - secrets, err := kubeClient.CoreV1().Secrets(namespace).List(ctx, v1.ListOptions{}) - if err != nil { - return nil, nil, err - } - for i := range secrets.Items { - item := secrets.Items[i] - if filter.Accept(&item) { - ret = append(ret, anonymizer.AnonymizeSecret(&item)) - } - } - return ret, nil, nil -} - -var _ Collector = &ServiceAccountCollector{} - -type ServiceAccountCollector struct{} - -func (s *ServiceAccountCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, anonymizer Anonymizer) ([]runtime.Object, []RawFile, error) { - return genericCollect(ctx, kubeClient, namespace, filter, func(ctx context.Context, kubeClient common.KubeClient, namespace string) (runtime.Object, error) { - return kubeClient.CoreV1().ServiceAccounts(namespace).List(ctx, v1.ListOptions{}) - }) -} - -var _ Collector = &RolesCollector{} - -type RolesCollector struct{} - -func (s *RolesCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, anonymizer Anonymizer) ([]runtime.Object, []RawFile, error) { - return genericCollect(ctx, kubeClient, namespace, filter, func(ctx context.Context, kubeClient common.KubeClient, namespace string) (runtime.Object, error) { - return kubeClient.RbacV1().Roles(namespace).List(ctx, v1.ListOptions{}) - }) -} - -var _ Collector = &RolesBindingsCollector{} - -type RolesBindingsCollector struct{} - -func (s *RolesBindingsCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, anonymizer Anonymizer) ([]runtime.Object, []RawFile, error) { - return genericCollect(ctx, kubeClient, namespace, filter, func(ctx context.Context, kubeClient common.KubeClient, namespace string) (runtime.Object, error) { - return kubeClient.RbacV1().RoleBindings(namespace).List(ctx, v1.ListOptions{}) - }) -} - -var _ Collector = &MongoDBCollector{} - -type MongoDBCollector struct{} - -func (s *MongoDBCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, anonymizer Anonymizer) ([]runtime.Object, []RawFile, error) { - return genericCollect(ctx, kubeClient, namespace, filter, func(ctx context.Context, kubeClient common.KubeClient, namespace string) (runtime.Object, error) { - return kubeClient.Resource(MongoDBGVR).List(ctx, v1.ListOptions{}) - }) -} - -var _ Collector = &MongoDBMultiClusterCollector{} - -type MongoDBMultiClusterCollector struct{} - -func (s *MongoDBMultiClusterCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, anonymizer Anonymizer) ([]runtime.Object, []RawFile, error) { - return genericCollect(ctx, kubeClient, namespace, filter, func(ctx context.Context, kubeClient common.KubeClient, namespace string) (runtime.Object, error) { - return kubeClient.Resource(MongoDBMultiClusterGVR).List(ctx, v1.ListOptions{}) - }) -} - -var _ Collector = &MongoDBUserCollector{} - -type MongoDBUserCollector struct{} - -func (s *MongoDBUserCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, anonymizer Anonymizer) ([]runtime.Object, []RawFile, error) { - return genericCollect(ctx, kubeClient, namespace, filter, func(ctx context.Context, kubeClient common.KubeClient, namespace string) (runtime.Object, error) { - return kubeClient.Resource(MongoDBUsersGVR).List(ctx, v1.ListOptions{}) - }) -} - -var _ Collector = &OpsManagerCollector{} - -type OpsManagerCollector struct{} - -func (s *OpsManagerCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, anonymizer Anonymizer) ([]runtime.Object, []RawFile, error) { - return genericCollect(ctx, kubeClient, namespace, filter, func(ctx context.Context, kubeClient common.KubeClient, namespace string) (runtime.Object, error) { - return kubeClient.Resource(OpsManagerSchemeGVR).List(ctx, v1.ListOptions{}) - }) -} - -var _ Collector = &MongoDBCommunityCollector{} - -type MongoDBCommunityCollector struct{} - -func (s *MongoDBCommunityCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, anonymizer Anonymizer) ([]runtime.Object, []RawFile, error) { - return genericCollect(ctx, kubeClient, namespace, filter, func(ctx context.Context, kubeClient common.KubeClient, namespace string) (runtime.Object, error) { - return kubeClient.Resource(MongoDBCommunityGVR).List(ctx, v1.ListOptions{}) - }) -} - -var _ Collector = &EventsCollector{} - -type EventsCollector struct{} - -func (s *EventsCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, anonymizer Anonymizer) ([]runtime.Object, []RawFile, error) { - return genericCollect(ctx, kubeClient, namespace, filter, func(ctx context.Context, kubeClient common.KubeClient, namespace string) (runtime.Object, error) { - return kubeClient.EventsV1().Events(namespace).List(ctx, v1.ListOptions{}) - }) -} - -var _ Collector = &LogsCollector{} - -type LogsCollector struct{} - -func (s *LogsCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, anonymizer Anonymizer) ([]runtime.Object, []RawFile, error) { - pods, err := kubeClient.CoreV1().Pods(namespace).List(ctx, v1.ListOptions{}) - if err != nil { - return nil, nil, err - } - var logsToCollect []RawFile - for podIdx := range pods.Items { - for containerIdx := range pods.Items[podIdx].Spec.Containers { - logsToCollect = append(logsToCollect, RawFile{ - Name: pods.Items[podIdx].Name, - ContainerName: pods.Items[podIdx].Spec.Containers[containerIdx].Name, - }) - } - } - for i := range logsToCollect { - podName := logsToCollect[i].Name - PodLogsConnection := kubeClient.CoreV1().Pods(namespace).GetLogs(podName, &corev1.PodLogOptions{ - Follow: false, - TailLines: ptr.To(int64(100)), - Container: logsToCollect[i].ContainerName, - }) - LogStream, err := PodLogsConnection.Stream(ctx) - if err != nil { - fmt.Printf(redColor+"[%T] error from %s/%s, ignoring: %s\n"+resetColor, s, namespace, podName, err) - continue - } - reader := bufio.NewScanner(LogStream) - var line string - for reader.Scan() { - line = fmt.Sprintf("%s\n", reader.Text()) - bytes := []byte(line) - logsToCollect[i].content = append(logsToCollect[i].content, bytes...) - } - LogStream.Close() //nolint: errcheck - } - return nil, logsToCollect, nil -} - -var _ Collector = &AgentHealthFileCollector{} - -type AgentHealthFileCollector struct{} - -func (s *AgentHealthFileCollector) Collect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, anonymizer Anonymizer) ([]runtime.Object, []RawFile, error) { - type AgentHealthFileToCollect struct { - podName string - RawFile rest.ContentConfig - agentFileName string - containerName string - } - - pods, err := kubeClient.CoreV1().Pods(namespace).List(ctx, v1.ListOptions{}) - if err != nil { - return nil, nil, err - } - var logsToCollect []AgentHealthFileToCollect - var collectedHealthFiles []RawFile - for i, pod := range pods.Items { - add := AgentHealthFileToCollect{ - podName: pods.Items[i].Name, - } - found := false - for _, c := range pod.Spec.Containers { - for _, e := range c.Env { - if e.Name == "AGENT_STATUS_FILEPATH" { - add.agentFileName = e.Value - found = true - break - } - } - if found { - add.containerName = c.Name - break - } - } - - if found { - logsToCollect = append(logsToCollect, add) - } - } - for _, l := range logsToCollect { - add := RawFile{ - Name: l.podName + "-agent-health", - } - content, err := getFileContent(kubeClient.GetRestConfig(), kubeClient, namespace, l.podName, l.containerName, l.agentFileName) - if err == nil { - add.content = content - collectedHealthFiles = append(collectedHealthFiles, add) - } - } - return nil, collectedHealthFiles, nil -} - -// Inspired by https://gist.github.com/kyroy/8453a0c4e075e91809db9749e0adcff2 -func getFileContent(config *rest.Config, clientset common.KubeClient, namespace, podName, containerName, path string) ([]byte, error) { - u := clientset.CoreV1().RESTClient().Post(). - Namespace(namespace). - Name(podName). - Resource("pods"). - SubResource("exec"). - Param("command", "/bin/cat"). - Param("command", path). - Param("container", containerName). - Param("stderr", "true"). - Param("stdout", "true").URL() - - buf := &bytes.Buffer{} - errBuf := &bytes.Buffer{} - exec, err := remotecommand.NewSPDYExecutor(config, "POST", u) // nolint: ineffassign,staticcheck - err = exec.Stream(remotecommand.StreamOptions{ // nolint:staticcheck - Stdout: buf, - Stderr: errBuf, - }) - if err != nil { - return nil, fmt.Errorf("%w Failed obtaining file %s from %v/%v", err, path, namespace, podName) - } - - return buf.Bytes(), nil -} - -type genericLister func(ctx context.Context, kubeClient common.KubeClient, namespace string) (runtime.Object, error) - -func genericCollect(ctx context.Context, kubeClient common.KubeClient, namespace string, filter Filter, lister genericLister) ([]runtime.Object, []RawFile, error) { - var ret []runtime.Object - listAsObject, err := lister(ctx, kubeClient, namespace) - if err != nil { - return nil, nil, err - } - list, err := meta.ExtractList(listAsObject) - if err != nil { - return nil, nil, err - } - for i := range list { - item := list[i] - if filter.Accept(item) { - ret = append(ret, item) - } - } - return ret, nil, nil -} - -type CollectionResult struct { - kubeResources []runtime.Object - rawObjects []RawFile - errors []error - namespace string - context string -} - -func Collect(ctx context.Context, kubeClient common.KubeClient, context string, namespace string, filter Filter, collectors []Collector, anonymizer Anonymizer) CollectionResult { - result := CollectionResult{} - result.context = context - result.namespace = namespace - - for _, collector := range collectors { - collectedKubeObjects, collectedRawObjects, err := collector.Collect(ctx, kubeClient, namespace, filter, anonymizer) - errorString := "" - if err != nil { - errorString = fmt.Sprintf(redColor+" error: %s"+resetColor, err) - } - fmt.Printf("[%T] collected %d kubeObjects, %d rawObjects%s\n", collector, len(collectedKubeObjects), len(collectedRawObjects), errorString) - result.kubeResources = append(result.kubeResources, collectedKubeObjects...) - result.rawObjects = append(result.rawObjects, collectedRawObjects...) - if err != nil { - result.errors = append(result.errors, err) - } - } - return result -} diff --git a/pkg/kubectl-mongodb/debug/collectors_test.go b/pkg/kubectl-mongodb/debug/collectors_test.go deleted file mode 100644 index 4cb31190b..000000000 --- a/pkg/kubectl-mongodb/debug/collectors_test.go +++ /dev/null @@ -1,175 +0,0 @@ -package debug - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/kubernetes/fake" - - v1 "k8s.io/api/apps/v1" - v12 "k8s.io/api/core/v1" - v13 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - fake2 "k8s.io/client-go/dynamic/fake" - - "github.com/mongodb/mongodb-kubernetes/pkg/kubectl-mongodb/common" -) - -func TestCollectors(t *testing.T) { - ctx := context.Background() - // given - collectors := []Collector{ - &MongoDBCommunityCollector{}, - &MongoDBCollector{}, - &MongoDBMultiClusterCollector{}, - &MongoDBUserCollector{}, - &OpsManagerCollector{}, - &StatefulSetCollector{}, - &SecretCollector{}, - &ConfigMapCollector{}, - &RolesCollector{}, - &ServiceAccountCollector{}, - &RolesBindingsCollector{}, - &ServiceAccountCollector{}, - } - filter := &AcceptAllFilter{} - anonymizer := &NoOpAnonymizer{} - namespace := "test" - testObjectNames := "test" - - kubeClient := kubeClientWithTestingResources(ctx, namespace, testObjectNames) - - // when - for _, collector := range collectors { - kubeObjects, rawObjects, err := collector.Collect(ctx, kubeClient, namespace, filter, anonymizer) - - // then - assert.NoError(t, err) - assert.Equal(t, 1, len(kubeObjects)) - assert.Equal(t, 0, len(rawObjects)) - } -} - -func kubeClientWithTestingResources(ctx context.Context, namespace, testObjectNames string) *common.KubeClientContainer { - resources := []runtime.Object{ - &v12.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: testObjectNames, - Namespace: namespace, - }, - }, - &v1.StatefulSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: testObjectNames, - Namespace: namespace, - }, - }, - &v12.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: testObjectNames, - Namespace: namespace, - }, - }, - &v12.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: testObjectNames, - Namespace: namespace, - }, - }, - &v13.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: testObjectNames, - Namespace: namespace, - }, - }, - &v13.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: testObjectNames, - Namespace: namespace, - }, - }, - &v12.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: testObjectNames, - Namespace: namespace, - }, - }, - } - - // Unfortunately most of the Kind and Resource parts are guessing and making fake.NewSimpleDynamicClientWithCustomListKinds - // happy. Sadly, it uses naming conventions (with List suffix) and tries to guess the plural names - mostly incorrectly. - - scheme := runtime.NewScheme() - MongoDBCommunityGVK := schema.GroupVersionKind{ - Group: MongoDBCommunityGVR.Group, - Version: MongoDBCommunityGVR.Version, - Kind: "MongoDBCommunity", - } - MongoDBGVK := schema.GroupVersionKind{ - Group: MongoDBGVR.Group, - Version: MongoDBGVR.Version, - Kind: "MongoDB", - } - MongoDBUserGVK := schema.GroupVersionKind{ - Group: MongoDBGVR.Group, - Version: MongoDBGVR.Version, - Kind: "MongoDBUser", - } - MongoDBMultiGVK := schema.GroupVersionKind{ - Group: MongoDBGVR.Group, - Version: MongoDBGVR.Version, - Kind: "MongoDBMulti", - } - OpsManagerGVK := schema.GroupVersionKind{ - Group: OpsManagerSchemeGVR.Group, - Version: OpsManagerSchemeGVR.Version, - Kind: "OpsManager", - } - - scheme.AddKnownTypeWithName(MongoDBCommunityGVK, &unstructured.Unstructured{}) - scheme.AddKnownTypeWithName(MongoDBGVK, &unstructured.Unstructured{}) - scheme.AddKnownTypeWithName(MongoDBMultiGVK, &unstructured.Unstructured{}) - scheme.AddKnownTypeWithName(MongoDBUserGVK, &unstructured.Unstructured{}) - - MongoDBCommunityResource := unstructured.Unstructured{} - MongoDBCommunityResource.SetGroupVersionKind(MongoDBCommunityGVK) - MongoDBCommunityResource.SetName(testObjectNames) - - MongoDBResource := unstructured.Unstructured{} - MongoDBResource.SetGroupVersionKind(MongoDBGVK) - MongoDBResource.SetName(testObjectNames) - - MongoDBUserResource := unstructured.Unstructured{} - MongoDBUserResource.SetGroupVersionKind(MongoDBUserGVK) - MongoDBUserResource.SetName(testObjectNames) - - MongoDBMultiClusterResource := unstructured.Unstructured{} - MongoDBMultiClusterResource.SetGroupVersionKind(MongoDBMultiGVK) - MongoDBMultiClusterResource.SetName(testObjectNames) - - OpsManagerResource := unstructured.Unstructured{} - OpsManagerResource.SetGroupVersionKind(OpsManagerGVK) - OpsManagerResource.SetName(testObjectNames) - - dynamicLists := map[schema.GroupVersionResource]string{ - MongoDBCommunityGVR: "MongoDBCommunityList", - MongoDBGVR: "MongoDBList", - MongoDBUsersGVR: "MongoDBUserList", - MongoDBMultiClusterGVR: "MongoDBMultiClusterList", - OpsManagerSchemeGVR: "OpsManagerList", - } - dynamicFake := fake2.NewSimpleDynamicClientWithCustomListKinds(scheme, dynamicLists) - - dynamicFake.Resource(MongoDBMultiClusterGVR).Create(ctx, &MongoDBMultiClusterResource, metav1.CreateOptions{}) - dynamicFake.Resource(MongoDBCommunityGVR).Create(ctx, &MongoDBCommunityResource, metav1.CreateOptions{}) - dynamicFake.Resource(MongoDBGVR).Create(ctx, &MongoDBResource, metav1.CreateOptions{}) - dynamicFake.Resource(MongoDBUsersGVR).Create(ctx, &MongoDBUserResource, metav1.CreateOptions{}) - dynamicFake.Resource(OpsManagerSchemeGVR).Create(ctx, &OpsManagerResource, metav1.CreateOptions{}) - - kubeClient := common.NewKubeClientContainer(nil, fake.NewSimpleClientset(resources...), dynamicFake) - return kubeClient -} diff --git a/pkg/kubectl-mongodb/debug/writer.go b/pkg/kubectl-mongodb/debug/writer.go deleted file mode 100644 index 9ee606fae..000000000 --- a/pkg/kubectl-mongodb/debug/writer.go +++ /dev/null @@ -1,133 +0,0 @@ -package debug - -import ( - "archive/zip" - "fmt" - "io" - "os" - "path/filepath" - "strings" - "time" - - "github.com/ghodss/yaml" - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/conversion" - "k8s.io/apimachinery/pkg/runtime" -) - -const ( - DefaultWritePath = ".mongodb/debug" -) - -func WriteToFile(path string, collectionResults ...CollectionResult) (string, string, error) { - err := os.MkdirAll(path, os.ModePerm) - if err != nil { - return "", "", err - } - for _, collectionResult := range collectionResults { - for _, obj := range collectionResult.kubeResources { - data, err := yaml.Marshal(obj) - if err != nil { - return "", "", err - } - meta, err := meta.Accessor(obj) - if err != nil { - return "", "", err - } - kubeType, err := getType(obj) - if err != nil { - return "", "", err - } - fileName := fmt.Sprintf("%s/%s-%s-%s-%s.yaml", path, cleanContext(collectionResult.context), collectionResult.namespace, kubeType, meta.GetName()) - err = os.WriteFile(fileName, data, os.ModePerm) // nolint:gosec - if err != nil { - return "", "", err - } - } - for _, obj := range collectionResult.rawObjects { - fileName := fmt.Sprintf("%s/%s-%s-%s-%s-%s.txt", path, cleanContext(collectionResult.context), collectionResult.namespace, "txt", obj.ContainerName, obj.Name) - err = os.WriteFile(fileName, obj.content, os.ModePerm) // nolint:gosec - if err != nil { - return "", "", err - } - } - } - compressedFile, err := compressDirectory(path) - if err != nil { - return "", "", err - } - return path, compressedFile, err -} - -// Inspired by https://stackoverflow.com/questions/37869793/how-do-i-zip-a-directory-containing-sub-directories-or-files-in-golang/63233911#63233911 -func compressDirectory(path string) (string, error) { - fileName := path + ".zip" - file, err := os.Create(fileName) - if err != nil { - return "", err - } - defer file.Close() // nolint: errcheck - - w := zip.NewWriter(file) - defer w.Close() // nolint: errcheck - - walker := func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if info.IsDir() { - return nil - } - file, err := os.Open(path) - if err != nil { - return err - } - defer file.Close() // nolint: errcheck - - // Ensure that `path` is not absolute; it should not start with "/". - // This snippet happens to work because I don't use - // absolute paths, but ensure your real-world code - // transforms path into a zip-root relative path. - f, err := w.Create(path) - if err != nil { - return err - } - - _, err = io.Copy(f, file) - if err != nil { - return err - } - - return nil - } - err = filepath.Walk(path, walker) - if err != nil { - return "", err - } - return fileName, nil -} - -func DebugDirectory() (string, error) { - home, err := os.UserHomeDir() - if err != nil { - return "", err - } - time, err := time.Now().UTC().MarshalText() - if err != nil { - return "", err - } - return fmt.Sprintf("%s/%s/%s", home, DefaultWritePath, time), nil -} - -// This is a workaround for https://github.com/kubernetes/kubernetes/pull/63972 -func getType(obj runtime.Object) (string, error) { - v, err := conversion.EnforcePtr(obj) - if err != nil { - return "", err - } - return v.Type().String(), nil -} - -func cleanContext(context string) string { - return strings.ReplaceAll(context, "/", "-") -} diff --git a/pkg/kubectl-mongodb/debug/writer_test.go b/pkg/kubectl-mongodb/debug/writer_test.go deleted file mode 100644 index 7b597239e..000000000 --- a/pkg/kubectl-mongodb/debug/writer_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package debug - -import ( - "fmt" - "os" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "k8s.io/apimachinery/pkg/runtime" - - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func TestWriteToFile(t *testing.T) { - // setup - uniqueTempDir, err := os.MkdirTemp(os.TempDir(), "*-TestWriteToFile") - assert.NoError(t, err) - defer os.RemoveAll(uniqueTempDir) - - // given - testNamespace := "testNamespace" - testContext := "testContext" - testError := fmt.Errorf("test") - testSecret := &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-secret", - Namespace: testNamespace, - }, - Data: map[string][]byte{ - "test": []byte("test"), - }, - } - testFile := RawFile{ - Name: "testFile", - content: []byte("test"), - ContainerName: "testContainer", - } - collectionResult := CollectionResult{ - kubeResources: []runtime.Object{testSecret}, - rawObjects: []RawFile{testFile}, - errors: []error{testError}, - namespace: testNamespace, - context: testContext, - } - outputFiles := []string{"testContext-testNamespace-txt-testContainer-testFile.txt", "testContext-testNamespace-v1.Secret-test-secret.yaml"} - - // when - path, compressedFile, err := WriteToFile(uniqueTempDir, collectionResult) - defer os.RemoveAll(path) // This is fine as in case of an empty path, this does nothing - defer os.RemoveAll(compressedFile) - - // then - assert.NoError(t, err) - assert.NotNil(t, path) - assert.NotNil(t, compressedFile) - - files, err := os.ReadDir(uniqueTempDir) - assert.NoError(t, err) - assert.Equal(t, len(outputFiles), len(files)) - for _, outputFile := range outputFiles { - found := false - for _, file := range files { - if strings.Contains(file.Name(), outputFile) { - found = true - break - } - } - assert.Truef(t, found, "File %s not found", outputFile) - } - _, err = os.Stat(compressedFile) - assert.NoError(t, err) -} - -func TestCleanContext(t *testing.T) { - tests := []struct { - input string - expected string - }{ - { - input: "kind-cluster-1", - expected: "kind-cluster-1", - }, - { - input: "api-project-openshiftapps-com:6443/admin-random-v1", - expected: "api-project-openshiftapps-com:6443-admin-random-v1", - }, - } - - for _, tc := range tests { - assert.Equal(t, tc.expected, cleanContext(tc.input)) - } -}