mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-08-27 00:37:20 +00:00
Image pull secrets
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
)
|
||||
|
||||
+12
-6
@@ -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")
|
||||
|
||||
@@ -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, ®istryAndUsername); 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
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -268,5 +323,6 @@ func (c *ClusterResourcesOutput) Redact() (*ClusterResourcesOutput, error) {
|
||||
Ingress: ingress,
|
||||
StorageClasses: storageClasses,
|
||||
CustomResourceDefinitions: crds,
|
||||
ImagePullSecrets: c.ImagePullSecrets,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -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 != "" {
|
||||
|
||||
@@ -28,7 +28,7 @@ func (r *ReconcileCollectorJob) createCollectorServer(instance *troubleshootv1be
|
||||
return err
|
||||
}
|
||||
|
||||
imageName := "replicatedhq/troubleshoot:latest"
|
||||
imageName := "replicated/troubleshoot:latest"
|
||||
imagePullPolicy := corev1.PullAlways
|
||||
|
||||
if instance.Spec.Image != "" {
|
||||
|
||||
@@ -359,7 +359,7 @@ func (r *ReconcileCollectorJob) createCollectorPod(instance *troubleshootv1beta1
|
||||
return err
|
||||
}
|
||||
|
||||
imageName := "replicatedhq/troubleshoot:latest"
|
||||
imageName := "replicated/troubleshoot:latest"
|
||||
imagePullPolicy := corev1.PullAlways
|
||||
|
||||
if instance.Spec.Image != "" {
|
||||
|
||||
@@ -38,7 +38,7 @@ func CreatePreflightServer(client client.Client, scheme *runtime.Scheme, options
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
imageName := "replicatedhq/troubleshoot:latest"
|
||||
imageName := "replicated/troubleshoot:latest"
|
||||
imagePullPolicy := corev1.PullAlways
|
||||
|
||||
if options.ImageName != "" {
|
||||
|
||||
Reference in New Issue
Block a user