diff --git a/internal/configure/hosts/hc_get.go b/internal/configure/hosts/hc_get.go index 37774c9ae..c32377003 100644 --- a/internal/configure/hosts/hc_get.go +++ b/internal/configure/hosts/hc_get.go @@ -29,6 +29,7 @@ import ( "github.com/opencurve/curveadm/internal/configure/curveadm" "github.com/opencurve/curveadm/internal/utils" "github.com/opencurve/curveadm/pkg/module" + "github.com/opencurve/curveadm/pkg/variable" ) func (hc *HostConfig) get(i *comm.Item) interface{} { @@ -77,6 +78,10 @@ func (hc *HostConfig) GetBecomeUser() string { return hc.getString(CONFIG_BE func (hc *HostConfig) GetLabels() []string { return hc.labels } func (hc *HostConfig) GetEnvs() []string { return hc.envs } +func (hc *HostConfig) GetInstances() int { return hc.instances } +func (hc *HostConfig) GetInstancesSequence() int { return hc.instancesSequence } +func (hc *HostConfig) GetVariables() *variable.Variables { return hc.variables } + func (hc *HostConfig) GetUser() string { user := hc.getString(CONFIG_USER) if user == "${user}" { @@ -84,7 +89,6 @@ func (hc *HostConfig) GetUser() string { } return user } - func (hc *HostConfig) GetSSHConfig() *module.SSHConfig { hostname := hc.GetSSHHostname() if len(hostname) == 0 { diff --git a/internal/configure/hosts/hosts.go b/internal/configure/hosts/hosts.go index 7efbf3cd9..30d84f4d2 100644 --- a/internal/configure/hosts/hosts.go +++ b/internal/configure/hosts/hosts.go @@ -28,16 +28,20 @@ import ( "bytes" "strings" + "github.com/spf13/viper" + "github.com/opencurve/curveadm/internal/build" "github.com/opencurve/curveadm/internal/configure/os" "github.com/opencurve/curveadm/internal/errno" "github.com/opencurve/curveadm/internal/utils" - "github.com/spf13/viper" + log "github.com/opencurve/curveadm/pkg/log/glg" + "github.com/opencurve/curveadm/pkg/variable" ) const ( - KEY_LABELS = "labels" - KEY_ENVS = "envs" + KEY_LABELS = "labels" + KEY_ENVS = "envs" + KEY_INSTANCES = "instances" PERMISSIONS_600 = 384 // -rw------- (256 + 128 = 384) ) @@ -49,10 +53,16 @@ type ( } HostConfig struct { - sequence int - config map[string]interface{} - labels []string - envs []string + sequence int + config map[string]interface{} + labels []string + envs []string + variables *variable.Variables + //instances and instancesSequence only used in the memcached deploy + //instances is the num of memcached servers will be deployed in the same host + instances int + //instancesSquence is the sequence num of memcached servers in the same host + instancesSequence int } ) @@ -71,7 +81,7 @@ func merge(parent, child map[string]interface{}) { } } -func (hc *HostConfig) convertLables() error { +func (hc *HostConfig) convertLabels() error { value := hc.config[KEY_LABELS] slice, ok := (value).([]interface{}) if !ok { @@ -107,14 +117,82 @@ func (hc *HostConfig) convertEnvs() error { hc.envs = append(hc.envs, v) } } + return nil +} + +func (hc *HostConfig) convertInstances() error { + value := hc.config[KEY_INSTANCES] + if v, ok := utils.All2Str(value); !ok { + return errno.ERR_UNSUPPORT_CONFIGURE_VALUE_TYPE. + F("hosts[%d].%s = %v", hc.sequence, KEY_INSTANCES, value) + } else if v, ok := utils.Str2Int(v); !ok { + return errno.ERR_CONFIGURE_VALUE_REQUIRES_INTEGER. + F("hosts[%d].%s = %v", hc.sequence, KEY_INSTANCES, value) + } else if v <= 0 { + return errno.ERR_CONFIGURE_VALUE_REQUIRES_POSITIVE_INTEGER. + F("hosts[%d].%s = %v", hc.sequence, KEY_INSTANCES, value) + } else { + hc.instances = v + return nil + } +} + +// convert config item to its required type after rendering, +// return error if convert failed +func (hc *HostConfig) convert() error { + for key, value := range hc.config { + if key == KEY_LABELS || key == KEY_ENVS || key == KEY_INSTANCES { + continue + } + if itemset.Get(key) == nil { + return errno.ERR_UNSUPPORT_HOSTS_CONFIGURE_ITEM. + F("hosts[%d].%s = %v", hc.sequence, key, value) + } + if v, err := itemset.Build(key, value); err != nil { + return err + } else { + hc.config[key] = v + } + } + privateKeyFile := hc.GetPrivateKeyFile() + if len(hc.GetName()) == 0 { + return errno.ERR_NAME_FIELD_MISSING. + F("hosts[%d].host/name = nil", hc.sequence) + } + if len(hc.GetHostname()) == 0 { + return errno.ERR_HOSTNAME_FIELD_MISSING. + F("hosts[%d].hostname = nil", hc.sequence) + } + if !utils.IsValidAddress(hc.GetHostname()) { + return errno.ERR_HOSTNAME_REQUIRES_VALID_IP_ADDRESS. + F("hosts[%d].hostname = %s", hc.sequence, hc.GetHostname()) + } + if hc.GetSSHPort() > os.GetMaxPortNum() { + return errno.ERR_HOSTS_SSH_PORT_EXCEED_MAX_PORT_NUMBER. + F("hosts[%d].ssh_port = %d", hc.sequence, hc.GetSSHPort()) + } + if !strings.HasPrefix(privateKeyFile, "/") { + return errno.ERR_PRIVATE_KEY_FILE_REQUIRE_ABSOLUTE_PATH. + F("hosts[%d].private_key_file = %s", hc.sequence, privateKeyFile) + } + if !hc.GetForwardAgent() { + if !utils.PathExist(privateKeyFile) { + return errno.ERR_PRIVATE_KEY_FILE_NOT_EXIST. + F("%s: no such file", privateKeyFile) + } + if utils.GetFilePermissions(privateKeyFile) != PERMISSIONS_600 { + return errno.ERR_PRIVATE_KEY_FILE_REQUIRE_600_PERMISSIONS. + F("%s: mode (%d)", privateKeyFile, utils.GetFilePermissions(privateKeyFile)) + } + } return nil } func (hc *HostConfig) Build() error { for key, value := range hc.config { if key == KEY_LABELS { // convert labels - if err := hc.convertLables(); err != nil { + if err := hc.convertLabels(); err != nil { return err } hc.config[key] = nil // delete labels section @@ -123,7 +201,13 @@ func (hc *HostConfig) Build() error { if err := hc.convertEnvs(); err != nil { return err } - hc.config[key] = nil // delete labels section + hc.config[key] = nil // delete envs section + continue + } else if key == KEY_INSTANCES { // convert instances + if err := hc.convertInstances(); err != nil { + return err + } + hc.config[key] = nil // delete instances section continue } @@ -142,27 +226,32 @@ func (hc *HostConfig) Build() error { privateKeyFile := hc.GetPrivateKeyFile() if len(hc.GetName()) == 0 { - return errno.ERR_HOST_FIELD_MISSING. + return errno.ERR_NAME_FIELD_MISSING. F("hosts[%d].host/name = nil", hc.sequence) - } else if len(hc.GetHostname()) == 0 { + } + if len(hc.GetHostname()) == 0 { return errno.ERR_HOSTNAME_FIELD_MISSING. F("hosts[%d].hostname = nil", hc.sequence) - } else if !utils.IsValidAddress(hc.GetHostname()) { + } + if !utils.IsValidAddress(hc.GetHostname()) { return errno.ERR_HOSTNAME_REQUIRES_VALID_IP_ADDRESS. F("hosts[%d].hostname = %s", hc.sequence, hc.GetHostname()) - } else if hc.GetSSHPort() > os.GetMaxPortNum() { + } + if hc.GetSSHPort() > os.GetMaxPortNum() { return errno.ERR_HOSTS_SSH_PORT_EXCEED_MAX_PORT_NUMBER. F("hosts[%d].ssh_port = %d", hc.sequence, hc.GetSSHPort()) - } else if !strings.HasPrefix(privateKeyFile, "/") { + } + if !strings.HasPrefix(privateKeyFile, "/") { return errno.ERR_PRIVATE_KEY_FILE_REQUIRE_ABSOLUTE_PATH. F("hosts[%d].private_key_file = %s", hc.sequence, privateKeyFile) } - if hc.GetForwardAgent() == false { + if !hc.GetForwardAgent() { if !utils.PathExist(privateKeyFile) { return errno.ERR_PRIVATE_KEY_FILE_NOT_EXIST. F("%s: no such file", privateKeyFile) - } else if utils.GetFilePermissions(privateKeyFile) != PERMISSIONS_600 { + } + if utils.GetFilePermissions(privateKeyFile) != PERMISSIONS_600 { return errno.ERR_PRIVATE_KEY_FILE_REQUIRE_600_PERMISSIONS. F("%s: mode (%d)", privateKeyFile, utils.GetFilePermissions(privateKeyFile)) } @@ -170,11 +259,96 @@ func (hc *HostConfig) Build() error { return nil } +// "PORT=112${instancesSquence}" -> "PORT=11201" +func (hc *HostConfig) renderVariables() error { + //0. get vars + vars := hc.GetVariables() + if err := vars.Build(); err != nil { + log.Error("Build variables failed", + log.Field("error", err)) + return errno.ERR_RESOLVE_VARIABLE_FAILED.E(err) + } + //1. all config to str + for k, v := range hc.config { + if v == nil { + continue + } + if strv, ok := utils.All2Str(v); !ok { + return errno.ERR_UNSUPPORT_CONFIGURE_VALUE_TYPE. + F("%s: %v", k, v) + } else { + hc.config[k] = strv + } + } + //2. rendering + //render labels and envs + err := func(allStrs ...[]string) error { + for k := range allStrs { + strs := allStrs[k] + for i := range strs { + realValue, err := vars.Rendering(strs[i]) + if err != nil { + return err + } + strs[i] = realValue + } + } + return nil + }(hc.labels, hc.envs) + if err != nil { + return errno.ERR_RENDERING_VARIABLE_FAILED.E(err) + } + //render config + for k, v := range hc.config { + if v == nil { + continue + } + realv, err := vars.Rendering(v.(string)) + if err != nil { + return errno.ERR_RENDERING_VARIABLE_FAILED.E(err) + } + hc.config[k] = realv + build.DEBUG(build.DEBUG_TOPOLOGY, + build.Field{Key: k, Value: v}, + build.Field{Key: k, Value: realv}) + } + //3. convert config item to its required type after rendering, + // return error if convert failed + return hc.convert() +} + func NewHostConfig(sequence int, config map[string]interface{}) *HostConfig { + vars := variable.NewVariables() + return &HostConfig{ + sequence: sequence, + config: config, + labels: []string{}, + envs: []string{}, + variables: vars, + //instances and instancesSquence only used in the memcached deploy + instances: 1, + instancesSequence: 1, + } +} + +// deepcopy a HostConfig with instancesSquence and return it (new variables) +func copyHostConfig(src *HostConfig, instancesSquence int) *HostConfig { + //deepcopy labels + newlabels := make([]string, len(src.labels)) + copy(newlabels, src.labels) + //deepcopy envs + newenvs := make([]string, len(src.envs)) + copy(newenvs, src.envs) + //create a new variables + vars := variable.NewVariables() return &HostConfig{ - sequence: sequence, - config: config, - labels: []string{}, + sequence: src.sequence, + config: utils.DeepCopy(src.config), + labels: newlabels, + envs: newenvs, + variables: vars, + instances: src.instances, + instancesSequence: instancesSquence, } } @@ -182,7 +356,6 @@ func ParseHosts(data string) ([]*HostConfig, error) { if len(data) == 0 { return nil, errno.ERR_EMPTY_HOSTS } - parser := viper.NewWithOptions(viper.KeyDelimiter("::")) parser.SetConfigType("yaml") err := parser.ReadConfig(bytes.NewBuffer([]byte(data))) @@ -210,9 +383,23 @@ func ParseHosts(data string) ([]*HostConfig, error) { return nil, errno.ERR_DUPLICATE_NAME. F("duplicate host: %s", hc.GetName()) } - hcs = append(hcs, hc) + //produce the instances of hc, append to hcs. (used in memcached deploy) + instances := hc.GetInstances() + for instancesSquence := 1; instancesSquence <= instances; instancesSquence++ { + hc_new := copyHostConfig(hc, instancesSquence) + hcs = append(hcs, hc_new) + } exist[hc.GetName()] = true } + //add Variables and Rendering + for idx, hc := range hcs { + if err = AddHostVariables(hcs, idx); err != nil { + return nil, err // already is error code + } else if err = hc.renderVariables(); err != nil { + return nil, err // already is error code + } + hc.GetVariables().Debug() + } build.DEBUG(build.DEBUG_HOSTS, hosts) return hcs, nil } diff --git a/internal/configure/hosts/variables.go b/internal/configure/hosts/variables.go new file mode 100644 index 000000000..4d31bfb66 --- /dev/null +++ b/internal/configure/hosts/variables.go @@ -0,0 +1,46 @@ +package hosts + +import ( + "fmt" + "github.com/opencurve/curveadm/internal/errno" + "github.com/opencurve/curveadm/pkg/variable" +) + +type Var struct { + name string + resolved bool +} + +var ( + hostVars = []Var{ + {name: "instances_sequence"}, + } +) + +func addVariables(hcs []*HostConfig, idx int, vars []Var) error { + hc := hcs[idx] + for _, v := range vars { + err := hc.GetVariables().Register(variable.Variable{ + Name: v.name, + Value: getValue(v.name, hcs, idx), + }) + if err != nil { + return errno.ERR_REGISTER_VARIABLE_FAILED.E(err) + } + } + + return nil +} + +func AddHostVariables(hcs []*HostConfig, idx int) error { + return addVariables(hcs, idx, hostVars) +} + +func getValue(name string, hcs []*HostConfig, idx int) string { + hc := hcs[idx] + switch name { + case "instances_sequence": + return fmt.Sprintf("%02d", hc.GetInstancesSequence()) + } + return "" +} diff --git a/internal/errno/errno.go b/internal/errno/errno.go index 2b6ec0ca7..d51bfd942 100644 --- a/internal/errno/errno.go +++ b/internal/errno/errno.go @@ -305,7 +305,7 @@ var ( ERR_PARSE_HOSTS_FAILED = EC(320003, "parse hosts failed") // 321: configure (hosts.yaml: invalid configure value) ERR_UNSUPPORT_HOSTS_CONFIGURE_ITEM = EC(321000, "unsupport hosts configure item") - ERR_HOST_FIELD_MISSING = EC(321001, "host field missing") + ERR_NAME_FIELD_MISSING = EC(321001, "name field missing") ERR_HOSTNAME_FIELD_MISSING = EC(321002, "hostname field missing") ERR_HOSTS_SSH_PORT_EXCEED_MAX_PORT_NUMBER = EC(321003, "ssh_port exceed max port number") ERR_PRIVATE_KEY_FILE_REQUIRE_ABSOLUTE_PATH = EC(321004, "SSH private key file needs to be an absolute path") diff --git a/playbook/memcached/hosts_instances.yaml b/playbook/memcached/hosts_instances.yaml new file mode 100644 index 000000000..2f6d8220b --- /dev/null +++ b/playbook/memcached/hosts_instances.yaml @@ -0,0 +1,46 @@ +global: + user: curve + ssh_port: 22 + private_key_file: /home/curve/.ssh/id_rsa + +hosts: + - name: server-host1 + hostname: 10.0.1.1 + labels: + - memcached + envs: + - SUDO_ALIAS=sudo + - ENGINE=docker + - IMAGE=memcached:1.6.17 + - EXPORTER_IMAGE=quay.io/prometheus/memcached-exporter:v0.13.0 + - LISTEN=10.0.1.1 + - PORT=112${instances_sequence} + - EXPORTER_PORT=91${instances_sequence} + - USER=root + - MEMORY_LIMIT=32768 # item memory in megabytes + - MAX_ITEM_SIZE=8m # adjusts max item size (default: 1m, min: 1k, max: 1024m) + - EXT_PATH=/mnt/memcachefile/cachefile:10${instances_sequence}G + - EXT_WBUF_SIZE=8 # size in megabytes of page write buffers. + - EXT_ITEM_AGE=1 # store items idle at least this long (seconds, default: no age limit) + - VERBOSE="v" + instances: 3 + + - name: server-host2 + hostname: 10.0.1.2 + labels: + - memcached + envs: + - SUDO_ALIAS=sudo + - ENGINE=docker + - IMAGE=memcached:1.6.17 + - EXPORTER_IMAGE=quay.io/prometheus/memcached-exporter:v0.13.0 + - LISTEN=10.0.1.2 + - PORT=11211 + - EXPORTER_PORT=9151 + - USER=root + - MEMORY_LIMIT=32768 # item memory in megabytes + - MAX_ITEM_SIZE=8m # adjusts max item size (default: 1m, min: 1k, max: 1024m) + - EXT_PATH=/mnt/memcachefile/cachefile:1024G + - EXT_WBUF_SIZE=8 # size in megabytes of page write buffers. + - EXT_ITEM_AGE=1 # store items idle at least this long (seconds, default: no age limit) + - VERBOSE="v" \ No newline at end of file diff --git a/playbook/memcached/scripts/clean.sh b/playbook/memcached/scripts/clean.sh index 84e0f2a6a..96b36554a 100644 --- a/playbook/memcached/scripts/clean.sh +++ b/playbook/memcached/scripts/clean.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash g_container_name="memcached-"${PORT} +g_exporter_container_name="memcached-exporter-"${EXPORTER_PORT} g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" g_rm_cmd="${SUDO_ALIAS} rm -rf" @@ -23,6 +24,13 @@ precheck() { die "container [${g_container_name}] not exists!!!\n" exit 1 fi + if [ "${EXPORTER_PORT}" ];then + container_id=`${g_docker_cmd} ps --all --format "{{.ID}}" --filter name=${g_exporter_container_name}` + if [ -z ${container_id} ]; then + die "container [${g_exporter_container_name}] not exists!!!\n" + exit 1 + fi + fi } stop_container() { @@ -32,6 +40,14 @@ stop_container() { exit 1 fi success "rm container[${g_container_name}]\n" + if [ "${EXPORTER_PORT}" ];then + msg=`${g_docker_cmd} rm ${g_exporter_container_name}` + if [ $? -ne 0 ];then + die "${msg}\n" + exit 1 + fi + success "rm container[${g_exporter_container_name}]\n" + fi } rm_cachefile() { diff --git a/playbook/memcached/scripts/deploy.sh b/playbook/memcached/scripts/deploy.sh index f2c48b165..7df5a2c25 100644 --- a/playbook/memcached/scripts/deploy.sh +++ b/playbook/memcached/scripts/deploy.sh @@ -1,7 +1,9 @@ #!/usr/bin/env bash g_container_name="memcached-"${PORT} +g_exporter_container_name="memcached-exporter-"${EXPORTER_PORT} g_start_args="" +g_exporter_start_args="" g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" g_lsof_cmd="${SUDO_ALIAS} lsof" g_rm_cmd="${SUDO_ALIAS} rm -rf" @@ -28,7 +30,21 @@ precheck() { container_id=`${g_docker_cmd} ps --format "{{.ID}}" --filter name=${g_container_name} --all` if [ "${container_id}" ]; then success "container [${g_container_name}] already exists, skip\n" - exit 0 + exit 1 + fi + + if [ "${EXPORTER_PORT}" ];then + container_id=`${g_docker_cmd} ps --format "{{.ID}}" --filter name=${g_exporter_container_name} --all` + if [ "${container_id}" ]; then + success "container [${g_exporter_container_name}] already exists, skip\n" + exit 1 + fi + + ${g_lsof_cmd} -i:${EXPORTER_PORT} >& /dev/null + if [ $? -eq 0 ];then + die "port[${EXPORTER_PORT}] is in use!\n" + exit 1 + fi fi # check port @@ -79,14 +95,28 @@ init() { if [ "${VERBOSE}" ];then g_start_args="${g_start_args} -${VERBOSE}" fi + + + if [ "${EXPORTER_PORT}" ];then + g_exporter_start_args="${g_exporter_start_args} --memcached.address=${LISTEN}:${PORT}" + g_exporter_start_args="${g_exporter_start_args} --web.listen-address=${LISTEN}:${EXPORTER_PORT}" + fi } create_container() { - success "create container [${g_container_name}]\n" ${g_docker_cmd} create --name ${g_container_name} ${g_user} --network host ${g_volume_bind} ${IMAGE} memcached ${g_start_args} >& /dev/null - - success "start container [${g_container_name}]\n" + success "create container [${g_container_name}]\n" + if [ "${EXPORTER_PORT}" ];then + ${g_docker_cmd} create --name ${g_exporter_container_name} --network host ${EXPORTER_IMAGE} ${g_exporter_start_args} >& /dev/null + success "create container [${g_exporter_container_name}]\n" + fi ${g_docker_cmd} start ${g_container_name} >& /dev/null + success "start container [${g_container_name}]\n" + if [ "${EXPORTER_PORT}" ];then + ${g_docker_cmd} start ${g_exporter_container_name} >& /dev/null + success "start container [${g_exporter_container_name}]\n" + fi + success "wait 3 seconds, check container status...\n" sleep 3 @@ -95,14 +125,25 @@ create_container() { if [ ${g_status} != "running" ]; then exit 1 fi + if [ "${EXPORTER_PORT}" ];then + if [ ${g_exporter_status} != "running" ]; then + exit 1 + fi + fi } get_status_container() { g_status=`${g_docker_cmd} inspect --format='{{.State.Status}}' ${g_container_name}` + if [ "${EXPORTER_PORT}" ];then + g_exporter_status=`${g_docker_cmd} inspect --format='{{.State.Status}}' ${g_exporter_container_name}` + fi } show_info_container() { ${g_docker_cmd} ps --all --filter "name=${g_container_name}" --format="table {{.ID}}\t{{.Names}}\t{{.Status}}" + if [ "${EXPORTER_PORT}" ];then + ${g_docker_cmd} ps --all --filter "name=${g_exporter_container_name}" --format="table {{.ID}}\t{{.Names}}\t{{.Status}}" + fi } precheck diff --git a/playbook/memcached/scripts/start.sh b/playbook/memcached/scripts/start.sh index 9c7c380fa..bd9e33455 100644 --- a/playbook/memcached/scripts/start.sh +++ b/playbook/memcached/scripts/start.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash g_container_name="memcached-"${PORT} +g_exporter_container_name="memcached-exporter-"${EXPORTER_PORT} g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" g_rm_cmd="${SUDO_ALIAS} rm -rf" g_mkdir_cmd="${SUDO_ALIAS} mkdir -p" @@ -34,6 +35,10 @@ precheck() { start_container() { ${g_docker_cmd} start ${g_container_name} >& /dev/null success "start container[${g_container_name}]\n" + if [ "${EXPORTER_PORT}" ];then + ${g_docker_cmd} start ${g_exporter_container_name} >& /dev/null + success "start container[${g_exporter_container_name}]\n" + fi } get_status_container() { diff --git a/playbook/memcached/scripts/status.sh b/playbook/memcached/scripts/status.sh index ed875ec85..32507bb5a 100644 --- a/playbook/memcached/scripts/status.sh +++ b/playbook/memcached/scripts/status.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash g_container_name="memcached-"${PORT} +g_exporter_container_name="memcached-exporter-"${EXPORTER_PORT} g_start_args="" g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" g_volume_bind="" g_container_id="" -g_status="running" function msg() { printf '%b' "$1" >&2 @@ -26,20 +26,39 @@ precheck() { success "container [${g_container_name}] not exists!!!" exit 1 fi + if [ "${EXPORTER_PORT}" ];then + g_container_id=`${g_docker_cmd} ps --all --format "{{.ID}}" --filter name=${g_exporter_container_name}` + if [ -z ${g_container_id} ]; then + success "container [${g_exporter_container_name}] not exists!!!" + exit 1 + fi + fi } show_info_container() { ${g_docker_cmd} ps --all --filter "name=${g_container_name}" --format="table {{.ID}}\t{{.Names}}\t{{.Status}}" + if [ "${EXPORTER_PORT}" ];then + ${g_docker_cmd} ps --all --filter "name=${g_exporter_container_name}" --format="table {{.ID}}\t{{.Names}}\t{{.Status}}" + fi } show_ip_port() { printf "memcached addr:\t%s:%d\n" ${LISTEN} ${PORT} + if [ "${EXPORTER_PORT}" ];then + printf "memcached-exporter addr:\t%s:%d\n" ${LISTEN} ${EXPORTER_PORT} + fi } get_status_container() { - g_status=`${g_docker_cmd} inspect --format='{{.State.Status}}' ${g_container_name}` - if [ ${g_status} != "running" ]; then + status=`${g_docker_cmd} inspect --format='{{.State.Status}}' ${g_container_name}` + if [ ${status} != "running" ]; then + exit 1 + fi + if [ "${EXPORTER_PORT}" ];then + status=`${g_docker_cmd} inspect --format='{{.State.Status}}' ${g_exporter_container_name}` + if [ ${status} != "running" ]; then exit 1 + fi fi } diff --git a/playbook/memcached/scripts/stop.sh b/playbook/memcached/scripts/stop.sh index 2dc84e53f..2d51a2b5b 100644 --- a/playbook/memcached/scripts/stop.sh +++ b/playbook/memcached/scripts/stop.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash g_container_name="memcached-"${PORT} +g_exporter_container_name="memcached-exporter-"${EXPORTER_PORT} g_docker_cmd="${SUDO_ALIAS} ${ENGINE}" function msg() { @@ -22,11 +23,22 @@ precheck() { die "container [${g_container_name}] not exists!!!\n" exit 1 fi + if [ "${EXPORTER_PORT}" ];then + container_id=`${g_docker_cmd} ps --all --format "{{.ID}}" --filter name=${g_exporter_container_name}` + if [ -z ${container_id} ]; then + die "container [${g_exporter_container_name}] not exists!!!\n" + exit 1 + fi + fi } stop_container() { ${g_docker_cmd} stop ${g_container_name} >& /dev/null success "stop container[${g_container_name}]\n" + if [ "${EXPORTER_PORT}" ];then + ${g_docker_cmd} stop ${g_exporter_container_name} >& /dev/null + success "stop container[${g_exporter_container_name}]\n" + fi } precheck