-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: yaroslavborbat <[email protected]>
- Loading branch information
1 parent
907380a
commit b365262
Showing
6 changed files
with
459 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
/* | ||
Copyright 2024 Flant JSC | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package powerstate | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
"github.com/deckhouse/virtualization/api/client/kubeclient" | ||
"github.com/spf13/pflag" | ||
"k8s.io/apimachinery/pkg/types" | ||
"k8s.io/client-go/tools/clientcmd" | ||
|
||
"github.com/deckhouse/deckhouse-cli/internal/virtualization/cmd/powerstate/vmop" | ||
"github.com/deckhouse/deckhouse-cli/internal/virtualization/templates" | ||
) | ||
|
||
type Command string | ||
|
||
const ( | ||
Stop Command = "stop" | ||
Start Command = "start" | ||
Restart Command = "restart" | ||
) | ||
|
||
type Manager interface { | ||
Stop(ctx context.Context, name, namespace string, wait, force bool) (msg string, err error) | ||
Start(ctx context.Context, name, namespace string, wait bool) (msg string, err error) | ||
Restart(ctx context.Context, name, namespace string, wait, force bool) (msg string, err error) | ||
} | ||
|
||
type Type string | ||
|
||
const TypeVirtualMachineOperation Type = "VirtualMachineOperation" | ||
|
||
func NewManager(t Type, client kubeclient.Client) (Manager, error) { | ||
switch t { | ||
case TypeVirtualMachineOperation: | ||
return vmop.New(client), nil | ||
default: | ||
return nil, fmt.Errorf("invalid type %q", t) | ||
} | ||
} | ||
|
||
func NewPowerState(cmd Command, clientConfig clientcmd.ClientConfig) *PowerState { | ||
return &PowerState{ | ||
cmd: cmd, | ||
clientConfig: clientConfig, | ||
opts: DefaultOptions(), | ||
} | ||
} | ||
|
||
type PowerState struct { | ||
cmd Command | ||
clientConfig clientcmd.ClientConfig | ||
opts Options | ||
} | ||
|
||
func DefaultOptions() Options { | ||
return Options{ | ||
Force: false, | ||
Wait: false, | ||
Timeout: 30 * time.Second, | ||
} | ||
} | ||
|
||
type Options struct { | ||
Force bool | ||
Wait bool | ||
Timeout time.Duration | ||
} | ||
|
||
func (ps *PowerState) Run(args []string) error { | ||
name, namespace, err := ps.getNameNamespace(args) | ||
key := types.NamespacedName{Namespace: namespace, Name: name} | ||
if err != nil { | ||
return err | ||
} | ||
mgr, err := ps.getManager() | ||
if err != nil { | ||
return err | ||
} | ||
ctx, cancel := context.WithTimeout(context.Background(), ps.opts.Timeout) | ||
defer cancel() | ||
writer := os.Stdout | ||
var msg string | ||
switch ps.cmd { | ||
case Stop: | ||
fmt.Fprint(writer, fmt.Sprintf("Stopping virtual machine %q\n", key.String())) | ||
msg, err = mgr.Stop(ctx, name, namespace, ps.opts.Wait, ps.opts.Force) | ||
case Start: | ||
fmt.Fprint(writer, fmt.Sprintf("Starting virtual machine %q\n", key.String())) | ||
msg, err = mgr.Start(ctx, name, namespace, ps.opts.Wait) | ||
case Restart: | ||
fmt.Fprint(writer, fmt.Sprintf("Restarting virtual machine %q\n", key.String())) | ||
msg, err = mgr.Restart(ctx, name, namespace, ps.opts.Wait, ps.opts.Force) | ||
default: | ||
return fmt.Errorf("invalid command %q", ps.cmd) | ||
} | ||
if msg != "" { | ||
fmt.Fprint(os.Stdout, msg) | ||
} | ||
return err | ||
} | ||
|
||
func (ps *PowerState) Usage() string { | ||
opts := DefaultOptions() | ||
usage := fmt.Sprintf(` # %s VirtualMachine 'myvm':`, strings.Title(string(ps.cmd))) | ||
usage += strings.Replace(fmt.Sprintf(` | ||
{{ProgramName}} {{operation}} myvm | ||
{{ProgramName}} {{operation}} myvm.mynamespace | ||
{{ProgramName}} {{operation}} myvm -n mynamespace | ||
# Configure one minute timeout (default: timeout=%v) | ||
{{ProgramName}} {{operation}} --%s=1m myvm | ||
# Configure wait vm phase (default: wait=%v) | ||
{{ProgramName}} {{operation}} --%s myvm`, opts.Timeout, timeoutFlag, opts.Wait, waitFlag), "{{operation}}", string(ps.cmd), -1) | ||
if ps.cmd != Start { | ||
usage += fmt.Sprintf(` | ||
# Configure shutdown policy (default: force=%v) | ||
{{ProgramName}} %s --%s myvm`, opts.Force, ps.cmd, forceFlag) | ||
} | ||
return usage | ||
} | ||
|
||
func (ps *PowerState) getNameNamespace(args []string) (string, string, error) { | ||
namespace, name, err := templates.ParseTarget(args[0]) | ||
if err != nil { | ||
return "", "", err | ||
} | ||
if namespace == "" { | ||
namespace, _, err = ps.clientConfig.Namespace() | ||
if err != nil { | ||
return "", "", err | ||
} | ||
} | ||
return name, namespace, nil | ||
} | ||
|
||
func (ps *PowerState) getManager() (Manager, error) { | ||
virtCli, err := kubeclient.GetClientFromClientConfig(ps.clientConfig) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return NewManager(TypeVirtualMachineOperation, virtCli) | ||
} | ||
|
||
const ( | ||
forceFlag, forceFlagShort = "force", "f" | ||
waitFlag, waitFlagShort = "wait", "w" | ||
timeoutFlag, timeoutFlagShort = "timeout", "t" | ||
) | ||
|
||
func AddCommandlineArgs(flagset *pflag.FlagSet, opts *Options) { | ||
flagset.BoolVarP(&opts.Force, forceFlag, forceFlagShort, opts.Force, | ||
fmt.Sprintf("--%s, -%s: Set this flag to force the operation.", forceFlag, forceFlagShort)) | ||
flagset.BoolVarP(&opts.Wait, waitFlag, waitFlagShort, opts.Wait, | ||
fmt.Sprintf("--%s, -%s: Set this flag to wait for the operation to complete.", waitFlag, waitFlagShort)) | ||
flagset.DurationVarP(&opts.Timeout, timeoutFlag, timeoutFlagShort, opts.Timeout, | ||
fmt.Sprintf("--%s, -%s: Set this flag to change the timeout.", timeoutFlag, timeoutFlagShort)) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
Copyright 2024 Flant JSC | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package powerstate | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
"k8s.io/client-go/tools/clientcmd" | ||
|
||
"github.com/deckhouse/deckhouse-cli/internal/virtualization/templates" | ||
) | ||
|
||
func NewRestartCommand(clientConfig clientcmd.ClientConfig) *cobra.Command { | ||
ps := NewPowerState(Restart, clientConfig) | ||
restart := string(Restart) | ||
cmd := &cobra.Command{ | ||
Use: restart + " (VirtualMachine)", | ||
Short: strings.Title(restart) + " a virtual machine.", | ||
Example: ps.Usage(), | ||
Args: templates.ExactArgs(restart, 1), | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return ps.Run(args) | ||
}, | ||
} | ||
AddCommandlineArgs(cmd.Flags(), &ps.opts) | ||
cmd.SetUsageTemplate(templates.UsageTemplate()) | ||
return cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
Copyright 2024 Flant JSC | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package powerstate | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
"k8s.io/client-go/tools/clientcmd" | ||
|
||
"github.com/deckhouse/deckhouse-cli/internal/virtualization/templates" | ||
) | ||
|
||
func NewStartCommand(clientConfig clientcmd.ClientConfig) *cobra.Command { | ||
ps := NewPowerState(Start, clientConfig) | ||
start := string(Start) | ||
cmd := &cobra.Command{ | ||
Use: start + " (VirtualMachine)", | ||
Short: strings.Title(start) + " a virtual machine.", | ||
Example: ps.Usage(), | ||
Args: templates.ExactArgs(start, 1), | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return ps.Run(args) | ||
}, | ||
} | ||
AddCommandlineArgs(cmd.Flags(), &ps.opts) | ||
cmd.SetUsageTemplate(templates.UsageTemplate()) | ||
return cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
Copyright 2024 Flant JSC | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package powerstate | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
"k8s.io/client-go/tools/clientcmd" | ||
|
||
"github.com/deckhouse/deckhouse-cli/internal/virtualization/templates" | ||
) | ||
|
||
func NewStopCommand(clientConfig clientcmd.ClientConfig) *cobra.Command { | ||
ps := NewPowerState(Stop, clientConfig) | ||
stop := string(Stop) | ||
cmd := &cobra.Command{ | ||
Use: stop + " (VirtualMachine)", | ||
Short: strings.Title(stop) + " a virtual machine.", | ||
Example: ps.Usage(), | ||
Args: templates.ExactArgs(stop, 1), | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return ps.Run(args) | ||
}, | ||
} | ||
AddCommandlineArgs(cmd.Flags(), &ps.opts) | ||
cmd.SetUsageTemplate(templates.UsageTemplate()) | ||
return cmd | ||
} |
Oops, something went wrong.