github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/cmd/puppeth/module.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:31</date>
    10  //</624342603155902464>
    11  
    12  
    13  package main
    14  
    15  import (
    16  	"encoding/json"
    17  	"errors"
    18  	"fmt"
    19  	"net"
    20  	"strconv"
    21  	"strings"
    22  	"time"
    23  
    24  	"github.com/ethereum/go-ethereum/log"
    25  )
    26  
    27  var (
    28  //当服务容器不存在时,返回errServiceUnknown。
    29  	ErrServiceUnknown = errors.New("service unknown")
    30  
    31  //存在服务容器时返回errServiceOffline,但不存在
    32  //跑步。
    33  	ErrServiceOffline = errors.New("service offline")
    34  
    35  //当服务容器正在运行时返回errServiceUnreachable,但是
    36  //似乎对沟通尝试没有反应。
    37  	ErrServiceUnreachable = errors.New("service unreachable")
    38  
    39  //如果Web服务没有公开的端口,则返回errnotexposed,或者
    40  //它前面的反向代理来转发请求。
    41  	ErrNotExposed = errors.New("service not exposed, nor proxied")
    42  )
    43  
    44  //ContainerInfos是大型检验数据集的一个大大简化的版本。
    45  //从Docker-Inspect返回,被puppeth解析成易于使用的形式。
    46  type containerInfos struct {
    47  running bool              //标记容器当前是否正在运行
    48  envvars map[string]string //容器上设置的环境变量集合
    49  portmap map[string]int    //从内部端口/协议组合到主机绑定的端口映射
    50  volumes map[string]string //从容器到主机目录的卷装入点
    51  }
    52  
    53  //InspectContainer运行Docker根据正在运行的容器进行检查
    54  func inspectContainer(client *sshClient, container string) (*containerInfos, error) {
    55  //检查是否有正在运行服务的容器
    56  	out, err := client.Run(fmt.Sprintf("docker inspect %s", container))
    57  	if err != nil {
    58  		return nil, ErrServiceUnknown
    59  	}
    60  //如果是,则提取各种配置选项
    61  	type inspection struct {
    62  		State struct {
    63  			Running bool
    64  		}
    65  		Mounts []struct {
    66  			Source      string
    67  			Destination string
    68  		}
    69  		Config struct {
    70  			Env []string
    71  		}
    72  		HostConfig struct {
    73  			PortBindings map[string][]map[string]string
    74  		}
    75  	}
    76  	var inspects []inspection
    77  	if err = json.Unmarshal(out, &inspects); err != nil {
    78  		return nil, err
    79  	}
    80  	inspect := inspects[0]
    81  
    82  //检索到的信息,将上面的内容解析为有意义的内容
    83  	infos := &containerInfos{
    84  		running: inspect.State.Running,
    85  		envvars: make(map[string]string),
    86  		portmap: make(map[string]int),
    87  		volumes: make(map[string]string),
    88  	}
    89  	for _, envvar := range inspect.Config.Env {
    90  		if parts := strings.Split(envvar, "="); len(parts) == 2 {
    91  			infos.envvars[parts[0]] = parts[1]
    92  		}
    93  	}
    94  	for portname, details := range inspect.HostConfig.PortBindings {
    95  		if len(details) > 0 {
    96  			port, _ := strconv.Atoi(details[0]["HostPort"])
    97  			infos.portmap[portname] = port
    98  		}
    99  	}
   100  	for _, mount := range inspect.Mounts {
   101  		infos.volumes[mount.Destination] = mount.Source
   102  	}
   103  	return infos, err
   104  }
   105  
   106  //TearDown通过ssh连接到远程计算机并终止Docker容器
   107  //在指定网络中以指定名称运行。
   108  func tearDown(client *sshClient, network string, service string, purge bool) ([]byte, error) {
   109  //拆下正在运行(或暂停)的容器
   110  	out, err := client.Run(fmt.Sprintf("docker rm -f %s_%s_1", network, service))
   111  	if err != nil {
   112  		return out, err
   113  	}
   114  //如果需要,也清除关联的Docker映像
   115  	if purge {
   116  		return client.Run(fmt.Sprintf("docker rmi %s/%s", network, service))
   117  	}
   118  	return nil, nil
   119  }
   120  
   121  //resolve通过返回
   122  //实际的服务器名称和端口,或者最好是nginx虚拟主机(如果可用)。
   123  func resolve(client *sshClient, network string, service string, port int) (string, error) {
   124  //检查服务以从中获取各种配置
   125  	infos, err := inspectContainer(client, fmt.Sprintf("%s_%s_1", network, service))
   126  	if err != nil {
   127  		return "", err
   128  	}
   129  	if !infos.running {
   130  		return "", ErrServiceOffline
   131  	}
   132  //在线容器,提取任何环境变量
   133  	if vhost := infos.envvars["VIRTUAL_HOST"]; vhost != "" {
   134  		return vhost, nil
   135  	}
   136  	return fmt.Sprintf("%s:%d", client.server, port), nil
   137  }
   138  
   139  //checkport尝试连接到给定主机上的远程主机
   140  func checkPort(host string, port int) error {
   141  	log.Trace("Verifying remote TCP connectivity", "server", host, "port", port)
   142  	conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), time.Second)
   143  	if err != nil {
   144  		return err
   145  	}
   146  	conn.Close()
   147  	return nil
   148  }
   149