Skip to content

Commit

Permalink
config file option completed
Browse files Browse the repository at this point in the history
  • Loading branch information
junaid committed Jun 18, 2020
0 parents commit cdfd37c
Show file tree
Hide file tree
Showing 14 changed files with 1,258 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin/
.idea/
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
### Intro
A simple tool to list all the vm instances run in a cloud account.
Supported clouds are AWS, Azure, GCP and DigitalOcean.


### Build

`go build -o bin/cloud-mon main.go`


### Config file

See `scratch/sample-conf.json` for sample config file.
Fill the necessary details in the config file.
Provide config file path with -c parameter.

`bin/cloud-mon -c /path/to/file.json`

If you want to exclude any cloud, remove it from config file.
142 changes: 142 additions & 0 deletions cloudman/aws.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package cloudman

import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"log"
)

type AWSCloud struct {
credentials AWSCredentials
session *session.Session
}

func NewAWSCloud(c AWSCredentials) *AWSCloud {

creds := credentials.NewStaticCredentials(c.AccessKey, c.AccessSecret, "")

sess, err := session.NewSession(&aws.Config{
Credentials: creds,
})
if err != nil {
log.Println(err)
}
out := AWSCloud{
credentials: c,
session: sess,
}

return &out

}

type AWSCredentials struct {
AccessKey string
AccessSecret string
}

func (c *AWSCloud) GetInstanceListAllRegions() ([]InstanceListResponse, error) {

rList := []string{
"ca-central-1",
"eu-central-1",
"eu-west-1",
"eu-west-2",
"eu-south-1",
"eu-west-3",
"eu-north-1",
"me-south-1",
"sa-east-1",
"ap-northeast-3",
"ap-northeast-2",
"ap-southeast-1",
"ap-southeast-2",
"ap-northeast-1",
"us-east-2",
"us-east-1",
"us-west-1",
"us-west-2",
"af-south-1",
"ap-east-1",
"ap-south-1",
}

var out []InstanceListResponse

recvChan := make(chan []InstanceListResponse, len(rList))

for _, region := range rList {
go func(reg string) {
res, _ := c.GetInstanceList(reg)
recvChan <- res
}(region)
}

for j := 0; j < len(rList); j++ {
list := <-recvChan
out = append(out, list...)
}

return out, nil
}

func (c *AWSCloud) GetInstanceList(region string) ([]InstanceListResponse, error) {

sess := c.session.Copy(&aws.Config{
Region: aws.String(region),
})
client := ec2.New(sess)

input := &ec2.DescribeInstancesInput{}

result, err := client.DescribeInstances(input)
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
switch aerr.Code() {
default:
log.Println(aerr.Error())
}
} else {
// Print the error, cast err to awserr.Error to get the Code and
// Message from an error.
log.Println(err.Error())
}
return nil, err
}

var out []InstanceListResponse
for _, res := range result.Reservations {
for _, ins := range res.Instances {
name := c.getInstanceName(ins.Tags)
obj := InstanceListResponse{
Name: name,
Id: *ins.InstanceId,
Status: *ins.State.Name,
LaunchDate: ins.LaunchTime.String(),
Region: region,
MachineType: *ins.InstanceType,
}
out = append(out, obj)
}

}

return out, nil
}

func (c *AWSCloud) getInstanceName(t []*ec2.Tag) string {
name := ""
for _, tag := range t {
if *tag.Key == "Name" {
name = *tag.Value
}
}
return name
}

func (c *AWSCloud) GetInstanceDetails() {

}
91 changes: 91 additions & 0 deletions cloudman/azure.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package cloudman

import (
"context"
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-04-01/compute"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/adal"
"github.com/Azure/go-autorest/autorest/azure"
"log"
)

type AzureCloud struct {
credentials AzureCredentials
authorizer *autorest.BearerAuthorizer
}

func NewAzureCloud(c AzureCredentials) *AzureCloud {

oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, c.Tenant)
if err != nil {
log.Println(err)
}

spt, err := adal.NewServicePrincipalToken(*oauthConfig, c.ID, c.Key, azure.PublicCloud.ResourceManagerEndpoint)
if err != nil {
log.Println(err)
}

