mirror of https://github.com/kubernetes/kops.git
Keep the good part from last attempt
This commit is contained in:
parent
e11146c0df
commit
c01455cf91
|
|
@ -32,6 +32,7 @@ go_library(
|
|||
"get.go",
|
||||
"get_cluster.go",
|
||||
"get_instancegroups.go",
|
||||
"get_instances.go",
|
||||
"get_secrets.go",
|
||||
"import.go",
|
||||
"import_cluster.go",
|
||||
|
|
@ -81,6 +82,8 @@ go_library(
|
|||
"//pkg/pki:go_default_library",
|
||||
"//pkg/pretty:go_default_library",
|
||||
"//pkg/resources:go_default_library",
|
||||
"//pkg/resources/aws:go_default_library",
|
||||
"//pkg/resources/openstack:go_default_library",
|
||||
"//pkg/resources/ops:go_default_library",
|
||||
"//pkg/sshcredentials:go_default_library",
|
||||
"//pkg/try:go_default_library",
|
||||
|
|
@ -89,6 +92,7 @@ go_library(
|
|||
"//upup/pkg/fi:go_default_library",
|
||||
"//upup/pkg/fi/cloudup:go_default_library",
|
||||
"//upup/pkg/fi/cloudup/awsup:go_default_library",
|
||||
"//upup/pkg/fi/cloudup/openstack:go_default_library",
|
||||
"//upup/pkg/fi/utils:go_default_library",
|
||||
"//upup/pkg/kutil:go_default_library",
|
||||
"//util/pkg/tables:go_default_library",
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ func NewCmdGet(f *util.Factory, out io.Writer) *cobra.Command {
|
|||
cmd.AddCommand(NewCmdGetCluster(f, out, options))
|
||||
cmd.AddCommand(NewCmdGetInstanceGroups(f, out, options))
|
||||
cmd.AddCommand(NewCmdGetSecrets(f, out, options))
|
||||
cmd.AddCommand(NewCmdGetInstances(f, out, options))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
Copyright 2020 The Kubernetes Authors.
|
||||
|
||||
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 main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kops/pkg/cloudinstances"
|
||||
"k8s.io/kubectl/pkg/util/i18n"
|
||||
"k8s.io/kubectl/pkg/util/templates"
|
||||
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
|
||||
"k8s.io/kops/pkg/client/simple"
|
||||
|
||||
"k8s.io/kops/pkg/resources/openstack"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
|
||||
"k8s.io/kops/pkg/resources"
|
||||
"k8s.io/kops/util/pkg/tables"
|
||||
|
||||
"k8s.io/kops/pkg/apis/kops"
|
||||
"k8s.io/kops/pkg/resources/aws"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/kops/cmd/kops/util"
|
||||
"k8s.io/kops/upup/pkg/fi/cloudup"
|
||||
|
||||
osCloudup "k8s.io/kops/upup/pkg/fi/cloudup/openstack"
|
||||
)
|
||||
|
||||
func NewCmdGetInstances(f *util.Factory, out io.Writer, options *GetOptions) *cobra.Command {
|
||||
getInstancesShort := i18n.T(`Display cluster instances.`)
|
||||
|
||||
getInstancesLong := templates.LongDesc(i18n.T(`
|
||||
Display cluster instances.`))
|
||||
|
||||
getInstancesExample := templates.Examples(i18n.T(`
|
||||
# Display all instances.
|
||||
kops get instances
|
||||
`))
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "instances",
|
||||
Short: getInstancesShort,
|
||||
Long: getInstancesLong,
|
||||
Example: getInstancesExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
ctx := context.TODO()
|
||||
|
||||
if err := rootCommand.ProcessArgs(args); err != nil {
|
||||
exitWithError(err)
|
||||
}
|
||||
|
||||
err := RunGetInstances(ctx, f, out, options)
|
||||
if err != nil {
|
||||
exitWithError(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func RunGetInstances(ctx context.Context, f *util.Factory, out io.Writer, options *GetOptions) error {
|
||||
|
||||
clientset, err := f.Clientset()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clusterName := rootCommand.ClusterName()
|
||||
options.clusterName = clusterName
|
||||
if clusterName == "" {
|
||||
return fmt.Errorf("--name is required")
|
||||
}
|
||||
|
||||
cluster, err := clientset.GetCluster(ctx, options.clusterName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cluster == nil {
|
||||
return fmt.Errorf("cluster not found %q", options.clusterName)
|
||||
}
|
||||
|
||||
cloud, err := cloudup.BuildCloud(cluster)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
k8sClient, err := createK8sClient(cluster)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var status map[string]string
|
||||
nodeList, err := k8sClient.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
klog.V(2).Infof("error listing nodes: %v", err)
|
||||
} else {
|
||||
status, _ = getNodeStatus(ctx, cloud, clientset, cluster, nodeList.Items)
|
||||
}
|
||||
|
||||
var instances []*resources.Instance
|
||||
|
||||
switch cloud.ProviderID() {
|
||||
case kops.CloudProviderAWS:
|
||||
rs, _ := aws.ListInstances(cloud, options.clusterName)
|
||||
for _, r := range rs {
|
||||
instances = append(instances, aws.GetInstanceFromResource(r))
|
||||
}
|
||||
case kops.CloudProviderOpenstack:
|
||||
rs, _ := openstack.ListResources(cloud.(osCloudup.OpenstackCloud), options.clusterName)
|
||||
for _, r := range rs {
|
||||
if r.Type == "Instance" {
|
||||
instances = append(instances, openstack.GetInstanceFromResource(r))
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("cloud provider not supported")
|
||||
}
|
||||
|
||||
switch options.output {
|
||||
case OutputTable:
|
||||
return instanceOutputTable(instances, status, out)
|
||||
default:
|
||||
return fmt.Errorf("Unsupported output format: %q", options.output)
|
||||
}
|
||||
}
|
||||
|
||||
func instanceOutputTable(instances []*resources.Instance, status map[string]string, out io.Writer) error {
|
||||
t := &tables.Table{}
|
||||
t.AddColumn("ID", func(i *resources.Instance) string {
|
||||
return i.ID
|
||||
})
|
||||
t.AddColumn("NAME", func(i *resources.Instance) string {
|
||||
return i.Name
|
||||
})
|
||||
t.AddColumn("STATUS", func(i *resources.Instance) string {
|
||||
s := status[i.ID]
|
||||
if s == "" {
|
||||
return "NotJoined"
|
||||
} else {
|
||||
return s
|
||||
}
|
||||
})
|
||||
t.AddColumn("ROLES", func(i *resources.Instance) string {
|
||||
return strings.Join(i.Roles, ", ")
|
||||
})
|
||||
t.AddColumn("INTERNAL-IP", func(i *resources.Instance) string {
|
||||
return i.PrivateAddress
|
||||
})
|
||||
t.AddColumn("INSTANCE-GROUP", func(i *resources.Instance) string {
|
||||
return i.InstanceGroup
|
||||
})
|
||||
t.AddColumn("MACHINE-TYPE", func(i *resources.Instance) string {
|
||||
return i.MachineType
|
||||
})
|
||||
return t.Render(instances, os.Stdout, "ID", "NAME", "STATUS", "ROLES", "INTERNAL-IP", "INSTANCE-GROUP", "MACHINE-TYPE")
|
||||
}
|
||||
|
||||
func getNodeStatus(ctx context.Context, cloud fi.Cloud, clientset simple.Clientset, cluster *kops.Cluster, nodes []v1.Node) (map[string]string, error) {
|
||||
status := make(map[string]string)
|
||||
igList, err := clientset.InstanceGroupsFor(cluster).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var instanceGroups []*kops.InstanceGroup
|
||||
for i := range igList.Items {
|
||||
instanceGroups = append(instanceGroups, &igList.Items[i])
|
||||
}
|
||||
igs := cloudinstances.GetNodeMap(nodes, cluster)
|
||||
|
||||
cloudGroups, err := cloud.GetCloudGroups(cluster, instanceGroups, false, nodes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, cg := range cloudGroups {
|
||||
for _, instance := range cg.Ready {
|
||||
if instance.Detached {
|
||||
status[instance.ID] = "Detached"
|
||||
} else {
|
||||
if igs[instance.ID] != nil {
|
||||
status[instance.ID] = "Ready"
|
||||
} else {
|
||||
status[instance.ID] = "NotJoined"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, cg := range cloudGroups {
|
||||
for _, node := range cg.NeedUpdate {
|
||||
if node.Detached {
|
||||
status[node.ID] = "Detached"
|
||||
} else {
|
||||
status[node.ID] = "NeedsUpdate"
|
||||
}
|
||||
}
|
||||
}
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func createK8sClient(cluster *kops.Cluster) (*kubernetes.Clientset, error) {
|
||||
contextName := cluster.ObjectMeta.Name
|
||||
clientGetter := genericclioptions.NewConfigFlags(true)
|
||||
clientGetter.Context = &contextName
|
||||
|
||||
config, err := clientGetter.ToRESTConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot load kubecfg settings for %q: %v", contextName, err)
|
||||
}
|
||||
k8sClient, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot build kubernetes api client for %q: %v", contextName, err)
|
||||
}
|
||||
return k8sClient, nil
|
||||
|
||||
}
|
||||
|
|
@ -71,5 +71,6 @@ kops get [flags]
|
|||
* [kops](kops.md) - kops is Kubernetes ops.
|
||||
* [kops get clusters](kops_get_clusters.md) - Get one or many clusters.
|
||||
* [kops get instancegroups](kops_get_instancegroups.md) - Get one or many instancegroups
|
||||
* [kops get instances](kops_get_instances.md) - Display cluster instances.
|
||||
* [kops get secrets](kops_get_secrets.md) - Get one or many secrets.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
<!--- This file is automatically generated by make gen-cli-docs; changes should be made in the go CLI command code (under cmd/kops) -->
|
||||
|
||||
## kops get instances
|
||||
|
||||
Display cluster instances.
|
||||
|
||||
### Synopsis
|
||||
|
||||
Display cluster instances.
|
||||
|
||||
```
|
||||
kops get instances [flags]
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
# Display all instances.
|
||||
kops get instances
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for instances
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--add_dir_header If true, adds the file directory to the header of the log messages
|
||||
--alsologtostderr log to standard error as well as files
|
||||
--config string yaml config file (default is $HOME/.kops.yaml)
|
||||
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
|
||||
--log_dir string If non-empty, write log files in this directory
|
||||
--log_file string If non-empty, use this log file
|
||||
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
|
||||
--logtostderr log to standard error instead of files (default true)
|
||||
--name string Name of cluster. Overrides KOPS_CLUSTER_NAME environment variable
|
||||
-o, --output string output format. One of: table, yaml, json (default "table")
|
||||
--skip_headers If true, avoid header prefixes in the log messages
|
||||
--skip_log_headers If true, avoid headers when opening log files
|
||||
--state string Location of state storage (kops 'config' file). Overrides KOPS_STATE_STORE environment variable
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
-v, --v Level number for the log level verbosity
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [kops get](kops_get.md) - Get one or many resources.
|
||||
|
||||
Loading…
Reference in New Issue