feat(tiller): sort list in tiller, not helm

pull/669/head
Matt Butcher 9 years ago
parent 62cb6ce45d
commit ea6b82a43c

@ -53,12 +53,27 @@ 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 zero-based offset at which the returned release list begins.
int64 offset = 2; int64 offset = 2;
// SortBy is the sort field that the ListReleases server should sort data before returning.
ListSort.SortBy sort_by = 3;
}
message ListSort{
enum SortBy {
UNKNOWN = 0;
NAME = 1;
LAST_RELEASED = 2;
}
} }
// ListReleasesResponse is a list of releases. // ListReleasesResponse is a list of releases.

@ -2,11 +2,11 @@ package main
import ( import (
"fmt" "fmt"
"sort"
"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"
) )
@ -45,7 +45,12 @@ func listCmd(cmd *cobra.Command, args []string) error {
fmt.Println("TODO: Implement filter.") fmt.Println("TODO: Implement filter.")
} }
res, err := helm.ListReleases(listMax, listOffset) sortBy := services.ListSort_NAME
if listByDate {
sortBy = services.ListSort_LAST_RELEASED
}
res, err := helm.ListReleases(listMax, listOffset, sortBy)
if err != nil { if err != nil {
return prettyError(err) return prettyError(err)
} }
@ -55,12 +60,6 @@ func listCmd(cmd *cobra.Command, args []string) error {
fmt.Println("Not all values were fetched.") fmt.Println("Not all values were fetched.")
} }
if listByDate {
sort.Sort(byDate(rels))
} else {
sort.Sort(byName(rels))
}
// Purty output, ya'll // Purty output, ya'll
if listLong { if listLong {
return formatList(rels) return formatList(rels)
@ -85,26 +84,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,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"log" "log"
"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"
@ -49,6 +50,17 @@ func (s *releaseServer) ListReleases(req *services.ListReleasesRequest, stream s
total := int64(len(rels)) total := int64(len(rels))
if req.SortBy != services.ListSort_UNKNOWN {
log.Printf("Sorting by %q", req.SortBy)
}
switch req.SortBy {
case services.ListSort_NAME:
sort.Sort(byName(rels))
case services.ListSort_LAST_RELEASED:
sort.Sort(byDate(rels))
}
l := int64(len(rels)) l := int64(len(rels))
if req.Offset > 0 { if req.Offset > 0 {
if req.Offset >= l { if req.Offset >= l {
@ -224,3 +236,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
}

@ -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, offset int, sort services.ListSort_SortBy) (*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
@ -23,6 +23,7 @@ func ListReleases(limit, offset int) (*services.ListReleasesResponse, error) {
req := &services.ListReleasesRequest{ req := &services.ListReleasesRequest{
Limit: int64(limit), Limit: int64(limit),
Offset: int64(offset), Offset: int64(offset),
SortBy: sort,
} }
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,42 @@ 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
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} }
// 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 zero-based offset at which the returned release list begins.
Offset int64 `protobuf:"varint,2,opt,name=offset" json:"offset,omitempty"` Offset int64 `protobuf:"varint,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"`
} }
func (m *ListReleasesRequest) Reset() { *m = ListReleasesRequest{} } func (m *ListReleasesRequest) Reset() { *m = ListReleasesRequest{} }
@ -59,6 +90,14 @@ 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} }
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 // The expected total number of releases to be returned
@ -74,7 +113,7 @@ type ListReleasesResponse struct {
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 +131,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 +144,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 +162,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 +173,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 +189,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 +198,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 +215,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 +239,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 +257,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 +268,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 +279,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 +291,7 @@ 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)
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -506,39 +547,44 @@ var _ReleaseService_serviceDesc = grpc.ServiceDesc{
} }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 540 bytes of a gzipped FileDescriptorProto // 623 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, 0x5d, 0x6f, 0xda, 0x3c,
0x10, 0xae, 0x49, 0x9a, 0x86, 0x29, 0x54, 0x74, 0xc8, 0x8f, 0xf1, 0xa9, 0xda, 0x03, 0x94, 0x42, 0x18, 0x6d, 0x5a, 0x1a, 0x78, 0x1f, 0xde, 0x22, 0xf0, 0xf8, 0xc8, 0x72, 0x55, 0x59, 0xda, 0xd6,
0x1d, 0x08, 0x6f, 0x40, 0x0e, 0x28, 0xa2, 0xa7, 0x45, 0xe5, 0xc0, 0x05, 0x99, 0x74, 0x43, 0x17, 0x75, 0x6b, 0xd8, 0xd8, 0x7d, 0x25, 0xda, 0xa1, 0x09, 0x95, 0x31, 0xc9, 0x8c, 0x4d, 0xda, 0x0d,
0x39, 0xeb, 0xe0, 0x5d, 0x47, 0xe2, 0x01, 0x38, 0xf2, 0x3e, 0x3c, 0x1e, 0xf6, 0xfe, 0x58, 0x71, 0x4a, 0xa9, 0x59, 0x33, 0x85, 0x84, 0xc5, 0x06, 0x89, 0xeb, 0x69, 0x97, 0xfb, 0x3f, 0xfb, 0x79,
0x62, 0x53, 0xab, 0x17, 0xb7, 0xbb, 0xdf, 0x37, 0xf3, 0xcd, 0xce, 0x7c, 0xa3, 0x40, 0x70, 0x1b, 0x4b, 0xec, 0x38, 0x22, 0x90, 0x6c, 0xa8, 0x37, 0x4e, 0xed, 0x73, 0xec, 0xf3, 0x7c, 0x9c, 0xa7,
0xad, 0xf9, 0x44, 0xb2, 0x74, 0xc3, 0x17, 0x4c, 0x4e, 0x14, 0x8f, 0x63, 0x96, 0x86, 0xeb, 0x34, 0x80, 0x79, 0x6f, 0x2f, 0x9c, 0x36, 0xa3, 0xc1, 0xca, 0x99, 0x52, 0xd6, 0xe6, 0x8e, 0xeb, 0xd2,
0x51, 0x09, 0x0e, 0x0a, 0x2c, 0x74, 0x58, 0x68, 0xb0, 0x60, 0xa4, 0x23, 0x16, 0xb7, 0x51, 0xaa, 0xc0, 0x5a, 0x04, 0x3e, 0xf7, 0x51, 0x3d, 0xc2, 0x2c, 0x85, 0x59, 0x12, 0x33, 0x9b, 0xe2, 0xc6,
0xcc, 0xd7, 0xb0, 0x83, 0xf1, 0xf6, 0x7d, 0x22, 0x96, 0xfc, 0xbb, 0x05, 0x8c, 0x44, 0xca, 0x62, 0xf4, 0xde, 0x0e, 0xb8, 0x5c, 0x25, 0xdb, 0x6c, 0x6d, 0x9e, 0xfb, 0xde, 0xcc, 0xf9, 0x1a, 0x03,
0x16, 0x49, 0xe6, 0xfe, 0x56, 0x82, 0x1c, 0xc6, 0xc5, 0x32, 0x31, 0x00, 0x99, 0xc1, 0xd3, 0x2b, 0x52, 0x22, 0xa0, 0x2e, 0xb5, 0x19, 0x55, 0xdf, 0xd4, 0x25, 0x85, 0x39, 0xde, 0xcc, 0x97, 0x00,
0x2e, 0x15, 0x35, 0x88, 0xa4, 0xec, 0x67, 0xc6, 0xa4, 0xc2, 0x01, 0x1c, 0xc6, 0x7c, 0xc5, 0x95, 0xfe, 0xa1, 0xc1, 0xa3, 0x81, 0xc3, 0x38, 0x91, 0x10, 0x23, 0xf4, 0xfb, 0x92, 0x32, 0x8e, 0xea,
0xef, 0x9d, 0x79, 0xe7, 0x1d, 0x6a, 0x0e, 0x38, 0x82, 0x5e, 0xb2, 0x5c, 0x4a, 0xa6, 0xfc, 0x07, 0x70, 0xec, 0x3a, 0x73, 0x87, 0x1b, 0xda, 0xa9, 0x76, 0x76, 0x44, 0xe4, 0x06, 0x35, 0x41, 0xf7,
0xfa, 0xda, 0x9e, 0xc8, 0x1f, 0x0f, 0x06, 0xd5, 0x2c, 0x72, 0x9d, 0x08, 0xc9, 0x8a, 0x34, 0x8b, 0x67, 0x33, 0x46, 0xb9, 0x71, 0x28, 0x8e, 0xe3, 0x1d, 0xba, 0x84, 0x22, 0xf3, 0x03, 0x3e, 0xb9,
0x24, 0x13, 0x65, 0x1a, 0x7d, 0x68, 0x4a, 0x53, 0xb0, 0x55, 0xa2, 0xa2, 0xd8, 0xef, 0x18, 0xb6, 0x5d, 0x1b, 0x47, 0x21, 0x50, 0xe9, 0x3c, 0xb1, 0xb2, 0x72, 0xb2, 0x22, 0xa5, 0x51, 0x48, 0xb4,
0x3e, 0xe0, 0x5b, 0xe8, 0xdb, 0xba, 0xa5, 0xdf, 0x3d, 0xeb, 0x9c, 0x1f, 0x4f, 0x87, 0xa1, 0x6e, 0xa2, 0xe5, 0x6a, 0x4d, 0x74, 0x26, 0xbe, 0xf8, 0x12, 0x4a, 0x0a, 0xc2, 0x1d, 0xd0, 0x25, 0x8a,
0x98, 0x7b, 0xa1, 0x55, 0xa5, 0x25, 0x8d, 0x5c, 0xc2, 0xf8, 0x03, 0x73, 0xd5, 0x7c, 0x52, 0x91, 0xca, 0x50, 0x1c, 0x0f, 0x6f, 0x86, 0x1f, 0x3e, 0x0f, 0xab, 0x07, 0xa8, 0x04, 0x85, 0x61, 0xf7,
0xca, 0xca, 0x87, 0x21, 0x74, 0x45, 0xb4, 0x62, 0xba, 0xa0, 0x87, 0x54, 0xff, 0x4f, 0x3e, 0x83, 0x7d, 0xaf, 0xaa, 0xa1, 0x1a, 0x9c, 0x0c, 0xba, 0xa3, 0x8f, 0x13, 0xd2, 0x1b, 0xf4, 0xba, 0xa3,
0xbf, 0x4f, 0xb7, 0x2f, 0xa8, 0xe1, 0xe3, 0x73, 0xe8, 0x16, 0x1d, 0xd4, 0xd5, 0x1f, 0x4f, 0xb1, 0xde, 0xdb, 0xea, 0x21, 0xfe, 0xa5, 0x41, 0x3d, 0x9d, 0x05, 0x5b, 0xf8, 0x1e, 0xa3, 0x51, 0x1a,
0x5a, 0xcd, 0x3c, 0x47, 0xa8, 0xc6, 0x49, 0xb8, 0x9d, 0x77, 0x96, 0x08, 0xc5, 0x84, 0xfa, 0x5f, 0x53, 0x7f, 0xe9, 0x25, 0x69, 0x88, 0x4d, 0x6e, 0x1a, 0x21, 0x9b, 0xfb, 0xdc, 0x76, 0x45, 0x12,
0x1d, 0x57, 0xf0, 0xac, 0x86, 0x6f, 0x0b, 0x99, 0xc0, 0x91, 0x95, 0xd0, 0x31, 0x8d, 0x5d, 0x70, 0x21, 0x5b, 0x6c, 0xd0, 0x6b, 0x28, 0xc5, 0x85, 0x63, 0x46, 0xe1, 0xf4, 0xe8, 0xac, 0xdc, 0x69,
0x2c, 0x32, 0x82, 0xc1, 0xf5, 0xfa, 0x26, 0x52, 0xcc, 0x21, 0x46, 0x99, 0x8c, 0x61, 0xb8, 0x73, 0xc8, 0xec, 0x54, 0x89, 0x63, 0x55, 0x92, 0xd0, 0xf0, 0x05, 0xb4, 0xde, 0x51, 0x15, 0xcd, 0x88,
0x6f, 0x14, 0xc8, 0x6f, 0x0f, 0x86, 0x73, 0x21, 0xf3, 0x9e, 0xc7, 0xd5, 0x10, 0x7c, 0x91, 0x8f, 0xdb, 0x7c, 0x99, 0x14, 0x16, 0x41, 0xc1, 0xb3, 0xe7, 0x54, 0x04, 0xf4, 0x1f, 0x11, 0x7f, 0xe3,
0xb1, 0xf0, 0x9b, 0x55, 0x3e, 0x35, 0xca, 0xc6, 0x94, 0xb3, 0xe2, 0x4b, 0x0d, 0x8e, 0x17, 0xd0, 0x4f, 0x60, 0xec, 0xd2, 0xe3, 0x0c, 0x32, 0xf8, 0xe8, 0x29, 0x14, 0xa2, 0x16, 0x8a, 0xe8, 0xcb,
0xdb, 0x44, 0x71, 0x1e, 0x53, 0xed, 0x8d, 0x65, 0x6a, 0xb3, 0x52, 0xcb, 0xc0, 0x31, 0x1c, 0xdd, 0x1d, 0x94, 0x8e, 0xa6, 0x1f, 0x22, 0x44, 0xe0, 0xd8, 0xda, 0x7c, 0xf7, 0xda, 0xf7, 0x38, 0xf5,
0xa4, 0xbf, 0xbe, 0xa6, 0x99, 0xd0, 0xf3, 0xee, 0xd3, 0x5e, 0x7e, 0xa4, 0x99, 0x20, 0x73, 0x18, 0xf8, 0xdf, 0xe2, 0x18, 0xc0, 0xe3, 0x0c, 0x7e, 0x1c, 0x48, 0x1b, 0x8a, 0xb1, 0x84, 0xb8, 0x93,
0xed, 0x96, 0x71, 0xdf, 0x1e, 0xe4, 0x46, 0xb8, 0x16, 0xbc, 0xf6, 0x4d, 0x75, 0x03, 0xf8, 0x08, 0x5b, 0x05, 0xc5, 0xc2, 0x4d, 0xa8, 0x8f, 0x17, 0x77, 0x36, 0xa7, 0x0a, 0x91, 0xca, 0xb8, 0x05,
0xfe, 0x3e, 0xfd, 0x9e, 0xda, 0xd3, 0xbf, 0x87, 0x70, 0xe2, 0x3c, 0x65, 0x56, 0x1b, 0x39, 0x3c, 0x8d, 0xad, 0x73, 0xa9, 0x80, 0x7f, 0x6a, 0xd0, 0xe8, 0x7b, 0x2c, 0xac, 0xb9, 0x9b, 0xbe, 0x82,
0xda, 0x5e, 0x13, 0x7c, 0x19, 0xd6, 0x6d, 0x7e, 0x58, 0xb3, 0x90, 0xc1, 0x45, 0x1b, 0xaa, 0x1d, 0x9e, 0x85, 0x6d, 0x8c, 0x0c, 0x1f, 0x2b, 0xd7, 0xa4, 0xb2, 0x9c, 0x8a, 0xeb, 0x68, 0x25, 0x12,
0xe4, 0xc1, 0x1b, 0x0f, 0x25, 0x3c, 0xd9, 0xf5, 0x34, 0x5e, 0xd6, 0xe7, 0x68, 0x58, 0x95, 0x20, 0x47, 0xe7, 0xa0, 0xaf, 0x6c, 0x37, 0xbc, 0x93, 0xae, 0x4d, 0xcc, 0x14, 0xd3, 0x42, 0x62, 0x06,
0x6c, 0x4b, 0x77, 0xb2, 0xb8, 0x81, 0xd3, 0x3d, 0x03, 0xe3, 0x9d, 0x69, 0xaa, 0x9b, 0x11, 0x4c, 0x6a, 0x41, 0xf1, 0x2e, 0x58, 0x4f, 0x82, 0xa5, 0x27, 0xfa, 0x5d, 0x22, 0x7a, 0xb8, 0x25, 0x4b,
0x5a, 0xf3, 0x4b, 0xdd, 0x1f, 0xf0, 0xb8, 0x62, 0x69, 0x6c, 0xe8, 0x56, 0xdd, 0x3e, 0x04, 0xaf, 0x0f, 0xf7, 0xa1, 0xb9, 0x1d, 0xc6, 0x43, 0x6b, 0x10, 0x1a, 0x61, 0xec, 0x39, 0x99, 0x39, 0x65,
0x5a, 0x71, 0x4b, 0xad, 0x15, 0x9c, 0x54, 0xdd, 0x89, 0x0d, 0x09, 0x6a, 0x57, 0x29, 0x78, 0xdd, 0x35, 0xe0, 0x06, 0x8c, 0x5d, 0xfa, 0x03, 0xb5, 0x3b, 0xbf, 0x8f, 0xa1, 0xa2, 0x3c, 0x25, 0xe7,
0x8e, 0x5c, 0xca, 0xe5, 0x73, 0xdc, 0xb5, 0x64, 0xd3, 0x1c, 0x1b, 0x9c, 0xde, 0x34, 0xc7, 0x26, 0x10, 0x39, 0xf0, 0xff, 0xe6, 0x98, 0xa0, 0xe7, 0xf9, 0x63, 0xba, 0xf5, 0x0f, 0xc1, 0x3c, 0xdf,
0xa7, 0x93, 0x83, 0xf7, 0xf0, 0xa5, 0xef, 0xd8, 0xdf, 0x7a, 0xfa, 0x77, 0xe2, 0xdd, 0xbf, 0x00, 0x87, 0x1a, 0x37, 0xf2, 0xe0, 0x95, 0x86, 0x18, 0x54, 0xb7, 0x3d, 0x8d, 0x2e, 0xb2, 0xdf, 0xc8,
0x00, 0x00, 0xff, 0xff, 0x8c, 0xd6, 0xc7, 0x2c, 0xc1, 0x06, 0x00, 0x00, 0x19, 0x15, 0xd3, 0xda, 0x97, 0xae, 0x64, 0xd1, 0x0a, 0x6a, 0x3b, 0x06, 0x46, 0xff, 0x7c, 0x26,
0x3d, 0x19, 0x66, 0x7b, 0x6f, 0x7e, 0xa2, 0xfb, 0x0d, 0x4e, 0x52, 0x96, 0x46, 0x39, 0xd5, 0xca,
0x9a, 0x07, 0xf3, 0xc5, 0x5e, 0xdc, 0x44, 0x6b, 0x0e, 0x95, 0xb4, 0x3b, 0x51, 0xce, 0x03, 0x99,
0xa3, 0x64, 0xbe, 0xdc, 0x8f, 0x9c, 0xc8, 0x85, 0x7d, 0xdc, 0xb6, 0x64, 0x5e, 0x1f, 0x73, 0x9c,
0x9e, 0xd7, 0xc7, 0x3c, 0xa7, 0xe3, 0x83, 0x2b, 0xf8, 0x52, 0x52, 0xec, 0x5b, 0x5d, 0xfc, 0x50,
0xbd, 0xf9, 0x13, 0x00, 0x00, 0xff, 0xff, 0xa2, 0xbb, 0x4a, 0x7d, 0x42, 0x07, 0x00, 0x00,
} }

Loading…
Cancel
Save