搜索
房产
装修
汽车
婚嫁
健康
理财
旅游
美食
跳蚤
二手房
租房
招聘
二手车
教育
茶座
我要买房
买东西
装修家居
交友
职场
生活
网购
亲子
情感
龙城车友
找美食
谈婚论嫁
美女
兴趣
八卦
宠物
手机

Go Goosy Disk Docker Port Provisioners (GDP)

[复制链接]
查看: 67|回复: 0

1万

主题

1万

帖子

3万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
32607
发表于 2020-1-15 00:13 | 显示全部楼层 |阅读模式
小同伴们,她们中出了一个叛徒,他是谁?是谁?是谁?
由一则口口相传的故事起头吧:
午时吃饭时候抽空小李跑到同座大楼的小张公司串门,小李是一位docker顾问熟称砖家,这间公司老板想挖小李,他盯了前台不到三秒,移开视野走到前同事小张的隔间边上打号召,看到小张眉头舒展,正在专著的看代码,小李把头凑过去,客套起来,正在忙呢,在学什么新技术?小张开口吼到:在翻小王的代码,你熟悉的那个烟友!小李一愣,哦那一个小王啊~,研讨他人的技术,挺钻的呀,小李嘴上阿谀道(心里暗忖着小张人为畴前没我高,跳到这里估量也还在当脱手吧),小张叹了一口气,嘣出三个字:烦着呢,小李映入眼前的是满屏密密层层的代码,左侧的行标表现9999,不愧是千足代码,还有那末一小行格空的诠释,精明的打着时候---5年前----这是旧代码,小李点头晃脑,有所憬悟
那就不打搅你了,想起烟瘾又犯了,正巧熟悉的小王也是同道中人,下认识就问,小王人呢?小张硕小的脑壳一震,青筋暴起,指了指打印机房外一个空台子,上面积了一层薄灰,放着一些杂物,像似很久没有人办公了,与此同时,一阵阴风从窗角吹过,扬起的窗帘把小张的脸映照成斑斑点点,小张把迟滞的眼光瞟向了窗外的浮云,恍如小王就在云端,小王离职了吗?小李不宁愿的问了一句,忽然一排没有窗户的老板格间悠悠的翻开一扇门,恍若有人藏在门后很久了,一个光妥ㄐ年把头探了出来利索的喊了一句,小张进来,讲话!小张小心翼翼的放下鼠标,快速使了一个撤离眼色,轻声说,小王的老板老王现在酿成了我的老板...就是畴前那一个咚咚咚画白板的那个...小李假装若有所悟的样子恢恢手溜了
此后小李再也没有去小张的办公室,至今小李还在打着寒战

这个故事有什么寓意?听过的人同心协力(张冠李戴),干脆作为发散性话题,放在本篇作引
题目GDP三个首字母的组合作为揭发233的docker/machine的后续,为了合适题目标意义,请Follow me一路探讨其中的机密
我们先从一段代码说起
  1. // b2d hosts need to wait for the daemon to be up// before continuing with provisioningif err = WaitForDocker(provisioner, engine.DefaultPort); err != nil {    return err}if err = makeDockerOptionsDir(provisioner); err != nil {    return err}provisioner.AuthOptions = setRemoteAuthOptions(provisioner)if err = ConfigureAuth(provisioner); err != nil {    return err}
