clusterinfo.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package clusterinfo
  14. import (
  15. "fmt"
  16. "io"
  17. "strconv"
  18. corev1 "k8s.io/api/core/v1"
  19. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  20. utilnet "k8s.io/apimachinery/pkg/util/net"
  21. "k8s.io/cli-runtime/pkg/genericclioptions"
  22. "k8s.io/cli-runtime/pkg/resource"
  23. restclient "k8s.io/client-go/rest"
  24. cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
  25. "k8s.io/kubernetes/pkg/kubectl/scheme"
  26. "k8s.io/kubernetes/pkg/kubectl/util/i18n"
  27. "k8s.io/kubernetes/pkg/kubectl/util/templates"
  28. ct "github.com/daviddengcn/go-colortext"
  29. "github.com/spf13/cobra"
  30. )
  31. var (
  32. longDescr = templates.LongDesc(i18n.T(`
  33. Display addresses of the master and services with label kubernetes.io/cluster-service=true
  34. To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.`))
  35. clusterinfoExample = templates.Examples(i18n.T(`
  36. # Print the address of the master and cluster services
  37. kubectl cluster-info`))
  38. )
  39. type ClusterInfoOptions struct {
  40. genericclioptions.IOStreams
  41. Namespace string
  42. Builder *resource.Builder
  43. Client *restclient.Config
  44. }
  45. func NewCmdClusterInfo(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
  46. o := &ClusterInfoOptions{
  47. IOStreams: ioStreams,
  48. }
  49. cmd := &cobra.Command{
  50. Use: "cluster-info",
  51. Short: i18n.T("Display cluster info"),
  52. Long: longDescr,
  53. Example: clusterinfoExample,
  54. Run: func(cmd *cobra.Command, args []string) {
  55. cmdutil.CheckErr(o.Complete(f, cmd))
  56. cmdutil.CheckErr(o.Run())
  57. },
  58. }
  59. cmd.AddCommand(NewCmdClusterInfoDump(f, ioStreams))
  60. return cmd
  61. }
  62. func (o *ClusterInfoOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
  63. var err error
  64. o.Client, err = f.ToRESTConfig()
  65. if err != nil {
  66. return err
  67. }
  68. cmdNamespace := cmdutil.GetFlagString(cmd, "namespace")
  69. if cmdNamespace == "" {
  70. cmdNamespace = metav1.NamespaceSystem
  71. }
  72. o.Namespace = cmdNamespace
  73. o.Builder = f.NewBuilder()
  74. return nil
  75. }
  76. func (o *ClusterInfoOptions) Run() error {
  77. // TODO use generalized labels once they are implemented (#341)
  78. b := o.Builder.
  79. WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
  80. NamespaceParam(o.Namespace).DefaultNamespace().
  81. LabelSelectorParam("kubernetes.io/cluster-service=true").
  82. ResourceTypeOrNameArgs(false, []string{"services"}...).
  83. Latest()
  84. err := b.Do().Visit(func(r *resource.Info, err error) error {
  85. if err != nil {
  86. return err
  87. }
  88. printService(o.Out, "Kubernetes master", o.Client.Host)
  89. services := r.Object.(*corev1.ServiceList).Items
  90. for _, service := range services {
  91. var link string
  92. if len(service.Status.LoadBalancer.Ingress) > 0 {
  93. ingress := service.Status.LoadBalancer.Ingress[0]
  94. ip := ingress.IP
  95. if ip == "" {
  96. ip = ingress.Hostname
  97. }
  98. for _, port := range service.Spec.Ports {
  99. link += "http://" + ip + ":" + strconv.Itoa(int(port.Port)) + " "
  100. }
  101. } else {
  102. name := service.ObjectMeta.Name
  103. if len(service.Spec.Ports) > 0 {
  104. port := service.Spec.Ports[0]
  105. // guess if the scheme is https
  106. scheme := ""
  107. if port.Name == "https" || port.Port == 443 {
  108. scheme = "https"
  109. }
  110. // format is <scheme>:<service-name>:<service-port-name>
  111. name = utilnet.JoinSchemeNamePort(scheme, service.ObjectMeta.Name, port.Name)
  112. }
  113. if len(o.Client.GroupVersion.Group) == 0 {
  114. link = o.Client.Host + "/api/" + o.Client.GroupVersion.Version + "/namespaces/" + service.ObjectMeta.Namespace + "/services/" + name + "/proxy"
  115. } else {
  116. link = o.Client.Host + "/api/" + o.Client.GroupVersion.Group + "/" + o.Client.GroupVersion.Version + "/namespaces/" + service.ObjectMeta.Namespace + "/services/" + name + "/proxy"
  117. }
  118. }
  119. name := service.ObjectMeta.Labels["kubernetes.io/name"]
  120. if len(name) == 0 {
  121. name = service.ObjectMeta.Name
  122. }
  123. printService(o.Out, name, link)
  124. }
  125. return nil
  126. })
  127. o.Out.Write([]byte("\nTo further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\n"))
  128. return err
  129. // TODO consider printing more information about cluster
  130. }
  131. func printService(out io.Writer, name, link string) {
  132. ct.ChangeColor(ct.Green, false, ct.None, false)
  133. fmt.Fprint(out, name)
  134. ct.ResetColor()
  135. fmt.Fprint(out, " is running at ")
  136. ct.ChangeColor(ct.Yellow, false, ct.None, false)
  137. fmt.Fprint(out, link)
  138. ct.ResetColor()
  139. fmt.Fprintln(out, "")
  140. }