Skip to content

Commit

Permalink
Image pull secrets
Browse files Browse the repository at this point in the history
  • Loading branch information
marccampbell committed Jul 22, 2019
1 parent e922dc7 commit ed0ad7e
Show file tree
Hide file tree
Showing 13 changed files with 213 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
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"`
}
29 changes: 29 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 @@ -648,6 +653,7 @@ func (in *CustomResourceDefinition) DeepCopy() *CustomResourceDefinition {
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
<<<<<<< HEAD
func (in *Exec) DeepCopyInto(out *Exec) {
*out = *in
if in.Selector != nil {
Expand Down Expand Up @@ -685,10 +691,25 @@ func (in *Get) DeepCopyInto(out *Get) {
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
=======
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)
}
>>>>>>> Image pull secrets
}
}
}

<<<<<<< HEAD
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Get.
func (in *Get) DeepCopy() *Get {
if in == nil {
Expand Down Expand Up @@ -725,6 +746,14 @@ func (in *HTTP) DeepCopy() *HTTP {
return nil
}
out := new(HTTP)
=======
// 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)
>>>>>>> Image pull secrets
in.DeepCopyInto(out)
return out
}
Expand Down
56 changes: 56 additions & 0 deletions pkg/collect/cluster_resources.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package collect

import (
"encoding/base64"
"encoding/json"
"fmt"
"strings"

"github.com/replicatedhq/troubleshoot/pkg/redact"
corev1 "k8s.io/api/core/v1"
Expand All @@ -20,6 +22,7 @@ type ClusterResourcesOutput struct {
Ingress map[string][]byte `json:"cluster-resources/ingress,omitempty"`
StorageClasses []byte `json:"cluster-resources/storage-classes.json,omitempty"`
CustomResourceDefinitions []byte `json:"cluster-resources/custom-resource-definitions.json,omitempty"`
ImagePullSecrets map[string][]byte `json:"cluster-resources/image-pull-secrets,omitempty"`
}

func ClusterResources(redact bool) error {
Expand Down Expand Up @@ -92,6 +95,13 @@ func ClusterResources(redact bool) error {
}
clusterResourcesOutput.CustomResourceDefinitions = customResourceDefinitions

// imagepullsecrets
imagePullSecrets, err := imagePullSecrets(client, namespaceNames)
if err != nil {
return err
}
clusterResourcesOutput.ImagePullSecrets = imagePullSecrets

if redact {
clusterResourcesOutput, err = clusterResourcesOutput.Redact()
if err != nil {
Expand Down Expand Up @@ -231,6 +241,51 @@ func crds(client *apiextensionsv1beta1clientset.ApiextensionsV1beta1Client) ([]b
return b, nil
}

func imagePullSecrets(client *kubernetes.Clientset, namespaces []string) (map[string][]byte, error) {
imagePullSecrets := make(map[string][]byte)

// better than vendoring in.... kubernetes
type DockerConfigEntry struct {
Auth string `json:"auth"`
}
type DockerConfigJSON struct {
Auths map[string]DockerConfigEntry `json:"auths"`
}

for _, namespace := range namespaces {
secrets, err := client.CoreV1().Secrets(namespace).List(metav1.ListOptions{})
if err != nil {
return nil, err
}

for _, secret := range secrets.Items {
if secret.Type == corev1.SecretTypeDockerConfigJson {
dockerConfigJSON := DockerConfigJSON{}
if err := json.Unmarshal(secret.Data[corev1.DockerConfigJsonKey], &dockerConfigJSON); err != nil {
return nil, err
}

for registry, registryAuth := range dockerConfigJSON.Auths {
decoded, err := base64.StdEncoding.DecodeString(registryAuth.Auth)
if err != nil {
return nil, err
}

registryAndUsername := make(map[string]string)
registryAndUsername[registry] = strings.Split(string(decoded), ":")[0]
b, err := json.Marshal(registryAndUsername)
if err != nil {
return nil, err
}
imagePullSecrets[fmt.Sprintf("%s/%s.json", namespace, secret.Name)] = b
}
}
}
}

return imagePullSecrets, nil
}

func (c *ClusterResourcesOutput) Redact() (*ClusterResourcesOutput, error) {
namespaces, err := redact.Redact(c.Namespaces)
if err != nil {
Expand Down Expand Up @@ -268,5 +323,6 @@ func (c *ClusterResourcesOutput) Redact() (*ClusterResourcesOutput, error) {
Ingress: ingress,
StorageClasses: storageClasses,
CustomResourceDefinitions: crds,
ImagePullSecrets: c.ImagePullSecrets,
}, nil
}
2 changes: 1 addition & 1 deletion pkg/collect/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func createCollectorPod(client client.Client, scheme *runtime.Scheme, ownerRef m
return nil, err
}

imageName := "replicatedhq/troubleshoot:latest"
imageName := "replicated/troubleshoot:latest"
imagePullPolicy := corev1.PullAlways

if image != "" {
Expand Down
Loading

0 comments on commit ed0ad7e

Please sign in to comment.