Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ssh - completion with machine objects #347

Merged
merged 16 commits into from
Jan 10, 2024
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/fatih/color v1.15.0
github.com/gardener/gardener v1.80.3
github.com/gardener/gardener-extension-provider-openstack v1.36.0
github.com/gardener/machine-controller-manager v0.50.0
github.com/golang/mock v1.6.0
github.com/google/uuid v1.3.1
github.com/mitchellh/go-homedir v1.1.0
Expand Down Expand Up @@ -45,7 +46,6 @@ require (
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gardener/etcd-druid v0.19.2 // indirect
github.com/gardener/hvpa-controller/api v0.5.0 // indirect
github.com/gardener/machine-controller-manager v0.48.1 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-logr/logr v1.2.4 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ github.com/gardener/gardener-extension-provider-openstack v1.36.0 h1:Zif2gepqRde
github.com/gardener/gardener-extension-provider-openstack v1.36.0/go.mod h1:fip83z/jRkH0kTyx0/GGTzSRgcL4hYVGi9i3x9ZROVc=
github.com/gardener/hvpa-controller/api v0.5.0 h1:f4F3O7YUrenwh4S3TgPREPiB287JjjUiUL18OqPLyAA=
github.com/gardener/hvpa-controller/api v0.5.0/go.mod h1:QQl3ELkCaki+8RhXl0FZMfvnm0WCGwGJlGmrxJj6lvM=
github.com/gardener/machine-controller-manager v0.48.1 h1:Oxr5e6gRm7P40Ds4nGlga/0nmfF7cH4rOfjthR6Mm38=
github.com/gardener/machine-controller-manager v0.48.1/go.mod h1:Axeu1Oh3agySk0oR4T+FUNax41Ni2K8tuksu8KRHuh0=
github.com/gardener/machine-controller-manager v0.50.0 h1:3dcQjzueFU1TGgprV00adjb3OCR99myTBx8DQGxywks=
github.com/gardener/machine-controller-manager v0.50.0/go.mod h1:RySZ40AgbNV/wMq60G/w49kb+okbj5Xs1A6usz5Pm/I=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
operationsv1alpha1 "github.com/gardener/gardener/pkg/apis/operations/v1alpha1"
seedmanagementv1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1"
machinev1alpha1 "github.com/gardener/machine-controller-manager/pkg/apis/machine/v1alpha1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/kubernetes/scheme"

Expand All @@ -19,6 +20,7 @@ func main() {
utilruntime.Must(gardencorev1beta1.AddToScheme(scheme.Scheme))
utilruntime.Must(operationsv1alpha1.AddToScheme(scheme.Scheme))
utilruntime.Must(seedmanagementv1alpha1.AddToScheme(scheme.Scheme))
utilruntime.Must(machinev1alpha1.AddToScheme(scheme.Scheme))

cmd.Execute()
}
77 changes: 66 additions & 11 deletions pkg/cmd/ssh/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/gardener/gardener/pkg/utils"
gutil "github.com/gardener/gardener/pkg/utils/gardener"
"github.com/gardener/gardener/pkg/utils/secrets"
machinev1alpha1 "github.com/gardener/machine-controller-manager/pkg/apis/machine/v1alpha1"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"golang.org/x/crypto/ssh"
Expand Down Expand Up @@ -820,13 +821,15 @@ func cleanup(ctx context.Context, o *SSHOptions, gardenClient client.Client, bas
}
}

