• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NVIDIA / skyhook / 20322461482

18 Dec 2025 01:07AM UTC coverage: 75.887% (+0.4%) from 75.452%
20322461482

Pull #132

github

web-flow
Merge c36a108b8 into c75dbbfc2
Pull Request #132: refactor(cli): restructure CLI to cmd/cli/app pattern and consolidate lifecycle commands

85 of 110 new or added lines in 2 files covered. (77.27%)

5819 of 7668 relevant lines covered (75.89%)

1.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.06
/operator/cmd/cli/app/lifecycle.go
1
/*
2
 * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
 * SPDX-License-Identifier: Apache-2.0
4
 *
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18

19
package app
20

21
import (
22
        "fmt"
23

24
        "github.com/spf13/cobra"
25

26
        "github.com/NVIDIA/skyhook/operator/internal/cli/client"
27
        cliContext "github.com/NVIDIA/skyhook/operator/internal/cli/context"
28
        "github.com/NVIDIA/skyhook/operator/internal/cli/utils"
29
)
30

31
// lifecycleConfig defines the configuration for a lifecycle command
32
type lifecycleConfig struct {
33
        use          string
34
        short        string
35
        long         string
36
        example      string
37
        annotation   string
38
        action       string // "set" or "remove"
39
        verb         string // past tense for output message (e.g., "paused", "resumed")
40
        confirmVerb  string // verb for confirmation prompt (e.g., "pause", "disable")
41
        needsConfirm bool
42
}
43

44
// lifecycleOptions holds the options for lifecycle commands that need confirmation
45
type lifecycleOptions struct {
46
        confirm bool
47
}
48

49
// newLifecycleCmd creates a lifecycle command based on the provided configuration
50
func newLifecycleCmd(ctx *cliContext.CLIContext, cfg lifecycleConfig) *cobra.Command {
1✔
51
        opts := &lifecycleOptions{}
1✔
52

1✔
53
        cmd := &cobra.Command{
1✔
54
                Use:     cfg.use,
1✔
55
                Short:   cfg.short,
1✔
56
                Long:    cfg.long,
1✔
57
                Example: cfg.example,
1✔
58
                Args:    cobra.ExactArgs(1),
1✔
59
                RunE: func(cmd *cobra.Command, args []string) error {
1✔
NEW
60
                        skyhookName := args[0]
×
NEW
61

×
NEW
62
                        if cfg.needsConfirm && !opts.confirm {
×
NEW
63
                                _, _ = fmt.Fprintf(cmd.OutOrStdout(), "This will %s Skyhook %q. Continue? [y/N]: ",
×
NEW
64
                                        cfg.confirmVerb, skyhookName)
×
NEW
65
                                var response string
×
NEW
66
                                if _, err := fmt.Scanln(&response); err != nil || (response != "y" && response != "Y") {
×
NEW
67
                                        _, _ = fmt.Fprintln(cmd.OutOrStdout(), "Aborted.")
×
NEW
68
                                        return nil
×
NEW
69
                                }
×
70
                        }
71

NEW
72
                        clientFactory := client.NewFactory(ctx.GlobalFlags.ConfigFlags)
×
NEW
73
                        kubeClient, err := clientFactory.Client()
×
NEW
74
                        if err != nil {
×
NEW
75
                                return fmt.Errorf("initializing kubernetes client: %w", err)
×
NEW
76
                        }
×
77

NEW
78
                        if cfg.action == "set" {
×
NEW
79
                                err = utils.SetSkyhookAnnotation(cmd.Context(), kubeClient.Dynamic(), skyhookName, cfg.annotation, "true")
×
NEW
80
                        } else {
×
NEW
81
                                err = utils.RemoveSkyhookAnnotation(cmd.Context(), kubeClient.Dynamic(), skyhookName, cfg.annotation)
×
NEW
82
                        }
×
NEW
83
                        if err != nil {
×
NEW
84
                                return err
×
NEW
85
                        }
×
86

NEW
87
                        _, _ = fmt.Fprintf(cmd.OutOrStdout(), "Skyhook %q %s\n", skyhookName, cfg.verb)
×
NEW
88
                        return nil
×
89
                },
90
        }
91

92
        if cfg.needsConfirm {
2✔
93
                cmd.Flags().BoolVarP(&opts.confirm, "confirm", "y", false, "Skip confirmation prompt")
1✔
94
        }
1✔
95

96
        return cmd
1✔
97
}
98

99
// NewPauseCmd creates the pause command
100
func NewPauseCmd(ctx *cliContext.CLIContext) *cobra.Command {
1✔
101
        return newLifecycleCmd(ctx, lifecycleConfig{
1✔
102
                use:   "pause <skyhook-name>",
1✔
103
                short: "Pause a Skyhook from processing",
1✔
104
                long: `Pause a Skyhook by setting the pause annotation.
1✔
105

1✔
106
When a Skyhook is paused, the operator will stop processing new nodes
1✔
107
but will not interrupt any currently running operations.`,
1✔
108
                example: `  # Pause a Skyhook
1✔
109
  kubectl skyhook pause gpu-init
1✔
110

1✔
111
  # Pause without confirmation
1✔
112
  kubectl skyhook pause gpu-init --confirm`,
1✔
113
                annotation:   utils.PauseAnnotation,
1✔
114
                action:       "set",
1✔
115
                verb:         "paused",
1✔
116
                confirmVerb:  "pause",
1✔
117
                needsConfirm: true,
1✔
118
        })
1✔
119
}
1✔
120

121
// NewResumeCmd creates the resume command
122
func NewResumeCmd(ctx *cliContext.CLIContext) *cobra.Command {
1✔
123
        return newLifecycleCmd(ctx, lifecycleConfig{
1✔
124
                use:   "resume <skyhook-name>",
1✔
125
                short: "Resume a paused Skyhook",
1✔
126
                long: `Resume a paused Skyhook by removing the pause annotation.
1✔
127

1✔
128
The operator will resume processing nodes after this command.`,
1✔
129
                example: `  # Resume a paused Skyhook
1✔
130
  kubectl skyhook resume gpu-init`,
1✔
131
                annotation:   utils.PauseAnnotation,
1✔
132
                action:       "remove",
1✔
133
                verb:         "resumed",
1✔
134
                needsConfirm: false,
1✔
135
        })
1✔
136
}
1✔
137

138
// NewDisableCmd creates the disable command
139
func NewDisableCmd(ctx *cliContext.CLIContext) *cobra.Command {
1✔
140
        return newLifecycleCmd(ctx, lifecycleConfig{
1✔
141
                use:   "disable <skyhook-name>",
1✔
142
                short: "Disable a Skyhook completely",
1✔
143
                long: `Disable a Skyhook by setting the disable annotation.
1✔
144

1✔
145
When a Skyhook is disabled, the operator will completely stop processing
1✔
146
and the Skyhook will be effectively inactive.`,
1✔
147
                example: `  # Disable a Skyhook
1✔
148
  kubectl skyhook disable gpu-init
1✔
149

1✔
150
  # Disable without confirmation
1✔
151
  kubectl skyhook disable gpu-init --confirm`,
1✔
152
                annotation:   utils.DisableAnnotation,
1✔
153
                action:       "set",
1✔
154
                verb:         "disabled",
1✔
155
                confirmVerb:  "disable",
1✔
156
                needsConfirm: true,
1✔
157
        })
1✔
158
}
1✔
159

160
// NewEnableCmd creates the enable command
161
func NewEnableCmd(ctx *cliContext.CLIContext) *cobra.Command {
1✔
162
        return newLifecycleCmd(ctx, lifecycleConfig{
1✔
163
                use:   "enable <skyhook-name>",
1✔
164
                short: "Enable a disabled Skyhook",
1✔
165
                long: `Enable a disabled Skyhook by removing the disable annotation.
1✔
166

1✔
167
The operator will resume normal processing after this command.`,
1✔
168
                example: `  # Enable a disabled Skyhook
1✔
169
  kubectl skyhook enable gpu-init`,
1✔
170
                annotation:   utils.DisableAnnotation,
1✔
171
                action:       "remove",
1✔
172
                verb:         "enabled",
1✔
173
                needsConfirm: false,
1✔
174
        })
1✔
175
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc