mirror of
https://github.com/foomo/posh-providers.git
synced 2025-10-16 12:35:41 +00:00
feat: support standard and access token kubeconfigs
This commit is contained in:
parent
ce2ddb5320
commit
76e169ea9b
@ -1,17 +1,96 @@
|
||||
# POSH gcloud provider
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
## Configuration:
|
||||
|
||||
```yaml
|
||||
gcloud:
|
||||
project: myproject-123456
|
||||
configPath: .posh/config/gcloud
|
||||
clusters:
|
||||
environments:
|
||||
- name: prod
|
||||
region: europe-west6
|
||||
- name: stage
|
||||
region: europe-west6
|
||||
project: myproject-123456
|
||||
clusters:
|
||||
- name: default
|
||||
role: admin
|
||||
region: europe-west6
|
||||
```
|
||||
|
||||
Using service account access tokens retrieved by OnePassword:
|
||||
|
||||
```yaml
|
||||
gcloud:
|
||||
configPath: .posh/config/gcloud
|
||||
accessTokenPath: .posh/config/gcloud/access_tokens
|
||||
environments:
|
||||
- name: prod
|
||||
project: myproject-123456
|
||||
clusters:
|
||||
- name: default
|
||||
role: admin
|
||||
region: europe-west6
|
||||
accessToken:
|
||||
field: 1234564dxtuty3vaaxezex4c7ey
|
||||
item: 1234564dxtuty3vaaxezex4c7ey
|
||||
vault: 1234564dxtuty3vaaxezex4c7ey
|
||||
account: foomo
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
func New(l log.Logger) (plugin.Plugin, error) {
|
||||
inst := &Plugin{}
|
||||
|
||||
// ...
|
||||
|
||||
// create provider
|
||||
provider, err := gcloud.New(l, inst.cache)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// add command
|
||||
inst.commands.Add(
|
||||
gcloud.NewCommand(l, provider, inst.kubectl, gcloud.CommandWithOnePassword(inst.op)),
|
||||
)
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Using service account access tokens retrieved by OnePassword:
|
||||
|
||||
```go
|
||||
func New(l log.Logger) (plugin.Plugin, error) {
|
||||
inst := &Plugin{}
|
||||
|
||||
// ...
|
||||
|
||||
// create provider
|
||||
provider, err := gcloud.New(l, inst.cache)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// add command
|
||||
inst.commands.Add(
|
||||
gcloud.NewCommand(l, provider, inst.kubectl, gcloud.CommandWithOnePassword(inst.op)),
|
||||
)
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Ownbrew
|
||||
|
||||
```yaml
|
||||
require:
|
||||
packages:
|
||||
- name: gcloud
|
||||
version: '>=409'
|
||||
command: gcloud --version 2>&1 | grep "Google Cloud SDK" | awk '{print $4}'
|
||||
help: |
|
||||
Please ensure you have 'gcloud' installed in a recent version: %s!
|
||||
|
||||
$ brew update
|
||||
$ brew install google-cloud-sdk
|
||||
```
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
package gcloud
|
||||
|
||||
type Account struct {
|
||||
Role string
|
||||
Environment string
|
||||
Cluster string
|
||||
Path string
|
||||
}
|
||||
@ -1,7 +1,32 @@
|
||||
package gcloud
|
||||
|
||||
import (
|
||||
"github.com/foomo/posh-providers/onepassword"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultRole string = "default"
|
||||
DefaultCluster string = "default"
|
||||
)
|
||||
|
||||
type Cluster struct {
|
||||
Project string `json:"project" yaml:"project"`
|
||||
Region string `json:"region" yaml:"region"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
FullName string `json:"fullName" yaml:"fullName"`
|
||||
Region string `json:"region" yaml:"region"`
|
||||
Role string `json:"role" yaml:"role"`
|
||||
AccessToken *onepassword.Secret `json:"accessToken" yaml:"accessToken"`
|
||||
}
|
||||
|
||||
func (c Cluster) DefaultFullName() string {
|
||||
if c.FullName != "" {
|
||||
return c.FullName
|
||||
}
|
||||
return c.Name
|
||||
}
|
||||
|
||||
func (c Cluster) DefaultRole() string {
|
||||
if c.Role != "" {
|
||||
return c.Role
|
||||
}
|
||||
return DefaultRole
|
||||
}
|
||||
|
||||
@ -3,69 +3,125 @@ package gcloud
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/foomo/posh-providers/kubernets/kubectl"
|
||||
"github.com/foomo/posh-providers/onepassword"
|
||||
"github.com/foomo/posh/pkg/command/tree"
|
||||
env2 "github.com/foomo/posh/pkg/env"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/foomo/posh/pkg/prompt/goprompt"
|
||||
"github.com/foomo/posh/pkg/readline"
|
||||
"github.com/foomo/posh/pkg/shell"
|
||||
"github.com/foomo/posh/pkg/util/files"
|
||||
"github.com/foomo/posh/pkg/util/suggests"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Command struct {
|
||||
l log.Logger
|
||||
gcloud *GCloud
|
||||
kubectl *kubectl.Kubectl
|
||||
commandTree *tree.Root
|
||||
type (
|
||||
Command struct {
|
||||
l log.Logger
|
||||
name string
|
||||
op *onepassword.OnePassword
|
||||
gcloud *GCloud
|
||||
kubectl *kubectl.Kubectl
|
||||
commandTree *tree.Root
|
||||
clusterNameFn ClusterNameFn
|
||||
}
|
||||
ClusterNameFn func(environment Environment, cluster Cluster) string
|
||||
CommandOption func(command *Command)
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Options
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func CommandWithName(v string) CommandOption {
|
||||
return func(o *Command) {
|
||||
o.name = v
|
||||
}
|
||||
}
|
||||
|
||||
func CommandWithOnePassword(v *onepassword.OnePassword) CommandOption {
|
||||
return func(o *Command) {
|
||||
o.op = v
|
||||
}
|
||||
}
|
||||
|
||||
func CommandWithClusterNameFn(v ClusterNameFn) CommandOption {
|
||||
return func(o *Command) {
|
||||
o.clusterNameFn = v
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func NewCommand(l log.Logger, gcloud *GCloud, kubectl *kubectl.Kubectl) *Command {
|
||||
func NewCommand(l log.Logger, gcloud *GCloud, kubectl *kubectl.Kubectl, opts ...CommandOption) *Command {
|
||||
inst := &Command{
|
||||
l: l.Named("gcloud"),
|
||||
name: "gcloud",
|
||||
gcloud: gcloud,
|
||||
kubectl: kubectl,
|
||||
clusterNameFn: func(environment Environment, cluster Cluster) string {
|
||||
ret := environment.Name
|
||||
if cluster.Name != DefaultCluster {
|
||||
ret = ret + "-" + cluster.Name
|
||||
}
|
||||
if cluster.DefaultRole() != DefaultRole {
|
||||
ret = cluster.DefaultRole() + "@" + ret
|
||||
}
|
||||
return ret
|
||||
},
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if opt != nil {
|
||||
opt(inst)
|
||||
}
|
||||
}
|
||||
|
||||
inst.commandTree = &tree.Root{
|
||||
Name: "gcloud",
|
||||
Name: inst.name,
|
||||
Description: "Run google cloud sdk commands",
|
||||
Node: &tree.Node{
|
||||
Execute: inst.execute,
|
||||
},
|
||||
Nodes: tree.Nodes{
|
||||
{
|
||||
Name: "environment",
|
||||
Description: "Environments to access",
|
||||
Values: inst.completeAccounts,
|
||||
Name: "login",
|
||||
Description: "Login to gcloud",
|
||||
Execute: inst.authLogin,
|
||||
},
|
||||
{
|
||||
Name: "docker",
|
||||
Description: "Configure docker access",
|
||||
Execute: inst.authConfigureDocker,
|
||||
},
|
||||
{
|
||||
Name: "kubeconfig",
|
||||
Description: "Retrieve kube config",
|
||||
Nodes: tree.Nodes{
|
||||
{
|
||||
Name: "login",
|
||||
Description: "Login to gcloud",
|
||||
Execute: inst.authLogin,
|
||||
},
|
||||
{
|
||||
Name: "docker",
|
||||
Description: "Configure docker access",
|
||||
Execute: inst.authConfigureDocker,
|
||||
},
|
||||
{
|
||||
Name: "kubeconfig",
|
||||
Description: "Retrieve kube config",
|
||||
Args: tree.Args{
|
||||
Name: "environment",
|
||||
Description: "Name of the environment",
|
||||
Values: func(ctx context.Context, r *readline.Readline) []goprompt.Suggest {
|
||||
return suggests.List(inst.gcloud.cfg.EnvironmentNames())
|
||||
},
|
||||
Nodes: tree.Nodes{
|
||||
{
|
||||
Name: "cluster",
|
||||
Repeat: true,
|
||||
Optional: true,
|
||||
Suggest: inst.completeClusters,
|
||||
Name: "cluster",
|
||||
Description: "Name of the cluster",
|
||||
Values: func(ctx context.Context, r *readline.Readline) []goprompt.Suggest {
|
||||
account, err := inst.gcloud.cfg.Environment(r.Args().At(1))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return suggests.List(account.ClusterNames())
|
||||
},
|
||||
Execute: inst.containerClustersGetCredentials,
|
||||
},
|
||||
},
|
||||
Execute: inst.containerClustersGetCredentials,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -102,9 +158,9 @@ Usage:
|
||||
gcloud [cmd]
|
||||
|
||||
Available commands:
|
||||
login Login into your google cloud account
|
||||
docker Configure docker access
|
||||
kubeconfig <cluster> Retrieve kube config
|
||||
login Login into your google cloud account
|
||||
docker Configure docker access
|
||||
kubeconfig [env] [cluster] Retrieve kube config for the given cluster
|
||||
`
|
||||
}
|
||||
|
||||
@ -121,39 +177,6 @@ func (c *Command) execute(ctx context.Context, r *readline.Readline) error {
|
||||
Run()
|
||||
}
|
||||
|
||||
// Auto-complete clusters based on selected account
|
||||
func (c *Command) completeClusters(ctx context.Context, t *tree.Root, r *readline.Readline) []goprompt.Suggest {
|
||||
var ret []goprompt.Suggest
|
||||
|
||||
account := r.Args().At(0)
|
||||
for _, acc := range c.gcloud.cfg.Environments {
|
||||
if strings.Contains(account, acc.Name) {
|
||||
for _, cluster := range acc.Clusters {
|
||||
ret = append(ret, goprompt.Suggest{Text: cluster.Name})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *Command) completeAccounts(ctx context.Context, r *readline.Readline) []goprompt.Suggest {
|
||||
accounts, err := c.gcloud.ParseAccounts(ctx)
|
||||
if err != nil {
|
||||
c.l.Debug("failed to walk files", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
var suggestions []goprompt.Suggest
|
||||
for _, acc := range accounts {
|
||||
suggestions = append(suggestions, goprompt.Suggest{
|
||||
Text: acc.Environment,
|
||||
Description: fmt.Sprintf("%q cluster with role %q", acc.Cluster, acc.Role),
|
||||
})
|
||||
}
|
||||
return suggestions
|
||||
}
|
||||
|
||||
func (c *Command) authLogin(ctx context.Context, r *readline.Readline) error {
|
||||
if err := shell.New(ctx, c.l, "gcloud", "auth", "login").
|
||||
Args(r.AdditionalArgs()...).
|
||||
@ -173,45 +196,51 @@ func (c *Command) authConfigureDocker(ctx context.Context, r *readline.Readline)
|
||||
}
|
||||
|
||||
func (c *Command) containerClustersGetCredentials(ctx context.Context, r *readline.Readline) error {
|
||||
environment := r.Args().At(0)
|
||||
clusterName := r.Args().At(2)
|
||||
|
||||
clusters := c.gcloud.cfg.ClusterNamesForEnv(environment)
|
||||
if clusterName != "" {
|
||||
clusters = []string{clusterName}
|
||||
var env []string
|
||||
environment, err := c.gcloud.cfg.Environment(r.Args().At(1))
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to retrieve environment for: %s", r.Args().At(1))
|
||||
}
|
||||
|
||||
for _, cluster := range clusters {
|
||||
serviceAccounts, err := c.gcloud.FindAccounts(ctx, environment, cluster)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(serviceAccounts) > 1 {
|
||||
c.l.Warnf("multiple accounts found for env %q and cluster %q", environment, cluster)
|
||||
}
|
||||
accountPath, _ := filepath.Abs(serviceAccounts[0].Path)
|
||||
|
||||
kubectlCluster := c.kubectl.Cluster(environment + "-" + cluster)
|
||||
gcloudCluster, ok := c.gcloud.cfg.FindCluster(environment, cluster)
|
||||
if !ok {
|
||||
return fmt.Errorf("could not find configuration for env %q and cluster %q", environment, cluster)
|
||||
}
|
||||
|
||||
sh := shell.New(ctx, c.l, "gcloud", "container", "clusters", "get-credentials",
|
||||
"--project", gcloudCluster.Project,
|
||||
"--region", gcloudCluster.Region,
|
||||
cluster,
|
||||
).
|
||||
Args(r.AdditionalArgs()...).
|
||||
Env("GOOGLE_APPLICATION_CREDENTIALS=" + accountPath).
|
||||
Env("CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE=" + accountPath).
|
||||
Env("GOOGLE_CREDENTIALS=" + accountPath).
|
||||
Env(kubectlCluster.Env())
|
||||
|
||||
if err := sh.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
cluster, err := environment.Cluster(r.Args().At(2))
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to retrieve cluster for: %s", r.Args().At(2))
|
||||
}
|
||||
return nil
|
||||
|
||||
// resolve or retrieve service account access token
|
||||
accessTokenFilename := path.Join(
|
||||
os.Getenv(env2.ProjectRoot),
|
||||
c.gcloud.cfg.AccessTokenPath,
|
||||
fmt.Sprintf("%s@%s-%s.json", cluster.DefaultRole(), environment.Name, cluster.Name),
|
||||
)
|
||||
if stat, err := os.Stat(accessTokenFilename); err == nil && !stat.IsDir() {
|
||||
c.l.Debug("using existing access token file:", accessTokenFilename)
|
||||
env = c.gcloud.EnvWithAccessToken(env, accessTokenFilename)
|
||||
} else if cluster.AccessToken != nil {
|
||||
if c.op == nil {
|
||||
return errors.New("missing OnePassword provider to retrieve configured access token")
|
||||
}
|
||||
// retrieve token and write to file
|
||||
if value, err := c.op.GetDocument(ctx, *cluster.AccessToken); err != nil {
|
||||
return errors.Wrap(err, "failed to retrieve access token")
|
||||
} else if err := files.MkdirAll(c.gcloud.cfg.AccessTokenPath); err != nil {
|
||||
return errors.Wrap(err, "failed to create access token path")
|
||||
} else if err := os.WriteFile(accessTokenFilename, []byte(value), 0600); err != nil {
|
||||
return errors.Wrap(err, "failed to write access token")
|
||||
}
|
||||
c.l.Debug("retrieved and store access token file:", accessTokenFilename)
|
||||
env = c.gcloud.EnvWithAccessToken(env, accessTokenFilename)
|
||||
}
|
||||
|
||||
kubectlCluster := c.kubectl.Cluster(c.clusterNameFn(environment, cluster))
|
||||
|
||||
return shell.New(ctx, c.l, "gcloud", "container", "clusters", "get-credentials",
|
||||
"--project", environment.Project,
|
||||
"--region", cluster.Region,
|
||||
cluster.DefaultFullName(),
|
||||
).
|
||||
Args(r.AdditionalArgs()...).
|
||||
Env(kubectlCluster.Env()).
|
||||
Env(env...).
|
||||
Run()
|
||||
}
|
||||
|
||||
@ -1,44 +1,36 @@
|
||||
package gcloud
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ConfigDir string `json:"configDir" yaml:"configDir"`
|
||||
Environments []Environment `json:"environments" yaml:"environments"`
|
||||
ConfigPath string `json:"configPath" yaml:"configPath"`
|
||||
AccessTokenPath string `json:"accessTokenPath" yaml:"accessTokenPath"`
|
||||
Environments []Environment `json:"environments" yaml:"environments"`
|
||||
}
|
||||
|
||||
func (c Config) FindCluster(envName, clusterName string) (Cluster, bool) {
|
||||
for _, env := range c.Environments {
|
||||
if env.Name != envName {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, cluster := range env.Clusters {
|
||||
if cluster.Name == clusterName {
|
||||
return cluster, true
|
||||
}
|
||||
func (c Config) Environment(name string) (Environment, error) {
|
||||
for _, environment := range c.Environments {
|
||||
if environment.Name == name {
|
||||
return environment, nil
|
||||
}
|
||||
}
|
||||
return Cluster{}, false
|
||||
return Environment{}, errors.Errorf("given environment not found: %s", name)
|
||||
}
|
||||
|
||||
func (c Config) ClusterNames() []string {
|
||||
var ret []string
|
||||
for _, account := range c.Environments {
|
||||
for _, cluster := range account.Clusters {
|
||||
ret = append(ret, cluster.Name)
|
||||
}
|
||||
func (c Config) EnvironmentNames() []string {
|
||||
ret := make([]string, len(c.Environments))
|
||||
for i, environment := range c.Environments {
|
||||
ret[i] = environment.Name
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c Config) ClusterNamesForEnv(envName string) []string {
|
||||
for _, env := range c.Environments {
|
||||
if env.Name == envName {
|
||||
names := make([]string, len(env.Clusters))
|
||||
for idx, cluster := range env.Clusters {
|
||||
names[idx] = cluster.Name
|
||||
}
|
||||
return names
|
||||
}
|
||||
func (c Config) AllEnvironmentsClusterNames() []string {
|
||||
var ret []string
|
||||
for _, environment := range c.Environments {
|
||||
ret = append(ret, environment.ClusterNames()...)
|
||||
}
|
||||
return nil
|
||||
return ret
|
||||
}
|
||||
|
||||
@ -1,6 +1,28 @@
|
||||
package gcloud
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Environment struct {
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Project string `json:"project" yaml:"project"`
|
||||
Clusters []Cluster `json:"clusters" yaml:"clusters"`
|
||||
}
|
||||
|
||||
func (e Environment) Cluster(name string) (Cluster, error) {
|
||||
for _, cluster := range e.Clusters {
|
||||
if cluster.Name == name {
|
||||
return cluster, nil
|
||||
}
|
||||
}
|
||||
return Cluster{}, errors.Errorf("given cluster not found: %s", name)
|
||||
}
|
||||
|
||||
func (e Environment) ClusterNames() []string {
|
||||
ret := make([]string, len(e.Clusters))
|
||||
for i, cluster := range e.Clusters {
|
||||
ret[i] = cluster.Name
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
package gcloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
|
||||
"github.com/foomo/posh/pkg/shell"
|
||||
"github.com/foomo/posh/pkg/env"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/foomo/posh/pkg/cache"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/foomo/posh/pkg/util/files"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
@ -71,8 +71,14 @@ func New(l log.Logger, cache cache.Cache, opts ...Option) (*GCloud, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err := files.MkdirAll(inst.cfg.ConfigDir); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to create directory %q", inst.cfg.ConfigDir)
|
||||
// ensure config path
|
||||
if err := files.MkdirAll(inst.cfg.ConfigPath); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to create directory %q", inst.cfg.ConfigPath)
|
||||
}
|
||||
|
||||
// set config path to encapsuplte any mishaps global gcloud usage!
|
||||
if err := os.Setenv("CLOUDSDK_CONFIG", path.Join(os.Getenv(env.ProjectRoot), inst.cfg.ConfigPath)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return inst, nil
|
||||
@ -82,68 +88,10 @@ func New(l log.Logger, cache cache.Cache, opts ...Option) (*GCloud, error) {
|
||||
// ~ Public methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (gc *GCloud) ParseAccounts(ctx context.Context) ([]Account, error) {
|
||||
accountFiles, err := files.Find(ctx, gc.cfg.ConfigDir, "*.json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var accounts []Account
|
||||
for _, f := range accountFiles {
|
||||
matchString := gc.accountFileNameRegex.FindAllStringSubmatch(filepath.Base(f), 1)
|
||||
if len(matchString) == 0 {
|
||||
continue
|
||||
}
|
||||
match := matchString[0]
|
||||
acc := Account{
|
||||
Role: match[1],
|
||||
Environment: match[2],
|
||||
Cluster: match[3],
|
||||
Path: f,
|
||||
}
|
||||
accounts = append(accounts, acc)
|
||||
}
|
||||
|
||||
return accounts, err
|
||||
}
|
||||
|
||||
func (gc *GCloud) FindAccounts(ctx context.Context, env, cluster string) ([]Account, error) {
|
||||
accounts, err := gc.ParseAccounts(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filtered := accounts[:0]
|
||||
for _, acc := range accounts {
|
||||
if acc.Environment == env && acc.Cluster == cluster {
|
||||
filtered = append(filtered, acc)
|
||||
}
|
||||
}
|
||||
|
||||
if len(filtered) == 0 {
|
||||
return nil, fmt.Errorf("account not found for cluster %q and env %q", cluster, env)
|
||||
}
|
||||
|
||||
return filtered, nil
|
||||
}
|
||||
|
||||
func (gc *GCloud) GenerateToken(ctx context.Context, env, cluster string) (string, error) {
|
||||
accounts, err := gc.FindAccounts(ctx, env, cluster)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(accounts) > 1 {
|
||||
gc.l.Warnf("multiple accounts found for env %q and cluster %q", env, cluster)
|
||||
}
|
||||
account := accounts[0]
|
||||
|
||||
out, err := shell.New(ctx, gc.l,
|
||||
"gcloud", "auth", "application-default", "print-access-token").
|
||||
Env("CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE=" + account.Path).
|
||||
Env("GOOGLE_APPLICATION_CREDENTIALS=" + account.Path).
|
||||
Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(out), nil
|
||||
func (p *GCloud) EnvWithAccessToken(env []string, accessTokenFilename string) []string {
|
||||
return append(env,
|
||||
fmt.Sprintf("GOOGLE_CREDENTIALS=%s", accessTokenFilename),
|
||||
fmt.Sprintf("GOOGLE_APPLICATION_CREDENTIALS=%s", accessTokenFilename),
|
||||
fmt.Sprintf("CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE=%s", accessTokenFilename),
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
package gcloud_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/foomo/posh-providers/google/gcloud"
|
||||
"github.com/foomo/posh/pkg/cache"
|
||||
"github.com/foomo/posh/pkg/log"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGCloud_ParseAccounts(t *testing.T) {
|
||||
l := log.NewTest(t)
|
||||
c := &cache.MemoryCache{}
|
||||
inst, err := gcloud.New(l, c, gcloud.WithConfig(
|
||||
&gcloud.Config{
|
||||
ConfigDir: "testdata/accounts",
|
||||
Environments: nil,
|
||||
},
|
||||
))
|
||||
require.NoError(t, err)
|
||||
|
||||
accounts, err := inst.ParseAccounts(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Len(t, accounts, 1)
|
||||
|
||||
assert.Equal(t, "testdata/accounts/admin@prod-default.json", accounts[0].Path)
|
||||
assert.Equal(t, "admin", accounts[0].Role)
|
||||
assert.Equal(t, "prod", accounts[0].Environment)
|
||||
assert.Equal(t, "default", accounts[0].Cluster)
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
chore
|
||||
Loading…
Reference in New Issue
Block a user