func getNodeNamesFromShoot(f util.Factory, prefix string) ([]string, error) {
func getNodeNamesFromMachinesOrNodes(f util.Factory) ([]string, error) {
petersutter marked this conversation as resolved.
Show resolved Hide resolved
ctx := f.Context()
logger := klog.FromContext(ctx)

manager, err := f.Manager()
if err != nil {
return nil, err
}

// validate the current target
currentTarget, err := manager.CurrentTarget()
if err != nil {
return nil, err
Expand All @@ -836,25 +839,68 @@ func getNodeNamesFromShoot(f util.Factory, prefix string) ([]string, error) {
return nil, errors.New("no Shoot cluster targeted")
}

// create client for the shoot cluster
shootClient, err := manager.ShootClient(f.Context(), currentTarget)
nodeNames, err := getNodeNamesFromMachines(ctx, manager, currentTarget)
if err != nil {
if !apierrors.IsForbidden(err) {
logger.Info("failed to fetch node names from machine objects", "err", err)
}

return getNodeNamesFromNodes(ctx, manager, currentTarget)
}

return nodeNames, nil
}

func getNodeNamesFromMachines(ctx context.Context, manager target.Manager, currentTarget target.Target) ([]string, error) {
gardenClient, err := manager.GardenClient(currentTarget.GardenName())
if err != nil {
return nil, fmt.Errorf("failed to create garden cluster client: %w", err)
}

shoot, err := gardenClient.FindShoot(ctx, currentTarget.AsListOption())
if err != nil {
return nil, err
}

seedTarget := target.NewTarget(currentTarget.GardenName(), "", *shoot.Spec.SeedName, "")

seedClient, err := manager.SeedClient(ctx, seedTarget)
if err != nil {
return nil, err
}

// fetch all nodes
nodes, err := getNodes(f.Context(), shootClient)
machines, err := getMachines(ctx, seedClient, shoot.Status.TechnicalID)
if err != nil {
return nil, err
}

// collect names, filter by prefix
nodeNames := []string{}
var nodeNames []string

for _, node := range nodes {
if strings.HasPrefix(node.Name, prefix) {
nodeNames = append(nodeNames, node.Name)
for _, machine := range machines {
if _, ok := machine.Labels[machinev1alpha1.NodeLabelKey]; !ok {
continue
}

nodeNames = append(nodeNames, machine.Labels[machinev1alpha1.NodeLabelKey])
}

return nodeNames, nil
}

func getNodeNamesFromNodes(ctx context.Context, manager target.Manager, currentTarget target.Target) ([]string, error) {
shootClient, err := manager.ShootClient(ctx, currentTarget)
if err != nil {
return nil, err
}

nodes, err := getNodes(ctx, shootClient)
if err != nil {
return nil, err
}

var nodeNames []string
for _, node := range nodes {
nodeNames = append(nodeNames, node.Name)
}

return nodeNames, nil
Expand Down Expand Up @@ -1103,6 +1149,15 @@ func getNodes(ctx context.Context, c client.Client) ([]corev1.Node, error) {
return nodeList.Items, nil
}

func getMachines(ctx context.Context, c client.Client, namespace string) ([]machinev1alpha1.Machine, error) {
machineList := machinev1alpha1.MachineList{}
if err := c.List(ctx, &machineList, client.InNamespace(namespace)); err != nil {
return nil, fmt.Errorf("failed to list machines: %w", err)
}

return machineList.Items, nil
}

func (o *SSHOptions) checkAccessRestrictions(cfg *config.Config, gardenName string, tf target.TargetFlags, shoot *gardencorev1beta1.Shoot) (bool, error) {
if cfg == nil {
return false, errors.New("garden configuration is required")
Expand Down
13 changes: 11 additions & 2 deletions pkg/cmd/ssh/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ SPDX-License-Identifier: Apache-2.0
package ssh

import (
"strings"

"github.com/spf13/cobra"
"k8s.io/klog/v2"

Expand Down Expand Up @@ -51,13 +53,20 @@ gardenctl ssh --keep-bastion --bastion-name cli-xxxxxxxx --public-key-file /path
return nil, cobra.ShellCompDirectiveNoFileComp
}

nodeNames, err := getNodeNamesFromShoot(f, toComplete)
nodeNames, err := getNodeNamesFromMachinesOrNodes(f)
if err != nil {
logger.Error(err, "could not get node names from shoot")
return nil, cobra.ShellCompDirectiveNoFileComp
}

return nodeNames, cobra.ShellCompDirectiveNoFileComp
var completions []string
for _, nodeName := range nodeNames {
if strings.HasPrefix(nodeName, toComplete) {
completions = append(completions, nodeName)
}
}

return completions, cobra.ShellCompDirectiveNoFileComp
},
RunE: base.WrapRunE(o, f),
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/cmd/ssh/ssh_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
operationsv1alpha1 "github.com/gardener/gardener/pkg/apis/operations/v1alpha1"
machinev1alpha1 "github.com/gardener/machine-controller-manager/pkg/apis/machine/v1alpha1"
"github.com/google/uuid"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
Expand All @@ -23,6 +24,7 @@ import (
func init() {
utilruntime.Must(gardencorev1beta1.AddToScheme(scheme.Scheme))
utilruntime.Must(operationsv1alpha1.AddToScheme(scheme.Scheme))
utilruntime.Must(machinev1alpha1.AddToScheme(scheme.Scheme))
}

func TestCommand(t *testing.T) {
Expand Down
Loading
Loading