Added more CLI commands and API endpoints

This commit is contained in:
Gabriel Adrian Samfira 2022-05-05 13:07:06 +00:00
parent 1e2e96ccb5
commit d9c65872e8
24 changed files with 901 additions and 116 deletions

View file

@ -27,7 +27,7 @@ func (a *APIController) ListPoolInstancesHandler(w http.ResponseWriter, r *http.
instances, err := a.r.ListPoolInstances(ctx, poolID)
if err != nil {
log.Printf("listing pools: %s", err)
log.Printf("listing pool instances: %s", err)
handleError(w, err)
return
}
@ -60,6 +60,68 @@ func (a *APIController) GetInstanceHandler(w http.ResponseWriter, r *http.Reques
json.NewEncoder(w).Encode(instance)
}
func (a *APIController) ListRepoInstancesHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
vars := mux.Vars(r)
repoID, ok := vars["repoID"]
if !ok {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(params.APIErrorResponse{
Error: "Bad Request",
Details: "No repo ID specified",
})
return
}
instances, err := a.r.ListRepoInstances(ctx, repoID)
if err != nil {
log.Printf("listing pools: %s", err)
handleError(w, err)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(instances)
}
func (a *APIController) ListOrgInstancesHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
vars := mux.Vars(r)
orgID, ok := vars["orgID"]
if !ok {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(params.APIErrorResponse{
Error: "Bad Request",
Details: "No org ID specified",
})
return
}
instances, err := a.r.ListOrgInstances(ctx, orgID)
if err != nil {
log.Printf("listing pools: %s", err)
handleError(w, err)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(instances)
}
func (a *APIController) ListAllInstancesHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
instances, err := a.r.ListAllInstances(ctx)
if err != nil {
log.Printf("listing instances: %s", err)
handleError(w, err)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(instances)
}
func (a *APIController) InstanceStatusMessageHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

View file

@ -266,27 +266,3 @@ func (a *APIController) UpdateOrgPoolHandler(w http.ResponseWriter, r *http.Requ
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(pool)
}
func (a *APIController) ListOrgInstancesHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
vars := mux.Vars(r)
orgID, ok := vars["orgID"]
if !ok {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(params.APIErrorResponse{
Error: "Bad Request",
Details: "No org ID specified",
})
return
}
instances, err := a.r.ListOrgInstances(ctx, orgID)
if err != nil {
log.Printf("listing pools: %s", err)
handleError(w, err)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(instances)
}

View file

@ -0,0 +1,111 @@
package controllers
import (
"encoding/json"
"log"
"net/http"
"garm/apiserver/params"
gErrors "garm/errors"
runnerParams "garm/params"
"github.com/gorilla/mux"
)
func (a *APIController) ListAllPoolsHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
pools, err := a.r.ListAllPools(ctx)
if err != nil {
log.Printf("listing pools: %s", err)
handleError(w, err)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(pools)
}
func (a *APIController) GetPoolByIDHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
vars := mux.Vars(r)
poolID, ok := vars["poolID"]
if !ok {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(params.APIErrorResponse{
Error: "Bad Request",
Details: "No pool ID specified",
})
return
}
pool, err := a.r.GetPoolByID(ctx, poolID)
if err != nil {
log.Printf("fetching pool: %s", err)
handleError(w, err)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(pool)
}
func (a *APIController) DeletePoolByIDHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
vars := mux.Vars(r)
poolID, ok := vars["poolID"]
if !ok {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(params.APIErrorResponse{
Error: "Bad Request",
Details: "No pool ID specified",
})
return
}
if err := a.r.DeletePoolByID(ctx, poolID); err != nil {
log.Printf("removing pool: %s", err)
handleError(w, err)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
func (a *APIController) UpdatePoolByIDHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
vars := mux.Vars(r)
poolID, ok := vars["poolID"]
if !ok {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(params.APIErrorResponse{
Error: "Bad Request",
Details: "No pool ID specified",
})
return
}
var poolData runnerParams.UpdatePoolParams
if err := json.NewDecoder(r.Body).Decode(&poolData); err != nil {
log.Printf("failed to decode: %s", err)
handleError(w, gErrors.ErrBadRequest)
return
}
pool, err := a.r.UpdatePoolByID(ctx, poolID, poolData)
if err != nil {
log.Printf("fetching pool: %s", err)
handleError(w, err)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(pool)
}

View file

@ -266,27 +266,3 @@ func (a *APIController) UpdateRepoPoolHandler(w http.ResponseWriter, r *http.Req
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(pool)
}
func (a *APIController) ListRepoInstancesHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
vars := mux.Vars(r)
repoID, ok := vars["repoID"]
if !ok {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(params.APIErrorResponse{
Error: "Bad Request",
Details: "No repo ID specified",
})
return
}
instances, err := a.r.ListRepoInstances(ctx, repoID)
if err != nil {
log.Printf("listing pools: %s", err)
handleError(w, err)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(instances)
}

View file

@ -42,16 +42,34 @@ func NewAPIRouter(han *controllers.APIController, logWriter io.Writer, authMiddl
apiRouter.Use(initMiddleware.Middleware)
apiRouter.Use(authMiddleware.Middleware)
// Runners (instances)
///////////
// Pools //
///////////
// List all pools
apiRouter.Handle("/pools/", log(os.Stdout, http.HandlerFunc(han.ListAllPoolsHandler))).Methods("GET", "OPTIONS")
apiRouter.Handle("/pools", log(os.Stdout, http.HandlerFunc(han.ListAllPoolsHandler))).Methods("GET", "OPTIONS")
// Get one pool
apiRouter.Handle("/pools/{poolID}/", log(os.Stdout, http.HandlerFunc(han.GetPoolByIDHandler))).Methods("GET", "OPTIONS")
apiRouter.Handle("/pools/{poolID}", log(os.Stdout, http.HandlerFunc(han.GetPoolByIDHandler))).Methods("GET", "OPTIONS")
// Delete one pool
apiRouter.Handle("/pools/{poolID}/", log(os.Stdout, http.HandlerFunc(han.DeletePoolByIDHandler))).Methods("DELETE", "OPTIONS")
apiRouter.Handle("/pools/{poolID}", log(os.Stdout, http.HandlerFunc(han.DeletePoolByIDHandler))).Methods("DELETE", "OPTIONS")
// Update one pool
apiRouter.Handle("/pools/{poolID}/", log(os.Stdout, http.HandlerFunc(han.UpdatePoolByIDHandler))).Methods("PUT", "OPTIONS")
apiRouter.Handle("/pools/{poolID}", log(os.Stdout, http.HandlerFunc(han.UpdatePoolByIDHandler))).Methods("PUT", "OPTIONS")
// List pool instances
apiRouter.Handle("/pools/instances/{poolID}/", log(os.Stdout, http.HandlerFunc(han.ListPoolInstancesHandler))).Methods("GET", "OPTIONS")
apiRouter.Handle("/pools/instances/{poolID}", log(os.Stdout, http.HandlerFunc(han.ListPoolInstancesHandler))).Methods("GET", "OPTIONS")
apiRouter.Handle("/pools/{poolID}/instances/", log(os.Stdout, http.HandlerFunc(han.ListPoolInstancesHandler))).Methods("GET", "OPTIONS")
apiRouter.Handle("/pools/{poolID}/instances", log(os.Stdout, http.HandlerFunc(han.ListPoolInstancesHandler))).Methods("GET", "OPTIONS")
/////////////
// Runners //
/////////////
// List runners
apiRouter.Handle("/instances/", log(os.Stdout, http.HandlerFunc(han.ListAllInstancesHandler))).Methods("GET", "OPTIONS")
apiRouter.Handle("/instances", log(os.Stdout, http.HandlerFunc(han.ListAllInstancesHandler))).Methods("GET", "OPTIONS")
// Get instance
apiRouter.Handle("/instances/{instanceName}/", log(os.Stdout, http.HandlerFunc(han.GetInstanceHandler))).Methods("GET", "OPTIONS")
apiRouter.Handle("/instances/{instanceName}", log(os.Stdout, http.HandlerFunc(han.GetInstanceHandler))).Methods("GET", "OPTIONS")
// Delete instance
// apiRouter.Handle("/instances/{instanceName}/", log(os.Stdout, http.HandlerFunc(han.CatchAll))).Methods("DELETE", "OPTIONS")
// apiRouter.Handle("/instances/{instanceName}", log(os.Stdout, http.HandlerFunc(han.CatchAll))).Methods("DELETE", "OPTIONS")
/////////////////////
// Repos and pools //

View file

@ -138,7 +138,7 @@ func (c *Client) GetInstanceByName(instanceName string) (params.Instance, error)
}
func (c *Client) ListPoolInstances(poolID string) ([]params.Instance, error) {
url := fmt.Sprintf("%s/api/v1/pools/instances/%s", c.Config.BaseURL, poolID)
url := fmt.Sprintf("%s/api/v1/pools/%s/instances", c.Config.BaseURL, poolID)
var response []params.Instance
resp, err := c.client.R().
@ -153,3 +153,90 @@ func (c *Client) ListPoolInstances(poolID string) ([]params.Instance, error) {
}
return response, nil
}
func (c *Client) ListAllInstances() ([]params.Instance, error) {
url := fmt.Sprintf("%s/api/v1/instances", c.Config.BaseURL)
var response []params.Instance
resp, err := c.client.R().
SetResult(&response).
Get(url)
if err != nil || resp.IsError() {
apiErr, decErr := c.decodeAPIError(resp.Body())
if decErr != nil {
return response, errors.Wrap(decErr, "sending request")
}
return response, fmt.Errorf("error performing login: %s", apiErr.Details)
}
return response, nil
}
func (c *Client) GetPoolByID(poolID string) (params.Pool, error) {
url := fmt.Sprintf("%s/api/v1/pools/%s", c.Config.BaseURL, poolID)
var response params.Pool
resp, err := c.client.R().
SetResult(&response).
Get(url)
if err != nil || resp.IsError() {
apiErr, decErr := c.decodeAPIError(resp.Body())
if decErr != nil {
return response, errors.Wrap(decErr, "sending request")
}
return response, fmt.Errorf("error performing login: %s", apiErr.Details)
}
return response, nil
}
func (c *Client) ListAllPools() ([]params.Pool, error) {
url := fmt.Sprintf("%s/api/v1/pools", c.Config.BaseURL)
var response []params.Pool
resp, err := c.client.R().
SetResult(&response).
Get(url)
if err != nil || resp.IsError() {
apiErr, decErr := c.decodeAPIError(resp.Body())
if decErr != nil {
return response, errors.Wrap(decErr, "sending request")
}
return response, fmt.Errorf("error performing login: %s", apiErr.Details)
}
return response, nil
}
func (c *Client) DeletePoolByID(poolID string) error {
url := fmt.Sprintf("%s/api/v1/pools/%s", c.Config.BaseURL, poolID)
resp, err := c.client.R().
Delete(url)
if err != nil || resp.IsError() {
apiErr, decErr := c.decodeAPIError(resp.Body())
if decErr != nil {
return errors.Wrap(decErr, "sending request")
}
return fmt.Errorf("error deleting pool by ID: %s", apiErr.Details)
}
return nil
}
func (c *Client) UpdatePoolByID(poolID string, param params.UpdatePoolParams) (params.Pool, error) {
url := fmt.Sprintf("%s/api/v1/pools/%s", c.Config.BaseURL, poolID)
var response params.Pool
body, err := json.Marshal(param)
if err != nil {
return response, err
}
resp, err := c.client.R().
SetBody(body).
SetResult(&response).
Put(url)
if err != nil || resp.IsError() {
apiErr, decErr := c.decodeAPIError(resp.Body())
if decErr != nil {
return response, errors.Wrap(decErr, "sending request")
}
return response, fmt.Errorf("error performing login: %s", apiErr.Details)
}
return response, nil
}

View file

@ -34,7 +34,7 @@ var orgPoolAddCmd = &cobra.Command{
Use: "add",
Aliases: []string{"create"},
Short: "Add pool",
Long: `Add a new pool organization to the manager.`,
Long: `Add a new pool to an organization.`,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if needsInit {

297
cmd/garm-cli/cmd/pool.go Normal file
View file

@ -0,0 +1,297 @@
/*
Copyright © 2022 NAME HERE <EMAIL ADDRESS>
*/
package cmd
import (
"fmt"
"garm/config"
"garm/params"
"os"
"strings"
"github.com/spf13/cobra"
)
var (
poolRepository string
poolOrganization string
poolAll bool
)
// runnerCmd represents the runner command
var poolCmd = &cobra.Command{
Use: "pool",
SilenceUsage: true,
Short: "List pools",
Long: `Query information or perform operations on pools.`,
Run: nil,
}
var poolListCmd = &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "List pools",
Long: `List pools of repositories, orgs or all of the above.
This command will list pools from one repo, one org or all pools
on the system. The list flags are mutually exclusive. You must however
specify one of them.
Example:
List pools from one repo:
garm-cli pool list --repo=05e7eac6-4705-486d-89c9-0170bbb576af
List pools from one org:
garm-cli pool list --org=5493e51f-3170-4ce3-9f05-3fe690fc6ec6
List all pools from all repos and orgs:
garm-cli pool list --all
`,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if needsInit {
return needsInitError
}
var pools []params.Pool
var err error
switch len(args) {
case 0:
if cmd.Flags().Changed("repo") {
pools, err = cli.ListRepoPools(poolRepository)
} else if cmd.Flags().Changed("org") {
pools, err = cli.ListOrgPools(poolOrganization)
} else if cmd.Flags().Changed("all") {
pools, err = cli.ListAllPools()
} else {
cmd.Help()
os.Exit(0)
}
default:
cmd.Help()
os.Exit(0)
}
if err != nil {
return err
}
formatPools(pools)
return nil
},
}
var poolShowCmd = &cobra.Command{
Use: "show",
Short: "Show details for a runner",
Long: `Displays a detailed view of a single runner.`,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if needsInit {
return needsInitError
}
if len(args) == 0 {
return fmt.Errorf("requires a pool ID")
}
if len(args) > 1 {
return fmt.Errorf("too many arguments")
}
pool, err := cli.GetPoolByID(args[0])
if err != nil {
return err
}
formatOnePool(pool)
return nil
},
}
var poolDeleteCmd = &cobra.Command{
Use: "delete",
Aliases: []string{"remove", "rm", "del"},
Short: "Delete pool by ID",
Long: `Delete one pool by referencing it's ID, regardless of repo or org.`,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if needsInit {
return needsInitError
}
if len(args) == 0 {
return fmt.Errorf("requires a pool ID")
}
if len(args) > 1 {
return fmt.Errorf("too many arguments")
}
if err := cli.DeletePoolByID(args[0]); err != nil {
return err
}
return nil
},
}
var poolAddCmd = &cobra.Command{
Use: "add",
Aliases: []string{"create"},
Short: "Add pool",
Long: `Add a new pool to a repository or organization.`,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if needsInit {
return needsInitError
}
tags := strings.Split(poolTags, ",")
newPoolParams := params.CreatePoolParams{
ProviderName: poolProvider,
MaxRunners: poolMaxRunners,
MinIdleRunners: poolMinIdleRunners,
Image: poolImage,
Flavor: poolFlavor,
OSType: config.OSType(poolOSType),
OSArch: config.OSArch(poolOSArch),
Tags: tags,
Enabled: poolEnabled,
}
if err := newPoolParams.Validate(); err != nil {
return err
}
var pool params.Pool
var err error
if cmd.Flags().Changed("repo") {
pool, err = cli.CreateRepoPool(poolRepository, newPoolParams)
} else if cmd.Flags().Changed("org") {
pool, err = cli.CreateOrgPool(poolOrganization, newPoolParams)
} else {
cmd.Help()
os.Exit(0)
}
if err != nil {
return err
}
formatOnePool(pool)
return nil
},
}
var poolUpdateCmd = &cobra.Command{
Use: "update",
Short: "Update one pool",
Long: `Updates pool characteristics.
This command updates the pool characteristics. Runners already created prior to updating
the pool, will not be recreated. IF they no longer suit your needs, you will need to
explicitly remove them using the runner delete command.
`,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if needsInit {
return needsInitError
}
if len(args) == 0 {
return fmt.Errorf("command requires a poolID")
}
if len(args) > 1 {
return fmt.Errorf("too many arguments")
}
poolUpdateParams := params.UpdatePoolParams{}
if cmd.Flags().Changed("image") {
poolUpdateParams.Image = poolImage
}
if cmd.Flags().Changed("flavor") {
poolUpdateParams.Flavor = poolFlavor
}
if cmd.Flags().Changed("tags") {
poolUpdateParams.Tags = strings.Split(poolTags, ",")
}
if cmd.Flags().Changed("os-type") {
poolUpdateParams.OSType = config.OSType(poolOSType)
}
if cmd.Flags().Changed("os-arch") {
poolUpdateParams.OSArch = config.OSArch(poolOSArch)
}
if cmd.Flags().Changed("max-runners") {
poolUpdateParams.MaxRunners = &poolMaxRunners
}
if cmd.Flags().Changed("min-idle-runners") {
poolUpdateParams.MinIdleRunners = &poolMinIdleRunners
}
if cmd.Flags().Changed("enabled") {
poolUpdateParams.Enabled = &poolEnabled
}
pool, err := cli.UpdatePoolByID(args[0], poolUpdateParams)
if err != nil {
return err
}
formatOnePool(pool)
return nil
},
}
func init() {
poolListCmd.Flags().StringVarP(&poolRepository, "repo", "r", "", "List all pools within this repository.")
poolListCmd.Flags().StringVarP(&poolOrganization, "org", "o", "", "List all pools withing this organization.")
poolListCmd.Flags().BoolVarP(&poolAll, "all", "a", false, "List all pools, regardless of org or repo.")
poolListCmd.MarkFlagsMutuallyExclusive("repo", "org", "all")
poolUpdateCmd.Flags().StringVar(&poolImage, "image", "", "The provider-specific image name to use for runners in this pool.")
poolUpdateCmd.Flags().StringVar(&poolFlavor, "flavor", "", "The flavor to use for this runner.")
poolUpdateCmd.Flags().StringVar(&poolTags, "tags", "", "A comma separated list of tags to assign to this runner.")
poolUpdateCmd.Flags().StringVar(&poolOSType, "os-type", "linux", "Operating system type (windows, linux, etc).")
poolUpdateCmd.Flags().StringVar(&poolOSArch, "os-arch", "amd64", "Operating system architecture (amd64, arm, etc).")
poolUpdateCmd.Flags().UintVar(&poolMaxRunners, "max-runners", 5, "The maximum number of runner this pool will create.")
poolUpdateCmd.Flags().UintVar(&poolMinIdleRunners, "min-idle-runners", 1, "Attempt to maintain a minimum of idle self-hosted runners of this type.")
poolUpdateCmd.Flags().BoolVar(&poolEnabled, "enabled", false, "Enable this pool.")
poolAddCmd.Flags().StringVar(&poolProvider, "provider-name", "", "The name of the provider where runners will be created.")
poolAddCmd.Flags().StringVar(&poolImage, "image", "", "The provider-specific image name to use for runners in this pool.")
poolAddCmd.Flags().StringVar(&poolFlavor, "flavor", "", "The flavor to use for this runner.")
poolAddCmd.Flags().StringVar(&poolTags, "tags", "", "A comma separated list of tags to assign to this runner.")
poolAddCmd.Flags().StringVar(&poolOSType, "os-type", "linux", "Operating system type (windows, linux, etc).")
poolAddCmd.Flags().StringVar(&poolOSArch, "os-arch", "amd64", "Operating system architecture (amd64, arm, etc).")
poolAddCmd.Flags().UintVar(&poolMaxRunners, "max-runners", 5, "The maximum number of runner this pool will create.")
poolAddCmd.Flags().UintVar(&poolMinIdleRunners, "min-idle-runners", 1, "Attempt to maintain a minimum of idle self-hosted runners of this type.")
poolAddCmd.Flags().BoolVar(&poolEnabled, "enabled", false, "Enable this pool.")
poolAddCmd.MarkFlagRequired("provider-name")
poolAddCmd.MarkFlagRequired("image")
poolAddCmd.MarkFlagRequired("flavor")
poolAddCmd.MarkFlagRequired("tags")
poolAddCmd.Flags().StringVarP(&poolRepository, "repo", "r", "", "Add the new pool within this repository.")
poolAddCmd.Flags().StringVarP(&poolOrganization, "org", "o", "", "Add the new pool withing this organization.")
poolAddCmd.MarkFlagsMutuallyExclusive("repo", "org")
poolCmd.AddCommand(
poolListCmd,
poolShowCmd,
poolDeleteCmd,
poolUpdateCmd,
poolAddCmd,
)
rootCmd.AddCommand(poolCmd)
}

