From c9b3c362439f996d0c341237a52e293336a32ce6 Mon Sep 17 00:00:00 2001 From: Matt Butcher Date: Mon, 25 Apr 2016 16:25:25 -0600 Subject: [PATCH] feat(helm): implement 'helm remove' --- _proto/hapi/release/info.proto | 9 ++- _proto/hapi/services/tiller.proto | 16 ++--- cmd/helm/remove.go | 52 +++++++++++++++ cmd/tiller/release_server.go | 48 ++++++++++++-- cmd/tiller/release_server_test.go | 36 +++++++++++ pkg/helm/client.go | 9 +++ pkg/helm/error.go | 1 + pkg/helm/helm.go | 13 +++- pkg/proto/hapi/release/info.pb.go | 19 ++++-- pkg/proto/hapi/services/tiller.pb.go | 95 ++++++++++++++-------------- 10 files changed, 229 insertions(+), 69 deletions(-) create mode 100644 cmd/helm/remove.go diff --git a/_proto/hapi/release/info.proto b/_proto/hapi/release/info.proto index fa8623ee8..382f4acfc 100644 --- a/_proto/hapi/release/info.proto +++ b/_proto/hapi/release/info.proto @@ -12,9 +12,12 @@ option go_package = "release"; // // message Info { - Status status = 1; + Status status = 1; - google.protobuf.Timestamp first_deployed = 2; + google.protobuf.Timestamp first_deployed = 2; - google.protobuf.Timestamp last_deployed = 3; + google.protobuf.Timestamp last_deployed = 3; + + // Deleted tracks when this object was deleted. + google.protobuf.Timestamp deleted = 4; } diff --git a/_proto/hapi/services/tiller.proto b/_proto/hapi/services/tiller.proto index 581fe659f..9768ca737 100644 --- a/_proto/hapi/services/tiller.proto +++ b/_proto/hapi/services/tiller.proto @@ -184,18 +184,14 @@ message InstallReleaseResponse { hapi.release.Release release = 1; } -// -// UninstallReleaseRequest: -// -// TODO -// +// UninstallReleaseRequest represents a request to uninstall a named release. message UninstallReleaseRequest { + // Name is the name of the release to delete. + string name = 1; } -// -// UninstallReleaseResponse: -// -// TODO -// +// UninstallReleaseResponse represents a successful response to an uninstall request. message UninstallReleaseResponse { + // Release is the release that was marked deleted. + hapi.release.Release release = 1; } diff --git a/cmd/helm/remove.go b/cmd/helm/remove.go new file mode 100644 index 000000000..cdaf93b13 --- /dev/null +++ b/cmd/helm/remove.go @@ -0,0 +1,52 @@ +package main + +import ( + "errors" + "fmt" + + "github.com/deis/tiller/pkg/helm" + "github.com/spf13/cobra" +) + +const removeDesc = ` +This command takes a release name, and then deletes the release from Kubernetes. +It removes all of the resources associated with the last release of the chart. + +Use the '--dry-run' flag to see which releases will be deleted without actually +deleting them. +` + +var removeDryRun bool + +var removeCommand = &cobra.Command{ + Use: "remove [flags] RELEASE_NAME", + Aliases: []string{"rm"}, + SuggestFor: []string{"delete", "del"}, + Short: "Given a release name, remove the release from Kubernetes", + Long: removeDesc, + RunE: rmRelease, +} + +func init() { + RootCommand.AddCommand(removeCommand) + removeCommand.Flags().BoolVar(&removeDryRun, "dry-run", false, "Simulate action, but don't actually do it.") +} + +func rmRelease(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return errors.New("Command 'remove' requires a release name.") + } + + // TODO: Handle dry run use case. + if removeDryRun { + fmt.Printf("Deleting %s\n", args[0]) + return nil + } + + _, err := helm.UninstallRelease(args[0]) + if err != nil { + return err + } + + return nil +} diff --git a/cmd/tiller/release_server.go b/cmd/tiller/release_server.go index dba45f1c9..a9ad6edff 100644 --- a/cmd/tiller/release_server.go +++ b/cmd/tiller/release_server.go @@ -4,10 +4,12 @@ import ( "bytes" "errors" "log" + "time" "github.com/deis/tiller/cmd/tiller/environment" "github.com/deis/tiller/pkg/proto/hapi/release" "github.com/deis/tiller/pkg/proto/hapi/services" + "github.com/golang/protobuf/ptypes/timestamp" "github.com/technosophos/moniker" ctx "golang.org/x/net/context" ) @@ -26,7 +28,10 @@ type releaseServer struct { var ( // errNotImplemented is a temporary error for uninmplemented callbacks. errNotImplemented = errors.New("not implemented") - errMissingChart = errors.New("no chart provided") + // errMissingChart indicates that a chart was not provided. + errMissingChart = errors.New("no chart provided") + // errMissingRelease indicates that a release (name) was not provided. + errMissingRelease = errors.New("no release provided") ) func (s *releaseServer) ListReleases(req *services.ListReleasesRequest, stream services.ReleaseService_ListReleasesServer) error { @@ -53,7 +58,8 @@ func (s *releaseServer) InstallRelease(c ctx.Context, req *services.InstallRelea // We should probably make a name generator part of the Environment. namer := moniker.New() // TODO: Make sure this is unique. - name := namer.Name() + name := namer.NameSep("-") + ts := now() // Render the templates files, err := s.env.EngineYard.Default().Render(req.Chart, req.Values) @@ -77,7 +83,9 @@ func (s *releaseServer) InstallRelease(c ctx.Context, req *services.InstallRelea Chart: req.Chart, Config: req.Values, Info: &release.Info{ - Status: &release.Status{Code: release.Status_UNKNOWN}, + FirstDeployed: ts, + LastDeployed: ts, + Status: &release.Status{Code: release.Status_UNKNOWN}, }, Manifest: b.String(), } @@ -94,6 +102,38 @@ func (s *releaseServer) InstallRelease(c ctx.Context, req *services.InstallRelea return &services.InstallReleaseResponse{Release: r}, nil } +func now() *timestamp.Timestamp { + t := time.Now() + ts := ×tamp.Timestamp{ + Seconds: t.Unix(), + Nanos: int32(t.Nanosecond()), + } + return ts +} + func (s *releaseServer) UninstallRelease(c ctx.Context, req *services.UninstallReleaseRequest) (*services.UninstallReleaseResponse, error) { - return nil, errNotImplemented + if req.Name == "" { + log.Printf("uninstall: Release not found: %s", req.Name) + return nil, errMissingRelease + } + + rel, err := s.env.Releases.Read(req.Name) + if err != nil { + log.Printf("uninstall: Release not loaded: %s", req.Name) + return nil, err + } + + log.Printf("uninstall: Deleting %s", req.Name) + rel.Info.Status.Code = release.Status_DELETED + rel.Info.Deleted = now() + + // TODO: Once KubeClient is ready, delete the resources. + log.Println("WARNING: Currently not deleting resources from k8s") + + if err := s.env.Releases.Update(rel); err != nil { + log.Printf("uninstall: Failed to store updated release: %s", err) + } + + res := services.UninstallReleaseResponse{Release: rel} + return &res, nil } diff --git a/cmd/tiller/release_server_test.go b/cmd/tiller/release_server_test.go index c09736341..878bbb9b5 100644 --- a/cmd/tiller/release_server_test.go +++ b/cmd/tiller/release_server_test.go @@ -6,6 +6,7 @@ import ( "github.com/deis/tiller/cmd/tiller/environment" "github.com/deis/tiller/pkg/proto/hapi/chart" + "github.com/deis/tiller/pkg/proto/hapi/release" "github.com/deis/tiller/pkg/proto/hapi/services" "github.com/deis/tiller/pkg/storage" "golang.org/x/net/context" @@ -97,6 +98,41 @@ func TestInstallReleaseDryRun(t *testing.T) { } } +func TestUninstallRelease(t *testing.T) { + c := context.Background() + rs := rsFixture() + rs.env.Releases.Create(&release.Release{ + Name: "angry-panda", + Info: &release.Info{ + FirstDeployed: now(), + Status: &release.Status{ + Code: release.Status_DEPLOYED, + }, + }, + }) + + req := &services.UninstallReleaseRequest{ + Name: "angry-panda", + } + + res, err := rs.UninstallRelease(c, req) + if err != nil { + t.Errorf("Failed uninstall: %s", err) + } + + if res.Release.Name != "angry-panda" { + t.Errorf("Expected angry-panda, got %q", res.Release.Name) + } + + if res.Release.Info.Status.Code != release.Status_DELETED { + t.Errorf("Expected status code to be DELETED, got %d", res.Release.Info.Status.Code) + } + + if res.Release.Info.Deleted.Seconds <= 0 { + t.Errorf("Expected valid UNIX date, got %d", res.Release.Info.Deleted.Seconds) + } +} + func mockEnvironment() *environment.Environment { e := environment.New() e.Releases = storage.NewMemory() diff --git a/pkg/helm/client.go b/pkg/helm/client.go index a68a1efb4..69c6b4535 100644 --- a/pkg/helm/client.go +++ b/pkg/helm/client.go @@ -29,6 +29,15 @@ func (c *client) install(req *services.InstallReleaseRequest) (res *services.Ins return c.impl.InstallRelease(context.TODO(), req, c.cfg.CallOpts()...) } +func (c *client) uninstall(req *services.UninstallReleaseRequest) (*services.UninstallReleaseResponse, error) { + if err := c.dial(); err != nil { + return nil, err + } + defer c.Close() + + return c.impl.UninstallRelease(context.TODO(), req, c.cfg.CallOpts()...) +} + func (c *client) Close() error { return c.conn.Close() } diff --git a/pkg/helm/error.go b/pkg/helm/error.go index 8f5a02499..b8d72a2c4 100644 --- a/pkg/helm/error.go +++ b/pkg/helm/error.go @@ -8,6 +8,7 @@ const ( errMissingValues = Error("missing chart values") ) +// Error represents a Helm client error. type Error string func (e Error) Error() string { diff --git a/pkg/helm/helm.go b/pkg/helm/helm.go index 7e535c1d2..963851064 100644 --- a/pkg/helm/helm.go +++ b/pkg/helm/helm.go @@ -6,31 +6,42 @@ import ( "github.com/deis/tiller/pkg/proto/hapi/services" ) +// Config defines a gRPC client's configuration. var Config = &config{ ServAddr: ":44134", Insecure: true, } +// ListReleases lists the current releases. func ListReleases(limit, offset int) (<-chan *services.ListReleasesResponse, error) { return nil, errNotImplemented } +// GetReleaseStatus returns the given release's status. func GetReleaseStatus(name string) (*services.GetReleaseStatusResponse, error) { return nil, errNotImplemented } +// GetReleaseContent returns the configuration for a given release. func GetReleaseContent(name string) (*services.GetReleaseContentResponse, error) { return nil, errNotImplemented } +// UpdateRelease updates a release to a new/different chart. +// TODO: This must take more than just name for an arg. func UpdateRelease(name string) (*services.UpdateReleaseResponse, error) { return nil, errNotImplemented } +// UninstallRelease uninstalls a named release and returns the response. func UninstallRelease(name string) (*services.UninstallReleaseResponse, error) { - return nil, errNotImplemented + u := &services.UninstallReleaseRequest{ + Name: name, + } + return Config.client().uninstall(u) } +// InstallRelease installs a new chart and returns the release response. func InstallRelease(ch *chart.Chart) (res *services.InstallReleaseResponse, err error) { chpb := new(chartpb.Chart) diff --git a/pkg/proto/hapi/release/info.pb.go b/pkg/proto/hapi/release/info.pb.go index 72c3225c5..4c3d8ed7c 100644 --- a/pkg/proto/hapi/release/info.pb.go +++ b/pkg/proto/hapi/release/info.pb.go @@ -39,6 +39,8 @@ type Info struct { Status *Status `protobuf:"bytes,1,opt,name=status" json:"status,omitempty"` FirstDeployed *google_protobuf.Timestamp `protobuf:"bytes,2,opt,name=first_deployed,json=firstDeployed" json:"first_deployed,omitempty"` LastDeployed *google_protobuf.Timestamp `protobuf:"bytes,3,opt,name=last_deployed,json=lastDeployed" json:"last_deployed,omitempty"` + // Deleted tracks when this object was deleted. + Deleted *google_protobuf.Timestamp `protobuf:"bytes,4,opt,name=deleted" json:"deleted,omitempty"` } func (m *Info) Reset() { *m = Info{} } @@ -67,23 +69,30 @@ func (m *Info) GetLastDeployed() *google_protobuf.Timestamp { return nil } +func (m *Info) GetDeleted() *google_protobuf.Timestamp { + if m != nil { + return m.Deleted + } + return nil +} + func init() { proto.RegisterType((*Info)(nil), "hapi.release.Info") } var fileDescriptor0 = []byte{ - // 194 bytes of a gzipped FileDescriptorProto + // 208 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x12, 0xcf, 0x48, 0x2c, 0xc8, 0xd4, 0x2f, 0x4a, 0xcd, 0x49, 0x4d, 0x2c, 0x4e, 0xd5, 0xcf, 0xcc, 0x4b, 0xcb, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x01, 0x49, 0xe8, 0x41, 0x25, 0xa4, 0xe4, 0xd3, 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0xc1, 0x72, 0x49, 0xa5, 0x69, 0xfa, 0x25, 0x99, 0xb9, 0xa9, 0xc5, 0x25, 0x89, 0xb9, 0x05, 0x10, 0xe5, 0x52, 0x92, 0x28, 0xe6, 0x00, 0x65, 0x4a, 0x4a, 0x8b, 0x21, 0x52, 0x4a, - 0x3b, 0x18, 0xb9, 0x58, 0x3c, 0x81, 0x06, 0x0b, 0xe9, 0x70, 0xb1, 0x41, 0x24, 0x24, 0x18, 0x15, + 0xef, 0x18, 0xb9, 0x58, 0x3c, 0x81, 0x06, 0x0b, 0xe9, 0x70, 0xb1, 0x41, 0x24, 0x24, 0x18, 0x15, 0x18, 0x35, 0xb8, 0x8d, 0x44, 0xf4, 0x90, 0xed, 0xd0, 0x0b, 0x06, 0xcb, 0x05, 0x41, 0xd5, 0x08, 0x39, 0x72, 0xf1, 0xa5, 0x65, 0x16, 0x15, 0x97, 0xc4, 0xa7, 0xa4, 0x16, 0xe4, 0xe4, 0x57, 0xa6, 0xa6, 0x48, 0x30, 0x81, 0x75, 0x49, 0xe9, 0x41, 0xdc, 0xa2, 0x07, 0x73, 0x8b, 0x5e, 0x08, 0xcc, 0x2d, 0x41, 0xbc, 0x60, 0x1d, 0x2e, 0x50, 0x0d, 0x42, 0xf6, 0x5c, 0xbc, 0x39, 0x89, 0xc8, 0x26, - 0x30, 0x13, 0x34, 0x81, 0x07, 0xa4, 0x01, 0x66, 0x80, 0x13, 0x67, 0x14, 0x3b, 0xd4, 0x75, 0x49, - 0x6c, 0x60, 0xc5, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfb, 0xae, 0xa9, 0x99, 0x31, 0x01, - 0x00, 0x00, + 0x30, 0x13, 0x34, 0x81, 0x07, 0xa4, 0x01, 0x6e, 0x80, 0x09, 0x17, 0x7b, 0x0a, 0xd0, 0x75, 0x25, + 0x40, 0xad, 0x2c, 0x04, 0xb5, 0xc2, 0x94, 0x3a, 0x71, 0x46, 0xb1, 0x43, 0xfd, 0x94, 0xc4, 0x06, + 0x56, 0x67, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xeb, 0x9d, 0xa1, 0xf8, 0x67, 0x01, 0x00, 0x00, } diff --git a/pkg/proto/hapi/services/tiller.pb.go b/pkg/proto/hapi/services/tiller.pb.go index e8922e10a..5c19915ce 100644 --- a/pkg/proto/hapi/services/tiller.pb.go +++ b/pkg/proto/hapi/services/tiller.pb.go @@ -225,12 +225,10 @@ func (m *InstallReleaseResponse) GetRelease() *hapi_release2.Release { return nil } -// -// UninstallReleaseRequest: -// -// TODO -// +// UninstallReleaseRequest represents a request to uninstall a named release. type UninstallReleaseRequest struct { + // Name is the name of the release to delete. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` } func (m *UninstallReleaseRequest) Reset() { *m = UninstallReleaseRequest{} } @@ -238,12 +236,10 @@ func (m *UninstallReleaseRequest) String() string { return proto.Comp func (*UninstallReleaseRequest) ProtoMessage() {} func (*UninstallReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{10} } -// -// UninstallReleaseResponse: -// -// TODO -// +// UninstallReleaseResponse represents a successful response to an uninstall request. type UninstallReleaseResponse struct { + // Release is the release that was marked deleted. + Release *hapi_release2.Release `protobuf:"bytes,1,opt,name=release" json:"release,omitempty"` } func (m *UninstallReleaseResponse) Reset() { *m = UninstallReleaseResponse{} } @@ -251,6 +247,13 @@ func (m *UninstallReleaseResponse) String() string { return proto.Com func (*UninstallReleaseResponse) ProtoMessage() {} func (*UninstallReleaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{11} } +func (m *UninstallReleaseResponse) GetRelease() *hapi_release2.Release { + if m != nil { + return m.Release + } + return nil +} + func init() { proto.RegisterType((*ListReleasesRequest)(nil), "hapi.services.tiller.ListReleasesRequest") proto.RegisterType((*ListReleasesResponse)(nil), "hapi.services.tiller.ListReleasesResponse") @@ -541,40 +544,40 @@ var _ReleaseService_serviceDesc = grpc.ServiceDesc{ } var fileDescriptor1 = []byte{ - // 550 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x55, 0x4d, 0x6f, 0xd3, 0x40, - 0x10, 0xad, 0x09, 0x4d, 0xc3, 0xa4, 0x8d, 0xe8, 0xe2, 0xc4, 0x8e, 0x4f, 0x65, 0x2f, 0x94, 0x02, - 0x0e, 0x84, 0x23, 0x70, 0x21, 0x07, 0x54, 0xa9, 0xe2, 0x60, 0xd4, 0x0b, 0x97, 0xca, 0xa4, 0x1b, - 0xba, 0xc8, 0x59, 0x07, 0xef, 0x3a, 0x12, 0xdc, 0x39, 0xf2, 0x7f, 0xf8, 0x79, 0xd8, 0xfb, 0x61, - 0xc5, 0x89, 0x57, 0x31, 0x5c, 0x1c, 0xed, 0xbe, 0x37, 0xf3, 0x66, 0x66, 0xdf, 0x28, 0x10, 0xdc, - 0xc5, 0x2b, 0x3a, 0xe1, 0x24, 0x5b, 0xd3, 0x39, 0xe1, 0x13, 0x41, 0x93, 0x84, 0x64, 0xe1, 0x2a, - 0x4b, 0x45, 0x8a, 0xdc, 0x12, 0x0b, 0x0d, 0x16, 0x2a, 0x2c, 0x18, 0xc9, 0x88, 0xf9, 0x5d, 0x9c, - 0x09, 0xf5, 0x55, 0xec, 0xc0, 0xdb, 0xbc, 0x4f, 0xd9, 0x82, 0x7e, 0xd5, 0x80, 0x92, 0xc8, 0x48, - 0x42, 0x62, 0x4e, 0xcc, 0xaf, 0xc6, 0xc6, 0x35, 0x8c, 0x8b, 0x58, 0xe4, 0x5c, 0x41, 0x78, 0x06, - 0x8f, 0xae, 0x28, 0x17, 0x91, 0xc2, 0x78, 0x44, 0xbe, 0xe7, 0x84, 0x0b, 0xe4, 0xc2, 0x61, 0x42, - 0x97, 0x54, 0xf8, 0xce, 0x99, 0x73, 0xde, 0x89, 0xd4, 0x01, 0x8d, 0xa0, 0x9b, 0x2e, 0x16, 0x9c, - 0x08, 0xff, 0x9e, 0xbc, 0xd6, 0x27, 0xfc, 0xdb, 0x01, 0xb7, 0x9e, 0x85, 0xaf, 0x52, 0xc6, 0x49, - 0x99, 0x66, 0x9e, 0xe6, 0xac, 0x4a, 0x23, 0x0f, 0xb6, 0x34, 0x25, 0x5b, 0xa4, 0x22, 0x4e, 0xfc, - 0x8e, 0x62, 0xcb, 0x03, 0x7a, 0x05, 0x3d, 0x5d, 0x39, 0xf7, 0xef, 0x9f, 0x75, 0xce, 0xfb, 0xd3, - 0x61, 0x28, 0x47, 0x66, 0x7a, 0xd4, 0xaa, 0x51, 0x45, 0xc3, 0x6f, 0xc1, 0xfb, 0x40, 0x4c, 0x35, - 0x9f, 0x64, 0xbb, 0xa6, 0xb1, 0xc7, 0x70, 0xac, 0x69, 0x37, 0x2c, 0x5e, 0x12, 0x59, 0xd8, 0x83, - 0xa8, 0xaf, 0xef, 0x3e, 0x16, 0x57, 0xf8, 0x27, 0xf8, 0xbb, 0xd1, 0xba, 0xa1, 0xfd, 0xe1, 0xe8, - 0x0d, 0x0c, 0x0c, 0x45, 0x4d, 0x5a, 0x76, 0xd9, 0x9f, 0xba, 0xf5, 0xaa, 0x75, 0xe2, 0x93, 0x6c, - 0x53, 0x07, 0xbf, 0xdb, 0xd4, 0x9e, 0xa5, 0x4c, 0x10, 0x26, 0xfe, 0xa1, 0xf4, 0x2b, 0x18, 0x37, - 0x84, 0xeb, 0xda, 0x27, 0x70, 0xa4, 0xb9, 0x32, 0xd4, 0x3a, 0x47, 0xc3, 0xc2, 0x23, 0x70, 0xaf, - 0x57, 0xb7, 0xb1, 0x20, 0x06, 0x51, 0x85, 0x60, 0x0f, 0x86, 0x5b, 0xf7, 0x4a, 0x01, 0xff, 0x72, - 0x60, 0x78, 0xc9, 0x8a, 0xae, 0x93, 0xa4, 0x1e, 0x82, 0x9e, 0x14, 0x46, 0x28, 0x3d, 0xab, 0x95, - 0x4f, 0x95, 0xb2, 0x32, 0xf6, 0xac, 0xfc, 0x46, 0x0a, 0x47, 0x17, 0xd0, 0x5d, 0xc7, 0x49, 0x11, - 0xa3, 0xa7, 0x86, 0x6a, 0x4c, 0x69, 0xf8, 0x48, 0x33, 0x90, 0x07, 0x47, 0xb7, 0xd9, 0x8f, 0x9b, - 0x2c, 0x67, 0xd2, 0x31, 0xbd, 0xa8, 0x5b, 0x1c, 0xa3, 0x9c, 0xe1, 0x4b, 0x18, 0x6d, 0x97, 0xf1, - 0xbf, 0x33, 0x18, 0x83, 0x77, 0xcd, 0x68, 0x53, 0x4f, 0x38, 0x00, 0x7f, 0x17, 0x52, 0x3a, 0xd3, - 0x3f, 0x87, 0x30, 0x30, 0x0e, 0x52, 0x9b, 0x8d, 0x28, 0x1c, 0x6f, 0xee, 0x08, 0x7a, 0x1a, 0x36, - 0x2d, 0x7e, 0xd8, 0xb0, 0x8d, 0xc1, 0x45, 0x1b, 0xaa, 0x7e, 0x83, 0x83, 0x97, 0x0e, 0xe2, 0xf0, - 0x70, 0xdb, 0xc1, 0xe8, 0x45, 0x73, 0x0e, 0xcb, 0x9e, 0x04, 0x61, 0x5b, 0xba, 0x91, 0x45, 0x6b, - 0x38, 0xdd, 0xf1, 0x1e, 0xda, 0x9b, 0xa6, 0xee, 0xf1, 0x60, 0xd2, 0x9a, 0x5f, 0xe9, 0x7e, 0x83, - 0x93, 0x9a, 0x1b, 0x91, 0x65, 0x5a, 0x4d, 0x56, 0x0e, 0x9e, 0xb5, 0xe2, 0x56, 0x5a, 0x4b, 0x18, - 0xd4, 0x8d, 0x85, 0x2c, 0x09, 0x1a, 0xb7, 0x20, 0x78, 0xde, 0x8e, 0x5c, 0xc9, 0x15, 0xef, 0xb8, - 0xed, 0x30, 0xdb, 0x3b, 0x5a, 0x4c, 0x6a, 0x7b, 0x47, 0x9b, 0x71, 0xf1, 0xc1, 0x7b, 0xf8, 0xdc, - 0x33, 0xec, 0x2f, 0x5d, 0xf9, 0x27, 0xf1, 0xfa, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0x65, - 0x97, 0x54, 0xc0, 0x06, 0x00, 0x00, + // 558 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x55, 0x3d, 0x73, 0xd3, 0x40, + 0x10, 0x8d, 0x71, 0xe2, 0x98, 0x75, 0xe2, 0x21, 0x8b, 0x6c, 0x29, 0xaa, 0xc2, 0x35, 0x84, 0x40, + 0x64, 0x30, 0x25, 0xd0, 0xe0, 0x82, 0xc9, 0x90, 0xa1, 0x10, 0x93, 0x86, 0x26, 0x23, 0x9c, 0x33, + 0x11, 0x23, 0x9f, 0x8c, 0xee, 0xe4, 0x19, 0xe8, 0x29, 0xf9, 0x3f, 0xfc, 0x3c, 0xa4, 0xfb, 0xd0, + 0x48, 0xb6, 0x34, 0x11, 0x69, 0x64, 0xdf, 0xed, 0xdb, 0x7d, 0xfb, 0xf1, 0x56, 0x02, 0xf7, 0x36, + 0x58, 0x85, 0x13, 0x4e, 0x93, 0x75, 0x38, 0xa7, 0x7c, 0x22, 0xc2, 0x28, 0xa2, 0x89, 0xb7, 0x4a, + 0x62, 0x11, 0xa3, 0x95, 0xdb, 0x3c, 0x63, 0xf3, 0x94, 0xcd, 0x1d, 0x4b, 0x8f, 0xf9, 0x6d, 0x90, + 0x08, 0xf5, 0x54, 0x68, 0xd7, 0x2e, 0xdf, 0xc7, 0x6c, 0x11, 0x7e, 0xd3, 0x06, 0x45, 0x91, 0xd0, + 0x88, 0x06, 0x9c, 0x9a, 0x5f, 0x6d, 0x3b, 0xae, 0xd8, 0xb8, 0x08, 0x44, 0xca, 0x95, 0x89, 0xcc, + 0xe0, 0xf1, 0x65, 0xc8, 0x85, 0xaf, 0x6c, 0xdc, 0xa7, 0x3f, 0x52, 0xca, 0x05, 0x5a, 0xb0, 0x17, + 0x85, 0xcb, 0x50, 0x38, 0x9d, 0x93, 0xce, 0x69, 0xd7, 0x57, 0x07, 0x1c, 0x43, 0x2f, 0x5e, 0x2c, + 0x38, 0x15, 0xce, 0x03, 0x79, 0xad, 0x4f, 0xe4, 0x4f, 0x07, 0xac, 0x6a, 0x14, 0xbe, 0x8a, 0x19, + 0xa7, 0x79, 0x98, 0x79, 0x9c, 0xb2, 0x22, 0x8c, 0x3c, 0x34, 0x85, 0xc9, 0xd1, 0x22, 0x16, 0x41, + 0xe4, 0x74, 0x15, 0x5a, 0x1e, 0xf0, 0x15, 0xf4, 0x75, 0xe6, 0xdc, 0xd9, 0x3d, 0xe9, 0x9e, 0x0e, + 0xa6, 0x23, 0x4f, 0xb6, 0xcc, 0xd4, 0xa8, 0x59, 0xfd, 0x02, 0x46, 0xde, 0x82, 0xfd, 0x81, 0x9a, + 0x6c, 0x3e, 0xcb, 0x72, 0x4d, 0x61, 0x4f, 0xe0, 0x40, 0xc3, 0xae, 0x59, 0xb0, 0xa4, 0x32, 0xb1, + 0x87, 0xfe, 0x40, 0xdf, 0x7d, 0xca, 0xae, 0xc8, 0x2f, 0x70, 0xb6, 0xbd, 0x75, 0x41, 0x77, 0xbb, + 0xe3, 0x1b, 0x18, 0x1a, 0x88, 0xea, 0xb4, 0xac, 0x72, 0x30, 0xb5, 0xaa, 0x59, 0xeb, 0xc0, 0x87, + 0x49, 0x99, 0x87, 0xbc, 0x2b, 0x73, 0xcf, 0x62, 0x26, 0x28, 0x13, 0xff, 0x91, 0xfa, 0x25, 0x1c, + 0xd7, 0xb8, 0xeb, 0xdc, 0x27, 0xb0, 0xaf, 0xb1, 0xd2, 0xb5, 0xb1, 0x8f, 0x06, 0x45, 0xc6, 0x60, + 0x5d, 0xad, 0x6e, 0x02, 0x41, 0x8d, 0x45, 0x25, 0x42, 0x6c, 0x18, 0x6d, 0xdc, 0x2b, 0x06, 0xf2, + 0xbb, 0x03, 0xa3, 0x0b, 0x96, 0x55, 0x1d, 0x45, 0x55, 0x17, 0x7c, 0x9a, 0x09, 0x21, 0xd7, 0xac, + 0x66, 0x3e, 0x52, 0xcc, 0x4a, 0xd8, 0xb3, 0xfc, 0xe9, 0x2b, 0x3b, 0x9e, 0x41, 0x6f, 0x1d, 0x44, + 0x99, 0x8f, 0xee, 0x1a, 0x56, 0x90, 0x52, 0xf0, 0xbe, 0x46, 0xa0, 0x0d, 0xfb, 0x37, 0xc9, 0xcf, + 0xeb, 0x24, 0x65, 0x52, 0x31, 0x7d, 0xbf, 0x97, 0x1d, 0xfd, 0x94, 0x91, 0x0b, 0x18, 0x6f, 0xa6, + 0x71, 0xdf, 0x1e, 0x9c, 0x83, 0x7d, 0xc5, 0xc2, 0xda, 0x9a, 0x10, 0x76, 0x4b, 0x73, 0x90, 0xff, + 0xc9, 0x47, 0x70, 0xb6, 0xe1, 0xf7, 0xe4, 0x9e, 0xfe, 0xdd, 0x83, 0xa1, 0x91, 0xa1, 0x7a, 0x3d, + 0x60, 0x08, 0x07, 0xe5, 0x45, 0xc3, 0x67, 0x5e, 0xdd, 0xdb, 0xc3, 0xab, 0x59, 0x69, 0xf7, 0xac, + 0x0d, 0x54, 0x0f, 0x72, 0xe7, 0x65, 0x07, 0x39, 0x3c, 0xda, 0x5c, 0x03, 0x3c, 0xaf, 0x8f, 0xd1, + 0xb0, 0x6c, 0xae, 0xd7, 0x16, 0x6e, 0x68, 0x71, 0x0d, 0x47, 0x5b, 0x02, 0xc6, 0x3b, 0xc3, 0x54, + 0x17, 0xc5, 0x9d, 0xb4, 0xc6, 0x17, 0xbc, 0xdf, 0xe1, 0xb0, 0x22, 0x69, 0x6c, 0xe8, 0x56, 0xdd, + 0x3e, 0xb8, 0xcf, 0x5b, 0x61, 0x0b, 0xae, 0x25, 0x0c, 0xab, 0xea, 0xc4, 0x86, 0x00, 0xb5, 0xab, + 0xe4, 0xbe, 0x68, 0x07, 0x2e, 0xe8, 0xb2, 0x39, 0x6e, 0x4a, 0xb2, 0x69, 0x8e, 0x0d, 0x4a, 0x6f, + 0x9a, 0x63, 0x93, 0xd2, 0xc9, 0xce, 0x7b, 0xf8, 0xd2, 0x37, 0xe8, 0xaf, 0x3d, 0xf9, 0xa5, 0x79, + 0xfd, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x9f, 0x15, 0x68, 0xaf, 0x05, 0x07, 0x00, 0x00, }