Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 126 additions & 7 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,16 @@ type configRoot struct {

// cache
type cache struct {
CacheDir string
Instances []*compute.Instance
Projects []*cloudresourcemanager.Project
CacheDir string
Instances []*compute.Instance
InstanceGroups []*instanceGroupExt
Projects []*cloudresourcemanager.Project
}

type instanceGroupExt struct {
InstanceGroup *compute.InstanceGroup
Project *cloudresourcemanager.Project
Members []*compute.InstanceWithNamedPorts
}

func loadCache() (*cache, error) {
Expand Down Expand Up @@ -124,6 +131,16 @@ func loadCache() (*cache, error) {
return nil, err
}
}
if fileinfo.Name() == "instance-groups.json" {
instanceGroupsJSON, err := ioutil.ReadFile(filepath.Join(c.CacheDir, fileinfo.Name()))
if err != nil {
return nil, err
}
err = json.Unmarshal(instanceGroupsJSON, &c.InstanceGroups)
if err != nil {
return nil, err
}
}
}

return &c, nil
Expand All @@ -140,6 +157,11 @@ func saveCache(c *cache) error {
if err != nil {
return err
}
instanceGroupsJSON, _ := json.Marshal(c.InstanceGroups)
err = ioutil.WriteFile(filepath.Join(c.CacheDir, "instance-groups.json"), instanceGroupsJSON, 0600)
if err != nil {
return err
}
return nil
}

Expand All @@ -166,6 +188,7 @@ func doCache(cliCtx *cli.Context) {
}
c.Projects = []*cloudresourcemanager.Project{}
c.Instances = []*compute.Instance{}
c.InstanceGroups = []*instanceGroupExt{}

ctx := oauth2.NoContext
scopes := []string{compute.ComputeReadonlyScope}
Expand Down Expand Up @@ -201,9 +224,9 @@ func doCache(cliCtx *cli.Context) {
log.Printf("loaded projects, %d projects found.\n", len(c.Projects))

semaphore := make(chan int, maxParallelAPICalls)
notify := make(chan []*compute.Instance)

// gcloud compute instances list (in parallel)
instancesNotify := make(chan []*compute.Instance)
for _, project := range c.Projects {
go func(project *cloudresourcemanager.Project, notify chan<- []*compute.Instance) {
semaphore <- 0
Expand All @@ -219,7 +242,6 @@ func doCache(cliCtx *cli.Context) {
}

aggregatedListCall := service.Instances.AggregatedList(project.ProjectId)
// aggregated_list_call.MaxResults(10)
for {
res, err := aggregatedListCall.Do()

Expand All @@ -246,15 +268,112 @@ func doCache(cliCtx *cli.Context) {
notify <- instances

log.Printf("loaded instances in %s (%s), %d instances found.\n", project.Name, project.ProjectId, len(instances))
}(project, notify)
}(project, instancesNotify)
}
for _ = range c.Projects {
instances, _ := <-notify
instances, _ := <-instancesNotify
if instances != nil {
c.Instances = append(c.Instances, instances...)
}
}

// gcloud compute instance-groups list (in parallel)
instanceGroupNotify := make(chan []*instanceGroupExt)
for _, project := range c.Projects {
go func(project *cloudresourcemanager.Project, notify chan<- []*instanceGroupExt) {
semaphore <- 0
var ret []*instanceGroupExt

log.Printf("loading instance groups in %s (%s)...\n", project.Name, project.ProjectId)
service, err := compute.New(client)
if err != nil {
log.Printf("error on loading instance groups in %s (%s), ignored: %s\n", project.Name, project.ProjectId, err)
notify <- nil
<-semaphore
return
}

aggregatedListCall := service.InstanceGroups.AggregatedList(project.ProjectId)
for {
res, err := aggregatedListCall.Do()

if err != nil {
log.Printf("error on loading instance groups in %s (%s), ignored: %s\n", project.Name, project.ProjectId, err)
notify <- nil
<-semaphore
return
}

for _, instanceGroupsScopedList := range res.Items {
for _, instanceGroup := range instanceGroupsScopedList.InstanceGroups {
ret = append(ret, &instanceGroupExt{
InstanceGroup: instanceGroup,
Project: project,
})
}
}

if res.NextPageToken != "" {
log.Printf("loading more instance groups with nextPageToken in %s (%s) ...", project.Name, project.ProjectId)
aggregatedListCall.PageToken(res.NextPageToken)
} else {
break
}
}

<-semaphore
notify <- ret

log.Printf("loaded instance groups in %s (%s), %d instances found.\n", project.Name, project.ProjectId, len(ret))
}(project, instanceGroupNotify)
}
for _ = range c.Projects {
instanceGroups, _ := <-instanceGroupNotify
if instanceGroups != nil {
c.InstanceGroups = append(c.InstanceGroups, instanceGroups...)
}
}

// gcloud compute instance-groups list-instances
// TODO: error check / handling, log message, parallel api call
for _, instanceGroupExt := range c.InstanceGroups {
instanceGroup := instanceGroupExt.InstanceGroup
project := instanceGroupExt.Project

service, err := compute.New(client)

if err != nil {
log.Printf("Error: %s", err.Error())
return
}

zone := (func(a []string) string { return a[len(a)-1] })(strings.Split(instanceGroup.Zone, "/"))

log.Printf("Loading instanceGroups.ListInstances with project=%s, zone=%s, name=%s\n",
project.ProjectId, zone, instanceGroup.Name)
listInstancesCall := service.InstanceGroups.ListInstances(project.ProjectId, zone, instanceGroup.Name, nil)

for {
res, err := listInstancesCall.Do()

if err != nil {
log.Printf("Error: %s", err.Error())
break
}

for _, v := range res.Items {
instanceGroupExt.Members = append(instanceGroupExt.Members, v)
}

if res.NextPageToken != "" {
log.Printf("Loading more instances with nextPageToken")
listInstancesCall.PageToken(res.NextPageToken)
} else {
break
}
}
}

// sort projects, instances
sort.Slice(c.Projects, func(i, j int) bool {
return c.Projects[i].ProjectId < c.Projects[j].ProjectId
Expand Down
2 changes: 1 addition & 1 deletion version.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package main

const version string = "2.0.8"
const version string = "2.1.0dev"