unregister runner (#1875)

* fix(login): expire cookie on error with login

* feat: allows to unregister runner via cli

* feat(runner): add subcommands

* feat(runners): unregister command

* refactor(runner): move config to util.gol

* Revert "fix(login): expire cookie on error with login"

This reverts commit 6d726e3475.
This commit is contained in:
Denis Gukov 2024-03-27 14:43:41 +01:00 committed by GitHub
parent 60d759872a
commit d33d752bea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 158 additions and 62 deletions

View File

@ -189,7 +189,7 @@ func RegisterRunner(w http.ResponseWriter, r *http.Request) {
return
}
res := runners.RunnerConfig{
res := util.RunnerConfig{
RunnerID: runner.ID,
Token: runner.Token,
}

View File

@ -1,27 +1,19 @@
package cmd
import (
"github.com/ansible-semaphore/semaphore/services/runners"
"github.com/ansible-semaphore/semaphore/util"
"github.com/spf13/cobra"
"os"
)
func init() {
rootCmd.AddCommand(runnerCmd)
}
func runRunner() {
util.ConfigInit(configPath)
taskPool := runners.JobPool{}
taskPool.Run()
}
var runnerCmd = &cobra.Command{
Use: "runner",
Short: "Run in runner mode",
Run: func(cmd *cobra.Command, args []string) {
runRunner()
_ = cmd.Help()
os.Exit(0)
},
}

27
cli/cmd/runner_start.go Normal file
View File

@ -0,0 +1,27 @@
package cmd
import (
"github.com/ansible-semaphore/semaphore/services/runners"
"github.com/ansible-semaphore/semaphore/util"
"github.com/spf13/cobra"
)
func init() {
runnerCmd.AddCommand(runnerStartCmd)
}
func runRunner() {
util.ConfigInit(configPath)
taskPool := runners.JobPool{}
taskPool.Run()
}
var runnerStartCmd = &cobra.Command{
Use: "start",
Short: "Run in runner mode",
Run: func(cmd *cobra.Command, args []string) {
runRunner()
},
}

View File

@ -0,0 +1,29 @@
package cmd
import (
"github.com/ansible-semaphore/semaphore/services/runners"
"github.com/ansible-semaphore/semaphore/util"
"github.com/spf13/cobra"
)
func init() {
runnerCmd.AddCommand(runnerUnregisterCmd)
}
func unregisterRunner() {
util.ConfigInit(configPath)
taskPool := runners.JobPool{}
err := taskPool.Unregister()
if err != nil {
panic(err)
}
}
var runnerUnregisterCmd = &cobra.Command{
Use: "unregister",
Short: "Unregister runner from the server",
Run: func(cmd *cobra.Command, args []string) {
unregisterRunner()
},
}

View File

@ -47,11 +47,6 @@ type job struct {
environmentVars []string
}
type RunnerConfig struct {
RunnerID int `json:"runner_id"`
Token string `json:"token"`
}
type JobData struct {
Username string
IncomingVersion *string
@ -105,7 +100,7 @@ type JobPool struct {
queue []*job
config *RunnerConfig
config *util.RunnerConfig
processing int32
}
@ -176,6 +171,45 @@ func (p *runningJob) logPipe(reader *bufio.Reader) {
}
func (p *JobPool) Unregister() (err error) {
config, err := util.LoadRunnerSettings(util.Config.Runner.ConfigFile)
if err != nil {
return
}
if config.Token == "" {
return fmt.Errorf("runner is not registered")
}
client := &http.Client{}
url := util.Config.Runner.ApiURL + "/runners"
req, err := http.NewRequest("DELETE", url, nil)
if err != nil {
return
}
resp, err := client.Do(req)
if err != nil {
return
}
if resp.StatusCode >= 400 && resp.StatusCode != 404 {
err = fmt.Errorf("encountered error while unregistering runner; server returned code %d", resp.StatusCode)
return
}
err = os.Remove(util.Config.Runner.ConfigFile)
if err != nil {
return
}
return
}
func (p *JobPool) Run() {
queueTicker := time.NewTicker(5 * time.Second)
requestTimer := time.NewTicker(1 * time.Second)
@ -190,7 +224,7 @@ func (p *JobPool) Run() {
if p.tryRegisterRunner() {
log.Info("The runner has been registered on the server")
log.Info("The runner has been started")
break
}
@ -321,52 +355,19 @@ func (p *JobPool) tryRegisterRunner() bool {
log.Info("Attempting to register on the server")
if os.Getenv("SEMAPHORE_RUNNER_ID") != "" {
config, err := util.LoadRunnerSettings(util.Config.Runner.ConfigFile)
runnerId, err := strconv.Atoi(os.Getenv("SEMAPHORE_RUNNER_ID"))
if err != nil {
panic(err)
}
if os.Getenv("SEMAPHORE_RUNNER_TOKEN") == "" {
panic(fmt.Errorf("runner token required"))
}
p.config = &RunnerConfig{
RunnerID: runnerId,
Token: os.Getenv("SEMAPHORE_RUNNER_TOKEN"),
}
return true
}
_, err := os.Stat(util.Config.Runner.ConfigFile)
if err == nil {
configBytes, err2 := os.ReadFile(util.Config.Runner.ConfigFile)
if err2 != nil {
panic(err2)
}
var config RunnerConfig
err2 = json.Unmarshal(configBytes, &config)
if err2 != nil {
panic(err2)
}
p.config = &config
return true
}
if !os.IsNotExist(err) {
if err != nil {
panic(err)
}
if config.Token != "" {
p.config = &config
return true
}
// Can not restore runner configuration. Register new runner on the server.
if util.Config.Runner.RegistrationToken == "" {
panic("registration token cannot be empty")
}
@ -401,7 +402,6 @@ func (p *JobPool) tryRegisterRunner() bool {
return false
}
var config RunnerConfig
err = json.Unmarshal(body, &config)
if err != nil {
fmt.Println("Error parsing JSON:", err)

View File

@ -97,6 +97,11 @@ const (
//
// */
type RunnerConfig struct {
RunnerID int `json:"runner_id" env:"SEMAPHORE_RUNNER_ID"`
Token string `json:"token" env:"SEMAPHORE_RUNNER_TOKEN"`
}
type RunnerSettings struct {
ApiURL string `json:"api_url" env:"SEMAPHORE_RUNNER_API_URL"`
RegistrationToken string `json:"registration_token" env:"SEMAPHORE_RUNNER_REGISTRATION_TOKEN"`
@ -202,6 +207,49 @@ func (conf *ConfigType) ToJSON() ([]byte, error) {
return json.MarshalIndent(&conf, " ", "\t")
}
func LoadRunnerSettings(path string) (config RunnerConfig, err error) {
configFileExists := false
if path != "" {
_, err = os.Stat(path)
if os.IsNotExist(err) {
configFileExists = false
} else if err != nil {
return
} else {
configFileExists = true
}
}
if configFileExists {
var configBytes []byte
configBytes, err = os.ReadFile(path)
if err != nil {
return
}
err = json.Unmarshal(configBytes, &config)
if err != nil {
return
}
}
err = loadEnvironmentToObject(&config)
if err != nil {
return
}
err = loadDefaultsToObject(&config)
return
}
// ConfigInit reads in cli flags, and switches actions appropriately on them
func ConfigInit(configPath string) {
fmt.Println("Loading config")