From c7573ef09d0f4eb0599bbff720af12b3ab122cd5 Mon Sep 17 00:00:00 2001 From: Stuart Nelson Date: Sat, 9 Dec 2017 15:45:29 +0100 Subject: [PATCH] test ci build --- config/config.go | 28 ++++++ config/config_test.go | 1 + config/notifiers.go | 48 ++++++++++ config/notifiers_test.go | 33 +++++++ notify/impl.go | 135 +++++++++++++++++++++++++++ notify/impl_test.go | 8 ++ notify/notify.go | 2 + template/default.tmpl | 16 ++++ template/internal/deftmpl/bindata.go | 4 +- 9 files changed, 273 insertions(+), 2 deletions(-) diff --git a/config/config.go b/config/config.go index 2b41640d..59965435 100644 --- a/config/config.go +++ b/config/config.go @@ -236,6 +236,29 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { ogc.APIURL += "/" } } + for _, wcc := range rcv.WechatConfigs { + wcc.APIURL = c.Global.WeChatAPIURL + if wcc.APIURL == "" { + if c.Global.WeChatAPIURL == "" { + return fmt.Errorf("no global Wechat URL set") + } + } + wcc.APISecret = c.Global.WeChatAPISecret + if wcc.APISecret == "" { + if c.Global.WeChatAPISecret == "" { + return fmt.Errorf("no global Wechat ApiSecret set") + } + } + if wcc.CorpID == "" { + if c.Global.WeChatAPICorpID == "" { + return fmt.Errorf("no global Wechat CorpID set") + } + wcc.CorpID = c.Global.WeChatAPICorpID + } + if !strings.HasSuffix(wcc.APIURL, "/") { + wcc.APIURL += "/" + } + } for _, voc := range rcv.VictorOpsConfigs { if voc.APIURL == "" { if c.Global.VictorOpsAPIURL == "" { @@ -301,6 +324,7 @@ var DefaultGlobalConfig = GlobalConfig{ PagerdutyURL: "https://events.pagerduty.com/v2/enqueue", HipchatAPIURL: "https://api.hipchat.com/", OpsGenieAPIURL: "https://api.opsgenie.com/", + WeChatAPIURL: "https://qyapi.weixin.qq.com/cgi-bin/", VictorOpsAPIURL: "https://alert.victorops.com/integrations/generic/20131114/alert/", } @@ -324,6 +348,9 @@ type GlobalConfig struct { HipchatAPIURL string `yaml:"hipchat_api_url,omitempty" json:"hipchat_api_url,omitempty"` HipchatAuthToken Secret `yaml:"hipchat_auth_token,omitempty" json:"hipchat_auth_token,omitempty"` OpsGenieAPIURL string `yaml:"opsgenie_api_url,omitempty" json:"opsgenie_api_url,omitempty"` + WeChatAPIURL string `yaml:"wechat_api_url,omitempty" json:"wechat_api_url,omitempty"` + WeChatAPISecret string `yaml:"wechat_api_secret,omitempty" json:"wechat_api_secret,omitempty"` + WeChatAPICorpID string `yaml:"wechat_api_corp_id,omitempty" json:"wechat_api_corp_id,omitempty"` VictorOpsAPIURL string `yaml:"victorops_api_url,omitempty" json:"victorops_api_url,omitempty"` VictorOpsAPIKey Secret `yaml:"victorops_api_key,omitempty" json:"victorops_api_key,omitempty"` @@ -459,6 +486,7 @@ type Receiver struct { SlackConfigs []*SlackConfig `yaml:"slack_configs,omitempty" json:"slack_configs,omitempty"` WebhookConfigs []*WebhookConfig `yaml:"webhook_configs,omitempty" json:"webhook_configs,omitempty"` OpsGenieConfigs []*OpsGenieConfig `yaml:"opsgenie_configs,omitempty" json:"opsgenie_configs,omitempty"` + WechatConfigs []*WechatConfig `yaml:"wechat_configs,omitempty" json:"wechat_configs,omitempty"` PushoverConfigs []*PushoverConfig `yaml:"pushover_configs,omitempty" json:"pushover_configs,omitempty"` VictorOpsConfigs []*VictorOpsConfig `yaml:"victorops_configs,omitempty" json:"victorops_configs,omitempty"` diff --git a/config/config_test.go b/config/config_test.go index 851bcde5..8fb3556c 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -285,6 +285,7 @@ func TestEmptyFieldsAndRegex(t *testing.T) { SMTPRequireTLS: true, PagerdutyURL: "https://events.pagerduty.com/v2/enqueue", OpsGenieAPIURL: "https://api.opsgenie.com/", + WeChatAPIURL: "https://qyapi.weixin.qq.com/cgi-bin/", VictorOpsAPIURL: "https://alert.victorops.com/integrations/generic/20131114/alert/", }, diff --git a/config/notifiers.go b/config/notifiers.go index 5193100d..86186028 100644 --- a/config/notifiers.go +++ b/config/notifiers.go @@ -94,6 +94,21 @@ var ( // TODO: Add a details field with all the alerts. } + // DefaultWechatConfig defines default values for wechat configurations. + DefaultWechatConfig = WechatConfig{ + NotifierConfig: NotifierConfig{ + VSendResolved: true, + }, + Message: `{{ template "wechat.default.message" . }}`, + APIURL: `{{ template "wechat.default.api_url" . }}`, + APISecret: `{{ template "wechat.default.api_secret" . }}`, + ToUser: `{{ template "wechat.default.to_user" . }}`, + ToParty: `{{ template "wechat.default.to_party" . }}`, + ToTag: `{{ template "wechat.default.to_tag" . }}`, + AgentID: `{{ template "wechat.default.agent_id" . }}`, + // TODO: Add a details field with all the alerts. + } + // DefaultVictorOpsConfig defines default values for VictorOps configurations. DefaultVictorOpsConfig = VictorOpsConfig{ NotifierConfig: NotifierConfig{ @@ -295,6 +310,39 @@ func (c *WebhookConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { return checkOverflow(c.XXX, "webhook config") } +// WechatConfig configures notifications via Wechat. +type WechatConfig struct { + NotifierConfig `yaml:",inline" json:",inline"` + + APISecret string `yaml:"api_secret,omitempty" json:"api_secret,omitempty"` + CorpID string `yaml:"corp_id,omitempty" json:"corp_id,omitempty"` + Message string `yaml:"message,omitempty" json:"message,omitempty"` + APIURL string `yaml:"api_url,omitempty" json:"api_url,omitempty"` + ToUser string `yaml:"to_user,omitempty" json:"to_user,omitempty"` + ToParty string `yaml:"to_party,omitempty" json:"to_party,omitempty"` + ToTag string `yaml:"to_tag,omitempty" json:"to_tag,omitempty"` + AgentID string `yaml:"agent_id,omitempty" json:"agent_id,omitempty"` + + // Catches all undefined fields and must be empty after parsing. + XXX map[string]interface{} `yaml:",inline" json:"-"` +} + +// UnmarshalYAML implements the yaml.Unmarshaler interface. +func (c *WechatConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { + *c = DefaultWechatConfig + type plain WechatConfig + if err := unmarshal((*plain)(c)); err != nil { + return err + } + if c.APISecret == "" { + return fmt.Errorf("missing Wechat APISecret in Wechat config") + } + if c.CorpID == "" { + return fmt.Errorf("missing Wechat CorpID in Wechat config") + } + return checkOverflow(c.XXX, "Wechat config") +} + // OpsGenieConfig configures notifications via OpsGenie. type OpsGenieConfig struct { NotifierConfig `yaml:",inline" json:",inline"` diff --git a/config/notifiers_test.go b/config/notifiers_test.go index b436f77e..6bb48e4c 100644 --- a/config/notifiers_test.go +++ b/config/notifiers_test.go @@ -110,6 +110,39 @@ url: '' } } +func TestWechatAPIKeyIsPresent(t *testing.T) { + in := ` +api_secret: '' +` + var cfg WechatConfig + err := yaml.Unmarshal([]byte(in), &cfg) + + expected := "missing Wechat APISecret in Wechat config" + + if err == nil { + t.Fatalf("no error returned, expected:\n%v", expected) + } + if err.Error() != expected { + t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error()) + } +} +func TestWechatCorpIDIsPresent(t *testing.T) { + in := ` +corp_id: '' +` + var cfg WechatConfig + err := yaml.Unmarshal([]byte(in), &cfg) + + expected := "missing Wechat CorpID in Wechat config" + + if err == nil { + t.Fatalf("no error returned, expected:\n%v", expected) + } + if err.Error() != expected { + t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error()) + } +} + func TestOpsGenieAPIKeyIsPresent(t *testing.T) { in := ` api_key: '' diff --git a/notify/impl.go b/notify/impl.go index 576bb1ea..b45966bd 100644 --- a/notify/impl.go +++ b/notify/impl.go @@ -20,6 +20,7 @@ import ( "encoding/json" "errors" "fmt" + "io/ioutil" "mime" "mime/multipart" "net" @@ -116,6 +117,10 @@ func BuildReceiverIntegrations(nc *config.Receiver, tmpl *template.Template, log n := NewOpsGenie(c, tmpl, logger) add("opsgenie", i, n, c) } + for i, c := range nc.WechatConfigs { + n := NewWechat(c, tmpl, logger) + add("wechat", i, n, c) + } for i, c := range nc.SlackConfigs { n := NewSlack(c, tmpl, logger) add("slack", i, n, c) @@ -771,6 +776,136 @@ func (n *Hipchat) retry(statusCode int) (bool, error) { return false, nil } +// Wechat implements a Notfier for wechat notifications +type Wechat struct { + conf *config.WechatConfig + tmpl *template.Template + logger log.Logger +} +type WechatToken struct { + AccessToken string `json:"access_token"` + // Catches all undefined fields and must be empty after parsing. + XXX map[string]interface{} `json:"-"` +} +type weChatMessage struct { + Content string `json:"content"` +} +type weChatCreateMessage struct { + Text weChatMessage `yaml:"text,omitempty" json:"text,omitempty"` + ToUser string `yaml:"touser,omitempty" json:"touser,omitempty"` + ToParty string `yaml:"toparty,omitempty" json:"toparty,omitempty"` + Totag string `yaml:"totag,omitempty" json:"totag,omitempty"` + AgentID string `yaml:"agentid,omitempty" json:"agentid,omitempty"` + Safe string `yaml:"safe,omitempty" json:"safe,omitempty"` + Type string `yaml:"msgtype,omitempty" json:"msgtype,omitempty"` +} + +type weChatCloseMessage struct { + Text weChatMessage `yaml:"text,omitempty" json:"text,omitempty"` + ToUser string `yaml:"touser,omitempty" json:"touser,omitempty"` + ToParty string `yaml:"toparty,omitempty" json:"toparty,omitempty"` + Totag string `yaml:"totag,omitempty" json:"totag,omitempty"` + AgentID string `yaml:"agentid,omitempty" json:"agentid,omitempty"` + Safe string `yaml:"safe,omitempty" json:"safe,omitempty"` + Type string `yaml:"msgtype,omitempty" json:"msgtype,omitempty"` +} + +type weChatErrorResponse struct { + Code int `json:"code"` + Error string `json:"error"` +} + +// NewWechat returns a new Wechat notifier. +func NewWechat(c *config.WechatConfig, t *template.Template, l log.Logger) *Wechat { + return &Wechat{conf: c, tmpl: t, logger: l} +} + +// Notify implements the Notifier interface. +func (n *Wechat) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { + key, ok := GroupKey(ctx) + if !ok { + return false, fmt.Errorf("group key missing") + } + data := n.tmpl.Data(receiverName(ctx, n.logger), groupLabels(ctx, n.logger), as...) + level.Debug(n.logger).Log("msg", "Notifying Wechat", "incident", key) + + var err error + tmpl := tmplText(n.tmpl, data, &err) + + var ( + msg interface{} + apiURL string + apiMsg = weChatMessage{ + Content: tmpl(n.conf.Message), + } + alerts = types.Alerts(as...) + ) + parameters := url.Values{} + parameters.Add("corpsecret", tmpl(string(n.conf.APISecret))) + parameters.Add("corpid", tmpl(string(n.conf.CorpID))) + apiURL = n.conf.APIURL + "gettoken" + u, err := url.Parse(apiURL) + if err != nil { + return false, err + } + u.RawQuery = parameters.Encode() + level.Debug(n.logger).Log("msg", "Sending Wechat message", "incident", key, "url", u.String()) + resp, err := ctxhttp.Get(ctx, http.DefaultClient, u.String()) + if err != nil { + return true, err + } + defer resp.Body.Close() + var wechatToken WechatToken + if err := json.NewDecoder(resp.Body).Decode(&wechatToken); err != nil { + return false, err + } + postMessageURL := n.conf.APIURL + "message/send?access_token=" + wechatToken.AccessToken + switch alerts.Status() { + case model.AlertResolved: + msg = &weChatCloseMessage{Text: apiMsg, + ToUser: tmpl(n.conf.ToUser), + ToParty: tmpl(n.conf.ToParty), + Totag: tmpl(n.conf.ToTag), + AgentID: tmpl(n.conf.AgentID), + Type: "text", + Safe: "0"} + default: + msg = &weChatCreateMessage{ + Text: weChatMessage{ + Content: tmpl(n.conf.Message), + }, + ToUser: tmpl(n.conf.ToUser), + ToParty: tmpl(n.conf.ToParty), + Totag: tmpl(n.conf.ToTag), + AgentID: tmpl(n.conf.AgentID), + Type: "text", + Safe: "0", + } + } + var buf bytes.Buffer + if err := json.NewEncoder(&buf).Encode(msg); err != nil { + return false, err + } + resp, err = ctxhttp.Post(ctx, http.DefaultClient, postMessageURL, contentTypeJSON, &buf) + if err != nil { + return true, err + } + body, _ := ioutil.ReadAll(resp.Body) + level.Debug(n.logger).Log("msg", "response: "+string(body), "incident", key) + defer resp.Body.Close() + return n.retry(resp.StatusCode) +} +func (n *Wechat) retry(statusCode int) (bool, error) { + // https://work.weixin.qq.com/api/doc#10649 + if statusCode/100 == 5 || statusCode == 429 { + return true, fmt.Errorf("unexpected status code %v", statusCode) + } else if statusCode/100 != 2 { + return false, fmt.Errorf("unexpected status code %v", statusCode) + } + + return false, nil +} + // OpsGenie implements a Notifier for OpsGenie notifications. type OpsGenie struct { conf *config.OpsGenieConfig diff --git a/notify/impl_test.go b/notify/impl_test.go index c7053d13..d2b40cb8 100644 --- a/notify/impl_test.go +++ b/notify/impl_test.go @@ -53,6 +53,14 @@ func TestHipchatRetry(t *testing.T) { } } +func TestWechatRetry(t *testing.T) { + notifier := new(Wechat) + retryCodes := append(defaultRetryCodes(), http.StatusTooManyRequests) + for statusCode, expected := range retryTests(retryCodes) { + actual, _ := notifier.retry(statusCode) + require.Equal(t, expected, actual, fmt.Sprintf("error on status %d", statusCode)) + } +} func TestOpsGenieRetry(t *testing.T) { notifier := new(OpsGenie) diff --git a/notify/notify.go b/notify/notify.go index 5f9ea206..932680e2 100644 --- a/notify/notify.go +++ b/notify/notify.go @@ -54,6 +54,7 @@ func init() { numNotifications.WithLabelValues("email") numNotifications.WithLabelValues("hipchat") numNotifications.WithLabelValues("pagerduty") + numNotifications.WithLabelValues("wechat") numNotifications.WithLabelValues("pushover") numNotifications.WithLabelValues("slack") numNotifications.WithLabelValues("opsgenie") @@ -62,6 +63,7 @@ func init() { numFailedNotifications.WithLabelValues("email") numFailedNotifications.WithLabelValues("hipchat") numFailedNotifications.WithLabelValues("pagerduty") + numFailedNotifications.WithLabelValues("wechat") numFailedNotifications.WithLabelValues("pushover") numFailedNotifications.WithLabelValues("slack") numFailedNotifications.WithLabelValues("opsgenie") diff --git a/template/default.tmpl b/template/default.tmpl index aa3ae37f..e7e0ebf9 100644 --- a/template/default.tmpl +++ b/template/default.tmpl @@ -46,6 +46,22 @@ Alerts Resolved: {{ define "opsgenie.default.source" }}{{ template "__alertmanagerURL" . }}{{ end }} +{{ define "wechat.default.message" }}{{ template "__subject" . }} +{{ .CommonAnnotations.SortedPairs.Values | join " " }} +{{ if gt (len .Alerts.Firing) 0 -}} +Alerts Firing: +{{ template "__text_alert_list" .Alerts.Firing }} +{{- end }} +{{ if gt (len .Alerts.Resolved) 0 -}} +Alerts Resolved: +{{ template "__text_alert_list" .Alerts.Resolved }} +{{- end }} +AlertmanagerUrl: +{{ template "__alertmanagerURL" . }} +{{- end }} + + + {{ define "victorops.default.state_message" }}{{ .CommonAnnotations.SortedPairs.Values | join " " }} {{ if gt (len .Alerts.Firing) 0 -}} Alerts Firing: diff --git a/template/internal/deftmpl/bindata.go b/template/internal/deftmpl/bindata.go index 78e63ec4..0ac8b5c6 100644 --- a/template/internal/deftmpl/bindata.go +++ b/template/internal/deftmpl/bindata.go @@ -68,7 +68,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _templateDefaultTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3b\x6b\x6f\xdb\x36\xbb\xdf\xf5\x2b\x9e\x69\x38\x58\x03\x58\x96\x93\x6e\xc5\xe2\xd8\x39\x70\x1d\xa5\x11\x8e\x23\x07\xb2\xd2\xae\x18\x86\x80\x96\x68\x9b\xad\x44\x6a\x24\x95\xc4\xcb\xfc\xdf\x0f\x48\xc9\x17\xc5\x72\xe2\x14\x5d\xe2\xf7\x5d\x12\xb4\x91\x28\x3e\xf7\x2b\x45\xea\xee\x0e\x22\x3c\x22\x14\x83\x79\x75\x85\x62\xcc\x65\x82\x28\x1a\x63\x6e\xc2\x6c\xd6\x51\xf7\xe7\xf9\xfd\xdd\x1d\x60\x1a\xc1\x6c\x66\x6c\x04\xb9\xf4\x7b\x0a\xea\xee\x0e\xea\xce\xad\xc4\x9c\xa2\xf8\xd2\xef\xc1\x6c\x66\xff\x68\xeb\x79\xe2\x7f\x39\x0e\x31\xb9\xc6\xbc\xad\x26\xf9\xc5\x4d\x0e\x53\x60\x2f\xa3\x17\xd9\xf0\x0b\x0e\xa5\x42\xfb\xbb\x02\x19\x48\x24\x33\x01\x7f\x83\x64\x97\x69\x3a\x07\x25\x23\xc0\x7f\x2e\x1e\x9a\x23\xc2\x09\x1d\x2b\x98\xa6\x82\xd1\x52\x88\xfa\xa9\x1e\x85\xbf\x21\xc6\x74\x95\xe2\x1f\xa0\x26\x7d\xe0\x2c\x4b\x7b\x68\x88\x63\x51\x1f\x30\x2e\x71\x74\x81\x08\x17\xf5\x8f\x28\xce\xb0\x22\xf8\x85\x11\x0a\x26\x28\xac\x90\x93\x1c\x4b\x78\xa3\x70\xd5\xbb\x2c\x49\x18\xcd\x81\xf7\x8a\xb1\x15\x7c\x7b\x30\x9b\xbd\xb9\xbb\x83\x1b\x22\x27\xe5\xc9\x75\x1f\x27\xec\x1a\x97\xa9\x7b\x28\xc1\xa2\x50\x63\x15\xf5\x05\xe3\x7b\x8b\xab\x0d\xb6\x89\xb0\x08\x39\x49\x25\x61\xd4\x7c\x40\xc7\x12\xdf\xca\xdc\x8e\x57\x31\x11\xb2\x98\xca\x11\x1d\x63\xa8\xc3\x6c\x96\xf3\xd5\x34\x96\x83\xeb\x7a\x52\x5a\xb1\xb4\x22\x15\xfb\xea\xae\x0d\x0b\x01\x0a\xc6\x72\xe2\x1d\x4a\x99\x44\x8a\xa7\x12\xca\x95\xe1\x6f\xc3\x3b\x60\x19\x0f\x71\x33\x37\x26\xa6\x98\x23\xc9\x78\xee\x7e\x46\x85\xa2\x4a\x3a\x10\x31\x0a\xbf\xd6\x23\x3c\x42\x59\x2c\xeb\x92\xc8\x18\x17\x5a\x90\x38\x49\x63\x24\xcb\xbe\x58\xdf\xa4\xf2\x32\x9e\x4c\xa8\x10\x48\xaa\x50\x95\x03\x6d\x4b\x7c\x23\x14\xc7\x43\x14\x7e\x5d\xc3\x57\xc9\xbe\x42\x0a\x7f\xc3\x63\x13\x63\x42\xbf\x6e\xcd\x41\xca\xb1\x72\x16\x73\xbb\xd9\x2b\xf8\x1f\x54\x80\x4e\x1b\x5b\x72\x40\x42\x46\x71\xc2\xbe\x90\x2d\x79\x50\xf3\x33\x1e\x6f\xcb\xf1\x9a\x70\x25\x37\x99\x90\x34\x9c\x20\xb9\x34\x08\x67\xc9\xb7\x1b\xf7\x3e\xb6\x04\x0b\x81\xc6\x4f\x70\xbc\x12\x6f\xa9\xa2\x16\x65\x72\xba\xc0\xb7\x1e\xfd\x4f\x73\xe6\x75\x8c\x61\x4c\x30\x95\xdf\x2e\xf1\x26\x8c\xcb\xba\xf1\x6d\x2e\xb2\x8e\x97\x50\x21\x11\x0d\xb1\xa8\xc0\xbb\x96\xee\x1e\xd0\x2a\x4b\xc5\x18\x53\x82\xbf\xdd\x48\x0f\x21\x5b\xb7\x50\x51\x1d\x36\x24\xc3\xca\x72\x60\xdc\x2b\x46\xa5\x6a\xb7\x07\x0d\xb0\x66\x33\x23\x1f\x84\x7c\x50\xa7\xdd\x87\x35\x52\x2e\x99\x9a\x88\xb5\x22\x51\x05\x3d\x1f\x0b\x16\x5f\xe3\xe8\x1e\xc5\xf9\xf0\xf6\x34\xe7\x10\x6b\x54\xad\x6d\x54\x2a\x74\x15\x78\xba\x37\x95\xac\x7e\x4d\x42\xc9\x38\x4b\xc5\x12\xad\x44\x12\x5f\x95\x8d\xff\x6a\xab\xa7\xd9\x6a\x5d\xab\x98\x4a\x22\xa7\x57\x11\x11\x69\x8c\xa6\x57\x1b\x6a\xe5\xe3\x81\xb5\x8e\x39\x61\x94\x48\xa6\x14\x72\x25\x19\x8b\x9f\x98\xb2\x56\x71\xe3\x04\x91\x78\xe9\x07\xcb\x76\xf4\xc9\x5c\x96\x31\x4d\x64\xa2\xd9\x32\x5a\x3f\x9c\xf4\xbb\xc1\xe7\x0b\x07\xd4\x10\x5c\x5c\xbe\xef\xb9\x5d\x30\x2d\xdb\xfe\xf4\xb6\x6b\xdb\x27\xc1\x09\xfc\x76\x16\x9c\xf7\x60\xbf\xde\x80\x80\x23\x2a\x88\x72\x36\x14\xdb\xb6\xe3\x99\x60\x4e\xa4\x4c\x9b\xb6\x7d\x73\x73\x53\xbf\x79\x5b\x67\x7c\x6c\x07\xbe\x7d\xab\x70\xed\x2b\xe0\xe2\xd2\x92\x2b\x90\xf5\x48\x46\xe6\xb1\xd1\xfa\xc1\xb2\x8c\x81\x9c\xc6\x18\x10\x8d\x40\x13\x89\x30\x27\xca\xa0\xaa\xb4\x81\x42\x2d\x9a\xb6\x3d\x26\x72\x92\x0d\xeb\x21\x4b\x6c\x25\xc3\x38\xa3\xb6\x46\x87\xc2\x1c\x9f\xa5\x45\xb3\xe6\xea\x10\x86\x61\x04\x13\x0c\xe7\x6e\x00\x3d\x12\x62\x2a\x30\xbc\x39\x77\x83\x3d\xc3\xe8\xb2\x74\xca\xc9\x78\x22\xe1\x4d\xb8\x07\x07\x8d\xfd\x9f\xe1\x3c\xc7\x68\x18\x17\x98\x27\x44\x08\xc2\x28\x10\x01\x13\xcc\xf1\x70\x0a\x63\x8e\xa8\xc4\x51\x0d\x46\x1c\x63\x60\x23\x08\x27\x88\x8f\x71\x0d\x24\x03\x44\xa7\x90\x62\x2e\x18\x05\x36\x94\x88\x50\xe5\xff\x08\x42\x96\x4e\x0d\x36\x02\x39\x21\x02\x04\x1b\xc9\x1b\xc4\x73\x09\x91\x10\x2c\x24\x48\xe2\x08\x22\x16\x66\x09\xa6\x79\xe0\xc2\x88\xc4\x58\xc0\x1b\x39\xc1\x60\x0e\x0a\x08\x73\x4f\x13\x89\x30\x8a\x0d\x42\x41\x3d\x9b\x3f\xd2\x9d\x3c\xcb\x24\x70\x2c\x24\x27\x5a\x0b\x35\x20\x34\x8c\xb3\x48\xf1\x30\x7f\x1c\x93\x84\x14\x14\x14\xb8\x16\x5c\x18\x92\x41\x26\x70\x4d\xf3\x59\x83\x84\x45\x64\xa4\xfe\x62\x2d\x56\x9a\x0d\x63\x22\x26\x35\x88\x88\x42\x3d\xcc\x24\xae\x81\x50\x83\x5a\x8f\x35\x25\x87\xcd\x38\x08\x1c\xc7\x46\xc8\x52\x82\x05\x68\x59\x97\xdc\xe9\x39\x8a\xf5\x54\x29\x54\x16\x2a\x12\x6a\xe4\x66\xc2\x92\xb2\x24\x44\x18\xa3\x8c\x53\x22\x26\x58\xc3\x44\x0c\x04\xd3\x14\x95\x37\xab\x11\x35\x7d\xc4\xe2\x98\xdd\x28\xd1\x42\x46\x23\x52\x34\xef\xda\xc8\x68\xa8\x16\x30\xe1\xc2\xae\x94\x49\x12\xe6\xea\xd6\x06\x48\x97\x56\x2d\x1e\x89\x09\x8a\x63\x18\xe2\x42\x61\x38\x02\x42\x01\xad\x88\xc3\x15\x79\x55\xbf\x25\x41\x31\xa4\x8c\x6b\x7a\xf7\xc5\xac\x1b\x46\x70\xe6\xc0\xa0\x7f\x1a\x7c\xea\xf8\x0e\xb8\x03\xb8\xf0\xfb\x1f\xdd\x13\xe7\x04\xcc\xce\x00\xdc\x81\x59\x83\x4f\x6e\x70\xd6\xbf\x0c\xe0\x53\xc7\xf7\x3b\x5e\xf0\x19\xfa\xa7\xd0\xf1\x3e\xc3\xff\xb9\xde\x49\x0d\x9c\xdf\x2e\x7c\x67\x30\x80\xbe\x6f\xb8\xe7\x17\x3d\xd7\x39\xa9\x81\xeb\x75\x7b\x97\x27\xae\xf7\x01\xde\x5f\x06\xe0\xf5\x03\xe8\xb9\xe7\x6e\xe0\x9c\x40\xd0\x07\x45\xb0\x40\xe5\x3a\x03\x85\xec\xdc\xf1\xbb\x67\x1d\x2f\xe8\xbc\x77\x7b\x6e\xf0\xb9\x66\x9c\xba\x81\xa7\x70\x9e\xf6\x7d\xe8\xc0\x45\xc7\x0f\xdc\xee\x65\xaf\xe3\xc3\xc5\xa5\x7f\xd1\x1f\x38\xd0\xf1\x4e\xc0\xeb\x7b\xae\x77\xea\xbb\xde\x07\xe7\xdc\xf1\x82\x3a\xb8\x1e\x78\x7d\x70\x3e\x3a\x5e\x00\x83\xb3\x4e\xaf\xa7\x48\x19\x9d\xcb\xe0\xac\xef\x2b\xfe\xa0\xdb\xbf\xf8\xec\xbb\x1f\xce\x02\x38\xeb\xf7\x4e\x1c\x7f\x00\xef\x1d\xe8\xb9\x9d\xf7\x3d\x27\x27\xe5\x7d\x86\x6e\xaf\xe3\x9e\xd7\xe0\xa4\x73\xde\xf9\xe0\x68\xa8\x7e\x70\xe6\xf8\x86\x9a\x96\x73\x07\x9f\xce\x1c\x35\xa4\xe8\x75\x3c\xe8\x74\x03\xb7\xef\x29\x31\xba\x7d\x2f\xf0\x3b\xdd\xa0\x06\x41\xdf\x0f\x16\xa0\x9f\xdc\x81\x53\x83\x8e\xef\x0e\x94\x42\x4e\xfd\xfe\x79\xcd\x50\xea\xec\x9f\xaa\x29\xae\xa7\xe0\x3c\x27\xc7\xa2\x54\x0d\x25\x8b\xf4\x7d\x7d\x7f\x39\x70\x16\x08\xe1\xc4\xe9\xf4\x5c\xef\xc3\x40\x01\x2b\x11\xe7\x93\xeb\x86\x65\x1d\x1b\x2d\x9d\x02\x6f\x93\x98\x8a\x76\x45\x62\xdb\x3f\x3c\x3c\xcc\xf3\x99\xb9\xdd\x24\xa1\x92\x5b\xdb\x1c\x31\x2a\xad\x11\x4a\x48\x3c\x6d\xc2\x4f\x67\x38\xbe\xc6\x92\x84\x08\x3c\x9c\xe1\x9f\x6a\xb0\x18\xa8\x41\x87\x13\x14\xd7\x40\x20\x2a\x2c\x81\x39\x19\x1d\xc1\x90\xdd\x5a\x82\xfc\xa5\x6a\x31\x0c\x19\x8f\x30\xb7\x86\xec\xf6\x08\x34\x52\x41\xfe\xc2\x4d\xd8\xff\x39\xbd\x3d\x82\x04\xf1\x31\xa1\x4d\x68\x1c\xa9\xdc\x3a\xc1\x28\x7a\x49\xfa\x09\x96\x08\x54\x45\x6d\x9b\xd7\x04\xdf\xa8\x28\x32\x55\xf4\x4a\x4c\x65\xdb\xbc\x21\x91\x9c\xb4\x23\x7c\x4d\x42\x6c\xe9\x9b\x97\x53\x16\xd8\x73\x76\x95\x31\x2d\xfc\x67\x46\xae\xdb\x66\x37\x67\xd5\x0a\xa6\x29\x5e\x61\x5c\xb5\x22\xb6\x32\xee\x91\xae\x04\x02\xcb\xf6\x65\x70\x6a\xfd\xfa\xc2\xec\xeb\xa5\xee\xcb\x99\xfb\xa1\x5e\xa4\x65\x6b\xe6\x8e\x0d\xa3\x65\x2b\xa7\x54\x17\x43\x16\x4d\x81\x48\x9c\x88\x90\xa5\xb8\x6d\x9a\xfa\x46\x4e\xd5\x75\x11\x51\x22\x9c\xe0\x04\xe9\x88\x72\x54\x75\x3f\x9f\xf7\xbe\xcf\x2a\xa4\x75\x83\x87\x5f\x89\xb4\xf2\x07\x09\x63\x72\xa2\x81\xf2\xda\x40\x90\xc0\xd1\x72\x92\xf2\x0d\x0d\x6d\xa1\xe8\x4b\x26\x64\x13\x28\xa3\xf8\x08\x26\x58\x55\xa6\x26\xec\x37\x1a\xff\x73\x04\x31\xa1\xd8\x5a\x0c\xd5\xdf\xe1\xe4\x08\x74\x04\xe4\x13\xe0\x07\x92\xa8\x60\x41\x54\x1e\xc1\x10\x85\x5f\xc7\x9c\x65\x34\xb2\x42\x16\x33\xde\x84\x1f\x47\xef\xd4\xef\xaa\xfa\x21\x45\x51\xa4\xb9\x52\xde\x30\x1c\xeb\x99\x6d\xb3\x98\x69\x2a\x7d\x4b\x34\x7c\x6e\xf7\x58\x11\x69\x4b\x39\x2a\x79\x07\x68\x49\xfe\x82\x79\x0c\x40\x71\xf0\xcc\x99\xf4\x1a\x73\x85\x24\xb6\x50\x4c\xc6\xb4\x09\x92\xa5\x65\x45\x5d\xeb\x07\x6d\x53\xb2\xd4\x3c\x6e\xd9\x32\x5a\x32\x9a\x67\x56\xf3\x5d\xa3\xf1\xcc\xa1\x52\xc9\x74\xb1\xb4\x6a\xc2\x30\x66\xe1\xd7\x92\x6f\x27\xe8\xd6\x2a\x9c\xe4\x5d\xa3\x91\xde\x96\x1e\x86\x31\x46\x5c\x11\x94\x93\xd2\xf8\xa6\x40\x59\x28\x07\x50\x26\xd9\xbd\x90\x28\x69\x4b\x2b\x0a\xa0\x15\x91\xeb\xe7\x76\xab\xb2\xbc\xf7\x95\xf3\xb0\x10\x73\xbe\x95\x91\x75\x30\x17\x76\x56\x9a\x30\x21\xc4\x71\x5c\xcc\x6e\x9b\x8d\xfc\x5e\xa4\x28\x9c\xdf\x3f\xab\xa0\xc5\x43\x8e\x22\x92\x89\x26\xbc\xd5\x63\x15\x09\x60\x34\x2a\x65\xb1\x1c\xac\x09\xfb\xe9\x2d\x08\x16\x93\x08\x7e\xc4\x87\xea\xb7\x9c\x18\x46\xa3\x15\x5d\xec\x42\x76\x58\x72\xf2\x7c\x59\xe2\xdd\xc6\x80\x2b\x69\x57\x83\xdc\x14\xa5\xe6\x97\x46\xe3\x08\x74\x89\x2a\xe6\x87\x98\x4a\xcc\xab\xec\xa5\xff\x35\xb4\x51\xd6\xed\xe6\xbc\xfb\xe5\xe0\xa0\x5b\x5d\x80\x0e\x94\x5f\x9b\x50\xc4\x5b\x4e\x60\xd5\x7a\x39\x6c\x75\x44\xce\x7f\x96\x3b\x66\x8b\xad\x32\xd0\x2f\x4b\x2a\xdf\x25\xed\xc1\x3e\xcc\x66\x62\xf1\xc2\x03\x46\x8c\xc3\x72\x57\x67\xc3\xae\x1a\xcc\x66\xf7\xa8\xc2\xea\x1e\x4f\xbb\xb4\xc3\xb3\x36\xad\x78\xb5\x52\x32\xfe\x22\x07\x2f\xee\xf9\xab\x9b\x6e\x53\xcc\x96\xce\xb3\x9f\x3b\xcf\x43\xbe\xb1\xf3\xb9\x6f\xa3\xda\x77\xcb\x09\x76\xdd\x15\x1a\xd0\x98\xe7\x92\x87\xdc\xa1\x10\x03\xc1\x84\xe3\x51\xdb\xdc\xe6\x8d\xfb\x33\xfb\xc3\x3c\x69\x9e\x9e\x9e\x16\xc9\x37\xc2\x21\xe3\xfa\x9d\xdc\x7c\x79\x50\x5a\x10\x1c\xa8\xe5\x40\x29\x6f\x0f\x59\x1c\x55\x27\xee\x30\xe3\x42\x61\x4f\x19\xc9\x07\x16\x0d\x05\xa1\x1a\x69\xd1\x57\xdc\x4b\xf0\xbf\x28\xc6\x34\x3e\xfd\x12\x75\xc4\x78\xd2\x84\x10\xa5\x44\xa2\x98\xfc\x85\x2b\x93\xfe\xdb\x9f\x7f\xc5\x11\xaa\xa8\xd7\x6b\x33\x8a\x61\xad\xe5\x66\x5e\xc8\x17\x83\x8b\xee\x2d\xbd\x2d\xcc\x7b\xfc\x91\xe0\x1b\x20\x14\x1e\x7d\x3b\xde\xb2\x51\xa5\x0f\xdf\x4b\xbc\xd5\xe9\x37\xff\x79\x6c\xf3\xa3\xa2\x28\xbc\x86\xec\x3f\x13\xb2\x42\x72\x46\xc7\x2f\xa7\xda\xdf\x37\x9f\xcb\xf9\xa3\xd8\xf9\x6a\xd9\x39\x93\xdf\xc1\xeb\x2a\x1a\x86\xe2\xc9\xfc\xf0\xc9\xfd\x2d\xb4\x57\x3f\xfc\x77\xf8\x61\xde\x9a\x2e\x5c\xad\x35\x7c\x39\x33\x83\x5d\xad\xa3\x47\x4e\x5d\x6d\x3e\x1a\xf5\xc2\xc2\x6c\x8e\x3b\xa8\xa8\x05\xcb\x4d\xf4\xbc\x12\xbc\xb8\x67\xac\x70\xb4\x2b\xee\xf1\xa8\x46\x1f\x3d\x4a\xf7\x1f\xea\x2c\xab\x1d\xe6\xfd\xb3\x7d\x2f\xd4\x50\xce\xdb\xad\xb5\x9e\x32\xa3\x11\xe6\xaa\xfb\x2b\xbb\x53\x7e\x3a\x51\x35\x51\xbb\x97\x63\xbe\xad\x9a\x6e\xd9\xde\xad\x9e\x35\xa9\x34\xef\x6b\x57\xb8\x33\xd5\x78\xe7\x3c\x13\xa0\x35\xd9\x41\x9e\x76\x4e\x4f\x4f\x89\xe0\x87\x3a\xe2\xd7\xc0\xfa\xef\x6c\x73\x57\x97\x5b\x8b\x33\x7b\xcb\x05\xd7\x7c\xe8\x05\x96\x5c\xab\x27\x08\x5f\xbd\xf1\xdf\xe1\x8d\xaf\x8b\xae\xd7\x45\xd7\xeb\xa2\x6b\xd7\x9d\xe5\x75\xd1\xb5\x33\x2d\xdb\x26\x43\xb5\x6c\xbd\x1f\x77\xfc\x84\xad\xd0\x05\xc8\x72\xe4\xd9\x4f\x62\x94\x8e\x26\xad\x9c\x34\x59\x1a\xfa\xf0\xf0\xf0\xa1\x0d\xee\xf2\xce\xee\xfa\x96\xe4\x6e\x34\x0d\xbb\xd4\xbe\x3c\x67\xeb\x72\xb0\xb1\x75\xa9\xdc\x44\x7b\xcc\xe4\x2b\xbd\xcd\xbd\x73\x0d\xe5\x53\x58\xab\xe9\xaa\xfc\xf5\xf1\xf3\x39\xc4\xc1\x6a\xb6\xd2\x12\x6d\x9d\xaa\x30\x95\x30\x9c\x6e\xb7\x0f\xb7\x9e\x3b\xd6\xce\x3b\xdc\xcf\x0c\x2d\x3b\x22\xd7\xc7\xf9\xff\x46\x39\x4d\xec\x5a\x5b\xbb\xe1\x78\x5d\x2e\xe2\x32\x7f\xb5\xec\x21\x8b\xa6\x6a\x64\x22\x93\xf8\xd8\x30\xaa\xbf\xdf\x49\x33\x31\x61\xd7\x98\x7f\x87\xaf\x7b\xd7\x50\xfd\xf3\xdf\x83\x7d\x9f\xcf\xc1\xb6\xff\x1a\xec\xfb\x7d\x0c\xb6\x42\x73\x0b\x4d\x2e\x3f\xd1\x7d\xc2\x37\x7b\xff\x1f\x00\x00\xff\xff\xae\x05\x86\xad\xbb\x40\x00\x00") +var _templateDefaultTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x1b\xff\x4f\xdb\xb8\xfe\xf7\xfc\x15\x9f\xcb\xe9\xe9\x86\xd4\x36\x85\xdd\x4d\x47\x69\x79\xea\x4a\x18\xd1\x2b\x29\x4a\xc3\x76\xd3\xe9\x84\xdc\xc4\x6d\xbd\x25\x76\xce\x76\x28\x3d\xd6\xff\xfd\xc9\x4e\xfa\x25\x34\x85\x82\x76\xd0\xf7\x0e\xd0\x46\xe2\xf8\xf3\xfd\xab\x63\xe7\xf6\x16\x42\x3c\x24\x14\x83\x79\x75\x85\x22\xcc\x65\x8c\x28\x1a\x61\x6e\xc2\x6c\xd6\x56\xf7\xe7\xd9\xfd\xed\x2d\x60\x1a\xc2\x6c\x66\x6c\x04\xb9\xf4\xba\x0a\xea\xf6\x16\x6a\xf6\x8d\xc4\x9c\xa2\xe8\xd2\xeb\xc2\x6c\x66\xfd\x68\xe9\x79\xe2\xdf\x1c\x07\x98\x5c\x63\xde\x52\x93\xbc\xfc\x26\x83\xc9\xb1\x17\xd1\x8b\x74\xf0\x05\x07\x52\xa1\xfd\x5d\x81\xf4\x25\x92\xa9\x80\x6f\x20\xd9\x65\x92\xcc\x41\xc9\x10\xf0\x9f\x8b\x87\xe6\x90\x70\x42\x47\x0a\xa6\xa1\x60\xb4\x14\xa2\x76\xaa\x47\xe1\x1b\x44\x98\xae\x52\xfc\x03\xd4\xa4\x0f\x9c\xa5\x49\x17\x0d\x70\x24\x6a\x7d\xc6\x25\x0e\x2f\x10\xe1\xa2\xf6\x11\x45\x29\x56\x04\xbf\x30\x42\xc1\x04\x85\x15\x32\x92\x23\x09\x6f\x14\xae\x5a\x87\xc5\x31\xa3\x19\xf0\x5e\x3e\xb6\x82\x6f\x0f\x66\xb3\x37\xb7\xb7\x30\x21\x72\x5c\x9c\x5c\xf3\x70\xcc\xae\x71\x91\xba\x8b\x62\x2c\x72\x35\x96\x51\x5f\x30\xbe\xb7\xb8\xda\x60\x9b\x10\x8b\x80\x93\x44\x12\x46\xcd\x7b\x74\x2c\xf1\x8d\xcc\xec\x78\x15\x11\x21\xf3\xa9\x1c\xd1\x11\x86\x1a\xcc\x66\x19\x5f\x0d\x63\x39\xb8\xae\x27\xa5\x95\xaa\x56\xa4\x62\x5f\xdd\xb5\x60\x21\x40\xce\x58\x46\xbc\x4d\x29\x93\x48\xf1\x54\x40\xb9\x32\xfc\x34\xbc\x7d\x96\xf2\x00\x37\x32\x63\x62\x8a\x39\x92\x8c\x67\xee\x67\x94\x28\xaa\xa0\x03\x11\xa1\xe0\x6b\x2d\xc4\x43\x94\x46\xb2\x26\x89\x8c\x70\xae\x05\x89\xe3\x24\x42\xb2\xe8\x8b\xb5\x4d\x2a\x2f\xe2\x49\x85\x0a\x81\xb8\x0c\x55\x31\xd0\xb6\xc4\x37\x44\x51\x34\x40\xc1\xd7\x35\x7c\xa5\xec\x2b\xa4\xf0\x0d\x1e\x9a\x18\x11\xfa\x75\x6b\x0e\x12\x8e\x95\xb3\x98\xdb\xcd\x5e\xc1\x7f\xaf\x02\x74\xda\xd8\x92\x03\x12\x30\x8a\x63\xf6\x85\x6c\xc9\x83\x9a\x9f\xf2\x68\x5b\x8e\xd7\x84\x2b\xb8\xc9\x98\x24\xc1\x18\xc9\xa5\x41\x38\x8b\x9f\x6e\xdc\xbb\xd8\x62\x2c\x04\x1a\x3d\xc2\xf1\x0a\xbc\x25\x8a\x5a\x98\xca\xe9\x02\xdf\x7a\xf4\x3f\xce\x99\xd7\x31\x06\x11\xc1\x54\x3e\x5d\xe2\x4d\x18\x97\x75\xe3\x69\x2e\xb2\x8e\x97\x50\x21\x11\x0d\xb0\x28\xc1\xbb\x96\xee\xee\xd1\x2a\x4b\xc4\x08\x53\x82\x9f\x6e\xa4\xfb\x90\xad\x5b\x28\xaf\x0e\x1b\x92\x61\x69\x39\x30\xee\x14\xa3\x42\xb5\xdb\x83\x3a\x54\x67\x33\x23\x1b\x84\x6c\x50\xa7\xdd\xfb\x35\x52\x2c\x99\x9a\x48\x75\x45\xa2\x12\x7a\x1e\x16\x2c\xba\xc6\xe1\x1d\x8a\xf3\xe1\xed\x69\xce\x21\xd6\xa8\x56\xb7\x51\xa9\xd0\x55\xe0\xf1\xde\x54\xb0\xfa\x04\x3f\x25\x30\x8d\x57\xfb\xdd\x63\xbf\xf6\xaa\xfe\x79\xb4\x86\xaf\xd4\x3e\xab\x08\x8a\x26\xba\x26\x81\x64\x9c\x25\x62\x69\x79\x89\x24\xbe\x2a\xda\xea\xd5\x1c\x8f\x0b\xa7\x75\xad\x62\x2a\x89\x9c\x5e\x85\x44\x24\x11\x9a\x5e\x6d\x68\x67\x1e\xce\x7d\xeb\x98\x63\x46\x89\x64\x4a\x21\x57\x92\xb1\xe8\x91\x55\x65\x15\x37\x8e\x11\x89\x96\x7e\xb0\x5c\x31\x3c\x9a\xcb\x22\xa6\xb1\x8c\x35\x5b\x46\xf3\x87\x93\x5e\xc7\xff\x7c\x61\x83\x1a\x82\x8b\xcb\xf7\x5d\xa7\x03\x66\xd5\xb2\x3e\xbd\xed\x58\xd6\x89\x7f\x02\xbf\x9d\xf9\xe7\x5d\xd8\xaf\xd5\xc1\xe7\x88\x0a\xa2\x9c\x0d\x45\x96\x65\xbb\x26\x98\x63\x29\x93\x86\x65\x4d\x26\x93\xda\xe4\x6d\x8d\xf1\x91\xe5\x7b\xd6\x8d\xc2\xb5\xaf\x80\xf3\xcb\xaa\x5c\x81\xac\x85\x32\x34\x8f\x8d\xe6\x0f\xd5\xaa\xd1\x97\xd3\x08\x03\xa2\x21\x68\x22\x21\xe6\x44\x19\x54\x75\x1f\xa0\x50\x8b\x86\x65\x8d\x88\x1c\xa7\x83\x5a\xc0\x62\x4b\xc9\x30\x4a\xa9\xa5\xd1\xa1\x20\xc3\x57\xd5\xa2\x55\xe7\xea\x10\x86\x61\xf8\x63\x0c\xe7\x8e\x0f\x5d\x12\x60\x2a\x30\xbc\x39\x77\xfc\x3d\xc3\xe8\xb0\x64\xca\xc9\x68\x2c\xe1\x4d\xb0\x07\x07\xf5\xfd\x9f\xe1\x3c\xc3\x68\x18\x17\x98\xc7\x44\x08\xc2\x28\x10\x01\x63\xcc\xf1\x60\x0a\x23\x8e\xa8\xc4\x61\x05\x86\x1c\x63\x60\x43\x08\xc6\x88\x8f\x70\x05\x24\x03\x44\xa7\x90\x60\x2e\x18\x05\x36\x90\x88\x50\xe5\xff\x08\x02\x96\x4c\x0d\x36\x04\x39\x26\x02\x04\x1b\xca\x09\xe2\x99\x84\x48\x08\x16\x10\x24\x71\x08\x21\x0b\xd2\x18\xd3\x2c\x70\x61\x48\x22\x2c\xe0\x8d\x1c\x63\x30\xfb\x39\x84\xb9\xa7\x89\x84\x18\x45\x06\xa1\xa0\x9e\xcd\x1f\xe9\xc5\x16\x4b\x25\x70\x2c\x24\x27\x5a\x0b\x15\x20\x34\x88\xd2\x50\xf1\x30\x7f\x1c\x91\x98\xe4\x14\x14\xb8\x16\x5c\x18\x92\x41\x2a\x70\x45\xf3\x59\x81\x98\x85\x64\xa8\xfe\x62\x2d\x56\x92\x0e\x22\x22\xc6\x15\x08\x89\x42\x3d\x48\x25\xae\x80\x50\x83\x5a\x8f\x15\x25\x87\xc5\x38\x08\x1c\x45\x46\xc0\x12\x82\x05\x68\x59\x97\xdc\xe9\x39\x8a\xf5\x44\x29\x54\xe6\x2a\x12\x6a\x64\x32\x66\x71\x51\x12\x22\x8c\x61\xca\x29\x11\x63\xac\x61\x42\x06\x82\x69\x8a\xca\x9b\xd5\x88\x9a\x3e\x64\x51\xc4\x26\x4a\xb4\x80\xd1\x90\xe4\xeb\x2b\x6d\x64\x34\x50\x6b\xcc\x60\x61\x57\xca\x24\x09\x32\x75\x6b\x03\x24\x4b\xab\xe6\x8f\xc4\x18\x45\x11\x0c\x70\xae\x30\x1c\x02\xa1\x80\x56\xc4\xe1\x8a\xbc\x6a\xb1\x24\x41\x11\x24\x8c\x6b\x7a\x77\xc5\xac\x19\x86\x7f\x66\x43\xbf\x77\xea\x7f\x6a\x7b\x36\x38\x7d\xb8\xf0\x7a\x1f\x9d\x13\xfb\x04\xcc\x76\x1f\x9c\xbe\x59\x81\x4f\x8e\x7f\xd6\xbb\xf4\xe1\x53\xdb\xf3\xda\xae\xff\x19\x7a\xa7\xd0\x76\x3f\xc3\x7f\x1c\xf7\xa4\x02\xf6\x6f\x17\x9e\xdd\xef\x43\xcf\x33\x9c\xf3\x8b\xae\x63\x9f\x54\xc0\x71\x3b\xdd\xcb\x13\xc7\xfd\x00\xef\x2f\x7d\x70\x7b\x3e\x74\x9d\x73\xc7\xb7\x4f\xc0\xef\x81\x22\x98\xa3\x72\xec\xbe\x42\x76\x6e\x7b\x9d\xb3\xb6\xeb\xb7\xdf\x3b\x5d\xc7\xff\x5c\x31\x4e\x1d\xdf\x55\x38\x4f\x7b\x1e\xb4\xe1\xa2\xed\xf9\x4e\xe7\xb2\xdb\xf6\xe0\xe2\xd2\xbb\xe8\xf5\x6d\x68\xbb\x27\xe0\xf6\x5c\xc7\x3d\xf5\x1c\xf7\x83\x7d\x6e\xbb\x7e\x0d\x1c\x17\xdc\x1e\xd8\x1f\x6d\xd7\x87\xfe\x59\xbb\xdb\x55\xa4\x8c\xf6\xa5\x7f\xd6\xf3\x14\x7f\xd0\xe9\x5d\x7c\xf6\x9c\x0f\x67\x3e\x9c\xf5\xba\x27\xb6\xd7\x87\xf7\x36\x74\x9d\xf6\xfb\xae\x9d\x91\x72\x3f\x43\xa7\xdb\x76\xce\x2b\x70\xd2\x3e\x6f\x7f\xb0\x35\x54\xcf\x3f\xb3\x3d\x43\x4d\xcb\xb8\x83\x4f\x67\xb6\x1a\x52\xf4\xda\x2e\xb4\x3b\xbe\xd3\x73\x95\x18\x9d\x9e\xeb\x7b\xed\x8e\x5f\x01\xbf\xe7\xf9\x0b\xd0\x4f\x4e\xdf\xae\x40\xdb\x73\xfa\x4a\x21\xa7\x5e\xef\xbc\x62\x28\x75\xf6\x4e\xd5\x14\xc7\x55\x70\xae\x9d\x61\x51\xaa\x86\x82\x45\x7a\x9e\xbe\xbf\xec\xdb\x0b\x84\x70\x62\xb7\xbb\x8e\xfb\xa1\xaf\x80\x95\x88\xf3\xc9\x35\xa3\x5a\x3d\x36\x9a\x3a\x05\xde\xc4\x11\x15\xad\x92\xc4\xb6\x7f\x78\x78\x98\xe5\x33\x73\xbb\x49\x42\x25\xb7\x96\x39\x64\x54\x56\x87\x28\x26\xd1\xb4\x01\x3f\x9d\xe1\xe8\x1a\x4b\x12\x20\x70\x71\x8a\x7f\xaa\xc0\x62\xa0\x02\x6d\x4e\x50\x54\x01\x81\xa8\xa8\x0a\xcc\xc9\xf0\x08\x06\xec\xa6\x2a\xc8\x5f\xaa\x16\xc3\x80\xf1\x10\xf3\xea\x80\xdd\x1c\x81\x46\x2a\xc8\x5f\xb8\x01\xfb\x3f\x27\x37\x47\x10\x23\x3e\x22\xb4\x01\xf5\x23\x95\x5b\xc7\x18\x85\x2f\x49\x3f\xc6\x12\x81\xaa\xa8\x2d\xf3\x9a\xe0\x89\x8a\x22\x53\x45\xaf\xc4\x54\xb6\xcc\x09\x09\xe5\xb8\x15\xe2\x6b\x12\xe0\xaa\xbe\x79\x39\x65\x81\x35\x67\x57\x19\xb3\x8a\xff\x4c\xc9\x75\xcb\xec\x64\xac\x56\xfd\x69\x82\x57\x18\x57\xad\x88\xa5\x8c\x7b\xa4\x2b\x81\xc0\xb2\x75\xe9\x9f\x56\x7f\x7d\x61\xf6\xf5\xdb\x88\x97\x33\xf7\x7d\xbd\x48\xd3\xd2\xcc\x1d\x1b\x46\xd3\x52\x4e\xa9\x2e\x06\x2c\x9c\x02\x91\x38\x16\x01\x4b\x70\xcb\x34\xf5\x8d\x9c\xaa\xeb\x3c\xa2\x44\x30\xc6\x31\xd2\x11\x65\xab\xea\x7e\x3e\xef\x7d\x9f\x55\xc8\xea\x04\x0f\xbe\x12\x59\xcd\x1e\xc4\x8c\xc9\xb1\x06\xca\x6a\x03\x41\x02\x87\xcb\x49\xca\x37\x34\x74\x15\x85\x5f\x52\x21\x1b\x40\x19\xc5\x47\x30\xc6\xaa\x32\x35\x60\xbf\x5e\xff\xd7\x11\x44\x84\xe2\xea\x62\xa8\xf6\x0e\xc7\x47\xa0\x23\x20\x9b\x00\x3f\x90\x58\x05\x0b\xa2\xf2\x08\x06\x28\xf8\x3a\xe2\x2c\xa5\x61\x35\x60\x11\xe3\x0d\xf8\x71\xf8\x4e\xfd\xae\xaa\x1f\x12\x14\x86\x9a\x2b\xe5\x0d\x83\x91\x9e\xd9\x32\xf3\x99\xa6\xd2\xb7\x44\x83\xe7\x76\x8f\x15\x91\xb6\x94\xa3\x94\x77\x80\xa6\xe4\x2f\x98\xc7\x00\x14\x07\xcf\x9c\x49\xaf\x31\x57\x48\xa2\x2a\x8a\xc8\x88\x36\x40\xb2\xa4\xa8\xa8\x6b\xfd\xa0\x65\x4a\x96\x98\xc7\x4d\x4b\x86\x4b\x46\xb3\xcc\x6a\xbe\xab\xd7\x9f\x39\x54\x4a\x99\xce\x97\x56\x0d\x18\x44\x2c\xf8\x5a\xf0\xed\x18\xdd\x54\x73\x27\x79\x57\xaf\x27\x37\x85\x87\x41\x84\x11\x57\x04\xe5\xb8\x30\xbe\x29\x50\x16\xca\x01\x94\x4a\x76\x27\x24\x0a\xda\xd2\x8a\x02\x68\x86\xe4\xfa\xb9\xdd\xaa\x28\xef\x5d\xe5\xdc\x2f\xc4\x9c\x6f\x65\x64\x1d\xcc\xb9\x9d\x95\x26\x4c\x08\x70\x14\xe5\xb3\x5b\x66\x3d\xbb\x17\x09\x0a\xe6\xf7\xcf\x2a\x68\xfe\x90\xa3\x90\xa4\xa2\x01\x6f\xf5\x58\x49\x02\x18\x0e\x0b\x59\x2c\x03\x6b\xc0\x7e\x72\x03\x82\x45\x24\x84\x1f\xf1\xa1\xfa\x2d\x26\x86\xe1\x70\x45\x17\xbb\x90\x1d\x96\x9c\x3c\x5f\x96\x78\xb7\x31\xe0\x0a\xda\xd5\x20\x93\xbc\xd4\xfc\x52\xaf\x1f\x81\x2e\x51\xf9\xfc\x00\x53\x89\x79\x99\xbd\xf4\xbf\xba\x36\xca\xba\xdd\xec\x77\xbf\x1c\x1c\x74\xca\x0b\xd0\x81\xf2\x6b\x13\xf2\x78\xcb\x08\xac\x5a\x2f\x83\x2d\x8f\xc8\xf9\xcf\x72\x53\x73\xb1\x9b\x09\xfa\x65\x49\xe9\xbb\xa4\x3d\xd8\x87\xd9\x4c\x2c\x5e\x78\xc0\x90\x71\x58\x6e\xbc\x6d\xd8\xf8\x84\xd9\xec\x0e\x55\x58\xdd\x86\x6b\x15\x36\xe1\xd6\xa6\xe5\xaf\x56\x0a\xc6\x5f\xe4\xe0\xc5\x3d\x7f\x75\xd3\x6d\x8a\xd9\xd2\x79\xf6\x33\xe7\xb9\xcf\x37\x76\x3e\xf7\x6d\x54\xfb\x6e\x39\xc1\xae\xbb\x42\x1d\xea\xf3\x5c\x72\x9f\x3b\xe4\x62\x20\x18\x73\x3c\x6c\x99\xdb\xbc\x74\x7f\x66\x7f\x98\x27\xcd\xd3\xd3\xd3\x3c\xf9\x86\x38\x60\x5c\xbf\x93\x9b\x2f\x0f\x0a\x0b\x82\x03\xb5\x1c\x28\xe4\xed\x01\x8b\xc2\xf2\xc4\x1d\xa4\x5c\x28\xec\x09\x23\xd9\xc0\xa2\xa1\x20\x54\x23\xcd\xfb\x8a\x3b\x09\xfe\x17\xc5\x98\xc6\xa7\x5f\xa2\x0e\x19\x8f\x1b\x10\xa0\x84\x48\x14\x91\xbf\x70\x69\xd2\x7f\xfb\xf3\xaf\x38\x44\x25\xf5\x7a\x6d\x46\x3e\xac\xb5\xdc\xc8\x0a\xf9\x62\x70\xd1\xbd\x25\x37\xb9\x79\x8f\x3f\x12\x3c\x01\x42\xe1\xc1\xb7\xe3\x4d\x0b\x95\xfa\xf0\x9d\xc4\x5b\x9e\x7e\xb3\x9f\x87\x36\x3f\x4a\x8a\xc2\x6b\xc8\xfe\x3d\x21\x2b\x24\x67\x74\xf4\x72\xaa\xfd\x7d\xf3\xd1\xa9\x3f\xf2\x9d\xaf\xa6\x95\x31\xf9\x1d\xbc\xae\xa4\x61\xc8\x9f\xcc\xcf\x07\xdd\xdd\x42\x7b\xf5\xc3\x7f\x86\x1f\x66\xad\xe9\xc2\xd5\x9a\x83\x97\x33\x33\x58\xe5\x3a\x7a\xe0\x60\xdc\xe6\xd3\x6b\x2f\x2c\xcc\xe6\xb8\x83\x92\x5a\xb0\xdc\x44\xcf\x2a\xc1\x8b\x7b\xc6\x0a\x47\xbb\xe2\x1e\x0f\x6a\xf4\xc1\xd3\x8e\xff\xa3\xce\xb2\xda\x61\xde\x3d\x7e\xf9\x42\x0d\xe5\xbc\xdd\x5a\xeb\x29\x53\x1a\x62\xae\xba\xbf\xa2\x3b\x65\x07\x48\x55\x13\xb5\x7b\x39\xe6\x69\xd5\x74\xcb\xf6\x6e\xf5\xac\x49\xa9\x79\x5f\xbb\xc2\x9d\xa9\xc6\x3b\xe7\x99\x00\xcd\xf1\x0e\xf2\xb4\x73\x7a\x7a\x4c\x04\xdf\xd7\x11\xbf\x06\xd6\xff\x67\x9b\xbb\xba\xdc\x5a\x9c\xd9\x5b\x2e\xb8\xe6\x43\x2f\xb0\xe4\x5a\x3d\x41\xf8\xea\x8d\xff\x0c\x6f\x7c\x5d\x74\xbd\x2e\xba\x5e\x17\x5d\xbb\xee\x2c\xaf\x8b\xae\x9d\x69\xd9\x36\x19\xaa\x69\xe9\xfd\xb8\xe3\x47\x6c\x85\x2e\x40\x96\x23\xcf\x7e\x12\xa3\x70\x34\x69\xe5\xa4\xc9\xd2\xd0\x87\x87\x87\xf7\x6d\x70\x17\x77\x76\xd7\xb7\x24\x77\xa3\x69\xd8\xa5\xf6\xe5\x39\x5b\x97\x83\x8d\xad\x4b\xe9\x26\xda\x43\x26\x5f\xe9\x6d\xee\x9c\x6b\x28\x9e\xc2\x5a\x4d\x57\xc5\x0f\xc4\x9f\xcf\x21\x0e\x56\xb3\x95\x96\x68\xeb\x54\x85\xa9\x84\xc1\x74\xbb\x7d\xb8\xf5\xdc\xb1\x76\xde\xe1\x6e\x66\x68\x5a\x21\xb9\x3e\xce\xfe\x37\x8a\x69\x62\xd7\xda\xda\x0d\xc7\xeb\x32\x11\x97\xf9\xab\x69\x0d\x58\x38\x55\x23\x63\x19\x47\xc7\x86\x51\xfe\xfd\x4e\x92\x8a\x31\xbb\xc6\xfc\x3b\x7c\x80\xbd\x86\xea\xef\xff\x1e\xec\xfb\x7c\x0e\xb6\xfd\xd7\x60\xdf\xef\x63\xb0\x15\x9a\x5b\x68\x72\xf9\x15\xf5\x23\x3e\xab\xfc\x6f\x00\x00\x00\xff\xff\xed\x58\x62\xaa\x5e\x42\x00\x00") func templateDefaultTmplBytes() ([]byte, error) { return bindataRead( @@ -83,7 +83,7 @@ func templateDefaultTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "template/default.tmpl", size: 16571, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "template/default.tmpl", size: 16990, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil }