chaosblade

Форк
0
/
cplus.go 
135 строк · 4.4 Кб
1
/*
2
 * Copyright 1999-2020 Alibaba Group Holding Ltd.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package cplus
18

19
import (
20
	"context"
21
	"fmt"
22
	"github.com/chaosblade-io/chaosblade-spec-go/log"
23
	"path"
24
	"strings"
25
	"time"
26

27
	"github.com/chaosblade-io/chaosblade-spec-go/channel"
28
	"github.com/chaosblade-io/chaosblade-spec-go/spec"
29
	"github.com/chaosblade-io/chaosblade-spec-go/util"
30
)
31

32
const ApplicationName = "chaosblade-exec-cplus"
33
const RemoveAction = "remove"
34

35
var cplusBinPath = path.Join(util.GetLibHome(), "cplus", ApplicationName)
36
var scriptDefaultPath = path.Join(util.GetLibHome(), "cplus", "script")
37

38
// 启动 spring boot application,需要校验程序是否已启动
39
func Prepare(ctx context.Context, port, ip string) *spec.Response {
40

41
	response := preCheck(ctx, port)
42
	if !response.Success {
43
		return response
44
	}
45
	response = startProxy(ctx, port, ip)
46
	if !response.Success {
47
		return response
48
	}
49
	return postCheck(ctx, port)
50
}
51

52
func preCheck(ctx context.Context, port string) *spec.Response {
53
	// check spring boot application
54
	if processExists(port) {
55
		return spec.ReturnSuccess("the server proxy has been started")
56
	}
57
	// check chaosblade-exec-cplus.jar file exists or not
58
	if !util.IsExist(cplusBinPath) {
59
		log.Errorf(ctx, spec.ChaosbladeFileNotFound.Sprintf(cplusBinPath))
60
		return spec.ResponseFailWithFlags(spec.ChaosbladeFileNotFound, cplusBinPath)
61
	}
62
	// check script file
63
	if !util.IsExist(scriptDefaultPath) {
64
		log.Errorf(ctx, spec.ChaosbladeFileNotFound.Sprintf(scriptDefaultPath))
65
		return spec.ResponseFailWithFlags(spec.ChaosbladeFileNotFound, scriptDefaultPath)
66
	}
67
	// check the port has been used or not
68
	portInUse := util.CheckPortInUse(port)
69
	if portInUse {
70
		log.Errorf(ctx, spec.ParameterInvalid.Sprintf("port", port, "the port has been used"))
71
		return spec.ResponseFailWithFlags(spec.ParameterInvalid, port, "the port has been used")
72
	}
73
	return spec.ReturnSuccess("success")
74
}
75

76
func processExists(port string) bool {
77
	ctx := context.WithValue(context.Background(), channel.ProcessKey, port)
78
	pids, _ := channel.NewLocalChannel().GetPidsByProcessName(ApplicationName, ctx)
79
	if pids != nil && len(pids) > 0 {
80
		return true
81
	}
82
	return false
83
}
84

85
func startProxy(ctx context.Context, port, ip string) *spec.Response {
86
	args := fmt.Sprintf("--port %s", port)
87
	if ip != "" {
88
		args = fmt.Sprintf("%s --ip %s", args, ip)
89
	}
90
	return channel.NewLocalChannel().Run(ctx, cplusBinPath, args)
91
}
92

93
func postCheck(ctx context.Context, port string) *spec.Response {
94
	url := getProxyServiceUrl(port, "status")
95
	result, err, _ := util.Curl(ctx, url)
96
	if err != nil {
97
		log.Errorf(ctx, spec.HttpExecFailed.Sprintf(url, err))
98
		return spec.ResponseFailWithFlags(spec.HttpExecFailed, url, err)
99
	}
100
	return spec.ReturnSuccess(result)
101
}
102

103
// 停止 spring boot application
104
func Revoke(ctx context.Context, port string) *spec.Response {
105
	// check process
106
	if !processExists(port) {
107
		return spec.ReturnSuccess("process not exists")
108
	}
109
	// Get http://127.0.0.1:xxx/remove: EOF, doesn't to check the result
110
	util.Curl(ctx, getProxyServiceUrl(port, RemoveAction))
111
	time.Sleep(time.Second)
112
	ctx = context.WithValue(ctx, channel.ExcludeProcessKey, "blade")
113
	pids, err := channel.NewLocalChannel().GetPidsByProcessName(ApplicationName, ctx)
114
	if err != nil {
115
		log.Errorf(ctx, spec.ProcessIdByNameFailed.Sprintf(ApplicationName, err))
116
		return spec.ResponseFailWithFlags(spec.ProcessIdByNameFailed, ApplicationName, err)
117
	}
118
	if len(pids) > 0 {
119
		response := channel.NewLocalChannel().Run(context.Background(), "kill", fmt.Sprintf("-9 %s", strings.Join(pids, " ")))
120
		if !response.Success {
121
			return response
122
		}
123
	}
124
	// revoke failed if the check operation returns success
125
	response := postCheck(ctx, port)
126
	if response.Success {
127
		log.Errorf(ctx, spec.HttpExecFailed.Sprintf(getProxyServiceUrl(port, RemoveAction), "process exists"))
128
	}
129
	return spec.ReturnSuccess("success")
130
}
131

132
func getProxyServiceUrl(port, action string) string {
133
	return fmt.Sprintf("http://127.0.0.1:%s/%s",
134
		port, action)
135
}
136

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.