From 8626af267488dd4ed7302e8eade6d6c2c57f94e2 Mon Sep 17 00:00:00 2001 From: marshyski Date: Tue, 26 Feb 2019 17:03:16 -0500 Subject: [PATCH] First commit --- .gitignore | 31 +++++++++++++++++++ README.md | 19 ++++++++++++ aws.go | 13 ++++++++ azure.go | 14 +++++++++ detect.go | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ digitalocean.go | 14 +++++++++ gce.go | 23 ++++++++++++++ openstack.go | 21 +++++++++++++ softlayer.go | 15 ++++++++++ vultr.go | 14 +++++++++ 10 files changed, 243 insertions(+) create mode 100644 .gitignore create mode 100644 aws.go create mode 100644 azure.go create mode 100644 detect.go create mode 100644 digitalocean.go create mode 100644 gce.go create mode 100644 openstack.go create mode 100644 softlayer.go create mode 100644 vultr.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2e31a8b --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +Gopkg.lock +*.log +# vendor/ + +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Ignore vendor dir and glide stuff +*.lock +#vendor/ + +# ignore binary (oops) +fit-client + +.firstrun +client.key +modules/ +*.log +middleware/ + +detectcloud \ No newline at end of file diff --git a/README.md b/README.md index 6881389..0ee86c7 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,21 @@ # detectcloud +http.Client timeout is set to `120ms`. Sometimes hitting the metadata service to fast will return unknown instead of the cloud provider detected. + + package main + + import ( + "fmt" + "gitlab.com/taskfitio/lib/detectcloud" + ) + + func main() { + + // detectcloud.Detect() will return a string + // Amazon Web Services, Microsoft Azure, Digital Ocean + // Google Compute Engine, OpenStack, SoftLayer, Vultr + // unknown + + fmt.Println(detectcloud.Detect()) + + } diff --git a/aws.go b/aws.go new file mode 100644 index 0000000..0183df4 --- /dev/null +++ b/aws.go @@ -0,0 +1,13 @@ +package detectcloud + +import ( + "net/http" +) + +func detectAWS() string { + resp, err := hc.Get("http://169.254.169.254/latest/") + if err == nil && resp.StatusCode == http.StatusOK { + return "Amazon Web Services" + } + return "" +} diff --git a/azure.go b/azure.go new file mode 100644 index 0000000..c5c2ced --- /dev/null +++ b/azure.go @@ -0,0 +1,14 @@ +package detectcloud + +import ( + "net/http" +) + +// https://azure.microsoft.com/en-us/blog/what-just-happened-to-my-vm-in-vm-metadata-service/ +func detectAzure() string { + resp, err := hc.Get("http://169.254.169.254/metadata/v1/InstanceInfo") + if err == nil && resp.StatusCode == http.StatusOK { + return "Microsoft Azure" + } + return "" +} diff --git a/detect.go b/detect.go new file mode 100644 index 0000000..fd05c41 --- /dev/null +++ b/detect.go @@ -0,0 +1,79 @@ +package detectcloud + +import ( + "net/http" + "runtime" + "sync" + "time" +) + +var hc = &http.Client{Timeout: 120 * time.Millisecond} + +type Clouds struct { + Aws string + Azure string + Do string + Gce string + Ost string + Sl string + Vr string +} + +func Detect() string { + if runtime.GOOS != "darwin" { + var c Clouds + var wg sync.WaitGroup + wg.Add(7) + go func() { + defer wg.Done() + c.Aws = detectAWS() + }() + go func() { + defer wg.Done() + c.Azure = detectAzure() + }() + go func() { + defer wg.Done() + c.Do = detectDigitalOcean() + }() + go func() { + defer wg.Done() + c.Gce = detectGCE() + }() + go func() { + defer wg.Done() + c.Ost = detectOpenStack() + }() + go func() { + defer wg.Done() + c.Sl = detectSoftlayer() + }() + go func() { + defer wg.Done() + c.Vr = detectVultr() + }() + wg.Wait() + if c.Aws != "" { + return c.Aws + } + if c.Azure != "" { + return c.Azure + } + if c.Do != "" { + return c.Do + } + if c.Gce != "" { + return c.Gce + } + if c.Ost != "" { + return c.Ost + } + if c.Sl != "" { + return c.Sl + } + if c.Vr != "" { + return c.Vr + } + } + return "unknown" +} diff --git a/digitalocean.go b/digitalocean.go new file mode 100644 index 0000000..d06946c --- /dev/null +++ b/digitalocean.go @@ -0,0 +1,14 @@ +package detectcloud + +import ( + "net/http" +) + +// https://developers.digitalocean.com/documentation/metadata/#metadata-in-json +func detectDigitalOcean() string { + resp, err := hc.Get("http://169.254.169.254/metadata/v1.json") + if err == nil && resp.StatusCode == http.StatusOK { + return "Digital Ocean" + } + return "" +} diff --git a/gce.go b/gce.go new file mode 100644 index 0000000..2e3f599 --- /dev/null +++ b/gce.go @@ -0,0 +1,23 @@ +package detectcloud + +import ( + "net/http" +) + +// https://cloud.google.com/compute/docs/storing-retrieving-metadata#endpoints +// curl "http://metadata.google.internal/computeMetadata/v1/instance/tags" -H "Metadata-Flavor: Google" +func detectGCE() string { + r, err := http.NewRequest("GET", "http://metadata.google.internal/computeMetadata/v1/instance/tags", nil) + if err != nil { + return "" + } + r.Header.Add("Metadata-Flavor", "Google") + resp, err := hc.Do(r) + if err != nil { + return "" + } + if resp.StatusCode == http.StatusOK { + return "Google Compute Engine" + } + return "" +} diff --git a/openstack.go b/openstack.go new file mode 100644 index 0000000..18cd847 --- /dev/null +++ b/openstack.go @@ -0,0 +1,21 @@ +package detectcloud + +import ( + "io/ioutil" + "runtime" + "strings" +) + +func detectOpenStack() string { + if runtime.GOOS != "windows" { + data, err := ioutil.ReadFile("/sys/class/dmi/id/sys_vendor") + if err != nil { + return "" + } + if strings.Contains(string(data), "OpenStack Foundation") { + return "OpenStack" + } + return "" + } + return "" +} diff --git a/softlayer.go b/softlayer.go new file mode 100644 index 0000000..ec22ef4 --- /dev/null +++ b/softlayer.go @@ -0,0 +1,15 @@ +package detectcloud + +import ( + "net/http" +) + +// https://sldn.softlayer.com/blog/jarteche/getting-started-user-data-and-post-provisioning-scripts +// https://github.com/bodenr/cci/wiki/SL-user-metadata +func detectSoftlayer() string { + resp, err := hc.Get("https://api.service.softlayer.com/rest/v3/SoftLayer_Resource_Metadata/UserMetadata.txt") + if err == nil && (resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound) { + return "SoftLayer" + } + return "" +} diff --git a/vultr.go b/vultr.go new file mode 100644 index 0000000..89a5d44 --- /dev/null +++ b/vultr.go @@ -0,0 +1,14 @@ +package detectcloud + +import ( + "net/http" +) + +// https://www.vultr.com/metadata/ +func detectVultr() string { + resp, err := hc.Get("http://169.254.169.254/v1.json") + if err == nil && resp.StatusCode == http.StatusOK { + return "Vultr" + } + return "" +}