type ClusterInfoOptions struct {//cluster-info结构体 genericclioptions.IOStreams Namespace string Builder *resource.Builder Client *restclient.Config }
//创建clusterinfo命令 func NewCmdClusterInfo(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { o := &ClusterInfoOptions{//初始化结构体 IOStreams: ioStreams, } cmd := &cobra.Command{//创建cobra命令 Use: "cluster-info", Short: i18n.T("Display cluster info"), Long: longDescr, Example: clusterinfoExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd))//准备 cmdutil.CheckErr(o.Run())//运行 }, } cmd.AddCommand(NewCmdClusterInfoDump(f, ioStreams))//添加dump子命令 return cmd }
//准备运行 func (o *ClusterInfoOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { var err error o.Client, err = f.ToRESTConfig()//获取restConfig if err != nil { return err } cmdNamespace := cmdutil.GetFlagString(cmd, "namespace")//获取namespace if cmdNamespace == "" { cmdNamespace = metav1.NamespaceSystem//如果namespace为空则用kube-system } o.Namespace = cmdNamespace//设置Namespace o.Builder = f.NewBuilder()//设置builder return nil }
//运行 func (o *ClusterInfoOptions) Run() error { // TODO use generalized labels once they are implemented (#341) b := o.Builder. WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). NamespaceParam(o.Namespace).DefaultNamespace(). LabelSelectorParam("kubernetes.io/cluster-service=true"). ResourceTypeOrNameArgs(false, []string{"services"}...). Latest()//构造result对象 err := b.Do().Visit(func(r *resource.Info, err error) error {// visit result对象 if err != nil { return err } printService(o.Out, "Kubernetes master", o.Client.Host)//打印kube master 服务 services := r.Object.(*corev1.ServiceList).Items//把obj转service List for _, service := range services {//遍历service var link string if len(service.Status.LoadBalancer.Ingress) > 0 {//如果service有loadBlancer ingress := service.Status.LoadBalancer.Ingress[0]//获取loadblancer的ingress ip := ingress.IP//获取ip if ip == "" { ip = ingress.Hostname// 如果ip为空,则用hostname } for _, port := range service.Spec.Ports {//遍历service的ports link += "http://" + ip + ":" + strconv.Itoa(int(port.Port)) + " " } } else { name := service.ObjectMeta.Name//获取service的Name if len(service.Spec.Ports) > 0 {//如果service有ports port := service.Spec.Ports[0]//获取第一个port // guess if the scheme is https scheme := "" if port.Name == "https" || port.Port == 443 {//设置schema scheme = "https" } // format is <scheme>:<service-name>:<service-port-name> name = utilnet.JoinSchemeNamePort(scheme, service.ObjectMeta.Name, port.Name)//拼接名称 } if len(o.Client.GroupVersion.Group) == 0 {//判断是否有group,拼接link link = o.Client.Host + "/api/" + o.Client.GroupVersion.Version + "/namespaces/" + service.ObjectMeta.Namespace + "/services/" + name + "/proxy" } else { link = o.Client.Host + "/api/" + o.Client.GroupVersion.Group + "/" + o.Client.GroupVersion.Version + "/namespaces/" + service.ObjectMeta.Namespace + "/services/" + name + "/proxy" } } name := service.ObjectMeta.Labels["kubernetes.io/name"]//从标签获取name if len(name) == 0 {//如果name为空,则用service的name name = service.ObjectMeta.Name } printService(o.Out, name, link)//打印服务 } return nil }) o.Out.Write([]byte("\nTo further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\n"))//输出提示 return err // TODO consider printing more information about cluster } //打印服务 func printService(out io.Writer, name, link string) { ct.ChangeColor(ct.Green, false, ct.None, false)//设置颜色 fmt.Fprint(out, name)//打印服务名称 ct.ResetColor()//c重置颜色 fmt.Fprint(out, " is running at ")//打印 ct.ChangeColor(ct.Yellow, false, ct.None, false)//设置颜色 fmt.Fprint(out, link)//打印连接 ct.ResetColor()//重置颜色 fmt.Fprintln(out, "") }