草庐IT

go - 在 kubectl 插件中,提示输入?

coder 2024-07-08 原文

我正在编写一个 kubectl 插件来对用户进行身份验证,我想在调用插件后提示用户输入密码。据我了解,从 STDIN 获取输入相当简单,但我很难看到写入 STDOUT 的消息。目前我的代码如下所示:

在 cmd/kubectl-myauth.go 中:

// This is mostly boilerplate, but it's needed for the MRE
// https://stackoverflow.com/help/minimal-reproducible-example
package myauth
import (...)
func main() {
    pflag.CommandLine = pflag.NewFlagSet("kubectl-myauth", pflag.ExitOnError)
    root := cmd.NewCmdAuthOp(genericclioptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr})
    if err := root.Execute(); err != nil {
        os.Exit(1)
    }
}

在 pkg/cmd/auth.go 中:

package cmd
...
type AuthOpOptions struct {
    configFlags *genericclioptions.ConfigFlags
    resultingContext *api.Context
    rawConfig       api.Config
    args            []string
    ...
    genericclioptions.IOStreams
}
func NewAuthOpOptions(streams genericclioptions.IOStreams) *AuthOpOptions {
    return &AuthOpOptions{
        configFlags: genericclioptions.NewConfigFlags(true),
        IOStreams: streams,
    }
}
func NewCmdAuthOp(streams genericclioptions.IOStreams) *cobra.Command {
    o := NewAuthOpOptions(streams)
    cmd := &cobra.Command{
        RunE: func(c *cobra.Command, args []string) error {
            return o.Run()
        },
    }
    return cmd
}
func (o *AuthOpOptions) Run() error {
    pass, err := getPassword(o)
    if err != nil {
        return err
    }
    // Do Auth Stuff
    // Eventually print an ExecCredential to STDOUT
    return nil
}
func getPassword(o *AuthOpOptions) (string, error) {
    var reader *bufio.Reader
    reader = nil
    pass := ""
    for pass == "" {
        // THIS IS AN IMPORTANT LINE [1]
        fmt.Fprintf(o.IOStreams.Out, "Password with which to authenticate:\n")
        // THE REST OF THIS IS STILL IMPORTANT, BUT LESS SO [2]
        if reader == nil {
            // The first time through, initialize the reader
            reader = bufio.NewReader(o.IOStreams.In)
        }
        pass, err := reader.ReadString('\n')
        if err != nil {
            return nil, err
        }
        pass = strings.Trim(pass, "\r\n")
        if pass == "" {
            // ALSO THIS LINE IS IMPORTANT [3]
            fmt.Fprintf(o.IOStreams.Out, `Read password was empty string.
Please input a valid password.
`)
        }
    }
    return pass, nil
}

当从 kubectl 上下文外部运行时,这按照我期望的方式工作 - 即,它打印字符串,提示输入,然后继续。然而,在 kubectl 上下文中,我相信前两个全大写注释([1] 和 [2])之间的打印被 kubectl 监听标准输出。我可以通过打印到 STDERR 来解决这个问题,但这感觉……不对。有没有一种方法可以绕过 kubectl 使用 STDOUT 与用户通信?

TL;DR:kubectl 似乎吞没了 kubectl 插件的所有 STDOUT,但我想提示用户输入 - 有没有简单的方法这个?

最佳答案

抱歉,我没有比“对我有用”更好的答案了:-)以下是步骤:

  • git clone https://github.com/kubernetes/kubernetes.git

  • sample-cli-plugin 复制为 test-cli-plugin(这涉及修复 import-restrictions.yaml、rules-godeps.yaml 和规则。 yaml 在暂存/发布下——也许没有必要,但这样更安全)

  • 将 kubectl-ns.go 更改为 kubectl-test.go:

package main

import (
        "os"

        "github.com/spf13/pflag"

        "k8s.io/cli-runtime/pkg/genericclioptions"
        "k8s.io/test-cli-plugin/pkg/cmd"
)

func main() {
        flags := pflag.NewFlagSet("kubectl-test", pflag.ExitOnError)
        pflag.CommandLine = flags

        root := cmd.NewCmdTest(genericclioptions.IOStreams{In: os.Stdin, 
                                                           Out: os.Stdout,
                                                           ErrOut: os.Stderr})
        if err := root.Execute(); err != nil {
                os.Exit(1)
        }
}
  • 将 ns.go 更改为 test.go:
package cmd

import (
        "fmt"
        "os"

        "github.com/spf13/cobra"

        "k8s.io/cli-runtime/pkg/genericclioptions"
)

type TestOptions struct {
        configFlags *genericclioptions.ConfigFlags
        genericclioptions.IOStreams
}

func NewTestOptions(streams genericclioptions.IOStreams) *TestOptions {
        return &TestOptions{
                configFlags: genericclioptions.NewConfigFlags(true),
                IOStreams:   streams,
        }
}

func NewCmdTest(streams genericclioptions.IOStreams) *cobra.Command {
        o := NewTestOptions(streams)

        cmd := &cobra.Command{
                Use:          "test",
                Short:        "Test plugin",
                SilenceUsage: true,
                RunE: func(c *cobra.Command, args []string) error {
                        o.Run()
                        return nil
                },
        }

        return cmd
}

