This repository has been archived by the owner on Jun 2, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathroot.go
116 lines (95 loc) · 3.22 KB
/
root.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Package gcp presents a filesystem hierarchy for Google Cloud Platform resources.
package gcp
import (
"context"
"fmt"
"net/http"
"time"
"github.com/puppetlabs/wash/activity"
"github.com/puppetlabs/wash/plugin"
"golang.org/x/oauth2/google"
crm "google.golang.org/api/cloudresourcemanager/v1"
"google.golang.org/api/option"
)
// Root of the GCP plugin
type Root struct {
plugin.EntryBase
oauthClient *http.Client
projects map[string]struct{}
}
// serviceScopes lists all scopes used by this module.
var serviceScopes = []string{crm.CloudPlatformScope, computeScope, storageScope}
// Init for root
func (r *Root) Init(cfg map[string]interface{}) error {
r.EntryBase = plugin.NewEntry("gcp")
r.SetTTLOf(plugin.ListOp, 1*time.Minute)
// We use the auto-generated SDK because it's the only one that allows us to list
// projects for the current credentials.
oauthClient, err := google.DefaultClient(context.Background(), serviceScopes...)
r.oauthClient = oauthClient
if projsI, ok := cfg["projects"]; ok {
projs, ok := projsI.([]interface{})
if !ok {
return fmt.Errorf("gcp.projects config must be an array of strings, not %s", projsI)
}
r.projects = make(map[string]struct{})
for _, elem := range projs {
proj, ok := elem.(string)
if !ok {
return fmt.Errorf("gcp.projects config must be an array of strings, not %s", projs)
}
r.projects[proj] = struct{}{}
}
}
return err
}
// ChildSchemas returns the root's child schema
func (r *Root) ChildSchemas() []*plugin.EntrySchema {
return []*plugin.EntrySchema{
(&project{}).Schema(),
}
}
// Schema returns the root's schema
func (r *Root) Schema() *plugin.EntrySchema {
return plugin.NewEntrySchema(r, "gcp").
SetDescription(rootDescription).
IsSingleton()
}
// List the available GCP projects
func (r *Root) List(ctx context.Context) ([]plugin.Entry, error) {
crmService, err := crm.NewService(context.Background(), option.WithHTTPClient(r.oauthClient))
if err != nil {
return nil, err
}
activity.Record(ctx, "Loading projects for %v", crmService.BasePath)
listResponse, err := crmService.Projects.List().Context(ctx).Do()
if err != nil {
return nil, err
}
projects := make([]plugin.Entry, 0, len(listResponse.Projects))
for _, proj := range listResponse.Projects {
if _, ok := r.projects[proj.Name]; len(r.projects) > 0 && !ok {
if _, ok := r.projects[proj.ProjectId]; !ok {
// If a list of enabled projects is provided and both name and project ID are not in it,
// omit this project.
continue
}
}
projects = append(projects, newProject(proj, r.oauthClient))
}
return projects, nil
}
const rootDescription = `
This is the GCP plugin root. It follows https://cloud.google.com/docs/authentication/production
to find your credentials:
* it will try GOOGLE_APPLICATION_CREDENTIALS as a service account file
* otherwise, it will use your credentials in $HOME/.config/gcloud/application_default_credentials.json.
The simplest way to set this up is with
gcloud init
gcloud auth application-default login
The GCP plugin will list all projects you have access to. The projects it lists can be limited
by adding
gcp:
projects: [project-1, project-2]
to Wash’s config file. Project can be referenced either by name or project ID.
`