Merge pull request #669 from technosophos/feat/better-list

feat(helm,tiller): improve list output, support filters
pull/707/head
Matt Butcher 9 years ago
commit b243a86f1c

@ -53,26 +53,61 @@ service ReleaseService {
} }
// ListReleasesRequest requests a list of releases. // ListReleasesRequest requests a list of releases.
//
// Releases can be retrieved in chunks by setting limit and offset.
//
// Releases can be sorted according to a few pre-determined sort stategies.
message ListReleasesRequest { message ListReleasesRequest {
// The maximum number of releases to be returned // Limit is the maximum number of releases to be returned.
int64 limit = 1; int64 limit = 1;
// The zero-based offset at which the returned release list begins // Offset is the last release name that was seen. The next listing
int64 offset = 2; // operation will start with the name after this one.
// Example: If list one returns albert, bernie, carl, and sets 'next: dennis'.
// dennis is the offset. Supplying 'dennis' for the next request should
// cause the next batch to return a set of results starting with 'dennis'.
string offset = 2;
// SortBy is the sort field that the ListReleases server should sort data before returning.
ListSort.SortBy sort_by = 3;
// Filter is a regular expression used to filter which releases should be listed.
//
// Anything that matches the regexp will be included in the results.
string filter = 4;
ListSort.SortOrder sort_order = 5;
}
// ListSort defines sorting fields on a release list.
message ListSort{
// SortBy defines sort operations.
enum SortBy {
UNKNOWN = 0;
NAME = 1;
LAST_RELEASED = 2;
}
// SortOrder defines sort orders to augment sorting operations.
enum SortOrder {
ASC = 0;
DESC = 1;
}
} }
// ListReleasesResponse is a list of releases. // ListReleasesResponse is a list of releases.
message ListReleasesResponse { message ListReleasesResponse {
// The expected total number of releases to be returned // Count is the expected total number of releases to be returned.
int64 count = 1; int64 count = 1;
// The zero-based offset at which the list is positioned // Next is the name of the next release. If this is other than an empty
int64 offset = 2; // string, it means there are more results.
string next = 2;
// The total number of queryable releases // Total is the total number of queryable releases.
int64 total = 3; int64 total = 3;
// The resulting releases // Releases is the list of found release objects.
repeated hapi.release.Release releases = 4; repeated hapi.release.Release releases = 4;
} }

