Skip to content

Commit a45bff9

Browse files
qiujian16claude
andauthored
Add --placement-ref flag to addon create command (#513)
This commit adds support for the --placement-ref flag to the addon create command, allowing users to specify a Placement resource reference for automatic addon installation. Changes: - Add PlacementRef field to Options struct - Add --placement-ref flag accepting namespace/name format - Implement parsePlacementRef() to parse and validate the flag value - Update newClusterManagementAddon() to set InstallStrategy based on flag - Manual strategy when flag is not provided (default behavior) - Placements strategy when flag is provided - Add validation for placement-ref format - Add comprehensive test coverage with 12 test cases including: - Unit tests for parsePlacementRef() - Unit tests for newClusterManagementAddon() - Integration tests for end-to-end functionality Fixes #505 🤖 Generated with [Claude Code](https://claude.com/claude-code) Signed-off-by: Jian Qiu <[email protected]> Co-authored-by: Claude <[email protected]>
1 parent edc0b2a commit a45bff9

File tree

5 files changed

+478
-3
lines changed

5 files changed

+478
-3
lines changed

pkg/cmd/addon/create/cmd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ func NewCmd(clusteradmFlags *genericclioptionsclusteradm.ClusteradmFlags, stream
5252
cmd.Flags().StringVar(&o.ClusterRoleBindingRef, "cluster-role-bind", "", "The rolebinding to the clusterrole in "+
5353
"the cluster namespace for the addon agent")
5454
cmd.Flags().StringSliceVar(&o.Labels, "labels", []string{}, "Labels to add to the ClusterManagementAddOn and AddOnTemplate resources (eg. key1=value1,key2=value2)")
55+
cmd.Flags().StringVar(&o.PlacementRef, "placement-ref", "", "The namespace/name reference to a Placement resource for automatic addon installation (eg. namespace/placement-name)")
5556
o.FileNameFlags.AddFlags(cmd.Flags())
5657

5758
return cmd

pkg/cmd/addon/create/exec.go

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package create
44
import (
55
"context"
66
"fmt"
7+
"strings"
78

89
"github.com/spf13/cobra"
910
"k8s.io/apimachinery/pkg/api/errors"
@@ -76,6 +77,29 @@ func newClusterManagementAddon(o *Options) (*addonv1alpha1.ClusterManagementAddO
7677
return nil, err
7778
}
7879

80+
// Parse placement reference
81+
placementNamespace, placementName, err := o.parsePlacementRef()
82+
if err != nil {
83+
return nil, err
84+
}
85+
86+
installStrategy := addonv1alpha1.InstallStrategy{
87+
Type: addonv1alpha1.AddonInstallStrategyManual,
88+
}
89+
90+
// If placement-ref is provided, change install strategy to Placements
91+
if placementNamespace != "" && placementName != "" {
92+
installStrategy.Type = addonv1alpha1.AddonInstallStrategyPlacements
93+
installStrategy.Placements = []addonv1alpha1.PlacementStrategy{
94+
{
95+
PlacementRef: addonv1alpha1.PlacementRef{
96+
Namespace: placementNamespace,
97+
Name: placementName,
98+
},
99+
},
100+
}
101+
}
102+
79103
cma := &addonv1alpha1.ClusterManagementAddOn{
80104
ObjectMeta: metav1.ObjectMeta{
81105
Name: o.Name,
@@ -96,9 +120,7 @@ func newClusterManagementAddon(o *Options) (*addonv1alpha1.ClusterManagementAddO
96120
},
97121
},
98122
},
99-
InstallStrategy: addonv1alpha1.InstallStrategy{
100-
Type: addonv1alpha1.AddonInstallStrategyManual,
101-
},
123+
InstallStrategy: installStrategy,
102124
},
103125
}
104126

@@ -133,6 +155,14 @@ func (o *Options) Validate() (err error) {
133155
return fmt.Errorf("manifest files must be specified")
134156
}
135157

158+
// Validate placement-ref format if provided
159+
if o.PlacementRef != "" {
160+
_, _, err := o.parsePlacementRef()
161+
if err != nil {
162+
return err
163+
}
164+
}
165+
136166
return nil
137167
}
138168

@@ -249,3 +279,24 @@ func (o *Options) readManifests() ([]workapiv1.Manifest, error) {
249279
func (o *Options) parseLabels() (map[string]string, error) {
250280
return parse.ParseLabels(o.Labels)
251281
}
282+
283+
// parsePlacementRef parses the placement-ref flag and returns namespace and name
284+
func (o *Options) parsePlacementRef() (namespace, name string, err error) {
285+
if o.PlacementRef == "" {
286+
return "", "", nil
287+
}
288+
289+
parts := strings.Split(o.PlacementRef, "/")
290+
if len(parts) != 2 {
291+
return "", "", fmt.Errorf("placement-ref must be in the format 'namespace/name'")
292+
}
293+
294+
namespace = strings.TrimSpace(parts[0])
295+
name = strings.TrimSpace(parts[1])
296+
297+
if namespace == "" || name == "" {
298+
return "", "", fmt.Errorf("placement-ref namespace and name cannot be empty")
299+
}
300+
301+
return namespace, name, nil
302+
}

0 commit comments

Comments
 (0)