func (o *TestOptions) Run() error {
        fmt.Fprintf(os.Stderr, "Testing Fprintf Stderr\n")
        fmt.Fprintf(os.Stdout, "Testing Fprintf Stdout\n")
        fmt.Printf("Testing Printf\n")
        fmt.Fprintf(o.IOStreams.Out, "Testing Fprintf o.IOStreams.Out\n")
        return nil
}
  • 相应地修复 BUILD 文件
  • 构建插件
  • 运行make
  • 复制kubectl-test到/usr/local/bin
  • 运行编译后的 kubectl 二进制文件:

~/k8s/_output/bin$ ./kubectl test

Testing Fprintf Stderr

Testing Fprintf Stdout

Testing Printf

Testing Fprintf o.IOStreams.Out

关于go - 在 kubectl 插件中,提示输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56796352/

有关go - 在 kubectl 插件中,提示输入?的更多相关文章

  1. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  2. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  3. ruby-on-rails - 您希望看到哪些 Rails 插件? - 2

    您认为可以作为插件很好地存在于您的Rails应用程序中必须实现的哪些行为?您过去曾搜索过哪些插件功能但找不到?哪些现有的Rails插件可以改进或扩展,如何改进或扩展? 最佳答案 我希望在管理界面中看到一个引擎插件,它提供了应用程序中所有模型的仪表板摘要,以及可配置的事件图表。 关于ruby-on-rails-您希望看到哪些Rails插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questio

  4. ruby - 鸭子输入字符串、符号和数组的优雅方式? - 2

    这是针对我无法破坏的现有公共(public)API,但我确实希望对其进行扩展。目前,该方法采用字符串或符号或任何其他在作为第一个参数传递给send时有意义的内容我想添加发送字符串、符号等列表的功能。我可以只使用is_a吗?数组,但还有其他发送列表的方法,这不是很像ruby​​。我将调用列表中的map,所以第一个倾向是使用respond_to?:map。但是字符串也会响应:map,所以这行不通。 最佳答案 如何将它们全部视为数组?String的行为与仅包含String的Array相同:deffoo(obj,arg)[*arg].eac

  5. ruby - 是否可以将 IRB 提示配置为动态更改? - 2

    我想在IRB中浏览文件系统并让提示更改以反射(reflect)当前工作目录,但我不知道如何在每个命令后进行提示更新。最终,我想在日常工作中更多地使用IRB,让bash溜走。我在我的.irbrc中试过这个:require'fileutils'includeFileUtilsIRB.conf[:PROMPT][:CUSTOM]={:PROMPT_N=>"\e[1m:\e[m",:PROMPT_I=>"\e[1m#{pwd}>\e[m",:PROMPT_S=>"FOO",:PROMPT_C=>"\e[1m#{pwd}>\e[m",:RETURN=>""}IRB.conf[:PROMPT_MO

  6. ruby - vagrant 从 github 安装插件 - 2

    我们正在使用Vagrant进行部署,我们最终希望将此集群部署在Rackspace上。vagrant-rackspace插件是一个自然的选择,但它有一些错误,这些错误未包含在最新的0.1.1版本中(notablythatvagrantprovisiondoesn'twork)。我已经在我的personalfork中解决了这个问题通过合并其他人的工作来对存储库进行改造。是否可以从github安装vagrant插件?显而易见的事情没有奏效:[unix]$vagrantplugininstallvagrant-rackspace--plugin-sourcehttps://github.com

  7. ruby - ruby 中的同一个程序如何接受来自用户的输入以及命令行参数 - 2

    我的ruby​​脚本从命令行参数获取某些输入。它检查是否缺少任何命令行参数,然后提示用户输入。但是我无法使用gets从用户那里获得输入。示例代码:test.rbname=""ARGV.eachdo|a|ifa.include?('-n')name=aputs"Argument:#{a}"endendifname==""puts"entername:"name=getsputsnameend运行脚本:rubytest.rbraghav-k错误结果:test.rb:6:in`gets':Nosuchfileordirectory-raghav-k(Errno::ENOENT)fromtes

  8. ruby-on-rails - 为什么用户必须输入 7 位数的 Twitter PIN 才能授予我的应用程序访问权限? - 2

    我正在为我的用户实现一些ruby​​onrails代码推特内容。我正在创建正确的oauth链接...类似http://twitter.com/oauth/authorize?oauth_token=y2RkuftYAEkbEuIF7zKMuzWN30O2XxM8U9j0egtzKv但在我的测试帐户授予对twitter的访问权限后,它会弹出一个页面,上面写着“您已成功授予对.我不知道用户应该在哪里输入此PIN以及他们为什么必须这样做。我认为这不是必要的步骤。Twitter应该将用户重定向到我在应用程序设置中提供的回调URL。有谁知道为什么会这样?更新我找到了thisarticle声明我需

  9. ruby - 在 StockChart (highchart) 中以编程方式显示柱形图的工具提示 - 2

    我有一个Highstock图表(带有标记和阴影的线条),并且想以编程方式显示一个highstock工具提示,例如,当我选择某个表上的一行(包含图表数据)我想显示相应的highstock工具提示。这可能吗? 最佳答案 股票图表thissolution不起作用:在thisexample你必须更换这个:chart.tooltip.refresh(chart.series[0].data[i]);为此:chart.tooltip.refresh([chart.series[0].points[i]]);解决方案可用here.

  10. ruby-on-rails - Textmate 'Go to symbol' 相当于 Vim - 2

    在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol

随机推荐