forked from openshift/origin
/
unlink_secret_from_object.go
151 lines (124 loc) · 4.3 KB
/
unlink_secret_from_object.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package secrets
import (
"errors"
"fmt"
"github.com/spf13/cobra"
coreapiv1 "k8s.io/api/core/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/printers"
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/kubectl/util/templates"
)
const UnlinkSecretRecommendedName = "unlink"
var (
unlinkSecretLong = templates.LongDesc(`
Unlink (detach) secrets from a service account
If a secret is no longer valid for a pod, build or image pull, you may unlink it from a service account.`)
unlinkSecretExample = templates.Examples(`
# Unlink a secret currently associated with a service account:
%[1]s serviceaccount-name secret-name another-secret-name ...`)
)
type UnlinkSecretOptions struct {
SecretOptions
PrintFlags *genericclioptions.PrintFlags
Printer printers.ResourcePrinter
genericclioptions.IOStreams
}
func NewUnlinkSecretOptions(streams genericclioptions.IOStreams) *UnlinkSecretOptions {
return &UnlinkSecretOptions{
PrintFlags: genericclioptions.NewPrintFlags("updated").WithTypeSetter(scheme.Scheme),
SecretOptions: SecretOptions{},
IOStreams: streams,
}
}
// NewCmdUnlinkSecret creates a command object for detaching one or more secret references from a service account
func NewCmdUnlinkSecret(name, fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
o := NewUnlinkSecretOptions(streams)
cmd := &cobra.Command{
Use: fmt.Sprintf("%s serviceaccount-name secret-name [another-secret-name] ...", name),
Short: "Detach secrets from a ServiceAccount",
Long: unlinkSecretLong,
Example: fmt.Sprintf(unlinkSecretExample, fullName),
Run: func(c *cobra.Command, args []string) {
if err := o.Complete(f, args); err != nil {
kcmdutil.CheckErr(kcmdutil.UsageErrorf(c, err.Error()))
}
if err := o.Validate(); err != nil {
kcmdutil.CheckErr(kcmdutil.UsageErrorf(c, err.Error()))
}
if err := o.Run(); err != nil {
kcmdutil.CheckErr(err)
}
},
}
o.PrintFlags.AddFlags(cmd)
return cmd
}
func (o *UnlinkSecretOptions) Complete(f kcmdutil.Factory, args []string) error {
if err := o.SecretOptions.Complete(f, args); err != nil {
return err
}
var err error
o.Printer, err = o.PrintFlags.ToPrinter()
if err != nil {
return err
}
return nil
}
func (o UnlinkSecretOptions) Run() error {
serviceaccount, err := o.GetServiceAccount()
if err != nil {
return err
}
if err = o.unlinkSecretsFromServiceAccount(serviceaccount); err != nil {
return err
}
return o.Printer.PrintObj(serviceaccount, o.Out)
}
// unlinkSecretsFromServiceAccount detaches pull and mount secrets from the service account.
func (o UnlinkSecretOptions) unlinkSecretsFromServiceAccount(serviceaccount *coreapiv1.ServiceAccount) error {
// All of the requested secrets must be present in either the Mount or Pull secrets
// If any of them are not present, we'll return an error and push no changes.
rmSecrets, hasNotFound, err := o.GetSecrets(true)
if err != nil {
return err
}
rmSecretNames := o.GetSecretNames(rmSecrets)
newMountSecrets := []coreapiv1.ObjectReference{}
newPullSecrets := []coreapiv1.LocalObjectReference{}
updated := false
// Check the mount secrets
for _, secret := range serviceaccount.Secrets {
if !rmSecretNames.Has(secret.Name) {
// Copy this back in, since it doesn't match the ones we're removing
newMountSecrets = append(newMountSecrets, secret)
} else {
updated = true
}
}
// Check the image pull secrets
for _, imagePullSecret := range serviceaccount.ImagePullSecrets {
if !rmSecretNames.Has(imagePullSecret.Name) {
// Copy this back in, since it doesn't match the one we're removing
newPullSecrets = append(newPullSecrets, imagePullSecret)
} else {
updated = true
}
}
if updated {
// Save the updated Secret lists back to the server
serviceaccount.Secrets = newMountSecrets
serviceaccount.ImagePullSecrets = newPullSecrets
_, err = o.KubeClient.ServiceAccounts(o.Namespace).Update(serviceaccount)
if err != nil {
return err
}
if hasNotFound {
return fmt.Errorf("Unlinked deleted secrets from %s/%s service account", o.Namespace, serviceaccount.Name)
}
return nil
} else {
return errors.New("No valid secrets found or secrets not linked to service account")
}
}