diff --git a/command/format/state.go b/command/format/state.go index 631c3d0558..7796427722 100644 --- a/command/format/state.go +++ b/command/format/state.go @@ -6,10 +6,13 @@ import ( "sort" "strings" + "github.com/hashicorp/terraform/addrs" + "github.com/hashicorp/terraform/plans" + "github.com/mitchellh/colorstring" "github.com/hashicorp/terraform/states" - "github.com/hashicorp/terraform/terraform" + // "github.com/hashicorp/terraform/terraform" ) // StateOpts are the options for formatting a state. @@ -19,10 +22,6 @@ type StateOpts struct { // Color is the colorizer. This is optional. Color *colorstring.Colorize - - // ModuleDepth is the depth of the modules to expand. By default this - // is zero which will not expand modules at all. - ModuleDepth int } // State takes a state and returns a string @@ -36,65 +35,58 @@ func State(opts *StateOpts) string { return "The state file is empty. No resources are represented." } - // FIXME: State formatter not yet updated for new state types - return "FIXME: State formatter not yet updated for new state types" - - /*var buf bytes.Buffer + var buf bytes.Buffer buf.WriteString("[reset]") + p := blockBodyDiffPrinter{ + buf: &buf, + color: opts.Color, + action: plans.NoOp, + } // Format all the modules for _, m := range s.Modules { - if len(m.Path)-1 <= opts.ModuleDepth || opts.ModuleDepth == -1 { - formatStateModuleExpand(&buf, m, opts) - } else { - formatStateModuleSingle(&buf, m, opts) - } + formatStateModule(&buf, m, opts) } // Write the outputs for the root module m := s.RootModule() - if len(m.Outputs) > 0 { - buf.WriteString("\nOutputs:\n\n") + + if m.OutputValues != nil { + if len(m.OutputValues) > 0 { + buf.WriteString("\nOutputs:\n\n") + } // Sort the outputs - ks := make([]string, 0, len(m.Outputs)) - for k, _ := range m.Outputs { + ks := make([]string, 0, len(m.OutputValues)) + for k := range m.OutputValues { ks = append(ks, k) } sort.Strings(ks) // Output each output k/v pair for _, k := range ks { - v := m.Outputs[k] - switch output := v.Value.(type) { - case string: - buf.WriteString(fmt.Sprintf("%s = %s", k, output)) - buf.WriteString("\n") - case []interface{}: - buf.WriteString(formatListOutput("", k, output)) - buf.WriteString("\n") - case map[string]interface{}: - buf.WriteString(formatMapOutput("", k, output)) - buf.WriteString("\n") - } + v := m.OutputValues[k] + buf.WriteString(fmt.Sprintf("%s = ", k)) + p.writeValue(v.Value, plans.NoOp, 0) } } return opts.Color.Color(strings.TrimSpace(buf.String())) - */ + } -func formatStateModuleExpand( - buf *bytes.Buffer, m *terraform.ModuleState, opts *StateOpts) { +func formatStateModule( + buf *bytes.Buffer, m *states.Module, opts *StateOpts) { + var moduleName string - if !m.IsRoot() { - moduleName = fmt.Sprintf("module.%s", strings.Join(m.Path[1:], ".")) + if !m.Addr.IsRoot() { + moduleName = fmt.Sprintf("module.%s", m.Addr.String()) } // First get the names of all the resources so we can show them // in alphabetical order. names := make([]string, 0, len(m.Resources)) - for name, _ := range m.Resources { + for name := range m.Resources { names = append(names, name) } sort.Strings(names) @@ -106,55 +98,69 @@ func formatStateModuleExpand( name = moduleName + "." + name } - rs := m.Resources[k] - is := rs.Primary - var id string - if is != nil { - id = is.ID - } - if id == "" { - id = "" + addr := m.Resources[k].Addr + switch addr.Mode { + case addrs.ManagedResourceMode: + buf.WriteString(fmt.Sprintf( + "resource %q %q", + addr.Type, + addr.Name, + )) + case addrs.DataResourceMode: + buf.WriteString(fmt.Sprintf( + "data %q %q ", + addr.Type, + addr.Name, + )) + default: + // should never happen, since the above is exhaustive + buf.WriteString(addr.String()) } - taintStr := "" - if rs.Primary != nil && rs.Primary.Tainted { - taintStr = " (tainted)" - } + buf.WriteString(" { attrs go here! }\n") - buf.WriteString(fmt.Sprintf("%s:%s\n", name, taintStr)) - buf.WriteString(fmt.Sprintf(" id = %s\n", id)) - - if is != nil { - // Sort the attributes - attrKeys := make([]string, 0, len(is.Attributes)) - for ak, _ := range is.Attributes { - // Skip the id attribute since we just show the id directly - if ak == "id" { - continue - } - - attrKeys = append(attrKeys, ak) - } - sort.Strings(attrKeys) - - // Output each attribute - for _, ak := range attrKeys { - av := is.Attributes[ak] - buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av)) - } - } } - buf.WriteString("[reset]\n") -} + // rs := m.Resources[k] + // is := rs.Instance + // var id string + // if is != nil { + // id = is + // } + // if id == "" { + // id = "" + // } + + // taintStr := "" + // // if rs.Primary != nil && rs.Primary.Tainted { + // // taintStr = " (tainted)" + // // } + + // buf.WriteString(fmt.Sprintf("%s:%s\n", name, taintStr)) + // buf.WriteString(fmt.Sprintf(" id = %s\n", id)) + + // if is != nil { + // // Sort the attributes + // attrKeys := make([]string, 0, len(is.Attributes)) + // for ak, _ := range is.Attributes { + // // Skip the id attribute since we just show the id directly + // if ak == "id" { + // continue + // } + + // attrKeys = append(attrKeys, ak) + // } + // sort.Strings(attrKeys) + + // // Output each attribute + // for _, ak := range attrKeys { + // av := is.Attributes[ak] + // buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av)) + // } + // } + // } -func formatStateModuleSingle( - buf *bytes.Buffer, m *terraform.ModuleState, opts *StateOpts) { - // Header with the module name - buf.WriteString(fmt.Sprintf("module.%s\n", strings.Join(m.Path[1:], "."))) - - // Now just write how many resources are in here. - buf.WriteString(fmt.Sprintf(" %d resource(s)\n", len(m.Resources))) + buf.WriteString("[reset]\n") } func formatNestedList(indent string, outputList []interface{}) string { diff --git a/command/format/state_test.go b/command/format/state_test.go new file mode 100644 index 0000000000..3415841c51 --- /dev/null +++ b/command/format/state_test.go @@ -0,0 +1,82 @@ +package format + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/addrs" + "github.com/hashicorp/terraform/states" + "github.com/mitchellh/colorstring" + "github.com/zclconf/go-cty/cty" +) + +var disabledColorize = &colorstring.Colorize{ + Colors: colorstring.DefaultColors, + Disable: true, +} + +func TestState(t *testing.T) { + state := states.NewState() + + rootModule := state.RootModule() + if rootModule == nil { + t.Errorf("root module is nil; want valid object") + } + + rootModule.SetLocalValue("foo", cty.StringVal("foo value")) + rootModule.SetOutputValue("bar", cty.StringVal("bar value"), false) + rootModule.SetResourceInstanceCurrent( + addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_thing", + Name: "baz", + }.Instance(addrs.IntKey(0)), + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectReady, + SchemaVersion: 1, + AttrsJSON: []byte(`{"woozles":"confuzles"}`), + }, + addrs.ProviderConfig{ + Type: "test", + }.Absolute(addrs.RootModuleInstance), + ) + + tests := []struct { + State *StateOpts + Want string + }{ + { + &StateOpts{ + State: &states.State{}, + Color: disabledColorize, + }, + "The state file is empty. No resources are represented.", + }, + { + &StateOpts{ + State: state, + Color: disabledColorize, + }, + "module.test_module.test_resource.foo", + }, + } + + for _, tt := range tests { + got := State(tt.State) + if got != tt.Want { + t.Errorf( + "wrong result\ninput: %v\ngot: %s\nwant: %s", + tt.State.State, got, tt.Want, + ) + } + } +} + +func mustParseModuleInstanceStr(s string) addrs.ModuleInstance { + addr, err := addrs.ParseModuleInstanceStr(s) + if err != nil { + fmt.Printf(err.Err().Error()) + panic(err) + } + return addr +} diff --git a/command/show.go b/command/show.go index 5c65c87b27..01a9406cbf 100644 --- a/command/show.go +++ b/command/show.go @@ -21,7 +21,6 @@ type ShowCommand struct { } func (c *ShowCommand) Run(args []string) int { - var moduleDepth int args, err := c.Meta.process(args, false) if err != nil { @@ -29,7 +28,7 @@ func (c *ShowCommand) Run(args []string) int { } cmdFlags := flag.NewFlagSet("show", flag.ContinueOnError) - c.addModuleDepthFlag(cmdFlags, &moduleDepth) + cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } if err := cmdFlags.Parse(args); err != nil { return 1 @@ -121,7 +120,6 @@ func (c *ShowCommand) Run(args []string) int { c.Ui.Output(format.State(&format.StateOpts{ State: state, Color: c.Colorize(), - ModuleDepth: moduleDepth, })) return 0 } diff --git a/go.mod b/go.mod index b7a8b1949d..ed1ff8acc7 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,7 @@ module github.com/hashicorp/terraform require ( cloud.google.com/go v0.15.0 + contrib.go.opencensus.io/exporter/stackdriver v0.6.0 // indirect github.com/Azure/azure-sdk-for-go v10.3.0-beta+incompatible github.com/Azure/go-autorest v8.3.1+incompatible github.com/Azure/go-ntlmssp v0.0.0-20170803034930-c92175d54006 // indirect @@ -19,7 +20,6 @@ require ( github.com/armon/go-radix v0.0.0-20160115234725-4239b77079c7 // indirect github.com/aws/aws-sdk-go v1.12.75 github.com/beevik/etree v0.0.0-20171015221209-af219c0c7ea1 // indirect - github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.0.0-20161015143505-675b82c74c0e // indirect github.com/blang/semver v0.0.0-20170202183821-4a1e882c79dc @@ -94,7 +94,6 @@ require ( github.com/mattn/go-colorable v0.0.0-20160220075935-9cbef7c35391 github.com/mattn/go-isatty v0.0.0-20161123143637-30a891c33c7c // indirect github.com/mattn/go-shellwords v1.0.1 - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/miekg/dns v1.0.8 // indirect github.com/mitchellh/cli v0.0.0-20171129193617-33edc47170b5 github.com/mitchellh/colorstring v0.0.0-20150917214807-8631ce90f286 @@ -116,10 +115,6 @@ require ( github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c // indirect github.com/pkg/errors v0.8.0 // indirect github.com/posener/complete v0.0.0-20171219111128-6bee943216c8 - github.com/prometheus/client_golang v0.8.0 // indirect - github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect - github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e // indirect - github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 // indirect github.com/satori/go.uuid v0.0.0-20160927100844-b061729afc07 // indirect github.com/satori/uuid v0.0.0-20160927100844-b061729afc07 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect @@ -139,15 +134,13 @@ require ( github.com/xanzy/ssh-agent v0.1.0 github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18 // indirect github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557 - github.com/zclconf/go-cty v0.0.0-20180925180032-d9b87d891d0b - golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b - golang.org/x/net v0.0.0-20180925072008-f04abc6bdfa7 - golang.org/x/oauth2 v0.0.0-20170928010508-bb50c06baba3 - golang.org/x/sys v0.0.0-20180925112736-b09afc3d579e // indirect + github.com/zclconf/go-cty v0.0.0-20180907002636-07dee8a1cfd4 + go.opencensus.io v0.17.0 // indirect + golang.org/x/crypto v0.0.0-20180816225734-aabede6cba87 + golang.org/x/net v0.0.0-20180906233101-161cd47e91fd + golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 // indirect - google.golang.org/api v0.0.0-20171005000305-7a7376eff6a5 - google.golang.org/appengine v1.2.0 // indirect - google.golang.org/genproto v0.0.0-20171002232614-f676e0f3ac63 // indirect + google.golang.org/api v0.0.0-20180921000521-920bb1beccf7 google.golang.org/grpc v1.14.0 gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect gopkg.in/fsnotify.v1 v1.4.7 // indirect diff --git a/go.sum b/go.sum index 5e1bb48882..cbab66f0f8 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,8 @@ cloud.google.com/go v0.15.0 h1:/e2wXYguItvFu4fJCvhMRPIwwrimuUxI+aCVx/ahLjg= cloud.google.com/go v0.15.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +contrib.go.opencensus.io/exporter/stackdriver v0.6.0 h1:U0FQWsZU3aO8W+BrZc88T8fdd24qe3Phawa9V9oaVUE= +contrib.go.opencensus.io/exporter/stackdriver v0.6.0/go.mod h1:QeFzMJDAw8TXt5+aRaSuE8l5BwaMIOIlaVkBOPRuMuw= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/Azure/azure-sdk-for-go v10.3.0-beta+incompatible h1:TP+nmGmOP7psi7CvIq/1pCliRBRj73vmMTDjaPrTnr8= github.com/Azure/azure-sdk-for-go v10.3.0-beta+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-autorest v8.3.1+incompatible h1:1+jMCOJcCh3GmI7FGJVOo8AlfPWDyjS7fLbbkZGzEGY= @@ -239,6 +242,7 @@ github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.1 h1:PZSj/UFNaVp3KxrzHOcS7oyuWA7LoOY/77yCTEFu21U= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/packer-community/winrmcp v0.0.0-20180102160824-81144009af58 h1:m3CEgv3ah1Rhy82L+c0QG/U3VyY1UsvsIdkh0/rU97Y= github.com/packer-community/winrmcp v0.0.0-20180102160824-81144009af58/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= @@ -305,8 +309,12 @@ github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557 h1:Jpn2j6wHkC9wJv5i github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/zclconf/go-cty v0.0.0-20180815031001-58bb2bc0302a h1:x70ZZ4caA8eY4abjpcCnf6uvIPY3cpgRFrXE47JF4Sc= github.com/zclconf/go-cty v0.0.0-20180815031001-58bb2bc0302a/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= -github.com/zclconf/go-cty v0.0.0-20180925180032-d9b87d891d0b h1:9rQAtgrPBuyPjmPEcx4pqJs6D+u41FYbbVE/hhdsrtk= -github.com/zclconf/go-cty v0.0.0-20180925180032-d9b87d891d0b/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= +github.com/zclconf/go-cty v0.0.0-20180831220647-752f6a689f5e h1:6R+foJ4aZJ3r0v9GajwCV7WuYCJ4J0H2ySXGUs093qc= +github.com/zclconf/go-cty v0.0.0-20180831220647-752f6a689f5e/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= +github.com/zclconf/go-cty v0.0.0-20180907002636-07dee8a1cfd4 h1:C02D0gjAVFMKqFUaZvaZK2YWGK1HAQwVTZWDAENYDjA= +github.com/zclconf/go-cty v0.0.0-20180907002636-07dee8a1cfd4/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= +go.opencensus.io v0.17.0 h1:2Cu88MYg+1LU+WVD+NWwYhyP0kKgRlN9QjWGaX0jKTE= +go.opencensus.io v0.17.0/go.mod h1:mp1VrMQxhlqqDpKvH4UcQUa4YwlzNmymAjPrDdfxNpI= golang.org/x/crypto v0.0.0-20180816225734-aabede6cba87 h1:gCHhzI+1R9peHIMyiWVxoVaWlk1cYK7VThX5ptLtbXY= golang.org/x/crypto v0.0.0-20180816225734-aabede6cba87/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b h1:2b9XGzhjiYsYPnKXoEfL7klWZQIt8IfyRCz62gCqqlQ= @@ -318,24 +326,30 @@ golang.org/x/net v0.0.0-20180925072008-f04abc6bdfa7 h1:zKzVgSQ8WOSHzD7I4k8LQjrHU golang.org/x/net v0.0.0-20180925072008-f04abc6bdfa7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/oauth2 v0.0.0-20170928010508-bb50c06baba3 h1:YGx0PRKSN/2n/OcdFycCC0JUA/Ln+i5lPcN8VoNDus0= golang.org/x/oauth2 v0.0.0-20170928010508-bb50c06baba3/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c h1:uHnKXcvx6SNkuwC+nrzxkJ+TpPwZOtumbhWrrOYN5YA= golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180925112736-b09afc3d579e h1:LSlw/Dbj0MkNvPYAAkGinYmGliq+aqS7eKPYlE4oWC4= -golang.org/x/sys v0.0.0-20180925112736-b09afc3d579e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 h1:+DCIGbF/swA92ohVg0//6X2IVY3KZs6p9mix0ziNYJM= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= google.golang.org/api v0.0.0-20171005000305-7a7376eff6a5 h1:PDkJGYjSvxJyevtZRGmBSO+HjbIKuqYEEc8gB51or4o= google.golang.org/api v0.0.0-20171005000305-7a7376eff6a5/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20180921000521-920bb1beccf7 h1:XKT3Wlpn+o6Car1ot74Z4R+R9CeRfITCLZb0Q9/mpx4= +google.golang.org/api v0.0.0-20180921000521-920bb1beccf7/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0 h1:S0iUepdCWODXRvtE+gcRDd15L+k+k1AiHlMiMjefH24= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20171002232614-f676e0f3ac63 h1:yNBw5bwywOTguAu+h6SkCUaWdEZ7ZXgfiwb2YTN1eQw= google.golang.org/genproto v0.0.0-20171002232614-f676e0f3ac63/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/grpc v1.14.0 h1:ArxJuB1NWfPY6r9Gp9gqwplT0Ge7nqv9msgu03lHLmo= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=