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

NVIDIA / skyhook / 20353746630

18 Dec 2025 10:50PM UTC coverage: 75.716% (-0.2%) from 75.958%
20353746630

Pull #133

github

web-flow
Merge a731af90a into 19dce4787
Pull Request #133: fix: cleanup cli code

29 of 63 new or added lines in 9 files covered. (46.03%)

11 existing lines in 6 files now uncovered.

5818 of 7684 relevant lines covered (75.72%)

1.12 hits per line

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

71.07
/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
        "bufio"
23
        "fmt"
24
        "strings"
25

26
        "github.com/spf13/cobra"
27

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

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

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

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

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

×
64
                        if cfg.needsConfirm && !opts.confirm {
×
65
                                _, _ = fmt.Fprintf(cmd.OutOrStdout(), "This will %s Skyhook %q. Continue? [y/N]: ",
×
66
                                        cfg.confirmVerb, skyhookName)
×
NEW
67
                                reader := bufio.NewReader(cmd.InOrStdin())
×
NEW
68
                                response, err := reader.ReadString('\n')
×
NEW
69
                                if err != nil {
×
70
                                        _, _ = fmt.Fprintln(cmd.OutOrStdout(), "Aborted.")
×
71
                                        return nil
×
72
                                }
×
NEW
73
                                response = strings.TrimSpace(response)
×
NEW
74
                                if response != "y" && response != "Y" {
×
NEW
75
                                        _, _ = fmt.Fprintln(cmd.OutOrStdout(), "Aborted.")
×
NEW
76
                                        return nil
×
NEW
77
                                }
×
78
                        }
79

80
                        // Check dry-run before making changes
NEW
81
                        if ctx.GlobalFlags.DryRun {
×
NEW
82
                                _, _ = fmt.Fprintf(cmd.OutOrStdout(), "[dry-run] Would %s Skyhook %q\n", cfg.confirmVerb, skyhookName)
×
NEW
83
                                return nil
×
UNCOV
84
                        }
×
85

86
                        clientFactory := client.NewFactory(ctx.GlobalFlags.ConfigFlags)
×
87
                        kubeClient, err := clientFactory.Client()
×
88
                        if err != nil {
×
89
                                return fmt.Errorf("initializing kubernetes client: %w", err)
×
90
                        }
×
91

92
                        if cfg.action == "set" {
×
93
                                err = utils.SetSkyhookAnnotation(cmd.Context(), kubeClient.Dynamic(), skyhookName, cfg.annotation, "true")
×
94
                        } else {
×
95
                                err = utils.RemoveSkyhookAnnotation(cmd.Context(), kubeClient.Dynamic(), skyhookName, cfg.annotation)
×
96
                        }
×
97
                        if err != nil {
×
98
                                return err
×
99
                        }
×
100

101
                        _, _ = fmt.Fprintf(cmd.OutOrStdout(), "Skyhook %q %s\n", skyhookName, cfg.verb)
×
102
                        return nil
×
103
                },
104
        }
105

106
        if cfg.needsConfirm {
2✔
107
                cmd.Flags().BoolVarP(&opts.confirm, "confirm", "y", false, "Skip confirmation prompt")
1✔
108
        }
1✔
109

110
        return cmd
1✔
111
}
112

113
// NewPauseCmd creates the pause command
114
func NewPauseCmd(ctx *cliContext.CLIContext) *cobra.Command {
1✔
115
        return newLifecycleCmd(ctx, lifecycleConfig{
1✔
116
                use:   "pause <skyhook-name>",
1✔
117
                short: "Pause a Skyhook from processing",
1✔
118
                long: `Pause a Skyhook by setting the pause annotation.
1✔
119

1✔
120
When a Skyhook is paused, the operator will stop processing new nodes
1✔
121
but will not interrupt any currently running operations.`,
1✔
122
                example: `  # Pause a Skyhook
1✔
123
  kubectl skyhook pause gpu-init
1✔
124

1✔
125
  # Pause without confirmation
1✔
126
  kubectl skyhook pause gpu-init --confirm`,
1✔
127
                annotation:   utils.PauseAnnotation,
1✔
128
                action:       "set",
1✔
129
                verb:         "paused",
1✔
130
                confirmVerb:  "pause",
1✔
131
                needsConfirm: true,
1✔
132
        })
1✔
133
}
1✔
134

135
// NewResumeCmd creates the resume command
136
func NewResumeCmd(ctx *cliContext.CLIContext) *cobra.Command {
1✔
137
        return newLifecycleCmd(ctx, lifecycleConfig{
1✔
138
                use:   "resume <skyhook-name>",
1✔
139
                short: "Resume a paused Skyhook",
1✔
140
                long: `Resume a paused Skyhook by removing the pause annotation.
1✔
141

1✔
142
The operator will resume processing nodes after this command.`,
1✔
143
                example: `  # Resume a paused Skyhook
1✔
144
  kubectl skyhook resume gpu-init`,
1✔
145
                annotation:   utils.PauseAnnotation,
1✔
146
                action:       "remove",
1✔
147
                verb:         "resumed",
1✔
148
                confirmVerb:  "resume",
1✔
149
                needsConfirm: false,
1✔
150
        })
1✔
151
}
1✔
152

153
// NewDisableCmd creates the disable command
154
func NewDisableCmd(ctx *cliContext.CLIContext) *cobra.Command {
1✔
155
        return newLifecycleCmd(ctx, lifecycleConfig{
1✔
156
                use:   "disable <skyhook-name>",
1✔
157
                short: "Disable a Skyhook completely",
1✔
158
                long: `Disable a Skyhook by setting the disable annotation.
1✔
159

1✔
160
When a Skyhook is disabled, the operator will completely stop processing
1✔
161
and the Skyhook will be effectively inactive.`,
1✔
162
                example: `  # Disable a Skyhook
1✔
163
  kubectl skyhook disable gpu-init
1✔
164

1✔
165
  # Disable without confirmation
1✔
166
  kubectl skyhook disable gpu-init --confirm`,
1✔
167
                annotation:   utils.DisableAnnotation,
1✔
168
                action:       "set",
1✔
169
                verb:         "disabled",
1✔
170
                confirmVerb:  "disable",
1✔
171
                needsConfirm: true,
1✔
172
        })
1✔
173
}
1✔
174

175
// NewEnableCmd creates the enable command
176
func NewEnableCmd(ctx *cliContext.CLIContext) *cobra.Command {
1✔
177
        return newLifecycleCmd(ctx, lifecycleConfig{
1✔
178
                use:   "enable <skyhook-name>",
1✔
179
                short: "Enable a disabled Skyhook",
1✔
180
                long: `Enable a disabled Skyhook by removing the disable annotation.
1✔
181

1✔
182
The operator will resume normal processing after this command.`,
1✔
183
                example: `  # Enable a disabled Skyhook
1✔
184
  kubectl skyhook enable gpu-init`,
1✔
185
                annotation:   utils.DisableAnnotation,
1✔
186
                action:       "remove",
1✔
187
                verb:         "enabled",
1✔
188
                confirmVerb:  "enable",
1✔
189
                needsConfirm: false,
1✔
190
        })
1✔
191
}
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