From 0a253f9f32fca0738808bf2966ea7b31761ed738 Mon Sep 17 00:00:00 2001 From: Ted Teng Date: Thu, 11 Jan 2024 09:36:33 +0800 Subject: [PATCH 1/3] init --- pkg/cmd/ssh/options.go | 64 +++++++++++++++++++++++++++++++++++++++++ pkg/cmd/ssh/ssh_test.go | 7 +++-- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/ssh/options.go b/pkg/cmd/ssh/options.go index 85670af6..ffcc6555 100644 --- a/pkg/cmd/ssh/options.go +++ b/pkg/cmd/ssh/options.go @@ -231,6 +231,11 @@ type SSHOptions struct { // ConfirmAccessRestriction, when set to true, implies the user understands the access restrictions for the targeted shoot. // In this case, the access restriction banner is displayed without further confirmation. ConfirmAccessRestriction bool + + // Operator is determines whether the command should be have the operator role assigned. + Operator bool + + client client.Client } // NewSSHOptions returns initialized SSHOptions. @@ -247,6 +252,7 @@ func NewSSHOptions(ioStreams util.IOStreams) *SSHOptions { NoKeepalive: false, BastionPort: strconv.Itoa(SSHPort), User: DefaultUsername, + Operator: false, } } @@ -537,6 +543,27 @@ func (o *SSHOptions) Run(f util.Factory) error { return err } + if shoot.Status.TechnicalID == "" { + return fmt.Errorf("shoot technical ID is empty: %w", err) + } + + // check operator role + if !o.Operator { + seedTarget := target.NewTarget(currentTarget.GardenName(), "", *shoot.Spec.SeedName, "") + + seedClient, err := manager.SeedClient(ctx, seedTarget) + if err != nil { + if !apierrors.IsForbidden(err) { + return nil + } + + return err + } + + o.Operator = true + o.client = seedClient + } + // check access restrictions ok, err := o.checkAccessRestrictions(manager.Configuration(), currentTarget.GardenName(), f.TargetFlags(), shoot) if err != nil { @@ -654,6 +681,43 @@ func (o *SSHOptions) Run(f util.Factory) error { } } + if o.Operator { + machines, err := getMachines(ctx, o.client, shoot.Status.TechnicalID) + if err != nil { + return fmt.Errorf("failed to list shoot cluster machines: %w", err) + } + + if len(machines) != len(nodes) { + type empty struct{} + + nodeSets := make(map[string]empty, len(nodes)) + + for _, node := range nodes { + nodeSets[node.Name] = empty{} + } + + for _, machine := range machines { + if _, ok := machine.Labels[machinev1alpha1.NodeLabelKey]; !ok { + continue + } + + if _, ok := nodeSets[machine.Labels[machinev1alpha1.NodeLabelKey]]; !ok { + nodes = append(nodes, corev1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: machine.Labels[machinev1alpha1.NodeLabelKey]}, + Status: corev1.NodeStatus{ + Conditions: []corev1.NodeCondition{ + { + Type: corev1.NodeReady, + Status: corev1.ConditionUnknown, + }, + }, + }, + }) + } + } + } + } + connectInformation, err := NewConnectInformation( bastion, bastionPreferredAddress, diff --git a/pkg/cmd/ssh/ssh_test.go b/pkg/cmd/ssh/ssh_test.go index 0cba7122..1660d520 100644 --- a/pkg/cmd/ssh/ssh_test.go +++ b/pkg/cmd/ssh/ssh_test.go @@ -302,14 +302,17 @@ var _ = Describe("SSH Command", func() { }) Describe("RunE", func() { + var manager *targetmocks.MockManager + BeforeEach(func() { - clientProvider.EXPECT().FromClientConfig(gomock.Any()).Return(shootClient, nil).AnyTimes(). + clientProvider.EXPECT().FromClientConfig(gomock.Any()).Return(shootClient, nil).AnyTimes() + manager = targetmocks.NewMockManager(ctrl) + manager.EXPECT().ShootClient(ctx, currentTarget).Return(shootClient, nil).AnyTimes(). Do(func(clientConfig clientcmd.ClientConfig) { config, err := clientConfig.RawConfig() Expect(err).NotTo(HaveOccurred()) Expect(config.CurrentContext).To(Equal(testShoot.Namespace + "--" + testShoot.Name + "-" + testShoot.Status.AdvertisedAddresses[0].Name)) }) - shootClient = internalfake.NewClientWithObjects(testNode) }) From 326401efaf6bf35b12f005b7aa6d79b6e415e786 Mon Sep 17 00:00:00 2001 From: Ted Teng Date: Mon, 15 Jan 2024 10:06:14 +0800 Subject: [PATCH 2/3] per feedback --- pkg/cmd/ssh/connect_information.go | 29 +++++++++++++ pkg/cmd/ssh/options.go | 67 ++++-------------------------- 2 files changed, 37 insertions(+), 59 deletions(-) diff --git a/pkg/cmd/ssh/connect_information.go b/pkg/cmd/ssh/connect_information.go index dc19308a..594a40d9 100644 --- a/pkg/cmd/ssh/connect_information.go +++ b/pkg/cmd/ssh/connect_information.go @@ -35,6 +35,9 @@ type ConnectInformation struct { // User is the name of the Shoot cluster node ssh login username User string + + // Machines is a list of machines name + Machines []string } var _ fmt.Stringer = &ConnectInformation{} @@ -87,6 +90,7 @@ func NewConnectInformation( sshPrivateKeyFile PrivateKeyFile, nodePrivateKeyFiles []PrivateKeyFile, nodes []corev1.Node, + machines []string, user string, ) (*ConnectInformation, error) { var nodeList []Node @@ -144,6 +148,7 @@ func NewConnectInformation( NodeHostname: nodeHostname, NodePrivateKeyFiles: nodePrivateKeyFiles, Nodes: nodeList, + Machines: machines, User: user, }, nil } @@ -195,6 +200,30 @@ func (p *ConnectInformation) String() string { return "" } + if len(p.Machines) != 0 && len(p.Machines) != len(p.Nodes) { + type empty struct{} + + nodeSets := make(map[string]empty, len(p.Nodes)) + + var missingNodes []string + + for _, node := range p.Nodes { + nodeSets[node.Name] = empty{} + } + + for _, machine := range p.Machines { + if _, ok := nodeSets[machine]; !ok { + missingNodes = append(missingNodes, machine) + } + } + + for _, node := range missingNodes { + table.Rows = append(table.Rows, metav1.TableRow{ + Cells: []interface{}{node, "unknown", "unknown"}, + }) + } + } + fmt.Fprintln(&buf, "") } diff --git a/pkg/cmd/ssh/options.go b/pkg/cmd/ssh/options.go index ffcc6555..1ef050c1 100644 --- a/pkg/cmd/ssh/options.go +++ b/pkg/cmd/ssh/options.go @@ -231,11 +231,6 @@ type SSHOptions struct { // ConfirmAccessRestriction, when set to true, implies the user understands the access restrictions for the targeted shoot. // In this case, the access restriction banner is displayed without further confirmation. ConfirmAccessRestriction bool - - // Operator is determines whether the command should be have the operator role assigned. - Operator bool - - client client.Client } // NewSSHOptions returns initialized SSHOptions. @@ -252,7 +247,6 @@ func NewSSHOptions(ioStreams util.IOStreams) *SSHOptions { NoKeepalive: false, BastionPort: strconv.Itoa(SSHPort), User: DefaultUsername, - Operator: false, } } @@ -543,27 +537,6 @@ func (o *SSHOptions) Run(f util.Factory) error { return err } - if shoot.Status.TechnicalID == "" { - return fmt.Errorf("shoot technical ID is empty: %w", err) - } - - // check operator role - if !o.Operator { - seedTarget := target.NewTarget(currentTarget.GardenName(), "", *shoot.Spec.SeedName, "") - - seedClient, err := manager.SeedClient(ctx, seedTarget) - if err != nil { - if !apierrors.IsForbidden(err) { - return nil - } - - return err - } - - o.Operator = true - o.client = seedClient - } - // check access restrictions ok, err := o.checkAccessRestrictions(manager.Configuration(), currentTarget.GardenName(), f.TargetFlags(), shoot) if err != nil { @@ -674,47 +647,22 @@ func (o *SSHOptions) Run(f util.Factory) error { if !o.Interactive { var nodes []corev1.Node + + machines := make([]string, 0) + if nodeHostname == "" { nodes, err = getNodes(ctx, shootClient) if err != nil { return fmt.Errorf("failed to list shoot cluster nodes: %w", err) } - } - if o.Operator { - machines, err := getMachines(ctx, o.client, shoot.Status.TechnicalID) + machines, err = getNodeNamesFromMachines(ctx, manager, currentTarget) if err != nil { - return fmt.Errorf("failed to list shoot cluster machines: %w", err) - } - - if len(machines) != len(nodes) { - type empty struct{} - - nodeSets := make(map[string]empty, len(nodes)) - - for _, node := range nodes { - nodeSets[node.Name] = empty{} + if !apierrors.IsForbidden(err) { + return nil } - for _, machine := range machines { - if _, ok := machine.Labels[machinev1alpha1.NodeLabelKey]; !ok { - continue - } - - if _, ok := nodeSets[machine.Labels[machinev1alpha1.NodeLabelKey]]; !ok { - nodes = append(nodes, corev1.Node{ - ObjectMeta: metav1.ObjectMeta{Name: machine.Labels[machinev1alpha1.NodeLabelKey]}, - Status: corev1.NodeStatus{ - Conditions: []corev1.NodeCondition{ - { - Type: corev1.NodeReady, - Status: corev1.ConditionUnknown, - }, - }, - }, - }) - } - } + return fmt.Errorf("failed to get shoot cluster node names from machines: %w", err) } } @@ -728,6 +676,7 @@ func (o *SSHOptions) Run(f util.Factory) error { o.SSHPrivateKeyFile, nodePrivateKeyFiles, nodes, + machines, o.User, ) if err != nil { From 043d835e23cbc3128967efc18ed7b3ec0adfa1c0 Mon Sep 17 00:00:00 2001 From: Ted Teng Date: Mon, 15 Jan 2024 11:03:24 +0800 Subject: [PATCH 3/3] fix [controller-runtime] log.SetLogger(...) was never called; logs will not be displayed. --- go.mod | 3 +++ go.sum | 8 ++++++++ main.go | 3 +++ 3 files changed, 14 insertions(+) diff --git a/go.mod b/go.mod index 6985ff5b..245b8fd3 100644 --- a/go.mod +++ b/go.mod @@ -49,6 +49,7 @@ require ( 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 + github.com/go-logr/zapr v1.2.4 // indirect github.com/go-openapi/errors v0.20.3 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect @@ -103,6 +104,8 @@ require ( github.com/subosito/gotenv v1.4.2 // indirect github.com/xlab/treeprint v1.2.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.25.0 // indirect golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.14.0 // indirect diff --git a/go.sum b/go.sum index 88cd05ca..acc38290 100644 --- a/go.sum +++ b/go.sum @@ -61,6 +61,9 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -494,12 +497,16 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU= go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -809,6 +816,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= diff --git a/main.go b/main.go index b7bd9e5e..c4a94dc2 100644 --- a/main.go +++ b/main.go @@ -9,9 +9,11 @@ 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" + "github.com/gardener/gardener/pkg/logger" machinev1alpha1 "github.com/gardener/machine-controller-manager/pkg/apis/machine/v1alpha1" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/kubernetes/scheme" + logf "sigs.k8s.io/controller-runtime/pkg/log" "github.com/gardener/gardenctl-v2/pkg/cmd" ) @@ -22,5 +24,6 @@ func main() { utilruntime.Must(seedmanagementv1alpha1.AddToScheme(scheme.Scheme)) utilruntime.Must(machinev1alpha1.AddToScheme(scheme.Scheme)) + logf.SetLogger(logger.MustNewZapLogger(logger.InfoLevel, logger.FormatJSON)) cmd.Execute() }