Skip to content

Commit

Permalink
Merge pull request #19 from replicatedhq/imagepullsecrets
Browse files Browse the repository at this point in the history
Image pull secret collector and analyzers
  • Loading branch information
marccampbell authored Jul 22, 2019
2 parents e1adf97 + d83e11a commit 537b117
Show file tree
Hide file tree
Showing 15 changed files with 290 additions and 45 deletions.
4 changes: 3 additions & 1 deletion cmd/preflight/cli/interactive_results.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,11 @@ func showSaved(filename string) {
func appName(preflightName string) string {
words := strings.Split(strings.Title(strings.Replace(preflightName, "-", " ", -1)), " ")
casedWords := []string{}
for _, word := range words {
for i, word := range words {
if strings.ToLower(word) == "ai" {
casedWords = append(casedWords, "AI")
} else if strings.ToLower(word) == "io" && i > 0 {
casedWords[i-1] += ".io"
} else {
casedWords = append(casedWords, word)
}
Expand Down
13 changes: 12 additions & 1 deletion cmd/preflight/cli/run_nocrd.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"net/http"
"os"
"path/filepath"
"strings"
"time"

analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
Expand Down Expand Up @@ -75,10 +76,20 @@ func runPreflightsNoCRD(v *viper.Viper, arg string) error {

return contents, nil
}
getChildCollectedFileContents := func(prefix string) (map[string][]byte, error) {
matching := make(map[string][]byte)
for k, v := range allCollectedData {
if strings.HasPrefix(k, prefix) {
matching[k] = v
}
}

return matching, nil
}

analyzeResults := []*analyzerunner.AnalyzeResult{}
for _, analyzer := range preflight.Spec.Analyzers {
analyzeResult, err := analyzerunner.Analyze(analyzer, getCollectedFileContents)
analyzeResult, err := analyzerunner.Analyze(analyzer, getCollectedFileContents, getChildCollectedFileContents)
if err != nil {
fmt.Printf("an analyzer failed to run: %v\n", err)
continue
Expand Down
42 changes: 42 additions & 0 deletions config/crds/troubleshoot.replicated.com_preflights.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,48 @@ spec:
- outcomes
- customResourceDefinitionName
type: object
imagePullSecret:
properties:
checkName:
type: string
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
registryName:
type: string
required:
- outcomes
- registryName
type: object
ingress:
properties:
checkName:
Expand Down
32 changes: 32 additions & 0 deletions config/crds/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ func (in *Analyze) DeepCopyInto(out *Analyze) {
*out = new(AnalyzeSecret)
(*in).DeepCopyInto(*out)
}
if in.ImagePullSecret != nil {
in, out := &in.ImagePullSecret, &out.ImagePullSecret
*out = new(ImagePullSecret)
(*in).DeepCopyInto(*out)
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Analyze.
Expand Down Expand Up @@ -713,6 +718,33 @@ func (in *HTTP) DeepCopy() *HTTP {
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImagePullSecret) DeepCopyInto(out *ImagePullSecret) {
*out = *in
out.AnalyzeMeta = in.AnalyzeMeta
if in.Outcomes != nil {
in, out := &in.Outcomes, &out.Outcomes
*out = make([]*Outcome, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(Outcome)
(*in).DeepCopyInto(*out)
}
}
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImagePullSecret.
func (in *ImagePullSecret) DeepCopy() *ImagePullSecret {
if in == nil {
return nil
}
out := new(ImagePullSecret)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Ingress) DeepCopyInto(out *Ingress) {
*out = *in
Expand Down
73 changes: 41 additions & 32 deletions config/samples/troubleshoot_v1beta1_preflight.yaml
Original file line number Diff line number Diff line change
@@ -1,41 +1,50 @@
apiVersion: troubleshoot.replicated.com/v1beta1
kind: Preflight
metadata:
name: shiny-new-ai
name: support-io
spec:
uploadResultsTo: https://hookb.in/Z26mz8R9VpC7q7eYrWob
analyzers:
- clusterVersion:
- imagePullSecret:
checkName: "blarg"
registryName: quay.io
outcomes:
- fail:
when: "< 1.13.0"
message: Sorry, ShinyNew.ai requires at least Kubernetes 1.14.0. Please update your Kubernetes cluster before installing.
uri: https://enterprise.shinynew.ai/install/requirements/kubernetes
- warn:
when: "< 1.15.0"
message: The version of Kubernetes you are running meets the minimum requirements to run ShineyNew.ai. It's recommended to run Kubernetes 1.15.0 or later.
uri: https://enterprise.shinynew.ai/install/requirements/kubernetes
message: Cannot pull from quay.io
- pass:
message: The version of Kubernetes you have installed meets the required and recommended versions.
- storageClass:
checkName: Required storage classes
storageClassName: "microk8s-hostpath"
outcomes:
- fail:
message: The required storage class was not found in the cluster.
- pass:
message: The required storage class was found in the cluster.
- ingress:
namespace: default
ingressName: my-app-ingress
outcomes:
- fail:
message: Expected to find an ingress named "my-app-ingress".
- pass:
message: Expected ingress was found.
customResourceDefinitionName: rook
outcomes:
- fail:
message: Rook is required for ShinyNew.ai. Rook was not found in the cluster.
- pass:
message: Found a supported version of Rook installed and running in the cluster.
message: Found credentials to pull from quay.io
# - clusterVersion:
# outcomes:
# - fail:
# when: "< 1.13.0"
# message: Sorry, support.io requires at least Kubernetes 1.14.0. Please update your Kubernetes cluster before installing.
# uri: https://enterprise.support.io/install/requirements/kubernetes
# - warn:
# when: "< 1.15.0"
# message: The version of Kubernetes you are running meets the minimum requirements to run support.io. It's recommended to run Kubernetes 1.15.0 or later.
# uri: https://enterprise.support.io/install/requirements/kubernetes
# - pass:
# message: The version of Kubernetes you have installed meets the required and recommended versions.
# - storageClass:
# checkName: Required storage classes
# storageClassName: "microk8s-hostpath"
# outcomes:
# - fail:
# message: The required storage class was not found in the cluster.
# - pass:
# message: The required storage class was found in the cluster.
# - ingress:
# namespace: default
# ingressName: my-app-ingress
# outcomes:
# - fail:
# message: Expected to find an ingress named "my-app-ingress".
# - pass:
# message: Expected ingress was found.
# - customResourceDefinitionName:
# customResourceDefinitionName: rook
# outcomes:
# - fail:
# message: Rook is required for Support.io. Rook was not found in the cluster.
# - pass:
# message: Found a supported version of Rook installed and running in the cluster.
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,4 @@ require (
k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible
sigs.k8s.io/controller-runtime v0.2.0-beta.2
sigs.k8s.io/controller-tools v0.2.0-beta.2 // indirect

)
18 changes: 12 additions & 6 deletions pkg/analyze/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,27 @@ type AnalyzeResult struct {
URI string
}

func Analyze(analyzer *troubleshootv1beta1.Analyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) {
type getCollectedFileContents func(string) ([]byte, error)
type getChildCollectedFileContents func(string) (map[string][]byte, error)

func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileContents, findFiles getChildCollectedFileContents) (*AnalyzeResult, error) {
if analyzer.ClusterVersion != nil {
return analyzeClusterVersion(analyzer.ClusterVersion, getCollectedFileContents)
return analyzeClusterVersion(analyzer.ClusterVersion, getFile)
}
if analyzer.StorageClass != nil {
return analyzeStorageClass(analyzer.StorageClass, getCollectedFileContents)
return analyzeStorageClass(analyzer.StorageClass, getFile)
}
if analyzer.CustomResourceDefinition != nil {
return analyzeCustomResourceDefinition(analyzer.CustomResourceDefinition, getCollectedFileContents)
return analyzeCustomResourceDefinition(analyzer.CustomResourceDefinition, getFile)
}
if analyzer.Ingress != nil {
return analyzeIngress(analyzer.Ingress, getCollectedFileContents)
return analyzeIngress(analyzer.Ingress, getFile)
}
if analyzer.Secret != nil {
return analyzeSecret(analyzer.Secret, getCollectedFileContents)
return analyzeSecret(analyzer.Secret, getFile)
}
if analyzer.ImagePullSecret != nil {
return analyzeImagePullSecret(analyzer.ImagePullSecret, findFiles)
}

return nil, errors.New("invalid analyzer")
Expand Down
49 changes: 49 additions & 0 deletions pkg/analyze/image_pull_secret.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package analyzer

import (
"encoding/json"

troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
)

func analyzeImagePullSecret(analyzer *troubleshootv1beta1.ImagePullSecret, getChildCollectedFileContents func(string) (map[string][]byte, error)) (*AnalyzeResult, error) {
imagePullSecrets, err := getChildCollectedFileContents("cluster-resources/image-pull-secrets")
if err != nil {
return nil, err
}

var failOutcome *troubleshootv1beta1.Outcome
var passOutcome *troubleshootv1beta1.Outcome
for _, outcome := range analyzer.Outcomes {
if outcome.Fail != nil {
failOutcome = outcome
} else if outcome.Pass != nil {
passOutcome = outcome
}
}

result := AnalyzeResult{
Title: analyzer.CheckName,
IsFail: true,
Message: failOutcome.Fail.Message,
URI: failOutcome.Fail.URI,
}

for _, v := range imagePullSecrets {
registryAndUsername := make(map[string]string)
if err := json.Unmarshal(v, &registryAndUsername); err != nil {
return nil, err
}

for registry, _ := range registryAndUsername {
if registry == analyzer.RegistryName {
result.IsPass = true
result.IsFail = false
result.Message = passOutcome.Pass.Message
result.URI = passOutcome.Pass.URI
}
}
}

return &result, nil
}
7 changes: 7 additions & 0 deletions pkg/apis/troubleshoot/v1beta1/analyzer_shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ type AnalyzeSecret struct {
Key string `json:"key,omitempty" yaml:"key,omitempty"`
}

type ImagePullSecret struct {
AnalyzeMeta `json:",inline" yaml:",inline"`
Outcomes []*Outcome `json:"outcomes" yaml:"outcomes"`
RegistryName string `json:"registryName" yaml:"registryName"`
}

type AnalyzeMeta struct {
CheckName string `json:"checkName,omitempty" yaml:"checkName,omitempty"`
}
Expand All @@ -54,4 +60,5 @@ type Analyze struct {
CustomResourceDefinition *CustomResourceDefinition `json:"customResourceDefinition,omitempty" yaml:"customResourceDefinition,omitempty"`
Ingress *Ingress `json:"ingress,omitempty" yaml:"ingress,omitempty"`
Secret *AnalyzeSecret `json:"secret,omitempty" yaml:"secret,omitempty"`
ImagePullSecret *ImagePullSecret `json:"imagePullSecret,omitempty" yaml:"imagePullSecret,omitempty"`
}
32 changes: 32 additions & 0 deletions pkg/apis/troubleshoot/v1beta1/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ func (in *Analyze) DeepCopyInto(out *Analyze) {
*out = new(AnalyzeSecret)
(*in).DeepCopyInto(*out)
}
if in.ImagePullSecret != nil {
in, out := &in.ImagePullSecret, &out.ImagePullSecret
*out = new(ImagePullSecret)
(*in).DeepCopyInto(*out)
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Analyze.
Expand Down Expand Up @@ -729,6 +734,33 @@ func (in *HTTP) DeepCopy() *HTTP {
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImagePullSecret) DeepCopyInto(out *ImagePullSecret) {
*out = *in
out.AnalyzeMeta = in.AnalyzeMeta
if in.Outcomes != nil {
in, out := &in.Outcomes, &out.Outcomes
*out = make([]*Outcome, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(Outcome)
(*in).DeepCopyInto(*out)
}
}
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImagePullSecret.
func (in *ImagePullSecret) DeepCopy() *ImagePullSecret {
if in == nil {
return nil
}
out := new(ImagePullSecret)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Ingress) DeepCopyInto(out *Ingress) {
*out = *in
Expand Down
Loading

0 comments on commit 537b117

Please sign in to comment.