View file

@ -43,11 +43,11 @@ spin up instances with access to a GPU, on the desired provider.`,
Run: nil,
}
var poolAddCmd = &cobra.Command{
var repoPoolAddCmd = &cobra.Command{
Use: "add",
Aliases: []string{"create"},
Short: "Add pool",
Long: `Add a new pool repository to the manager.`,
Long: `Add a new pool to a repository.`,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if needsInit {
@ -86,7 +86,7 @@ var poolAddCmd = &cobra.Command{
},
}
var poolListCmd = &cobra.Command{
var repoPoolListCmd = &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "List repository pools",
@ -114,7 +114,7 @@ var poolListCmd = &cobra.Command{
},
}
var poolShowCmd = &cobra.Command{
var repoPoolShowCmd = &cobra.Command{
Use: "show",
Short: "Show details for one pool",
Long: `Displays detailed information about a single pool.`,
@ -137,7 +137,7 @@ var poolShowCmd = &cobra.Command{
},
}
var poolDeleteCmd = &cobra.Command{
var repoPoolDeleteCmd = &cobra.Command{
Use: "delete",
Aliases: []string{"remove", "rm", "del"},
Short: "Removes one pool",
@ -158,7 +158,7 @@ var poolDeleteCmd = &cobra.Command{
},
}
var poolUpdateCmd = &cobra.Command{
var repoPoolUpdateCmd = &cobra.Command{
Use: "update",
Short: "Update one pool",
Long: `Updates pool characteristics.
@ -222,35 +222,35 @@ explicitly remove them using the runner delete command.
}
func init() {
poolAddCmd.Flags().StringVar(&poolProvider, "provider-name", "", "The name of the provider where runners will be created.")
poolAddCmd.Flags().StringVar(&poolImage, "image", "", "The provider-specific image name to use for runners in this pool.")
poolAddCmd.Flags().StringVar(&poolFlavor, "flavor", "", "The flavor to use for this runner.")
poolAddCmd.Flags().StringVar(&poolTags, "tags", "", "A comma separated list of tags to assign to this runner.")
poolAddCmd.Flags().StringVar(&poolOSType, "os-type", "linux", "Operating system type (windows, linux, etc).")
poolAddCmd.Flags().StringVar(&poolOSArch, "os-arch", "amd64", "Operating system architecture (amd64, arm, etc).")
poolAddCmd.Flags().UintVar(&poolMaxRunners, "max-runners", 5, "The maximum number of runner this pool will create.")
poolAddCmd.Flags().UintVar(&poolMinIdleRunners, "min-idle-runners", 1, "Attempt to maintain a minimum of idle self-hosted runners of this type.")
poolAddCmd.Flags().BoolVar(&poolEnabled, "enabled", false, "Enable this pool.")
poolAddCmd.MarkFlagRequired("provider-name")
poolAddCmd.MarkFlagRequired("image")
poolAddCmd.MarkFlagRequired("flavor")
poolAddCmd.MarkFlagRequired("tags")
repoPoolAddCmd.Flags().StringVar(&poolProvider, "provider-name", "", "The name of the provider where runners will be created.")
repoPoolAddCmd.Flags().StringVar(&poolImage, "image", "", "The provider-specific image name to use for runners in this pool.")
repoPoolAddCmd.Flags().StringVar(&poolFlavor, "flavor", "", "The flavor to use for this runner.")
repoPoolAddCmd.Flags().StringVar(&poolTags, "tags", "", "A comma separated list of tags to assign to this runner.")
repoPoolAddCmd.Flags().StringVar(&poolOSType, "os-type", "linux", "Operating system type (windows, linux, etc).")
repoPoolAddCmd.Flags().StringVar(&poolOSArch, "os-arch", "amd64", "Operating system architecture (amd64, arm, etc).")
repoPoolAddCmd.Flags().UintVar(&poolMaxRunners, "max-runners", 5, "The maximum number of runner this pool will create.")
repoPoolAddCmd.Flags().UintVar(&poolMinIdleRunners, "min-idle-runners", 1, "Attempt to maintain a minimum of idle self-hosted runners of this type.")
repoPoolAddCmd.Flags().BoolVar(&poolEnabled, "enabled", false, "Enable this pool.")
repoPoolAddCmd.MarkFlagRequired("provider-name")
repoPoolAddCmd.MarkFlagRequired("image")
repoPoolAddCmd.MarkFlagRequired("flavor")
repoPoolAddCmd.MarkFlagRequired("tags")
poolUpdateCmd.Flags().StringVar(&poolImage, "image", "", "The provider-specific image name to use for runners in this pool.")
poolUpdateCmd.Flags().StringVar(&poolFlavor, "flavor", "", "The flavor to use for this runner.")
poolUpdateCmd.Flags().StringVar(&poolTags, "tags", "", "A comma separated list of tags to assign to this runner.")
poolUpdateCmd.Flags().StringVar(&poolOSType, "os-type", "linux", "Operating system type (windows, linux, etc).")
poolUpdateCmd.Flags().StringVar(&poolOSArch, "os-arch", "amd64", "Operating system architecture (amd64, arm, etc).")
poolUpdateCmd.Flags().UintVar(&poolMaxRunners, "max-runners", 5, "The maximum number of runner this pool will create.")
poolUpdateCmd.Flags().UintVar(&poolMinIdleRunners, "min-idle-runners", 1, "Attempt to maintain a minimum of idle self-hosted runners of this type.")
poolUpdateCmd.Flags().BoolVar(&poolEnabled, "enabled", false, "Enable this pool.")
repoPoolUpdateCmd.Flags().StringVar(&poolImage, "image", "", "The provider-specific image name to use for runners in this pool.")
repoPoolUpdateCmd.Flags().StringVar(&poolFlavor, "flavor", "", "The flavor to use for this runner.")
repoPoolUpdateCmd.Flags().StringVar(&poolTags, "tags", "", "A comma separated list of tags to assign to this runner.")
repoPoolUpdateCmd.Flags().StringVar(&poolOSType, "os-type", "linux", "Operating system type (windows, linux, etc).")
repoPoolUpdateCmd.Flags().StringVar(&poolOSArch, "os-arch", "amd64", "Operating system architecture (amd64, arm, etc).")
repoPoolUpdateCmd.Flags().UintVar(&poolMaxRunners, "max-runners", 5, "The maximum number of runner this pool will create.")
repoPoolUpdateCmd.Flags().UintVar(&poolMinIdleRunners, "min-idle-runners", 1, "Attempt to maintain a minimum of idle self-hosted runners of this type.")
repoPoolUpdateCmd.Flags().BoolVar(&poolEnabled, "enabled", false, "Enable this pool.")
repoPoolCmd.AddCommand(
poolListCmd,
poolAddCmd,
poolShowCmd,
poolDeleteCmd,
poolUpdateCmd,
repoPoolAddCmd,
repoPoolShowCmd,
repoPoolDeleteCmd,
repoPoolUpdateCmd,
)
repositoryCmd.AddCommand(repoPoolCmd)
@ -258,7 +258,7 @@ func init() {
func formatPools(pools []params.Pool) {
t := table.NewWriter()
header := table.Row{"ID", "Image", "Flavor", "Tags", "Enabled"}
header := table.Row{"ID", "Image", "Flavor", "Tags", "Belongs to", "Level", "Enabled"}
t.AppendHeader(header)
for _, pool := range pools {
@ -266,7 +266,17 @@ func formatPools(pools []params.Pool) {
for _, tag := range pool.Tags {
tags = append(tags, tag.Name)
}
t.AppendRow(table.Row{pool.ID, pool.Image, pool.Flavor, strings.Join(tags, " "), pool.Enabled})
var belongsTo string
var level string
if pool.RepoID != "" && pool.RepoName != "" {
belongsTo = pool.RepoName
level = "repo"
} else if pool.OrgID != "" && pool.OrgName != "" {
belongsTo = pool.OrgName
level = "org"
}
t.AppendRow(table.Row{pool.ID, pool.Image, pool.Flavor, strings.Join(tags, " "), belongsTo, level, pool.Enabled})
t.AppendSeparator()
}
fmt.Println(t.Render())
@ -283,6 +293,17 @@ func formatOnePool(pool params.Pool) {
tags = append(tags, tag.Name)
}
var belongsTo string
var level string
if pool.RepoID != "" && pool.RepoName != "" {
belongsTo = pool.RepoName
level = "repo"
} else if pool.OrgID != "" && pool.OrgName != "" {
belongsTo = pool.OrgName
level = "org"
}
t.AppendHeader(header)
t.AppendRow(table.Row{"ID", pool.ID})
t.AppendRow(table.Row{"Provider Name", pool.ProviderName})
@ -293,6 +314,8 @@ func formatOnePool(pool params.Pool) {
t.AppendRow(table.Row{"Max Runners", pool.MaxRunners})
t.AppendRow(table.Row{"Min Idle Runners", pool.MinIdleRunners})
t.AppendRow(table.Row{"Tags", strings.Join(tags, ", ")})
t.AppendRow(table.Row{"Belongs to", belongsTo})
t.AppendRow(table.Row{"Level", level})
t.AppendRow(table.Row{"Enabled", pool.Enabled})
if len(pool.Instances) > 0 {

View file

@ -7,14 +7,22 @@ package cmd
import (
"fmt"
"garm/params"
"os"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
)
var (
runnerRepository string
runnerOrganization string
runnerAll bool
)
// runnerCmd represents the runner command
var runnerCmd = &cobra.Command{
Use: "runner",
Aliases: []string{"run"},
SilenceUsage: true,
Short: "List runners in a pool",
Long: `Given a pool ID, of either a repository or an organization,
@ -23,25 +31,63 @@ list all instances.`,
}
var runnerListCmd = &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "List pool runners",
Long: `List all configured pools for a given repository.`,
Use: "list",
Aliases: []string{"ls"},
Short: "List runners",
Long: `List runners of pools, repositories, orgs or all of the above.
This command expects to get either a pool ID as a positional parameter, or it expects
that one of the supported switches be used to fetch runners of --repo, --org or --all
Example:
List runners from one pool:
garm-cli runner list e87e70bd-3d0d-4b25-be9a-86b85e114bcb
List runners from one repo:
garm-cli runner list --repo=05e7eac6-4705-486d-89c9-0170bbb576af
List runners from one org:
garm-cli runner list --org=5493e51f-3170-4ce3-9f05-3fe690fc6ec6
List all runners from all pools belonging to all repos and orgs:
garm-cli runner list --all
`,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if needsInit {
return needsInitError
}
if len(args) == 0 {
return fmt.Errorf("requires a pool ID")
var instances []params.Instance
var err error
switch len(args) {
case 1:
if cmd.Flags().Changed("repo") ||
cmd.Flags().Changed("org") ||
cmd.Flags().Changed("all") {
return fmt.Errorf("specifying a pool ID and any of [all org repo] are mutually exclusive")
}
instances, err = cli.ListPoolInstances(args[0])
case 0:
if cmd.Flags().Changed("repo") {
instances, err = cli.ListRepoInstances(runnerRepository)
} else if cmd.Flags().Changed("org") {
instances, err = cli.ListOrgInstances(runnerOrganization)
} else if cmd.Flags().Changed("all") {
instances, err = cli.ListAllInstances()
} else {
cmd.Help()
os.Exit(0)
}
default:
cmd.Help()
os.Exit(0)
}
if len(args) > 1 {
return fmt.Errorf("too many arguments")
}
instances, err := cli.ListPoolInstances(args[0])
if err != nil {
return err
}
@ -78,6 +124,11 @@ var runnerShowCmd = &cobra.Command{
}
func init() {
runnerListCmd.Flags().StringVarP(&runnerRepository, "repo", "r", "", "List all runners from all pools within this repository.")
runnerListCmd.Flags().StringVarP(&runnerOrganization, "org", "o", "", "List all runners from all pools withing this organization.")
runnerListCmd.Flags().BoolVarP(&runnerAll, "all", "a", false, "List all runners, regardless of org or repo.")
runnerListCmd.MarkFlagsMutuallyExclusive("repo", "org", "all")
runnerCmd.AddCommand(
runnerListCmd,
runnerShowCmd,

View file

@ -28,6 +28,11 @@ type Store interface {
ListRepoPools(ctx context.Context, repoID string) ([]params.Pool, error)
ListOrgPools(ctx context.Context, orgID string) ([]params.Pool, error)
// Probably a bad idea without some king of filter or at least pagination
// TODO: add filter/pagination
ListAllPools(ctx context.Context) ([]params.Pool, error)
GetPoolByID(ctx context.Context, poolID string) (params.Pool, error)
DeletePoolByID(ctx context.Context, poolID string) error
DeleteRepositoryPool(ctx context.Context, repoID, poolID string) error
DeleteOrganizationPool(ctx context.Context, orgID, poolID string) error
@ -42,10 +47,14 @@ type Store interface {
DeleteInstance(ctx context.Context, poolID string, instanceID string) error
UpdateInstance(ctx context.Context, instanceID string, param params.UpdateInstanceParams) (params.Instance, error)
ListInstances(ctx context.Context, poolID string) ([]params.Instance, error)
ListPoolInstances(ctx context.Context, poolID string) ([]params.Instance, error)
ListRepoInstances(ctx context.Context, repoID string) ([]params.Instance, error)
ListOrgInstances(ctx context.Context, orgID string) ([]params.Instance, error)
// Probably a bad idea without some king of filter or at least pagination
// TODO: add filter/pagination
ListAllInstances(ctx context.Context) ([]params.Instance, error)
GetPoolInstanceByName(ctx context.Context, poolID string, instanceName string) (params.Instance, error)
GetInstanceByName(ctx context.Context, instanceName string) (params.Instance, error)
AddInstanceStatusMessage(ctx context.Context, instanceID string, statusMessage string) error

View file

@ -182,7 +182,7 @@ func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceID string, par
return s.sqlToParamsInstance(instance), nil
}
func (s *sqlDatabase) ListInstances(ctx context.Context, poolID string) ([]params.Instance, error) {
func (s *sqlDatabase) ListPoolInstances(ctx context.Context, poolID string) ([]params.Instance, error) {
pool, err := s.getPoolByID(ctx, poolID, "Tags", "Instances")
if err != nil {
return nil, errors.Wrap(err, "fetching pool")
@ -194,3 +194,17 @@ func (s *sqlDatabase) ListInstances(ctx context.Context, poolID string) ([]param
}
return ret, nil
}
func (s *sqlDatabase) ListAllInstances(ctx context.Context) ([]params.Instance, error) {
var instances []Instance
q := s.conn.Model(&Instance{}).Find(&instances)
if q.Error != nil {
return nil, errors.Wrap(q.Error, "fetching instances")
}
ret := make([]params.Instance, len(instances))
for idx, instance := range instances {
ret[idx] = s.sqlToParamsInstance(instance)
}
return ret, nil
}

View file

@ -182,7 +182,7 @@ func (s *sqlDatabase) CreateOrganizationPool(ctx context.Context, orgId string,
}
}
pool, err := s.getPoolByID(ctx, newPool.ID.String(), "Tags")
pool, err := s.getPoolByID(ctx, newPool.ID.String(), "Tags", "Instances", "Organization", "Repository")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
@ -247,7 +247,7 @@ func (s *sqlDatabase) ListOrgInstances(ctx context.Context, orgID string) ([]par
}
func (s *sqlDatabase) UpdateOrganizationPool(ctx context.Context, orgID, poolID string, param params.UpdatePoolParams) (params.Pool, error) {
pool, err := s.getOrgPool(ctx, orgID, poolID, "Tags")
pool, err := s.getOrgPool(ctx, orgID, poolID, "Tags", "Instances", "Organization", "Repository")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}

49
database/sql/pools.go Normal file
View file

@ -0,0 +1,49 @@
package sql
import (
"context"
"garm/params"
"github.com/pkg/errors"
)
func (s *sqlDatabase) ListAllPools(ctx context.Context) ([]params.Pool, error) {
var pools []Pool
q := s.conn.Model(&Pool{}).
Preload("Tags").
Preload("Organization").
Preload("Repository").
Find(&pools)
if q.Error != nil {
return nil, errors.Wrap(q.Error, "fetching all pools")
}
ret := make([]params.Pool, len(pools))
for idx, val := range pools {
ret[idx] = s.sqlToCommonPool(val)
}
return ret, nil
}
func (s *sqlDatabase) GetPoolByID(ctx context.Context, poolID string) (params.Pool, error) {
pool, err := s.getPoolByID(ctx, poolID, "Tags", "Instances", "Organization", "Repository")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool by ID")
}
return s.sqlToCommonPool(pool), nil
}
func (s *sqlDatabase) DeletePoolByID(ctx context.Context, poolID string) error {
pool, err := s.getPoolByID(ctx, poolID)
if err != nil {
return errors.Wrap(err, "fetching pool by ID")
}
if q := s.conn.Unscoped().Delete(&pool); q.Error != nil {
return errors.Wrap(q.Error, "removing pool")
}
return nil
}

View file

@ -190,7 +190,7 @@ func (s *sqlDatabase) CreateRepositoryPool(ctx context.Context, repoId string, p
}
}
pool, err := s.getPoolByID(ctx, newPool.ID.String(), "Tags")
pool, err := s.getPoolByID(ctx, newPool.ID.String(), "Tags", "Instances", "Organization", "Repository")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
@ -256,7 +256,7 @@ func (s *sqlDatabase) ListRepoInstances(ctx context.Context, repoID string) ([]p
}
func (s *sqlDatabase) UpdateRepositoryPool(ctx context.Context, repoID, poolID string, param params.UpdatePoolParams) (params.Pool, error) {
pool, err := s.getRepoPool(ctx, repoID, poolID, "Tags")
pool, err := s.getRepoPool(ctx, repoID, poolID, "Tags", "Instances", "Organization", "Repository")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}

View file

@ -1,9 +1,11 @@
package sql
import (
"fmt"
"garm/params"
"github.com/pkg/errors"
uuid "github.com/satori/go.uuid"
"gorm.io/gorm"
)
@ -73,6 +75,18 @@ func (s *sqlDatabase) sqlToCommonPool(pool Pool) params.Pool {
Instances: make([]params.Instance, len(pool.Instances)),
}
if pool.RepoID != uuid.Nil {
ret.RepoID = pool.RepoID.String()
if pool.Repository.Owner != "" && pool.Repository.Name != "" {
ret.RepoName = fmt.Sprintf("%s/%s", pool.Repository.Owner, pool.Repository.Name)
}
}
if pool.OrgID != uuid.Nil && pool.Organization.Name != "" {
ret.OrgID = pool.OrgID.String()
ret.OrgName = pool.Organization.Name
}
for idx, val := range pool.Tags {
ret.Tags[idx] = s.sqlToCommonTags(*val)
}

2
go.mod
View file

@ -16,7 +16,7 @@ require (
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354
github.com/pkg/errors v0.9.1
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b
github.com/spf13/cobra v1.4.0
github.com/spf13/cobra v1.4.1-0.20220504202302-9e88759b19cd
golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
gopkg.in/natefinch/lumberjack.v2 v2.0.0

2
go.sum
View file

@ -219,6 +219,8 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/cobra v1.4.1-0.20220504202302-9e88759b19cd h1:0Hv1DPpsKWp/xjP1sQRfLDIymRDu79mErd9H9+l0uaE=
github.com/spf13/cobra v1.4.1-0.20220504202302-9e88759b19cd/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

View file

@ -103,6 +103,10 @@ type Pool struct {
Tags []Tag `json:"tags"`
Enabled bool `json:"enabled"`
Instances []Instance `json:"instances"`
RepoID string `json:"repo_id,omitempty"`
RepoName string `json:"repo_name,omitempty"`
OrgID string `json:"org_id,omitempty"`
OrgName string `json:"org_name,omitempty"`
}
type Internal struct {

View file

@ -218,7 +218,7 @@ func (r *Runner) DeleteOrgPool(ctx context.Context, orgID, poolID string) error
return errors.Wrap(err, "fetching pool")
}
instances, err := r.store.ListInstances(ctx, pool.ID)
instances, err := r.store.ListPoolInstances(ctx, pool.ID)
if err != nil {
return errors.Wrap(err, "fetching instances")
}

View file

@ -146,7 +146,7 @@ func (r *basePool) acquireNewInstance(job params.WorkflowJob) error {
}
// TODO: implement count
poolInstances, err := r.store.ListInstances(r.ctx, pool.ID)
poolInstances, err := r.store.ListPoolInstances(r.ctx, pool.ID)
if err != nil {
return errors.Wrap(err, "fetching instances")
}
@ -365,7 +365,7 @@ func (r *basePool) ensureIdleRunnersForOnePool(pool params.Pool) {
log.Printf("pool %s is disabled, skipping", pool.ID)
return
}
existingInstances, err := r.store.ListInstances(r.ctx, pool.ID)
existingInstances, err := r.store.ListPoolInstances(r.ctx, pool.ID)
if err != nil {
log.Printf("failed to ensure minimum idle workers for pool %s: %s", pool.ID, err)
return

83
runner/pools.go Normal file
View file

@ -0,0 +1,83 @@
package runner
import (
"context"
"garm/auth"
runnerErrors "garm/errors"
"garm/params"
"github.com/pkg/errors"
)
func (r *Runner) ListAllPools(ctx context.Context) ([]params.Pool, error) {
if !auth.IsAdmin(ctx) {
return []params.Pool{}, runnerErrors.ErrUnauthorized
}
pools, err := r.store.ListAllPools(ctx)
if err != nil {
return nil, errors.Wrap(err, "fetching pools")
}
return pools, nil
}
func (r *Runner) GetPoolByID(ctx context.Context, poolID string) (params.Pool, error) {
if !auth.IsAdmin(ctx) {
return params.Pool{}, runnerErrors.ErrUnauthorized
}
pool, err := r.store.GetPoolByID(ctx, poolID)
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
return pool, nil
}
func (r *Runner) DeletePoolByID(ctx context.Context, poolID string) error {
if !auth.IsAdmin(ctx) {
return runnerErrors.ErrUnauthorized
}
if err := r.store.DeletePoolByID(ctx, poolID); err != nil {
return errors.Wrap(err, "fetching pool")
}
return nil
}
func (r *Runner) UpdatePoolByID(ctx context.Context, poolID string, param params.UpdatePoolParams) (params.Pool, error) {
if !auth.IsAdmin(ctx) {
return params.Pool{}, runnerErrors.ErrUnauthorized
}
pool, err := r.store.GetPoolByID(ctx, poolID)
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
maxRunners := pool.MaxRunners
minIdleRunners := pool.MinIdleRunners
if param.MaxRunners != nil {
maxRunners = *param.MaxRunners
}
if param.MinIdleRunners != nil {
minIdleRunners = *param.MinIdleRunners
}
if minIdleRunners > maxRunners {
return params.Pool{}, runnerErrors.NewBadRequestError("min_idle_runners cannot be larger than max_runners")
}
var newPool params.Pool
if pool.RepoID != "" {
newPool, err = r.store.UpdateRepositoryPool(ctx, pool.RepoID, poolID, param)
} else if pool.OrgID != "" {
newPool, err = r.store.UpdateOrganizationPool(ctx, pool.OrgID, poolID, param)
}
if err != nil {
return params.Pool{}, errors.Wrap(err, "updating pool")
}
return newPool, nil
}

View file

@ -217,7 +217,7 @@ func (r *Runner) DeleteRepoPool(ctx context.Context, repoID, poolID string) erro
return errors.Wrap(err, "fetching pool")
}
instances, err := r.store.ListInstances(ctx, pool.ID)
instances, err := r.store.ListPoolInstances(ctx, pool.ID)
if err != nil {
return errors.Wrap(err, "fetching instances")
}
@ -254,7 +254,7 @@ func (r *Runner) ListPoolInstances(ctx context.Context, poolID string) ([]params
return nil, runnerErrors.ErrUnauthorized
}
instances, err := r.store.ListInstances(ctx, poolID)
instances, err := r.store.ListPoolInstances(ctx, poolID)
if err != nil {
return []params.Instance{}, errors.Wrap(err, "fetching instances")
}

View file

@ -483,6 +483,18 @@ func (r *Runner) GetInstance(ctx context.Context, instanceName string) (params.I
return instance, nil
}
func (r *Runner) ListAllInstances(ctx context.Context) ([]params.Instance, error) {
if !auth.IsAdmin(ctx) {
return nil, runnerErrors.ErrUnauthorized
}
instances, err := r.store.ListAllInstances(ctx)
if err != nil {
return nil, errors.Wrap(err, "fetcing instances")
}
return instances, nil
}
func (r *Runner) AddInstanceStatusMessage(ctx context.Context, param params.InstanceUpdateMessage) error {
instanceID := auth.InstanceID(ctx)
if instanceID == "" {
@ -493,9 +505,6 @@ func (r *Runner) AddInstanceStatusMessage(ctx context.Context, param params.Inst
return errors.Wrap(err, "adding status update")
}
// if param.Status == providerCommon.RunnerIdle {
// }
updateParams := params.UpdateInstanceParams{
RunnerStatus: param.Status,
}