authorizer := autorest.NewBearerAuthorizer(spt)

out := AzureCloud{
credentials: c,
authorizer: authorizer,
}

return &out

}

type AzureCredentials struct {
ID string
Key string
Tenant string
Subscription string
}

func (c *AzureCloud) GetInstanceListAllRegions() ([]InstanceListResponse, error) {

out, err := c.GetInstanceList("")

return out, err
}

func (c *AzureCloud) GetInstanceList(project string) ([]InstanceListResponse, error) {

vmClient := compute.NewVirtualMachinesClient(c.credentials.Subscription)
vmClient.Authorizer = c.authorizer

res, err := vmClient.List(context.Background(), "application-0jkqy6")
if err != nil {
log.Println(err)
return nil, err
}
vmList := res.Values()

for err := res.NextWithContext(context.Background()); err != nil; {
log.Println(err)
vmList = append(res.Values())
}

var out []InstanceListResponse
for _, vm := range vmList {
//log.Println(*vm.Name)

obj := InstanceListResponse{
Name: *vm.Name,
Id: *vm.ID,
Status: *vm.ProvisioningState,
LaunchDate: "",
Region: *vm.Location,
MachineType: string(vm.HardwareProfile.VMSize),
}
out = append(out, obj)
}

return out, nil
}

func (c *AzureCloud) GetInstanceDetails() {

}
18 changes: 18 additions & 0 deletions cloudman/cloud.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package cloudman

type Cloud interface {
//SetClientCredentials()
GetInstanceListAllRegions() ([]InstanceListResponse, error)
GetInstanceList(region string) ([]InstanceListResponse, error)
GetInstanceDetails()
}

type InstanceListResponse struct {
Name string
Id string
Status string
LaunchDate string
Region string
MachineType string
Project string
}
100 changes: 100 additions & 0 deletions cloudman/do.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package cloudman

import (
"context"
"github.com/digitalocean/godo"
"golang.org/x/oauth2"
"strconv"
"strings"
)

type DOCloud struct {
credentials DOCredentials
client *godo.Client
}

// first login using gcloud cli
// use autogenerated credentials from cli to authenicate as acount level
type TokenSource struct {
AccessToken string
}

func (t *TokenSource) Token() (*oauth2.Token, error) {
token := &oauth2.Token{
AccessToken: t.AccessToken,
}
return token, nil
}
func NewDOCloud(c DOCredentials) *DOCloud {

tokenSource := &TokenSource{
AccessToken: c.AccessToken,
}

oauthClient := oauth2.NewClient(context.Background(), tokenSource)
client := godo.NewClient(oauthClient)

out := DOCloud{
credentials: c,
client: client,
}

return &out

}

type DOCredentials struct {
AccessToken string
}

func (c *DOCloud) GetInstanceListAllRegions() ([]InstanceListResponse, error) {

out, err := c.GetInstanceList("")
return out, err
}

func (c *DOCloud) GetInstanceList(project string) ([]InstanceListResponse, error) {

droplets, _, err := c.client.Droplets.List(context.Background(), &godo.ListOptions{
Page: 0,
PerPage: 100,
})

if err != nil {
return nil, err
}

var res []InstanceListResponse

for _, droplet := range droplets {

obj := InstanceListResponse{
Name: droplet.Name,
Id: strconv.Itoa(int(droplet.ID)),
Status: droplet.Status,
LaunchDate: droplet.Created,
Region: droplet.Region.Name,
MachineType: droplet.Size.Slug,
Project: "",
}
res = append(res, obj)
}

return res, nil
}

// split and extract last part or uri
// e.g https://www.googleapis.com/compute/v1/projects/cloudplex-infrastructure/zones/us-central1-b
func (c *DOCloud) extract(in string) string {

out := strings.Split(in, "/")
if len(out) > 0 {
return out[len(out)-1]
} else {
return in
}
}

func (c *DOCloud) GetInstanceDetails() {

}
Loading

0 comments on commit cdfd37c

Please sign in to comment.