复制代码
这是一段在233篇中重点划出揭露的片断
节选自libmachine/provision/boot2docker.go
从233篇匿伏的逻辑可以判定,此处,致使了全部匿伏在Docker Machine中的b2d出现了port排异
函数WaitForDocker成为此段有争议的焦点
我们进入这段函数看看它究竟是什么实现
  1. func checkDaemonUp(p Provisioner, dockerPort int) func() bool {        reDaemonListening := fmt.Sprintf(":%d\\s+.*:.*", dockerPort)        return func() bool {                // HACK: Check netstat's output to see if anyone's listening on the Docker API port.                netstatOut, err := p.SSHCommand("if ! type netstat 1>/dev/null; then ss -tln; else netstat -tln; fi")                if err != nil {                        log.Warnf("Error running SSH command: %s", err)                        return false                }                return matchNetstatOut(reDaemonListening, netstatOut)        }}
复制代码
这段试图在netstat返回成果字符典范中实行婚配函数matchNetstatOut
  1. matchNetstatOut = regexp.MatchString(reDaemonListening, line)
复制代码
婚配的配角很不幸在这里被倔强的设备为engine.DefaultPort,在233篇里曾试图罗列过engine.DefaultPort的一些用例,不晓得小同伴们看出些什么眉目
在这里我们再次回到起头的那些函数片断,留意到随后挪用的if err = ConfigureAuth(provisioner)没有?
这是一段惊心动魄的代码,路经在libmachine/provision/utils.go
无妨我们一路看一下这个ConfigureAuth函数有哪些内在???
  1. func (provisioner *Boot2DockerProvisioner) Service(name string, action serviceaction.ServiceAction) error {    _, err := provisioner.SSHCommand(fmt.Sprintf("sudo /etc/init.d/%s %s", name, action.String()))    return err}[b]bits := [/b][b]2048[/b] p.Service("docker", serviceaction.Stop);.log.Info("Copying certs to the local machine directory...");...dockerPort := engine.DefaultPortparts := strings.Split(u.Host, ":")if len(parts) == 2 {    dPort, err := strconv.Atoi(parts[1])    if err != nil {        return err    }    dockerPort = dPort}...p.Service("docker", serviceaction.Start);.[b]return WaitForDocker(p, dockerPort);[/b]
复制代码

这是我笼统出来的慰慰代码,在这段代码里,吉祥寺(似)dockerPort被切确公道的设备成它应当有的值,我把这段代码称号为2048代码,为了抵消你们不时出现的1024的动机!
假如诸位可以认真地再多看几遍,必定会发生出一群问号???
这里全数的op都以SSH的方式挪用,而SSH又匿伏了什么不为人知的小故事?我们一路来猜测,谁是哪一位画白板的人
  1. func (provisioner *Boot2DockerProvisioner) SSHCommand(args string) (string, error) {        return drivers.RunSSHCommandFromDriver(provisioner.Driver, args)}
复制代码
在b2d内部,SSH的义务链落到driver头上,对就是那一个driver,那一个,那一个,我在手动滑稽之golang-vmware-driver广告篇贴图之一,不会错了
driver为什么会对SSH驾轻就熟?
As:
  1. func GetSSHClientFromDriver(d Driver) (ssh.Client, error) {        address, err := d.GetSSHHostname()        if err != nil {                return nil, err        }        port, err := d.GetSSHPort()        if err != nil {                return nil, err        }        var auth *ssh.Auth        if d.GetSSHKeyPath() == "" {                auth = &ssh.Auth{}        } else {                auth = &ssh.Auth{                        Keys: []string{d.GetSSHKeyPath()},                }        }        client, err := ssh.NewClient(d.GetSSHUsername(), address, port, auth)        return client, err}func RunSSHCommandFromDriver(d Driver, command string) (string, error) {        client, err := GetSSHClientFromDriver(d)        if err != nil {                return "", err        }        log.Debugf("About to run SSH command:\n%s", command)        output, err := client.Output(command)        log.Debugf("SSH cmd err, output: %v: %s", err, output)        if err != nil {                return "", fmt.Errorf(`ssh command error:command : %serr     : %voutput  : %s`, command, err, output)        }        return output, nil}
复制代码
回到现象
  1. func WaitForSpecificOrError(f func() (bool, error), maxAttempts int, waitInterval time.Duration) error {        for i := 0; i < maxAttempts; i++ {                stop, err := f()                if err != nil {                        return err                }                if stop {                        return nil                }                time.Sleep(waitInterval)        }        return fmt.Errorf("Maximum number of retries (%d) exceeded", maxAttempts)}func WaitForSpecific(f func() bool, maxAttempts int, waitInterval time.Duration) error {        return WaitForSpecificOrError(func() (bool, error) {                return f(), nil        }, maxAttempts, waitInterval)}
复制代码
假如docker port已经点窜这里会抽风10次,表现ssh挪用if ! type netstat 1>/dev/null; then ss -tln; else netstat -tln; fi切确返回已经改变的docker port和ssh port侦听列表
但是没法match engine.DefaultPort带来的err是臆想不到的,err msg更没法判定b2d的内部排异,这迫使我试图根究AzureProvisioner,这个不存在的称号
假如看到这里我再向你吐露docker port从driver中发生大要一点也不会受惊,末端的伪函数片断是
  1. // Driver defines how a host is created and controlled. Different types of// driver represent different ways hosts can be created (e.g. different// hypervisors, different cloud providers)type Driver interface {    // Create a host using the driver's config    Create() error    // DriverName returns the name of the driver    DriverName() string    // GetCreateFlags returns the mcnflag.Flag slice representing the flags    // that can be set, their descriptions and defaults.    GetCreateFlags() []mcnflag.Flag    // GetIP returns an IP or hostname that this host is available at    // e.g. 1.2.3.4 or docker-host-d60b70a14d3a.cloudapp.net    GetIP() (string, error)    // GetMachineName returns the name of the machine    GetMachineName() string    // GetSSHHostname returns hostname for use with ssh    GetSSHHostname() (string, error)    // GetSSHKeyPath returns key path for use with ssh    GetSSHKeyPath() string    // GetSSHPort returns port for use with ssh    GetSSHPort() (int, error)    // GetSSHUsername returns username for use with ssh    GetSSHUsername() string    // GetURL returns a Docker compatible host URL for connecting to this host    // e.g. tcp://1.2.3.4:2376    GetURL() (string, error)    // GetState returns the state that the host is in (running, stopped, etc)    GetState() (state.State, error)    // Kill stops a host forcefully    Kill() error    // PreCreateCheck allows for pre-create operations to make sure a driver is ready for creation    PreCreateCheck() error    // Remove a host    Remove() error    // Restart a host. This may just call Stop(); Start() if the provider does not    // have any special restart behaviour.    Restart() error    // SetConfigFromFlags configures the driver with the object that was returned    // by RegisterCreateFlags    SetConfigFromFlags(opts DriverOptions) error    // Start a host    Start() error    // Stop a host gracefully    Stop() error}
复制代码
  1. u.Host from GetUrl() from Implementation of DriverThat's ALL of it.
复制代码
这些代码挪用关系逐一展现过以后
  1. // b2d hosts need to wait for the daemon to be up// before continuing with provisioning
复制代码
这里,唯一的诠释让我加倍确信,以下一行是可以删除的代码,我们都长于反向操纵
但是我对改Machine始终抱No的态度,大要未来大要会注册一个账户submit patch,可是让我犹豫的是,我还没有写过任何hello world go,为什么比我更合适的人选没有呢???
这个疑问始终挥之不去,到了放松环节,请随着我的节奏Blame(扒)一下出色截图
图片被我约束了HTML尺寸,请点击零丁在TAB页旁观图片链接
[img=620,NaN]http://www.45zhe.com/https://images.cnblogs.com/cnblogs_com/A-Z/117549/o_b2d_provision.PNG[/img]

-->-->
[img=620,NaN]http://www.45zhe.com/https://images.cnblogs.com/cnblogs_com/A-Z/117549/o_b2d_provision2.PNG[/img]

a
[img=620,NaN]http://www.45zhe.com/https://images.cnblogs.com/cnblogs_com/A-Z/117549/o_b2d_provision3.PNG[/img]


简出:
对策篇:

  • 上文提到的建造自己的Machine,怜惜华而不为
  • 提交patch,为社区进献,怜惜指日可待
  • Register Injection by Init Driver AND YOU CAN HAVE 4069
作为一个万全的对策必定要有一些把握,forkersfolk贡起宝典手册,找到了入门
请看
Init() functions can be used within a package block and regardless of how many times that package is imported
The init() function will only be called once
[code]provisioners          = make(map[string]*RegisteredProvisioner)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Copyright © 2006-2014 全椒百姓网-全椒知名**,发布及时新鲜的全椒新闻资讯 生活信息 版权所有 法律顾问:高律师 客服电话:0791-88289918
技术支持:迪恩网络科技公司  Powered by Discuz! X3.2
快速回复 返回顶部 返回列表