mirror of
https://github.com/adammck/terraform-inventory
synced 2024-11-22 20:01:58 +01:00
Add Digital Ocean support
This commit is contained in:
parent
ce6f474f0f
commit
bde4ea23d1
@ -41,6 +41,11 @@ It's just a Go app, so the usual:
|
||||
cd $GOPATH/adammck/terraform-inventory
|
||||
go build
|
||||
|
||||
To test against an example statefile, run:
|
||||
|
||||
terraform-inventory --list fixtures/example.tfstate
|
||||
terraform-inventory --host=web-aws fixtures/example.tfstate
|
||||
|
||||
To update the fixtures, populate `fixtures/secrets.tfvars` with your DO and AWS
|
||||
account details, and run `fixtures/update`. You probably don't need to do this.
|
||||
|
||||
|
10
cli.go
10
cli.go
@ -11,17 +11,17 @@ func cmdList(stdout io.Writer, stderr io.Writer, s *state) int {
|
||||
|
||||
// add each instance as a pseudo-group, so they can be provisioned
|
||||
// individually where necessary.
|
||||
for name, inst := range s.instances() {
|
||||
groups[name] = []string{inst.Attributes["private_ip"]}
|
||||
for name, res := range s.resources() {
|
||||
groups[name] = []string{res.Address()}
|
||||
}
|
||||
|
||||
return output(stdout, stderr, groups)
|
||||
}
|
||||
|
||||
func cmdHost(stdout io.Writer, stderr io.Writer, s *state, hostname string) int {
|
||||
for _, inst := range s.instances() {
|
||||
if hostname == inst.Attributes["private_ip"] {
|
||||
return output(stdout, stderr, inst.Attributes)
|
||||
for name, res := range s.resources() {
|
||||
if hostname == name {
|
||||
return output(stdout, stderr, res.Attributes())
|
||||
}
|
||||
}
|
||||
|
||||
|
2
main.go
2
main.go
@ -23,7 +23,7 @@ func main() {
|
||||
env.MustProcess(cfg)
|
||||
|
||||
if *version == true {
|
||||
fmt.Printf("%s version %d\n", os.Args[0], versionInfo())
|
||||
fmt.Printf("%s version %s\n", os.Args[0], versionInfo())
|
||||
return
|
||||
}
|
||||
|
||||
|
41
parser.go
41
parser.go
@ -4,7 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type state struct {
|
||||
@ -29,16 +29,17 @@ func (s *state) read(stateFile io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// hosts returns a map of name to instanceState, for each of the aws_instance
|
||||
// resources found in the statefile.
|
||||
func (s *state) instances() map[string]instanceState {
|
||||
inst := make(map[string]instanceState)
|
||||
// resources returns a map of name to resourceState, for any supported resources
|
||||
// found in the statefile.
|
||||
func (s *state) resources() map[string]resourceState {
|
||||
typeRemover := regexp.MustCompile(`^[\w_]+\.`)
|
||||
inst := make(map[string]resourceState)
|
||||
|
||||
for _, m := range s.Modules {
|
||||
for k, r := range m.Resources {
|
||||
if r.Type == "aws_instance" {
|
||||
name := strings.TrimPrefix(k, "aws_instance.")
|
||||
inst[name] = r.Primary
|
||||
if r.isSupported() {
|
||||
name := typeRemover.ReplaceAllString(k, "")
|
||||
inst[name] = r
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -55,6 +56,30 @@ type resourceState struct {
|
||||
Primary instanceState `json:"primary"`
|
||||
}
|
||||
|
||||
// isSupported returns true if terraform-inventory supports this resource.
|
||||
func (s *resourceState) isSupported() bool {
|
||||
return s.Address() != ""
|
||||
}
|
||||
|
||||
// Address returns the IP address of this resource.
|
||||
func (s *resourceState) Address() string {
|
||||
switch s.Type {
|
||||
case "aws_instance":
|
||||
return s.Primary.Attributes["private_ip"]
|
||||
|
||||
case "digitalocean_droplet":
|
||||
return s.Primary.Attributes["ipv4_address"]
|
||||
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// Attributes returns a map containing everything we know about this resource.
|
||||
func (s *resourceState) Attributes() map[string]string {
|
||||
return s.Primary.Attributes
|
||||
}
|
||||
|
||||
type instanceState struct {
|
||||
ID string `json:"id"`
|
||||
Attributes map[string]string `json:"attributes,omitempty"`
|
||||
|
153
parser_test.go
153
parser_test.go
@ -8,48 +8,58 @@ import (
|
||||
|
||||
const exampleStateFile = `
|
||||
{
|
||||
"version": 1,
|
||||
"serial": 1,
|
||||
"modules": [
|
||||
{
|
||||
"path": [
|
||||
"root"
|
||||
],
|
||||
"outputs": {},
|
||||
"resources": {
|
||||
"aws_instance.one": {
|
||||
"type": "aws_instance",
|
||||
"primary": {
|
||||
"id": "i-aaaaaaaa",
|
||||
"attributes": {
|
||||
"ami": "ami-XXXXXXXX",
|
||||
"id": "i-aaaaaaaa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws_instance.two": {
|
||||
"type": "aws_instance",
|
||||
"primary": {
|
||||
"id": "i-bbbbbbbb",
|
||||
"attributes": {
|
||||
"ami": "ami-YYYYYYYY",
|
||||
"id": "i-bbbbbbbb"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws_security_group.example": {
|
||||
"type": "aws_security_group",
|
||||
"primary": {
|
||||
"id": "sg-cccccccc",
|
||||
"attributes": {
|
||||
"description": "Whatever",
|
||||
"id": "sg-cccccccc"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
"version": 1,
|
||||
"serial": 1,
|
||||
"modules": [
|
||||
{
|
||||
"path": [
|
||||
"root"
|
||||
],
|
||||
"outputs": {},
|
||||
"resources": {
|
||||
"aws_instance.one": {
|
||||
"type": "aws_instance",
|
||||
"primary": {
|
||||
"id": "i-aaaaaaaa",
|
||||
"attributes": {
|
||||
"id": "i-aaaaaaaa",
|
||||
"private_ip": "10.0.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws_instance.two": {
|
||||
"type": "aws_instance",
|
||||
"primary": {
|
||||
"id": "i-bbbbbbbb",
|
||||
"attributes": {
|
||||
"id": "i-bbbbbbbb",
|
||||
"private_ip": "10.0.0.2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws_security_group.example": {
|
||||
"type": "aws_security_group",
|
||||
"primary": {
|
||||
"id": "sg-cccccccc",
|
||||
"attributes": {
|
||||
"id": "sg-cccccccc",
|
||||
"description": "Whatever"
|
||||
}
|
||||
}
|
||||
},
|
||||
"digitalocean_droplet.three": {
|
||||
"type": "digitalocean_droplet",
|
||||
"primary": {
|
||||
"id": "ddddddd",
|
||||
"attributes": {
|
||||
"id": "ddddddd",
|
||||
"ipv4_address": "192.168.0.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
@ -69,8 +79,8 @@ func TestStateRead(t *testing.T) {
|
||||
Primary: instanceState{
|
||||
ID: "i-aaaaaaaa",
|
||||
Attributes: map[string]string{
|
||||
"ami": "ami-XXXXXXXX",
|
||||
"id": "i-aaaaaaaa",
|
||||
"id": "i-aaaaaaaa",
|
||||
"private_ip": "10.0.0.1",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -79,8 +89,8 @@ func TestStateRead(t *testing.T) {
|
||||
Primary: instanceState{
|
||||
ID: "i-bbbbbbbb",
|
||||
Attributes: map[string]string{
|
||||
"ami": "ami-YYYYYYYY",
|
||||
"id": "i-bbbbbbbb",
|
||||
"id": "i-bbbbbbbb",
|
||||
"private_ip": "10.0.0.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -89,8 +99,18 @@ func TestStateRead(t *testing.T) {
|
||||
Primary: instanceState{
|
||||
ID: "sg-cccccccc",
|
||||
Attributes: map[string]string{
|
||||
"description": "Whatever",
|
||||
"id": "sg-cccccccc",
|
||||
"description": "Whatever",
|
||||
},
|
||||
},
|
||||
},
|
||||
"digitalocean_droplet.three": resourceState{
|
||||
Type: "digitalocean_droplet",
|
||||
Primary: instanceState{
|
||||
ID: "ddddddd",
|
||||
Attributes: map[string]string{
|
||||
"id": "ddddddd",
|
||||
"ipv4_address": "192.168.0.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -102,15 +122,44 @@ func TestStateRead(t *testing.T) {
|
||||
assert.Equal(t, exp, s)
|
||||
}
|
||||
|
||||
func TestInstances(t *testing.T) {
|
||||
func TestResources(t *testing.T) {
|
||||
r := strings.NewReader(exampleStateFile)
|
||||
|
||||
var s state
|
||||
err := s.read(r)
|
||||
assert.Nil(t, err)
|
||||
|
||||
inst := s.instances()
|
||||
assert.Equal(t, 2, len(inst))
|
||||
assert.Equal(t, "i-aaaaaaaa", inst["one"].ID)
|
||||
assert.Equal(t, "i-bbbbbbbb", inst["two"].ID)
|
||||
inst := s.resources()
|
||||
assert.Equal(t, 3, len(inst))
|
||||
assert.Equal(t, "aws_instance", inst["one"].Type)
|
||||
assert.Equal(t, "aws_instance", inst["two"].Type)
|
||||
assert.Equal(t, "digitalocean_droplet", inst["three"].Type)
|
||||
}
|
||||
|
||||
func TestIsSupported(t *testing.T) {
|
||||
|
||||
r := resourceState{
|
||||
Type: "something",
|
||||
}
|
||||
assert.Equal(t, false, r.isSupported())
|
||||
|
||||
r = resourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: instanceState{
|
||||
Attributes: map[string]string{
|
||||
"private_ip": "10.0.0.2",
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.Equal(t, true, r.isSupported())
|
||||
|
||||
r = resourceState{
|
||||
Type: "digitalocean_droplet",
|
||||
Primary: instanceState{
|
||||
Attributes: map[string]string{
|
||||
"ipv4_address": "192.168.0.3",
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.Equal(t, true, r.isSupported())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user