Add enterprise support to garm-cli
Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
parent
fb344ab2f2
commit
3e3b91ee59
16 changed files with 479 additions and 62 deletions
|
|
@ -158,7 +158,7 @@ func (a *APIController) ListEnterpriseInstancesHandler(w http.ResponseWriter, r
|
|||
return
|
||||
}
|
||||
|
||||
instances, err := a.r.ListOrgInstances(ctx, enterpriseID)
|
||||
instances, err := a.r.ListEnterpriseInstances(ctx, enterpriseID)
|
||||
if err != nil {
|
||||
log.Printf("listing instances: %s", err)
|
||||
handleError(w, err)
|
||||
|
|
|
|||
203
cmd/garm-cli/client/enterprises.go
Normal file
203
cmd/garm-cli/client/enterprises.go
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
// Copyright 2022 Cloudbase Solutions SRL
|
||||
//
|
||||
// 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 client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"garm/params"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (c *Client) ListEnterprises() ([]params.Enterprise, error) {
|
||||
var enterprises []params.Enterprise
|
||||
url := fmt.Sprintf("%s/api/v1/enterprises", c.Config.BaseURL)
|
||||
resp, err := c.client.R().
|
||||
SetResult(&enterprises).
|
||||
Get(url)
|
||||
if err != nil || resp.IsError() {
|
||||
apiErr, decErr := c.decodeAPIError(resp.Body())
|
||||
if decErr != nil {
|
||||
return nil, errors.Wrap(decErr, "sending request")
|
||||
}
|
||||
return nil, fmt.Errorf("error fetching enterprises: %s", apiErr.Details)
|
||||
}
|
||||
return enterprises, nil
|
||||
}
|
||||
|
||||
func (c *Client) CreateEnterprise(param params.CreateEnterpriseParams) (params.Enterprise, error) {
|
||||
var response params.Enterprise
|
||||
url := fmt.Sprintf("%s/api/v1/enterprises", c.Config.BaseURL)
|
||||
|
||||
body, err := json.Marshal(param)
|
||||
if err != nil {
|
||||
return params.Enterprise{}, err
|
||||
}
|
||||
resp, err := c.client.R().
|
||||
SetBody(body).
|
||||
SetResult(&response).
|
||||
Post(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 creating enterprise: %s", apiErr.Details)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetEnterprise(enterpriseID string) (params.Enterprise, error) {
|
||||
var response params.Enterprise
|
||||
url := fmt.Sprintf("%s/api/v1/enterprises/%s", c.Config.BaseURL, enterpriseID)
|
||||
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 fetching enterprise: %s", apiErr.Details)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c *Client) DeleteEnterprise(enterpriseID string) error {
|
||||
url := fmt.Sprintf("%s/api/v1/enterprises/%s", c.Config.BaseURL, enterpriseID)
|
||||
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 fetching removing enterprise: %s", apiErr.Details)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) CreateEnterprisePool(enterpriseID string, param params.CreatePoolParams) (params.Pool, error) {
|
||||
url := fmt.Sprintf("%s/api/v1/enterprises/%s/pools", c.Config.BaseURL, enterpriseID)
|
||||
|
||||
var response params.Pool
|
||||
body, err := json.Marshal(param)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
resp, err := c.client.R().
|
||||
SetBody(body).
|
||||
SetResult(&response).
|
||||
Post(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 creating enterprise pool: %s", apiErr.Details)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c *Client) ListEnterprisePools(enterpriseID string) ([]params.Pool, error) {
|
||||
url := fmt.Sprintf("%s/api/v1/enterprises/%s/pools", c.Config.BaseURL, enterpriseID)
|
||||
|
||||
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 listing enterprise pools: %s", apiErr.Details)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetEnterprisePool(enterpriseID, poolID string) (params.Pool, error) {
|
||||
url := fmt.Sprintf("%s/api/v1/enterprises/%s/pools/%s", c.Config.BaseURL, enterpriseID, 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 fetching enterprise pool: %s", apiErr.Details)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c *Client) DeleteEnterprisePool(enterpriseID, poolID string) error {
|
||||
url := fmt.Sprintf("%s/api/v1/enterprises/%s/pools/%s", c.Config.BaseURL, enterpriseID, 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 enterprise pool: %s", apiErr.Details)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) UpdateEnterprisePool(enterpriseID, poolID string, param params.UpdatePoolParams) (params.Pool, error) {
|
||||
url := fmt.Sprintf("%s/api/v1/enterprises/%s/pools/%s", c.Config.BaseURL, enterpriseID, 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 updating enterprise pool: %s", apiErr.Details)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (c *Client) ListEnterpriseInstances(enterpriseID string) ([]params.Instance, error) {
|
||||
url := fmt.Sprintf("%s/api/v1/enterprises/%s/instances", c.Config.BaseURL, enterpriseID)
|
||||
|
||||
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 listing enterprise instances: %s", apiErr.Details)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ func (c *Client) CreateOrganization(param params.CreateOrgParams) (params.Organi
|
|||
if decErr != nil {
|
||||
return response, errors.Wrap(decErr, "sending request")
|
||||
}
|
||||
return response, fmt.Errorf("error performing login: %s", apiErr.Details)
|
||||
return response, fmt.Errorf("error creating org: %s", apiErr.Details)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
|
@ -72,7 +72,7 @@ func (c *Client) GetOrganization(orgID string) (params.Organization, error) {
|
|||
if decErr != nil {
|
||||
return response, errors.Wrap(decErr, "sending request")
|
||||
}
|
||||
return response, fmt.Errorf("error fetching orgs: %s", apiErr.Details)
|
||||
return response, fmt.Errorf("error fetching org: %s", apiErr.Details)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
|
@ -86,7 +86,7 @@ func (c *Client) DeleteOrganization(orgID string) error {
|
|||
if decErr != nil {
|
||||
return errors.Wrap(decErr, "sending request")
|
||||
}
|
||||
return fmt.Errorf("error fetching orgs: %s", apiErr.Details)
|
||||
return fmt.Errorf("error removing org: %s", apiErr.Details)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
186
cmd/garm-cli/cmd/enterprise.go
Normal file
186
cmd/garm-cli/cmd/enterprise.go
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
// Copyright 2022 Cloudbase Solutions SRL
|
||||
//
|
||||
// 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"
|
||||
"garm/params"
|
||||
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
enterpriseName string
|
||||
enterpriseWebhookSecret string
|
||||
enterpriseCreds string
|
||||
)
|
||||
|
||||
// enterpriseCmd represents the enterprise command
|
||||
var enterpriseCmd = &cobra.Command{
|
||||
Use: "enterprise",
|
||||
Aliases: []string{"ent"},
|
||||
SilenceUsage: true,
|
||||
Short: "Manage enterprise",
|
||||
Long: `Add, remove or update enterprise for which we manage
|
||||
self hosted runners.
|
||||
|
||||
This command allows you to define a new enterprise or manage an existing
|
||||
enterprise for which garm maintains pools of self hosted runners.`,
|
||||
Run: nil,
|
||||
}
|
||||
|
||||
var enterpriseAddCmd = &cobra.Command{
|
||||
Use: "add",
|
||||
Aliases: []string{"create"},
|
||||
Short: "Add enterprise",
|
||||
Long: `Add a new enterprise to the manager.`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if needsInit {
|
||||
return needsInitError
|
||||
}
|
||||
|
||||
newEnterpriseReq := params.CreateEnterpriseParams{
|
||||
Name: enterpriseName,
|
||||
WebhookSecret: enterpriseWebhookSecret,
|
||||
CredentialsName: enterpriseCreds,
|
||||
}
|
||||
enterprise, err := cli.CreateEnterprise(newEnterpriseReq)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
formatOneEnterprise(enterprise)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var enterpriseListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Aliases: []string{"ls"},
|
||||
Short: "List enterprises",
|
||||
Long: `List all configured enterprises that are currently managed.`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if needsInit {
|
||||
return needsInitError
|
||||
}
|
||||
|
||||
enterprises, err := cli.ListEnterprises()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
formatEnterprises(enterprises)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var enterpriseShowCmd = &cobra.Command{
|
||||
Use: "show",
|
||||
Short: "Show details for one enterprise",
|
||||
Long: `Displays detailed information about a single enterprise.`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if needsInit {
|
||||
return needsInitError
|
||||
}
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("requires a enterprise ID")
|
||||
}
|
||||
if len(args) > 1 {
|
||||
return fmt.Errorf("too many arguments")
|
||||
}
|
||||
enterprise, err := cli.GetEnterprise(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
formatOneEnterprise(enterprise)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var enterpriseDeleteCmd = &cobra.Command{
|
||||
Use: "delete",
|
||||
Aliases: []string{"remove", "rm", "del"},
|
||||
Short: "Removes one enterprise",
|
||||
Long: `Delete one enterprise from the manager.`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if needsInit {
|
||||
return needsInitError
|
||||
}
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("requires a enterprise ID")
|
||||
}
|
||||
if len(args) > 1 {
|
||||
return fmt.Errorf("too many arguments")
|
||||
}
|
||||
if err := cli.DeleteEnterprise(args[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
enterpriseAddCmd.Flags().StringVar(&enterpriseName, "name", "", "The name of the enterprise")
|
||||
enterpriseAddCmd.Flags().StringVar(&enterpriseWebhookSecret, "webhook-secret", "", "The webhook secret for this enterprise")
|
||||
enterpriseAddCmd.Flags().StringVar(&enterpriseCreds, "credentials", "", "Credentials name. See credentials list.")
|
||||
enterpriseAddCmd.MarkFlagRequired("credentials")
|
||||
enterpriseAddCmd.MarkFlagRequired("name")
|
||||
|
||||
enterpriseCmd.AddCommand(
|
||||
enterpriseListCmd,
|
||||
enterpriseAddCmd,
|
||||
enterpriseShowCmd,
|
||||
enterpriseDeleteCmd,
|
||||
)
|
||||
|
||||
rootCmd.AddCommand(enterpriseCmd)
|
||||
}
|
||||
|
||||
func formatEnterprises(enterprises []params.Enterprise) {
|
||||
t := table.NewWriter()
|
||||
header := table.Row{"ID", "Name", "Credentials name"}
|
||||
t.AppendHeader(header)
|
||||
for _, val := range enterprises {
|
||||
t.AppendRow(table.Row{val.ID, val.Name, val.CredentialsName})
|
||||
t.AppendSeparator()
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
}
|
||||
|
||||
func formatOneEnterprise(enterprise params.Enterprise) {
|
||||
t := table.NewWriter()
|
||||
rowConfigAutoMerge := table.RowConfig{AutoMerge: true}
|
||||
header := table.Row{"Field", "Value"}
|
||||
t.AppendHeader(header)
|
||||
t.AppendRow(table.Row{"ID", enterprise.ID})
|
||||
t.AppendRow(table.Row{"Name", enterprise.Name})
|
||||
t.AppendRow(table.Row{"Credentials", enterprise.CredentialsName})
|
||||
|
||||
if len(enterprise.Pools) > 0 {
|
||||
for _, pool := range enterprise.Pools {
|
||||
t.AppendRow(table.Row{"Pools", pool.ID}, rowConfigAutoMerge)
|
||||
}
|
||||
}
|
||||
t.SetColumnConfigs([]table.ColumnConfig{
|
||||
{Number: 1, AutoMerge: true},
|
||||
{Number: 2, AutoMerge: true},
|
||||
})
|
||||
|
||||
fmt.Println(t.Render())
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ var organizationCmd = &cobra.Command{
|
|||
self hosted runners.
|
||||
|
||||
This command allows you to define a new organization or manage an existing
|
||||
organization for which the garm maintains pools of self hosted runners.`,
|
||||
organization for which garm maintains pools of self hosted runners.`,
|
||||
Run: nil,
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ var orgListCmd = &cobra.Command{
|
|||
Use: "list",
|
||||
Aliases: []string{"ls"},
|
||||
Short: "List organizations",
|
||||
Long: `List all configured respositories that are currently managed.`,
|
||||
Long: `List all configured organizations that are currently managed.`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if needsInit {
|
||||
|
|
@ -134,29 +134,6 @@ var orgDeleteCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
var orgInstanceListCmd = &cobra.Command{
|
||||
Use: "delete",
|
||||
Aliases: []string{"remove", "rm", "del"},
|
||||
Short: "Removes one organization",
|
||||
Long: `Delete one organization from the manager.`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if needsInit {
|
||||
return needsInitError
|
||||
}
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("requires a organization ID")
|
||||
}
|
||||
if len(args) > 1 {
|
||||
return fmt.Errorf("too many arguments")
|
||||
}
|
||||
if err := cli.DeleteOrganization(args[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
orgAddCmd.Flags().StringVar(&orgName, "name", "", "The name of the organization")
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
var (
|
||||
poolRepository string
|
||||
poolOrganization string
|
||||
poolEnterprise string
|
||||
poolAll bool
|
||||
)
|
||||
|
||||
|
|
@ -57,6 +58,9 @@ Example:
|
|||
List pools from one org:
|
||||
garm-cli pool list --org=5493e51f-3170-4ce3-9f05-3fe690fc6ec6
|
||||
|
||||
List pools from one enterprise:
|
||||
garm-cli pool list --org=a8ee4c66-e762-4cbe-a35d-175dba2c9e62
|
||||
|
||||
List all pools from all repos and orgs:
|
||||
garm-cli pool list --all
|
||||
|
||||
|
|
@ -76,6 +80,8 @@ Example:
|
|||
pools, err = cli.ListRepoPools(poolRepository)
|
||||
} else if cmd.Flags().Changed("org") {
|
||||
pools, err = cli.ListOrgPools(poolOrganization)
|
||||
} else if cmd.Flags().Changed("enterprise") {
|
||||
pools, err = cli.ListEnterprisePools(poolEnterprise)
|
||||
} else if cmd.Flags().Changed("all") {
|
||||
pools, err = cli.ListAllPools()
|
||||
} else {
|
||||
|
|
@ -183,6 +189,8 @@ var poolAddCmd = &cobra.Command{
|
|||
pool, err = cli.CreateRepoPool(poolRepository, newPoolParams)
|
||||
} else if cmd.Flags().Changed("org") {
|
||||
pool, err = cli.CreateOrgPool(poolOrganization, newPoolParams)
|
||||
} else if cmd.Flags().Changed("enterprise") {
|
||||
pool, err = cli.CreateEnterprisePool(poolEnterprise, newPoolParams)
|
||||
} else {
|
||||
cmd.Help()
|
||||
os.Exit(0)
|
||||
|
|
@ -270,8 +278,9 @@ explicitly remove them using the runner delete command.
|
|||
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().StringVarP(&poolEnterprise, "enterprise", "e", "", "List all pools withing this enterprise.")
|
||||
poolListCmd.Flags().BoolVarP(&poolAll, "all", "a", false, "List all pools, regardless of org or repo.")
|
||||
poolListCmd.MarkFlagsMutuallyExclusive("repo", "org", "all")
|
||||
poolListCmd.MarkFlagsMutuallyExclusive("repo", "org", "all", "enterprise")
|
||||
|
||||
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.")
|
||||
|
|
@ -300,7 +309,8 @@ func init() {
|
|||
|
||||
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")
|
||||
poolAddCmd.Flags().StringVarP(&poolEnterprise, "enterprise", "e", "", "Add the new pool withing this enterprise.")
|
||||
poolAddCmd.MarkFlagsMutuallyExclusive("repo", "org", "enterprise")
|
||||
|
||||
poolCmd.AddCommand(
|
||||
poolListCmd,
|
||||
|
|
|
|||
|
|
@ -286,6 +286,9 @@ func formatPools(pools []params.Pool) {
|
|||
} else if pool.OrgID != "" && pool.OrgName != "" {
|
||||
belongsTo = pool.OrgName
|
||||
level = "org"
|
||||
} else if pool.EnterpriseID != "" && pool.EnterpriseName != "" {
|
||||
belongsTo = pool.EnterpriseName
|
||||
level = "enterprise"
|
||||
}
|
||||
t.AppendRow(table.Row{pool.ID, pool.Image, pool.Flavor, strings.Join(tags, " "), belongsTo, level, pool.Enabled})
|
||||
t.AppendSeparator()
|
||||
|
|
@ -313,6 +316,9 @@ func formatOnePool(pool params.Pool) {
|
|||
} else if pool.OrgID != "" && pool.OrgName != "" {
|
||||
belongsTo = pool.OrgName
|
||||
level = "org"
|
||||
} else if pool.EnterpriseID != "" && pool.EnterpriseName != "" {
|
||||
belongsTo = pool.EnterpriseName
|
||||
level = "enterprise"
|
||||
}
|
||||
|
||||
t.AppendHeader(header)
|
||||
|
|
|
|||
|
|
@ -136,29 +136,6 @@ var repoDeleteCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
var repoInstanceListCmd = &cobra.Command{
|
||||
Use: "delete",
|
||||
Aliases: []string{"remove", "rm", "del"},
|
||||
Short: "Removes one repository",
|
||||
Long: `Delete one repository from the manager.`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if needsInit {
|
||||
return needsInitError
|
||||
}
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("requires a repository ID")
|
||||
}
|
||||
if len(args) > 1 {
|
||||
return fmt.Errorf("too many arguments")
|
||||
}
|
||||
if err := cli.DeleteRepository(args[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
repoAddCmd.Flags().StringVar(&repoOwner, "owner", "", "The owner of this repository")
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
var (
|
||||
runnerRepository string
|
||||
runnerOrganization string
|
||||
runnerEnterprise string
|
||||
runnerAll bool
|
||||
forceRemove bool
|
||||
)
|
||||
|
|
@ -61,6 +62,9 @@ Example:
|
|||
List runners from one org:
|
||||
garm-cli runner list --org=5493e51f-3170-4ce3-9f05-3fe690fc6ec6
|
||||
|
||||
List runners from one enterprise:
|
||||
garm-cli runner list --enterprise=a966188b-0e05-4edc-9b82-bc81a1fd38ed
|
||||
|
||||
List all runners from all pools belonging to all repos and orgs:
|
||||
garm-cli runner list --all
|
||||
|
||||
|
|
@ -78,9 +82,10 @@ Example:
|
|||
case 1:
|
||||
if cmd.Flags().Changed("repo") ||
|
||||
cmd.Flags().Changed("org") ||
|
||||
cmd.Flags().Changed("enterprise") ||
|
||||
cmd.Flags().Changed("all") {
|
||||
|
||||
return fmt.Errorf("specifying a pool ID and any of [all org repo] are mutually exclusive")
|
||||
return fmt.Errorf("specifying a pool ID and any of [all org repo enterprise] are mutually exclusive")
|
||||
}
|
||||
instances, err = cli.ListPoolInstances(args[0])
|
||||
case 0:
|
||||
|
|
@ -88,6 +93,8 @@ Example:
|
|||
instances, err = cli.ListRepoInstances(runnerRepository)
|
||||
} else if cmd.Flags().Changed("org") {
|
||||
instances, err = cli.ListOrgInstances(runnerOrganization)
|
||||
} else if cmd.Flags().Changed("enterprise") {
|
||||
instances, err = cli.ListEnterpriseInstances(runnerEnterprise)
|
||||
} else if cmd.Flags().Changed("all") {
|
||||
instances, err = cli.ListAllInstances()
|
||||
} else {
|
||||
|
|
@ -172,8 +179,9 @@ to either cancel the workflow or wait for it to finish.
|
|||
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().StringVarP(&runnerEnterprise, "enterprise", "e", "", "List all runners from all pools withing this enterprise.")
|
||||
runnerListCmd.Flags().BoolVarP(&runnerAll, "all", "a", false, "List all runners, regardless of org or repo.")
|
||||
runnerListCmd.MarkFlagsMutuallyExclusive("repo", "org", "all")
|
||||
runnerListCmd.MarkFlagsMutuallyExclusive("repo", "org", "enterprise", "all")
|
||||
|
||||
runnerDeleteCmd.Flags().BoolVarP(&forceRemove, "force-remove-runner", "f", false, "Confirm you want to delete a runner")
|
||||
runnerDeleteCmd.MarkFlagsMutuallyExclusive("force-remove-runner")
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ func (s *sqlDatabase) FindEnterprisePoolByTags(ctx context.Context, enterpriseID
|
|||
}
|
||||
|
||||
func (s *sqlDatabase) ListEnterprisePools(ctx context.Context, enterpriseID string) ([]params.Pool, error) {
|
||||
pools, err := s.getEnterprisePools(ctx, enterpriseID, "Tags")
|
||||
pools, err := s.getEnterprisePools(ctx, enterpriseID, "Tags", "Enterprise")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching pools")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ func (s *sqlDatabase) ListAllPools(ctx context.Context) ([]params.Pool, error) {
|
|||
Preload("Tags").
|
||||
Preload("Organization").
|
||||
Preload("Repository").
|
||||
Preload("Enterprise").
|
||||
Find(&pools)
|
||||
if q.Error != nil {
|
||||
return nil, errors.Wrap(q.Error, "fetching all pools")
|
||||
|
|
|
|||
|
|
@ -128,6 +128,11 @@ func (s *sqlDatabase) sqlToCommonPool(pool Pool) params.Pool {
|
|||
ret.OrgName = pool.Organization.Name
|
||||
}
|
||||
|
||||
if pool.EnterpriseID != uuid.Nil && pool.Enterprise.Name != "" {
|
||||
ret.EnterpriseID = pool.EnterpriseID.String()
|
||||
ret.EnterpriseName = pool.Enterprise.Name
|
||||
}
|
||||
|
||||
for idx, val := range pool.Tags {
|
||||
ret.Tags[idx] = s.sqlToCommonTags(*val)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,6 +128,8 @@ type Pool struct {
|
|||
RepoName string `json:"repo_name,omitempty"`
|
||||
OrgID string `json:"org_id,omitempty"`
|
||||
OrgName string `json:"org_name,omitempty"`
|
||||
EnterpriseID string `json:"enterprise_id,omitempty"`
|
||||
EnterpriseName string `json:"enterprise_name,omitempty"`
|
||||
RunnerBootstrapTimeout uint `json:"runner_bootstrap_timeout"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ func (r *basePool) loop() {
|
|||
reapTimer := time.NewTicker(common.PoolReapTimeoutInterval)
|
||||
toolUpdateTimer := time.NewTicker(common.PoolToolUpdateInterval)
|
||||
defer func() {
|
||||
log.Printf("repository %s loop exited", r.helper.String())
|
||||
log.Printf("%s loop exited", r.helper.String())
|
||||
consolidateTimer.Stop()
|
||||
reapTimer.Stop()
|
||||
toolUpdateTimer.Stop()
|
||||
|
|
@ -896,6 +896,7 @@ func (r *basePool) ForceDeleteRunner(runner params.Instance) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
log.Printf("setting instance status for: %v", runner.Name)
|
||||
|
||||
if err := r.setInstanceStatus(runner.Name, providerCommon.InstancePendingDelete, nil); err != nil {
|
||||
log.Printf("failed to update runner %s status", runner.Name)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ package runner
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"garm/auth"
|
||||
runnerErrors "garm/errors"
|
||||
|
|
@ -112,6 +113,10 @@ func (r *Runner) UpdatePoolByID(ctx context.Context, poolID string, param params
|
|||
newPool, err = r.store.UpdateRepositoryPool(ctx, pool.RepoID, poolID, param)
|
||||
} else if pool.OrgID != "" {
|
||||
newPool, err = r.store.UpdateOrganizationPool(ctx, pool.OrgID, poolID, param)
|
||||
} else if pool.EnterpriseID != "" {
|
||||
newPool, err = r.store.UpdateEnterprisePool(ctx, pool.EnterpriseID, poolID, param)
|
||||
} else {
|
||||
return params.Pool{}, fmt.Errorf("pool not bound to a repo, org or enterprise")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ func NewRunner(ctx context.Context, cfg config.Config) (*Runner, error) {
|
|||
credentials: creds,
|
||||
repositories: map[string]common.PoolManager{},
|
||||
organizations: map[string]common.PoolManager{},
|
||||
enterprises: map[string]common.PoolManager{},
|
||||
}
|
||||
runner := &Runner{
|
||||
ctx: ctx,
|
||||
|
|
@ -81,7 +82,7 @@ func NewRunner(ctx context.Context, cfg config.Config) (*Runner, error) {
|
|||
credentials: creds,
|
||||
}
|
||||
|
||||
if err := runner.loadReposAndOrgs(); err != nil {
|
||||
if err := runner.loadReposOrgsAndEnterprises(); err != nil {
|
||||
return nil, errors.Wrap(err, "loading pool managers")
|
||||
}
|
||||
|
||||
|
|
@ -293,7 +294,7 @@ func (r *Runner) ListProviders(ctx context.Context) ([]params.Provider, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (r *Runner) loadReposAndOrgs() error {
|
||||
func (r *Runner) loadReposOrgsAndEnterprises() error {
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
|
|
@ -307,7 +308,12 @@ func (r *Runner) loadReposAndOrgs() error {
|
|||
return errors.Wrap(err, "fetching organizations")
|
||||
}
|
||||
|
||||
expectedReplies := len(repos) + len(orgs)
|
||||
enterprises, err := r.store.ListEnterprises(r.ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching enterprises")
|
||||
}
|
||||
|
||||
expectedReplies := len(repos) + len(orgs) + len(enterprises)
|
||||
errChan := make(chan error, expectedReplies)
|
||||
|
||||
for _, repo := range repos {
|
||||
|
|
@ -326,6 +332,14 @@ func (r *Runner) loadReposAndOrgs() error {
|
|||
}(org)
|
||||
}
|
||||
|
||||
for _, enterprise := range enterprises {
|
||||
go func(enterprise params.Enterprise) {
|
||||
log.Printf("creating pool manager for enterprise %s", enterprise.Name)
|
||||
_, err := r.poolManagerCtrl.CreateEnterprisePoolManager(r.ctx, enterprise, r.providers, r.store)
|
||||
errChan <- err
|
||||
}(enterprise)
|
||||
}
|
||||
|
||||
for i := 0; i < expectedReplies; i++ {
|
||||
select {
|
||||
case err := <-errChan:
|
||||
|
|
@ -354,7 +368,12 @@ func (r *Runner) Start() error {
|
|||
return errors.Wrap(err, "fetch org pool managers")
|
||||
}
|
||||
|
||||
expectedReplies := len(repositories) + len(organizations)
|
||||
enterprises, err := r.poolManagerCtrl.GetEnterprisePoolManagers()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetch enterprise pool managers")
|
||||
}
|
||||
|
||||
expectedReplies := len(repositories) + len(organizations) + len(enterprises)
|
||||
errChan := make(chan error, expectedReplies)
|
||||
|
||||
for _, repo := range repositories {
|
||||
|
|
@ -373,6 +392,14 @@ func (r *Runner) Start() error {
|
|||
|
||||
}
|
||||
|
||||
for _, enterprise := range enterprises {
|
||||
go func(org common.PoolManager) {
|
||||
err := org.Start()
|
||||
errChan <- err
|
||||
}(enterprise)
|
||||
|
||||
}
|
||||
|
||||
for i := 0; i < expectedReplies; i++ {
|
||||
select {
|
||||
case err := <-errChan:
|
||||
|
|
@ -688,6 +715,15 @@ func (r *Runner) ForceDeleteRunner(ctx context.Context, instanceName string) err
|
|||
if err != nil {
|
||||
return errors.Wrapf(err, "fetching pool manager for org %s", pool.OrgName)
|
||||
}
|
||||
} else if pool.EnterpriseID != "" {
|
||||
enterprise, err := r.store.GetEnterpriseByID(ctx, pool.EnterpriseID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching enterprise")
|
||||
}
|
||||
poolMgr, err = r.findEnterprisePoolManager(enterprise.Name)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "fetching pool manager for enterprise %s", pool.EnterpriseName)
|
||||
}
|
||||
}
|
||||
|
||||
if err := poolMgr.ForceDeleteRunner(instance); err != nil {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue