diff --git a/cmd/root.go b/cmd/root.go index 7984fed..017af0d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -16,13 +16,16 @@ limitations under the License. package cmd -import "github.com/spf13/cobra" +import ( + exec "github.com/linuxsuren/go-fake-runtime" + "github.com/spf13/cobra" +) func CreateRootCmd() (c *cobra.Command) { c = &cobra.Command{ Use: "atest-collector", Short: "A collector for API testing, it will start a HTTP proxy server", } - c.AddCommand(createCollectorCmd(), createControllerCmd()) + c.AddCommand(createCollectorCmd(), createControllerCmd(), createServiceCommand(exec.FakeExecer{})) return } diff --git a/cmd/service.go b/cmd/service.go new file mode 100644 index 0000000..18d54da --- /dev/null +++ b/cmd/service.go @@ -0,0 +1,149 @@ +/* +Copyright 2024 LinuxSuRen. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "fmt" + "io" + "os" + "strings" + + "github.com/linuxsuren/api-testing/pkg/version" + fakeruntime "github.com/linuxsuren/go-fake-runtime" + service "github.com/linuxsuren/go-service" + "github.com/spf13/cobra" +) + +func createServiceCommand(execer fakeruntime.Execer) (c *cobra.Command) { + opt := &serviceOption{ + Execer: execer, + } + c = &cobra.Command{ + Use: "service", + Aliases: []string{"s"}, + Example: `atest service install +atest service start`, + Short: "Install atest as service", + Long: `It could be a native or container service. +Try use sudo if you met any permission issues. + +You could choose the alternative images: +Docker Hub: docker.io/linuxsuren/api-testing +GitHub Container Registry: ghcr.io/linuxsuren/api-testing +Scarf: linuxsuren.docker.scarf.sh/linuxsuren/api-testing +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.scriptPath, "script-path", "", "", "The service script file path") + flags.StringVarP(&opt.mode, "mode", "m", "", + fmt.Sprintf("Availeble values: %v", service.ServiceModeOS.All())) + flags.StringVarP(&opt.image, "image", "", 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", + "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") + return +} + +const defaultImage = "linuxsuren.docker.scarf.sh/linuxsuren/api-testing" + +type serviceOption struct { + action string + scriptPath string + service service.Service + image string + version string + fakeruntime.Execer + mode string + pull string + + SecretServer string + SkyWalking string + LocalStorage string + stdOut io.Writer +} + +func (o *serviceOption) preRunE(c *cobra.Command, args []string) (err error) { + o.stdOut = c.OutOrStdout() + o.action = args[0] + + if o.service, err = service.GetAvailableService(service.ServiceMode(o.mode), + service.ContainerOption{ + Image: o.action, + Pull: o.pull, + Tag: o.version, + Writer: c.OutOrStdout(), + }, service.CommonService{ + ID: "atest-collector", + Name: "atest-collector", + Description: "atest-collector", + Command: "atest-collector", + Args: []string{"controller", "/Users/rick/.config/atest/sample_controller.yaml"}, + Execer: o.Execer, + }); err != nil { + return + } + + 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 +} + +func (o *serviceOption) runE(c *cobra.Command, args []string) (err error) { + var output string + switch Action(o.action) { + case ActionInstall: + output, err = o.service.Install() + case ActionUninstall: + output, err = o.service.Uninstall() + case ActionStart: + output, err = o.service.Start() + case ActionStop: + output, err = o.service.Stop() + case ActionRestart: + output, err = o.service.Restart() + case ActionStatus: + output, err = o.service.Status() + default: + err = fmt.Errorf("not support action: %q", o.action) + } + + output = strings.TrimSpace(output) + if output != "" { + c.Println(output) + } + return +} + +type Action string + +const ( + ActionInstall Action = "install" + ActionUninstall Action = "uninstall" + ActionStart Action = "start" + ActionStop Action = "stop" + ActionRestart Action = "restart" + ActionStatus Action = "status" +) diff --git a/go.mod b/go.mod index 84c4e86..170f0ea 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,8 @@ require ( github.com/huandu/xstrings v1.3.3 // indirect github.com/imdario/mergo v0.3.11 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/linuxsuren/go-fake-runtime v0.0.4 // indirect + github.com/linuxsuren/go-service v0.0.1 // indirect github.com/mitchellh/copystructure v1.0.0 // indirect github.com/mitchellh/reflectwalk v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -32,6 +34,7 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect golang.org/x/crypto v0.15.0 // indirect + golang.org/x/sys v0.15.0 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index e1d2247..3754574 100644 --- a/go.sum +++ b/go.sum @@ -31,6 +31,10 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/linuxsuren/api-testing v0.0.15 h1:lDcMRfWuWHJVF5R4GG5OAc8h9XCOJipotWWx+d9VEC0= github.com/linuxsuren/api-testing v0.0.15/go.mod h1:Qww1Tqdh9t3Pi6DPqa9szVCJBjPL7dqdXoisxODfwnw= +github.com/linuxsuren/go-fake-runtime v0.0.4 h1:y+tvBuw6MKTCav8Bo5HWwaXhBx1Z//VAvqI3gpOWqvw= +github.com/linuxsuren/go-fake-runtime v0.0.4/go.mod h1:zmh6J78hSnWZo68faMA2eKOdaEp8eFbERHi3ZB9xHCQ= +github.com/linuxsuren/go-service v0.0.1 h1:GoeK2HLDlRh+QQvFlxOferGtDUwzO3YduumMJ0XYPJ8= +github.com/linuxsuren/go-service v0.0.1/go.mod h1:QX22v61PxpOfJa4Xug8qzGTbPjclDZFx2j1PlGLknJw= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= @@ -81,6 +85,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=