TUN-2260: add name/group to CapnpConnectParameters, remove Scope

This commit is contained in:
Nick Vollmar 2019-08-29 19:03:43 -05:00
parent b836cb350a
commit dc730615f2
8 changed files with 282 additions and 608 deletions

View File

@ -506,21 +506,19 @@ func startDeclarativeTunnel(ctx context.Context,
return err
}
var scope pogs.Scope
if c.IsSet("group") == c.IsSet("system-name") {
err = fmt.Errorf("exactly one of --group or --system-name must be specified")
logger.WithError(err).Error("unable to determine scope")
name := c.String("name")
group := c.String("group")
if group == "" {
err := fmt.Errorf("--group must be specified")
logger.WithError(err).Error("unable to parse group name")
return err
} else if c.IsSet("group") {
scope = pogs.NewGroup(c.String("group"))
} else {
scope = pogs.NewSystemName(c.String("system-name"))
}
cloudflaredConfig := &connection.CloudflaredConfig{
BuildInfo: buildInfo,
CloudflaredID: cloudflaredID,
Scope: scope,
Name: name,
Group: group,
Tags: tags,
}
@ -944,15 +942,15 @@ func tunnelFlags(shouldHide bool) []cli.Flag {
Hidden: true,
}),
altsrc.NewStringFlag(&cli.StringFlag{
Name: "system-name",
Usage: "Unique identifier for this cloudflared instance. It can be configured individually in the Declarative Tunnel UI. Mutually exclusive with `--group`.",
EnvVars: []string{"TUNNEL_SYSTEM_NAME"},
Name: "name",
Usage: "Friendly name for this cloudflared instance.",
EnvVars: []string{"TUNNEL_DECLARATIVE_NAME"},
Hidden: true,
}),
altsrc.NewStringFlag(&cli.StringFlag{
Name: "group",
Usage: "Name of a group of cloudflared instances, of which this instance should be an identical copy. They can be configured collectively in the Declarative Tunnel UI. Mutually exclusive with `--system-name`.",
EnvVars: []string{"TUNNEL_GROUP"},
Usage: "The group whose behavior this cloudflared instance will adopt. This behavior can be configured by editing the group's 'intent' in the Declarative Tunnel UI.",
EnvVars: []string{"TUNNEL_DECLARATIVE_GROUP"},
Hidden: true,
}),
altsrc.NewDurationFlag(&cli.DurationFlag{

View File

@ -47,7 +47,8 @@ type CloudflaredConfig struct {
CloudflaredID uuid.UUID
Tags []pogs.Tag
BuildInfo *buildinfo.BuildInfo
Scope pogs.Scope
Name string
Group string
}
func NewEdgeManager(
@ -136,7 +137,8 @@ func (em *EdgeManager) newConnection(ctx context.Context) error {
CloudflaredVersion: em.cloudflaredConfig.BuildInfo.CloudflaredVersion,
NumPreviousAttempts: 0,
OriginCert: em.state.getUserCredential(),
Scope: em.cloudflaredConfig.Scope,
Name: em.cloudflaredConfig.Name,
Group: em.cloudflaredConfig.Group,
Tags: em.cloudflaredConfig.Tags,
}, em.logger)
if err != nil {

View File

@ -8,39 +8,6 @@ import (
"github.com/pkg/errors"
)
// ScopeUnmarshaler can marshal a Scope pog from JSON.
type ScopeUnmarshaler struct {
Scope Scope
}
// UnmarshalJSON takes in a JSON string, and attempts to marshal it into a Scope.
// If successful, the Scope member of this ScopeUnmarshaler is set and nil is returned.
// If unsuccessful, returns an error.
func (su *ScopeUnmarshaler) UnmarshalJSON(b []byte) error {
var scopeJSON map[string]interface{}
if err := json.Unmarshal(b, &scopeJSON); err != nil {
return errors.Wrapf(err, "cannot unmarshal %s into scopeJSON", string(b))
}
if group, ok := scopeJSON["group"]; ok {
if val, ok := group.(string); ok {
su.Scope = NewGroup(val)
return nil
}
return fmt.Errorf("JSON should have been a Scope, but the 'group' key contained %v", group)
}
if systemName, ok := scopeJSON["system_name"]; ok {
if val, ok := systemName.(string); ok {
su.Scope = NewSystemName(val)
return nil
}
return fmt.Errorf("JSON should have been a Scope, but the 'system_name' key contained %v", systemName)
}
return fmt.Errorf("JSON should have been an object with one root key, either 'system_name' or 'group'")
}
// OriginConfigJSONHandler is a wrapper to serialize OriginConfig with type information, and deserialize JSON
// into an OriginConfig.
type OriginConfigJSONHandler struct {

View File

@ -9,59 +9,6 @@ import (
"github.com/stretchr/testify/assert"
)
func TestScopeUnmarshaler_UnmarshalJSON(t *testing.T) {
type fields struct {
Scope Scope
}
type args struct {
b []byte
}
tests := []struct {
name string
fields fields
args args
wantErr bool
wantScope Scope
}{
{
name: "group_successful",
args: args{b: []byte(`{"group": "my-group"}`)},
wantScope: NewGroup("my-group"),
},
{
name: "system_name_successful",
args: args{b: []byte(`{"system_name": "my-computer"}`)},
wantScope: NewSystemName("my-computer"),
},
{
name: "not_a_scope",
args: args{b: []byte(`{"x": "y"}`)},
wantErr: true,
},
{
name: "malformed_group",
args: args{b: []byte(`{"group": ["a", "b"]}`)},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
su := &ScopeUnmarshaler{
Scope: tt.fields.Scope,
}
err := su.UnmarshalJSON(tt.args.b)
if !tt.wantErr {
if err != nil {
t.Errorf("ScopeUnmarshaler.UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
}
if !eqScope(tt.wantScope, su.Scope) {
t.Errorf("Wanted scope %v but got scope %v", tt.wantScope, su.Scope)
}
}
})
}
}
func TestUnmarshalOrigin(t *testing.T) {
tests := []struct {
jsonLiteral string
@ -336,7 +283,3 @@ type prettyJSON string
func prettyToValidJSON(prettyJSON string) string {
return strings.ReplaceAll(strings.ReplaceAll(prettyJSON, "\n", ""), "\t", "")
}
func eqScope(s1, s2 Scope) bool {
return s1.Value() == s2.Value() && s1.PostgresType() == s2.PostgresType()
}

View File

@ -2,7 +2,6 @@ package pogs
import (
"context"
"fmt"
"time"
"github.com/cloudflare/cloudflared/tunnelrpc"
@ -129,82 +128,14 @@ func UnmarshalServerInfo(s tunnelrpc.ServerInfo) (*ServerInfo, error) {
return p, err
}
//go-sumtype:decl Scope
type Scope interface {
Value() string
PostgresType() string
GraphQLType() string
isScope()
}
type SystemName struct {
systemName string
}
func NewSystemName(systemName string) *SystemName {
return &SystemName{systemName: systemName}
}
func (s *SystemName) Value() string { return s.systemName }
func (_ *SystemName) PostgresType() string { return "system_name" }
func (_ *SystemName) GraphQLType() string { return "SYSTEM_NAME" }
func (_ *SystemName) isScope() {}
type Group struct {
group string
}
func NewGroup(group string) *Group {
return &Group{group: group}
}
func (g *Group) Value() string { return g.group }
func (_ *Group) PostgresType() string { return "group" }
func (_ *Group) GraphQLType() string { return "GROUP" }
func (_ *Group) isScope() {}
func MarshalScope(s tunnelrpc.Scope, p Scope) error {
ss := s.Value()
switch scope := p.(type) {
case *SystemName:
ss.SetSystemName(scope.systemName)
case *Group:
ss.SetGroup(scope.group)
default:
return fmt.Errorf("unexpected Scope value: %v", p)
}
return nil
}
func UnmarshalScope(s tunnelrpc.Scope) (Scope, error) {
ss := s.Value()
switch ss.Which() {
case tunnelrpc.Scope_value_Which_systemName:
systemName, err := ss.SystemName()
if err != nil {
return nil, err
}
return NewSystemName(systemName), nil
case tunnelrpc.Scope_value_Which_group:
group, err := ss.Group()
if err != nil {
return nil, err
}
return NewGroup(group), nil
default:
return nil, fmt.Errorf("unexpected Scope tag: %v", ss.Which())
}
}
type ConnectParameters struct {
OriginCert []byte
CloudflaredID uuid.UUID
NumPreviousAttempts uint8
Tags []Tag
CloudflaredVersion string
Scope Scope
Name string
Group string
}
func MarshalConnectParameters(s tunnelrpc.CapnpConnectParameters, p *ConnectParameters) error {
@ -237,11 +168,13 @@ func MarshalConnectParameters(s tunnelrpc.CapnpConnectParameters, p *ConnectPara
if err := s.SetCloudflaredVersion(p.CloudflaredVersion); err != nil {
return err
}
scope, err := s.NewScope()
if err != nil {
if err := s.SetName(p.Name); err != nil {
return err
}
return MarshalScope(scope, p.Scope)
if err := s.SetGroup(p.Group); err != nil {
return err
}
return nil
}
func UnmarshalConnectParameters(s tunnelrpc.CapnpConnectParameters) (*ConnectParameters, error) {
@ -282,11 +215,12 @@ func UnmarshalConnectParameters(s tunnelrpc.CapnpConnectParameters) (*ConnectPar
return nil, err
}
scopeCapnp, err := s.Scope()
name, err := s.Name()
if err != nil {
return nil, err
}
scope, err := UnmarshalScope(scopeCapnp)
group, err := s.Group()
if err != nil {
return nil, err
}
@ -297,7 +231,8 @@ func UnmarshalConnectParameters(s tunnelrpc.CapnpConnectParameters) (*ConnectPar
NumPreviousAttempts: s.NumPreviousAttempts(),
Tags: tags,
CloudflaredVersion: cloudflaredVersion,
Scope: scope,
Name: name,
Group: group,
}, nil
}

View File

@ -11,35 +11,6 @@ import (
capnp "zombiezen.com/go/capnproto2"
)
// Assert *SystemName implements Scope
var _ Scope = (*SystemName)(nil)
// Assert *Group implements Scope
var _ Scope = (*Group)(nil)
func TestScope(t *testing.T) {
testCases := []Scope{
&SystemName{systemName: "my_system"},
&Group{group: "my_group"},
}
for i, testCase := range testCases {
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
capnpEntity, err := tunnelrpc.NewScope(seg)
if !assert.NoError(t, err) {
t.Fatal("Couldn't initialize a new message")
}
err = MarshalScope(capnpEntity, testCase)
if !assert.NoError(t, err, "testCase index %v failed to marshal", i) {
continue
}
result, err := UnmarshalScope(capnpEntity)
if !assert.NoError(t, err, "testCase index %v failed to unmarshal", i) {
continue
}
assert.Equal(t, testCase, result, "testCase index %v didn't preserve struct through marshalling and unmarshalling", i)
}
}
func sampleTestConnectResult() *ConnectResult {
return &ConnectResult{
Err: &ConnectError{
@ -78,7 +49,7 @@ func TestConnectParameters(t *testing.T) {
testCases := []*ConnectParameters{
sampleConnectParameters(),
sampleConnectParameters(func(c *ConnectParameters) {
c.Scope = &SystemName{systemName: "my_system"}
c.Name = ""
}),
sampleConnectParameters(func(c *ConnectParameters) {
c.Tags = nil
@ -118,7 +89,8 @@ func sampleConnectParameters(overrides ...func(*ConnectParameters)) *ConnectPara
},
},
CloudflaredVersion: "7.0",
Scope: &Group{group: "my_group"},
Name: "My Computer",
Group: "www",
}
sample.ensureNoZeroFields()
for _, f := range overrides {

View File

@ -57,17 +57,10 @@ struct CapnpConnectParameters {
tags @3 :List(Tag);
# release version of cloudflared
cloudflaredVersion @4 :Text;
# identifier for this cloudflared instance
scope @5 :Scope;
}
struct Scope {
value :union {
# Standalone instance
systemName @0 :Text;
# Associated with a group of identical cloudflared instances
group @1 :Text;
}
# friendly name for this cloudflared instance
name @5 :Text;
# group whose behavior this cloudflared instance will adopt
group @6 :Text;
}
struct ConnectResult {

View File

@ -504,12 +504,12 @@ type CapnpConnectParameters struct{ capnp.Struct }
const CapnpConnectParameters_TypeID = 0xa78f37418c1077c8
func NewCapnpConnectParameters(s *capnp.Segment) (CapnpConnectParameters, error) {
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 5})
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 6})
return CapnpConnectParameters{st}, err
}
func NewRootCapnpConnectParameters(s *capnp.Segment) (CapnpConnectParameters, error) {
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 5})
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 6})
return CapnpConnectParameters{st}, err
}
@ -603,29 +603,42 @@ func (s CapnpConnectParameters) SetCloudflaredVersion(v string) error {
return s.Struct.SetText(3, v)
}
func (s CapnpConnectParameters) Scope() (Scope, error) {
func (s CapnpConnectParameters) Name() (string, error) {
p, err := s.Struct.Ptr(4)
return Scope{Struct: p.Struct()}, err
return p.Text(), err
}
func (s CapnpConnectParameters) HasScope() bool {
func (s CapnpConnectParameters) HasName() bool {
p, err := s.Struct.Ptr(4)
return p.IsValid() || err != nil
}
func (s CapnpConnectParameters) SetScope(v Scope) error {
return s.Struct.SetPtr(4, v.Struct.ToPtr())
func (s CapnpConnectParameters) NameBytes() ([]byte, error) {
p, err := s.Struct.Ptr(4)
return p.TextBytes(), err
}
// NewScope sets the scope field to a newly
// allocated Scope struct, preferring placement in s's segment.
func (s CapnpConnectParameters) NewScope() (Scope, error) {
ss, err := NewScope(s.Struct.Segment())
if err != nil {
return Scope{}, err
}
err = s.Struct.SetPtr(4, ss.Struct.ToPtr())
return ss, err
func (s CapnpConnectParameters) SetName(v string) error {
return s.Struct.SetText(4, v)
}
func (s CapnpConnectParameters) Group() (string, error) {
p, err := s.Struct.Ptr(5)
return p.Text(), err
}
func (s CapnpConnectParameters) HasGroup() bool {
p, err := s.Struct.Ptr(5)
return p.IsValid() || err != nil
}
func (s CapnpConnectParameters) GroupBytes() ([]byte, error) {
p, err := s.Struct.Ptr(5)
return p.TextBytes(), err
}
func (s CapnpConnectParameters) SetGroup(v string) error {
return s.Struct.SetText(5, v)
}
// CapnpConnectParameters_List is a list of CapnpConnectParameters.
@ -633,7 +646,7 @@ type CapnpConnectParameters_List struct{ capnp.List }
// NewCapnpConnectParameters creates a new list of CapnpConnectParameters.
func NewCapnpConnectParameters_List(s *capnp.Segment, sz int32) (CapnpConnectParameters_List, error) {
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 5}, sz)
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 6}, sz)
return CapnpConnectParameters_List{l}, err
}
@ -658,147 +671,6 @@ func (p CapnpConnectParameters_Promise) Struct() (CapnpConnectParameters, error)
return CapnpConnectParameters{s}, err
}
func (p CapnpConnectParameters_Promise) Scope() Scope_Promise {
return Scope_Promise{Pipeline: p.Pipeline.GetPipeline(4)}
}
type Scope struct{ capnp.Struct }
type Scope_value Scope
type Scope_value_Which uint16
const (
Scope_value_Which_systemName Scope_value_Which = 0
Scope_value_Which_group Scope_value_Which = 1
)
func (w Scope_value_Which) String() string {
const s = "systemNamegroup"
switch w {
case Scope_value_Which_systemName:
return s[0:10]
case Scope_value_Which_group:
return s[10:15]
}
return "Scope_value_Which(" + strconv.FormatUint(uint64(w), 10) + ")"
}
// Scope_TypeID is the unique identifier for the type Scope.
const Scope_TypeID = 0xc54a4a6fd4d87596
func NewScope(s *capnp.Segment) (Scope, error) {
st, err := capnp.NewStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1})
return Scope{st}, err
}
func NewRootScope(s *capnp.Segment) (Scope, error) {
st, err := capnp.NewRootStruct(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1})
return Scope{st}, err
}
func ReadRootScope(msg *capnp.Message) (Scope, error) {
root, err := msg.RootPtr()
return Scope{root.Struct()}, err
}
func (s Scope) String() string {
str, _ := text.Marshal(0xc54a4a6fd4d87596, s.Struct)
return str
}
func (s Scope) Value() Scope_value { return Scope_value(s) }
func (s Scope_value) Which() Scope_value_Which {
return Scope_value_Which(s.Struct.Uint16(0))
}
func (s Scope_value) SystemName() (string, error) {
if s.Struct.Uint16(0) != 0 {
panic("Which() != systemName")
}
p, err := s.Struct.Ptr(0)
return p.Text(), err
}
func (s Scope_value) HasSystemName() bool {
if s.Struct.Uint16(0) != 0 {
return false
}
p, err := s.Struct.Ptr(0)
return p.IsValid() || err != nil
}
func (s Scope_value) SystemNameBytes() ([]byte, error) {
p, err := s.Struct.Ptr(0)
return p.TextBytes(), err
}
func (s Scope_value) SetSystemName(v string) error {
s.Struct.SetUint16(0, 0)
return s.Struct.SetText(0, v)
}
func (s Scope_value) Group() (string, error) {
if s.Struct.Uint16(0) != 1 {
panic("Which() != group")
}
p, err := s.Struct.Ptr(0)
return p.Text(), err
}
func (s Scope_value) HasGroup() bool {
if s.Struct.Uint16(0) != 1 {
return false
}
p, err := s.Struct.Ptr(0)
return p.IsValid() || err != nil
}
func (s Scope_value) GroupBytes() ([]byte, error) {
p, err := s.Struct.Ptr(0)
return p.TextBytes(), err
}
func (s Scope_value) SetGroup(v string) error {
s.Struct.SetUint16(0, 1)
return s.Struct.SetText(0, v)
}
// Scope_List is a list of Scope.
type Scope_List struct{ capnp.List }
// NewScope creates a new list of Scope.
func NewScope_List(s *capnp.Segment, sz int32) (Scope_List, error) {
l, err := capnp.NewCompositeList(s, capnp.ObjectSize{DataSize: 8, PointerCount: 1}, sz)
return Scope_List{l}, err
}
func (s Scope_List) At(i int) Scope { return Scope{s.List.Struct(i)} }
func (s Scope_List) Set(i int, v Scope) error { return s.List.SetStruct(i, v.Struct) }
func (s Scope_List) String() string {
str, _ := text.MarshalList(0xc54a4a6fd4d87596, s.List)
return str
}
// Scope_Promise is a wrapper for a Scope promised by a client call.
type Scope_Promise struct{ *capnp.Pipeline }
func (p Scope_Promise) Struct() (Scope, error) {
s, err := p.Pipeline.Struct()
return Scope{s}, err
}
func (p Scope_Promise) Value() Scope_value_Promise { return Scope_value_Promise{p.Pipeline} }
// Scope_value_Promise is a wrapper for a Scope_value promised by a client call.
type Scope_value_Promise struct{ *capnp.Pipeline }
func (p Scope_value_Promise) Struct() (Scope_value, error) {
s, err := p.Pipeline.Struct()
return Scope_value{s}, err
}
type ConnectResult struct{ capnp.Struct }
// ConnectResult_TypeID is the unique identifier for the type ConnectResult.
@ -3704,229 +3576,223 @@ func (p ClientService_useConfiguration_Results_Promise) Result() UseConfiguratio
return UseConfigurationResult_Promise{Pipeline: p.Pipeline.GetPipeline(0)}
}
const schema_db8274f9144abc7e = "x\xda\xacY}l]\xe5y\x7f\x9e\xf3^\xfb\xd8\x89" +
"o\xae\x0f\xe7\"b\x13\xcbU\x04jCI\x06\xf1\xb2" +
"\x11o\xeb\x8d\xed$\xb5\xdd|\xdc\xe3\x8f\x00!\x91r" +
"r\xef\xeb\xeb\xe3\x9c{\xce\xcd\xf9\x08v\x946\x90\x85" +
"\x01\x1e)\x09m&\x92\x86\x0a\xb2f|(]\x09\x0d" +
"\xda\xca\xa0*\xd3\x18d\xad\x04h0\xc1\xc6\xfeX!" +
"\x9a@\x8b\x18\xb4\x12\xa2*\x9c\xe99\xdf\xbe\xbeu\xc2" +
"\xd4\x7f\x92\xab\xe7<\xef\xfb>\x9f\xbf\xe7\xc37e[" +
"\xd7\x0977\x99Y\x00\xe5TS\xb3\xf7\xa7\xd5WO" +
"\xff\xd1\xf1\x9f\x1f\x06\xa9S\xf0\xbe\xf5\xfcp\xfeS\xe7" +
"\xd0\x7f\x00`\xcf#\xcd\xfbQ>\xd7,\x02\xc8?l" +
"\xde\x0a\xe8\xfd\xebM\x07\xde\xdb\xf5\xabc\xf7\x81\xd4\x89" +
"\x09gF\x04\xe8y\xa9y\x16\xe5\xffl\x16\x81y\x8f" +
"\xdc\x91\xff\x17|\xf4\x93c }\x05\x01\x9a\x90>\xff" +
"\xa4y\x91\x00(\xbf\xde\\\x00\xf4^\xbd\xf1\xf9\xe7\x8e" +
"\xfe\xf8\xde\xef\x81\xf2eD\x08\xce\x7f\xd4\xfc\x1b\x04\x94" +
"\x9bDb\xf8\xe8\x07_\xcd\xfc\xf0\xd5\xab\xbe\xef3x" +
"g^\xbf\xf5\x99\xa3?\xfe\xd2\x070.\x88\x98\x01\xe8" +
"Y)Z\xc4\xbbV\xfco@\xef\xbbo\xbd\xb0\xa5z" +
"\xec\xe4i\x90\xbe\x1c\xdd\xd5\xd1\"\x08\x90\xf1\xd6\xfc\xfb" +
"\xc5\xad\x9b\x9f\x99x<\xf8\x12\xc8\x91my\x86\x8ev" +
"\xb5\xd03\xaf\xdc\xd9\xfe@\xdf\x1f?\xf88(\x9d\x98" +
"\xd2\xa7\xa9\x898\xfbZfQ\xbe\xbd\x85~\x8e\xb7\xdc" +
"\x8a\x80\xde\xec\xda\x17\xb6\xfd\xea/\xec\xa7@Y\x89\x19" +
"\xef\x9f\xee\x7fw\xdf\x8a''^\xf6\xa5b\x00=\x17" +
"ZO\xd3\xd5o\xb7\xfe\x08\xd0\xcb\xfe\xc3\x0d[\x1e|" +
"o\xd39\xba:e\xd4@\x88\x99E\xbd(\xdf\xbf\x88" +
"\xecz\xcf\"\xe2~\xed\xc6m?\xfd\xe9\xd3\x95s\xf5" +
"\x82\x08\xc4}\xfd\xe2a\x94\xd7.&\xee5\x8b\x89\xfb" +
"\xea!|\xe7g7g\xfe.\xd4\x8b\x11\xd3\xfb\x8b?" +
"\xa0\xc7?\xf3\x19\xee\xf8\xed\xb3\xff\xb8\xe1\xc37~\x92" +
"v\xc0#m\x029\xe0\\\x1b)\xdeu\xa9?k|" +
"x\xe8gs\xfd\x18\xdc\xf4v\xdb0\xca\x97\xda\xe8\xb9" +
"\xf7\xdb\xe8\xb6\xbfr\xdfz\xc3\x1c\x1e~\xa9^8\xff" +
"\xda{\xb2\x02\xca\xc7\xb2\xc4}$[\x00\xfc\xe4\xa9{" +
"\x8f\x0e\xbd\xbb\xfee\xa5\x133\xf5\xbc\xc7\xb2\xfbQ>" +
"C\xbc=\x8fe\xbb\xc9\xa2\xb1\x0d\xeb\xd8}\xbd__" +
"2\x85\xf2\xc5%\xf4\xf3\xbf\x96\xf8\xec\xc3w|\xe7\xa1" +
"\xa6\x8b\xdfy\xb9\xde\xa8\xa2o\x81\x9c\x85\xf2g9\xfa" +
"\xf9i\xeeq\x01\xd0\xfb\xcd\xd9?\xe7\x17W\xbdr\x01" +
"\x94/aJ\x8dq\x14Q\x00\xe8\xb9x\xd5j2\xd9" +
"\xa5\xab\xee\x04\xf4:\x9f\xfe\x93\xbf\xed/\xbf\xfd\xf3:" +
"\x8b\x90 \xf2f\xf9c\xf9v\x99~\x8d\xcb\xc4{\xef" +
"Wg\xf6o\xb9~\xf6\xcd\x86\x069'\xcf\xa2|\xc1" +
"\xe7~\xc9\xe7\x16.\xaa\x1dw\xfd\xdb\xd7\xdeI\xc5\xe7" +
"\x9a\xfc/\x112\xde\x96mwL\xb5~\xf3\xddw\xd3" +
"\xf1\xb9\"\xef\xfb\xf1\xcf\xf2\xe4\xa6\xf3\xd2C\xf2\xf3\x8f" +
"\xfd\xcd{\xf4\x90X\xef\xa7\x9d\xf9\xed(\xef\xcd\xd3\xcf" +
"j\xde\xd77\xce\x93FQ\xa4]\xd3\x8b\xf2\xcc5$" +
"\x97{\x0d\xc9\xb5fW\x1f\xdfq\xcbm\x1f\x80\xd4\xc9" +
"\xe6d\xfd\xb3\xc4\xf9\x12q\xf6\xbcx\x8d\x88\xf2\xde\xa5" +
"\"\x80\xf7\xed\xca\xf6\x0b\x1f\x0d<\xf6\xbf\xf5\x97\xfb\x0a" +
"\xdd\xbe\xb4\x17e\x8d\xf8z\xf8R\xdfU=7\xff\xe5" +
"\xa5\xe3\x7f=\xf0\xd1\xbc\xdb\xcfu\xf4\xa3\xfcb\x07\xc9" +
"\xf1B\xc7\xd7\xe5K\x1d\xfe\xe5\xdfZ\xbfu\xed\xf2\x17" +
"?N[\xe2\xcd\x8e\x8f\xc9\x12\xefw\x90%&n\xf9" +
"\x9f\xaf_\xff\xed\x7f\xfe\xb8\xce=>ck\xe7\x0d(" +
"wt\xd2\x8dWw\x16\x00?\xdc\xf8\xfd7:s\x9d" +
"\xbfn$\xe8\xda\xce)\x947\x13o\xcfP\xa7/\xe8" +
"m\xbf<yg\xe1{\xbf\xfe\x84\xf4bu\x986s" +
"\xedv\x94\x8f\\K7\xdf\x7f-\xa5\xc2\xa6\xb3o\x7f" +
"m\xf2\xf8+\x9f\xd6\x1b\xc1w\xc8\x9ae\x87P\x1eZ" +
"F\xdc\x1b\x96\x112\x1d\xf8\xf0\xc4\xe0\x83;\xce~\x9e" +
"\xd6je\xd7s\xbe\x7f\xbbH\xab\xa9\xe3\x07\x9c\xc1\x87" +
"\x8fx\x8d\xd2pgW?\xca\xd5.\xbaM\xeb\xfa\x11" +
"\xac\xf4\x1c\xd70\xb8n\xd52\xa5?\x88~\x96V\x95" +
"\xd4\x9aQ\xeb\xdd0\xad\xd9\x8efT\xc6|z\xa1h" +
"\xeaZi\xa6\x88\xa8\xb4Q\xa0K]\xbd\x00\x88\xd2\xd5" +
"\xdb\x01P\x90\xa4~\x80\x82V1L\x8b{e\xcd." +
"\x99\x86\xc1\x81\x95\x9c\x83\xbbU]5J<~\xa8i" +
"\xfeC\x83\\\xd7\xcd[MK/o\xb5\xb4\x8af\x0c" +
"\x98\xc6\x84V\x01(\"\xc6\xc7\xc4\xf9\xc7\x06t\x8d\x1b" +
"\xce(\xb7\xf6i%\xbe\xca\xb5yp\xce\xb5TG3" +
"\x8d\xebF\xb8\xed\xea\x8e\x0d\xa0dX\x06 \x83\x00R" +
"\xb6\x17@ia\xa8\xe4\x05,X>\x03\xb6'\x99\x07" +
"\x88\xed\x90\xbc\xd9<\xff\xcd\xc0\x16\xf4&\xb7V\xb9\x86" +
"\xc5+\x9a\xedp+ _W(\xaa\x96Z\xb5\xd3\x0f" +
"\x9e\x04P\xda\x19*\xcb\x04\xf4*\x96Z\xe2En\xa1" +
"f\x96\xb7\xa8\x869\xcax\x09\x9b@\xc0\xa6\xd4\xa3\x0d" +
"\x1c\xb1Q\xd5t^\x0e\xb4[U\xea\xf6\xffW\xdaY" +
"\xa6\xcd\xf3\xfcG\xd4\xed\x00\xca.\x86\x8a.`\x16?" +
"\xf7\xf2T\xfe$m?\x802\xc9Pq\x04\xcc\x0a\x9f" +
"yy\xdfk{\x97\x03(:CeZ\xc0,\xfb\xad" +
"\x97\xa7\"#\xb9S\x00\x8a\xc3P\xb9K@\xcfvk" +
"dS\x1b\x98ia{\x12\xca\xa1ux\xb9B\x966" +
"\xa0\xc0Kdhl\x8f\xd09`\x10\xcb\xe6$\xb6'" +
"\xc5'<f\xf1}\xdc\xb2y\x11r\x969=\x83\xed" +
"\x09J\xd7Y=\xfbE\xad\x1e9:>\xb5\xf0y?" +
"4K\xceu\xc5\xeey\xce\";\xb61T\x96\x0a\xe8" +
"\xd5\xe8+w80\xcb\xc6\xf6\xa4\xa8\xd7I\xdb \x9c" +
"\x07\xe8\xdf\x81\xe0\x95bx\x8be\xfb\xe1\xac,\x8d\x1f" +
";A\x8f=\xccP\xf9\x81\x80\x12b\xe0\xb3\xc7,\x00" +
"\xe5Q\x86\xcaY\x01Q\x08<\xf6\xe4i\x00\xe5,C" +
"\xe5\xef\x05\x94\x98\x108\xec\xd9\x1b\x00\x94\xa7\x19*\xbf" +
"\x10P\xca\xb0<50\xd2\x05\x0a\xb6_0T\xde\x12" +
"Pj\xca\xe4\xb1\x09@zs5\x80\xf2\x1aC\xe5\x1d" +
"\x01=3\xc8/R\xca\xc1,\x08\x98\x05\xf4J\xba\xe9" +
"\x96't\x15\xba-^\x1eZ\x1f\xd3\x0d\xb7Z\xb4\xf8" +
">\x0dM\xd7\xees\x1c^\x15k\x8e\x8d\xcd `3" +
"`\xceQ+6.\x01,2\xc4\xf6\xa4\xd0\x01\x121" +
"\xbe\x13-^\xde\xc6-[c\xa6\x81m `\x1b`" +
"\xb7]2k\x1c\xdb\x93\xdayy\x9b\x8e\x84\xd1C\xb1" +
"\x13&\x82iibE3\x946\x96Y\xe6y\xa1\x01" +
"7\x90]\xd61T6\x09\xd8\x85\x9f\x13\x99l84" +
"\x02\xa0\x0c2T\xc6\x04\xec\x12>#2YQ!\x1f" +
"\x14\x19*;\x04\xccM:N\x0d\xdb\x93\xea\x18\x0au" +
"'\xdfm\x9b\xa5=\x1c\x90\xa0\"\x86\xea\xf0\xebd\x08" +
"]\xc0\xf42\xb6'\x9dl\x9dF\xacA\x94\xf8\x01R" +
"p6X\x96i\xf9\xa8\x1a\x87\xc6\x86\xd5\x89\x12Qd" +
"\x0cmO4\x90\x84u\x81Z\xca\xeeD\xfe\xee\x92\xea" +
"\xda<\xb2\xb1gq\xc7\x9a\xe9\x9bp\x80q+\xc6\x18" +
"{\xd2t\xf5\xf2\x08\x07\xd1\xb1f\x10A@\\\x18y" +
"\xd6\x9b\x83)\x93\x07!\x9c\x92\x93dZ\xcfP)&" +
"rn&\xda&\x86\xcam$gh\xfeq2\xff\x18" +
"C\xa5&\xa0\xa7S\xee\x1a\x83&0\xdb\x89\xc5\x0d\x88" +
"E\xd3\x0fL\x11\x04\x14\x01=\xb7f;\x16W\xab\x80" +
"q\xa4\x11\xff\x92/\x00\xd1uPQTs~\xce7" +
"\xd6!N\xc3\xcd\xc3i%\xc2<\x1c\xefO\x8c\xdd8" +
"\x91&M\xdb1\xd4*\x07\x80H\xb1\x83f\x8d0\x92" +
"\x10$n3\xebb\xe3\x8bW\xb6\xa0\xca\xcc\xa9k\xa7" +
"Se\xa6\x14\x9eF\xff\xf8\x80i\x88\x13Z\x05\xdb\x93" +
"^\xabN\x80\x06~\xefs\x9dIn8Z\xc9\x7fp" +
"\x9e\xdf\x97'\xf1\x19\xdblhu\xca\x90\x91\xcd6\xef" +
"N\x0c)\xee\xe131\x04\xf0\xaa\xaa\xe9\xb1\xf7Ck" +
"\xf6\x81\xf8\x8d\x84g\xa1\xe4\x19%\x04\xf1\xa5\xf2m\x80" +
"\xa9\xae\\\xca\xae\x06\xa1{\x9f\xaa\xbb|\xc1\xe6&\xac" +
"bA\x0d+\x04\x06\xa6\x0b\xf3\xb1\x9a\xdf\x9c\x05P\xee" +
"b\xa8<\x90R\xf3\xfe\x87\x00\x94\x07\x18*\x0f\xa7\xd4" +
"<N\xa1q\x94\xa1r\x8a \x9a\x05\xe0r\x82|r" +
"\x8a\xa1\xf2\x84\x80\x98\x09\x10\xfa\x0c!\xf4\x13\x0c\x95\xf3" +
"\x82\x8f\xaf\x83}\x03\xa6\x81\xa1\x106@\x84\xae\xde$" +
"W-g7W\xd1\x192\x1cn\xedSQ\x8f\xb2\xf8" +
"\xa0\xa3U\xb9\xe9:qVW\xd5i\xbfC\xc0\xf2`" +
"pJT\x1d\x1b[A\xc0VJ\"\x9b[\x03\x16/" +
"#\xf9S\xd5\x8b*s&\xe7\x998s9\xc4\xcd5" +
"0\x0f\xf5\x17\x07\x18*\xf7Q\xf6cj\x90\x95\xee\xe9" +
"\x05\xc1O~\xd2\xb9\xda\x9f\xf4!~\xfd\xa2\xaa\xb4\xf7" +
"\xa1\xa4\xe1\xf0\xebW3\xddx21x(\xda\xa0\x09" +
"\x85 \xa9\"\x99\x0bA\xb0\x1c$\x80\xd3x\xa2gX" +
"\xd654\x8d1\xdf@\x98X\xa8dVk\x16\xb7m" +
"\xd4LCqU]c\xceL|pA\x1b\x10z\x04" +
"Y\xb7\xb5\xd6\xed;\x89\x8cpSd\x04\xb9\x0f\x87\x01" +
"F\xd7!\xc3\xd1M\x98\x84\x89<\x84\xfd\x00\xa3\xeb\x89" +
"^\xc4$R\xe4\xcd\xd8\x090:H\xf41\x14\x10\x83" +
"X\x91\x15|\x0a`t\x8c\xc8\xbb0\xa9\xe8\xf2N\xff" +
"\xfa\x1dD\x9f\xc4\xa4\xa8\xcb\x1co\x00\x18\xddE\xf4\x03" +
"Do\x16|\x0b\xca38\x050:M\xf4\xc3D\x17" +
"\x9b\xf24\x1f\xc8w\xa3\x050z\x17\xd1\x1f z\xcb" +
"\xd2<\xb6\xd0\xfc\xe1\xd3\xef#\xfaw\x89\xde\xda\x91\xc7" +
"V\x00\xf9\x18\x1e\x02\x18=J\xf4SD_\x84y\\" +
"\x04 \x9f\xc0\x93\x00\xa3\xa7\x88\xfe\x04\xd1\x177\xe7q" +
"1\x80|\xc6\x97\xe7Q\xa2\x9f\xc5\x18\x82\x86\xcai$" +
"\xa4p\xd2\x92.\x80\x99v\x1c\x86<\x9c40\x80\xe9" +
"\xa2\x99\xa3Q\x03s\xc9\x0e\x09\x10s\x80^\xcd4\xf5" +
"-s\x11\xf6r\x8dH\x18\x16\x903\x8d\xa1r\x9c_" +
"A\x10m2\xa1\xbb\xa4\xeaC\xb5X\x12\xcd\xees\x1d" +
"\xd3\xadAwYux9\xae\x91\x96kl\xb4\xcc\xea" +
"\x18r\xab\xaa\x19\xaa\x0e\xf1\x97\x85b+\xe7\xbaZ\xf9" +
"\x8a\xf1lU\x80ZJK\xd2\xd9\xaf\xa0\xea\xf4\x15\x86" +
"\xca\x1f\xa6;\xfb\x9b\x09jod\xa8\xdcB\xdd\xfa\x8c" +
"\xed\xf0\xea\x16\x15X\x92#\xdd\x15\xcbtk\xf3\x1e\x16" +
"\xea\x1f\xee\xae\xf5\x8e\xa9~Z\xb7\xc4i\xbd\x82:\xa8" +
"\xeb\x18*7\xa5Po\xe5\xeaD\x8e\\:\x1b\x03\x91" +
"\xe7\xbd\xd4\xa0\x83\x1b\xaf\xabbA\xd7\x1e\x94\x96\xd4\xeb" +
"\xfd\xc9\xeb\xf1\xe3V\xa8\xee\xa0\x80\x07m\xb7T\"k" +
"G\xe6\x9f\x08g#\xe8\xa6\xbbS\x81\x10\xaf-\xc2@" +
"\xb8\xd2\x8e\xa1\xc2\x9d\xe0\xd7\x901aR\xa9\x15\xd5\xaa" +
"\xfd\xff<=\xc2\xed\x1c\x8d&\x97\x9d@\xe3E\xc4\xe5" +
"K\xf3\xe0\xd8X1\x19\x93Y\x80\xcai@\x1aI\x03" +
"R\x82GSi\xdc\x89:HY\xf1\x01\xa0H\xf4\x1d" +
"\x98\xcc\x17\xf2\xedxz\x0e\xf0d\xfa\x02@\xe2\xfe\xf5" +
"e\xa2\xd7|@\xc2\x00\x90\xaa\xfe\xfd:\xd1\xa7\xd3\x80" +
"\xe4\xe2\xec\\@b\x11 \x11\x90\x1c&\xfaQ\x1f\x90" +
"2\x01 \x1d\xc1g\xe6\x00OkS\x00H'\xf0\xb9" +
"9\xc0\xb3\xa89\x00\xa43>\xff\x13D?\xef\x03R" +
"\x7f\x00H\xe7|\x00{\x9a\xe8\xcf\x13 \xb9\x96>\xea" +
"X\x9a\x01XI\x82\xb5T\xfb\x06\xe7\xb5>\xc8\xe9\xda" +
">\x1e\x17\x8b\xb2\xa6\xea\xeb]U\x87\xeeQG-\xed" +
"I\xdad\xdd\x1eT\x8d\xb2\x8d\x93\xea\x1eN%FL" +
"\x17aG\xb7\xb7qK\x9b\x00L\x1a\xeb\xb8\xad\xc9\x15" +
"M\xb3\xbe\xdb\xf1\xfb3n\x05h\x16\x7f\xab\xaa\xd3C" +
"e\x9d\x0f`\xd4\x9a0#)q\x1a}1\x0d\x03\x83" +
"~aL\xeb\x9e\xdb\x08\xd4\xc2V=j(\xc6\x0au" +
"\x9d\x02\x9f\xae\xf1\x923`\xa2\xe1h\x86\xcb\xe7]P" +
"\x9at\x8d=\xbc\xbc\x01\x8d\x92Y\xd6\x8c\x0a\xcc\x9b\x11" +
"\xd8\xef\xdaN\xa4:\xa8\x96\xb0%\x8b\xd7\xed\xd2\x0a\xea" +
"\x070\xec\x07\xa4\xded\xca.\x94\xfcS\x05\x8b\xabv" +
"R\x1a\x16z-\\F\x05IF\xaf\xb5\xb3&\x80x" +
"y\x8d\xd1\xceO\xda\xbb\x1f\x04I\x131Y\x95b\xb4" +
"\x19\x95vZ H\xe3\"\x0a\xf1\xdf\x0c0\xda\xf7K" +
"C\xb3 H\x1bDd\xf1\xa2\x1f\xa3\x8d\x9b\xb4\xb6\x1f" +
"\x04i\xa5\xe8ES\x05\x14\x02q\xd6\xa1\x17%>t" +
"\xfb\xa9\xbf\x0e\xbdhO\x81\xd1\xf4\x01\xb0\x0e\x0f\x86\xf5" +
"h\x1d\xa6\x97[\xecw\x8d\x00\x8d\xfbR\xc2\xc8i\x86" +
"\xca\xe1\x04#\xef\xa6^\xf50C\xe5hj\xec:\xf2" +
"T\xba-\x0d7\x07'\x0e\x85{\x87\xf3\xa9\xcd\xc19" +
"\xeaU\xcf3T^\x13\x92B\x1d\x85]\xb4\x0fB\xd3" +
"\x8a\xe6\xc0\x05\xd6Bap\x86-c\xfdr\xc8+\x9b" +
"\x93~K\x89\xc1U6$\x88\x9d\xde\x18-Im\x8c" +
"0\x9a@\xc59\x00\x9f\xde\x1f-Y\x183\xe7\xccS" +
"\xe1\xd8@Q\x13\xfdE\x03\xa3\xbf-I\x12y?+" +
"z\xd1\xcc\x85Q\xb9\"\xe7\xa5]\xf6\x05\x07\xcf\x11\xde" +
"m_I%\x88\xb6\xcc\x97\xdf\x1f\x04\xef\xe4(\xd8\xe2" +
"9(\xb8w*\xb5\xc5\xd2\xcdp\x84\xcbmIU\xed" +
"\x85l\x15\x08\x1cu\xbe9:\\\x17~\xcb\x93\xf0\x8b" +
"\x1b\x84\xbb\x97'\xc3@<\x16\xdd3\x1c\x06\xe5\xa3q" +
"\xa7+=2\x9bl\xb8\xe2\xf0{r8\x19\x8bDn" +
"Y\x91\x9c\xa2k%\xb0\xa9\x9b\x95M\x9a\xc1m\xea\xfd" +
"\xea\xb6\x015nUU\x83\x1b\xe8\x10\x18\xb9\x16!\xea" +
"\\\xe4\x1aZ\x9fj\x19\x17R\x7f4\x0c\xf6 \xd6\xc3" +
"\xf2\x9a\x1a}O\xa7\xd60\x91\xf2\xcas\xe1zcW" +
"J\xf9\x9d4\xfa\xee`\xa8L\x0a\xe8\xa9\xaec\x8e\xd7" +
"\xca*:|\xa3\xc5\xf7\xba\\4J3\xc9\x00G\xa3" +
"L\xc9\x1e\xc7\x1a5\x9d\x1b-^\xd8\xeb\xf24C\xb4" +
"8\x06Q3\xcb\xf36\xc6\x0d\x9a\xad[\xf9\xeeQ\xb3" +
"\xb4\x87;s\x16\xea\x01\\F\xaa\xa8#\xc9\xd68\xd2" +
"D\x1bI\xcdj\x11\x8c\xec\xa5\x80\xaa1T\x0e\xa4`" +
"df6qx\xe3\xea\xfa\xfb)\x88\x0b(\xd9p\xab" +
";R\xe0W\x94h\xc9_I.\xdfr\x85{\x82\xb0" +
"c\xbd\x92]\xc8\x9ce]\x18\x10\xcaT\xb2?\xf2\x83" +
"\xbc=\xf9sn(\x83\x1d\xb6\x8e\xc0&\xcc\x06]a" +
"0U\x0d\x98\x10Bk\xfdF\xe7\xff\x02\x00\x00\xff\xff" +
"\xd4\xcdz3"
const schema_db8274f9144abc7e = "x\xda\xacY{p\\\xe5u?\xe7~\xab\xbd\x96-" +
"y\xf7r\x15\x88\x84=j<0\x09\x04S\x8cK\x1b" +
"\xd4N\xd6\x92,Gr\xfc\xd8O+\x1b0\xf6\x8c\xaf" +
"w?\xad\xae}\xf7\xde\xf5}\x18\xc9cb\xf0\x98\x02" +
"*\x04C\xf0\x0cv C\xdc\xba<\x06\xca#0\x1d" +
"\xa8\x9d\x92N)\xd0\x94!L\xa0S\xb7\xc9\x1f\x04<" +
"\x0dL2\x04B\x87\xd2\x01n\xe7\xdc\xb7VB\xb6;" +
"\xfd\x07\xae\xcf\x9e\xef\xfb\xce\xf3w\x1e\xba\xe2\xe7\x0bV" +
"I+\xda\xfe\xbe\x03\x80\xdf\xdb\x96\xf7\xff\xac\xf1\xda\xb1" +
"?>\xfc\xd3\x83\xa0\xf4H\xfewN\xac\xed\xfa\xc4=" +
"\xf0\x1f\x00\xb8r(\xbf\x17\xd5\xeb\xf22\x80\xba)\xbf" +
"\x11\xd0\xff\xf9\x15\xfb\xde\xd9\xfe\xfb\xbbo\x03\xa5\x07S" +
"\xce\x9c\x0c\xb0\xb2\x91\x9fF\xf5\x96\xbc\x0c\xcc\x7f\xe0\xfa" +
"\xae\x7f\xc6\x07?\xbe\x1b\x94\xaf!@\x1b\xd2\xcfZ~" +
"\xa1\x04\xa8N\xe5K\x80\xfek\x97\x9dx\xfe\xd0\x8fn" +
"\xfd>\xf0\xaf\"Bx\xfeH\xfe\x7f\x10P}<`" +
"\xf8\xe0\xaf\xbe\x9e{\xfc\xb5\xf3~\x100\xf8\xc7_\xbf" +
"\xe6\xe9C?\xfa\x83\xf7`\x93$c\x0e`\xe5\x9by" +
"\x9bx\xdf\xca\xff'\xa0\x7f\xef\xbf\x9d\xdc\xd0\xb8\xfb\xe8" +
"1P\xbe\x1a\xdf\xf5\x13Y\x92 \xe7_\xf5\xef\xa77" +
"\xae\x7fz\xfc\xa1\xf0\x97P\x8eg\xe5\xa7\xe9\xe8\x8b2" +
"=\xf3\xf2\x0d\xc5;\xfa\xff\xe4\xae\x87\x80\xf7`F\x9f" +
"6\xd2x\xe5\xbb\xf24\xaa\xb8\x80>?\x93\xefB@" +
"\x7f\xfa\xea\x93\x9b\x7f\xff\xe7\xce\xa3\xc0\x97c\xce\xff\xc7" +
"\xdb\xdf\xdes\xc9#\xe3/\x05R1\x80\x95\x8f\xb7\x1f" +
"\xa3\xabO\xb6?\x01\xe8w\xfe\xdd\xa5\x1b\xeezg\xdd" +
"Stu\xc6\xa8\xa1\x10\xdb\x16\xf6\xa1\xdaXHv\xd5" +
"\x17\x12\xf7\xcf.\xdb\xfc\xe3\x1f?Y\x7f\xaaU\x10\x89" +
"\xb8\xdb\x17\xadEu\xe9\"\xe2\xee^D\xdc_\x1a\xc1" +
"_\xbc\xb0\"\xf7\xb7\x91^\x8c\x98^]\xf4^`\x92" +
"\x80\xe1\xfaO\x9f\xfd\x87\xa1\xf7\xdfx.\xeb\x80\x9b;" +
"$r\xc0\xe1\x0eR|\xe9o\x07:\xcd\xf7\x0f\xbc0" +
"\xd3\x8f\xe1M';\xd6\xa2\xfaz\x07=\xf7j\xc7\x13" +
"\x80\x1f?z\xeb\xa1\x91\xb7W\xbf\xc4{0\xd7\xaa\x88" +
"\xde\xb9\x17\xd5\x1b;\xe9s\xaa\xb3\x97l\x94X\xa5\x85" +
"=\xd0\xe4\x91\xc5;Q=\xb9\x98>\x9f[\x1c\xb0\xaf" +
"\xbd\xfe{\xf7\xb4\x9d\xfe\xdeK\xadf\x92\x037\x16l" +
"T\xdf,\xd0\xe7\xeb\x85\x87$@\xbf\xe7\xc9?\xfd\x9b" +
"\x81\xda\xa9\x9f\xb6\xc8M\x97\xab'\xcf\xfbP}\xe5<" +
"\xfaz\xf1\xbc\x1b\x00\xfd[\xbf>\xb5w\xc3\xc5\xd3o" +
"\xb6\xda4\x10\xfc+\xea4\xaaW\xab\xc4}\x95J\xdc" +
"\xd2i\xad\xfb\xa6\x7f\xfd\xe6/2Qt\\\xfd\x15B" +
"\xce\xdf\xb0\xf9\xfa\x9d\xed7\xbe\xfdv6\x8a\x8e\xa8\x81" +
"\xb5\x1fW\xc9\x98\xcf(\xf7\xa8'~\xf8\xd7\xef\xd0C" +
"r\xab5_U\xb7\xa0\xfa\x16=\xb4\xf2\x97j\xa0C" +
"\x12\xcds\xf9\xfa\xd4\xf9}\xa8\xbe{>\xc9u\xfa|" +
"\x92\xeb\xaa\xed\xfdb\xeb7\xae}\x0f\x94\x1e6#7" +
"/\xbe\xa0\x0f\xd5\xab.\xa0C+.\x90Q}\x8b>" +
"\xfd\xef\xd6\xb7\xbc\xf2\xc1\xe0\x0f\x7f\xd7zy\xa0\xd0+" +
"t\xe4Tp\xe4\xcd\x0b\x02\xf3\xaf\\\xf1\x17\xbf=\xfc" +
"\x97\x83\x1f\xcc\xba\xfd+\xdd\x03\xa8\xae\xe8&9\x96w" +
"\x7fK\xdd\xd6\x1d\\\xfe\x9d\xd5\x1b\xaf^\xf6\x93\x0f\xb3" +
"\x96\x18\xea\xfe\x90,q]7Yb\xfc\x1b\xbf\xf9\xd6" +
"\xc5\xdf\xfd\xa7\x0f[\xdc\x130Nu_\x8a\xea\xed\xc1" +
"\x8d\xb7\x10\xf3\xfbk~\xf0FO\xa1\xe7\xa3\xb9\x04}" +
"\xa4\x9b\xe2\xa4;\x88\x93\xee@\xd0k\x7fu\xf4\x86\xd2" +
"\xf7?\xfa\x98\xf4b-\xc8\xf3n\xcf\x16T?\xeb\xa1" +
"\x9b?\xe9\xa1\xf0_\xf7\xd8\xa9oN\x1c~\xf9\x93V" +
"#\x04\x0e9~\xe1\x01T\x9f\xbb\x90\xb8\x9f\xbd\x90\xf0" +
"c\xdf\xfbG\x86\xef\xda\xfa\xd8\xe7Y\xad\x1eX\xf2|" +
"\xe0\xdf%\xa4\xd5\xce\xc3\xfb\xdc\xe1\xfb\xee\xf4\xe7J\x96" +
"W\x97\x0c\xa0\xfa\xcb%t\xdb\xa9%O\xc0r\xdf\xf5" +
"LS\x18v3W\xfd\xc3\xf8\xb3zyUk\x9a\xcd" +
"\xbe\xa1I\xddqu\xb3>\x16\xd0Ke\xcb\xd0\xabS" +
"eD\xde\x81\x12\x80\xb2\xb4\x0f\x00Q\xf9\xd2\x16\x00\x94" +
"\x14e\x00\xa0\xa4\xd7M\xcb\x16~Mw\xaa\x96i\x0a" +
"`Uw\xff\x0e\xcd\xd0\xcc\xaaH\x1ej\x9b\xfd\xd0\xb0" +
"0\x0c\xeb\x1a\xcb6j\x1bm\xbd\xae\x9b\x83\x969\xae" +
"\xd7\x01\xca\x88\xc91y\xf6\xb1AC\x17\xa6[\x11\xf6" +
"\x1e\xbd*.\xf7\x1c\x11\x9e\xf3l\xcd\xd5-\xf3\xa2Q" +
"\xe1x\x86\xeb\x00\xf0\x1c\xcb\x01\xe4\x10@\xe9\xec\x03\xe0" +
"\x0b\x18\xf2.\x09Kv\xc0\x80\xc54\xf3\x00\xb1\x08\xe9" +
"\x9b\xf9\xd9o\x86\xb6\xa07\x85}\xb9g\xda\xa2\xae;" +
"\xae\xb0C\xf2E\xa5\xb2fk\x0d'\xfb\xe0Q\x00^" +
"d\xc8\x97H\xe8\xd7m\xad*\xca\xc2F\xdd\xaam\xd0" +
"L\xab\xc2D\x15\xdb@\xc2\xb6\xcc\xa3s8b\x8d\xa6" +
"\x1b\xa2\x16jwy\xb57\xf8?/\xb2\\\x87\xef\x07" +
"\x8fh[\x00\xf8v\x86\xdc\x90\xb0\x13?\xf7\xbb\xa8H" +
")\xfa^\x00>\xc1\x90\xbb\x12vJ\x9f\xf9]\x81\xd7" +
"v/\x03\xe0\x06C>)a'\xfb\xd4\xef\xa2R\xa0" +
"x;\x01\xb8\xcb\x90\xdf$\xa1\xefxM\xb2\xa9\x03\xcc" +
"\xb2\xb1\x98\x86rd\x1dQ\xab\x93\xa5M(\x89*\x19" +
"\x1a\x8b1\xe2\x86\x0cr\xcd\x9a\xc0bZ\"\xa2c\xb6" +
"\xd8#lG\x94\xa1`[\x93SXL\x91\xb7\xc5\xea" +
"\x9d\xe7j\xf5\xd8\xd1\xc9\xa9\xf9\xcf\x07\xa1Yu/*" +
"\xf7\xcer\x16\xd9\xb1\x83!\xff\xb2\x84~\x93~\x15\xae" +
"\x00f;XLKo\x8b\xb4s\x84\xf3 \xfdw0" +
"|\xa5\x1c\xddb;A8\xf3%\xc9c\xcf\xd2c\xcf" +
"0\xe4/H\xa8 \x86>;i\x03\xf0\x13\x0c\xf9\xcb" +
"\x12\xa2\x14z\xec\xc5c\x00\xfce\x86\xfc\x0d\x09\x15&" +
"\x85\x0e{\xfdR\x00\xfe/\x0c\xf9\xaf%Tr\xac\x8b" +
"\xda\x0c\xe54\x05\xdb\xaf\x19\xf2\x8f$T\xdar]\xd8" +
"\x06\xa0|@\x9c\xbfa\xc8\xff[B%\xdf\xd6\x85y" +
"\x00\xe5\xbf\xae\x04\xe0\xbfc\xc8?\x95\xd0\xb7\xc2\xa4#" +
"M]\xec\x04\x09;\x01\xfd\xaaay\xb5qC\x83^" +
"[\xd4FV't\xd3k\x94m\xb1GG\xcbs\xfa" +
"]W4\xe4\xa6\xeb`\x1e$\xcc\x03\x16\\\xad\xee\xe0" +
"b\xc02C,\xa6\xd5\x0f\x90\x88\xc9\x9dh\x8b\xdaf" +
"a;:\xb3L\xec\x00\x09;\x00\x0b\xa6\xd6\x10\xf1?" +
"z\xeb\xb6\xe55\xe3\x7f\xcdg\xeb\xd1(\xaa(\xa6\xa2" +
"\x04\xb1l]\xae\xeb&\xef`\xb9%\xbe\x1f\x19v\x88" +
"\xac\xb0\x8a!_'\xe1R\xfc\x9c\xc8d\xdb\x91Q\x00" +
">\xcc\x90\x8fI\xb8T\xfa\x8c\xc8d]N\xbe)3" +
"\xe4[%,L\xb8n\x13\x8bi\xd5\x8c\x02\xe0\x06\xb1" +
"\xc3\xb1\xaa\xbb\x04 AH\x02\xe1\xd1\xaf\x13\x11\xa4\x01" +
"3jXL\xfb\xd0\x96\xe8asDO\x108%w" +
"\xc8\xb6-;@\xdb$d\x86\xaeL\x95\x88#fd" +
"K\xaa\x81\"\xad\x0a\xd5\xe2;R\xf9{\xab\x9a\xe7$" +
"\x96\xf5m\xe1\xdaS\xfd\xe3.0a'\xd8\xe3LX" +
"\x9eQ\x1b\x15 \xbb\xf6\x14\"H\x88\xf3#\xd2jk" +
"8c\xf20\xb43r\x92L\xab\x19\xf2r*\xe7z" +
"\xa2\xadc\xc8\xaf%9#\xf3o\"\xf3\x8f1\xe4M" +
"\x09}\x83r\xda\x1c\xb6\x809n\"nH,[A" +
"l\xca \xa1\x0c\xe8{M\xc7\xb5\x85\xd6\x00L\x82\x8d" +
"\xf8\x17\x9f\x03t\xb7@HY+\x04X0\xb7\x0eI" +
"z\xae_\x9bU\"\xca\xcfM\x03\xa9\xb1\xe7\xce\xa5\x09" +
"\xcbq)\xbc\x01 Vl\xbf\xd5$\xec$dIZ" +
"\xca\x96\xd88\xf7\x8a\x17V\x9f\x19\xf5\xeeX\xa6\xfcT" +
"\xa3\xd3\x18\x1c\x1f\xb4Ly\\\xafc1\xed\xc1Z\x04" +
"\x98\xc3\xef\xfd\x9e;!LW\xaf\x06\x0f\xce\xf2\xfb\xb2" +
"4>\x13\x9b\x8d\\\x991dl\xb3\xf5;RC\xca" +
"\xbb\xc4T\x92\xf8\xa2\xa1\xe9F\xe2\xfd\xc8\x9a\xfd \x7f" +
";\xe5\x99\xb7e\x89jSX\x99J\xa1yH\xc8\xae" +
"D\xc8\x1b\xa7\x01\xf8M\x0c\xf9\x1d\x19!o\xbf\x07\x80" +
"\xdf\xc1\x90\xdf\x97\x11\xf209\xf6\x10C~?\x01/" +
"\x0b\xa1\xe1\x08Y\xf4~\x86\xfca\x091\x17\xe2\xeeq" +
"\xc2\xdd\x87\x19\xf2g\xa4\x00 \x87\xfb\x07-\x13#!" +
"\x1c\x80\x18\x1e\xfd\x09\xa1\xd9\xee\x0e\xa1\xa1;b\xba\xc2" +
"\xde\xa3\xa1\x11\xe7\xe0~Wo\x08\xcbs\x93\x9clh" +
"\x93A\xdd\xc7\xdapxJ\xd6\\\x07\xdbA\xc2vJ" +
"\x01G\xd8\x83\xb6\xa8!yC3\xca\x1as'\xce\xc6" +
"@3\xf1\xb20\x87y\xa8k\xd8\xc7\x90\xdfF\xb9\x8b" +
"\x99!R\xb9\xa5\x0f\xa4 uI\xe7\xc6@\xda]\x04" +
"U\x89j\xcd\xee{\xd26\"\xa8JTkn<\x9a" +
"\x1a<\x12m\xd8\x82R\x98\x12\xb1\xcc\xa5\xd0\xd5\xfb\x09" +
"\x9et\x91\xea\x19\x15k\x1d-s,0\x10\xa6\x16\xaa" +
"Z\x8d\xa6-\x1c\x07u\xcb\xe4\x9ef\xe8\xcc\x9dJ\x0e" +
"\xcek\x03\xca\xfd0g66{\x03'\x91\x11\xae\x88" +
"\x8d\xa0\xf6\xe3Z\x80\xca*dXY\x87i\x98\xa8#" +
"8\x00PYM\xf42\xa6\x91\xa2\xae\xc7\x1e\x80\xca0" +
"\xd1\xc7PB\x0ccE\xe5\xf8(@e\x8c\xc8\xdb1" +
"\xad\xd3\xea\xb6\xe0\xfa\xadD\x9f\xc0\xb4T\xab\x02/\x05" +
"\xa8l'\xfa>\xa2\xe7\xa5\xc0\x82\xea\x14\xee\x04\xa8L" +
"\x12\xfd \xd1\xe5\xb6.\xea\xfa\xd5\x9b\xd1\x06\xa8\xdcD" +
"\xf4;\x88\xbe\xe0\xcb]\xb8\x00@\xbd=\xa0\xdfF\xf4" +
"{\x89\xde\xde\xdd\x85\xed\x00\xea\xddx\x00\xa0r\x88\xe8" +
"\xf7\x13}!v\xe1B\x00\xf5\x08\x1e\x05\xa8\xdcO\xf4" +
"\x87\x89\xbe(\xdf\x85\x8b\x00\xd4\xe3\x81<\x0f\x12\xfd1" +
"L\x00d\xa4\x96\xc51\x0a'=-\xe3\xccr\x920" +
"\x14\xd1\xfc\x80!\xc8\x96\xad\x02\x0d\x10XH\xf77\x80" +
"X\x00\xf4\x9b\x96el\x98\x89\x8fg\xea$\xa2\xb0\x80" +
"\x82e\x8e\xd4\x92\xfc\x0a\x83h\x9d\x05\xbdU\xcd\x18I" +
"\x1b\x08\xdd\xe9\xf7\\\xcbkBoMsE-\xa9p" +
"\xb6g\xae\xb1\xad\xc6\x18\x0a\xbb\xa1\x9b\x9a\x01\xc9/\xf3" +
"\xc5V\xc1\xf3\xf4\xda\xacd\x93Z\x03\xad\xb7\xd97\xa6" +
"\x05\xd9\xb5 \xc9\xaeK\xa8\x0d\xb9\x88!\xbf\"\x03>" +
"\xcb\x09!\xbf\xc6\x90\xff\x91\xd4\xd2\x06\xed\xd1\x0cO\x9c" +
"M\x1b\xb4\xa9\xa5\x14\x84-q\x88\xcf\x99\xd7\x07\xd2\xd7" +
"\x93\xc7\xa9\xe3\xbc\x8c!\x1f\x96p\xbf\xe3U\xab\xa4t" +
"l\x85\xf1h\xf0\x80^\xba;\xe3\x8fd'\x10\xf9\xe3" +
"l\xcbn]\xb8\xe1\xd7\x889nQ\xbd\x92\xb5\x86\xf3" +
"\x7f<=*\x9c\x02\xf5\xfdg\x1c\xef\x92)\xff\xcc\xf5" +
"mxl\xac\x9c\xce\xa0,\x04\xc7,.\x8cfq!" +
"\x85\x85\x9d\xd9\xf4\x8f\xdb0\x95\x07yX&\xfaVL" +
"\x9bw\xf5:<6#\xffs\xfd!.\x88\xe0\xfa\x1a" +
"\xd1\x9b\x01.`\x88\x0b\x8d\xe0~\x83\xe8\x93Y\\\xf0" +
"pz&.\xb0\x18\x17(\x9f\x0f\x12\xfdP\x80\x0b\xb9" +
"\x10\x17\xee\xc4\xa7g\xe4\x7f{[\x88\x0bG\xf0\xf9\x19" +
"\xf9\xbf0\x1f\xe2\xc2\xf1\x80\xffa\xa2?\x13\xe0\xc2@" +
"\x88\x0bO\x058\xf2$\xd1O\x10.x\xb6Qqm" +
"\xdd\x04\xac\xa7\xc1Zm~[\x88f?\x14\x0c}\x8f" +
"H0\xbb\xa6k\xc6jO3\xa0\xb7\xe2j\xd5]i" +
"\xafi8\xc3\x9aYspB\xdb%\x08\xe9\xe5l-" +
"t\x0dg\xb3\xb0\xf5q\xc0\xb4;Mz\x83B\xd9\xb2" +
"Z[\x86\xa0\xc9\x11v\x08*\xc9o\x0dmr\xa4f" +
"\x88A\x8c;\x04f\xa6\x95F\xa7_,\xd3\xc4\xb0l" +
"\x8f\xe9\xbd3\xebq3\xeaw\xe3\xba>Vj)\xd8" +
"b\xb2)\xaa\xee\xa0\x85\xa6\xab\x9b\x9e\x98uAu\xc2" +
"3w\x89\xda\x10\x9aU\xab\xa6\x9bu\x98\xd5h\xb3/" +
"\x1a\xfd3\x8dL\x90\xcd\x98\xd98+\x97PY\xc6\xa8" +
",+}\xe9\x08[\xaa\x06\xa7J\xb6\xd0\x9c\x14\xa1\xe7" +
"{-\xda\xf4\x84IF\xaf\x15Y\x1b@\xb2\xbf\xc5x" +
"\xa1\xa6\xec\xde\x0b\x92\xa2\xcb\x98\xee!1^;*\xdb" +
"l\x90\x94M2J\xc9\xda\x1c\xe3\x95\xb722\x0d\x92" +
"2$#Kv\xdd\x18\xaf\xb3\x94\xab\x07@R\x96\xcb" +
"~\xdc\x9aC)\x14g\x15\xfaq\xe2Co\x90\xfa\xab" +
"\xd0\x8f\x97\x00\x18\xb7\xf0\x00\xabp\x7fT\x16Vav" +
"s\xc4\xbe\xa8\x8f\x9e\xbb=$\x8c\x9cd\xc8\x0f\xa6\x18" +
"y3\xb5\x8c\x07\x19\xf2C\x99\xd9\xe5\xceG\xb3\xdda" +
"4\x96\x1f9\x00\xc0\xef\x0b;\xc1d,\x7f\xeaX4" +
"\xe9\xffLJ\xebe\x1cv\xf1\xb2\x05-;\x1e\xa6\xe6" +
"\xd9\xb9D\xc1\x19un\xad\x9b\x17\xbffM\x04\x9d\x1d" +
"\x86W9\x90\"vv\x1d\xb38\xb3\x8e\xc1x\x8c\x93" +
"g\x00|v9\xb3x~\xcc\x9c1\x94\x04\x15'\x17" +
"DM\xbc\xd4\xc7\xf8\xcf+\x8aB\xde\xef\x94\xfdxp" +
"\xc1\xb8\\\x91\xf3\xb2.;\xc7\xe9mT\xf4:gS" +
"\x09\xe2\x15\xee\x99\x87\xf0\xf0\x9d\x02\x05[\xa8Pr\xef" +
"\xce\xcc\x8a\xc8\xb0\xa29\xa8\xb0!S\xb5\xe7\xb3U(" +
"p\xdc\x80\x16\xe8pK\xf8-K\xc3/i\x10n^" +
"\x96\xf6\xe4\xc9tr\xcb\xda((\x1fL\x1aN\xe5\x01" +
"\x0a\xd4\x07\x19\xf2\xc72\xe1\xf7\xc8\xdat:\x91\x85m" +
"\xc7r\xca\x9e\x9d\xc2\xa6a\xd5\xd7\xe9\xa6p\xa8\x05k" +
"\x19\xa9\x9b\xc2nh\xa60\xd1%0\xf2lB\xd4\x99" +
"\xc85\xb2:\xd3\xb9\xcd\xa7~%\x0a\xf60\xd6\xa3\xf2" +
"\x9a\x99\x1f\x8fev\x19\xb1\xf2\xfc\xf9hG\xb0=\xa3" +
"\xfc6\x9a\x1f\xb72\xe4\x13\x12\xfa\x9a\xe7Z\x9b\x9a5" +
"\x0d]\xb1\xc6\x16\xbb=!\x9b\xd5\xa9t\x8e\xa2\x89\xa2" +
"\xeal\xc2&\xf5~klQ\xda\xed\x89,C\xbc\x95" +
"\x05Y\xb7j\xb3\xd6\xb1s4[\xd7\x88\x1d\x15\xab\xba" +
"K\xb83\xb6\xd5!\\\xc6\xaah\xa3\xe9J6\xd6D" +
"\x1f\xcd\x8cL1\x8c\xec\xa6\x80j2\xe4\xfb202" +
"5\x9d:|\xee\xea\xfa\xffS\x10\xe7Qr\xce\x95\xe9" +
"hI\x9cU\xa2\xa5\x7f\x828s\xcb\x15\x8d\xebQ\xc7" +
"z6\x0b\x85\x19\x1b\xaf( \xf8\xcet\x09\x13\x04y" +
"1\xfd\x8bf$\x83\x13\xb5\x8e\xc0\xc6\xad9\xba\xc2p" +
"\xb8\x19\xb4 \x82\xd6\xd6\xb5\xc8\xff\x06\x00\x00\xff\xffX" +
"t1W"
func init() {
schemas.Register(schema_db8274f9144abc7e,
@ -3944,11 +3810,9 @@ func init() {
0xb70431c0dc014915,
0xb9d4ef45c2b5fc5b,
0xc082ef6e0d42ed1d,
0xc54a4a6fd4d87596,
0xc744e349009087aa,
0xc766a92976e389c4,
0xc793e50592935b4a,
0xc9c82ee56583acfa,
0xcbd96442ae3bb01a,
0xd58a254e7a792b87,
0xdc3ed6801961e502,