diff --git a/ffi/main.go b/ffi/main.go index 22fe48f85..21241b413 100644 --- a/ffi/main.go +++ b/ffi/main.go @@ -3,18 +3,17 @@ package main import "C" import ( - "fmt" "encoding/json" - - "gopkg.in/yaml.v2" + "fmt" + analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze" - "github.com/replicatedhq/troubleshoot/pkg/logger" "github.com/replicatedhq/troubleshoot/pkg/convert" - + "github.com/replicatedhq/troubleshoot/pkg/logger" + "gopkg.in/yaml.v2" ) //export Analyze -func Analyze(bundleURL string, analyzers string, outputFormat string, compatibility string) *C.char { +func Analyze(bundleURL string, analyzers string, outputFormat string, compatibility string) *C.char { logger.SetQuiet(true) result, err := analyzer.DownloadAndAnalyze(bundleURL, analyzers) diff --git a/go.mod b/go.mod index 3e2bdadfc..89910b37b 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,6 @@ require ( github.com/hashicorp/go-getter v1.3.1-0.20190627223108-da0323b9545e github.com/hashicorp/go-multierror v1.0.0 github.com/imdario/mergo v0.3.7 // indirect - github.com/mattn/go-colorable v0.1.2 // indirect github.com/mholt/archiver v3.1.1+incompatible github.com/mitchellh/go-wordwrap v1.0.0 // indirect github.com/nwaples/rardecode v1.0.0 // indirect @@ -36,7 +35,9 @@ require ( k8s.io/apimachinery v0.17.0 k8s.io/cli-runtime v0.17.0 k8s.io/client-go v0.17.0 + k8s.io/code-generator v0.16.5-beta.1 // indirect sigs.k8s.io/controller-runtime v0.4.0 + sigs.k8s.io/controller-tools v0.2.4 // indirect ) replace github.com/appscode/jsonpatch => github.com/gomodules/jsonpatch v2.0.1+incompatible diff --git a/go.sum b/go.sum index e9536e924..c81535d0a 100644 --- a/go.sum +++ b/go.sum @@ -163,6 +163,8 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobuffalo/flect v0.1.5 h1:xpKq9ap8MbYfhuPCF0dBH854Gp9CxZjr/IocxELFflo= +github.com/gobuffalo/flect v0.1.5/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I= @@ -564,6 +566,7 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac h1:MQEvx39qSf8vyrx3XRaOe+j1UDIzKwkYOVObRgGPVqI= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -625,6 +628,8 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966 h1:B0J02caTR6tpSJozBJyiAzT6CtBzjclw4pgm9gg8Ys0= +gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -646,8 +651,11 @@ k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53 k8s.io/client-go v0.17.0 h1:8QOGvUGdqDMFrm9sD6IUFl256BcffynGoe80sxgTEDg= k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k= k8s.io/code-generator v0.0.0-20190912054826-cd179ad6a269/go.mod h1:V5BD6M4CyaN5m+VthcclXWsVcT1Hu+glwa1bi3MIsyE= +k8s.io/code-generator v0.16.5-beta.1 h1:+zWxMQH3a6fd8lZe6utWyW/V7nmG2ZMXwtovSJI2p+0= +k8s.io/code-generator v0.16.5-beta.1/go.mod h1:mJUgkl06XV4kstAnLHAIzJPVCOzVR+ZcfPIv4fUsFCY= k8s.io/component-base v0.0.0-20190918160511-547f6c5d7090/go.mod h1:933PBGtQFJky3TEwYx4aEPZ4IxqhWh3R6DCmzqIn1hA= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190822140433-26a664648505 h1:ZY6yclUKVbZ+SdWnkfY+Je5vrMpKOxmGeKRbsXVmqYM= k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= @@ -667,6 +675,8 @@ modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9NPsg= sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns= +sigs.k8s.io/controller-tools v0.2.4 h1:la1h46EzElvWefWLqfsXrnsO3lZjpkI0asTpX6h8PLA= +sigs.k8s.io/controller-tools v0.2.4/go.mod h1:m/ztfQNocGYBgTTCmFdnK94uVvgxeZeE3LtJvd/jIzA= 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/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= diff --git a/pkg/analyze/analyzer.go b/pkg/analyze/analyzer.go index 8e219c285..cddfab5fa 100644 --- a/pkg/analyze/analyzer.go +++ b/pkg/analyze/analyzer.go @@ -79,6 +79,12 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont } return analyzeDistribution(analyzer.Distribution, getFile) } + if analyzer.NodeResources != nil { + if analyzer.NodeResources.Exclude { + return nil, nil + } + return analyzeNodeResources(analyzer.NodeResources, getFile) + } if analyzer.TextAnalyze != nil { return analyzeTextAnalyze(analyzer.TextAnalyze, getFile) } diff --git a/pkg/analyze/data_test.go b/pkg/analyze/data_test.go index b847c3c62..c278647c4 100644 --- a/pkg/analyze/data_test.go +++ b/pkg/analyze/data_test.go @@ -1,5 +1,618 @@ package analyzer +var collectedNodes = ` +[ + { + "metadata": { + "name": "ip-192-168-28-59.us-east-2.compute.internal", + "selfLink": "/api/v1/nodes/ip-192-168-28-59.us-east-2.compute.internal", + "uid": "6d679c35-1dfe-11ea-89c7-0ab299bbd38c", + "resourceVersion": "7417849", + "creationTimestamp": "2019-12-13T23:15:18Z", + "labels": { + "alpha.eksctl.io/cluster-name": "schemahero-demo", + "alpha.eksctl.io/instance-id": "i-026467ed98dc19788", + "alpha.eksctl.io/nodegroup-name": "ng-f2f5f9a5", + "beta.kubernetes.io/arch": "amd64", + "beta.kubernetes.io/instance-type": "m5.large", + "beta.kubernetes.io/os": "linux", + "failure-domain.beta.kubernetes.io/region": "us-east-2", + "failure-domain.beta.kubernetes.io/zone": "us-east-2a", + "kubernetes.io/arch": "amd64", + "kubernetes.io/hostname": "ip-192-168-28-59.us-east-2.compute.internal", + "kubernetes.io/os": "linux" + }, + "annotations": { + "node.alpha.kubernetes.io/ttl": "0", + "volumes.kubernetes.io/controller-managed-attach-detach": "true" + } + }, + "spec": { + "providerID": "aws:///us-east-2a/i-026467ed98dc19788" + }, + "status": { + "capacity": { + "attachable-volumes-aws-ebs": "25", + "cpu": "2", + "ephemeral-storage": "20959212Ki", + "hugepages-1Gi": "0", + "hugepages-2Mi": "0", + "memory": "7951376Ki", + "pods": "29" + }, + "allocatable": { + "attachable-volumes-aws-ebs": "25", + "cpu": "2", + "ephemeral-storage": "19316009748", + "hugepages-1Gi": "0", + "hugepages-2Mi": "0", + "memory": "7848976Ki", + "pods": "29" + }, + "conditions": [ + { + "type": "MemoryPressure", + "status": "False", + "lastHeartbeatTime": "2020-01-29T18:50:15Z", + "lastTransitionTime": "2020-01-22T02:01:14Z", + "reason": "KubeletHasSufficientMemory", + "message": "kubelet has sufficient memory available" + }, + { + "type": "DiskPressure", + "status": "False", + "lastHeartbeatTime": "2020-01-29T18:50:15Z", + "lastTransitionTime": "2020-01-24T01:31:53Z", + "reason": "KubeletHasNoDiskPressure", + "message": "kubelet has no disk pressure" + }, + { + "type": "PIDPressure", + "status": "False", + "lastHeartbeatTime": "2020-01-29T18:50:15Z", + "lastTransitionTime": "2020-01-22T02:01:14Z", + "reason": "KubeletHasSufficientPID", + "message": "kubelet has sufficient PID available" + }, + { + "type": "Ready", + "status": "True", + "lastHeartbeatTime": "2020-01-29T18:50:15Z", + "lastTransitionTime": "2020-01-22T02:01:14Z", + "reason": "KubeletReady", + "message": "kubelet is posting ready status" + } + ], + "addresses": [ + { + "type": "InternalIP", + "address": "***HIDDEN***" + }, + { + "type": "ExternalIP", + "address": "***HIDDEN***" + }, + { + "type": "Hostname", + "address": "ip-192-168-28-59.us-east-2.compute.internal" + }, + { + "type": "InternalDNS", + "address": "ip-192-168-28-59.us-east-2.compute.internal" + }, + { + "type": "ExternalDNS", + "address": "ec2-3-133-126-65.us-east-2.compute.amazonaws.com" + } + ], + "daemonEndpoints": { + "kubeletEndpoint": { + "Port": 10250 + } + }, + "nodeInfo": { + "machineID": "ec2d1877f782e9caa8d0f7cb5c6154b8", + "systemUUID": "EC2D1877-F782-E9CA-A8D0-F7CB5C6154B8", + "bootID": "8e91eddd-e115-4efe-a4e1-a32affdbab61", + "kernelVersion": "4.14.146-119.123.amzn2.x86_64", + "osImage": "Amazon Linux 2", + "containerRuntimeVersion": "docker://18.6.1", + "kubeletVersion": "v1.14.7-eks-1861c5", + "kubeProxyVersion": "v1.14.7-eks-1861c5", + "operatingSystem": "linux", + "architecture": "amd64" + }, + "images": [ + { + "names": [ + "kotsadm/kotsadm-api@sha256:257efb64c42c4e83f51618bc94b2898687292b7a1763c8c1165a0b8fb52b2c47", + "kotsadm/kotsadm-api:v1.11.4" + ], + "sizeBytes": 1025604685 + }, + { + "names": [ + "kotsadm/kotsadm-api@sha256:bbdaf7b3abf9864953e3a25fb5d58746ee8b3056d4dbf1c9c477c4c08d7b3e6f", + "kotsadm/kotsadm-api:v1.11.1" + ], + "sizeBytes": 1025603901 + }, + { + "names": [ + "kotsadm/kotsadm-api@sha256:0781a0d3ab73147db616a5359e7385dad5c1f942eb4dbf0032d965fc56342600" + ], + "sizeBytes": 1025603901 + }, + { + "names": [ + "kotsadm/kotsadm-api@sha256:29084f5f9896baaf947caf96b56e05af1d28a662dd437f222063df7d835f90e4" + ], + "sizeBytes": 1025603901 + }, + { + "names": [ + "kotsadm/kotsadm-api@sha256:000572c198f73af001713b10bd4869710c99313dde81d5589445a069271c0338" + ], + "sizeBytes": 1025603901 + }, + { + "names": [ + "sentry@sha256:5a9fb82278c8ee4deb0fc9cb98dfcb6e1e0e184f7267a6a2c9074e0c687a0cd2", + "sentry:9.1.2" + ], + "sizeBytes": 868746022 + }, + { + "names": [ + "602401143452.dkr.ecr.us-east-2.amazonaws.com/amazon-k8s-cni@sha256:c071dfc45cd957fc6ab2db769ae6374b1f59a08db90b0ff0b9166b8531497a35", + "602401143452.dkr.ecr.us-east-2.amazonaws.com/amazon-k8s-cni:v1.5.3" + ], + "sizeBytes": 290731139 + }, + { + "names": [ + "bitnami/postgresql@sha256:7b8f251a3ffdc3a5392b6b7bd1ac863d34f7cb1e9cc0ec3b2f92a45f9570eae5", + "bitnami/postgresql:11.5.0-debian-9-r60" + ], + "sizeBytes": 165095931 + }, + { + "names": [ + "kotsadm/kotsadm-migrations@sha256:1c19f3d507876e62889c0f592b20e15324effc579f2cd0591039fa0cdbac633d", + "kotsadm/kotsadm-migrations:v1.11.1" + ], + "sizeBytes": 156079510 + }, + { + "names": [ + "kotsadm/kotsadm-migrations@sha256:5ae3fd834b72a37d92c801cc5b281b2339c17865be0c5298e4fdff62a9c4dde4" + ], + "sizeBytes": 156079510 + }, + { + "names": [ + "kotsadm/kotsadm-migrations@sha256:c1a7dce8fc27c2fedbf567370d24e0a3759c1840fa16a46a8569d6c4a3e09152", + "kotsadm/kotsadm-migrations:v1.11.4" + ], + "sizeBytes": 156079510 + }, + { + "names": [ + "bitnami/redis@sha256:505188ab03eae7d63902fed9e2ab1bcfc2bf98a0244ba69f488cc6018eb6f330", + "bitnami/redis:5.0.5-debian-9-r141" + ], + "sizeBytes": 96707700 + }, + { + "names": [ + "602401143452.dkr.ecr.us-east-2.amazonaws.com/eks/kube-proxy@sha256:d3a6122f63202665aa50f3c08644ef504dbe56c76a1e0ab05f8e296328f3a6b4", + "602401143452.dkr.ecr.us-east-2.amazonaws.com/eks/kube-proxy:v1.14.6" + ], + "sizeBytes": 82044796 + }, + { + "names": [ + "bitnami/minideb@sha256:7f79535202f3610cf637b4ce9d92d7e28600ce9d7e05284f7c861c6ef35dcd1f", + "bitnami/minideb:stretch" + ], + "sizeBytes": 53743451 + }, + { + "names": [ + "ttl.sh/sdfsdfsdf/minideb@sha256:b02b0c29f37f90a013e0a7a38f47667a219a5785b55aba6af0bbb54c5ad691b8", + "ttl.sh/sdfsdfsdf/minideb:stretch" + ], + "sizeBytes": 53743418 + }, + { + "names": [ + "kotsadm/minio@sha256:a68fb7b34d58c8167d11a93ebe887ab44ccb9447593e9ce7c36ac940c78221d4", + "kotsadm/minio:v1.11.1" + ], + "sizeBytes": 51885319 + }, + { + "names": [ + "602401143452.dkr.ecr.us-east-2.amazonaws.com/eks/coredns@sha256:c85954b828a5627b9f3c4540893ab9d8a4be5f8da7513882ad122e08f5c2e60a", + "602401143452.dkr.ecr.us-east-2.amazonaws.com/eks/coredns:v1.3.1" + ], + "sizeBytes": 35174083 + }, + { + "names": [ + "602401143452.dkr.ecr.us-east-2.amazonaws.com/eks/pause-amd64@sha256:bea77c323c47f7b573355516acf927691182d1333333d1f41b7544012fab7adf", + "602401143452.dkr.ecr.us-east-2.amazonaws.com/eks/pause-amd64:3.1" + ], + "sizeBytes": 742472 + } + ] + } + }, + { + "metadata": { + "name": "ip-192-168-71-129.us-east-2.compute.internal", + "selfLink": "/api/v1/nodes/ip-192-168-71-129.us-east-2.compute.internal", + "uid": "6c8f3260-1dfe-11ea-89c7-0ab299bbd38c", + "resourceVersion": "7417782", + "creationTimestamp": "2019-12-13T23:15:16Z", + "labels": { + "alpha.eksctl.io/cluster-name": "schemahero-demo", + "alpha.eksctl.io/instance-id": "i-0b7ad3f63b3a123b8", + "alpha.eksctl.io/nodegroup-name": "ng-f2f5f9a5", + "beta.kubernetes.io/arch": "amd64", + "beta.kubernetes.io/instance-type": "m5.large", + "beta.kubernetes.io/os": "linux", + "failure-domain.beta.kubernetes.io/region": "us-east-2", + "failure-domain.beta.kubernetes.io/zone": "us-east-2c", + "kubernetes.io/arch": "amd64", + "kubernetes.io/hostname": "ip-192-168-71-129.us-east-2.compute.internal", + "kubernetes.io/os": "linux" + }, + "annotations": { + "node.alpha.kubernetes.io/ttl": "0", + "volumes.kubernetes.io/controller-managed-attach-detach": "true" + } + }, + "spec": { + "providerID": "aws:///us-east-2c/i-0b7ad3f63b3a123b8" + }, + "status": { + "capacity": { + "attachable-volumes-aws-ebs": "25", + "cpu": "2", + "ephemeral-storage": "20959212Ki", + "hugepages-1Gi": "0", + "hugepages-2Mi": "0", + "memory": "7865360Ki", + "pods": "29" + }, + "allocatable": { + "attachable-volumes-aws-ebs": "25", + "cpu": "2", + "ephemeral-storage": "19316009748", + "hugepages-1Gi": "0", + "hugepages-2Mi": "0", + "memory": "7762960Ki", + "pods": "29" + }, + "conditions": [ + { + "type": "MemoryPressure", + "status": "False", + "lastHeartbeatTime": "2020-01-29T18:49:36Z", + "lastTransitionTime": "2019-12-13T23:15:16Z", + "reason": "KubeletHasSufficientMemory", + "message": "kubelet has sufficient memory available" + }, + { + "type": "DiskPressure", + "status": "False", + "lastHeartbeatTime": "2020-01-29T18:49:36Z", + "lastTransitionTime": "2020-01-22T14:30:11Z", + "reason": "KubeletHasNoDiskPressure", + "message": "kubelet has no disk pressure" + }, + { + "type": "PIDPressure", + "status": "False", + "lastHeartbeatTime": "2020-01-29T18:49:36Z", + "lastTransitionTime": "2019-12-13T23:15:16Z", + "reason": "KubeletHasSufficientPID", + "message": "kubelet has sufficient PID available" + }, + { + "type": "Ready", + "status": "True", + "lastHeartbeatTime": "2020-01-29T18:49:36Z", + "lastTransitionTime": "2019-12-13T23:16:06Z", + "reason": "KubeletReady", + "message": "kubelet is posting ready status" + } + ], + "addresses": [ + { + "type": "InternalIP", + "address": "***HIDDEN***" + }, + { + "type": "ExternalIP", + "address": "***HIDDEN***" + }, + { + "type": "Hostname", + "address": "ip-192-168-71-129.us-east-2.compute.internal" + }, + { + "type": "InternalDNS", + "address": "ip-192-168-71-129.us-east-2.compute.internal" + }, + { + "type": "ExternalDNS", + "address": "ec2-3-18-214-18.us-east-2.compute.amazonaws.com" + } + ], + "daemonEndpoints": { + "kubeletEndpoint": { + "Port": 10250 + } + }, + "nodeInfo": { + "machineID": "ec2502eb42ac572c0fc598fd2854029d", + "systemUUID": "EC2502EB-42AC-572C-0FC5-98FD2854029D", + "bootID": "d6ce6c46-98af-44c0-8f0a-7c6f0affba35", + "kernelVersion": "4.14.146-119.123.amzn2.x86_64", + "osImage": "Amazon Linux 2", + "containerRuntimeVersion": "docker://18.6.1", + "kubeletVersion": "v1.14.7-eks-1861c5", + "kubeProxyVersion": "v1.14.7-eks-1861c5", + "operatingSystem": "linux", + "architecture": "amd64" + }, + "images": [ + { + "names": [ + "kotsadm/kotsadm-api@sha256:9bc79559156f04a1e086b865db962c7e3ca32575f654c0f09d5fdc4acf118d8a", + "kotsadm/kotsadm-api:alpha" + ], + "sizeBytes": 1025599949 + }, + { + "names": [ + "codescope/mjml-tcpserver@sha256:5a3f0c82a483f10255a06be5c74a34686f844b37b818a8b07c137f9c1bb1e8d7", + "codescope/mjml-tcpserver:0.8.0" + ], + "sizeBytes": 920297781 + }, + { + "names": [ + "sentry@sha256:5a9fb82278c8ee4deb0fc9cb98dfcb6e1e0e184f7267a6a2c9074e0c687a0cd2", + "sentry:9.1.2" + ], + "sizeBytes": 868746022 + }, + { + "names": [ + "kotsadm/kotsadm-operator@sha256:849ba88648a4d85e8eff5c845477af593b139d0a695a1ad5c44ba0a9eec80b54" + ], + "sizeBytes": 478334600 + }, + { + "names": [ + "kotsadm/kotsadm-operator@sha256:e8ebbbad7cdc44f9ddf8237ec38e75a9211d83e2ebec7dffd9c8c5f40f888cd3", + "kotsadm/kotsadm-operator:v1.11.1" + ], + "sizeBytes": 478334600 + }, + { + "names": [ + "kotsadm/kotsadm-operator@sha256:207b23336e6ac227c5bba39990107e42eaffe9f237e94e49abf9520e70826aa8", + "kotsadm/kotsadm-operator:v1.11.0" + ], + "sizeBytes": 478334600 + }, + { + "names": [ + "kotsadm/kotsadm-operator@sha256:9790dd5bc5450520db67b272b4bd38da595ee4d99af17307ae01ecf05b2844db" + ], + "sizeBytes": 478334600 + }, + { + "names": [ + "kotsadm/kotsadm-operator@sha256:61fdc4c1b80106717ea364de6a1dff31f0634215d5408b4bca86e1cfa84f37eb" + ], + "sizeBytes": 478334600 + }, + { + "names": [ + "kotsadm/kotsadm-operator@sha256:66cefcfd42ebab1ac441a9bf0ff755584d82631da853e40f84e5059ec928a985", + "kotsadm/kotsadm-operator:v1.11.4" + ], + "sizeBytes": 478334600 + }, + { + "names": [ + "kotsadm/kotsadm-operator@sha256:a19bf2afcbc318c169db4dbd6c6f8cdca02e6b0ee9922555441025f67c9e21f4", + "kotsadm/kotsadm-operator:v1.10.3" + ], + "sizeBytes": 478317692 + }, + { + "names": [ + "codescope/core@sha256:c8914b21b47d8394969e71054f1b964466fc1fe69cd70a778c142b947d8d08bf", + "codescope/core:1.5.0" + ], + "sizeBytes": 405019853 + }, + { + "names": [ + "kotsadm/kotsadm@sha256:6363777cbc9e57939ee33032dcfdd4619cee1b73428d031c8966948ec8172499", + "kotsadm/kotsadm:v1.11.4" + ], + "sizeBytes": 300000312 + }, + { + "names": [ + "kotsadm/kotsadm@sha256:dcff0ff224cb18e19026928a5d7a27ccfa9950032900b0c2a5fa5de8d6456ef2", + "kotsadm/kotsadm:v1.11.1" + ], + "sizeBytes": 299996710 + }, + { + "names": [ + "kotsadm/kotsadm@sha256:3fdeedc495df96c5831a3a198190c1b5b2708f5a438fea940f4798085e0a70c1" + ], + "sizeBytes": 299996710 + }, + { + "names": [ + "kotsadm/kotsadm@sha256:271ba33be8a1d0d51fe387e7df8709809fcaa00a5501e7f107253afb5628999a" + ], + "sizeBytes": 299996560 + }, + { + "names": [ + "602401143452.dkr.ecr.us-east-2.amazonaws.com/amazon-k8s-cni@sha256:c071dfc45cd957fc6ab2db769ae6374b1f59a08db90b0ff0b9166b8531497a35", + "602401143452.dkr.ecr.us-east-2.amazonaws.com/amazon-k8s-cni:v1.5.3" + ], + "sizeBytes": 290731139 + }, + { + "names": [ + "kotsadm/kotsadm@sha256:08de237443b718d8b0ee260701dddc4b8c9b67fee5b5929b051a20312bf9aa39" + ], + "sizeBytes": 255742861 + }, + { + "names": [ + "postgres@sha256:cc8fb6b149b387fed332b5bebd144f810df544e2df514383f82f6e61698b2aea", + "postgres:10.7" + ], + "sizeBytes": 229651900 + }, + { + "names": [ + "bitnami/postgresql@sha256:7b8f251a3ffdc3a5392b6b7bd1ac863d34f7cb1e9cc0ec3b2f92a45f9570eae5", + "bitnami/postgresql:11.5.0-debian-9-r60" + ], + "sizeBytes": 165095931 + }, + { + "names": [ + "kotsadm/kotsadm-migrations@sha256:9ebee83999219df4226d7f85b1da71420c3ebd3011cb79012a15c0fb805b9b3e" + ], + "sizeBytes": 156079510 + }, + { + "names": [ + "kotsadm/kotsadm-migrations@sha256:1c19f3d507876e62889c0f592b20e15324effc579f2cd0591039fa0cdbac633d" + ], + "sizeBytes": 156079510 + }, + { + "names": [ + "kotsadm/kotsadm-migrations@sha256:5ae3fd834b72a37d92c801cc5b281b2339c17865be0c5298e4fdff62a9c4dde4", + "kotsadm/kotsadm-migrations:v1.11.1" + ], + "sizeBytes": 156079510 + }, + { + "names": [ + "kotsadm/kotsadm-migrations@sha256:1f467665d4e6714b19d8b82a9c859e958537c91452588c67a09db6f66b751af3", + "kotsadm/kotsadm-migrations:alpha" + ], + "sizeBytes": 156079510 + }, + { + "names": [ + "bitnami/redis@sha256:505188ab03eae7d63902fed9e2ab1bcfc2bf98a0244ba69f488cc6018eb6f330", + "bitnami/redis:5.0.5-debian-9-r141" + ], + "sizeBytes": 96707700 + }, + { + "names": [ + "602401143452.dkr.ecr.us-east-2.amazonaws.com/eks/kube-proxy@sha256:d3a6122f63202665aa50f3c08644ef504dbe56c76a1e0ab05f8e296328f3a6b4", + "602401143452.dkr.ecr.us-east-2.amazonaws.com/eks/kube-proxy:v1.14.6" + ], + "sizeBytes": 82044796 + }, + { + "names": [ + "bitnami/minideb@sha256:7f79535202f3610cf637b4ce9d92d7e28600ce9d7e05284f7c861c6ef35dcd1f", + "bitnami/minideb:stretch" + ], + "sizeBytes": 53743451 + }, + { + "names": [ + "kotsadm/minio@sha256:3b1aadcd350f2c5b003b1e736bc89b23a636c2cf4eb3bbc7e459452a504e18ef", + "kotsadm/minio:alpha" + ], + "sizeBytes": 51885319 + }, + { + "names": [ + "kotsadm/minio@sha256:a68fb7b34d58c8167d11a93ebe887ab44ccb9447593e9ce7c36ac940c78221d4", + "kotsadm/minio:v1.11.1" + ], + "sizeBytes": 51885319 + }, + { + "names": [ + "kotsadm/minio@sha256:38c18cc2d92573cfce813931aaf04183b8c23b87a5ba0d672a8cfc1ca4f1acc6", + "kotsadm/minio:v1.10.3" + ], + "sizeBytes": 51885319 + }, + { + "names": [ + "kotsadm/minio@sha256:1c7c8a0e953fccbe44f44134a29431fd86a5cfc7845b84adb12a808b503cf847", + "kotsadm/minio:v1.11.0" + ], + "sizeBytes": 51885319 + }, + { + "names": [ + "kotsadm/minio@sha256:ffc3a26ce3fca3a6f5802444ceb6fee7a98a136c8e60b7f0020c6ce036ec628c", + "kotsadm/minio:v1.11.4" + ], + "sizeBytes": 51885319 + }, + { + "names": [ + "flungo/netutils@sha256:cf2a22cf9edee0640bae64fc33b8916fef524cc7f454e0279d91509cc1aecd60", + "flungo/netutils:latest" + ], + "sizeBytes": 42668818 + }, + { + "names": [ + "codescope/ui@sha256:147be2359690e9b4237462010111986234ec253cf19f2f7fed8e9a5c1ea59938", + "codescope/ui:1.6.3" + ], + "sizeBytes": 25522501 + }, + { + "names": [ + "codescope/router@sha256:fea5f5bf3b2fe8c872c769c91762108e7d6ff791e793c92d068035462d149de7", + "codescope/router:0.4.2" + ], + "sizeBytes": 23233618 + }, + { + "names": [ + "602401143452.dkr.ecr.us-east-2.amazonaws.com/eks/pause-amd64@sha256:bea77c323c47f7b573355516acf927691182d1333333d1f41b7544012fab7adf", + "602401143452.dkr.ecr.us-east-2.amazonaws.com/eks/pause-amd64:3.1" + ], + "sizeBytes": 742472 + } + ] + } + } +] + +` + var collectedDeployments = `[ { "metadata": { diff --git a/pkg/analyze/node_resources.go b/pkg/analyze/node_resources.go new file mode 100644 index 000000000..03ec26abf --- /dev/null +++ b/pkg/analyze/node_resources.go @@ -0,0 +1,41 @@ +package analyzer + +import ( + "encoding/json" + "strings" + + "github.com/blang/semver" + "github.com/pkg/errors" + troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" + "github.com/replicatedhq/troubleshoot/pkg/collect" +) + +func analyzeNoderesources(analyzer *troubleshootv1beta1.NodeResources, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) { + collected, err := getCollectedFileContents("cluster-info/nods.json") + if err != nil { + return nil, errors.Wrap(err, "failed to get contents of nodes.json") + } + + var nodes []corev1.Node + if err := json.Unmarshal(collected, &nodes); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal node list") + } + + matchingNodeCount := 0 + + for _, node := range nodes { + matches, err := nodeMatchesFilters(node, analyzer.Filters) + if err != nil { + return nil, errors.Wrap(err, "failed to check if node matches filter") + } + } + return analyzeClusterVersionResult(k8sVersion, analyzer.Outcomes, analyzer.CheckName) +} + +func nodeMatchesFilters(node *corev1.Node, filters *troubleshootv1beta1.NodeResourceFilters) (bool, error) { + if filters == nil { + return true, nil + } + + return false, nil +} diff --git a/pkg/analyze/node_resources_test.go b/pkg/analyze/node_resources_test.go new file mode 100644 index 000000000..9ab0b555b --- /dev/null +++ b/pkg/analyze/node_resources_test.go @@ -0,0 +1,78 @@ +package analyzer + +import ( + "testing" + + troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_nodeMatchesRfilters(t *testing.T) { + tests := []struct { + name string + node *corev1.Node + filters *troubleshootv1beta1.NodeResourceFilters + expectResult bool + }{ + { + name: "true when empty filters", + node: &corev1.Node{ + Status: corev1.NodeStatus{ + Capacity: corev1.Sometrhing{}, + Allocatable: corev1.Something{}, + }, + }, + filters: &troubleshootv1beta1.NodeResourceFilters{}, + expectResult: true, + }, + { + name: "true while nil/missing filters", + node: &corev1.Node{ + Status: corev1.NodeStatus{ + Capacity: corev1.Sometrhing{}, + Allocatable: corev1.Something{}, + }, + }, + expectResult: true, + }, + { + name: "false when allocatable memory is too high", + node: &corev1.Node{ + Status: corev1.NodeStatus{ + Capacity: corev1.Sometrhing{}, + Allocatable: corev1.Something{}, + }, + }, + filters: &troubleshootv1beta1.NodeResourceFilters{ + MemoryAllocatable: "32Gi", + }, + expectResult: false, + }, + { + name: "true when allocatable memory is available", + node: &corev1.Node{ + Status: corev1.NodeStatus{ + Capacity: corev1.Sometrhing{}, + Allocatable: corev1.Something{}, + }, + }, + filters: &troubleshootv1beta1.NodeResourceFilters{ + MemoryAllocatable: "8Gi", + }, + expectResult: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + req := require.New(t) + + actual, err := nodeMatchesFilters(test.node, test.filters) + req.NoError(err) + + assert.Equal(t, &test.expectResult, actual) + + }) + } +} diff --git a/pkg/apis/troubleshoot/v1beta1/analyzer_shared.go b/pkg/apis/troubleshoot/v1beta1/analyzer_shared.go index 7ee573649..f48e185dd 100644 --- a/pkg/apis/troubleshoot/v1beta1/analyzer_shared.go +++ b/pkg/apis/troubleshoot/v1beta1/analyzer_shared.go @@ -1,5 +1,9 @@ package v1beta1 +import ( + "k8s.io/apimachinery/pkg/util/intstr" +) + type SingleOutcome struct { When string `json:"when,omitempty" yaml:"when,omitempty"` Message string `json:"message,omitempty" yaml:"message,omitempty"` @@ -74,6 +78,23 @@ type Distribution struct { Outcomes []*Outcome `json:"outcomes" yaml:"outcomes"` } +type NodeResources struct { + // AnalyzeMeta `json:",inline" yaml:",inline"` + // Outcomes []*Outcome `json:"outcomes" yaml:"outcomes"` + // Filters *NodeResourceFilters `json:"filters,omitempty" yaml:"filters,omitempty"` +} + +type NodeResourceFilters struct { + // CPUCapacity *intstr.Intstr `json:"cpuCapacity,omitempty" yaml:"cpuCapacity,omitempty"` + // CPUAllocatable *intstr.Intstr `json:"cpuAllocatable,omitempty" yaml:"cpuAllocatable,omitempty"` + // MemoryCapacity *intstr.Intstr `json:"memoryCapacity,omitempty" yaml:"memoryCapacity,omitempty"` + // MemoryAllocatable *intstr.Intstr `json:"memoryAllocatable,omitempty" yaml:"memoryAllocatable,omitempty"` + // PodCapacity *intstr.Intstr `json:"podCapacity,omitempty" yaml:"podCapacity,omitempty"` + // PodAllocatable *intstr.Intstr `json:"podAllocatable,omitempty" yaml:"podAllocatable,omitempty"` + // EphemeralStorageCapacity *intstr.Intstr `json:"ephemeralStorageCapacity,omitempty" yaml:"ephemeralStorageCapacity,omitempty"` + // EphemeralStorageAllocatable*intstr.Intstr `json:"ephemeralStorageAllocatable,omitempty" yaml:"ephemeralStorageAllocatable,omitempty"` +} + type TextAnalyze struct { AnalyzeMeta `json:",inline" yaml:",inline"` CollectorName string `json:"collectorName,omitempty" yaml:"collectorName,omitempty"` @@ -99,5 +120,6 @@ type Analyze struct { StatefulsetStatus *StatefulsetStatus `json:"statefulsetStatus,omitempty" yaml:"statefulsetStatus,omitempty"` ContainerRuntime *ContainerRuntime `json:"containerRuntime,omitempty" yaml:"containerRuntime,omitempty"` Distribution *Distribution `json:"distribution,omitempty" yaml:"distribution,omitempty"` + NodeResources *NodeResources `json:"nodeResources,omitempty" yaml:"nodeResources,omitempty"` TextAnalyze *TextAnalyze `json:"textAnalyze,omitempty" yaml:"textAnalyze,omitempty"` } diff --git a/pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go b/pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go index 5123659f7..ce74b652e 100644 --- a/pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go @@ -102,6 +102,11 @@ func (in *Analyze) DeepCopyInto(out *Analyze) { *out = new(Distribution) (*in).DeepCopyInto(*out) } + if in.NodeResources != nil { + in, out := &in.NodeResources, &out.NodeResources + *out = new(NodeResources) + **out = **in + } if in.TextAnalyze != nil { in, out := &in.TextAnalyze, &out.TextAnalyze *out = new(TextAnalyze) @@ -1044,6 +1049,36 @@ func (in *Logs) DeepCopy() *Logs { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeResourceFilters) DeepCopyInto(out *NodeResourceFilters) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeResourceFilters. +func (in *NodeResourceFilters) DeepCopy() *NodeResourceFilters { + if in == nil { + return nil + } + out := new(NodeResourceFilters) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeResources) DeepCopyInto(out *NodeResources) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeResources. +func (in *NodeResources) DeepCopy() *NodeResources { + if in == nil { + return nil + } + out := new(NodeResources) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Outcome) DeepCopyInto(out *Outcome) { *out = *in