Skip to content

Commit e232cc0

Browse files
authored
Merge pull request #253 from manavellamnimble/runImagePullSecret
Add or create ImagePullSecret in a run collector
2 parents f68e0db + 1f08424 commit e232cc0

File tree

3 files changed

+110
-15
lines changed

3 files changed

+110
-15
lines changed

pkg/apis/troubleshoot/v1beta1/collector_shared.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,20 @@ type Data struct {
5252

5353
type Run struct {
5454
CollectorMeta `json:",inline" yaml:",inline"`
55-
Name string `json:"name,omitempty" yaml:"name,omitempty"`
56-
Namespace string `json:"namespace" yaml:"namespace"`
57-
Image string `json:"image" yaml:"image"`
58-
Command []string `json:"command,omitempty" yaml:"command,omitempty"`
59-
Args []string `json:"args,omitempty" yaml:"args,omitempty"`
60-
Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty"`
61-
ImagePullPolicy string `json:"imagePullPolicy,omitempty" yaml:"imagePullPolicy,omitempty"`
55+
Name string `json:"name,omitempty" yaml:"name,omitempty"`
56+
Namespace string `json:"namespace" yaml:"namespace"`
57+
Image string `json:"image" yaml:"image"`
58+
Command []string `json:"command,omitempty" yaml:"command,omitempty"`
59+
Args []string `json:"args,omitempty" yaml:"args,omitempty"`
60+
Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty"`
61+
ImagePullPolicy string `json:"imagePullPolicy,omitempty" yaml:"imagePullPolicy,omitempty"`
62+
ImagePullSecret *ImagePullSecrets `json:"imagePullSecret,omitempty" yaml:"imagePullSecret,omitempty"`
63+
}
64+
65+
type ImagePullSecrets struct {
66+
Name string `json:"name,omitempty" yaml:"name,omitempty"`
67+
Data map[string]string `json:"data,omitempty" yaml:"data,omitempty"`
68+
SecretType string `json:"type,omitempty" yaml:"type,omitempty"`
6269
}
6370

6471
type Exec struct {

pkg/apis/troubleshoot/v1beta2/collector_shared.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,20 @@ type Data struct {
5252

5353
type Run struct {
5454
CollectorMeta `json:",inline" yaml:",inline"`
55-
Name string `json:"name,omitempty" yaml:"name,omitempty"`
56-
Namespace string `json:"namespace" yaml:"namespace"`
57-
Image string `json:"image" yaml:"image"`
58-
Command []string `json:"command,omitempty" yaml:"command,omitempty"`
59-
Args []string `json:"args,omitempty" yaml:"args,omitempty"`
60-
Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty"`
61-
ImagePullPolicy string `json:"imagePullPolicy,omitempty" yaml:"imagePullPolicy,omitempty"`
55+
Name string `json:"name,omitempty" yaml:"name,omitempty"`
56+
Namespace string `json:"namespace" yaml:"namespace"`
57+
Image string `json:"image" yaml:"image"`
58+
Command []string `json:"command,omitempty" yaml:"command,omitempty"`
59+
Args []string `json:"args,omitempty" yaml:"args,omitempty"`
60+
Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty"`
61+
ImagePullPolicy string `json:"imagePullPolicy,omitempty" yaml:"imagePullPolicy,omitempty"`
62+
ImagePullSecret *ImagePullSecrets `json:"imagePullSecret,omitempty" yaml:"imagePullSecret,omitempty"`
63+
}
64+
65+
type ImagePullSecrets struct {
66+
Name string `json:"name,omitempty" yaml:"name,omitempty"`
67+
Data map[string]string `json:"data,omitempty" yaml:"data,omitempty"`
68+
SecretType string `json:"type,omitempty" yaml:"type,omitempty"`
6269
}
6370

6471
type Exec struct {

pkg/collect/run.go

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package collect
22

33
import (
4+
"bytes"
45
"context"
6+
"encoding/base64"
7+
"encoding/json"
8+
"io/ioutil"
59
"time"
610

711
"github.com/pkg/errors"
@@ -30,7 +34,15 @@ func Run(c *Collector, runCollector *troubleshootv1beta2.Run) (map[string][]byte
3034
logger.Printf("Failed to delete pod %s: %v\n", pod.Name, err)
3135
}
3236
}()
33-
37+
if runCollector.ImagePullSecret.Data != nil {
38+
defer func() {
39+
for _, k := range pod.Spec.ImagePullSecrets {
40+
if err := client.CoreV1().Secrets(pod.Namespace).Delete(ctx, k.Name, metav1.DeleteOptions{}); err != nil {
41+
logger.Printf("Failed to delete secret %s: %v\n", k.Name, err)
42+
}
43+
}
44+
}()
45+
}
3446
if runCollector.Timeout == "" {
3547
return runWithoutTimeout(ctx, c, pod, runCollector)
3648
}
@@ -137,10 +149,79 @@ func runPod(ctx context.Context, client *kubernetes.Clientset, runCollector *tro
137149
},
138150
}
139151

152+
if runCollector.ImagePullSecret != nil {
153+
err := createSecret(ctx, client, runCollector.ImagePullSecret, &pod)
154+
if err != nil {
155+
return nil, errors.Wrap(err, "failed to create secret")
156+
}
157+
}
140158
created, err := client.CoreV1().Pods(namespace).Create(ctx, &pod, metav1.CreateOptions{})
141159
if err != nil {
142160
return nil, errors.Wrap(err, "failed to create pod")
143161
}
144162

145163
return created, nil
146164
}
165+
func createSecret(ctx context.Context, client *kubernetes.Clientset, imagePullSecret *troubleshootv1beta2.ImagePullSecrets, pod *corev1.Pod) error {
166+
//In case a new secret needs to be created
167+
if imagePullSecret.Data != nil {
168+
var out bytes.Buffer
169+
data := make(map[string][]byte)
170+
if imagePullSecret.SecretType == "kubernetes.io/dockerconfigjson" {
171+
//If secret type is dockerconfigjson, check if required field in data exists
172+
v, found := imagePullSecret.Data[".dockerconfigjson"]
173+
if !found {
174+
return errors.Errorf("Secret type kubernetes.io/dockerconfigjson requires argument \".dockerconfigjson\"")
175+
}
176+
if len(imagePullSecret.Data) > 1 {
177+
return errors.Errorf("Secret type kubernetes.io/dockerconfigjson accepts only one argument \".dockerconfigjson\"")
178+
}
179+
//Then, if data is a path to a config file, it is opened
180+
configFile, err := ioutil.ReadFile(v)
181+
if err != nil {
182+
//If data is not a valid path, we assume data is a base64 encoded config.json file
183+
//Client only accepts Json formated files as data, so we decode and indent it (indentation is required)
184+
parsedConfig, err := base64.StdEncoding.DecodeString(v)
185+
if err != nil {
186+
return errors.Wrap(err, "Secret's config file not found or unable to decode data.")
187+
}
188+
err = json.Indent(&out, parsedConfig, "", "\t")
189+
if err != nil {
190+
return errors.Wrap(err, "Unable to parse encoded data.")
191+
}
192+
data[".dockerconfigjson"] = out.Bytes()
193+
} else {
194+
data[".dockerconfigjson"] = configFile
195+
}
196+
} else {
197+
for k, v := range imagePullSecret.Data {
198+
data[k] = []byte(v)
199+
}
200+
}
201+
secret := corev1.Secret{
202+
TypeMeta: metav1.TypeMeta{
203+
APIVersion: "v1",
204+
Kind: "Secret",
205+
},
206+
ObjectMeta: metav1.ObjectMeta{
207+
Name: imagePullSecret.Name,
208+
GenerateName: "troubleshoot",
209+
Namespace: pod.Namespace,
210+
},
211+
Data: data,
212+
Type: corev1.SecretType(imagePullSecret.SecretType),
213+
}
214+
created, err := client.CoreV1().Secrets(pod.Namespace).Create(ctx, &secret, metav1.CreateOptions{})
215+
if err != nil {
216+
return errors.Wrap(err, "failed to create secret")
217+
}
218+
pod.Spec.ImagePullSecrets = append(pod.Spec.ImagePullSecrets, corev1.LocalObjectReference{Name: created.Name})
219+
return nil
220+
}
221+
//In case secret must only be added to the specs.
222+
if imagePullSecret.Name != "" {
223+
pod.Spec.ImagePullSecrets = append(pod.Spec.ImagePullSecrets, corev1.LocalObjectReference{Name: imagePullSecret.Name})
224+
return nil
225+
}
226+
return errors.Errorf("Secret must at least have a Name")
227+
}

0 commit comments

Comments
 (0)