fix: the service command not working in some cases (#311)
Co-authored-by: rick <LinuxSuRen@users.noreply.github.com>
This commit is contained in:
parent
0d9016e03a
commit
be3976d91d
|
@ -56,6 +56,8 @@ jobs:
|
|||
sudo atest service status
|
||||
atest run -p '.github/testing/*.yaml' --request-ignore-error --report github --report-file bin/report.json --report-github-repo linuxsuren/api-testing --report-github-pr ${{ github.event.number }}
|
||||
sudo atest service status
|
||||
sudo atest service stop
|
||||
sudo atest service uninstall
|
||||
|
||||
atest convert -p .github/testing/core.yaml --converter jmeter -t sample.jmx
|
||||
- name: Run JMeter Tests
|
||||
|
|
|
@ -9,5 +9,6 @@ ports:
|
|||
|
||||
vscode:
|
||||
extensions:
|
||||
- golang.goteractive port
|
||||
- linuxsuren.api-testing
|
||||
- golang.go
|
||||
- Vue.volar
|
||||
|
|
284
cmd/service.go
284
cmd/service.go
|
@ -36,29 +36,22 @@ AliYun: registry.aliyuncs.com/linuxsuren/api-testing
|
|||
DaoCloud: docker.m.daocloud.io/linuxsuren/api-testing`,
|
||||
PreRunE: opt.preRunE,
|
||||
RunE: opt.runE,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
}
|
||||
flags := c.Flags()
|
||||
flags.StringVarP(&opt.action, "action", "a", "",
|
||||
fmt.Sprintf("The action of the service, available values: %v", Action("").All()))
|
||||
flags.StringVarP(&opt.scriptPath, "script-path", "", "", "The service script file path")
|
||||
flags.StringVarP(&opt.mode, "mode", "m", string(ServiceModeOS),
|
||||
fmt.Sprintf("Availeble values: %v", ServiceModeOS.All()))
|
||||
flags.StringVarP(&opt.image, "image", "", defaultImage, "The image of the service which as a container")
|
||||
flags.StringVarP(&opt.mode, "mode", "m", "",
|
||||
fmt.Sprintf("Availeble values: %v", service.ServiceModeOS.All()))
|
||||
flags.StringVarP(&opt.image, "image", "", service.DefaultImage, "The image of the service which as a container")
|
||||
flags.StringVarP(&opt.pull, "pull", "", "always", `Pull image before creating ("always"|"missing"|"never")`)
|
||||
flags.StringVarP(&opt.version, "version", "", version.GetVersion(), "The version of the service image")
|
||||
flags.StringVarP(&opt.localStorage, "local-storage", "", "/var/data/atest",
|
||||
flags.StringVarP(&opt.LocalStorage, "local-storage", "", "/var/data/atest",
|
||||
"The local storage path which will be mounted into the container")
|
||||
flags.StringVarP(&opt.secretServer, "secret-server", "", "", "The secret server URL")
|
||||
flags.StringVarP(&opt.skyWalking, "skywalking", "", "", "Push the browser tracing data to the Apache SkyWalking URL")
|
||||
flags.StringVarP(&opt.SecretServer, "secret-server", "", "", "The secret server URL")
|
||||
flags.StringVarP(&opt.SkyWalking, "skywalking", "", "", "Push the browser tracing data to the Apache SkyWalking URL")
|
||||
return
|
||||
}
|
||||
|
||||
type serverFeatureOption struct {
|
||||
secretServer string
|
||||
skyWalking string
|
||||
localStorage string
|
||||
}
|
||||
|
||||
type serviceOption struct {
|
||||
action string
|
||||
scriptPath string
|
||||
|
@ -69,46 +62,29 @@ type serviceOption struct {
|
|||
mode string
|
||||
pull string
|
||||
|
||||
serverFeatureOption
|
||||
service.ServerFeatureOption
|
||||
stdOut io.Writer
|
||||
}
|
||||
|
||||
type serviceMode string
|
||||
|
||||
const (
|
||||
ServiceModeOS serviceMode = "os"
|
||||
ServiceModeContainer serviceMode = "container"
|
||||
ServiceModePodman serviceMode = "podman"
|
||||
ServiceModeDocker serviceMode = "docker"
|
||||
)
|
||||
|
||||
func (s serviceMode) All() []serviceMode {
|
||||
return []serviceMode{ServiceModeOS, ServiceModeContainer,
|
||||
ServiceModePodman, ServiceModeDocker}
|
||||
}
|
||||
|
||||
func (s serviceMode) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (o *serviceOption) preRunE(c *cobra.Command, args []string) (err error) {
|
||||
o.stdOut = c.OutOrStdout()
|
||||
if o.action == "" && len(args) > 0 {
|
||||
o.action = args[0]
|
||||
}
|
||||
o.action = args[0]
|
||||
|
||||
switch serviceMode(o.mode) {
|
||||
case ServiceModeOS:
|
||||
o.service = service.NewService(o.Execer, o.scriptPath)
|
||||
default:
|
||||
o.service, err = o.getContainerService()
|
||||
}
|
||||
o.service = service.GetAvailableService(service.ServiceMode(o.mode), o.Execer,
|
||||
service.ContainerOption{
|
||||
Image: o.action,
|
||||
Pull: o.pull,
|
||||
Tag: o.version,
|
||||
Writer: c.OutOrStdout(),
|
||||
}, o.ServerFeatureOption, o.scriptPath)
|
||||
|
||||
if o.service == nil {
|
||||
err = fmt.Errorf("not supported service")
|
||||
return
|
||||
} else if err == nil {
|
||||
err = o.Execer.MkdirAll(o.localStorage, os.ModePerm)
|
||||
local := os.ExpandEnv("$HOME/.config/atest")
|
||||
if err = o.Execer.MkdirAll(local, os.ModePerm); err == nil {
|
||||
err = o.Execer.MkdirAll(o.LocalStorage, os.ModePerm)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -149,223 +125,3 @@ const (
|
|||
ActionRestart Action = "restart"
|
||||
ActionStatus Action = "status"
|
||||
)
|
||||
|
||||
func (a Action) All() []Action {
|
||||
return []Action{ActionInstall, ActionUninstall,
|
||||
ActionStart, ActionStop,
|
||||
ActionRestart, ActionStatus}
|
||||
}
|
||||
|
||||
func emptyThenDefault(value, defaultValue string) string {
|
||||
if value == "" {
|
||||
value = defaultValue
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (o *serviceOption) getOSService() (svc service.Service, err error) {
|
||||
//if o.Execer.OS() != fakeruntime.OSLinux && o.Execer.OS() != fakeruntime.OSDarwin {
|
||||
// err = fmt.Errorf("only support on Linux/Darwin instead of %s", o.Execer.OS())
|
||||
//} else {
|
||||
// svc = service.NewService(o.Execer, o.scriptPath)
|
||||
//}
|
||||
svc = service.NewService(o.Execer, o.scriptPath)
|
||||
return
|
||||
}
|
||||
|
||||
func (o *serviceOption) getContainerService() (service service.Service, err error) {
|
||||
var client string
|
||||
switch serviceMode(o.mode) {
|
||||
case ServiceModeDocker:
|
||||
client = ServiceModeDocker.String()
|
||||
case ServiceModePodman, ServiceModeContainer:
|
||||
client = ServiceModePodman.String()
|
||||
default:
|
||||
err = fmt.Errorf("not support mode: '%s'", o.mode)
|
||||
return
|
||||
}
|
||||
|
||||
var clientPath string
|
||||
if clientPath, err = o.LookPath(client); err == nil {
|
||||
if clientPath == "" {
|
||||
clientPath = client
|
||||
}
|
||||
service = newContainerService(o.Execer, clientPath,
|
||||
o.image, o.version, o.pull, o.serverFeatureOption, o.stdOut)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type commonService struct {
|
||||
fakeruntime.Execer
|
||||
scriptPath string
|
||||
script string
|
||||
}
|
||||
|
||||
type containerService struct {
|
||||
Execer fakeruntime.Execer
|
||||
name string
|
||||
client string
|
||||
image string
|
||||
tag string
|
||||
pull string
|
||||
localStorage string
|
||||
secretServer string
|
||||
skyWalking string
|
||||
stdOut io.Writer
|
||||
errOut io.Writer
|
||||
}
|
||||
|
||||
const defaultImage = "linuxsuren.docker.scarf.sh/linuxsuren/api-testing"
|
||||
|
||||
func newContainerService(execer fakeruntime.Execer, client, image, tag, pull string,
|
||||
featureOption serverFeatureOption, writer io.Writer) (svc service.Service) {
|
||||
if tag == "" {
|
||||
tag = "latest"
|
||||
}
|
||||
if image == "" {
|
||||
image = defaultImage
|
||||
}
|
||||
|
||||
containerServer := &containerService{
|
||||
Execer: execer,
|
||||
client: client,
|
||||
name: service.ServiceName,
|
||||
image: image,
|
||||
tag: tag,
|
||||
pull: pull,
|
||||
localStorage: featureOption.localStorage,
|
||||
secretServer: featureOption.secretServer,
|
||||
skyWalking: featureOption.skyWalking,
|
||||
stdOut: writer,
|
||||
errOut: writer,
|
||||
}
|
||||
|
||||
if strings.HasSuffix(client, ServiceModePodman.String()) {
|
||||
svc = &podmanService{
|
||||
containerService: containerServer,
|
||||
}
|
||||
} else {
|
||||
svc = containerServer
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Start() (output string, err error) {
|
||||
if s.exist() {
|
||||
output, err = s.Execer.RunCommandAndReturn(s.client, "", "start", s.name)
|
||||
} else {
|
||||
err = s.Execer.SystemCall(s.client, append([]string{s.client}, s.getStartArgs()...), os.Environ())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Stop() (output string, err error) {
|
||||
output, err = s.Execer.RunCommandAndReturn(s.client, "", "stop", s.name)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Restart() (output string, err error) {
|
||||
output, err = s.Execer.RunCommandAndReturn(s.client, "", "restart", s.name)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Status() (_ string, err error) {
|
||||
err = s.Execer.SystemCall(s.client, []string{s.client, "stats", s.name}, os.Environ())
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Install() (output string, err error) {
|
||||
output, err = s.Start()
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Uninstall() (output string, err error) {
|
||||
output, err = s.Stop()
|
||||
if err == nil {
|
||||
output, err = s.Execer.RunCommandAndReturn(s.client, "", "rm", s.name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) exist() bool {
|
||||
output, err := s.Execer.RunCommandAndReturn(s.client, "", "ps", "--all", "--filter", fmt.Sprintf("name=%s", s.name))
|
||||
return err == nil && strings.Contains(output, s.name)
|
||||
}
|
||||
|
||||
func (s *containerService) getStartArgs() []string {
|
||||
args := []string{"run", "--name=" + s.name,
|
||||
"--restart=always",
|
||||
"-d",
|
||||
fmt.Sprintf("--pull=%s", s.pull),
|
||||
"--network=host",
|
||||
"-v", s.localStorage + ":/var/www/data",
|
||||
"-v", os.ExpandEnv("$HOME/.config/atest:/root/.config/atest"),
|
||||
s.image + ":" + s.tag,
|
||||
"atest", "server"}
|
||||
if s.secretServer != "" {
|
||||
args = append(args, "--secret-server="+s.secretServer)
|
||||
}
|
||||
if s.skyWalking != "" {
|
||||
args = append(args, "--skywalking="+s.skyWalking)
|
||||
}
|
||||
args = append(args, "--console-path=/var/www/html")
|
||||
return args
|
||||
}
|
||||
|
||||
type podmanService struct {
|
||||
*containerService
|
||||
}
|
||||
|
||||
func (s *podmanService) Install() (output string, err error) {
|
||||
output, err = s.Start()
|
||||
return
|
||||
}
|
||||
|
||||
func (s *podmanService) Start() (output string, err error) {
|
||||
if s.exist() {
|
||||
err = s.Execer.RunCommandWithIO(s.client, "", s.stdOut, s.errOut, nil, "start", s.name)
|
||||
} else {
|
||||
err = s.Execer.RunCommandWithIO(s.client, "", s.stdOut, s.errOut, nil, s.getStartArgs()...)
|
||||
if err == nil {
|
||||
output, err = s.installService()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *podmanService) Stop() (output string, err error) {
|
||||
output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "stop", service.PodmanServiceName)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *podmanService) installService() (output string, err error) {
|
||||
output, err = s.Execer.RunCommandAndReturn(s.client, "", "generate", "systemd", "--new", "--files", "--name", s.name)
|
||||
if err == nil {
|
||||
var result string
|
||||
result, err = s.Execer.RunCommandAndReturn("mv", "", service.PodmanServiceName, "/etc/systemd/system")
|
||||
if err == nil {
|
||||
output = fmt.Sprintf("%s\n%s", output, result)
|
||||
if result, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "enable", service.PodmanServiceName); err == nil {
|
||||
output = fmt.Sprintf("%s\n%s", output, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *podmanService) Uninstall() (output string, err error) {
|
||||
output, err = s.containerService.Uninstall()
|
||||
if err == nil {
|
||||
var result string
|
||||
if result, err = s.uninstallService(); err == nil {
|
||||
output = fmt.Sprintf("%s\n%s", output, result)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *podmanService) uninstallService() (output string, err error) {
|
||||
output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "disable", service.PodmanServiceName)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
MIT License
|
||||
Copyright (c) 2023 API Testing Authors.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/linuxsuren/api-testing/pkg/version"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
)
|
||||
|
||||
type containerService struct {
|
||||
Execer fakeruntime.Execer
|
||||
name string
|
||||
client string
|
||||
image string
|
||||
tag string
|
||||
pull string
|
||||
localStorage string
|
||||
secretServer string
|
||||
skyWalking string
|
||||
stdOut io.Writer
|
||||
errOut io.Writer
|
||||
}
|
||||
|
||||
type ContainerOption struct {
|
||||
Image, Tag, Pull string
|
||||
Writer io.Writer
|
||||
}
|
||||
|
||||
const defaultImage = "linuxsuren.docker.scarf.sh/linuxsuren/api-testing"
|
||||
|
||||
func NewContainerService(execer fakeruntime.Execer, client string,
|
||||
featureOption ServerFeatureOption, containerOption ContainerOption) (svc Service) {
|
||||
tag := containerOption.Tag
|
||||
image := containerOption.Image
|
||||
pull := containerOption.Pull
|
||||
writer := containerOption.Writer
|
||||
|
||||
if tag == "" {
|
||||
tag = "latest"
|
||||
} else if tag == version.UnknownVersion {
|
||||
tag = "master"
|
||||
} else if !strings.HasPrefix(tag, "v") {
|
||||
tag = fmt.Sprintf("v%s", tag)
|
||||
}
|
||||
if image == "" {
|
||||
image = defaultImage
|
||||
}
|
||||
|
||||
containerServer := &containerService{
|
||||
Execer: execer,
|
||||
client: client,
|
||||
name: ServiceName,
|
||||
image: image,
|
||||
tag: tag,
|
||||
pull: pull,
|
||||
localStorage: featureOption.LocalStorage,
|
||||
secretServer: featureOption.SecretServer,
|
||||
skyWalking: featureOption.SkyWalking,
|
||||
stdOut: writer,
|
||||
errOut: writer,
|
||||
}
|
||||
|
||||
if strings.HasSuffix(client, ServiceModePodman.String()) {
|
||||
svc = &podmanService{
|
||||
containerService: containerServer,
|
||||
}
|
||||
} else {
|
||||
svc = containerServer
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Start() (output string, err error) {
|
||||
if s.exist() {
|
||||
output, err = s.Execer.RunCommandAndReturn(s.client, "", "start", s.name)
|
||||
} else {
|
||||
err = s.Execer.SystemCall(s.client, append([]string{s.client}, s.getStartArgs()...), os.Environ())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Stop() (output string, err error) {
|
||||
output, err = s.Execer.RunCommandAndReturn(s.client, "", "stop", s.name)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Restart() (output string, err error) {
|
||||
output, err = s.Execer.RunCommandAndReturn(s.client, "", "restart", s.name)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Status() (output string, err error) {
|
||||
output, err = s.Execer.RunCommandAndReturn(s.client, "", "stats", s.name)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Install() (output string, err error) {
|
||||
output, err = s.Start()
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Uninstall() (output string, err error) {
|
||||
output, err = s.Stop()
|
||||
if err == nil {
|
||||
output, err = s.Execer.RunCommandAndReturn(s.client, "", "rm", s.name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *containerService) Available() bool {
|
||||
return s.isAvailable("docker")
|
||||
}
|
||||
|
||||
func (s *containerService) exist() bool {
|
||||
output, err := s.Execer.RunCommandAndReturn(s.client, "", "ps", "--all", "--filter", fmt.Sprintf("name=%s", s.name))
|
||||
return err == nil && strings.Contains(output, s.name)
|
||||
}
|
||||
|
||||
func (s *containerService) getStartArgs() []string {
|
||||
args := []string{"run", "--name=" + s.name,
|
||||
"--restart=always",
|
||||
"-d",
|
||||
fmt.Sprintf("--pull=%s", s.pull),
|
||||
"--network=host",
|
||||
"-v", s.localStorage + ":/var/www/data",
|
||||
"-v", os.ExpandEnv("$HOME/.config/atest:/root/.config/atest"),
|
||||
s.image + ":" + s.tag,
|
||||
"atest", "server"}
|
||||
if s.secretServer != "" {
|
||||
args = append(args, "--secret-server="+s.secretServer)
|
||||
}
|
||||
if s.skyWalking != "" {
|
||||
args = append(args, "--skywalking="+s.skyWalking)
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func (s *containerService) isAvailable(client string) bool {
|
||||
clientPath, err := s.Execer.LookPath(client)
|
||||
return err == nil && clientPath != ""
|
||||
}
|
||||
|
||||
type podmanService struct {
|
||||
*containerService
|
||||
}
|
||||
|
||||
func (s *podmanService) Install() (output string, err error) {
|
||||
output, err = s.Start()
|
||||
return
|
||||
}
|
||||
|
||||
func (s *podmanService) Start() (output string, err error) {
|
||||
if s.exist() {
|
||||
err = s.Execer.RunCommandWithIO(s.client, "", s.stdOut, s.errOut, nil, "start", s.name)
|
||||
} else {
|
||||
err = s.Execer.RunCommandWithIO(s.client, "", s.stdOut, s.errOut, nil, s.getStartArgs()...)
|
||||
if err == nil {
|
||||
output, err = s.installService()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *podmanService) Stop() (output string, err error) {
|
||||
output, err = s.Execer.RunCommandAndReturn(SystemCtl, "", "stop", PodmanServiceName)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *podmanService) installService() (output string, err error) {
|
||||
output, err = s.Execer.RunCommandAndReturn(s.client, "", "generate", "systemd", "--new", "--files", "--name", s.name)
|
||||
if err == nil {
|
||||
var result string
|
||||
result, err = s.Execer.RunCommandAndReturn("mv", "", PodmanServiceName, "/etc/systemd/system")
|
||||
if err == nil {
|
||||
output = fmt.Sprintf("%s\n%s", output, result)
|
||||
if result, err = s.Execer.RunCommandAndReturn(SystemCtl, "", "enable", PodmanServiceName); err == nil {
|
||||
output = fmt.Sprintf("%s\n%s", output, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *podmanService) Uninstall() (output string, err error) {
|
||||
output, err = s.containerService.Uninstall()
|
||||
if err == nil {
|
||||
var result string
|
||||
if result, err = s.uninstallService(); err == nil {
|
||||
output = fmt.Sprintf("%s\n%s", output, result)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *podmanService) uninstallService() (output string, err error) {
|
||||
output, err = s.Execer.RunCommandAndReturn(SystemCtl, "", "disable", PodmanServiceName)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *podmanService) Available() bool {
|
||||
return s.isAvailable("podman")
|
||||
}
|
||||
|
||||
const DefaultImage = "linuxsuren.docker.scarf.sh/linuxsuren/api-testing"
|
|
@ -20,7 +20,9 @@ SOFTWARE.
|
|||
|
||||
package service
|
||||
|
||||
import fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
import (
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
)
|
||||
|
||||
// Service is the interface of service
|
||||
type Service interface {
|
||||
|
@ -30,6 +32,7 @@ type Service interface {
|
|||
Status() (string, error) // status of the service
|
||||
Install() (string, error) // install the service
|
||||
Uninstall() (string, error) // uninstall the service
|
||||
Available() bool
|
||||
}
|
||||
|
||||
type commonService struct {
|
||||
|
@ -38,9 +41,56 @@ type commonService struct {
|
|||
script string
|
||||
}
|
||||
|
||||
func emptyThenDefault(value, defaultValue string) string {
|
||||
if value == "" {
|
||||
value = defaultValue
|
||||
}
|
||||
return value
|
||||
type ServiceMode string
|
||||
|
||||
const (
|
||||
ServiceModeOS ServiceMode = "os"
|
||||
ServiceModeContainer ServiceMode = "container"
|
||||
ServiceModePodman ServiceMode = "podman"
|
||||
ServiceModeDocker ServiceMode = "docker"
|
||||
)
|
||||
|
||||
func (s ServiceMode) All() []ServiceMode {
|
||||
return []ServiceMode{ServiceModeOS, ServiceModeContainer,
|
||||
ServiceModePodman, ServiceModeDocker}
|
||||
}
|
||||
|
||||
func (s ServiceMode) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
type ServerFeatureOption struct {
|
||||
SecretServer string
|
||||
SkyWalking string
|
||||
LocalStorage string
|
||||
}
|
||||
|
||||
func GetAvailableService(mode ServiceMode, execer fakeruntime.Execer,
|
||||
containerOption ContainerOption, featureOption ServerFeatureOption,
|
||||
scriptPath string) (svc Service) {
|
||||
osService := NewService(execer, scriptPath)
|
||||
dockerService := NewContainerService(execer, "docker", featureOption, containerOption)
|
||||
podmanService := NewContainerService(execer, "podman", featureOption, containerOption)
|
||||
|
||||
switch mode {
|
||||
case ServiceModeOS:
|
||||
svc = osService
|
||||
case ServiceModeDocker, ServiceModeContainer:
|
||||
svc = dockerService
|
||||
case ServiceModePodman:
|
||||
svc = podmanService
|
||||
default:
|
||||
if osService.Available() {
|
||||
svc = osService
|
||||
} else if dockerService.Available() {
|
||||
svc = dockerService
|
||||
} else if podmanService.Available() {
|
||||
svc = podmanService
|
||||
}
|
||||
}
|
||||
|
||||
if svc != nil && !svc.Available() {
|
||||
svc = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -25,8 +25,10 @@ package service
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
"os"
|
||||
|
||||
"github.com/linuxsuren/api-testing/pkg/util"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
)
|
||||
|
||||
type macOSService struct {
|
||||
|
@ -39,7 +41,7 @@ func NewService(execer fakeruntime.Execer, scriptPath string) Service {
|
|||
return &macOSService{
|
||||
commonService: commonService{
|
||||
Execer: execer,
|
||||
scriptPath: emptyThenDefault(scriptPath, "/Library/LaunchDaemons/com.github.linuxsuren.atest.plist"),
|
||||
scriptPath: util.EmptyThenDefault(scriptPath, "/Library/LaunchDaemons/com.github.linuxsuren.atest.plist"),
|
||||
script: macOSServiceScript,
|
||||
},
|
||||
}
|
||||
|
@ -79,5 +81,10 @@ func (s *macOSService) Uninstall() (output string, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (s *macOSService) Available() bool {
|
||||
// TODO need a way to determine if it's available
|
||||
return true
|
||||
}
|
||||
|
||||
//go:embed data/macos_service.xml
|
||||
var macOSServiceScript string
|
||||
|
|
|
@ -25,15 +25,18 @@ package service
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/linuxsuren/api-testing/pkg/util"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
)
|
||||
|
||||
func NewService(execer fakeruntime.Execer, scriptPath string) Service {
|
||||
return &linuxService{
|
||||
commonService: commonService{
|
||||
Execer: execer,
|
||||
scriptPath: emptyThenDefault(scriptPath, "/lib/systemd/system/atest.service"),
|
||||
scriptPath: util.EmptyThenDefault(scriptPath, "/lib/systemd/system/atest.service"),
|
||||
script: linuxServiceScript,
|
||||
},
|
||||
}
|
||||
|
@ -79,5 +82,11 @@ func (s *linuxService) Uninstall() (output string, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (s *linuxService) Available() bool {
|
||||
output, err := s.Execer.RunCommandAndReturn("systemctl", "", "is-system-running")
|
||||
output = strings.TrimSpace(output)
|
||||
return err == nil && output != "offline"
|
||||
}
|
||||
|
||||
//go:embed data/linux_service.txt
|
||||
var linuxServiceScript string
|
||||
|
|
|
@ -25,9 +25,10 @@ package service
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
"golang.org/x/sys/windows/svc/mgr"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func NewService(execer fakeruntime.Execer, scriptPath string) Service {
|
||||
|
@ -114,3 +115,8 @@ func (s *windowsService) Uninstall() (output string, err error) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *windowsService) Available() bool {
|
||||
// TODO need a way to determine if it's available
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -26,10 +26,12 @@ package cmd
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/linuxsuren/api-testing/cmd/service"
|
||||
"github.com/linuxsuren/api-testing/pkg/server"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -119,81 +121,27 @@ func TestService(t *testing.T) {
|
|||
action: "uninstall",
|
||||
targetOS: fakeruntime.OSDarwin,
|
||||
expectOutput: "output4",
|
||||
}, {
|
||||
name: "start in podman",
|
||||
action: "start",
|
||||
targetOS: fakeruntime.OSLinux,
|
||||
mode: string(ServiceModePodman),
|
||||
expectOutput: "",
|
||||
}, {
|
||||
name: "start in docker",
|
||||
action: "start",
|
||||
targetOS: fakeruntime.OSLinux,
|
||||
mode: string(ServiceModeDocker),
|
||||
expectOutput: "",
|
||||
}, {
|
||||
name: "stop in docker",
|
||||
action: "stop",
|
||||
targetOS: fakeruntime.OSLinux,
|
||||
mode: string(ServiceModeDocker),
|
||||
expectOutput: "",
|
||||
}, {
|
||||
name: "restart in docker",
|
||||
action: "restart",
|
||||
targetOS: fakeruntime.OSLinux,
|
||||
mode: string(ServiceModeDocker),
|
||||
expectOutput: "",
|
||||
}, {
|
||||
name: "status in docker",
|
||||
action: "status",
|
||||
targetOS: fakeruntime.OSLinux,
|
||||
mode: string(ServiceModeDocker),
|
||||
expectOutput: "",
|
||||
}, {
|
||||
name: "install in docker",
|
||||
action: "install",
|
||||
targetOS: fakeruntime.OSLinux,
|
||||
mode: string(ServiceModeDocker),
|
||||
expectOutput: "",
|
||||
}, {
|
||||
name: "uninstall in docker",
|
||||
action: "uninstall",
|
||||
targetOS: fakeruntime.OSLinux,
|
||||
mode: string(ServiceModeDocker),
|
||||
expectOutput: "",
|
||||
}, {
|
||||
name: "install in podman",
|
||||
action: "install",
|
||||
targetOS: fakeruntime.OSLinux,
|
||||
mode: ServiceModePodman.String(),
|
||||
expectOutput: "",
|
||||
}, {
|
||||
name: "uninstall in podman",
|
||||
action: "uninstall",
|
||||
targetOS: fakeruntime.OSLinux,
|
||||
mode: ServiceModePodman.String(),
|
||||
expectOutput: "",
|
||||
}, {
|
||||
name: "stop in podman",
|
||||
action: "stop",
|
||||
targetOS: fakeruntime.OSLinux,
|
||||
mode: ServiceModePodman.String(),
|
||||
expectOutput: "",
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.mode == "" {
|
||||
tt.mode = string(ServiceModeOS)
|
||||
tt.mode = string(service.ServiceModeOS)
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
normalRoot := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: tt.targetOS, ExpectOutput: tt.expectOutput},
|
||||
server.NewFakeHTTPServer())
|
||||
normalRoot.SetOut(buf)
|
||||
normalRoot.SetArgs([]string{"service", "--action", tt.action,
|
||||
normalRoot.SetArgs([]string{"service",
|
||||
"--script-path", tmpFile.Name(), "--mode", tt.mode, "--image=",
|
||||
"--skywalking=http://localhost:8080",
|
||||
"--secret-server=http://localhost:9090"})
|
||||
"--secret-server=http://localhost:9090",
|
||||
tt.action})
|
||||
fmt.Println([]string{"service",
|
||||
"--script-path", tmpFile.Name(), "--mode", tt.mode, "--image=",
|
||||
"--skywalking=http://localhost:8080",
|
||||
"--secret-server=http://localhost:9090",
|
||||
tt.action})
|
||||
err = normalRoot.Execute()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, tt.expectOutput, strings.TrimSpace(buf.String()))
|
||||
|
|
|
@ -27,6 +27,8 @@ package version
|
|||
|
||||
import "fmt"
|
||||
|
||||
const UnknownVersion = "unknown"
|
||||
|
||||
// should be injected during the build process
|
||||
var version string
|
||||
var date string
|
||||
|
@ -34,7 +36,7 @@ var date string
|
|||
// GetVersion returns the version
|
||||
func GetVersion() string {
|
||||
if version == "" {
|
||||
return "unknown"
|
||||
return UnknownVersion
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue