diff --git a/config/struct.go b/config/struct.go index 3eda819..5df9a2e 100644 --- a/config/struct.go +++ b/config/struct.go @@ -36,6 +36,13 @@ type DBInstance struct { Tags Tags } +// DBCluster is a group of DBInstances +type DBCluster struct { + *rds.DBCluster + Instances []*DBInstance + Tags Tags +} + // Filters ... type Filters map[string]string diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f57cdf1 --- /dev/null +++ b/go.mod @@ -0,0 +1,27 @@ +module github.com/seatgeek/aws-dynamic-consul-catalog + +go 1.14 + +require ( + github.com/armon/go-metrics v0.3.3 // indirect + github.com/aws/aws-sdk-go v1.13.5-0.20180223184012-ebef4262e06a + github.com/go-ini/ini v1.27.3-0.20170519023713-afbc45e87f3b // indirect + github.com/hashicorp/consul v1.1.0 + github.com/hashicorp/go-msgpack v1.1.5 // indirect + github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 // indirect + github.com/hashicorp/go-uuid v1.0.2 // indirect + github.com/hashicorp/memberlist v0.2.2 // indirect + github.com/hashicorp/serf v0.8.2-0.20170419221626-65c2babe73c7 // indirect + github.com/imkira/go-observer v1.0.3 + github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7 // indirect + github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/patrickmn/go-cache v2.0.1-0.20170418232947-7ac151875ffb+incompatible + github.com/pkg/errors v0.9.1 // indirect + github.com/seatgeek/logrus-gelf-formatter v0.0.0-20180829220724-ce23ecb3f367 + github.com/sirupsen/logrus v1.4.2 + github.com/smartystreets/goconvey v1.6.4 // indirect + github.com/stretchr/testify v1.5.1 // indirect + golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 // indirect + gopkg.in/urfave/cli.v1 v1.19.1 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..7439b5b --- /dev/null +++ b/go.sum @@ -0,0 +1,180 @@ +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.3 h1:a9F4rlj7EWWrbj7BYw8J8+x+ZZkJeqzNyRk8hdPF+ro= +github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/aws/aws-sdk-go v1.13.5-0.20180223184012-ebef4262e06a h1:giSYG4mSxRjnz1kTZoVKHWPw/yM9dZxjkdm+ZyBzifE= +github.com/aws/aws-sdk-go v1.13.5-0.20180223184012-ebef4262e06a/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-ini/ini v1.27.3-0.20170519023713-afbc45e87f3b h1:Q5ATg4ybF9SCggZ/Vq+BLW7Sw6bE40VZt3lb/VoJzao= +github.com/go-ini/ini v1.27.3-0.20170519023713-afbc45e87f3b/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/hashicorp/consul v1.1.0 h1:xKwxj1mDPRmQVbiZxJlD7R5PiS7XsttGP7vNx16IcLY= +github.com/hashicorp/consul v1.1.0/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs= +github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 h1:VBj0QYQ0u2MCJzBfeYXGexnAl17GsH1yidnoxCqqD9E= +github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90/go.mod h1:o4zcYY1e0GEZI6eSEr+43QDYmuGglw1qSO6qdHUHCgg= +github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/memberlist v0.2.2 h1:5+RffWKwqJ71YPu9mWsF7ZOscZmwfasdA8kbdC7AO2g= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.8.2-0.20170419221626-65c2babe73c7 h1:/G+Fc2pvvOuyjpVFpaS66G3h5dbLlTr32K66gK3rEnk= +github.com/hashicorp/serf v0.8.2-0.20170419221626-65c2babe73c7/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE= +github.com/imkira/go-observer v1.0.3 h1:l45TYAEeAB4L2xF6PR2gRLn2NE5tYhudh33MLmC7B80= +github.com/imkira/go-observer v1.0.3/go.mod h1:zLzElv2cGTHufQG17IEILJMPDg32TD85fFgKyFv00wU= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7 h1:SMvOWPJCES2GdFracYbBQh93GXac8fq7HeN6JnpduB8= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747 h1:eQox4Rh4ewJF+mqYPxCkmBAirRnPaHEB26UkNuPyjlk= +github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/patrickmn/go-cache v2.0.1-0.20170418232947-7ac151875ffb+incompatible h1:fLw7mzwSPiPxbQAQL5sqFliqVcX9S1ZV6WgsF0ZA118= +github.com/patrickmn/go-cache v2.0.1-0.20170418232947-7ac151875ffb+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/seatgeek/logrus-gelf-formatter v0.0.0-20180829220724-ce23ecb3f367 h1:kjJVIlsZ+29dcgTtHVJDtK7ykrf7e1tW/63UvYSCEJw= +github.com/seatgeek/logrus-gelf-formatter v0.0.0-20180829220724-ce23ecb3f367/go.mod h1:/THDZYi7F/BsVEcYzYPqdcWFQ+1C2InkawTKfLOAnzg= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 h1:eDrdRpKgkcCqKZQwyZRyeFZgfqt37SL7Kv3tok06cKE= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/urfave/cli.v1 v1.19.1 h1:pkwzWQSFerxgLtkdWlnjwOS+Vd7VCp/Kwdn3kmeflXQ= +gopkg.in/urfave/cli.v1 v1.19.1/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/service/rds/app.go b/service/rds/app.go index b66fd45..5a66100 100644 --- a/service/rds/app.go +++ b/service/rds/app.go @@ -90,12 +90,18 @@ func (r *RDS) Run() { allInstances := observer.NewProperty(nil) filteredInstances := observer.NewProperty(nil) + + writableInstances := observer.NewProperty(nil) + writableClusters := observer.NewProperty(nil) + catalogState := &config.CatalogState{} go r.backend.CatalogReader(catalogState, r.consulNodeName, r.quitCh) go r.reader(allInstances) go r.filter(allInstances, filteredInstances) - go r.writer(filteredInstances, catalogState) + go r.clusterize(filteredInstances, writableInstances, writableClusters) + go r.writer(writableInstances, catalogState) + go r.clusterWriter(writableClusters, catalogState) <-r.quitCh } diff --git a/service/rds/clusterize.go b/service/rds/clusterize.go new file mode 100644 index 0000000..3224c01 --- /dev/null +++ b/service/rds/clusterize.go @@ -0,0 +1,85 @@ +package rds + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/rds" + observer "github.com/imkira/go-observer" + "github.com/seatgeek/aws-dynamic-consul-catalog/config" + log "github.com/sirupsen/logrus" +) + +func (r *RDS) clusterize(inInstancesProp, outInstancesProp, outClustersProp observer.Property) { + logger := log.WithField("worker", "clusterize") + logger.Info("Starting RDS instance clusterize worker") + stream := inInstancesProp.Observe() + + for { + select { + case <-r.quitCh: + return + + // wait for changes + case <-stream.Changes(): + logger.Debug("Clusterizing instances") + + stream.Next() + instances := stream.Value().([]*config.DBInstance) + + standaloneInstances := make([]*config.DBInstance, 0) + clusters := make(map[string]*config.DBCluster) + + for _, instance := range instances { + clusterID := aws.StringValue(instance.DBClusterIdentifier) + if clusterID == "" { + standaloneInstances = append(standaloneInstances, instance) + logger.Debugf("Instance %s is not part of a cluster", aws.StringValue(instance.DBInstanceIdentifier)) + continue + } + + logger.Debugf("Instance %s is part of cluster: %s", + aws.StringValue(instance.DBInstanceIdentifier), clusterID) + cluster, ok := clusters[clusterID] + if !ok { + rdsCluster := r.readDBCluster(clusterID) + if rdsCluster == nil { + log.Errorf("Error fetching cluster for instance: %s with ClusterID: %s (skipping)", + aws.StringValue(instance.DBInstanceIdentifier), clusterID) + continue + } + + cluster = &config.DBCluster{ + DBCluster: rdsCluster, + Instances: []*config.DBInstance{}, + Tags: make(config.Tags), + } + clusters[clusterID] = cluster + } + // attach this instance to the cluster... + cluster.Instances = append(cluster.Instances, instance) + } + outInstancesProp.Update(standaloneInstances) + + clusterList := []*config.DBCluster{} + for _, v := range clusters { + clusterList = append(clusterList, v) + } + outClustersProp.Update(clusterList) + logger.Debugf("Finished clusterizing RDS instances. Clusters: %d Instances: %d", + len(clusters), len(instances)) + } + } +} + +func (r *RDS) readDBCluster(clusterID string) *rds.DBCluster { + input := &rds.DescribeDBClustersInput{DBClusterIdentifier: aws.String(clusterID)} + output, err := r.rds.DescribeDBClusters(input) + if err != nil { + log.Fatal(err) + } + for _, cluster := range output.DBClusters { + if clusterID == aws.StringValue(cluster.DBClusterIdentifier) { + return cluster + } + } + return nil +} diff --git a/service/rds/clusterwriter.go b/service/rds/clusterwriter.go new file mode 100644 index 0000000..e26f9c2 --- /dev/null +++ b/service/rds/clusterwriter.go @@ -0,0 +1,229 @@ +package rds + +import ( + "fmt" + "os" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/imkira/go-observer" + "github.com/seatgeek/aws-dynamic-consul-catalog/config" + log "github.com/sirupsen/logrus" +) + +func (r *RDS) clusterWriter(inClustersProp observer.Property, state *config.CatalogState) { + logger := log.WithField("worker", "clusterWriter") + logger.Info("Starting RDS Consul Catalog clusterWriter") + + stream := inClustersProp.Observe() + for { + select { + case <-r.quitCh: + return + + // wait for changes + case <-stream.Changes(): + state.Lock() + stream.Next() + clusters := stream.Value().([]*config.DBCluster) + + seen := state.Services.GetSeen() + + found := &config.SeenCatalog{ + Services: make([]string, 0), + Checks: make([]string, 0), + } + + for _, cluster := range clusters { + r.writeClusterBackendCatalog(cluster, logger, state, found) + } + + for _, service := range r.getDifference(seen.Services, found.Services) { + logger.Warnf("Deleting service %s", service) + r.backend.DeleteService(service, r.consulNodeName) + } + + for _, check := range r.getDifference(seen.Checks, found.Checks) { + logger.Warnf("Deleting check %s", check) + r.backend.DeleteCheck(check, r.consulNodeName) + } + + logger.Debug("Finished Consul Catalog cluster write") + state.Unlock() + } + } +} + +func (r *RDS) writeClusterBackendCatalog(cluster *config.DBCluster, logger *log.Entry, state *config.CatalogState, seen *config.SeenCatalog) { + logger = logger.WithField("cluster", aws.StringValue(cluster.DBClusterIdentifier)) + + name := r.getClusterServiceName(cluster) + if name == "" { + return + } + id := aws.StringValue(cluster.DBClusterIdentifier) + + if *cluster.Status == "creating" { + logger.Warnf("Cluster %s id being created, skipping for now", name) + return + } + + if cluster.Endpoint == nil { + logger.Errorf("Cluster %s does not have an endpoint yet, the cluster is in state: %s", + name, *cluster.Status) + return + } + + clusterStatus := extractStatus(aws.StringValue(cluster.Status)) + + memberRole := map[string]string{} + for _, member := range cluster.DBClusterMembers { + if aws.BoolValue(member.IsClusterWriter) { + memberRole[aws.StringValue(member.DBInstanceIdentifier)] = "cluster-writer" + } else { + memberRole[aws.StringValue(member.DBInstanceIdentifier)] = "cluster-reader" + } + } + + for _, instance := range cluster.Instances { + tags := []string{} + for k, v := range instance.Tags { + tags = append(tags, fmt.Sprintf("%s-%s", k, v)) + } + tags = append(tags, fmt.Sprintf("cluster-rw-role-%s", + memberRole[aws.StringValue(instance.DBInstanceIdentifier)])) + service := &config.Service{ + ServiceID: id, + ServiceName: name, + ServicePort: int(aws.Int64Value(instance.DbInstancePort)), + ServiceTags: tags, + CheckID: fmt.Sprintf("service:%s Node:%s", id, aws.StringValue(instance.DBInstanceIdentifier)), + CheckNode: aws.StringValue(instance.DBInstanceIdentifier), + CheckNotes: fmt.Sprintf("RDS Instance Status: %s", aws.StringValue(instance.DBInstanceStatus)), + CheckStatus: clusterStatus, + CheckOutput: fmt.Sprintf("Pending tasks: %s\n\nAddr: %s\n\nmanaged by aws-dynamic-consul-catalog", + instance.PendingModifiedValues.GoString(), aws.StringValue(instance.Endpoint.Address)), + ServiceAddress: aws.StringValue(instance.Endpoint.Address), + } + + service.ServiceMeta = make(map[string]string) + service.ServiceMeta["Engine"] = aws.StringValue(instance.Engine) + service.ServiceMeta["EngineVersion"] = aws.StringValue(instance.EngineVersion) + service.ServiceMeta["DBName"] = aws.StringValue(instance.DBName) + service.ServiceMeta["DBInstanceClass"] = aws.StringValue(instance.DBInstanceClass) + service.ServiceMeta["DBInstanceIdentifier"] = aws.StringValue(instance.DBInstanceIdentifier) + service.ServiceMeta["RoleInCluster"] = memberRole[aws.StringValue(instance.DBInstanceIdentifier)] + service.ServiceMeta["ClusterName"] = aws.StringValue(cluster.DBClusterIdentifier) + + if stringInSlice(service.ServiceAddress, seen.Services) { + logger.Errorf("Found duplicate Service ID %s - possible duplicate 'consul_service_name' RDS tag with same Replication Role", service.ServiceID) + if r.onDuplicate == "quit" { + os.Exit(1) + } + if r.onDuplicate == "ignore-skip-last" { + logger.Errorf("Ignoring current service") + return + } + } + seen.Services = append(seen.Services, service.ServiceAddress) + + if stringInSlice(service.CheckID, seen.Checks) { + logger.Errorf("Found duplicate Check ID %s - possible duplicate 'consul_service_name' RDS tag with same Replication Role", service.CheckID) + if r.onDuplicate == "quit" { + os.Exit(1) + } + if r.onDuplicate == "ignore-skip-last" { + logger.Errorf("Ignoring current service") + return + } + } + seen.Checks = append(seen.Checks, service.CheckID) + + existingService, ok := state.Services[id] + if ok { + logger.Debugf("Service %s exist in remote catalog, lets compare", id) + + if r.identicalService(existingService, service, logger) { + logger.Debugf("Services are identical, skipping") + return + } + + logger.Info("Services are not identical, updating catalog") + } else { + logger.Infof("Service %s doesn't exist in remote catalog, creating", id) + } + + service.CheckOutput = service.CheckOutput + fmt.Sprintf("\n\nLast update: %s", time.Now().Format(time.RFC1123Z)) + r.backend.WriteService(service) + } +} + +func extractStatus(status string) string { + switch status { + case "backing-up": + status = "passing" + case "available": + status = "passing" + case "maintenance": + status = "passing" + case "modifying": + status = "passing" + case "creating": + status = "critical" + case "deleting": + status = "critical" + case "failed": + status = "critical" + case "rebooting": + status = "passing" + case "renaming": + status = "critical" + case "restore-error": + status = "critical" + case "inaccessible-encryption-credentials": + status = "critical" + case "incompatible-credentials": + status = "critical" + case "incompatible-network": + status = "critical" + case "incompatible-option-group": + status = "critical" + case "incompatible-parameters": + status = "critical" + case "incompatible-restore": + status = "critical" + case "resetting-master-credentials": + status = "warning" + case "storage-optimization": + status = "passing" + case "storage-full": + status = "warning" + case "upgrading": + status = "warning" + default: + status = "passing" + } + return status +} + +func (r *RDS) getClusterServiceName(cluster *config.DBCluster) string { + // prefer the consul_service_name from instance tags + if name, ok := cluster.Tags["consul_service_name"]; ok { + return r.servicePrefix + name + r.serviceSuffix + } + + // derive from the instance DB cluster name + name := aws.StringValue(cluster.DBClusterIdentifier) + if name != "" { + return r.servicePrefix + name + r.serviceSuffix + } + + // derive from the instance DB name + name = aws.StringValue(cluster.DatabaseName) + if name != "" { + return r.servicePrefix + name + r.serviceSuffix + } + + log.Errorf("Failed to find service name for " + aws.StringValue(cluster.DBClusterArn)) + return "" +} diff --git a/service/rds/kill.sh b/service/rds/kill.sh new file mode 100644 index 0000000..99fa134 --- /dev/null +++ b/service/rds/kill.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +leader="$(curl https://consul.internal.classdojo.com/v1/status/leader | sed 's/:8300//' | sed 's/"//g')" +while : +do + serviceID="$(curl http://$leader:8500/v1/health/state/critical | ./jq '.[0].ServiceID' | sed 's/"//g')" + node="$(curl http://$leader:8500/v1/health/state/critical | ./jq '.[0].Node' | sed 's/"//g')" + echo "serviceID=$serviceID, node=$node" + size=${#serviceID} + echo "size=$size" + if [ $size -ge 7 ]; then + curl --request PUT http://$node:8500/v1/agent/service/deregister/$serviceID + else + break + fi +done +curl http://$leader:8500/v1/health/state/critical \ No newline at end of file diff --git a/service/rds/reader.go b/service/rds/reader.go index 2661f8e..ed156a0 100644 --- a/service/rds/reader.go +++ b/service/rds/reader.go @@ -8,13 +8,13 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/rds" - observer "github.com/imkira/go-observer" - cache "github.com/patrickmn/go-cache" + "github.com/imkira/go-observer" + "github.com/patrickmn/go-cache" "github.com/seatgeek/aws-dynamic-consul-catalog/config" log "github.com/sirupsen/logrus" ) -func (r *RDS) reader(prop observer.Property) { +func (r *RDS) reader(instances observer.Property) { logger := log.WithField("worker", "indexer") logger.Info("Starting RDS index worker") @@ -27,7 +27,7 @@ func (r *RDS) reader(prop observer.Property) { signal.Notify(sigs, syscall.SIGUSR1) // read right away on start - r.read(prop, logger) + r.read(instances, logger) for { select { @@ -35,17 +35,17 @@ func (r *RDS) reader(prop observer.Property) { return case <-sigs: - r.read(prop, logger) // run updater + r.read(instances, logger) // run updater ticker.Reset(r.checkInterval) // schedule new timed run case <-ticker.C: - r.read(prop, logger) // run updater + r.read(instances, logger) // run updater ticker.Reset(r.checkInterval) // schedule new timed run } } } -func (r *RDS) read(prop observer.Property, logger *log.Entry) { +func (r *RDS) read(allInstances observer.Property, logger *log.Entry) { logger.Debug("Starting refresh of RDS information") var marker *string @@ -80,7 +80,12 @@ func (r *RDS) read(prop observer.Property, logger *log.Entry) { marker = resp.Marker for _, instance := range resp.DBInstances { - instances = append(instances, &config.DBInstance{instance, r.getInstanceTags(instance)}) + i := &config.DBInstance{ + DBInstance: instance, + Tags: r.getInstanceTags(instance), + } + r.augmentClusterTags(i.DBInstance, i.Tags) + instances = append(instances, i) } if marker == nil { @@ -89,10 +94,31 @@ func (r *RDS) read(prop observer.Property, logger *log.Entry) { } } - prop.Update(instances) + allInstances.Update(instances) logger.Debug("Finished refresh of RDS information") } + +func (r *RDS) augmentClusterTags(instance *rds.DBInstance, tags config.Tags) { + input := &rds.DescribeDBClustersInput{DBClusterIdentifier: instance.DBClusterIdentifier} + output, err := r.rds.DescribeDBClusters(input) + if err != nil { + log.Fatal(err) + } + for _, cluster := range output.DBClusters { + for _, member := range cluster.DBClusterMembers { + if aws.StringValue(member.DBInstanceIdentifier) == aws.StringValue(instance.DBInstanceIdentifier) { + if aws.BoolValue(member.IsClusterWriter) { + tags["is-cluster-writer"] = "true" + } else { + tags["is-cluster-writer"] = "false" + } + return + } + } + } +} + func (r *RDS) getInstanceTags(instance *rds.DBInstance) config.Tags { instanceArn := aws.StringValue(instance.DBInstanceArn) @@ -115,6 +141,5 @@ func (r *RDS) getInstanceTags(instance *rds.DBInstance) config.Tags { } r.tagCache.Set(instanceArn, &res, cache.DefaultExpiration) - return res } diff --git a/service/rds/writer.go b/service/rds/writer.go index 31cc82a..04a786f 100644 --- a/service/rds/writer.go +++ b/service/rds/writer.go @@ -70,7 +70,7 @@ func (r *RDS) writeBackendCatalog(instance *config.DBInstance, logger *log.Entry if name == "" { return } - id := name + id := aws.StringValue(instance.DBInstanceIdentifier) if *instance.DBInstanceStatus == "creating" { logger.Warnf("Instance %s id being created, skipping for now", name) @@ -88,12 +88,22 @@ func (r *RDS) writeBackendCatalog(instance *config.DBInstance, logger *log.Entry isSlave := instance.ReadReplicaSourceDBInstanceIdentifier != nil isMaster := len(instance.ReadReplicaDBInstanceIdentifiers) > 0 + isClusterWriter, clusterWriterTagged := instance.Tags["is-cluster-writer"] + logger.Debugf(" ID: %s", id) logger.Debugf(" Name: %s", name) logger.Debugf(" Addr: %s", addr) logger.Debugf(" Port: %d", port) tags := make([]string, 0) + if clusterWriterTagged { + if isClusterWriter == "true" { + tags = append(tags, "clusterWriter") + } else { + tags = append(tags, "clusterReader") + } + } + if isSlave { tags = append(tags, r.consulReplicaTag) id = fmt.Sprintf("%s-%s-%s", id, *instance.DBInstanceIdentifier, r.consulReplicaTag) @@ -104,57 +114,16 @@ func (r *RDS) writeBackendCatalog(instance *config.DBInstance, logger *log.Entry id = id + "-" + r.consulMasterTag } + if clusterWriterTagged { + id = id + "-clusterwriter-" + isClusterWriter + } + if !isSlave && !isMaster { tags = append(tags, r.consulMasterTag) tags = append(tags, r.consulReplicaTag) } - status := "passing" - switch aws.StringValue(instance.DBInstanceStatus) { - case "backing-up": - status = "passing" - case "available": - status = "passing" - case "maintenance": - status = "passing" - case "modifying": - status = "passing" - case "creating": - status = "critical" - case "deleting": - status = "critical" - case "failed": - status = "critical" - case "rebooting": - status = "passing" - case "renaming": - status = "critical" - case "restore-error": - status = "critical" - case "inaccessible-encryption-credentials": - status = "critical" - case "incompatible-credentials": - status = "critical" - case "incompatible-network": - status = "critical" - case "incompatible-option-group": - status = "critical" - case "incompatible-parameters": - status = "critical" - case "incompatible-restore": - status = "critical" - case "resetting-master-credentials": - status = "warning" - case "storage-optimization": - status = "passing" - case "storage-full": - status = "warning" - case "upgrading": - status = "warning" - default: - status = "passing" - } - + status := extractStatus(aws.StringValue(instance.DBInstanceStatus)) service := &config.Service{ ServiceID: id, ServiceName: name, @@ -162,7 +131,7 @@ func (r *RDS) writeBackendCatalog(instance *config.DBInstance, logger *log.Entry ServicePort: int(port), ServiceTags: tags, CheckID: fmt.Sprintf("service:%s", id), - CheckNode: r.consulNodeName, + CheckNode: name, CheckNotes: fmt.Sprintf("RDS Instance Status: %s", aws.StringValue(instance.DBInstanceStatus)), CheckStatus: status, CheckOutput: fmt.Sprintf("Pending tasks: %s\n\nAddr: %s\n\nmanaged by aws-dynamic-consul-catalog", instance.PendingModifiedValues.GoString(), addr), @@ -174,6 +143,9 @@ func (r *RDS) writeBackendCatalog(instance *config.DBInstance, logger *log.Entry service.ServiceMeta["DBName"] = aws.StringValue(instance.DBName) service.ServiceMeta["DBInstanceClass"] = aws.StringValue(instance.DBInstanceClass) service.ServiceMeta["DBInstanceIdentifier"] = aws.StringValue(instance.DBInstanceIdentifier) + if clusterWriterTagged { + service.ServiceMeta["IsClusterWriter"] = isClusterWriter + } if stringInSlice(service.ServiceID, seen.Services) { logger.Errorf("Found duplicate Service ID %s - possible duplicate 'consul_service_name' RDS tag with same Replication Role", service.ServiceID) @@ -223,8 +195,20 @@ func (r *RDS) getServiceName(instance *config.DBInstance) string { return r.servicePrefix + name + r.serviceSuffix } + // derive from the instance DB cluster name + name := aws.StringValue(instance.DBClusterIdentifier) + if name != "" { + return r.servicePrefix + name + r.serviceSuffix + } + // derive from the instance DB name - name := aws.StringValue(instance.DBName) + name = aws.StringValue(instance.DBName) + if name != "" { + return r.servicePrefix + name + r.serviceSuffix + } + + // derive from the instance DB instance identifier + name = aws.StringValue(instance.DBInstanceIdentifier) if name != "" { return r.servicePrefix + name + r.serviceSuffix } diff --git a/vendor/vendor.json b/vendor/vendor.json deleted file mode 100644 index 05bb204..0000000 --- a/vendor/vendor.json +++ /dev/null @@ -1,255 +0,0 @@ -{ - "comment": "", - "ignore": "test", - "package": [ - { - "checksumSHA1": "uMrarrd/UjcGWEK5bBQmaPx0nyQ=", - "path": "github.com/aws/aws-sdk-go/aws", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "Y9W+4GimK4Fuxq+vyIskVYFRnX4=", - "path": "github.com/aws/aws-sdk-go/aws/awserr", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "yyYr41HZ1Aq0hWc3J5ijXwYEcac=", - "path": "github.com/aws/aws-sdk-go/aws/awsutil", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "wGf8GkrbZe2VFXOo28K0jq68A+g=", - "path": "github.com/aws/aws-sdk-go/aws/client", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "ieAJ+Cvp/PKv1LpUEnUXpc3OI6E=", - "path": "github.com/aws/aws-sdk-go/aws/client/metadata", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "U2W3pMTHfONS6R/QP/Zg18+89TQ=", - "path": "github.com/aws/aws-sdk-go/aws/corehandlers", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "Y+cPwQL0dZMyqp3wI+KJWmA9KQ8=", - "path": "github.com/aws/aws-sdk-go/aws/credentials", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "u3GOAJLmdvbuNUeUEcZSEAOeL/0=", - "path": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "NUJUTWlc1sV8b7WjfiYc4JZbXl0=", - "path": "github.com/aws/aws-sdk-go/aws/credentials/endpointcreds", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "JEYqmF83O5n5bHkupAzA6STm0no=", - "path": "github.com/aws/aws-sdk-go/aws/credentials/stscreds", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "OnU/n7R33oYXiB4SAGd5pK7I0Bs=", - "path": "github.com/aws/aws-sdk-go/aws/defaults", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "pDnK93CqjQ4ROSW8Y/RuHXjv52M=", - "path": "github.com/aws/aws-sdk-go/aws/ec2metadata", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "dUurC4Vz9SYV3ZSSP+aM+DH4F14=", - "path": "github.com/aws/aws-sdk-go/aws/endpoints", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "FpjCPoRNsVKM1hOg9EpC7jn5pRI=", - "path": "github.com/aws/aws-sdk-go/aws/request", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "DIn7B+oP++/nw603OB95fmupzu8=", - "path": "github.com/aws/aws-sdk-go/aws/session", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "4gwCpxPnVQISJGF/skyWpzzxFAc=", - "path": "github.com/aws/aws-sdk-go/aws/signer/v4", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "MYLldFRnsZh21TfCkgkXCT3maPU=", - "path": "github.com/aws/aws-sdk-go/internal/sdkrand", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "04ypv4x12l4q0TksA1zEVsmgpvw=", - "path": "github.com/aws/aws-sdk-go/internal/shareddefaults", - "revision": "ebef4262e06a772a06a80aaee8e952c2514e1606", - "revisionTime": "2018-02-23T18:40:12Z" - }, - { - "checksumSHA1": "wk7EyvDaHwb5qqoOP/4d3cV0708=", - "path": "github.com/aws/aws-sdk-go/private/protocol", - "revision": "31484500fe77b88dbe197c6348358ed275aed5d7", - "revisionTime": "2017-05-19T23:36:38Z" - }, - { - "checksumSHA1": "ZqY5RWavBLWTo6j9xqdyBEaNFRk=", - "path": "github.com/aws/aws-sdk-go/private/protocol/query", - "revision": "31484500fe77b88dbe197c6348358ed275aed5d7", - "revisionTime": "2017-05-19T23:36:38Z" - }, - { - "checksumSHA1": "Drt1JfLMa0DQEZLWrnMlTWaIcC8=", - "path": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil", - "revision": "31484500fe77b88dbe197c6348358ed275aed5d7", - "revisionTime": "2017-05-19T23:36:38Z" - }, - { - "checksumSHA1": "VCTh+dEaqqhog5ncy/WTt9+/gFM=", - "path": "github.com/aws/aws-sdk-go/private/protocol/rest", - "revision": "31484500fe77b88dbe197c6348358ed275aed5d7", - "revisionTime": "2017-05-19T23:36:38Z" - }, - { - "checksumSHA1": "ODo+ko8D6unAxZuN1jGzMcN4QCc=", - "path": "github.com/aws/aws-sdk-go/private/protocol/restxml", - "revision": "31484500fe77b88dbe197c6348358ed275aed5d7", - "revisionTime": "2017-05-19T23:36:38Z" - }, - { - "checksumSHA1": "0qYPUga28aQVkxZgBR3Z86AbGUQ=", - "path": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil", - "revision": "31484500fe77b88dbe197c6348358ed275aed5d7", - "revisionTime": "2017-05-19T23:36:38Z" - }, - { - "checksumSHA1": "aO69igvJSXy8Hw3zCP2g9d/icv4=", - "path": "github.com/aws/aws-sdk-go/service/elasticache", - "revision": "49ddb3a699c1030337daeceaedbc6b6a10ca0f0c", - "revisionTime": "2017-05-22T22:31:00Z" - }, - { - "checksumSHA1": "hOMvmDsta9bUZXcE59EYXAF2lMM=", - "path": "github.com/aws/aws-sdk-go/service/rds", - "revision": "31484500fe77b88dbe197c6348358ed275aed5d7", - "revisionTime": "2017-05-19T23:36:38Z" - }, - { - "checksumSHA1": "krqUUMDYRN2ohYcumxZl8BTR5EQ=", - "path": "github.com/aws/aws-sdk-go/service/s3", - "revision": "31484500fe77b88dbe197c6348358ed275aed5d7", - "revisionTime": "2017-05-19T23:36:38Z" - }, - { - "checksumSHA1": "fbROB+q5aRgvH79KOnEqr63ahRE=", - "path": "github.com/aws/aws-sdk-go/service/sts", - "revision": "31484500fe77b88dbe197c6348358ed275aed5d7", - "revisionTime": "2017-05-19T23:36:38Z" - }, - { - "checksumSHA1": "kPviFEMWr7Ynp/OsxggKRSv0TEE=", - "path": "github.com/go-ini/ini", - "revision": "afbc45e87f3ba324c532d12c71918ef52e0fb194", - "revisionTime": "2017-05-19T02:37:13Z" - }, - { - "checksumSHA1": "cZw5u6BGWe3gjJxmXT6J0Tfn6Mw=", - "path": "github.com/hashicorp/consul/api", - "revision": "5174058f0d2bda63fa5198ab96c33d9a909c58ed", - "revisionTime": "2018-05-11T18:57:42Z", - "version": "v1.1.0", - "versionExact": "v1.1.0" - }, - { - "checksumSHA1": "b8F628srIitj5p7Y130xc9k0QWs=", - "path": "github.com/hashicorp/go-cleanhttp", - "revision": "3573b8b52aa7b37b9358d966a898feb387f62437", - "revisionTime": "2017-02-11T01:34:15Z" - }, - { - "checksumSHA1": "A1PcINvF3UiwHRKn8UcgARgvGRs=", - "path": "github.com/hashicorp/go-rootcerts", - "revision": "6bb64b370b90e7ef1fa532be9e591a81c3493e00", - "revisionTime": "2016-05-03T14:34:40Z" - }, - { - "checksumSHA1": "E3Xcanc9ouQwL+CZGOUyA/+giLg=", - "path": "github.com/hashicorp/serf/coordinate", - "revision": "65c2babe73c7a096cd24e9eeec67613eb4e436c9", - "revisionTime": "2017-04-19T22:16:26Z" - }, - { - "checksumSHA1": "uxdfA/xMBbIZ89WdzjeDYM2N8Gw=", - "path": "github.com/imkira/go-observer", - "revision": "2b5c0039075a41408f1a33aa6391bd77d3e5a132", - "revisionTime": "2016-09-18T09:16:08Z" - }, - { - "checksumSHA1": "0ZrwvB6KoGPj2PoDNSEJwxQ6Mog=", - "path": "github.com/jmespath/go-jmespath", - "revision": "bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d", - "revisionTime": "2016-08-03T19:07:31Z" - }, - { - "checksumSHA1": "V/quM7+em2ByJbWBLOsEwnY3j/Q=", - "path": "github.com/mitchellh/go-homedir", - "revision": "b8bc1bf767474819792c23f32d8286a45736f1c6", - "revisionTime": "2016-12-03T19:45:07Z" - }, - { - "checksumSHA1": "SQi5yeNb9HnAMRpEhQgcv9x9yKc=", - "path": "github.com/patrickmn/go-cache", - "revision": "7ac151875ffb48b9f3ccce9ea20f020b0c1596c8", - "revisionTime": "2017-04-18T23:29:47Z" - }, - { - "checksumSHA1": "XAGndbmKH374GMFHOrgi5MThUYQ=", - "path": "github.com/seatgeek/logrus-gelf-formatter", - "revision": "ce23ecb3f367c85481346bcc4e4ca65d4c5ca262", - "revisionTime": "2018-08-29T22:07:24Z" - }, - { - "checksumSHA1": "x/C9sWJ33glBGKgGvb8VvUQvR8s=", - "path": "github.com/sirupsen/logrus", - "revision": "5e5dc898656f695e2a086b8e12559febbfc01562", - "revisionTime": "2017-05-15T10:45:16Z" - }, - { - "checksumSHA1": "4owIzLmRdrdy3H3j/OD8UMJD5ZE=", - "path": "golang.org/x/sys/unix", - "revision": "dbc2be9168a660ef302e04b6ff6406de6f967473", - "revisionTime": "2017-05-20T17:05:02Z" - }, - { - "checksumSHA1": "brhONOPp4CSdTZf5uEtcH+FpFUI=", - "path": "gopkg.in/urfave/cli.v1", - "revision": "0bdeddeeb0f650497d603c4ad7b20cfe685682f6", - "revisionTime": "2016-11-22T04:36:10Z" - } - ], - "rootPath": "github.com/seatgeek/aws-dynamic-consul-catalog" -}