github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/cmd/puppeth/module.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2017 Go Ethereum作者
    10  //此文件是Go以太坊的一部分。
    11  //
    12  //Go以太坊是免费软件:您可以重新发布和/或修改它
    13  //根据GNU通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊的分布希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU通用公共许可证了解更多详细信息。
    21  //
    22  //你应该已经收到一份GNU通用公共许可证的副本
    23  //一起去以太坊吧。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package main
    26  
    27  import (
    28  	"encoding/json"
    29  	"errors"
    30  	"fmt"
    31  	"net"
    32  	"strconv"
    33  	"strings"
    34  	"time"
    35  
    36  	"github.com/ethereum/go-ethereum/log"
    37  )
    38  
    39  var (
    40  //当服务容器不存在时,返回errServiceUnknown。
    41  	ErrServiceUnknown = errors.New("service unknown")
    42  
    43  //存在服务容器时返回errServiceOffline,但不存在
    44  //跑步。
    45  	ErrServiceOffline = errors.New("service offline")
    46  
    47  //当服务容器正在运行时返回errServiceUnreachable,但是
    48  //似乎对沟通尝试没有反应。
    49  	ErrServiceUnreachable = errors.New("service unreachable")
    50  
    51  //如果Web服务没有公开的端口,则返回errnotexposed,或者
    52  //它前面的反向代理来转发请求。
    53  	ErrNotExposed = errors.New("service not exposed, nor proxied")
    54  )
    55  
    56  //ContainerInfos是大型检验数据集的一个大大简化的版本。
    57  //从Docker-Inspect返回,被puppeth解析成易于使用的形式。
    58  type containerInfos struct {
    59  running bool              //标记容器当前是否正在运行
    60  envvars map[string]string //容器上设置的环境变量集合
    61  portmap map[string]int    //从内部端口/协议组合到主机绑定的端口映射
    62  volumes map[string]string //从容器到主机目录的卷装入点
    63  }
    64  
    65  //InspectContainer运行Docker根据正在运行的容器进行检查
    66  func inspectContainer(client *sshClient, container string) (*containerInfos, error) {
    67  //检查是否有正在运行服务的容器
    68  	out, err := client.Run(fmt.Sprintf("docker inspect %s", container))
    69  	if err != nil {
    70  		return nil, ErrServiceUnknown
    71  	}
    72  //如果是,则提取各种配置选项
    73  	type inspection struct {
    74  		State struct {
    75  			Running bool
    76  		}
    77  		Mounts []struct {
    78  			Source      string
    79  			Destination string
    80  		}
    81  		Config struct {
    82  			Env []string
    83  		}
    84  		HostConfig struct {
    85  			PortBindings map[string][]map[string]string
    86  		}
    87  	}
    88  	var inspects []inspection
    89  	if err = json.Unmarshal(out, &inspects); err != nil {
    90  		return nil, err
    91  	}
    92  	inspect := inspects[0]
    93  
    94  //检索到的信息,将上面的内容解析为有意义的内容
    95  	infos := &containerInfos{
    96  		running: inspect.State.Running,
    97  		envvars: make(map[string]string),
    98  		portmap: make(map[string]int),
    99  		volumes: make(map[string]string),
   100  	}
   101  	for _, envvar := range inspect.Config.Env {
   102  		if parts := strings.Split(envvar, "="); len(parts) == 2 {
   103  			infos.envvars[parts[0]] = parts[1]
   104  		}
   105  	}
   106  	for portname, details := range inspect.HostConfig.PortBindings {
   107  		if len(details) > 0 {
   108  			port, _ := strconv.Atoi(details[0]["HostPort"])
   109  			infos.portmap[portname] = port
   110  		}
   111  	}
   112  	for _, mount := range inspect.Mounts {
   113  		infos.volumes[mount.Destination] = mount.Source
   114  	}
   115  	return infos, err
   116  }
   117  
   118  //TearDown通过ssh连接到远程计算机并终止Docker容器
   119  //在指定网络中以指定名称运行。
   120  func tearDown(client *sshClient, network string, service string, purge bool) ([]byte, error) {
   121  //拆下正在运行(或暂停)的容器
   122  	out, err := client.Run(fmt.Sprintf("docker rm -f %s_%s_1", network, service))
   123  	if err != nil {
   124  		return out, err
   125  	}
   126  //如果需要,也清除关联的Docker映像
   127  	if purge {
   128  		return client.Run(fmt.Sprintf("docker rmi %s/%s", network, service))
   129  	}
   130  	return nil, nil
   131  }
   132  
   133  //resolve通过返回
   134  //实际的服务器名称和端口,或者最好是nginx虚拟主机(如果可用)。
   135  func resolve(client *sshClient, network string, service string, port int) (string, error) {
   136  //检查服务以从中获取各种配置
   137  	infos, err := inspectContainer(client, fmt.Sprintf("%s_%s_1", network, service))
   138  	if err != nil {
   139  		return "", err
   140  	}
   141  	if !infos.running {
   142  		return "", ErrServiceOffline
   143  	}
   144  //在线容器,提取任何环境变量
   145  	if vhost := infos.envvars["VIRTUAL_HOST"]; vhost != "" {
   146  		return vhost, nil
   147  	}
   148  	return fmt.Sprintf("%s:%d", client.server, port), nil
   149  }
   150  
   151  //checkport尝试连接到给定主机上的远程主机
   152  func checkPort(host string, port int) error {
   153  	log.Trace("Verifying remote TCP connectivity", "server", host, "port", port)
   154  	conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), time.Second)
   155  	if err != nil {
   156  		return err
   157  	}
   158  	conn.Close()
   159  	return nil
   160  }