Skip to content

Commit 986626c

Browse files
committed
default operator install approval to 'Manual'; auto-approve initial install
1 parent a7b5cd1 commit 986626c

File tree

4 files changed

+75
-11
lines changed

4 files changed

+75
-11
lines changed

internal/cmd/operator_list_available.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ func newOperatorListAvailableCmd(cfg *action.Configuration) *cobra.Command {
2121
cmd := &cobra.Command{
2222
Use: "list-available",
2323
Short: "List operators available to be installed",
24-
Args: cobra.ExactArgs(0),
24+
Args: cobra.MaximumNArgs(1),
2525
Run: func(cmd *cobra.Command, args []string) {
26+
if len(args) == 1 {
27+
l.Package = args[0]
28+
}
29+
2630
operators, err := l.Run(cmd.Context())
2731
if err != nil {
2832
log.Fatal(err)

internal/pkg/action/operator_install.go

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package action
22

33
import (
44
"context"
5-
"flag"
65
"fmt"
76
"time"
87

@@ -25,7 +24,7 @@ type OperatorInstall struct {
2524

2625
Package string
2726
Channel string
28-
Approve string
27+
Approval subscription.ApprovalValue
2928
InstallMode operator.InstallMode
3029
InstallTimeout time.Duration
3130
CleanupTimeout time.Duration
@@ -40,12 +39,11 @@ func NewOperatorInstall(cfg *Configuration) *OperatorInstall {
4039

4140
func (i *OperatorInstall) BindFlags(fs *pflag.FlagSet) {
4241
fs.StringVarP(&i.Channel, "channel", "c", "", "subscription channel")
43-
fs.StringVarP(&i.Approve, "approval", "a", "", "approval (Automatic or Manual)")
42+
fs.VarP(&i.Approval, "approval", "a", fmt.Sprintf("approval (%s or %s)", v1alpha1.ApprovalManual, v1alpha1.ApprovalAutomatic))
43+
fs.VarP(&i.InstallMode, "install-mode", "i", "install mode")
4444
fs.DurationVarP(&i.InstallTimeout, "timeout", "t", time.Minute, "the amount of time to wait before cancelling the install")
4545
fs.DurationVar(&i.CleanupTimeout, "cleanup-timeout", time.Minute, "the amount to time to wait before cancelling cleanup")
4646
fs.BoolVar(&i.CreateOperatorGroup, "create-operator-group", false, "create operator group if necessary")
47-
imVal := pflag.PFlagFromGoFlag(&flag.Flag{Value: &i.InstallMode}).Value
48-
fs.VarP(imVal, "install-mode", "i", "install mode")
4947
}
5048

5149
func (i *OperatorInstall) Run(ctx context.Context) (*v1alpha1.ClusterServiceVersion, error) {
@@ -85,9 +83,7 @@ func (i *OperatorInstall) Run(ctx context.Context) (*v1alpha1.ClusterServiceVers
8583
}
8684

8785
opts := []subscription.Option{}
88-
if i.Approve != "" {
89-
opts = append(opts, subscription.InstallPlanApproval(v1alpha1.Approval(i.Approve)))
90-
}
86+
opts = append(opts, subscription.InstallPlanApproval(i.Approval.Approval))
9187

9288
subKey := types.NamespacedName{
9389
Namespace: i.config.Namespace,
@@ -103,6 +99,34 @@ func (i *OperatorInstall) Run(ctx context.Context) (*v1alpha1.ClusterServiceVers
10399
}
104100
log.Printf("subscription %q created", sub.Name)
105101

102+
// We need to approve the initial install plan
103+
if i.Approval.Approval == v1alpha1.ApprovalManual {
104+
if err := wait.PollImmediateUntil(time.Millisecond*250, func() (bool, error) {
105+
if err := i.config.Client.Get(ctx, subKey, sub); err != nil {
106+
return false, err
107+
}
108+
if sub.Status.InstallPlanRef != nil {
109+
return true, nil
110+
}
111+
return false, nil
112+
}, ctx.Done()); err != nil {
113+
return nil, fmt.Errorf("waiting for subscription install plan to exist: %v", err)
114+
}
115+
116+
ip := v1alpha1.InstallPlan{}
117+
ipKey := types.NamespacedName{
118+
Namespace: sub.Status.InstallPlanRef.Namespace,
119+
Name: sub.Status.InstallPlanRef.Name,
120+
}
121+
if err := i.config.Client.Get(ctx, ipKey, &ip); err != nil {
122+
return nil, fmt.Errorf("get install plan: %v", err)
123+
}
124+
ip.Spec.Approved = true
125+
if err := i.config.Client.Update(ctx, &ip); err != nil {
126+
return nil, fmt.Errorf("approve install plan: %v", err)
127+
}
128+
}
129+
106130
if err := wait.PollImmediateUntil(time.Millisecond*250, func() (bool, error) {
107131
if err := i.config.Client.Get(ctx, subKey, sub); err != nil {
108132
return false, err
@@ -112,7 +136,7 @@ func (i *OperatorInstall) Run(ctx context.Context) (*v1alpha1.ClusterServiceVers
112136
}
113137
return false, nil
114138
}, ctx.Done()); err != nil {
115-
return nil, fmt.Errorf("waiting for state \"AtLatestKnown\": %v", err)
139+
return nil, fmt.Errorf("waiting for subscription state \"AtLatestKnown\": %v", err)
116140
}
117141

118142
csvKey := types.NamespacedName{

internal/pkg/action/operator_list_available.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type OperatorListAvailable struct {
1515
config *Configuration
1616

1717
Catalog NamespacedName
18+
Package string
1819
}
1920

2021
func NewOperatorListAvailable(cfg *Configuration) *OperatorListAvailable {
@@ -24,15 +25,22 @@ func NewOperatorListAvailable(cfg *Configuration) *OperatorListAvailable {
2425
}
2526

2627
func (l *OperatorListAvailable) Run(ctx context.Context) ([]v1.PackageManifest, error) {
27-
pms := v1.PackageManifestList{}
28+
if l.Package != "" {
29+
return nil, fmt.Errorf("listing all versions of a package is not currently supported")
30+
}
31+
return l.getAllPackageManifests(ctx)
32+
}
2833

34+
func (l *OperatorListAvailable) getAllPackageManifests(ctx context.Context) ([]v1.PackageManifest, error) {
2935
labelSelector := client.MatchingLabels{}
3036
if l.Catalog.Name != "" {
3137
labelSelector["catalog"] = l.Catalog.Name
3238
}
3339
if l.Catalog.Namespace != "" {
3440
labelSelector["catalog-namespace"] = l.Catalog.Namespace
3541
}
42+
43+
pms := v1.PackageManifestList{}
3644
if err := l.config.Client.List(ctx, &pms, labelSelector); err != nil {
3745
return nil, err
3846
}

internal/pkg/subscription/subscription.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package subscription
22

33
import (
4+
"fmt"
5+
46
"github.com/operator-framework/api/pkg/operators/v1alpha1"
57
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
68
"k8s.io/apimachinery/pkg/types"
@@ -32,3 +34,29 @@ func Build(key types.NamespacedName, channel string, source types.NamespacedName
3234
}
3335
return s
3436
}
37+
38+
const defaultApproval = v1alpha1.ApprovalManual
39+
40+
type ApprovalValue struct {
41+
v1alpha1.Approval
42+
}
43+
44+
func (a *ApprovalValue) Set(str string) error {
45+
switch v := v1alpha1.Approval(str); v {
46+
case v1alpha1.ApprovalAutomatic, v1alpha1.ApprovalManual:
47+
a.Approval = v
48+
return nil
49+
}
50+
return fmt.Errorf("invalid approval value %q", str)
51+
}
52+
53+
func (a *ApprovalValue) String() string {
54+
if a.Approval == "" {
55+
a.Approval = defaultApproval
56+
}
57+
return string(a.Approval)
58+
}
59+
60+
func (a ApprovalValue) Type() string {
61+
return "ApprovalValue"
62+
}

0 commit comments

Comments
 (0)