@ -2,11 +2,12 @@ package main
import ( import (
"fmt" "fmt"
"sort" "strings"
"github.com/gosuri/uitable" "github.com/gosuri/uitable"
"github.com/kubernetes/helm/pkg/helm" "github.com/kubernetes/helm/pkg/helm"
"github.com/kubernetes/helm/pkg/proto/hapi/release" "github.com/kubernetes/helm/pkg/proto/hapi/release"
"github.com/kubernetes/helm/pkg/proto/hapi/services"
"github.com/kubernetes/helm/pkg/timeconv" "github.com/kubernetes/helm/pkg/timeconv"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -14,54 +15,79 @@ import (
var listHelp = ` var listHelp = `
This command lists all of the currently deployed releases. This command lists all of the currently deployed releases.
By default, items are sorted alphabetically. Sorting is done client-side, so if By default, items are sorted alphabetically. Use the '-d' flag to sort by
the number of releases is less than the setting in '--max', some values will release date.
be omitted, and in no particular lexicographic order.
If an argument is provided, it will be treated as a filter. Filters are
regular expressions (Perl compatible) that are applied to the list of releases.
Only items that match the filter will be returned.
$ helm list -l 'ara[a-z]+'
NAME UPDATED CHART
maudlin-arachnid Mon May 9 16:07:08 2016 alpine-0.1.0
If no results are found, 'helm list' will exit 0, but with no output (or in
the case of '-l', only headers).
By default, up to 256 items may be returned. To limit this, use the '--max' flag.
Setting '--max' to 0 will not return all results. Rather, it will return the
server's default, which may be much higher than 256. Pairing the '--max'
flag with the '--offset' flag allows you to page through results.
` `
var listCommand = &cobra.Command{ var listCommand = &cobra.Command{
Use: "list [flags]", Use: "list [flags] [FILTER]",
Short: "List releases", Short: "List releases",
Long: listHelp, Long: listHelp,
RunE: listCmd, RunE: listCmd,
Aliases: []string{"ls"}, Aliases: []string{"ls"},
} }
var listLong bool var (
var listMax int listLong bool
var listOffset int listMax int
var listByDate bool listOffset string
listByDate bool
listSortDesc bool
)
func init() { func init() {
listCommand.Flags().BoolVarP(&listLong, "long", "l", false, "output long listing format") f := listCommand.Flags()
listCommand.Flags().BoolVarP(&listByDate, "date", "d", false, "sort by release date") f.BoolVarP(&listLong, "long", "l", false, "output long listing format")
listCommand.Flags().IntVarP(&listMax, "max", "m", 256, "maximum number of releases to fetch") f.BoolVarP(&listByDate, "date", "d", false, "sort by release date")
listCommand.Flags().IntVarP(&listOffset, "offset", "o", 0, "offset from start value (zero-indexed)") f.BoolVarP(&listSortDesc, "reverse", "r", false, "reverse the sort order")
f.IntVarP(&listMax, "max", "m", 256, "maximum number of releases to fetch")
f.StringVarP(&listOffset, "offset", "o", "", "the next release name in the list, used to offset from start value")
RootCommand.AddCommand(listCommand) RootCommand.AddCommand(listCommand)
} }
func listCmd(cmd *cobra.Command, args []string) error { func listCmd(cmd *cobra.Command, args []string) error {
var filter string
if len(args) > 0 { if len(args) > 0 {
fmt.Println("TODO: Implement filter.") filter = strings.Join(args, " ")
} }
res, err := helm.ListReleases(listMax, listOffset) sortBy := services.ListSort_NAME
if err != nil { if listByDate {
return prettyError(err) sortBy = services.ListSort_LAST_RELEASED
} }
rels := res.Releases sortOrder := services.ListSort_ASC
if res.Count+res.Offset < res.Total { if listSortDesc {
fmt.Println("Not all values were fetched.") sortOrder = services.ListSort_DESC
} }
if listByDate { res, err := helm.ListReleases(listMax, listOffset, sortBy, sortOrder, filter)
sort.Sort(byDate(rels)) if err != nil {
} else { return prettyError(err)
sort.Sort(byName(rels))
} }
// Purty output, ya'll if res.Next != "" {
fmt.Printf("\tnext: %s", res.Next)
}
rels := res.Releases
if listLong { if listLong {
return formatList(rels) return formatList(rels)
} }
@ -85,26 +111,3 @@ func formatList(rels []*release.Release) error {
return nil return nil
} }
// byName implements the sort.Interface for []*release.Release.
type byName []*release.Release
func (r byName) Len() int {
return len(r)
}
func (r byName) Swap(p, q int) {
r[p], r[q] = r[q], r[p]
}
func (r byName) Less(i, j int) bool {
return r[i].Name < r[j].Name
}
type byDate []*release.Release
func (r byDate) Len() int { return len(r) }
func (r byDate) Swap(p, q int) {
r[p], r[q] = r[q], r[p]
}
func (r byDate) Less(p, q int) bool {
return r[p].Info.LastDeployed.Seconds < r[q].Info.LastDeployed.Seconds
}

@ -5,6 +5,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"log" "log"
"regexp"
"sort"
"github.com/kubernetes/helm/cmd/tiller/environment" "github.com/kubernetes/helm/cmd/tiller/environment"
"github.com/kubernetes/helm/pkg/proto/hapi/release" "github.com/kubernetes/helm/pkg/proto/hapi/release"
@ -47,14 +49,49 @@ func (s *releaseServer) ListReleases(req *services.ListReleasesRequest, stream s
return err return err
} }
if len(req.Filter) != 0 {
rels, err = filterReleases(req.Filter, rels)
if err != nil {
return err
}
}
total := int64(len(rels)) total := int64(len(rels))
switch req.SortBy {
case services.ListSort_NAME:
sort.Sort(byName(rels))
case services.ListSort_LAST_RELEASED:
sort.Sort(byDate(rels))
}
if req.SortOrder == services.ListSort_DESC {
ll := len(rels)
rr := make([]*release.Release, ll)
for i, item := range rels {
rr[ll-i-1] = item
}
rels = rr
}
l := int64(len(rels)) l := int64(len(rels))
if req.Offset > 0 { if req.Offset != "" {
if req.Offset >= l {
return fmt.Errorf("offset %d is outside of range %d", req.Offset, l) i := -1
for ii, cur := range rels {
if cur.Name == req.Offset {
i = ii
}
} }
rels = rels[req.Offset:] if i == -1 {
return fmt.Errorf("offset %q not found", req.Offset)
}
if len(rels) < i {
return fmt.Errorf("no items after %q", req.Offset)
}
rels = rels[i:]
l = int64(len(rels)) l = int64(len(rels))
} }
@ -62,13 +99,15 @@ func (s *releaseServer) ListReleases(req *services.ListReleasesRequest, stream s
req.Limit = ListDefaultLimit req.Limit = ListDefaultLimit
} }
next := ""
if l > req.Limit { if l > req.Limit {
next = rels[req.Limit].Name
rels = rels[0:req.Limit] rels = rels[0:req.Limit]
l = int64(len(rels)) l = int64(len(rels))
} }
res := &services.ListReleasesResponse{ res := &services.ListReleasesResponse{
Offset: 0, Next: next,
Count: l, Count: l,
Total: total, Total: total,
Releases: rels, Releases: rels,
@ -77,6 +116,20 @@ func (s *releaseServer) ListReleases(req *services.ListReleasesRequest, stream s
return nil return nil
} }
func filterReleases(filter string, rels []*release.Release) ([]*release.Release, error) {
preg, err := regexp.Compile(filter)
if err != nil {
return rels, err
}
matches := []*release.Release{}
for _, r := range rels {
if preg.MatchString(r.Name) {
matches = append(matches, r)
}
}
return matches, nil
}
func (s *releaseServer) GetReleaseStatus(c ctx.Context, req *services.GetReleaseStatusRequest) (*services.GetReleaseStatusResponse, error) { func (s *releaseServer) GetReleaseStatus(c ctx.Context, req *services.GetReleaseStatusRequest) (*services.GetReleaseStatusResponse, error) {
if req.Name == "" { if req.Name == "" {
return nil, errMissingRelease return nil, errMissingRelease
@ -224,3 +277,26 @@ func (s *releaseServer) UninstallRelease(c ctx.Context, req *services.UninstallR
res := services.UninstallReleaseResponse{Release: rel} res := services.UninstallReleaseResponse{Release: rel}
return &res, nil return &res, nil
} }
// byName implements the sort.Interface for []*release.Release.
type byName []*release.Release
func (r byName) Len() int {
return len(r)
}
func (r byName) Swap(p, q int) {
r[p], r[q] = r[q], r[p]
}
func (r byName) Less(i, j int) bool {
return r[i].Name < r[j].Name
}
type byDate []*release.Release
func (r byDate) Len() int { return len(r) }
func (r byDate) Swap(p, q int) {
r[p], r[q] = r[q], r[p]
}
func (r byDate) Less(p, q int) bool {
return r[p].Info.LastDeployed.Seconds < r[q].Info.LastDeployed.Seconds
}

@ -208,7 +208,7 @@ func TestListReleases(t *testing.T) {
} }
mrs := &mockListServer{} mrs := &mockListServer{}
if err := rs.ListReleases(&services.ListReleasesRequest{Offset: 0, Limit: 64}, mrs); err != nil { if err := rs.ListReleases(&services.ListReleasesRequest{Offset: "", Limit: 64}, mrs); err != nil {
t.Fatalf("Failed listing: %s", err) t.Fatalf("Failed listing: %s", err)
} }
@ -217,6 +217,86 @@ func TestListReleases(t *testing.T) {
} }
} }
func TestListReleasesSort(t *testing.T) {
rs := rsFixture()
// Put them in by reverse order so that the mock doesn't "accidentally"
// sort.
num := 7
for i := num; i > 0; i-- {
rel := releaseMock()
rel.Name = fmt.Sprintf("rel-%d", i)
if err := rs.env.Releases.Create(rel); err != nil {
t.Fatalf("Could not store mock release: %s", err)
}
}
limit := 6
mrs := &mockListServer{}
req := &services.ListReleasesRequest{
Offset: "",
Limit: int64(limit),
SortBy: services.ListSort_NAME,
}
if err := rs.ListReleases(req, mrs); err != nil {
t.Fatalf("Failed listing: %s", err)
}
if len(mrs.val.Releases) != limit {
t.Errorf("Expected %d releases, got %d", limit, len(mrs.val.Releases))
}
for i := 0; i < limit; i++ {
n := fmt.Sprintf("rel-%d", i+1)
if mrs.val.Releases[i].Name != n {
t.Errorf("Expected %q, got %q", n, mrs.val.Releases[i].Name)
}
}
}
func TestListReleasesFilter(t *testing.T) {
rs := rsFixture()
names := []string{
"axon",
"dendrite",
"neuron",
"neuroglia",
"synapse",
"nucleus",
"organelles",
}
num := 7
for i := 0; i < num; i++ {
rel := releaseMock()
rel.Name = names[i]
if err := rs.env.Releases.Create(rel); err != nil {
t.Fatalf("Could not store mock release: %s", err)
}
}
mrs := &mockListServer{}
req := &services.ListReleasesRequest{
Offset: "",
Limit: 64,
Filter: "neuro[a-z]+",
SortBy: services.ListSort_NAME,
}
if err := rs.ListReleases(req, mrs); err != nil {
t.Fatalf("Failed listing: %s", err)
}
if len(mrs.val.Releases) != 2 {
t.Errorf("Expected 2 releases, got %d", len(mrs.val.Releases))
}
if mrs.val.Releases[0].Name != "neuroglia" {
t.Errorf("Unexpected sort order: %v.", mrs.val.Releases)
}
if mrs.val.Releases[1].Name != "neuron" {
t.Errorf("Unexpected sort order: %v.", mrs.val.Releases)
}
}
func mockEnvironment() *environment.Environment { func mockEnvironment() *environment.Environment {
e := environment.New() e := environment.New()
e.Releases = storage.NewMemory() e.Releases = storage.NewMemory()

@ -13,7 +13,7 @@ var Config = &config{
} }
// ListReleases lists the current releases. // ListReleases lists the current releases.
func ListReleases(limit, offset int) (*services.ListReleasesResponse, error) { func ListReleases(limit int, offset string, sort services.ListSort_SortBy, order services.ListSort_SortOrder, filter string) (*services.ListReleasesResponse, error) {
c := Config.client() c := Config.client()
if err := c.dial(); err != nil { if err := c.dial(); err != nil {
return nil, err return nil, err
@ -21,8 +21,11 @@ func ListReleases(limit, offset int) (*services.ListReleasesResponse, error) {
defer c.Close() defer c.Close()
req := &services.ListReleasesRequest{ req := &services.ListReleasesRequest{
Limit: int64(limit), Limit: int64(limit),
Offset: int64(offset), Offset: offset,
SortBy: sort,
SortOrder: order,
Filter: filter,
} }
cli, err := c.impl.ListReleases(context.TODO(), req, c.cfg.CallOpts()...) cli, err := c.impl.ListReleases(context.TODO(), req, c.cfg.CallOpts()...)
if err != nil { if err != nil {

@ -10,6 +10,7 @@ It is generated from these files:
It has these top-level messages: It has these top-level messages:
ListReleasesRequest ListReleasesRequest
ListSort
ListReleasesResponse ListReleasesResponse
GetReleaseStatusRequest GetReleaseStatusRequest
GetReleaseStatusResponse GetReleaseStatusResponse
@ -46,12 +47,74 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against. // is compatible with the proto package it is being compiled against.
const _ = proto.ProtoPackageIsVersion1 const _ = proto.ProtoPackageIsVersion1
// SortBy defines sort operations.
type ListSort_SortBy int32
const (
ListSort_UNKNOWN ListSort_SortBy = 0
ListSort_NAME ListSort_SortBy = 1
ListSort_LAST_RELEASED ListSort_SortBy = 2
)
var ListSort_SortBy_name = map[int32]string{
0: "UNKNOWN",
1: "NAME",
2: "LAST_RELEASED",
}
var ListSort_SortBy_value = map[string]int32{
"UNKNOWN": 0,
"NAME": 1,
"LAST_RELEASED": 2,
}
func (x ListSort_SortBy) String() string {
return proto.EnumName(ListSort_SortBy_name, int32(x))
}
func (ListSort_SortBy) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 0} }
// SortOrder defines sort orders to augment sorting operations.
type ListSort_SortOrder int32
const (
ListSort_ASC ListSort_SortOrder = 0
ListSort_DESC ListSort_SortOrder = 1
)
var ListSort_SortOrder_name = map[int32]string{
0: "ASC",
1: "DESC",
}
var ListSort_SortOrder_value = map[string]int32{
"ASC": 0,
"DESC": 1,
}
func (x ListSort_SortOrder) String() string {
return proto.EnumName(ListSort_SortOrder_name, int32(x))
}
func (ListSort_SortOrder) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 1} }
// ListReleasesRequest requests a list of releases. // ListReleasesRequest requests a list of releases.
//
// Releases can be retrieved in chunks by setting limit and offset.
//
// Releases can be sorted according to a few pre-determined sort stategies.
type ListReleasesRequest struct { type ListReleasesRequest struct {
// The maximum number of releases to be returned // Limit is the maximum number of releases to be returned.
Limit int64 `protobuf:"varint,1,opt,name=limit" json:"limit,omitempty"` Limit int64 `protobuf:"varint,1,opt,name=limit" json:"limit,omitempty"`
// The zero-based offset at which the returned release list begins // Offset is the last release name that was seen. The next listing
Offset int64 `protobuf:"varint,2,opt,name=offset" json:"offset,omitempty"` // operation will start with the name after this one.
// Example: If list one returns albert, bernie, carl and we supply
// carl as the offset, the next one should begin with the next release name
// after carl (e.g. dennis).
Offset string `protobuf:"bytes,2,opt,name=offset" json:"offset,omitempty"`
// SortBy is the sort field that the ListReleases server should sort data before returning.
SortBy ListSort_SortBy `protobuf:"varint,3,opt,name=sort_by,json=sortBy,enum=hapi.services.tiller.ListSort_SortBy" json:"sort_by,omitempty"`
// Filter is a regular expression used to filter which releases should be listed.
//
// Anything that matches the regexp will be included in the results.
Filter string `protobuf:"bytes,4,opt,name=filter" json:"filter,omitempty"`
SortOrder ListSort_SortOrder `protobuf:"varint,5,opt,name=sort_order,json=sortOrder,enum=hapi.services.tiller.ListSort_SortOrder" json:"sort_order,omitempty"`
} }
func (m *ListReleasesRequest) Reset() { *m = ListReleasesRequest{} } func (m *ListReleasesRequest) Reset() { *m = ListReleasesRequest{} }
@ -59,22 +122,32 @@ func (m *ListReleasesRequest) String() string { return proto.CompactT
func (*ListReleasesRequest) ProtoMessage() {} func (*ListReleasesRequest) ProtoMessage() {}
func (*ListReleasesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (*ListReleasesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
// ListSort defines sorting fields on a release list.
type ListSort struct {
}
func (m *ListSort) Reset() { *m = ListSort{} }
func (m *ListSort) String() string { return proto.CompactTextString(m) }
func (*ListSort) ProtoMessage() {}
func (*ListSort) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
// ListReleasesResponse is a list of releases. // ListReleasesResponse is a list of releases.
type ListReleasesResponse struct { type ListReleasesResponse struct {
// The expected total number of releases to be returned // Count is the expected total number of releases to be returned.
Count int64 `protobuf:"varint,1,opt,name=count" json:"count,omitempty"` Count int64 `protobuf:"varint,1,opt,name=count" json:"count,omitempty"`
// The zero-based offset at which the list is positioned // Next is the name of the next release. If this is other than an empty
Offset int64 `protobuf:"varint,2,opt,name=offset" json:"offset,omitempty"` // string, it means there are more results.
// The total number of queryable releases Next string `protobuf:"bytes,2,opt,name=next" json:"next,omitempty"`
// Total is the total number of queryable releases.
Total int64 `protobuf:"varint,3,opt,name=total" json:"total,omitempty"` Total int64 `protobuf:"varint,3,opt,name=total" json:"total,omitempty"`
// The resulting releases // Releases is the list of found release objects.
Releases []*hapi_release2.Release `protobuf:"bytes,4,rep,name=releases" json:"releases,omitempty"` Releases []*hapi_release2.Release `protobuf:"bytes,4,rep,name=releases" json:"releases,omitempty"`
} }
func (m *ListReleasesResponse) Reset() { *m = ListReleasesResponse{} } func (m *ListReleasesResponse) Reset() { *m = ListReleasesResponse{} }
func (m *ListReleasesResponse) String() string { return proto.CompactTextString(m) } func (m *ListReleasesResponse) String() string { return proto.CompactTextString(m) }
func (*ListReleasesResponse) ProtoMessage() {} func (*ListReleasesResponse) ProtoMessage() {}
func (*ListReleasesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (*ListReleasesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (m *ListReleasesResponse) GetReleases() []*hapi_release2.Release { func (m *ListReleasesResponse) GetReleases() []*hapi_release2.Release {
if m != nil { if m != nil {
@ -92,7 +165,7 @@ type GetReleaseStatusRequest struct {
func (m *GetReleaseStatusRequest) Reset() { *m = GetReleaseStatusRequest{} } func (m *GetReleaseStatusRequest) Reset() { *m = GetReleaseStatusRequest{} }
func (m *GetReleaseStatusRequest) String() string { return proto.CompactTextString(m) } func (m *GetReleaseStatusRequest) String() string { return proto.CompactTextString(m) }
func (*GetReleaseStatusRequest) ProtoMessage() {} func (*GetReleaseStatusRequest) ProtoMessage() {}
func (*GetReleaseStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (*GetReleaseStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
// GetReleaseStatusResponse is the response indicating the status of the named release. // GetReleaseStatusResponse is the response indicating the status of the named release.
type GetReleaseStatusResponse struct { type GetReleaseStatusResponse struct {
@ -105,7 +178,7 @@ type GetReleaseStatusResponse struct {
func (m *GetReleaseStatusResponse) Reset() { *m = GetReleaseStatusResponse{} } func (m *GetReleaseStatusResponse) Reset() { *m = GetReleaseStatusResponse{} }
func (m *GetReleaseStatusResponse) String() string { return proto.CompactTextString(m) } func (m *GetReleaseStatusResponse) String() string { return proto.CompactTextString(m) }
func (*GetReleaseStatusResponse) ProtoMessage() {} func (*GetReleaseStatusResponse) ProtoMessage() {}
func (*GetReleaseStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (*GetReleaseStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
func (m *GetReleaseStatusResponse) GetInfo() *hapi_release1.Info { func (m *GetReleaseStatusResponse) GetInfo() *hapi_release1.Info {
if m != nil { if m != nil {
@ -123,7 +196,7 @@ type GetReleaseContentRequest struct {
func (m *GetReleaseContentRequest) Reset() { *m = GetReleaseContentRequest{} } func (m *GetReleaseContentRequest) Reset() { *m = GetReleaseContentRequest{} }
func (m *GetReleaseContentRequest) String() string { return proto.CompactTextString(m) } func (m *GetReleaseContentRequest) String() string { return proto.CompactTextString(m) }
func (*GetReleaseContentRequest) ProtoMessage() {} func (*GetReleaseContentRequest) ProtoMessage() {}
func (*GetReleaseContentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (*GetReleaseContentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
// GetReleaseContentResponse is a response containing the contents of a release. // GetReleaseContentResponse is a response containing the contents of a release.
type GetReleaseContentResponse struct { type GetReleaseContentResponse struct {
@ -134,7 +207,7 @@ type GetReleaseContentResponse struct {
func (m *GetReleaseContentResponse) Reset() { *m = GetReleaseContentResponse{} } func (m *GetReleaseContentResponse) Reset() { *m = GetReleaseContentResponse{} }
func (m *GetReleaseContentResponse) String() string { return proto.CompactTextString(m) } func (m *GetReleaseContentResponse) String() string { return proto.CompactTextString(m) }
func (*GetReleaseContentResponse) ProtoMessage() {} func (*GetReleaseContentResponse) ProtoMessage() {}
func (*GetReleaseContentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (*GetReleaseContentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (m *GetReleaseContentResponse) GetRelease() *hapi_release2.Release { func (m *GetReleaseContentResponse) GetRelease() *hapi_release2.Release {
if m != nil { if m != nil {
@ -150,7 +223,7 @@ type UpdateReleaseRequest struct {
func (m *UpdateReleaseRequest) Reset() { *m = UpdateReleaseRequest{} } func (m *UpdateReleaseRequest) Reset() { *m = UpdateReleaseRequest{} }
func (m *UpdateReleaseRequest) String() string { return proto.CompactTextString(m) } func (m *UpdateReleaseRequest) String() string { return proto.CompactTextString(m) }
func (*UpdateReleaseRequest) ProtoMessage() {} func (*UpdateReleaseRequest) ProtoMessage() {}
func (*UpdateReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } func (*UpdateReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
// UpdateReleaseResponse is the response to an update request. // UpdateReleaseResponse is the response to an update request.
type UpdateReleaseResponse struct { type UpdateReleaseResponse struct {
@ -159,7 +232,7 @@ type UpdateReleaseResponse struct {
func (m *UpdateReleaseResponse) Reset() { *m = UpdateReleaseResponse{} } func (m *UpdateReleaseResponse) Reset() { *m = UpdateReleaseResponse{} }
func (m *UpdateReleaseResponse) String() string { return proto.CompactTextString(m) } func (m *UpdateReleaseResponse) String() string { return proto.CompactTextString(m) }
func (*UpdateReleaseResponse) ProtoMessage() {} func (*UpdateReleaseResponse) ProtoMessage() {}
func (*UpdateReleaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (*UpdateReleaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
// InstallReleaseRequest is the request for an installation of a chart. // InstallReleaseRequest is the request for an installation of a chart.
type InstallReleaseRequest struct { type InstallReleaseRequest struct {
@ -176,7 +249,7 @@ type InstallReleaseRequest struct {
func (m *InstallReleaseRequest) Reset() { *m = InstallReleaseRequest{} } func (m *InstallReleaseRequest) Reset() { *m = InstallReleaseRequest{} }
func (m *InstallReleaseRequest) String() string { return proto.CompactTextString(m) } func (m *InstallReleaseRequest) String() string { return proto.CompactTextString(m) }
func (*InstallReleaseRequest) ProtoMessage() {} func (*InstallReleaseRequest) ProtoMessage() {}
func (*InstallReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } func (*InstallReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
func (m *InstallReleaseRequest) GetChart() *hapi_chart3.Chart { func (m *InstallReleaseRequest) GetChart() *hapi_chart3.Chart {
if m != nil { if m != nil {
@ -200,7 +273,7 @@ type InstallReleaseResponse struct {
func (m *InstallReleaseResponse) Reset() { *m = InstallReleaseResponse{} } func (m *InstallReleaseResponse) Reset() { *m = InstallReleaseResponse{} }
func (m *InstallReleaseResponse) String() string { return proto.CompactTextString(m) } func (m *InstallReleaseResponse) String() string { return proto.CompactTextString(m) }
func (*InstallReleaseResponse) ProtoMessage() {} func (*InstallReleaseResponse) ProtoMessage() {}
func (*InstallReleaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } func (*InstallReleaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
func (m *InstallReleaseResponse) GetRelease() *hapi_release2.Release { func (m *InstallReleaseResponse) GetRelease() *hapi_release2.Release {
if m != nil { if m != nil {
@ -218,7 +291,7 @@ type UninstallReleaseRequest struct {
func (m *UninstallReleaseRequest) Reset() { *m = UninstallReleaseRequest{} } func (m *UninstallReleaseRequest) Reset() { *m = UninstallReleaseRequest{} }
func (m *UninstallReleaseRequest) String() string { return proto.CompactTextString(m) } func (m *UninstallReleaseRequest) String() string { return proto.CompactTextString(m) }
func (*UninstallReleaseRequest) ProtoMessage() {} func (*UninstallReleaseRequest) ProtoMessage() {}
func (*UninstallReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (*UninstallReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
// UninstallReleaseResponse represents a successful response to an uninstall request. // UninstallReleaseResponse represents a successful response to an uninstall request.
type UninstallReleaseResponse struct { type UninstallReleaseResponse struct {
@ -229,7 +302,7 @@ type UninstallReleaseResponse struct {
func (m *UninstallReleaseResponse) Reset() { *m = UninstallReleaseResponse{} } func (m *UninstallReleaseResponse) Reset() { *m = UninstallReleaseResponse{} }
func (m *UninstallReleaseResponse) String() string { return proto.CompactTextString(m) } func (m *UninstallReleaseResponse) String() string { return proto.CompactTextString(m) }
func (*UninstallReleaseResponse) ProtoMessage() {} func (*UninstallReleaseResponse) ProtoMessage() {}
func (*UninstallReleaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (*UninstallReleaseResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
func (m *UninstallReleaseResponse) GetRelease() *hapi_release2.Release { func (m *UninstallReleaseResponse) GetRelease() *hapi_release2.Release {
if m != nil { if m != nil {
@ -240,6 +313,7 @@ func (m *UninstallReleaseResponse) GetRelease() *hapi_release2.Release {
func init() { func init() {
proto.RegisterType((*ListReleasesRequest)(nil), "hapi.services.tiller.ListReleasesRequest") proto.RegisterType((*ListReleasesRequest)(nil), "hapi.services.tiller.ListReleasesRequest")
proto.RegisterType((*ListSort)(nil), "hapi.services.tiller.ListSort")
proto.RegisterType((*ListReleasesResponse)(nil), "hapi.services.tiller.ListReleasesResponse") proto.RegisterType((*ListReleasesResponse)(nil), "hapi.services.tiller.ListReleasesResponse")
proto.RegisterType((*GetReleaseStatusRequest)(nil), "hapi.services.tiller.GetReleaseStatusRequest") proto.RegisterType((*GetReleaseStatusRequest)(nil), "hapi.services.tiller.GetReleaseStatusRequest")
proto.RegisterType((*GetReleaseStatusResponse)(nil), "hapi.services.tiller.GetReleaseStatusResponse") proto.RegisterType((*GetReleaseStatusResponse)(nil), "hapi.services.tiller.GetReleaseStatusResponse")
@ -251,6 +325,8 @@ func init() {
proto.RegisterType((*InstallReleaseResponse)(nil), "hapi.services.tiller.InstallReleaseResponse") proto.RegisterType((*InstallReleaseResponse)(nil), "hapi.services.tiller.InstallReleaseResponse")
proto.RegisterType((*UninstallReleaseRequest)(nil), "hapi.services.tiller.UninstallReleaseRequest") proto.RegisterType((*UninstallReleaseRequest)(nil), "hapi.services.tiller.UninstallReleaseRequest")
proto.RegisterType((*UninstallReleaseResponse)(nil), "hapi.services.tiller.UninstallReleaseResponse") proto.RegisterType((*UninstallReleaseResponse)(nil), "hapi.services.tiller.UninstallReleaseResponse")
proto.RegisterEnum("hapi.services.tiller.ListSort_SortBy", ListSort_SortBy_name, ListSort_SortBy_value)
proto.RegisterEnum("hapi.services.tiller.ListSort_SortOrder", ListSort_SortOrder_name, ListSort_SortOrder_value)
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -506,39 +582,48 @@ var _ReleaseService_serviceDesc = grpc.ServiceDesc{
} }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 540 bytes of a gzipped FileDescriptorProto // 682 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x55, 0xcd, 0x6e, 0xd3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x55, 0xdd, 0x4e, 0x13, 0x41,
0x10, 0xae, 0x49, 0x9a, 0x86, 0x29, 0x54, 0x74, 0xc8, 0x8f, 0xf1, 0xa9, 0xda, 0x03, 0x94, 0x42, 0x14, 0x66, 0x69, 0x69, 0xcb, 0x41, 0x48, 0x39, 0x96, 0xb6, 0xee, 0x85, 0x31, 0x93, 0xa8, 0x88,
0x1d, 0x08, 0x6f, 0x40, 0x0e, 0x28, 0xa2, 0xa7, 0x45, 0xe5, 0xc0, 0x05, 0x99, 0x74, 0x43, 0x17, 0xb2, 0xd5, 0x7a, 0x6f, 0x52, 0xa0, 0x21, 0x84, 0x5a, 0x92, 0xa9, 0x68, 0xe2, 0x85, 0x64, 0x81,
0x39, 0xeb, 0xe0, 0x5d, 0x47, 0xe2, 0x01, 0x38, 0xf2, 0x3e, 0x3c, 0x1e, 0xf6, 0xfe, 0x58, 0x71, 0xa9, 0xac, 0x59, 0x76, 0xeb, 0xce, 0x94, 0xc8, 0x03, 0x78, 0xe1, 0x1b, 0xf9, 0x40, 0x3e, 0x88,
0x62, 0x53, 0xab, 0x17, 0xb7, 0xbb, 0xdf, 0x37, 0xf3, 0xcd, 0xce, 0x7c, 0xa3, 0x40, 0x70, 0x1b, 0xb3, 0x33, 0x3b, 0x1b, 0xb6, 0xdd, 0xd5, 0x86, 0x9b, 0xdd, 0x39, 0xfb, 0x7d, 0xe7, 0x7c, 0x67,
0xad, 0xf9, 0x44, 0xb2, 0x74, 0xc3, 0x17, 0x4c, 0x4e, 0x14, 0x8f, 0x63, 0x96, 0x86, 0xeb, 0x34, 0xce, 0x4f, 0x0b, 0xf6, 0x95, 0x3b, 0xf1, 0x3a, 0x9c, 0x45, 0x37, 0xde, 0x05, 0xe3, 0x1d, 0xe1,
0x51, 0x09, 0x0e, 0x0a, 0x2c, 0x74, 0x58, 0x68, 0xb0, 0x60, 0xa4, 0x23, 0x16, 0xb7, 0x51, 0xaa, 0xf9, 0x3e, 0x8b, 0x9c, 0x49, 0x14, 0x8a, 0x10, 0x1b, 0x31, 0xe6, 0x18, 0xcc, 0xd1, 0x98, 0xdd,
0xcc, 0xd7, 0xb0, 0x83, 0xf1, 0xf6, 0x7d, 0x22, 0x96, 0xfc, 0xbb, 0x05, 0x8c, 0x44, 0xca, 0x62, 0x54, 0x1e, 0x17, 0x57, 0x6e, 0x24, 0xf4, 0x53, 0xb3, 0xed, 0xd6, 0xdd, 0xef, 0x61, 0x30, 0xf6,
0x16, 0x49, 0xe6, 0xfe, 0x56, 0x82, 0x1c, 0xc6, 0xc5, 0x32, 0x31, 0x00, 0x99, 0xc1, 0xd3, 0x2b, 0xbe, 0x26, 0x80, 0x96, 0x88, 0x98, 0xcf, 0x5c, 0xce, 0xcc, 0x3b, 0xe3, 0x64, 0x30, 0x2f, 0x18,
0x2e, 0x15, 0x35, 0x88, 0xa4, 0xec, 0x67, 0xc6, 0xa4, 0xc2, 0x01, 0x1c, 0xc6, 0x7c, 0xc5, 0x95, 0x87, 0x1a, 0x20, 0x7f, 0x2c, 0x78, 0x38, 0xf0, 0xb8, 0xa0, 0x1a, 0xe2, 0x94, 0x7d, 0x9f, 0x32,
0xef, 0x9d, 0x79, 0xe7, 0x1d, 0x6a, 0x0e, 0x38, 0x82, 0x5e, 0xb2, 0x5c, 0x4a, 0xa6, 0xfc, 0x07, 0x2e, 0xb0, 0x01, 0x2b, 0xbe, 0x77, 0xed, 0x89, 0xb6, 0xf5, 0xc4, 0xda, 0x2e, 0x51, 0x6d, 0x60,
0xfa, 0xda, 0x9e, 0xc8, 0x1f, 0x0f, 0x06, 0xd5, 0x2c, 0x72, 0x9d, 0x08, 0xc9, 0x8a, 0x34, 0x8b, 0x13, 0x2a, 0xe1, 0x78, 0xcc, 0x99, 0x68, 0x2f, 0xcb, 0xcf, 0xab, 0x34, 0xb1, 0xf0, 0x1d, 0x54,
0x24, 0x13, 0x65, 0x1a, 0x7d, 0x68, 0x4a, 0x53, 0xb0, 0x55, 0xa2, 0xa2, 0xd8, 0xef, 0x18, 0xb6, 0x79, 0x18, 0x89, 0xb3, 0xf3, 0xdb, 0x76, 0x49, 0x02, 0x1b, 0xdd, 0xa7, 0x4e, 0xde, 0x9d, 0x9c,
0x3e, 0xe0, 0x5b, 0xe8, 0xdb, 0xba, 0xa5, 0xdf, 0x3d, 0xeb, 0x9c, 0x1f, 0x4f, 0x87, 0xa1, 0x6e, 0x58, 0x69, 0x24, 0x89, 0x4e, 0xfc, 0xd8, 0xbb, 0xa5, 0x15, 0xae, 0xde, 0x71, 0xdc, 0xb1, 0xe7,
0x98, 0x7b, 0xa1, 0x55, 0xa5, 0x25, 0x8d, 0x5c, 0xc2, 0xf8, 0x03, 0x73, 0xd5, 0x7c, 0x52, 0x91, 0x0b, 0x16, 0xb5, 0xcb, 0x3a, 0xae, 0xb6, 0xf0, 0x10, 0x40, 0xc5, 0x0d, 0xa3, 0x4b, 0x89, 0xad,
0xca, 0xca, 0x87, 0x21, 0x74, 0x45, 0xb4, 0x62, 0xba, 0xa0, 0x87, 0x54, 0xff, 0x4f, 0x3e, 0x83, 0xa8, 0xd0, 0xdb, 0x0b, 0x84, 0x3e, 0x89, 0xf9, 0x74, 0x95, 0x9b, 0x23, 0xf9, 0x02, 0x35, 0x43,
0xbf, 0x4f, 0xb7, 0x2f, 0xa8, 0xe1, 0xe3, 0x73, 0xe8, 0x16, 0x1d, 0xd4, 0xd5, 0x1f, 0x4f, 0xb1, 0x20, 0x5d, 0xa8, 0x68, 0x79, 0x5c, 0x83, 0xea, 0xe9, 0xf0, 0x78, 0x78, 0xf2, 0x69, 0x58, 0x5f,
0x5a, 0xcd, 0x3c, 0x47, 0xa8, 0xc6, 0x49, 0xb8, 0x9d, 0x77, 0x96, 0x08, 0xc5, 0x84, 0xfa, 0x5f, 0xc2, 0x1a, 0x94, 0x87, 0xbd, 0xf7, 0xfd, 0xba, 0x85, 0x9b, 0xb0, 0x3e, 0xe8, 0x8d, 0x3e, 0x9c,
0x1d, 0x57, 0xf0, 0xac, 0x86, 0x6f, 0x0b, 0x99, 0xc0, 0x91, 0x95, 0xd0, 0x31, 0x8d, 0x5d, 0x70, 0xd1, 0xfe, 0xa0, 0xdf, 0x1b, 0xf5, 0x0f, 0xea, 0xcb, 0xe4, 0x31, 0xac, 0xa6, 0x71, 0xb1, 0x0a,
0x2c, 0x32, 0x82, 0xc1, 0xf5, 0xfa, 0x26, 0x52, 0xcc, 0x21, 0x46, 0x99, 0x8c, 0x61, 0xb8, 0x73, 0xa5, 0xde, 0x68, 0x5f, 0xbb, 0x1c, 0xf4, 0xe5, 0xc9, 0x22, 0xbf, 0x2c, 0x68, 0x64, 0xcb, 0xc8,
0x6f, 0x14, 0xc8, 0x6f, 0x0f, 0x86, 0x73, 0x21, 0xf3, 0x9e, 0xc7, 0xd5, 0x10, 0x7c, 0x91, 0x8f, 0x27, 0x61, 0xc0, 0x59, 0x5c, 0xc7, 0x8b, 0x70, 0x1a, 0xa4, 0x75, 0x54, 0x06, 0x22, 0x94, 0x03,
0xb1, 0xf0, 0x9b, 0x55, 0x3e, 0x35, 0xca, 0xc6, 0x94, 0xb3, 0xe2, 0x4b, 0x0d, 0x8e, 0x17, 0xd0, 0xf6, 0xc3, 0x54, 0x51, 0x9d, 0x63, 0xa6, 0x08, 0x85, 0xeb, 0xab, 0x0a, 0x4a, 0xa6, 0x32, 0xf0,
0xdb, 0x44, 0x71, 0x1e, 0x53, 0xed, 0x8d, 0x65, 0x6a, 0xb3, 0x52, 0xcb, 0xc0, 0x31, 0x1c, 0xdd, 0x0d, 0xd4, 0x92, 0xae, 0x71, 0x59, 0x9b, 0xd2, 0xf6, 0x5a, 0x77, 0x4b, 0xdf, 0xdf, 0xf4, 0x37,
0xa4, 0xbf, 0xbe, 0xa6, 0x99, 0xd0, 0xf3, 0xee, 0xd3, 0x5e, 0x7e, 0xa4, 0x99, 0x20, 0x73, 0x18, 0x51, 0xa4, 0x29, 0x8d, 0xec, 0x42, 0xeb, 0x90, 0x99, 0x4c, 0x46, 0xc2, 0x15, 0xd3, 0xb4, 0xab,
0xed, 0x96, 0x71, 0xdf, 0x1e, 0xe4, 0x46, 0xb8, 0x16, 0xbc, 0xf6, 0x4d, 0x75, 0x03, 0xf8, 0x08, 0xb1, 0xae, 0x7b, 0xcd, 0x54, 0x32, 0xb1, 0xae, 0x3c, 0x93, 0x8f, 0xd0, 0x9e, 0xa7, 0x27, 0xd9,
0xfe, 0x3e, 0xfd, 0x9e, 0xda, 0xd3, 0xbf, 0x87, 0x70, 0xe2, 0x3c, 0x65, 0x56, 0x1b, 0x39, 0x3c, 0xe7, 0xf0, 0xf1, 0x19, 0x94, 0xe3, 0xf9, 0x51, 0xb9, 0xaf, 0x75, 0x31, 0x9b, 0xcd, 0x91, 0x44,
0xda, 0x5e, 0x13, 0x7c, 0x19, 0xd6, 0x6d, 0x7e, 0x58, 0xb3, 0x90, 0xc1, 0x45, 0x1b, 0xaa, 0x1d, 0xa8, 0xc2, 0x89, 0x73, 0x37, 0xee, 0x7e, 0x18, 0x08, 0x16, 0x88, 0x7f, 0xe5, 0x31, 0x80, 0x47,
0xe4, 0xc1, 0x1b, 0x0f, 0x25, 0x3c, 0xd9, 0xf5, 0x34, 0x5e, 0xd6, 0xe7, 0x68, 0x58, 0x95, 0x20, 0x39, 0xfc, 0x24, 0x91, 0x0e, 0x54, 0x13, 0x09, 0xe5, 0x53, 0x58, 0x05, 0xc3, 0x22, 0x4d, 0x68,
0x6c, 0x4b, 0x77, 0xb2, 0xb8, 0x81, 0xd3, 0x3d, 0x03, 0xe3, 0x9d, 0x69, 0xaa, 0x9b, 0x11, 0x4c, 0x9c, 0x4e, 0x2e, 0x5d, 0xc1, 0x0c, 0xa2, 0x95, 0x49, 0x0b, 0xb6, 0x66, 0xbe, 0x6b, 0x05, 0xf2,
0x5a, 0xf3, 0x4b, 0xdd, 0x1f, 0xf0, 0xb8, 0x62, 0x69, 0x6c, 0xe8, 0x56, 0xdd, 0x3e, 0x04, 0xaf, 0xd3, 0x82, 0xad, 0xa3, 0x80, 0xcb, 0x9a, 0xfb, 0x59, 0x17, 0x7c, 0x2e, 0x5b, 0x18, 0x6f, 0x5b,
0x5a, 0x71, 0x4b, 0xad, 0x15, 0x9c, 0x54, 0xdd, 0x89, 0x0d, 0x09, 0x6a, 0x57, 0x29, 0x78, 0xdd, 0xa2, 0xbc, 0xa9, 0x95, 0xf5, 0x4a, 0xee, 0xc7, 0x4f, 0xaa, 0x71, 0xdc, 0x81, 0xca, 0x8d, 0xeb,
0x8e, 0x5c, 0xca, 0xe5, 0x73, 0xdc, 0xb5, 0x64, 0xd3, 0x1c, 0x1b, 0x9c, 0xde, 0x34, 0xc7, 0x26, 0x4b, 0x9f, 0x6c, 0x6d, 0x12, 0xa6, 0x5a, 0x55, 0x9a, 0x30, 0xb0, 0x05, 0xd5, 0xcb, 0xe8, 0xf6,
0xa7, 0x93, 0x83, 0xf7, 0xf0, 0xa5, 0xef, 0xd8, 0xdf, 0x7a, 0xfa, 0x77, 0xe2, 0xdd, 0xbf, 0x00, 0x2c, 0x9a, 0x06, 0xaa, 0xdf, 0x35, 0x5a, 0x91, 0x26, 0x9d, 0x06, 0xe4, 0x08, 0x9a, 0xb3, 0x69,
0x00, 0x00, 0xff, 0xff, 0x8c, 0xd6, 0xc7, 0x2c, 0xc1, 0x06, 0x00, 0x00, 0xdc, 0xb7, 0x06, 0x72, 0x10, 0x4e, 0x03, 0x2f, 0xf7, 0x4e, 0x79, 0x0d, 0x38, 0x86, 0xf6, 0x3c,
0xfd, 0x9e, 0xda, 0xdd, 0xdf, 0x2b, 0xb0, 0x61, 0x66, 0x4a, 0x6f, 0x2a, 0x7a, 0xf0, 0xe0, 0xee,
0x8a, 0xe0, 0x8b, 0xe2, 0x45, 0x9e, 0xf9, 0x35, 0xb2, 0x77, 0x16, 0xa1, 0x26, 0x8d, 0x5c, 0x7a,
0x6d, 0x21, 0x87, 0xfa, 0xec, 0x4c, 0xe3, 0x6e, 0x7e, 0x8c, 0x82, 0x55, 0xb1, 0x9d, 0x45, 0xe9,
0x46, 0x16, 0x6f, 0x60, 0x73, 0x6e, 0x80, 0xf1, 0xbf, 0x61, 0xb2, 0x9b, 0x61, 0x77, 0x16, 0xe6,
0xa7, 0xba, 0xdf, 0x60, 0x3d, 0x33, 0xd2, 0x58, 0x50, 0xad, 0xbc, 0x7d, 0xb0, 0x5f, 0x2e, 0xc4,
0x4d, 0xb5, 0xae, 0x61, 0x23, 0x3b, 0x9d, 0x58, 0x10, 0x20, 0x77, 0x95, 0xec, 0x57, 0x8b, 0x91,
0x53, 0x39, 0xd9, 0xc7, 0xd9, 0x91, 0x2c, 0xea, 0x63, 0xc1, 0xa4, 0x17, 0xf5, 0xb1, 0x68, 0xd2,
0xc9, 0xd2, 0x1e, 0x7c, 0xae, 0x19, 0xf6, 0x79, 0x45, 0xfd, 0x4b, 0xbe, 0xfd, 0x1b, 0x00, 0x00,
0xff, 0xff, 0x9a, 0xaa, 0x47, 0x7a, 0xbf, 0x07, 0x00, 0x00,
} }

Loading…
Cancel
Save