-
Notifications
You must be signed in to change notification settings - Fork 314
/
Copy pathenable.go
181 lines (156 loc) · 4.69 KB
/
enable.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package cli
import (
"context"
"fmt"
"strconv"
"time"
"github.com/pkg/errors"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"github.com/tilt-dev/tilt/internal/analytics"
engineanalytics "github.com/tilt-dev/tilt/internal/engine/analytics"
"github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1"
"github.com/tilt-dev/tilt/pkg/model"
)
type enableCmd struct {
all bool
only bool
labels []string
}
func newEnableCmd() *enableCmd {
return &enableCmd{}
}
func (c *enableCmd) name() model.TiltSubcommand { return "enable" }
func (c *enableCmd) register() *cobra.Command {
cmd := &cobra.Command{
Use: "enable {-all | [--only] <resource>...}",
DisableFlagsInUseLine: true,
Short: "Enables resources",
Long: `Enables the specified resources in Tilt.
# enables the resources named 'frontend' and 'backend'
tilt enable frontend backend
# enables frontend and backend and disables all others
tilt enable --only frontend backend
# enables all resources
tilt enable --all
`,
}
addConnectServerFlags(cmd)
cmd.Flags().StringSliceVarP(&c.labels, "labels", "l", c.labels, "Enable all resources with the specified labels")
cmd.Flags().BoolVar(&c.only, "only", false, "Enable the specified resources, disable all others")
cmd.Flags().BoolVar(&c.all, "all", false, "Enable all resources")
return cmd
}
func (c *enableCmd) run(ctx context.Context, args []string) error {
ctrlclient, err := newClient(ctx)
if err != nil {
return err
}
if c.all {
if c.only {
return errors.New("cannot use --all with --only")
} else if len(args) > 0 {
return errors.New("cannot use --all with resource names")
}
} else if len(args) == 0 && len(c.labels) == 0 {
return errors.New("must specify at least one resource")
}
a := analytics.Get(ctx)
cmdTags := engineanalytics.CmdTags(map[string]string{})
cmdTags["only"] = strconv.FormatBool(c.only)
cmdTags["all"] = strconv.FormatBool(c.all)
a.Incr("cmd.enable", cmdTags.AsMap())
defer a.Flush(time.Second)
names := make(map[string]bool)
for _, name := range args {
names[name] = true
}
err = changeEnabledResources(ctx, ctrlclient, args, enableOptions{enable: true, all: c.all, only: c.only, labels: c.labels})
if err != nil {
return err
}
return nil
}
type enableOptions struct {
enable bool
all bool
only bool
labels []string
}
// Changes which resources are enabled in Tilt.
// For resources in `selectedResources`, enable them if `opts.enable` is true, else disable them.
// If `opts.only` is true, enable/disable `selectedResources` as above, and do the opposite to all other resources.
// If `opts.all` is true, ignore `selectedResources` and act on all resources.
func changeEnabledResources(
ctx context.Context,
cli client.Client,
selectedResources []string,
opts enableOptions) error {
var uirs v1alpha1.UIResourceList
err := cli.List(ctx, &uirs)
if err != nil {
return err
}
// before making any changes, validate that all selected names actually exist
uirByName := make(map[string]v1alpha1.UIResource)
for _, uir := range uirs.Items {
uirByName[uir.Name] = uir
}
selectedResourcesByName := make(map[string]bool)
for _, name := range selectedResources {
uir, ok := uirByName[name]
if !ok {
return fmt.Errorf("no such resource %q", name)
}
if len(uir.Status.DisableStatus.Sources) == 0 {
return fmt.Errorf("%s cannot be enabled or disabled", name)
}
selectedResourcesByName[name] = true
}
for _, uir := range uirs.Items {
// resources w/o disable sources are always enabled (e.g., (Tiltfile))
if len(uir.Status.DisableStatus.Sources) == 0 {
continue
}
var enable bool
if selectedResourcesByName[uir.Name] {
enable = opts.enable
} else if len(opts.labels) > 0 {
var hasLabel bool
for _, label := range opts.labels {
if _, hasLabel = uir.Labels[label]; hasLabel {
enable = opts.enable
break
}
}
if !hasLabel {
continue
}
} else if opts.all {
enable = opts.enable
} else if opts.only {
enable = !opts.enable
} else {
continue
}
for _, source := range uir.Status.DisableStatus.Sources {
if source.ConfigMap == nil {
return fmt.Errorf("internal error: resource %s's DisableSource does not have a ConfigMap'", uir.Name)
}
cm := &v1alpha1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: source.ConfigMap.Name}}
_, err := controllerutil.CreateOrUpdate(ctx, cli, cm, func() error {
if cm.Data == nil {
cm.Data = make(map[string]string)
}
cm.Data[source.ConfigMap.Key] = strconv.FormatBool(!enable)
return nil
})
if err != nil {
return err
}
}
}
return nil
}