From 03c3b8bec3708dc0e2d4db9249413193a6789d48 Mon Sep 17 00:00:00 2001 From: Nitish Tiwari Date: Wed, 2 Dec 2020 16:10:42 +0530 Subject: [PATCH 1/2] Cleanup operator plugin Also update the statik files to refer to changes done in #371 --- kubectl-minio/README.md | 20 +- kubectl-minio/cmd/delete.go | 39 +- kubectl-minio/cmd/helpers/constants.go | 17 +- kubectl-minio/cmd/helpers/helpers.go | 62 + kubectl-minio/cmd/init.go | 10 +- kubectl-minio/cmd/kubectl-minio.go | 10 +- kubectl-minio/cmd/resources/tenant.go | 39 +- kubectl-minio/cmd/tenant-create.go | 82 +- kubectl-minio/cmd/tenant-delete.go | 37 +- kubectl-minio/cmd/tenant-expand.go | 32 +- kubectl-minio/cmd/tenant-info.go | 73 +- kubectl-minio/cmd/tenant-upgrade.go | 56 +- kubectl-minio/cmd/tenant.go | 6 +- kubectl-minio/go.mod | 4 + kubectl-minio/go.sum | 14 + kubectl-minio/statik/statik.go | 2 +- .../crds/minio.min.io_tenants.yaml | 3108 +++++++++-------- pkg/resources/services/service.go | 19 +- 18 files changed, 1874 insertions(+), 1756 deletions(-) diff --git a/kubectl-minio/README.md b/kubectl-minio/README.md index 25a35063dbe..40821e366d3 100644 --- a/kubectl-minio/README.md +++ b/kubectl-minio/README.md @@ -41,11 +41,11 @@ Options: #### MinIO Tenant Creation -Command: `kubectl minio tenant create --name TENANT_NAME --servers SERVERS --volumes TOTAL_VOLUMES --capacity TOTAL_RAW_CAPACITY [options]` +Command: `kubectl minio tenant create TENANT_NAME --servers SERVERS --volumes TOTAL_VOLUMES --capacity TOTAL_RAW_CAPACITY [options]` Creates a MinIO Tenant based on the passed values. -example: `kubectl minio tenant create --name tenant1 --servers 4 --volumes 16 --capacity 16Ti` +example: `kubectl minio tenant create tenant1 --servers 4 --volumes 16 --capacity 16Ti` Options: @@ -55,11 +55,11 @@ Options: #### Add Tenant pools -Command: `kubectl minio tenant expand --name TENANT_NAME --servers SERVERS --volumes TOTAL_VOLUMES --capacity TOTAL_RAW_CAPACITY [options]` +Command: `kubectl minio tenant expand TENANT_NAME --servers SERVERS --volumes TOTAL_VOLUMES --capacity TOTAL_RAW_CAPACITY [options]` Add new volumes (and nodes) to existing MinIO Tenant. -example: `kubectl minio tenant expand --name tenant1 --servers 4 --volumes 16 --capacity 16Ti` +example: `kubectl minio tenant expand tenant1 --servers 4 --volumes 16 --capacity 16Ti` Options: @@ -68,11 +68,11 @@ Options: #### List Tenant pools -Command: `kubectl minio tenant info --name TENANT_NAME [options]` +Command: `kubectl minio tenant info TENANT_NAME [options]` List all existing MinIO pools in the given MinIO Tenant. -example: `kubectl minio tenant info --name tenant1` +example: `kubectl minio tenant info tenant1` Options: @@ -80,11 +80,11 @@ Options: #### Upgrade Images -Command: `kubectl minio tenant upgrade --name TENANT_NAME --image IMAGE_TAG [options]` +Command: `kubectl minio tenant upgrade TENANT_NAME --image IMAGE_TAG [options]` Upgrade MinIO Docker image for the given MinIO Tenant. -example: `kubectl minio tenant upgrade --name tenant1 --image minio/minio:RELEASE.2020-11-19T23-48-16Z` +example: `kubectl minio tenant upgrade tenant1 --image minio/minio:RELEASE.2020-11-19T23-48-16Z` Options: @@ -93,11 +93,11 @@ Options: #### Remove Tenant -Command: `kubectl minio tenant delete --name TENANT_NAME [options]` +Command: `kubectl minio tenant delete TENANT_NAME [options]` Delete an existing MinIO Tenant. -example: `kubectl minio tenant delete --name tenant1` +example: `kubectl minio tenant delete tenant1` Options: diff --git a/kubectl-minio/cmd/delete.go b/kubectl-minio/cmd/delete.go index 6cf67298e41..76a15c0f1ca 100644 --- a/kubectl-minio/cmd/delete.go +++ b/kubectl-minio/cmd/delete.go @@ -19,16 +19,14 @@ package cmd import ( - "bufio" "context" "errors" "fmt" "io" - "os" - "strings" "github.com/minio/kubectl-minio/cmd/helpers" "github.com/minio/kubectl-minio/cmd/resources" + "github.com/minio/minio/pkg/color" "github.com/spf13/cobra" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -37,7 +35,7 @@ import ( const ( deleteDesc = ` -'delete' command delete MinIO Operator deployment along with all the tenants.` +'delete' command delete MinIO Operator along with all the tenants.` deleteExample = ` kubectl minio delete` ) @@ -54,51 +52,28 @@ func newDeleteCmd(out io.Writer, errOut io.Writer) *cobra.Command { cmd := &cobra.Command{ Use: "delete", - Short: "Delete MinIO Operator deployment", + Short: "Delete MinIO Operator", Long: deleteDesc, Example: deleteExample, PreRunE: func(cmd *cobra.Command, args []string) error { - fmt.Printf("Are you sure you want to delete ALL the MinIO Tenants and MinIO Operator? [Y/N]: ") - if !o.ask() { - return errors.New("Aborting Operator deletion") + if !helpers.Ask(fmt.Sprintf("Are you sure you want to delete ALL the MinIO Tenants and MinIO Operator?")) { + return fmt.Errorf(color.Bold("Aborting Operator deletion\n")) } return nil }, RunE: func(cmd *cobra.Command, args []string) error { if len(args) != 0 { - return errors.New("this command does not accept arguments") + return errors.New("delete command does not accept arguments") } return o.run() }, } - + cmd = helpers.DisableHelp(cmd) f := cmd.Flags() f.StringVarP(&o.operatorOpts.NS, "namespace", "n", helpers.DefaultNamespace, "namespace scope for this request") - return cmd } -func (o *deleteCmd) ask() bool { - reader := bufio.NewReader(os.Stdin) - for { - s, _ := reader.ReadString('\n') - s = strings.TrimSuffix(s, "\n") - s = strings.ToLower(s) - if len(s) > 1 { - fmt.Fprintln(os.Stderr, "Please enter Y or N") - continue - } - if strings.Compare(s, "n") == 0 { - return false - } else if strings.Compare(s, "y") == 0 { - break - } else { - continue - } - } - return true -} - func (o *deleteCmd) run() error { client, err := helpers.GetKubeClient() if err != nil { diff --git a/kubectl-minio/cmd/helpers/constants.go b/kubectl-minio/cmd/helpers/constants.go index d3566f331ea..452ddbe9296 100644 --- a/kubectl-minio/cmd/helpers/constants.go +++ b/kubectl-minio/cmd/helpers/constants.go @@ -23,9 +23,6 @@ import ( ) const ( - // StaticYamlPath is path to the static yaml files - // StaticYamlPath = "https://raw.githubusercontent.com/nitisht/kubectl-minio/master/cmd/static/static.yaml" - // ClusterRoleBindingName is the name for CRB ClusterRoleBindingName = "minio-operator-binding" @@ -86,11 +83,13 @@ const ( DefaultConsoleImage = "minio/console:v0.4.6" ) -// DeploymentReplicas is the number of replicas for MinIO Operator -var DeploymentReplicas int32 = 1 +var ( + // DeploymentReplicas is the number of replicas for MinIO Operator + DeploymentReplicas int32 = 1 -// KESReplicas is the number of replicas for MinIO KES -var KESReplicas int32 = 2 + // KESReplicas is the number of replicas for MinIO KES + KESReplicas int32 = 2 -// ConsoleReplicas is the number of replicas for MinIO Console -var ConsoleReplicas int32 = 2 + // ConsoleReplicas is the number of replicas for MinIO Console + ConsoleReplicas int32 = 2 +) diff --git a/kubectl-minio/cmd/helpers/helpers.go b/kubectl-minio/cmd/helpers/helpers.go index f13e7c8464a..b40afbaa79b 100644 --- a/kubectl-minio/cmd/helpers/helpers.go +++ b/kubectl-minio/cmd/helpers/helpers.go @@ -21,15 +21,23 @@ package helpers import ( "bytes" "context" + "fmt" "io" + "os" "os/exec" + "strings" + "github.com/dustin/go-humanize" + "github.com/manifoldco/promptui" operatorv1 "github.com/minio/operator/pkg/client/clientset/versioned" + "github.com/spf13/cobra" apiextension "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/yaml" + miniov1 "github.com/minio/operator/pkg/apis/minio.min.io/v1" + table "github.com/olekukonko/tablewriter" "github.com/pkg/errors" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" @@ -134,6 +142,16 @@ func CapacityPerVolume(capacity string, volumes int32) (*resource.Quantity, erro return resource.NewQuantity(bytesPerVolume, totalQuantity.Format), nil } +// TotalCapacity returns total capacity of a given tenant +func TotalCapacity(tenant miniov1.Tenant) string { + var totalBytes int64 + for _, z := range tenant.Spec.Pools { + pvcBytes, _ := z.VolumeClaimTemplate.Spec.Resources.Requests.Storage().AsInt64() + totalBytes = totalBytes + (pvcBytes * int64(z.Servers) * int64(z.VolumesPerServer)) + } + return humanize.IBytes(uint64(totalBytes)) +} + // ToYaml takes a slice of values, and returns corresponding YAML // representation as a string slice func ToYaml(objs []runtime.Object) ([]string, error) { @@ -148,3 +166,47 @@ func ToYaml(objs []runtime.Object) ([]string, error) { return manifests, nil } + +// GetTable returns a formatted instance of the table +func GetTable() *table.Table { + t := table.NewWriter(os.Stdout) + t.SetAutoWrapText(false) + t.SetHeaderAlignment(table.ALIGN_LEFT) + t.SetAlignment(table.ALIGN_LEFT) + return t +} + +// DisableHelp disables the help command +func DisableHelp(cmd *cobra.Command) *cobra.Command { + cmd.SetHelpCommand(&cobra.Command{ + Use: "no-help", + Hidden: true, + }) + return cmd +} + +// Ask user for Y/N input. Return true if response is "y" +func Ask(label string) bool { + validate := func(input string) error { + s := strings.TrimSuffix(input, "\n") + s = strings.ToLower(s) + if strings.Compare(s, "n") != 0 && strings.Compare(s, "y") != 0 { + return errors.New("Please enter y/n") + } + return nil + } + + prompt := promptui.Prompt{ + Label: label, + Validate: validate, + } + fmt.Println() + result, err := prompt.Run() + if err != nil { + return false + } + if strings.Compare(result, "n") == 0 { + return false + } + return true +} diff --git a/kubectl-minio/cmd/init.go b/kubectl-minio/cmd/init.go index ecc1cd72636..2c199883e66 100644 --- a/kubectl-minio/cmd/init.go +++ b/kubectl-minio/cmd/init.go @@ -28,7 +28,7 @@ import ( "github.com/minio/kubectl-minio/cmd/resources" "github.com/spf13/cobra" - apiextensionv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextension "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" appsv1 "k8s.io/api/apps/v1" @@ -43,7 +43,7 @@ import ( const ( operatorInitDesc = ` 'init' command creates MinIO Operator deployment along with all the dependencies.` - operatorInitExample = ` kubectl minio operator init` + operatorInitExample = ` kubectl minio init` ) type operatorInitCmd struct { @@ -59,7 +59,7 @@ func newInitCmd(out io.Writer, errOut io.Writer) *cobra.Command { cmd := &cobra.Command{ Use: "init", - Short: "Initialize MinIO Operator deployment", + Short: "Initialize MinIO Operator", Long: operatorInitDesc, Example: operatorInitExample, RunE: func(cmd *cobra.Command, args []string) error { @@ -69,7 +69,7 @@ func newInitCmd(out io.Writer, errOut io.Writer) *cobra.Command { return o.run() }, } - + cmd = helpers.DisableHelp(cmd) f := cmd.Flags() f.StringVarP(&o.operatorOpts.Image, "image", "i", helpers.DefaultOperatorImage, "operator image") f.StringVarP(&o.operatorOpts.NS, "namespace", "n", helpers.DefaultNamespace, "namespace scope for this request") @@ -124,7 +124,7 @@ func (o *operatorInitCmd) run() error { } func createCRD(client *apiextension.Clientset, crd *apiextensionv1.CustomResourceDefinition) error { - _, err := client.ApiextensionsV1beta1().CustomResourceDefinitions().Create(context.Background(), crd, v1.CreateOptions{}) + _, err := client.ApiextensionsV1().CustomResourceDefinitions().Create(context.Background(), crd, v1.CreateOptions{}) if err != nil { if k8serrors.IsAlreadyExists(err) { return fmt.Errorf("CustomResourceDefinition %s: already present, skipped", crd.ObjectMeta.Name) diff --git a/kubectl-minio/cmd/kubectl-minio.go b/kubectl-minio/cmd/kubectl-minio.go index 7190c6584fb..0f8c6ed6945 100644 --- a/kubectl-minio/cmd/kubectl-minio.go +++ b/kubectl-minio/cmd/kubectl-minio.go @@ -35,8 +35,9 @@ import ( "k8s.io/client-go/scale/scheme" // Statik CRD assets for our plugin + "github.com/minio/kubectl-minio/cmd/helpers" _ "github.com/minio/kubectl-minio/statik" - apiextensionv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + apiextensionv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" ) var ( @@ -49,7 +50,7 @@ var ( const ( minioDesc = ` -kubectl plugin to manage MinIO operator CRDs.` +Deploy and manage the multi tenant, S3 API compatible object storage on Kubernetes` ) func init() { @@ -105,10 +106,11 @@ func NewCmdMinIO(streams genericclioptions.IOStreams) *cobra.Command { Long: minioDesc, SilenceUsage: true, } - + cmd = helpers.DisableHelp(cmd) + cobra.EnableCommandSorting = false cmd.AddCommand(newInitCmd(cmd.OutOrStdout(), cmd.ErrOrStderr())) - cmd.AddCommand(newDeleteCmd(cmd.OutOrStdout(), cmd.ErrOrStderr())) cmd.AddCommand(newTenantCmd(cmd.OutOrStdout(), cmd.ErrOrStderr())) + cmd.AddCommand(newDeleteCmd(cmd.OutOrStdout(), cmd.ErrOrStderr())) return cmd } diff --git a/kubectl-minio/cmd/resources/tenant.go b/kubectl-minio/cmd/resources/tenant.go index bfd4e0e3883..e1a2a11ec2c 100644 --- a/kubectl-minio/cmd/resources/tenant.go +++ b/kubectl-minio/cmd/resources/tenant.go @@ -41,30 +41,20 @@ type TenantOptions struct { StorageClass string KmsSecret string ConsoleSecret string - CertSecret string DisableTLS bool ImagePullSecret string } // Validate Tenant Options func (t TenantOptions) Validate() error { - if t.Name == "" { - return errors.New("--name flag is required for tenant creation") + if t.Servers <= 0 { + return errors.New("--servers is required. Specify a value greater than or equal to 1") } - if t.Servers == 0 { - return errors.New("--servers flag is required for tenant creation") - } - if t.Servers < 0 { - return errors.New("servers can not be negative") - } - if t.Volumes == 0 { - return errors.New("--volumes flag is required for tenant creation") - } - if t.Volumes < 0 { - return errors.New("volumes can not be negative") + if t.Volumes <= 0 { + return errors.New("--volumes is required. Specify a positive value") } if t.Capacity == "" { - return errors.New("--capacity flag is required for tenant creation") + return errors.New("--capacity flag is required") } _, err := resource.ParseQuantity(t.Capacity) if err != nil { @@ -132,16 +122,6 @@ func tenantConsoleConfig(tenant, secret string) *miniov1.ConsoleConfiguration { return nil } -func externalCertSecret(secret string) []*miniov1.LocalCertificateReference { - certs := make([]*miniov1.LocalCertificateReference, 1) - if secret != "" { - certs[0] = &miniov1.LocalCertificateReference{ - Name: secret, - } - } - return certs -} - func storageClass(sc string) *string { if sc != "" { return &sc @@ -179,11 +159,10 @@ func NewTenant(opts *TenantOptions) (*miniov1.Tenant, error) { OrganizationName: []string{}, DNSNames: []string{}, }, - Mountpath: helpers.MinIOMountPath, - KES: tenantKESConfig(opts.Name, opts.KmsSecret), - Console: tenantConsoleConfig(opts.Name, opts.ConsoleSecret), - ExternalCertSecret: externalCertSecret(opts.CertSecret), - ImagePullSecret: v1.LocalObjectReference{Name: opts.ImagePullSecret}, + Mountpath: helpers.MinIOMountPath, + KES: tenantKESConfig(opts.Name, opts.KmsSecret), + Console: tenantConsoleConfig(opts.Name, opts.ConsoleSecret), + ImagePullSecret: v1.LocalObjectReference{Name: opts.ImagePullSecret}, }, } return t, t.Validate() diff --git a/kubectl-minio/cmd/tenant-create.go b/kubectl-minio/cmd/tenant-create.go index c60f24fa586..87f26f06115 100644 --- a/kubectl-minio/cmd/tenant-create.go +++ b/kubectl-minio/cmd/tenant-create.go @@ -20,27 +20,30 @@ package cmd import ( "context" + "errors" "fmt" "io" + "strconv" + "strings" "github.com/minio/kubectl-minio/cmd/helpers" "github.com/minio/kubectl-minio/cmd/resources" "github.com/minio/minio/pkg/color" + miniov1 "github.com/minio/operator/pkg/apis/minio.min.io/v1" + operatorv1 "github.com/minio/operator/pkg/client/clientset/versioned" + "github.com/minio/operator/pkg/resources/services" + "github.com/spf13/cobra" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "sigs.k8s.io/yaml" - - miniov1 "github.com/minio/operator/pkg/apis/minio.min.io/v1" - operatorv1 "github.com/minio/operator/pkg/client/clientset/versioned" - "github.com/spf13/cobra" ) const ( createDesc = ` 'create' command creates a new MinIO tenant` - createExample = ` kubectl minio tenant create --name tenant1 --servers 4 --volumes 16 --capacity 16Ti --namespace tenant1-ns` + createExample = ` kubectl minio tenant create tenant1 --servers 4 --volumes 16 --capacity 16Ti --namespace tenant1-ns` tenantSecretSuffix = "-creds-secret" consoleSecretSuffix = "-console-secret" ) @@ -56,20 +59,19 @@ func newTenantCreateCmd(out io.Writer, errOut io.Writer) *cobra.Command { c := &createCmd{out: out, errOut: errOut} cmd := &cobra.Command{ - Use: "create", + Use: "create --servers --volumes --capacity --namespace ", Short: "Create a MinIO tenant", Long: createDesc, Example: createExample, RunE: func(cmd *cobra.Command, args []string) error { - if err := c.validate(); err != nil { + if err := c.validate(args); err != nil { return err } return c.run(args) }, } - + cmd = helpers.DisableHelp(cmd) f := cmd.Flags() - f.StringVar(&c.tenantOpts.Name, "name", "", "name of the MinIO tenant to create") f.Int32Var(&c.tenantOpts.Servers, "servers", 0, "total number of pods in MinIO tenant") f.Int32Var(&c.tenantOpts.Volumes, "volumes", 0, "total number of volumes in the MinIO tenant") f.StringVar(&c.tenantOpts.Capacity, "capacity", "", "total raw capacity of MinIO tenant in this pool, e.g. 16Ti") @@ -78,13 +80,26 @@ func newTenantCreateCmd(out io.Writer, errOut io.Writer) *cobra.Command { f.StringVar(&c.tenantOpts.KmsSecret, "kes-config", "", "name of secret with details for enabling encryption, refer example https://github.com/minio/operator/blob/master/examples/kes-secret.yaml") f.BoolVarP(&c.output, "output", "o", false, "dry run this command and generate requisite yaml") + cmd.MarkFlagRequired("servers") + cmd.MarkFlagRequired("volumes") + cmd.MarkFlagRequired("capacity") return cmd } -func (c *createCmd) validate() error { +func (c *createCmd) validate(args []string) error { + c.tenantOpts.Name = args[0] c.tenantOpts.SecretName = c.tenantOpts.Name + tenantSecretSuffix c.tenantOpts.ConsoleSecret = c.tenantOpts.Name + consoleSecretSuffix c.tenantOpts.Image = helpers.DefaultTenantImage + if args == nil { + return errors.New("create command requires specifying the tenant name as an argument, e.g. 'kubectl minio tenant create tenant1'") + } + if len(args) != 1 { + return errors.New("create command requires specifying the tenant name as an argument, e.g. 'kubectl minio tenant create tenant1'") + } + if args[0] == "" { + return errors.New("create command requires specifying the tenant name as an argument, e.g. 'kubectl minio tenant create tenant1'") + } return c.tenantOpts.Validate() } @@ -143,34 +158,31 @@ func createTenant(oclient *operatorv1.Clientset, kclient *kubernetes.Clientset, if err != nil { return err } + minSvc := services.NewClusterIPForMinIO(to) + conSvc := services.NewClusterIPForConsole(to) if color.IsTerminal() { - consolePort := miniov1.ConsolePort - minioPort := miniov1.MinIOPort - if to.HasCertConfig() || to.AutoCert() { - consolePort = miniov1.ConsoleTLSPort - } - printBanner(to.ObjectMeta.Name, string(console.Data["CONSOLE_ACCESS_KEY"]), string(console.Data["CONSOLE_SECRET_KEY"]), - to.ConsoleCIServiceName(), to.MinIOHLServiceName(), consolePort, minioPort, (to.HasCertConfig() || to.AutoCert())) + printBanner(to.ObjectMeta.Name, to.ObjectMeta.Namespace, string(console.Data["CONSOLE_ACCESS_KEY"]), string(console.Data["CONSOLE_SECRET_KEY"]), + minSvc, conSvc) } return nil } -func printBanner(tenantName, user, pwd, consoleSVCName, minioSVCName string, consolePort, minioPort int, tls bool) { - minioLocalPort := 9000 - consoleLocalPort := 9090 - scheme := "http" - if tls { - scheme = "https" - } - fmt.Printf(color.Bold(fmt.Sprintf("\nMinIO Tenant '%s' created\n\n", tenantName))) - fmt.Printf(color.Blue("Username: ") + color.Bold(fmt.Sprintf("%s \n", user))) - fmt.Printf(color.Blue("Password: ") + color.Bold(fmt.Sprintf("%s \n\n", pwd))) - - fmt.Printf(color.Blue("Web interface access: \n")) - fmt.Printf(fmt.Sprintf("\t$ kubectl port-forward svc/%s %d:%d\n", consoleSVCName, consoleLocalPort, consolePort)) - fmt.Printf(fmt.Sprintf("\tPoint browser to %s://localhost:%d\n\n", scheme, consoleLocalPort)) - - fmt.Printf(color.Blue("Object storage access: \n")) - fmt.Printf(fmt.Sprintf("\t$ kubectl port-forward svc/%s %d:%d\n", minioSVCName, minioLocalPort, minioPort)) - fmt.Printf((fmt.Sprintf("\t$ mc alias set %s %s://localhost:%d %s %s\n\n", tenantName, scheme, minioLocalPort, user, pwd))) +func printBanner(tenantName, ns, user, pwd string, s, c *corev1.Service) { + fmt.Printf(color.Bold(fmt.Sprintf("\nTenant '%s' created in '%s' Namespace\n\n", tenantName, ns))) + fmt.Printf(color.Blue(" Username: %s \n", user)) + fmt.Printf(color.Blue(" Password: %s \n", pwd)) + fmt.Printf(color.Blue(" Note: Copy the credentials to a secure location. MinIO will not display these again.\n\n")) + var minPorts, consolePorts string + for _, p := range s.Spec.Ports { + minPorts = minPorts + strconv.Itoa(int(p.Port)) + "," + } + for _, p := range c.Spec.Ports { + consolePorts = consolePorts + strconv.Itoa(int(p.Port)) + "," + } + t := helpers.GetTable() + t.SetHeader([]string{"Application", "Service Name", "Namespace", "Service Type", "Service Port"}) + t.Append([]string{"MinIO", s.Name, ns, "ClusterIP", strings.TrimSuffix(minPorts, ",")}) + t.Append([]string{"Console", c.Name, ns, "ClusterIP", strings.TrimSuffix(consolePorts, ",")}) + t.Render() + fmt.Println() } diff --git a/kubectl-minio/cmd/tenant-delete.go b/kubectl-minio/cmd/tenant-delete.go index 4f7ac053116..41c9a854643 100644 --- a/kubectl-minio/cmd/tenant-delete.go +++ b/kubectl-minio/cmd/tenant-delete.go @@ -25,6 +25,7 @@ import ( "io" "github.com/minio/kubectl-minio/cmd/helpers" + "github.com/minio/minio/pkg/color" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -36,13 +37,12 @@ import ( const ( tenantDeleteDesc = ` 'delete' command deletes a MinIO tenant` - tenantDeleteExample = ` kubectl minio tenant delete --name tenant1 --namespace tenant1-ns` + tenantDeleteExample = ` kubectl minio tenant delete tenant1 --namespace tenant1-ns` ) type tenantDeleteCmd struct { out io.Writer errOut io.Writer - name string ns string } @@ -54,23 +54,34 @@ func newTenantDeleteCmd(out io.Writer, errOut io.Writer) *cobra.Command { Short: "Delete a MinIO tenant", Long: deleteDesc, Example: deleteExample, - RunE: func(cmd *cobra.Command, args []string) error { - if err := c.validate(); err != nil { + PreRunE: func(cmd *cobra.Command, args []string) error { + if err := c.validate(args); err != nil { return err } + if !helpers.Ask(fmt.Sprintf("This will delete the Tenant %s and ALL its data. Do you want to proceed?", args[0])) { + return fmt.Errorf(color.Bold("Aborting Tenant deletion\n")) + } + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { return c.run(args) }, } - + cmd = helpers.DisableHelp(cmd) f := cmd.Flags() - f.StringVar(&c.name, "name", "", "name of the MinIO tenant to delete") f.StringVarP(&c.ns, "namespace", "n", helpers.DefaultNamespace, "namespace scope for this request") return cmd } -func (d *tenantDeleteCmd) validate() error { - if d.name == "" { - return errors.New("--name flag is required for tenant deletion") +func (d *tenantDeleteCmd) validate(args []string) error { + if args == nil { + return errors.New("provide the name of the tenant, e.g. 'kubectl minio tenant delete tenant1'") + } + if len(args) != 1 { + return errors.New("delete command requires specifying the tenant name as an argument, e.g. 'kubectl minio tenant delete tenant1'") + } + if args[0] == "" { + return errors.New("provide the name of the tenant, e.g. 'kubectl minio tenant delete tenant1'") } return nil } @@ -85,15 +96,15 @@ func (d *tenantDeleteCmd) run(args []string) error { if err != nil { return err } - return deleteTenant(oclient, kclient, d) + return deleteTenant(oclient, kclient, d, args[0]) } -func deleteTenant(client *operatorv1.Clientset, kclient *kubernetes.Clientset, d *tenantDeleteCmd) error { - tenant, err := client.MinioV1().Tenants(d.ns).Get(context.Background(), d.name, metav1.GetOptions{}) +func deleteTenant(client *operatorv1.Clientset, kclient *kubernetes.Clientset, d *tenantDeleteCmd, name string) error { + tenant, err := client.MinioV1().Tenants(d.ns).Get(context.Background(), name, metav1.GetOptions{}) if err != nil { return err } - if err := client.MinioV1().Tenants(d.ns).Delete(context.Background(), d.name, v1.DeleteOptions{}); err != nil { + if err := client.MinioV1().Tenants(d.ns).Delete(context.Background(), name, v1.DeleteOptions{}); err != nil { return err } if err := kclient.CoreV1().Secrets(d.ns).Delete(context.Background(), tenant.Spec.CredsSecret.Name, metav1.DeleteOptions{}); err != nil { diff --git a/kubectl-minio/cmd/tenant-expand.go b/kubectl-minio/cmd/tenant-expand.go index 2c313f58632..760b748957d 100644 --- a/kubectl-minio/cmd/tenant-expand.go +++ b/kubectl-minio/cmd/tenant-expand.go @@ -21,11 +21,13 @@ package cmd import ( "context" "encoding/json" + "errors" "fmt" "io" "github.com/minio/kubectl-minio/cmd/helpers" "github.com/minio/kubectl-minio/cmd/resources" + "github.com/minio/minio/pkg/color" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/yaml" @@ -38,7 +40,7 @@ import ( const ( expandDesc = ` 'expand' command adds storage capacity to a MinIO tenant` - expandExample = ` kubectl minio tenant expand --name tenant1 --servers 4 --volumes 32 --capacity 32Ti --namespace tenant1-ns` + expandExample = ` kubectl minio tenant expand tenant1 --servers 4 --volumes 32 --capacity 32Ti --namespace tenant1-ns` ) type expandCmd struct { @@ -52,30 +54,42 @@ func newTenantExpandCmd(out io.Writer, errOut io.Writer) *cobra.Command { v := &expandCmd{out: out, errOut: errOut} cmd := &cobra.Command{ - Use: "expand", + Use: "expand --servers --volumes --capacity --namespace ", Short: "Add capacity to existing tenant", Long: expandDesc, Example: expandExample, RunE: func(cmd *cobra.Command, args []string) error { - if err := v.validate(); err != nil { + if err := v.validate(args); err != nil { return err } return v.run() }, } - + cmd = helpers.DisableHelp(cmd) f := cmd.Flags() - f.StringVar(&v.tenantOpts.Name, "name", "", "name of the MinIO tenant to add volumes") f.Int32Var(&v.tenantOpts.Servers, "servers", 0, "total number of pods to add to tenant") f.Int32Var(&v.tenantOpts.Volumes, "volumes", 0, "total number of volumes to add to tenant") f.StringVar(&v.tenantOpts.Capacity, "capacity", "", "total raw capacity to add to tenant, e.g. 16Ti") f.StringVarP(&v.tenantOpts.NS, "namespace", "n", helpers.DefaultNamespace, "namespace scope for this request") f.BoolVarP(&v.output, "output", "o", false, "dry run this command and generate requisite yaml") + cmd.MarkFlagRequired("servers") + cmd.MarkFlagRequired("volumes") + cmd.MarkFlagRequired("capacity") return cmd } -func (v *expandCmd) validate() error { +func (v *expandCmd) validate(args []string) error { + if args == nil { + return errors.New("provide the name of the tenant, e.g. 'kubectl minio tenant expand tenant1'") + } + if len(args) != 1 { + return errors.New("expand command supports a single argument, e.g. 'kubectl minio tenant expand tenant1'") + } + if args[0] == "" { + return errors.New("provide the name of the tenant, e.g. 'kubectl minio tenant expand tenant1'") + } + v.tenantOpts.Name = args[0] return v.tenantOpts.Validate() } @@ -91,7 +105,7 @@ func (v *expandCmd) run() error { if err != nil { return err } - + currentCapacity := helpers.TotalCapacity(*t) volumesPerServer := helpers.VolumesPerServer(v.tenantOpts.Volumes, v.tenantOpts.Servers) capacityPerVolume, err := helpers.CapacityPerVolume(v.tenantOpts.Capacity, v.tenantOpts.Volumes) if err != nil { @@ -99,8 +113,9 @@ func (v *expandCmd) run() error { } t.Spec.Pools = append(t.Spec.Pools, resources.Pool(v.tenantOpts.Servers, volumesPerServer, *capacityPerVolume, v.tenantOpts.StorageClass)) - + expandedCapacity := helpers.TotalCapacity(*t) if !v.output { + fmt.Printf(color.Bold(fmt.Sprintf("\nExpanding Tenant '%s/%s' from %s to %s\n\n", t.ObjectMeta.Name, t.ObjectMeta.Namespace, currentCapacity, expandedCapacity))) return addPoolToTenant(client, t) } @@ -120,6 +135,5 @@ func addPoolToTenant(client *operatorv1.Clientset, t *miniov1.Tenant) error { if _, err := client.MinioV1().Tenants(t.Namespace).Patch(context.Background(), t.Name, types.MergePatchType, data, metav1.PatchOptions{FieldManager: "kubectl"}); err != nil { return err } - fmt.Printf("Adding new volumes to MinIO Tenant %s\n", t.ObjectMeta.Name) return nil } diff --git a/kubectl-minio/cmd/tenant-info.go b/kubectl-minio/cmd/tenant-info.go index e42f24ce59f..fcd315540e5 100644 --- a/kubectl-minio/cmd/tenant-info.go +++ b/kubectl-minio/cmd/tenant-info.go @@ -21,28 +21,29 @@ package cmd import ( "context" "errors" + "fmt" "io" - "os" + "strconv" + "strings" "github.com/minio/kubectl-minio/cmd/helpers" + "github.com/minio/minio/pkg/color" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/jedib0t/go-pretty/table" - "github.com/jedib0t/go-pretty/text" - operatorv1 "github.com/minio/operator/pkg/client/clientset/versioned" + miniov1 "github.com/minio/operator/pkg/apis/minio.min.io/v1" + "github.com/minio/operator/pkg/resources/services" "github.com/spf13/cobra" ) const ( infoDesc = ` 'info' command lists pools from a MinIO tenant` - infoExample = ` kubectl minio tenant info --name tenant1 --namespace tenant1-ns` + infoExample = ` kubectl minio tenant info tenant1 --namespace tenant1-ns` ) type infoCmd struct { out io.Writer errOut io.Writer - name string ns string } @@ -54,53 +55,73 @@ func newTenantInfoCmd(out io.Writer, errOut io.Writer) *cobra.Command { Short: "List all volumes in existing tenant", Long: infoDesc, RunE: func(cmd *cobra.Command, args []string) error { - if err := c.validate(); err != nil { + if err := c.validate(args); err != nil { return err } - return c.run() + return c.run(args) }, } - + cmd = helpers.DisableHelp(cmd) f := cmd.Flags() - f.StringVar(&c.name, "name", "", "name of the MinIO tenant to list volumes") f.StringVarP(&c.ns, "namespace", "n", helpers.DefaultNamespace, "namespace scope for this request") return cmd } -func (d *infoCmd) validate() error { - if d.name == "" { - return errors.New("--name flag is required for adding volumes to tenant") +func (d *infoCmd) validate(args []string) error { + if args == nil { + return errors.New("provide the name of the tenant, e.g. 'kubectl minio tenant info tenant1'") + } + if len(args) != 1 { + return errors.New("info command supports a single argument, e.g. 'kubectl minio tenant info tenant1'") + } + if args[0] == "" { + return errors.New("provide the name of the tenant, e.g. 'kubectl minio tenant info tenant1'") } return nil } // run initializes local config and installs MinIO Operator to Kubernetes cluster. -func (d *infoCmd) run() error { +func (d *infoCmd) run(args []string) error { // Create operator client oclient, err := helpers.GetKubeOperatorClient() if err != nil { return err } - err = listPoolsTenant(oclient, d) + + tenant, err := oclient.MinioV1().Tenants(d.ns).Get(context.Background(), args[0], metav1.GetOptions{}) if err != nil { return err } + printTenantInfo(*tenant) + return nil } -func listPoolsTenant(client *operatorv1.Clientset, d *infoCmd) error { - tenant, err := client.MinioV1().Tenants(d.ns).Get(context.Background(), d.name, metav1.GetOptions{}) - if err != nil { - return err +func printTenantInfo(tenant miniov1.Tenant) { + minSvc := services.NewClusterIPForMinIO(&tenant) + conSvc := services.NewClusterIPForConsole(&tenant) + var minPorts, consolePorts string + for _, p := range minSvc.Spec.Ports { + minPorts = minPorts + strconv.Itoa(int(p.Port)) + "," + } + for _, p := range conSvc.Spec.Ports { + consolePorts = consolePorts + strconv.Itoa(int(p.Port)) + "," + } + fmt.Printf(color.Bold(fmt.Sprintf("\nTenant '%s/%s', total capacity %s\n\n", tenant.Name, tenant.ObjectMeta.Namespace, helpers.TotalCapacity(tenant)))) + fmt.Printf(color.Blue(" Current status: %s \n", tenant.Status.CurrentState)) + fmt.Printf(color.Blue(" MinIO version: %s \n", tenant.Spec.Image)) + fmt.Printf(color.Blue(" MinIO service: %s/ClusterIP (port %s)\n\n", minSvc.Name, strings.TrimSuffix(minPorts, ","))) + fmt.Printf(color.Blue(" Console version: %s \n", tenant.Spec.Console.Image)) + fmt.Printf(color.Blue(" Console service: %s/ClusterIP (port %s)\n\n", conSvc.Name, strings.TrimSuffix(consolePorts, ","))) + if tenant.Spec.KES != nil && tenant.Spec.KES.Image != "" { + fmt.Printf(color.Blue(" KES version: %s \n\n", tenant.Spec.KES.Image)) } - t := table.NewWriter() - t.SetOutputMirror(os.Stdout) - t.AppendHeader(table.Row{"Pool", "Servers", "Volumes Per Server", "Capacity Per Volume", "Version"}) + + t := helpers.GetTable() + t.SetHeader([]string{"Pool", "Servers", "Volumes Per Server", "Capacity Per Volume"}) for i, z := range tenant.Spec.Pools { - t.AppendRow(table.Row{i, z.Servers, z.VolumesPerServer, z.VolumeClaimTemplate.Spec.Resources.Requests.Storage().String()}) + t.Append([]string{strconv.Itoa(i), strconv.Itoa(int(z.Servers)), strconv.Itoa(int(z.VolumesPerServer)), z.VolumeClaimTemplate.Spec.Resources.Requests.Storage().String()}) } - t.AppendFooter(table.Row{"Version", tenant.Spec.Image}) - t.SetAlign([]text.Align{text.AlignRight, text.AlignRight, text.AlignRight, text.AlignRight}) t.Render() - return nil + fmt.Println() } diff --git a/kubectl-minio/cmd/tenant-upgrade.go b/kubectl-minio/cmd/tenant-upgrade.go index 00d5473bd3f..8a0fb8ce9a4 100644 --- a/kubectl-minio/cmd/tenant-upgrade.go +++ b/kubectl-minio/cmd/tenant-upgrade.go @@ -27,6 +27,7 @@ import ( "github.com/minio/kubectl-minio/cmd/helpers" "github.com/minio/kubectl-minio/cmd/resources" + "github.com/minio/minio/pkg/color" miniov1 "github.com/minio/operator/pkg/apis/minio.min.io/v1" operatorv1 "github.com/minio/operator/pkg/client/clientset/versioned" "github.com/spf13/cobra" @@ -38,7 +39,7 @@ import ( const ( upgradeDesc = ` 'upgrade' command upgrades a MinIO tenant to the specified MinIO version` - upgradeExample = ` kubectl minio tenant upgrade --name tenant1 --image minio/minio:RELEASE.2020-11-19T23-48-16Z --namespace tenant1-ns` + upgradeExample = ` kubectl minio tenant upgrade tenant1 --image minio/minio:RELEASE.2020-11-19T23-48-16Z --namespace tenant1-ns` ) type upgradeCmd struct { @@ -52,48 +53,51 @@ func newTenantUpgradeCmd(out io.Writer, errOut io.Writer) *cobra.Command { c := &upgradeCmd{out: out, errOut: errOut} cmd := &cobra.Command{ - Use: "upgrade", + Use: "upgrade --image ", Short: "Upgrade MinIO image for existing tenant", Long: upgradeDesc, RunE: func(cmd *cobra.Command, args []string) error { - if err := c.validate(); err != nil { + if err := c.validate(args); err != nil { return err } - return c.run(args) + return c.run() }, } - + cmd = helpers.DisableHelp(cmd) f := cmd.Flags() - f.StringVar(&c.tenantOpts.Name, "name", "", "name of the MinIO tenant to upgrade") - f.StringVarP(&c.tenantOpts.Image, "image", "i", helpers.DefaultTenantImage, "image to which tenant is to be upgraded") + f.StringVarP(&c.tenantOpts.Image, "image", "i", "", "image to which tenant is to be upgraded") f.StringVarP(&c.tenantOpts.NS, "namespace", "n", helpers.DefaultNamespace, "namespace scope for this request") f.BoolVarP(&c.output, "output", "o", false, "dry run this command and generate requisite yaml") + cmd.MarkFlagRequired("image") return cmd } -func (u *upgradeCmd) validate() error { - if u.tenantOpts.Name == "" { - return errors.New("--name flag is required for tenant upgrade") +func (u *upgradeCmd) validate(args []string) error { + u.tenantOpts.Name = args[0] + if args == nil { + return errors.New("provide the name of the tenant, e.g. 'kubectl minio tenant upgrade tenant1'") + } + if len(args) != 1 { + return errors.New("info command supports a single argument, e.g. 'kubectl minio tenant upgrade tenant1'") + } + if args[0] == "" { + return errors.New("provide the name of the tenant, e.g. 'kubectl minio tenant upgrade tenant1'") } if u.tenantOpts.Image == "" { - return errors.New("--image flag is required for tenant upgrade") + return fmt.Errorf("provide the --image flag, e.g. 'kubectl minio tenant upgrade tenant1 --image %s'", helpers.DefaultTenantImage) } return nil } // run initializes local config and installs MinIO Operator to Kubernetes cluster. -func (u *upgradeCmd) run(args []string) error { +func (u *upgradeCmd) run() error { // Create operator client client, err := helpers.GetKubeOperatorClient() if err != nil { return err } - t, err := client.MinioV1().Tenants(u.tenantOpts.NS).Get(context.Background(), u.tenantOpts.Name, v1.GetOptions{}) - if err != nil { - return err - } imageSplits := strings.Split(u.tenantOpts.Image, ":") if len(imageSplits) == 1 { return fmt.Errorf("MinIO operator does not allow images without RELEASE tags") @@ -104,16 +108,18 @@ func (u *upgradeCmd) run(args []string) error { return fmt.Errorf("Unsupported release tag, unable to apply requested update %w", err) } + t, err := client.MinioV1().Tenants(u.tenantOpts.NS).Get(context.Background(), u.tenantOpts.Name, v1.GetOptions{}) + if err != nil { + return err + } currentImageSplits := strings.Split(t.Spec.Image, ":") if len(currentImageSplits) == 1 { return fmt.Errorf("MinIO operator already deployed container with RELEASE tags, update not allowed please manually fix this using 'kubectl patch --help'") } - current, err := miniov1.ReleaseTagToReleaseTime(currentImageSplits[1]) if err != nil { return fmt.Errorf("Unsupported release tag on current image, non-disruptive update not allowed %w", err) } - // Verify if the new release tag is latest, if its not latest refuse to apply the new config. if latest.Before(current) { return fmt.Errorf("Refusing to downgrade the tenant %s to version %s, from %s", @@ -127,7 +133,7 @@ func (u *upgradeCmd) run(args []string) error { } if !u.output { - return upgradeTenant(client, t) + return u.upgradeTenant(client, t, t.Spec.Image, u.tenantOpts.Image) } o, err := yaml.Marshal(&t) @@ -138,10 +144,14 @@ func (u *upgradeCmd) run(args []string) error { return nil } -func upgradeTenant(client *operatorv1.Clientset, t *miniov1.Tenant) error { - if _, err := client.MinioV1().Tenants(t.Namespace).Update(context.Background(), t, v1.UpdateOptions{}); err != nil { - return err +func (u *upgradeCmd) upgradeTenant(client *operatorv1.Clientset, t *miniov1.Tenant, c, p string) error { + if helpers.Ask(fmt.Sprintf("Upgrade is a one way process. Are you sure to upgrade Tenant '%s/%s' from version %s to %s?", t.ObjectMeta.Name, t.ObjectMeta.Namespace, c, p)) { + fmt.Printf(color.Bold(fmt.Sprintf("\nUpgrading Tenant '%s/%s'\n\n", t.ObjectMeta.Name, t.ObjectMeta.Namespace))) + if _, err := client.MinioV1().Tenants(t.Namespace).Update(context.Background(), t, v1.UpdateOptions{}); err != nil { + return err + } + } else { + fmt.Printf(color.Bold(fmt.Sprintf("\nAborting Tenant upgrade\n\n"))) } - fmt.Printf("Upgrading MinIO Tenant %s to MinIO Image %s\n", t.ObjectMeta.Name, t.Spec.Image) return nil } diff --git a/kubectl-minio/cmd/tenant.go b/kubectl-minio/cmd/tenant.go index 3092894b76d..bf334120108 100644 --- a/kubectl-minio/cmd/tenant.go +++ b/kubectl-minio/cmd/tenant.go @@ -37,7 +37,7 @@ const ( func newTenantCmd(out io.Writer, errOut io.Writer) *cobra.Command { cmd := &cobra.Command{ Use: "tenant", - Short: "Manage MinIO tenant", + Short: "Manage MinIO tenant(s)", Long: tenantDesc, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { client, err := helpers.GetKubeExtensionClient() @@ -54,10 +54,10 @@ func newTenantCmd(out io.Writer, errOut io.Writer) *cobra.Command { return nil }, } - + cmd = helpers.DisableHelp(cmd) cmd.AddCommand(newTenantCreateCmd(cmd.OutOrStdout(), cmd.ErrOrStderr())) - cmd.AddCommand(newTenantExpandCmd(cmd.OutOrStdout(), cmd.ErrOrStderr())) cmd.AddCommand(newTenantInfoCmd(cmd.OutOrStdout(), cmd.ErrOrStderr())) + cmd.AddCommand(newTenantExpandCmd(cmd.OutOrStdout(), cmd.ErrOrStderr())) cmd.AddCommand(newTenantUpgradeCmd(cmd.OutOrStdout(), cmd.ErrOrStderr())) cmd.AddCommand(newTenantDeleteCmd(cmd.OutOrStdout(), cmd.ErrOrStderr())) diff --git a/kubectl-minio/go.mod b/kubectl-minio/go.mod index 7bf8c08a9d3..b72ab7f77ca 100644 --- a/kubectl-minio/go.mod +++ b/kubectl-minio/go.mod @@ -6,6 +6,8 @@ replace github.com/minio/operator => ../ require ( github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect + github.com/briandowns/spinner v1.12.0 + github.com/dustin/go-humanize v1.0.0 github.com/go-openapi/errors v0.19.6 // indirect github.com/go-openapi/strfmt v0.19.5 // indirect github.com/golang/protobuf v1.4.2 // indirect @@ -13,11 +15,13 @@ require ( github.com/googleapis/gnostic v0.4.0 // indirect github.com/imdario/mergo v0.3.10 // indirect github.com/jedib0t/go-pretty v4.3.0+incompatible + github.com/manifoldco/promptui v0.8.0 github.com/mattn/go-runewidth v0.0.9 // indirect github.com/minio/minio v0.0.0-20201203193910-919441d9c4d2 github.com/minio/operator v0.3.23 github.com/mitchellh/mapstructure v1.3.3 // indirect github.com/montanaflynn/stats v0.6.3 // indirect + github.com/olekukonko/tablewriter v0.0.4 github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/secure-io/sio-go v0.3.1 // indirect diff --git a/kubectl-minio/go.sum b/kubectl-minio/go.sum index a7c87ed11a0..78d424fc431 100644 --- a/kubectl-minio/go.sum +++ b/kubectl-minio/go.sum @@ -168,6 +168,8 @@ github.com/bombsimon/wsl/v2 v2.0.0/go.mod h1:mf25kr/SqFEPhhcxW1+7pxzGlW+hIl/hYTK github.com/bombsimon/wsl/v2 v2.2.0/go.mod h1:Azh8c3XGEJl9LyX0/sFC+CKMc7Ssgua0g+6abzXN4Pg= github.com/bombsimon/wsl/v3 v3.0.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/briandowns/spinner v1.12.0 h1:72O0PzqGJb6G3KgrcIOtL/JAGGZ5ptOMCn9cUHmqsmw= +github.com/briandowns/spinner v1.12.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw= github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo= github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A= @@ -178,6 +180,7 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cheggaaa/pb v1.0.28/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= @@ -625,6 +628,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= +github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= @@ -670,6 +675,8 @@ github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw= +github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -682,6 +689,8 @@ github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8= github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo= +github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= @@ -709,6 +718,7 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= @@ -813,7 +823,10 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA github.com/nsqio/go-nsq v1.0.7/go.mod h1:XP5zaUs3pqf+Q71EqUJs3HYfBIqfK6G83WQMdNN+Ito= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5 h1:58+kh9C6jJVXYjt8IE48G2eWl6BjwU5Gj0gqY84fy78= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= +github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/olivere/elastic/v7 v7.0.12/go.mod h1:14rWX28Pnh3qCKYRVnSGXWLf9MbLonYS/4FDCY3LAPo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1204,6 +1217,7 @@ golang.org/x/sys v0.0.0-20181021155630-eda9bb28ed51/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/kubectl-minio/statik/statik.go b/kubectl-minio/statik/statik.go index 82cf324c0e4..f6a6487daba 100644 --- a/kubectl-minio/statik/statik.go +++ b/kubectl-minio/statik/statik.go @@ -8,7 +8,7 @@ import ( func init() { - data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x85\x93\xf9P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00 \x00cluster-role-binding.yamlUT\x05\x00\x01\xbay\x1c_|\x8d\xbdN\xc50\x0cF\xf7<\x85_\xa0El(\x1b0\xb0\x17\x89\xddM\\0M\xed\xc8q:\xf0\xf4\xa8Ru\x97\xfb3\x7f\xe7;\x07+\x7f\x915V\x89`3\xa6\x11\xbb\xff\xa8\xf1\x1f:\xab\x8c\xebK\x1bY\x9f\xf6\xe7\xb0\xb2\xe4\x08\xef\xa57'\x9b\xb4\xd0\x1bKf\xf9\x0e\x1b9ft\x8c\x01@p\xa3\x08\x1b\x0b\xeb\xa0\x95\x0c]m\x98O\xd0\xb4\xd0D\xcb\xc1a\xe5\x0f\xd3^\x1f4\x03\xc0U\xf2^\xe10\x87\xd6\xe7_J\xde\x0e\xffp~?\xc9vN\xf4\x9a\x92v\xf1\x00p[p\x19Z\xc5D\x112-\xd8\x8b\x87\xff\x00\x00\x00\xff\xffPK\x07\x08$\xaf\xb0M\xa2\x00\x00\x00\x1d\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00E\x96\"Q\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00 \x00cluster-role.yamlUT\x05\x00\x01c\xe9O_\xcc\x941\x8f\xdb0\x0c\x85\xf7\xfc\n#c\x01'\xe8Vd\xed\xd0\xadC\x87\xee\xb4\xfc.\xc7F\x16U\x8a\xf2\xe1\xfa\xeb\x0b%\x07\x9fl\xd8i\xda\xa9\x99D\xf1E~\xdf\xa3e\x8a\xfc\x1d\x9aX\xc2\xa9\xd1\x8e\xdc\x81\xb2=\x8b\xf2/2\x96p\xb8|J\x07\x96\xe3\xf8qw\xe1\xd0\x9f\x9a\xcf>'\x83~\x13\x8f\xdd\x00\xa3\x9e\x8cN\xbb\xa6 4\xe0\xd4\x0c\x1cXZ\x89P2\xd1V\x8bJ\xb3G*\x92\xb6\xa1\xc8_Tr\xbc\x96\xe5\xd76\xfb\xfdu\xa9H\x92\xd5\xa1\xea\xc4\xe2*\x19\x82\x8d\xe2\xf3\x00\xe7\x89\x87tm\x8f\xd0\xaeR\x9ea\xd3:\xc7\x9e\x0cS\xe99\xd9\xdf?\xba\xc0\xa4H\x0ei\xdaJp\n{\xaf\xa3\xf4uSG\xae\xd5\x18\x11\xec\x8f^_\xc8\xdc\xf3T9\xc5\x8a\xf3[\xd1\xc3\xa3\xea\xddJ'\xde\xc3\x95)m\x11R\x8ci\x8b1\x19\x19\x9e\xb2O5U\x8f\xe8\xe5ux\xc4\xfc=\xbbq\x066\xc7\\\x0ch\"[\x05\xe8\xa6\xbf\xae\x10\xfc\x90\xee\xffp\xb9wP\xe3'vdHo7f\xf3\xdd\x9a\x89\xf9\x1c8\x9c\x15?3\x92\xa5\xfd#\xa2#\xc5\xa82\x92\x7fL]\xc6\x9c\xdfN^\xe4\xb4`\\DU\xa7x\x1f\x7f\x85~\x06\xff\xb5\xdc\xa6w\xf9%w\xd0\x80\"f9z\x9c\xc9\xbd\xb69\\\x82\xbc\x84\xad\xd0\n\x15tu\xda\xb780\x93n9\xbd~\x9e\x0e\x03\x87\xa5\xc5z>\x1fV\xc3\xbamo\x9d\xfao\xe7\xfd\x0e\x00\x00\xff\xffPK\x07\x08\xe2\xbc\xc6/u\x01\x00\x00{\x05\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\xc2\xb0\x83Q\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00 \x00crds/minio.min.io_tenants.yamlUT\x05\x00\x01Ma\xc9_\xec}\xfds\xe36\x92\xe8\xef\xf9+\xba&\xa9\x1a{c\xc9\xc9\xe5\xd5\xab;\xdf\xd6\xa6\xbc\x9eI\x9e\xdf|\xb9\xc6\xb3sU/\x9b\xbb\x85HH\xc2\x99\x04\xb8\x00(\x8f\xf6r\xff\xfb+4\x00~H$\x01\xc8vvr+\xfc0cId\xb3\xd1\xddh\xf4'\xf8\xc5l6\xfb\x82T\xec#\x95\x8a ~\x01\xa4b\xf4\x93\xa6\xdc|R\xf3\xbb\x7fVs&\xce7\xdf.\xa8&\xdf~q\xc7x~\x01W\xb5\xd2\xa2|O\x95\xa8eF_\xd0%\xe3L3\xc1\xbf(\xa9&9\xd1\xe4\xe2\x0b\x00\xc2\xb9\xd0\xc4|\xad\xccG\x80Lp-EQP9[Q>\xbf\xab\x17tQ\xb3\"\xa7\x12\x9f\xe0\x9f\xbf\xf9f\xfe\xdd\xfc\x9b/\x002I\xf1\xf6\x0f\xac\xa4J\x93\xb2\xba\x00^\x17\xc5\x17\x00\x9c\x94\xf4\x024\xe5\x84k5/\x19g\xc2\xfc;g\xe2\x0bU\xd1\x0c\x9f\x9e\xe7\x88\x12)n$\xe3\x9a\xca+Q\xd4\xa5Ee\x06\xff\xf7\xf6\xdd\xdb\x1b\xa2\xd7\x170W\x9a\xe8Z\xcd\xb3ZJ\xca\xf5\xad&\x9a\"\xb6\xf6\x19\xedg\xbd\xad\xe8\x05(-\x19_\xed\xc2\xf0\xd3\x9e\xef\xa1\xdc\x01u\xb9\xea\x02\xca-\xdc\x95\x14uu\x01\xbd)\xd8\x1b\x1c\xd1,\xc1?\xe0T\xf1\x8b\x82)\xfd\xaa\xf3\xe5k\xa6\xec\x0fUQKR4d\xc1\xef\xd4ZH\xfd\xb6\x856s\xbf\xda\x1f\x19_\xd5\x05\x91\x17\xed\x97*\x13\x069\xbc\xa3\"\x19\xcd\xcdw\xf5B:N;(\x96d\x17\xf0_\xff\xfd\x05\xc0\x86\x14,\xc7I\xdb\x1fEE\xf9\xe5\xcd\xf5\xc7\xefn\xb35-\x89\xfd\x12 \xa7*\x93\xac\xc2\xeb\x1c\xe6\xc0\x14\x100\x0ccK\x96!\x08X\n \x04\xde0~\xfd\x0e\xfcS\x1d\x84J\x8a\x8aJ\xcd<\x16ft\xe4\xb6\xf9n\xe7Y\xcf\x0d2\xf6\x1a\xc8\x8d\xa4R\x05zM\xc1\xc9\x1b\xcdA!\xa2 \x96\xa0\xd7L\x81\xa4\x95\xa4\x8ar+\xbb\x1d\xb0`.!\x1c\xc4\xe2?i\xa6\xe7pK\xa5\x01b\x88\\\x17\xb9\x11\xef\x0d\x95\x1a$\xcd\xc4\x8a\xb3\xbf5\x90\x15h\x81\x8f,\x88\xa6\x8eY~\xa0hrR\x182\xd6\xf4\x0c\x08\xcf\xa1$[\x90\xd4<\x03j\xde\x81\x86\x97\xa89\xbc\x11\x92\x02\xe3Kq\x01k\xad+uq~\xbeb\xda\xaf\xd4L\x94e\xcd\x99\xde\x9e\xe3zc\x8bZ\x0b\xa9\xces\xba\xa1\xc5\xb9b\xab\x19\x91\xd9\x9ai\x9a\xe9Z\xd2sR\xb1\x19\"\xceq\xa1\xce\xcb\xfc\xcb\x86\xd9\xcf;\x98\xeeH\xbf\x1d(\x9b\xa3t7B\xeaX\x8c\xb7Y\xfc[\xf2\x9a\xaf\x0cU\xde\xbf\xbc\xfd\xd0\xf0\x1aY\xd0\xa79R\xbb\xbdM\xb5\x847\x84b|I\xa5e\xdcR\x8a\x12!R\x9eW\x82q\x8d\x1f\xb2\x82Q\xde'\xba\xaa\x17%\xd3\x86\xd3\x7f\xad\xa9\xd2\x86?s\xb8B}\x05\x0b\nue\x16g>\x87k\x0eW\xa4\xa4\xc5\x15Q\xf4\xc9\xc9n(\xacf\x86\xa4a\xc2w\xd5l\xffBK\xad\xe6k#\x80y]P9\xca&\xbb\x14o\xfdu\x86a\x86jfU\xba\xc5\xe8\x16k\x03\xaa\x03ihI\x82Wx\xbdov\x9e\xda<\xcfh\x9a\xde\xb24\xb7\x9au\xd6<\xce,\x1e\xc3\x14\x85\xca\xa8?\xb4h\xae\xf3hV\"W;\xd7\x0d\x92\x10\x90\xfbL\xd2\x9e\x04\xcf\xf0\xf9A\xaa\xba=\xc6\x8f!\x82\x1a\xfa\x8d\xd2rG\xb3\xc1\x04)3*\xf5\x95\xe0K\xb6\x9a$\xe8Us\x19\x90\xa2\x10\xf7\xca\x10L\xa2\xe6QT\x035\"I\x15\x14\xec\x8e\xc2\x95(K\xc1\x0d\xe5\xcf\xf6(\xfaN\xae\x08g\x7fC\xd5w\x06T[\xc4q\x1d\x19\xecPO\xd3\x9d\xbb\xc6P\x07\xdc\xf3\xfd\xb3\xf6\x7f\x1b\xe5\x8c\x1d9W\x9d\x9d\xab?\x98\xa6\xe5\xe0\x0f\x01\x98\xfeg\"%\xd9\xee\xfd*:\x93\x1fC\xf9)\x9e<(d`-&%\x8a\xe9\xa5te\xaf\xb1\xcc\xaf\xa5\xddF\x8d6\x14\xd2\xb0\x1e\xd5l]Y\x0b\xe3\xdc\x014?\xeea\xb8\x92\xa4Z\xb3\x8c\x14(:vgZ\x92,\x85\xdb{&\xdf\xce\xcf\x1d\x9bl\x1c\x08\x84I\xd9#\xc0\xf5\xd2\xe0\xb4a9\xcd\xcf\x0c\xeaFZ\x15\xed\xe2\x82\xb4pt\x82w\xfbd\xf6\xe3\x0d\xd5\xa4{\xdf(\x13\x07X\x05-\xbbni&\xa9\x1e\x9aX_Q\x98=K\xe1\xb5~\x02\xca,^\xa0|\xc3\xa4\xe0%\xe5\x1a6D2\xb2(\xa8\x1ad\x99\x19\xaf^\xdeZP\xb8\xd5\x96\x84\xe7D\x0b\xb9\x85%\xa3\xc5\xbe\xc6\x9c\xe6\x1f\x8c\xe8n?\xfa\x1b\xfc[\xa7\xaa\x8dv\x90tI\x8d\xfd<\xb8M\x1aK_r\xaa)\xee\x94\xb9\xc8\x94\x11\xc4\x8cVZ\x9d\x8b\x0d\x95\x1bF\xef\xcf\xef\x85\xbcc|5\xbbgz=\xb3\x04V\xe7h\x08\x9f\x7f\x89\xff\x8d\xe0\x04\xf0\xe1\xdd\x8bw\x17p\x99\xe7 \xf4\x9aJ#\x03\xcb\xba\xb0\x04P\xf3\x8e\x8dx\x86\x16\xcb\x19\xd4,\xff\xfe\xf9\x08\xb8\xa8E<\xc2\x7f\xca7A\xae\x8fH\xeb(\xcf\xbd\xdc\x0e\xa2;\xb0\x8f\xf81\xa1\xa7z\xf8\xbc\xe4\x9b\x8fDv\xcc+c\xe1\x0ea\x03\xee\x82\x11\xba1\x0e\xc4\xe0\xaa \xe3T\xce\x07\xaf\n\x89\xde\xb4\xf0\xed \xde\x95\xbe!|\xe7\xf0\xa6Vh\xcf\x11\xb8\xfa\x8f\xeb\x17/\xdf~\xb8\xfe\xe1\xfa\xe5\xfba\xd4 \xccz3\xd0\x84\x8dD\xf0\xf9GO9\xb782\xaa\xe0\xab\x93\x8f\x97\xef\xff\xe3\xed\xe5\x9b\x97\xa7@$\x05\xfa\xa9\"<\x1f0m\xdaQ+o)W\x92n\x98\xa8\x953\x98\xf2\x11\xa9a\xdc\\=\x011\xf3lBw\x83\xf0-(\xb3\x08\xb3\x111\x9c\x1b\xa1%\xcd\xe7)\xc0\x8d\x0dm$\xb3\xd8\x18\x19\xefh\x87\x8c:\xdc\x80\xf1\xaa\xd6\xde/\xb8g\xe8\xd4\x8f\x0dc\xfc\xf1lM\xf8\xca\xd8\xe4\x1f\xd6\xb4GD\xb5\xe5\x9a|2O6\x17R\x95\x91\x8a\xe6`\x94\xc8\x04H\x02\xb9\xa8\x0dg\xbe\xfa\xea\x0c\x18\xbd\x80\xaf: \xe7\xf0\xd2A\xe9\xf0\xcd\xe0\x08\x9cn\xe8\xb0\x12\xb6c\xd1\xf2\xf3\x0c$]\x11\x99\x17T)#\xa5\xf7k\x8a\xba =O/\x17\xf4\x133\xde\xc7\x88b\xb7\x83\x0b=\x87\x17tI\xea\x02\x1d\x15x\xf6l>\xa6\xbb\xe2E\xf8\x07)\xcaH1\xbe\xb5~\x997\x03\x87$\xe4\xb9\xb2P\xc7\x97\x16t\xdd+Es`K\xe7\x0e2e\xa6\x08\xb4\xac\xf4v\xfc\xfe\xb0\xe6\x00+\xd7K\xb6zC\xaaWt\xfb\x9e.\xa7.\xdd\x9d$-\xcc~\x03\x04\xee\xe8\x16\xdd|\xb8\xf2\xc0\xa6f\x15\x8b\x99\x19wt\x1b\xbad\xcfB\xa0\x88\x0f\x1a\xf1\x06\xc1iT N\x00\xfc\x98\xd6\xb5~|\x9e[~;R7\xff\x08\x90S\xe6A;\x12(-*k\xf5&R\xfb\x16#c\xdb\x9e\xeeh\xa4\x12\x84\x04\xa6c(d$\xa8t[\xa1\xdb8\x82w\xd9\xc9-\x84((\xe1\x93W\x0fy\xd1\xfbcf\xb0\x98\xbcb\xd2\xb0j\x07\xf25mm?o\x177\xde\xed\xe5\xb7\x12\xf9\x05\xa8\xba\xaa\x84\xd4\xaa \xa9\xcc\xf9\xa0_\xdc\x1f\xbd\x8b1Pz\xd6~W\x90\x05-T\xe7\x8b\x8eG\x11\x02\xac*\x9a\xcd\xb9\xc8)z\xe7\xf6\xa3\xdb\x9b/\xb3L\xd4\\\xbb\x1fl\xd0z-\x94\xbe\xbe \x02\xb5\x17W\"\xbf\xbe9\xeb}R\x13[ $)\xb7\xe1@\xec\xf0\xe8q\xc7\x87f\x1dS\\,\xd6\xfc\xf9\x83a\xd6\x0d\xd1k`1b~/\x99\xd6\x94\xa3\x85Aeiv\xdd3#\xef\xed\xc6\xb9\xf9\xf6\xd9\xa3*\xd0\xa5G0q\xca8'7_+\x91\x8d\x82\xf7\xf6\x91\x0b\x8aG\xacT\x80\xcb\x9bk\x1f\xcc~\xc4\xe9\xc5\xae\xeb\x86\x08\x8f\xb1\xba\xbd?\xf3\xc3\x83Vy\x13Kv4n\xcc\xdd\x0b\x10\xbc\x98VC-\x0e\n\n\x86Qbc#7\x91\xe2\x13\xfb\xe5<\xab\xea3w\xc1\xbc\xa4\xa5\x90\xdb\xd0*t\x17\xd3jMK*I1SZH\xb2\xa2g\x0dp\x0b\xb4\xf9d\xc1\x86\xd6]\x07\xb9}\xd8\xd6\xc7p\xa9\xadb\xeb\xb5\x1d\xcd\x1fm\xdd7\xb4\x1d\x8b\x97\xf5G\x9fe\x8d\xbb\xe82d^\xe6\xd0\xd8\xdc\x88\xa2.iPcBg\x7f\xc5\xfb(\xdf\x18\xc3T=\xea\x0e\x9e\xb3\x0dSB\x86'H\xf8\xf6]@l\xc1\xe6\xe1\xf0\xe1\x8ck\xba\x9a\xf4)\xfa\xd7G!;hF0\x17_\x17\xb56\xae\xd7R\xc8\x92\xe8\xc6\x7f\xfeT\x89\xa1\xf8\xfa\xfehV\xc7\x8en\xfd\xf6Y\xf0\xe6\x8ahM%\xbf\x80\x7f?\xf9\xf3\xd7\xbf\xccN\xbf?9\xf9\xe9\x9b\xd9\xbf\xfc\xfc\xf5\xc9\x9f\xe7\xf8\xc7\xefN\xbf?\xfd\xc5\x7f\xf8\xfa\xf4\xf4\xe4\xe4\xa7Wo~\xfcp\xf3\xf2gv\xfa\xcbO\xbc.\xef\xec\xa7_N~\xa2/\x7f\x8e\x04rz\xfa\xfdWA\xd4>\xcdZ{u\xc6\xb8\x9e 9\xb3\xa4\xbe\x00-\xeb)\x97\x17:D \xf3\xbd/\xff\xef\xbd\x8e\xed\xa4\xbf\xfcN\xf0\x88\xe2\x1b\xab\xca'\xa2I\xed\x88\xd4\xe46\xae\xf9\x18~\x98\x8b\x90\xba\x8d\xb1\x12\xf9s\x05\x8d\xd9\xf5HZ\xecp\xd7\xcc\x9b-\x16\xc9v\x1f_JQ\xce\x01CPA\xc0`\x83T\x98H\xf7\x90\xee\xe8\x847\xecG\xb4\x04\x1c\x9d\xbd\xd1\xf19;{6\x91\xe0<\xbd\xa0\x07e\xc7\xff\x10O/x\xd146{y\xdcv\x04 O\xe5\x07\xe9'[\xacqE\xae\xa8\xd4\x91i\x9e\x97\x037\xf9\x1c-\xb1\xa96-|N\xa0\x93\"\x1bD\xfe\xea\xb2\x9b\x87U\xf3&\xf3\x83A\xb5n\x9aK\x0b\xe3\x14\x18\x89\xfa\xf0\xfa\xd6\x98i\x9cfcI-\xc0x\xa9[S\xa4\xaa\nW\x8d\xa3\x86TPlb\xe1\xb5\xc8Hq\xd5\"\xfb\xbe\x89\x01w\xd3\xfdmn|D\x14\n\x03f\"\xf9lGX\xd5O+\xc0\x88\xf5\x8d\x97\x1c\x0e\xe0\xef*\xaf\x07Hk\x8c\xac\xf2\xe6 \x83\x98w\x98\x86~J%\xd9\xc6\xfcm\xf6\xb6}\xc1\xa5\x9c,\n\xc6W(\xafbX\x15y\xe16\xd0\xd6D\x19\x88B2\xbd\x05\xb3\xcb\xc0e\xad\x85\xc1{HjC\x022%\x1eA\xdeN\x89F\xe0\xe6)\xb1\x18\x15\x8aI\x91`%Y\x0db\xd3OC\x9a\xabz+\xd1\x95\xa6x\x12\xbf\x10\xd9\x1d\x95\x16\xda\x10A'\xe7\x85w\xdd\xd4Eq#\n\x96\x0d\xdaV\x03\xd8TuQ@\x85w\xcc\xe1\x1dG\xdb\xe3\xb2\xb8'[u\x06o\xe9\x86\xca3\xb8^\xbe\x15\xfa\xc6&\"\x87\xed\xa3&\x15n\xd4\x18\xc5\xd0\x8a\xad&\xf4\x13\xabD\xae0\x0e0\x07TI\xf0\xaa\xb1^ \x17Y]\x0eV\xfe\xf9a$5\xa7\x9a\xb0BE\x99?\x8d\x7f\xac\xce\x91(\xeaK\xac.3\x86\x90\xfd\x9cJZ\x1b]\x1c\xa2\xe8\xafZ]a\xd1\x18(\xac\xc0\"\x8a\xc1\xa7\xda[R\xc5\x99\x8b\x9cZ\xaf`\xd8\xfd\xfeUg\xddE&\xa9\xa8\xa4{c*\x05$\xc5\x0dypV=\xa4\xdf\xbb\x0b\x9be\xcd\xebrA\xa5YF(\xf4\x06\xe1W/omM\xf3\xb2.n\xe9\xe0\x1a\xb2\xa1\x01\x8cM|\xf7O\xa3\xc8\x8eE.vJ\x85\xfb#\x86\xc6M\xa8\xcd(y\x0c\x9a!\xe2YU\x9fOD\xc4\x1a\x07\xda\xecV\xd9\xd8\xfa\x0d\xed\x026F7\xa6\xca\xe3E\x0d\xc2\x91\xa0\xd8\x08Pd\xe4\xe73\x0c\xae\x1c\x18T\xe9\xfb\xa0\xafm\x0c\xd6~\xb9p[UI>\xb1\xb2.\x81\x94\xa2\xe6\x18\xc4\xcaDY\xd5#\xb6!\xf4\x82\xbah\xcd\xd0<\xd9\x8f\xcd\xba\xf5u\xe7%\xe1dEg\xee\xb1\xb3\x06\xfc\xac\xd1\xf7\xe7\xd3\x05F\x01\xcf\xc6,\x80\xa3\x18~>b\xf8\xde+\xa5\x1dAd\xfc`A\xf4\x96\x1fV\xd74\xf0\x99\x02Q2\xad\x9dQL\xda\x00\xfbx0\x83\xe9^,\xd6-\x19\xb6\x04\xbd&\xd8dA?\x99\x8d\x81a\x06\xc0'\x96\xce\xac\xbbw\xcf\xd48\xb2Z\x18\x1b\x9f\x95UA\x1b\xabh\xe6k\x8fl\xc5\xc7\xe7\xba\x8c&\x7f\xde\xcf\xa8\x067\xab\xdb\xbd[|u7\xefD\xc9\xfaW\x0db\xae\x85\xdd\xeb\x04\xc8\x9a;ct\x89e\x9f\xde\x96\xb81\xdfa#\x11\xcd\x81\x18\xc7\xab\"R\xfb\xf6\x94A\xa0\xd6vO4\xd3\xc7\\\x8fY\xbf\x8eu\xe7\xd7Q\xc2f\x92\xe6j\xd8\xcb\x0cm\xfbm\x1d,\xb145\xb0(\xd7\x8c8\x13\xb3\xd3\xfe\xd4\x1d\xcd\xa6\xff\xce\x8b\xb2\xb3\xf5\x156\x888\"*\xc8\xb7\x9c\x94,\xeb\x81\xad\xb0+l?>&x\x1f\x86\xd2D\xea\xba\x82\x05\xe1|O?N\xd9\x13c\x1e\xe5\xe7\x17cM\x8d\xaa\x8e\xc6L'\x84mTl\x06jfC\xe22]/\x1b\x90\x95\x9d\x1fF\xa2Y\xfd\x98Hj\x89,\xb0!\xe3s\xb2k\xa2\xca>\x9b\x1d, \xd6\xf1%\x9fQr\x1dY\xea\x19Q\xe6\x19\x1bY\x85\xf8\xe8*\x0co\xd9\x8fP\xday`Y\xe7g\x18\xee\x85\xc3C\xbe\x10]\xca\xb9\x1f\x1c>\xac\x8c3\x8a\xeb1\xaa6X\xba\x19\xa1i\xe3J6C\xde\xc7a\xe5\x9aq\x1a\xe70\x87\xe4\xe1%\x9a\x07\x94gFq\xf6\xe8\xde\xec\x8dH\xba=\x92{\xb3W`\x89\xdeKX\x1a~C\xbeM\xa0\xb4`\xec\xe9#\xb5G\x13\xd0\xecO\xfb\x85h1E\x93\xfdp\xebc\x15L\x86\x8b%m\xa4?\xbeT2\xb2L2&\xa8\x9cZ\x1ei\x0b!\x07Xu\xc5l\x98|\x11\xcb\xf1\xba\x7fm_!6\x8e\x83\xcf\xfb\x98)U\xf5\xc0\xa15\xf8H{\x0e%i\x96\xdf\x14\xef\x0fY\x1c\x9f\x9fG\xf0h~\xc0\xc4\x12\x1e]\x95w\xfb\xb4\xebQ\xc8h\xa8\xb1\xe3\xf0\xee\xccN\xad\x9c\x88\xbfzs\x9b\xc0\x9d\xcf\xf9\xa8;3\xe5P5\xf6C\x8e\xb9\x0blt\xb0\x8bv\xfc&G\xc6\xb693\xa4\x10;\xbb\xdc\xfe\xce\x87\x1b\x9f\xfbzo\xff\x1b\x84:\xba'\xee\xed\x81\x86\xac\xbb\x9b\xdf0m{\x1b\"\x90\x15a\\i\xf8H\xea\x02\x9dM\xbbJ^\xbd\xb9\xb5\x15zm\xc2\xe8\xc3\xeb\xdb\x7f\xec\xe6\x95\xb0\xf9\x0e\x87\x98\xf0\x01\x1b\n\xf6\x9c\xc5=\x03\n\xf9\x8d\x87u\xfbz|d\xed\xed\xed\xeb\x7fl\x86=\xb0\xdb\xc8,\xa9\xffA\x9dFf:\x87[J\xf0+XK\x10\"\xe8\x1d\x1d)\xe2\x84\xfd\xf8*S\xed\xe5\xd6/UM\x05g\xef8\xda)ey<\xbb\xf4QL'\x0816\xb0\x90?\xbf\xbe\xb2\x1d+\xe6\x7fd\xffX;\xc7\xc1G\xfe\x83\xf5\x8e}\x9eu\xf9f\xda\xd35\xf9\x8f]\x7f\xdf(\xd5\x9d_FY]\x88\xe9\xd3\xe1_\x8b\x95;\x1c\xde\xb3\xb7\xaf\x9f+\"II5\x95\x96\xd1\xaf\xc5\n\x96\x94\xe8z/\xd29\xe9\x11\xd59\x0b\xef\x1a\x97\xe6*\x87\xccZ\x14\xf9.*h\x86\x9bk\xcc\xa4\xec;\x1d\x86\x97\x86\xf1\xd9\x06~ m\x119SwW\xa4\"\x19\xd3\xdb\x1f\xff\x18\xb5Y\xbc\xe8\xdd\xd23c\x0c4\xc8\xdco\xc08\xfc\xf8\xc7\x11\x88\x00dCX\x81\x85\xb0\xc6\"\xd5f\xabi':r\xd7\xf4zy\"\xdb\xcc\xbe\x0d\xe6\xb92rpK\x89\xcc\xd6\x977\xd7\x9dC\x83\x0f\xb1\xd4F\x11\xc5\xce\xa9\xa1\xaa\xa8\x1e\x92o\xb0\xbf\xaa\"z\xdd\xc9\xdb\xd8R\x118\xb9\xf9x\xda\xaf&>\xa7\x9f\x8cC5\x88\xc2\x00v\x95\xc8\xdf`#\x921\xcd\"bm7\"\x87\xf6\x06\xb0w\xd8\xa0\x90\xc8\x1b-\xb1\xd8v\x95e<.b\x7f\x17\xeeKc\xf3\xb6%|\xe4UQ+\x8d\xc7\xf5\xc3\x8am\xa8\x8f\xd4f\xf6\xeb\x1d@1Y\x82\x1b!\x8a\xb1\x84\x80\x8f\x02\x8b\xfd\xd0\xd7\xf4\xba#KDz$}\xbf\xbbuv\x9a\xd4\xfc\x8d\xb6\x1a\xdd\xa2\xd5\xa9,po\xff\x18O\x16g\x82+- \xe3#G\xa5\x86\xd4\x855 .'\xd1\x87}\x16)\xd7$hnn\xe7\xd0b\x0b\xb2\x9e:\xd3\xdf\x0e7\xcd\x87\x96qWh\xdfJ\x9a\xbf\xa8\x8d\xb8\xdd6H\\\xaf\xb8h\xbe~\xf9\x89f5\xa2?\x01j\xcf\x03\xa0\x9d\xf7\xb4 \x87\xec\xc3\xa0\xfbb\x96\x817\xb2\xec\x0e-\x90R\xca\xc5C\x88fj\xb9\xc5\xf97\xb4\xa3\x9f*I\x15\xbe\x93,\xba\xe4q\xb1u/\x062\xd6\xf4\x19,j\x0dL\xe3[\x83\xb2\xb5\x10\x8a\x825\xae\xecS7L\xe0\xfb\x99\x020;Y\xc0N\x89\x95G\xcd\x9eO\xde\x02e\nJ\x11\xac(h8\xe4m\x17\xf3\x10\xcc5\x9b\x0f+\xdb\xc5\xa6A\xd5%\xf6VP\xb6Z\xeb\xe0\xc1\x88lN\xe76\xcfH\xb2u\x07\xa5\x92Rm\xdf3\xd1\xa9\x9b\x9d\\C~8\x83\xa5\xc4\x16\xa8\x93\xa6\xd6\xc9U%\x9e5\x06\xcd\xae\x9c\x05\xc0\x0e\xb1\x18_=3?=\xf3\xfd\xb4@p\xf6\x8b\xadQa\x12\xfd\xdb\x90H\xad\xa5\xa8W\x96\x82\xb4pH{{\xcd\x96\xd2b\xf7\x8f\x8d\xf8=\xb3D\x0d\x1db\xe8\xde\xe3ePa\x96xH\xd7\x92\xe8lM\xbd\xe3+%U\x95\xe0\x08\x17\x7fy\xd9\xce\xeb_C\x0fp O\xd4i+\x00k\xb6Z{\xfe\x13i\xd5\x9f\x91\xaaVn\xa6k\x91&NljG\xdfH\xe3\xb6\x97\xa5#\x99\x1d\xdd\xa5\xa9,\xfd\x9c\x03P\xc1\n\x9a\xf5\x88\xed\x8cXi\x9b\x91\x9d\x1c\xc37p\x82\xa2\xca\x8c\xc5a\x16\xe4LT\xa7\xe1\xb3\xef.\xf1]\x80a\x04\x81\x0b\xff\xfc L\x87\x88Y\x1dJD\xe3\x12\xa7\x85\xfd\xb5>\xe7\x1e\xbev\x97'V\xd6\x94w\x1f\xcd$\xcf\x80(%2\x86\x06G\xe0\x9d\x07\xed\xd8\x17S\xcb\x8a\xd0D!q\xb2f\xec.\x80\xb8\xbb\xf6\xa6^0\x85\xdeV\x9f\x04]\x85\x14 \x177\x05\x03\xe5\xb9r\x01\x85\x98YC\xec*j\xc7$\xef:\x88\xc7\x1dn\xed\x07\xe9\xf0\xdf(sg\x94\xbb\xb65uf+1C[Cw\xd8\x16H0\\%\x0dXIq+DI\xb9\xa3X|\x9e\x00\xd2\xbd\xa70\xfa\x8eT\x99\xb2#X\x0c\xba;\xf6L\x17\xe4\xbf\xedY3\x93\xb6\xb9\xde\xd18\xcb\xd4\xb0!`|\x8f`\xd2\x9d\xc1X\xff\xf0\xf0\xccz\xc0\xfc\xdfw\x9a\x99\x0d \x9e+\xcbt\xb3F\xd7\xacJ\x02l\x0f\x8a\xc0\xf7\xcc\x89e\xf3\x96\xca\x8fX/\xebQM\x11rpM\x0b\xd7\xfc\x0c\xde\nm\xfe{\x89\xad\xa3g\xf0BP\xf5Vh\xfc\x98Fj\x80\x1f\xb5\xcd\xea\xbcN\xbc\xf3@&Y:<\x80E\x97\xdc\x16\x1b\x19\xa2\xda\xa7'\xaf,;\xae\xad\xa9\xd2,q\xa6\xe0\x9a\x1b#\xd6\x11w\xfaeAC\xc3\xe2\xe1\xd0\xf3\x0d\x7f\\\xf0\x99\xed\x80uOL\x04\xda\xc5\xefe\xd3*\xdc\xe5x\x8a^\x03\xb7\xd1\x0d\xa2\xfaXh\xfe\x88\xe9\xdc\xd7\xfal\xefQ\x89@\x11\xb15\xd9\xa0\xa1\xcb\xf8\xaah\x8c\xd63\xb8_\xb3l\x1dzI\xd2\xd0XP\xfb\x12\xbfJR\x1f\xb6\xe4>\x96\xe4\n\xc2\x0e\xc1\xd5\xbe\"\xb7 \x19\xcd!GS\xdf\xbe\xe2\x95h\xbab\x19\x94T\xaeRiZ\x19+!M\xac\x13\xb7c;\x0e\\\xca\xfe\xc64j\x85K\xbbwG\xf8\xec\xdc\xee\x985\xa2\x18}\xcbd\xb8px\xa4\xce\x1c\x0d>l\xd6\x8b\xe6\xce\xafa\xeb\xb9\x84Z\xe4\x9d\x89\xc2u\xb4\xf5\xa2\xef8\xdaz\x89\xba\xe7h\xeb\x1dm\xbd\x84q\xb4\xf5\x8e\xb6\xde\xd1\xd6\x83\xc3\x97r\xba\xc5\x03\xff\xa0\xb6^\xd2\x03l\x841\x86<=\xbd\xf8o6F\xbc\x13\xe5\xb4F\xa6{+n\x04H\xd8 wv+j>`\x18\xd5\xb5+K\xc2W\x14\xbe\x9d}\xfb\xcd71\x12\x1a\xaav\xd9\x1d\xa1l~w\xc4J\xd4\xac\x13S\x0e^j\xb9\x10\xb8,\x9a\xafq\xe22\x96\x15zp\xf6\xd1muM\xfa\xa8\x97\x9ejR\x84\xb0\x08\xc9r7#$)\x1e\xe4UR\x0dD\xf7R\n\xac\xa4V\xf3W\"\x8fQ\xd0\xeee\xb7>\x0b\x9a\x83\xe0.{d\xa4o>\x89}\x00twn]\xec3Jl\x05\xd3\x8263\x10\xa5\xc1\x98\x8d\xbe\xb6\xdb\x0f\xa7\xdc\xcd\xe4\xa8\xe7\x05\x9c\xd0\xf9j\x0eyM\xddI\xb0XZJO-\x1d\xd4Vi:\\\x9b\xd3\x8e\xd2\x984\x12\xff3\x04\xd1\x12\xcf\x07\xa3\x1b\xcauM\x8ab\x0bt\xc32\xdd\xd0u\xb4\xda\xa7\x1dL\xdb\xac\xfa\xf4\xfa\x8cw3vuA\xf0\x86=\xe3\xda\x1f\xe3;\xe6\xb9\xe2\xb1B1\xea\xe4\x03\xd6\xde\xc8R\xa1\x1c\xbe{\x1f\xca\xebA\xca\xd6\xb8\xeb\xa3\xd6Ea8c\xd3|\xfb\x08G@\x84\x81\x14\x9b\xcd\x7f\xf7V\xa2\xcd2c\xe62\n\xe8\xe5\xdb\x17\xfe=\xdf\x1fD%\n\xb1\xdav\xf9\x83Z\xa7=\x938\xb4V\xec \xa0\xea\x85\xf3Y\x8c\xac\xbd\xddaz\x98\xce)\"e\xc71\xf3u\x8c\x86\x84F\xaaL\xd9q\x8c\x86\x1c\xa3!I\xe3\x18\x0d9FC\x8e\xd1\x90c4$})\xc7:y\xfd\x11\xeb\xbb\xb6\xe3\xb7\x1f\x0d9f\xbe\x8e\xb6\xde\xe48\xdaz\x89\xba\xe7h\xeb\x1dm\xbd\x84q\xb4\xf5\x8e\xb6\xde\xd1\xd6\x83\xc3\x97r\xba\xc5\x03\xff\xa0\xb6^\xd2\x03bA\xc7\x11r\xb6\x1f\xb0\x9e\xbc>\n\xd5\x88\x8b*\x91\x1f\xdc\x04W\x89|\xa2\x07\x0e\x93\x0c\x13s\xc8\xc4\x0c\xdf\xe8\xe9^\x14f\x80\xf9\x93\xefIi\xb3)g\xf07\xc1\xa9\xed\x192\n@\x89\x91wi\xdbaOZ\xa8D~\xa2N'\xba;\xe2\x0c\xb6cw\xdd\xb1\xbb\xee\xd8]\xf7\x94\xddu\xf8\xa2w\x91+g\"\x8c6\xdb\x85\xc4\xa0\xd5`Fm\xfek\xf3\x80\xa9^\xbb\x10\xc6O\xde\x89g\x04\xde\x89\xa4?\x8f\xc2 \x96\xa5C\xeeJ$h~\xd3\x9f_p_\xb2q\x01tAH\x9e\xd3\x1c**gV\x90\x05,\x19\xcf\x07f\x17\x04\xea\xe8\x19bE\x94fu\xd7\xf6\xa7\x15\xbea\"?\xdb\xdb\x88v\xfb\xe7\"\x00C+'\xbfV\xff\x1cz\xefS\xe7\xd7\x0c\x8d\xdd\xb0\x12F\x00\xfeZS\xb9\x05\xb1\xa1\xb2\xf5b\xdb\xd7>DB\xb6\xef\xc91\x8b<#\xcan>1\xb3\x86\x03f\x0e\x0f\xc8\xa1\xc2.\x11v\x01\xd9\x03\xa7\n\x16\xdc<\xfaC,\x1d1\x07\x83s\xfb\xc9\xef$\xe0f%\xda\xe4w\xc2mQ\x1a\xa5?\x06\xa5chBIP\xc1\x92t:p\x97\x08\xd1\x86\xf9&\x83w\x89\x10;\xa1\xbe\x83\xc2\x0c\x87\x08\xb1\x1d\xc9\x81<\xd8e\x95\xc1\xdbY0ML/\x19\"\xecG\x01\x0f\x8e\xeb\xc1C|\xcdC\xe3{\xb0K\x96F,\xba\xefgM\x06 \x03\xe1\xc1\xa1\x80\xdf\x01\x80wB\x84\xc3A\xbf\x03\xe0\x1a\x19~H\xa4\xf0A\xcc;$\xee\x07\xbb\xacs\xa1$\x86!\x1b\x1f\x05L\x06 ;q\xc3\x81H\xe0\x010wc\x87\xfb!\xb6\x03\x80\x0e\xc5\x0f\x1f\x88\xe7H\x0c\xb1\x83\xf2\x01@\x07\xe3\x88\x07\x87\xd2\xe0i\xc2ipXH\x0d\x0e\xdb5\xedx\xc0\x8a\x89\x8f\x04\xed\x8e\xb8\xc8\xd0\xeeH\x0b\xb3\xc1a\xa16\x88\x8b\x1e\x0d\x8dC\xa8\x81f\xdc\xeb\xd1\x93*\xc7F\xfc\x19\x8fc\xe3@\xbe\xef\xdb\xa0\x16y\x7f\xdeiev\x96\xff2F\x0e.\xd5\xffN\x00md\x9fIe\xdc\x1a\x17J\xef\xc0\xf1\x11\xb2\xce#\x93@\x1b\xcc\x98\x02#w\x1bRP\xae]\x01\xb0s\xf5\x0d\xd6\xbb\x16u\x9amw\xbf\x16\xca\x9d\xab\x8c\xc1\x02\xa6\xe0\xd9\x1d\xdd>;\xebi\xc4$\x90\x06\xc45\x7ff\xcd\xc5=\x85\xed-\xd1$\x90\xf8z\xc8g\x08\xe7\xd9@e\xebA\x06\xfb\x01\xab%\xf9\x96\xe6}k\xd1R\xde\x13\xd4\xf6\xf6&\x16\xe8\x83/\xedO\x91\x80\xa1\xb5Wo\xf7\xedM8\xf1\xd1\x1cwF\xfai\xe8\x80\xa4v\xf4+\x98\xb1t\xa2\xa4\x84+x\xe6\xe3\xc4\xdd7\xcf\x85bO~$\xee\x0c\x07\xe8\x85T\xbd\xa7]\x11\xf4\xabx\x07b'\x82\xe4\xa2\xe6j-\xea\"7\x1bz\x13R\xcf\xe1\xc4\xc7CB1\x9bv\xd8\xf7\xb7\xf7\x81p\xcdf\x0d\xa4&J\x12\x0d\x12\xc3{\xdd\xa6\x9e\x1d\x89I|\xd5m;Zy=\x83\xfb5\x95\xbd\xb93\x7f\xdam\x0e$^\x9ee\xcd\xb9\xc1Rp\x1f\xe0\xb6\xca\x0c\xd5\x84\x0f\xce!\xfa\xd1 \x91^\xf6\xdd\xe9\x0d\xaf;qN\xfb2O\xc2mIO4T\xc1\xdd\xa25w6/A4\x14\xa5\xb9\xa5\xb81\xca\xecl\xe25\xd8K\\n]D\xdd\xcb\xef\xf1\xd0\xfdx]\x98\xb8rRl\xa0Y\x17\xbd\x88\xeb\x93\xf4\xeb\x81\x8dl\xf7O\xd2\xc8\xb6\x13\x1c\xfd\x8d\xf7\xb1%\x05\xb0\x8f\xcdl\x83\xe3\xd8\xcc\x16\xd7\xcc\x86?\xda0\x9a\xefj\x0bR\xd6\xf7\xbc%t\xb5\x05`\xfa\x9e\xb7\xb6\xab\x0d\xfemMq\x0dK\x8a\x0c,\xebB\xb3\xaa-\x94 \xda\xd9\xb8\xfb\xd8\x90\xc0\xd2\xa5}\xfb:\xc3`J\xb2u\xe2r#\xd2\x95\xd9(\xdc?\xcel\x02\x94\x14\x85\xebX\xf3\xb1\x02\x9b]f\xa1} \xca\xcc\xda)'\xb0'\x127\x019\xdc\xc1N\xcc\x06_\x18\xc11[\xb0\xd7\xa6A\x15\xb6oa\xd8\xb8\xdf\x86\xfa$\xa4=K\xb91\x1fN\xd4i\xd8@r\x91\xd58s\xcb\x99QA\xa0\x013k\xdf\xac B\xec\x99=Q\xe6L\x10\xa4]H\x8d\x19\xf3\xfb\xce\xfe\xfb\x87\xc3\x0d\x99\xd6\x80A\x826&L\xcb\xfe\xd6\x80 -\xb4\x04\xbf?9\xe5\xf6T\xe9\xb6\x83Rm)3\x85\x07\xa4\xd8\"\xd3kM\xca,\x12,\xc4\xa6\xd6\"\xb2\xf3\xedH\xf2\xd2\xa3tS;\x9e\"\x9d\x16\x91J;\xd6\xc0\x8f\x8f`\xda\x0c\xe7\x9e\x04\x12\x1e'e\x96\xe8\xf5\xf8qX\xaa,\x9c&\xb3I\xaf$\xa0\x10L\x91\xd9\x84W\"\xd0@z,Q.\xcd8<5v \x93\x0eI\x89\x85\xd3a\xe9x@\xbb0CE\xf1\x89P\x07\xd3`\xfd\xa4V\"\xc4\x01\xfc~\x9d\xa2\xf8\xd1\xd7A\x8e\x0f\x0bg:\x91\x95\x08\x12\xd3^\x87$\xb1\x12\xf7(;\x0e\x94\xebX\xdf\xb8?b\xfd\xfev\xa4%\xac\x0eHVE\xc7\x02\xda\x91:\xf3\x03\x12T\x0fKN\x1d\xc0\xd3'KJ=QB\xeaI\x93Qq\x89\xa8\x94\xd4|D\x12\xaa\x9fX\x8a\x86\xfc\xf0\x04T\xe2\nH\xba<-\xe9\xf4D \xa7\xa7H6=~\xa2)A{'\xae\xef\x14}\x95\x98Xz\xba\xa4R|B)\xa6\xdb\xc1\x8e\x84dR7I\x14\x05{:\x91\xb4\x1fQ\x89\x04:\x9cD\x1aL\x0eEA\x1c\x8b\xbbL&\x86\xa2 \xef&\x8f\x1e%)\x94 \xe9\xb1\xb6EJ\"(Z\xd7\xc5,\xb1\x08`\x95\xc8/\xb9f\x0fk\xaa\xea\xae\x92\xbd\xce\xaa\x89Y\xd8X8\xd9\x08\x96CU\xdb\x97\xe2GuWM\xc0t}W\xc7\xee\xaa\xb6\xbb\xaa\xc7\x9eN\xffM\x00\xe2HJ$\xd0b\x15\x00\xea\x1b\xb0\xd2Z\xac\x02@]\x03VZ\x8bU\x00\xa6o\xc0\xfa\x0d\xb5X\x8d\xf1\xf9\xd8gu\xec\xb3:\xf6Y\x1d\xfb\xacR\x13?ph\xf2\x07\x0e\x989< \x04\xf1\x89\xa0\x04\x88\xc7>\xab\xc9\x11\x91\x1cJ\x84x\xec\xb3\n%\x8c\x92!\x1e\xfb\xac\xc6\xc6\xb1\xcf*e\x1c\x92T\x82\xa8\xc4R2\xc8c\x9f\xd5\xb1\xcf*q\x1c\xb0k\xda\xf1\x80\x15\x13\x17\xa1\x19\x1a\xb1a\xa5\xfeHK[\xc1a\xa9+\x88\x0b*\x0d\x8dC\xa8q@\x1a\x0b\x1e\x9c\xca\x82\xc3\xf9\xfed)-x\xba\xb4\x16\xabc\x9f\xd5\x13\xa4\xfd|\xa7R/e3\xdcl\x15\x98q\xbf])\xb2\xd9*\x00\x13\xd3\x90\xb1\xcdV\xdd)\xc4 \xc7~7\xd9D\xc7U\x00d\xaf\x1f+\xb6\xe3*\x00\xb3\xdf\x8fe\x15i\\\xc7U\x00\xf0\xfe[\xc6\xc2\x1dW!\x90\xbe\x1f\xcb\xeeC\xc7\x8e\xab\xe9\xb1ok\x1c;\xae\x8e\x1dWn$'\xdf\x9e*\xf1vP\xd2-e\xa6\xf0\x80d[d\xa2\xed\xd8quHb-\"\xa9v\xec\xb8\x1a\x1f\xc1\x04ZL5\xd1\xeex\x94\xe4Y\xa2\xff\xe3\xc7aI\xb3p\xc2\xec\xd8q54\x0ed\xd2!\xc9\xb1pb,\x1d\x0f8v\\\x1d;\xae\x86\xc6\x81r\x1d\xeb%\xf7Gl\x04\xa0\x1di\xa9\xab\x03\xd2V\xd1Q\x81v\xa4\xce\xfc\x80T\xd5\xc3\xd2T\x07\xf0\xf4\xc9\xd2SO\x94\x9az\xd2\xb4T\\J*%I\x1f\x91\x8e:v\\=U\xea\xe9)\xd2N\x8f\x9frJ\xd0\xde\x89\xeb;E_%\xa6\x98\x9e.\xbd\x14\x9fZ\x8a\xe9\x80\xb0#!\xadt\xec\xb8:v\\%\xe8\xba\x98%\x16\x04\x16\xb8\xc0H\xe4\xf0\xe4z\xab\xf0-)\x1ba\xa9\x84\x18\x8e\xb1\x04\xe8\xca;/\xf0\x1a~d\x8a\x81\x12db\x0f\xff\xe7o;\x0f\xdf z\xb8\xb6\x0fg\xb5kYSX\x8e\xdaz>\x96\x8e=\x0c\xba]ys\xb8\x1d\x80\x87\x0b\xc3]\xf1|\xd4\xfd-\xacQ\xb4\xc4HI\x03~'\x15b\x17\x97}\xd4\x1b\x811\xf2\xa5\x18#\xceZ\xebJ]\x9c\x9f\xdf\xd5\x0b*9\xd5T\xcd\x998\xcfE\xa6\xce3\xc13Zi\xfcc\xc9V\xb5D\x0f\xfb\x9c(\xc5V|V\x89\x1c{4\xce\x9f\x1f\"LM\xd41B\xa2\xae\x97PI\xb1a9\xcd\xcf\xa0V\xd4L]5=I\xe8\x86C\xc1J\xa6\x91.YU\x9f\x97\xb4\x14rl%4MMF\x0fd8\xa7\xc1+\xc3q!|\xe8\xc4\x9e\x99\"\xa4x=\xdf\xbe[N]0\x8b\xcew\xce\xc2RoGE\xb4\xa6\x92_\xc0\xbf\x9f\xfc\xf9\xeb_f\xa7\xdf\x9f\x9c\xfc\xf4\xcd\xec_~\xfe\xfa\xe4\xcfs\xfc\xe3w\xa7\xdf\x9f\xfe\xe2?|}zzr\xf2\xd3\xab7?~\xb8y\xf93;\xfd\xe5'^\x97w\xf6\xd3/'?\xd1\x97?G\x029=\xfd\xfe\xab \xa4>\xcdZq\x9c1\xaegB\xce\xecL.p\xd5\x8d\xde\xda_\xc9\xaf\x91?\xee\xcb\x85\x0b(\x96\xe4\x13+\xeb\x12H)jk\xa8\xbb\xd6\xb3 |\x1aim\xf6\x8e\xce\xc2:` \x95\x84\x93\x15\x9d\xb9\x07\xcf\x1a\xf03g\x8cS9\xb2\xaa \xbc\xb2\xc0\xedEfi\x1cE\xf3s\x15\xcd\xf7^y\xed\x08'\xe3\x0f\x10N\xd94\x98]/\xa1y\x02S J\xa6\x8dMh\xf4#\x81F\xc8\xa6,K\xa6\x8d\xf9H\xeaB\xa3\x9b\xe2\x96\x126C\xda\xd7\n\xd2OU\xc12\xa6\x8bmk\xb5\x9e\xd9\xd6\xe6{\xa6\xa6\x10\xb6\x9e2++\xeb+\xe3\x92\x98y[\x15\x8d\xcd\xcfzy\x05.PTn\xa8\x8c\xd9\xd7\xde\xd6\xe5\x82J\xc3\xe4[{\x8f\xf7\x02F\xcd\xa6puLh\x11jQPK\xa5\x18\x0c?\xb4W[\xcd\xa7\xcc\xfe+Q\"\x14\xd5@\xb9\x96\xc6\x8f-\xd8\x1d\x05\xba\\\xd2l4&\x8a\xedS>tq\xe6\xd8\xdd\xe9\xeb\xd5\x12\xcf\x96\xfd}\x136:\xb3\xf3\xfc\x03\xd4jJ}5\x81%\xf4\xba|\xc8\xe6\xf7\xfe\xaf?\x8cy\x1fa\xab\x03\x1c\xa5\xa7\xb4q\x8fL/\xf1r`\xd63}\x12\xa8\xc1\xca\xb3\x87\xe7\xf8\x11\xd1{(\xf1c\x92\x87=\x0e\xbc\x1bO\x15\xee&\xff\xa6\x89\xef\xe3\x9f\xf3\xc1n\xb86\xb3\x07/\xffZ\x93b\x0e/\xdc.\x18`\xa9\xbf\xdc\x01\xd8\x8b\x0d\xdf\xb3\"\xcf\x88\xb4{\xb0U$\x93\x10\x95\xb0\xf2e\xcbL2\xc2\x1b5\xd6J\x8a\xed\xc3\x87\x8aH\xcd\xb2\xba \xd3Y\x07\xb3\xf6WBN\xa6\xc3\xa2x\xd7\x8a\xfb-\xcd\x04\xcf'\x0d\xc7\x91\xfd\xc4\xdd\xd9\xe5&\xee|T2\xac\xaa\x99\xa66+\xe9\xee\xc2;\xe9\xfb\xe6b\xe9u[\xa30\x02\xab\xc7\x1b.\xddz?\xa6\x80\xd9r\xca\xd3v\x17i\xb5\xc0\xb4\xba\xfc\xe3\xd6[Pg\xc6\x9ar\xc1'E\x9b7\xf9\xfbe\xe8\xd8\xda\x80\x9d\x84\xba\x14\x92n\xa8\x84\x93\\ <\xac\xdb;\x9d\xc3\xff\xa3R\xa0\xd8r\xba\xb2Ecn\xd9\x06\xcf\xae\xc7H\x06\xc5\x98!Q\xf0\x0d\x9c\xd8R@V\x964gD\xd3b{j\xcb }\xa9\xe1\xd4\xb4;\x16\xca\xff\xfe_AA\x0b9\x0b8\x85h\xe9\xfa\x88q\xca\x9e\x9a\xb6\xa1\xcb\x1dQq\xdb{PG\x8f\xe6\x81;-\x8d\x9dXs\x8c\x8an\x84\xec?\x8d\x9c\x12\x90te\xd6\xad[q\x0f\\\x99\x91\x96\xebX\x94p#\x8a\xba\xa4W\x05a\xe5\x07ZV\x05\xd11\xe1\xbe\x8f\xfbwyS\x91\xa0\xb1\x88\xb6\"\xda\x03[X\x8b\xfb\x11\xdc\xed\xc3\x8d\x05\xacXN\x81\xc0\x07\xca\xc9\xc8R\x08\x9bH\xa4b\x1f\xa9T\x93u\xcf}\x7f\xec\xf2\xe6\xda\xdd\xe1\xa2\xe6V\x8a6\xf6;\x9ac\x80\xad$\xfe`\x99 F5\x1a\xcd\n\x1b\xc6\xb8\x1dS\xe6\x8d\xa1\xef\xa4&\x13|C\xa5\x06I3\xb1\xe2\xeco\x93v\x92\xc5@\xf9b\xd0\xc2\x1e\x18\x84\xf5\xaf\x9c\xb8]\xda\xe6\xf8J\xb2\x05I\xcd\x13\xa1\xe6Q\xb0}i\xc6\x80\xdb\xb5bz~\xf7\xcf\xe8se\xa2,k\xce\xf4\xd6\xf8[Z\xb2Em\xf6\xcd\xf3\x9cnhq\xae\xd8jFd\xb6f\x9af\xba\x96\xf4\x9cTl\x86\x13\xe4\xb87\xcf\xcb\xfc\xcb\xc6\x13\x0b\xb9_\x93r~\xc7\xf8D\x94\xbd\xcf\xd7W\x8c\xe7.\x88\xdb\xe9\xccn\x99\xe4\xb31\xef_\xde~\x98d\xaa\x8b\x19\xe2\xe6`\xb9\xd9\xd9\xbbZ\xc6\x1a\xd23\x8egdM\x8b VX\x9b'S\x9e\xdb\x02q\xf3!+\x98\xb1\x17T\xbd@w\xbb q\x1autE\xf8tm\xee\x82\xba\xc2\xf0|\x0e\xd7\x1c\xaeHI\x8b+\xa2\x86\xbd\xe9\xc7d\xab\xe1\x99\x9a\x19\xb6<\x8c\xb1%\xd5$'\x9a\xc42\xf7V\x13\x9e\x1b\x9b\xca2\xe4\xf9s\xd5\x80x\xf29\xfb\x07\x85&<\x19\xa73z1z\xb2\x15\xcdz\xba)\xa7\x8aI\x9aC\xb6&\x92d\x9aJ\xa64\xcb\xd4\xb4\xf1D\x9c\xa6\xf5\xa2e[\x1c\xac\x91Ij\xbd\x1629\xf6\xa2\xb4\x90dE\xcf+\xa3+\x95\xa6\\\xcf\x9c6\xff\xb2\xfd\xca~\x93\x99mbBF\xc2\x9a\xdd\x0c\x92eT\xa97\"\x0fe\xf5wT|{[[\xf4\xd0%\xa4\x85; \x11\xa0t\x07\xd9QOH\xa7\xca\xd7d\x93\x1e\xb6\x9a \x9dEf\x86\x8f\x9b};N2\x08EL\xfc\x88X\x7f\xdd\x0bC\xe9z#\xfb\xb7\xa8\x13Sx\xf0\xa1\xd3KC8j,e\x834\xdeD\xa0\xcc\xd8H\xa1\xc9\xfc\x0e.9Pc\x8c\x19\x05nm\x90[N*\xb5\x16\xda\xab\xe7\x13\xe5\xbe\x98;2\xfb\xb5\xdf\xbf<\xf0\xa4\x19\xfc\x91jr\xba\xf3\xc4\x9b\x8fWpr\xd3p\xadc\x04\x9d\xc2\xef\x02\x10\xbbp\xb2ZiQ6\xdb\xcb\xb9C\xdd\xc6X}\x80T!\xb1\x03P+Q\xd5\x85s\x85.\x8bjMNmQen-\xb0Z\xd1a2EH\x8d\xb3wIe\x96\xa74.\x01,)1\x8a\x11V\xe6CS\xc5\xc8\xc9\xa2\x08f\xebO\xfah\xbch\xe4\x08\x84\x84K\xbe\xb5?\xb7_\x9f\xc2u\xe8 \x16\xf4\x1c\xa5\xd80\xb4\xd5\xa4\x01D\x0c\x91\x9de\x84\x1a^\x14\x05\x95(t\xaa\xae*!\x83\x13\xefUc\x18\x06\x80\xe5\x11:s\xd8\x85\x96\xa1\xd7\x04\x048\xbdw\xda \x00tA\x94\xcf\xd0RD\xab=\xacp\xe4i\xa1\"\x85\xeb\x89{\x1b\x97\xd3N\x98\xe6g\x1d\xbd\x15\x80\xdbm\xb3\xcb\xbcw\xe8\xca\xc7\x96\x84\x15\x86\xf9x\xcd\x02\x8d)\x04\x1f\x00I\xb0\x84\x18\x1b\xd2\xd0>AP\xb5\x11\xa33\xb8\xa7P\x15\x18\xe3\xf0\xd8\xe2\xe9\x9b\x01\x88\xdd\xb9\xa2\xa06(.\xe8\x9al\x98\x90M!B+\x1d!\xfd\x8e'\x87\x12\xbe\xa2\xf3i\xa5\x1b\xb7W\x81\xf5F~\x94\xa2\xaeB\xd7\xed\xb6m\xdc\\\xe3m\xde\xa3]\xe1\x07\x9f\xfa\xf7*#\x08\xd3\xd8\x85x\xe0-]RIy\xe6\xd2C]\xe8($M\xc86\x02b_\xe4\xd0\xc6\xf6J\x80y\xe1\x96\xd4<\xc3b\x1d\x92b3~\xc0U\xbbu\x87\xe3\xea5\x93\xf9\xac\"Ro\xbd\x0e\xeab\xdcd\xba\x82\x80\xa3\xb7\xbd\x90_\xe1G?.\xec\xdc\x0b\x8c0l+\xdam\xa8\xda\xa3{\x10t\x02\xae\xe3\xc58\xdd\xb1_\x98\xe3p\xe5\xaeH\xe7W\xc05\xae.j\x86\xd4\x0f\\b\xb0\x9e\xbc$\xc2\xe4\x86p\xf1\x89\x1f\xbb\x19\xdb6\xcd\xda\x8bY\xfa\x9cm\x035bgyZ\xdb1\xc2\xcd\x86$\x0d\x16*t\xf1#\xb5\xaa\xa0\xb9/T]\xe0G|\x95\xc1\xee\x1d\x11\x92j\xc7gYu\xe0\xc7\xc1\xd5\x07~$\x17\xc8\x04!B\xa7J\xe1\xf3*\x94\xf1#R+@T\xe1\x8c\x1fGQ\xffm\x89zT\xc1M\x10\xe6\x88\xb0\x87\no\"\xe0\xee\x96\xe6\x04\x0bp\"`\x06Jt&\x0bq\"\xc0\xff\xddKu\xfc\x88^\xe0\x91\x17\xaa\xa8>\xfb\xbe\xb1\xbe\xdfa\xefS\x1aZ\x18\xb6*f<\xf1\xf1ja?\x16\x0cO\xc4\x986l\xe3w\xee\xf4N\xfa\xde\xb4\"z\xe8\x1bj\x05!CD\xf7|l\xebPT\xc8\x0b\xc6\xb84\xd4 \xdf/\xf5\x8e\x80\x0c\x93=\xf0\x83\x9d\xedQP\x07\xba\xdf\x13z\xda\xe3E\xc3\x8e\x84>\xf6\x1e)G;\xd8\xads\x98BF@\x1f9\xb5w=q\xaf\x8b+9\xe9\x8e\xdet':\xd5{\xe5'\x91\xb0a\xbcG}\xbf\xeb<\x1a\xe6^w\xfaA\xfd\xe6\xc9\x84M\xeb1\xef\x91u\xaa\xbb\xcb\x88\xf5\xa54\xd1\xf5\x84\xde\xde\xab\x91\xd1\xf5^\xcc:\xab\xa5D\x9f\x87\xdb\x82M\xe3\x8a[\xb8\x13S\xb0\xc5\xc6\x0d\x19\xbc\xbc9\xf1yOI>3\x1a\xe91\xd7\xdco\xa3\x80\x84d\xba&\x85\x03k+D\x02\xc2\xd4\xc9\x01\xb4bD\xb1\xac`M\x86\xeb\xf0\x0e\xa4\xe0\xe7^G\x92\x91\x8ad\x93o\xf7\x84\x03-\x97\xa8HkZ\x945)\xc2\xfa\xd9FW\x1f\x14Y\xed-\x89\xf7}\xad\xe2\xd6A\x1b\x17u\xbbx\xcds*\x8bm\x98dVhc\xd4h\xd0\x02\xc9\x04\xb7\"\x93\xb2\xc4\xaf\x9cZ\xbc\xf27\x9b\x19\x8ci\xbc\xc0\\\xae\x97\x9dy\x0f\x00a\xaaI\xba*\xf67\x8a\x96\xe0p#z;\x0c1[\xdc|\xfd\x85\xa2\xd8a\xf2\xfc=\x02\xba\xd5Dj\x9a?\x9f\xc6/j\xa9\xf7h3X\xed\xd4\"c\x15b\xc4 J9\xc5\xeb\x80,D\xadq3C\xa3\xa3\xda\x84\xce)\x8b\xd3\xedv\x14D\xe9\x1b)\x16\xf4\x03\x0bY\x0bv\xf4\xa6\xfa\x9a(m\x9bL\xee\xb1tda\xb9\xd3\xcaT\x88\xf7\xd0\xe9\x84\xc8\x89\xa63\x03,\xe2\x9e\x04\xedb\xe7\xf8A\x12\xae\x10\xa5\x07N\xb47=\xd0\x0d\xd8\xa0\xe1g\x07V3\x0bN\x9dqb\xdd)L4|\x16\xa4*\xa9Rd\x95N\x9f\xffS\x97\x84\xcf$%9Y\x14\xd4\x83\xf1\x9d\x94f\xf1:i\x8e\x00\x0cN\xe2\x0b\xa4yC\xe0\x18\xfa$\xcdUR\xa2B\xe7\xbd\xdb\xd1\x9b\xea\x9f8\xfbk\x8d\xa7\xb03\xd5ij!\xe6o\xa9\xcf\xa0$\xd9\x9a\xf1\x18\xce\x80\xd5{\n\x8b\xb3\x0d\xd9\\8\x0f\x83\xc3+\xb6q\xa1m\x8bgDF\xc4\x8eF8\x9f\xab=\x12\x1a]\xcb\xb4\xabCS\xf0\xac\xa7\x08c\xce\xbe\x02\xff\xdad\xe2,\xba\x80\xe6\x8e\x02\xd9\xd3\xee\x8f\xce\xe6\x90\x17\xd0\x8e$\xb0xq\xf0\xaa\xa4\xad\xe1\xc3\xb6\x8a\x13\x1b\x0c\x10m0\x06\xde\x1c95\x0dz\x1e ;\x81\x04\xb1\x81\xc2\x19\x04\xfd%h,\xc6\xc0E\x91&M\xacI]\xad\x89Jq\x91o\xcc\xf5c\x1e\"\x02\x1b\xe5D\x8c\xa9\xf6P\x8f7p\x81stn\xa8\xb4=8\xc3\x13\xefW\xc25\x07/\xec-nw2\x997\xad\xfc1\x02#\xd8WT\xba\xf3\x1e\x06/x\xe8q\x0d\xe3\xb28\xf3\xc7L\x0c\xfc2\xd0\xc77zUK\xb6\xbdK&\xc8>&\x86\x95dB2\xbd\x1d\x0d\xfb\xf5\xc5n\xf7\xea\x9d\x13\nnD\xde@\xc4P\xe9\x9a\xf2\x81zWV\x1a\xadOxFm\x80\xc2\xdc\xd6}q\x82\xad'\xbd\x11\xb9r\xa9\x11\xa3f0\xdb\x88}\x07o\x18\xbf~\xb7\x07\x14\x0f\x93\xb3\xc1\x8c\xf7tI%\xbcj<&\xc8EV7\xe5\x12X\xb7\xe1M\xda\x18W\xbd_\xfeP\x89|\xe6\xe78\xab$\xa5%\x12\xe7\xfcK\xff%\x06\x1d\x07\xc9?\xb0\xac\\\xf5\xd2e\xad\xc5\x15\x95{\x07D\x0c\x16\xc4\xf8\x8b\xbb\xe7{\xe0\xeb8\xb0\x98\xbf;o,^\xdf\xa3\xd4\x87\xd7\xb7\x90\x99\xfbW\x947\x87 \xf0\x1c\x14[\xe1\x81\x83\xc4\x9e\x14C\xf0p\x975\x95t2\xa2\xa1\x89\xbaS\xe7\xbaP\xb60\x84\xf1\xd5L\x17\xc6I\x9d\x91YV\xd4J\x0f\xd4\x83Xr,\x84((\xe9;P\xea\xbbI\x12\xdc~\xe7r\xed\xb9\xefgP\xbe+%g\n{\x19\xf0\x88M\xdb\xd6\x00\xaa\xce\xd6Co\xe7\xfa\xcb\xa2\xce\xee\xa8~\xf1\xf6\xf6/@\xf5^\xa8s\xcami\xee\x1cRZ=\\\xff\xe8\xaf\x04\xb6\x84\xe7\xc6K\x7f\xee\xcc\x15\xfbK\x83\xb9\x8d\xf7\xd0|\xe2x\x92\xbf\xfc\xde>\xf7\x0f\xf3\x92q&\xe6\xae\xcch\xae6\xd9\xdc\x11y^\x88\x8c\x14\x7f\x19\xb8}\x9c\xda\xe3\xfaj\xd6Nt\x90w\x03JF\xd1\xacF\xe5 \xb8\xa6\x9f\xa6E\xf9\xd6]\x0b\xee\xe2]Q\xde;\xa9F\xd6\xfcR\xfdI\x0d\x1d\x80TI\xb6a\x05]Q\xa0*#\xae\xa1&\x91\xabK5Z\xee\xdf\xc3\xfb\xd9\xa5-\xcb\"\x056=\xb8\"\xac\xc2\x15\xfa\xdb\xd3\x1f\xda\x83bIQ\xb4\xe5a\xc3f\x07\xe3\xb6\x93o\x0e\xb7\xa2l\x02\x8c\xdavF\x18\x9a\xa0^5K\xba\xb0!\x03\xdb\xe8`\xb3S\xf7\x06\xecX\x05\x83peg\x1e$\x9e9hni\x92\x08\x95\xc8/\xe0\xcf\x1c\xbe\xb5\x89(q\x8f\xab\xff\xc7\xeb\x17\xe3\x07\x10,\xec\x93\x7f\xb8\xb5e\xfd\xffd\xefTT\xafX\x0e\x0b{d\x82\xe1\xdd \xa7\xf7\xb0d\x85Y\x9e\xae\x15\x85\x0dGJ:aU\xbf\x837H\xba\xc7\x9c\xc2w\xf69\x15\x95%\xc3\xdc\x9ey\xd6\xf8\xab;\xde\xbd\x7f\xee\xde\x90&\xefg\xf2~6\x9b\xcd\xcc<1\xbc\x83\x879ti\xda\xb4\xcd\x94\"g\xcb\xf14UCm\xd4\x95-*\xf6D\x0f\xbe\xf5\x91\xb0!\xe7%t\xc4\xc2\xb4M\xe1\x84\xf3\n9\x7f#\n\x96\x0d\x86^\xfb{\xc5\xc0MM\n\xaa\xdbj\x83\xf2\x84\x07\x1eMJS\x7f\xce>J\xe8\xe3\xe1t)\xa4oH\xa0\x9f*\xa1\x90\xdfx,\xc0\x8d\x18q\xa4:}\x85\xc8\x02\xcc\x8c\x9a\xc5\x83/\xc1\xea-\x04{\xf6\x86\xef2r3\x1b\x96O\xdb\xad\xe5\xa7r\xb2\xc3\xaa\xd39\\;\x8e\xaf\xc9\x86\x02\x17\xfe\xc8\x11\xa32\xaa5-\xa9$\xc3\x92\xdfC\xc8\xed+\x17F\xe7I#P\xd6D(Iekx\xb0\xac#g\xd2\xd7\x07M\x94\xb0\x10I\xe1\xd9;\xfe^\x08\xfd\x86)La?C\x18\xcf.\x8b{\xb2U\xcf\xd0U\xee\xb5\xfbt\x8bL\x07a6\xb7\x0e\xe5\x0e&-|T\xb3q\xaa\xd0,H\xa3+\xb40w\xa18\x18\x8d\xbd\xb5\x9d\xf1N@\x1a\xedg\xb4\xaf\xd9\xe5\x86e\xe1O\x8a\xe2)\xc0\x18\xd7r\xb33\xbb&.\xd79\xbc![ \x85\x12>r\xcax\xb3\x81\xb8\xfdc\x0ec-\x87\xee\xfa\x85\xd0\xeb\xdd\x9b\x90\xcc7\"\xdf\xf9\xbaS\xd63\x0c\xb1\xe1\xc3>\x1e\xa0\xc9\x1dUPI\x9a\xd1\x1c\x13\x95\xcb\x9d\x17\xef\x0c\x87\xd7\x1e\xa6 \x90ko\x05\nQ\x90o\xd7\x1d\x8b\xdd\x95\xfe\xb5\\\xc2\xb2)\xc3N\xa2\xf0`[>\x93b\xa4\xdf\xd6l\xd5\xb6\xa8J\xd6t@\xa5bT\xc0\x1f\x92\xc3J\xb22\xae\x99g\xf2\xf0V`LXUK\xea\xea\xa55\xe4\x82\xdaV7\x87\xd2\x9f\xae_\xc07pbp:E\xee- +\xd0^\xd0d\xa4=\xb4??\xb6\xf4`\xe7\xcdv`\x0c\xc6%)\x14=3\xfa\x00\x97\xb6\xc3}\xec\x98Y\xbfQUT\x1a\xc6a\xcbD\x9c\x88\x9a\xdf\xc6\xec\x80\xc3D4\xf0f\xc7\x08\x11\x1d\x92\xc7)\x93\x11Zc,(lFI\xfc\xe9\x91\x94\xc4\x8bNi=\xda\x89\xbd\x85h%\xcc\x1f\xf1\xe0\x94\x87\xbf\x00\xf93\xac~\xe3x6\xc6\x9f\xd1\xbd2\x92g\x03\xcf\x1c\x96\xe2\xbf\x87ZQ\xf45\xe3\xf5\xa7w\xc8\xcb\xc1\xb8\xe5\x1e\xafo_\xe2-\xb6Q\xfa\x93vVg\xc7w\xef\x9b\xc4\xc3\x8c\xbe\xee\xf1\xeelGF\xfc6\x81\x8b\xd0\x9d\x07M\x81\x80$<\x17\xa5\xc7`\x10\xb0\xc7\xca\x10\x0f\xdf]\xd9\x12\x0fbW\xf0ox\x93 e\xe3\n\xba\xa1\xc5X\x10\xb2\x9f\x842W\x1a[\xdf\xf3\x1bouU\xe5\xbb^\xd0T\x9d\xce$\xbe\x10\xb2V\xcc\x90\xa2\x18\x0d\x9c\xf6\x13\xdf\xa2\xa06^\xed\x916\xb7\xfe]p\x9e\x8a\xd8\xf7\x97\xd4\xb6\xda\xc1\xd9\xdc\xfaw\xc1\xb9\x1eQ\xf7\xb0\x97\x952\xaa\xb9\x873*\xeb_\x1f\xe7\xc9 t\xd7{G{7\xac\xdf.\x9b&\x1a\xf4\xf6{!I\xb3\x98\x97L*\xed\xb70\xdc\xeeF\\\xde\xbe\xea\xc1\xd7n\xfbb\x19\x0f\xab\xf9\xf5\xb9Y\xe7\xac$rk\x8c\xedq\x0d\xd4S\x98\\x\x14\x9b\xa0x\x9e;\xfd\xcb\xb7\xd3\x84\x9d\xa82\x08\xed&\xa1\xfdd:\x19\xa2\xb6*\xd3\xc3%\xd1\xfd\xd0\x91\xbd\x0e\xd6\xa2\xc8;\x8dM\xcd\xcbWr\x0f\xc9\x9eS3\x96\xact\x01\x909\x86\x99m\xb0\xa0\xe6\xcd\xb1\x1b\x0d\x8c\x13_p\xb9\xbb\xff\x0c\xbf\x92\xa6\xc4\xf7\xb4{\xab\xb4 5\x1f\xae\xbf\x9f\xa0\xf2\xc0d\x1b\xc7\x9d\xc0\x1d\x95\x9c\x16P\x11IJ\xaam\xb0\xccnX\x83\xc0B*?t*A?\x07\xe3\xaa|\x89\x07\xbbu\xa1\xba\xd1\xdb\x83Z%x^d\xbf0\xd4\xa7\x18\x1f\x11\x83\xe9\xe4\xe1\xc4\x01\x06\xb3\x89\xdd;\x90\xff\x9aZ\x06\xf7\x8c\xe7\xe2^\xa5\x18]\xfffo\xf16Cf\x08\xa2\x19_\xa9\xc70\xbc\x84E\x04W\x08\x06+\xbb\xaa)\xc6t\xf5*\xc8\xac\xc6y\xc0\x9c\x1e3\x96FWp\xd8\x9c\x8erwB\xcbdU*r%\xcd\xfd\x9a\x91\xe2v\xe2\x08\xb8\x1es~|s{\xd9\xbf\xcdl\x8c\xf6\xb5O\x06{\xf3;\x90\xdcE\xa7Fe\xf8\x9e.\xd6B\xdc\xc1I\xe7P\xbcu\xbd\x98g\xa2\xec$df\x8a\xad\xd4\xb9\x13\x9f\x99\xc1x\xfc\xadY\x8c\x17\xcd\x99t\xbbg\x1a!RY\x835\x12\x17WA\x0e\x8b\x897\x15\xb9;\xfb\xd3E\x8d\x811\xbe\x03\xf7\xf0!\xd2OU\x93\x07\xc8?t\x9e\x8a\xc7|tj\xbb\xb4\xb0\xee\xe7\xc1\x13j\x9c\xe7\xe8y\xa0\x13\xedn0\x12\xee\xd7\xfb\x98S=\xc9\xa4}g\xbb\xe7X\x9bKF\x9c\xebQ\xb0SN\xf7\xaeK\xb5\xbf\xb8\xc7\xeb\x11\x0e\xd3\x15\x936\xe5#\xe9\x0b\x083:\x98\x8b\x1f\xcc\xa0\xc9\x0d\xcb\xe8e\x96\x89\x9a\xeb`6\xfev\xef\xf2!\xd9\xee_5\x142\xae\xed\xb9\x02F\x96l\x12}\x89\xbb\x05\xa6\xd9\xady\x94\xb5\x87M\xdb\xb3\xcb\xc1\x1d\xaa\xeb\xce\xfc\xdd\xa5\xd1(mT\xbd\xb8!z==\xadzQ\x11\xbd\xf6 \x04\xfbZ\x15\xf3M[\x0c`\xe6\x953\x89\xfd\xca[\xabP\xf7fe\xd1WZHjO\xe3k\x04\xddL\xf6\xd938\xc1(\xfd\xae\x92\x1cA}\xc8L\x98\xe1[?\xbaa\xfdA\xce\xee\x97}\xf5\xa7k\xcb/\xdd\xeb\xb2TS\x99\xe0\x8f\x98\xf3\xd5\xb6\xe6\xc3\xde \xcbc\x1b\x17\xd9\x10V\x90EA\xdf\xd3\xaa`\x19\xd9\xdb\xd7\xa6\xea\\\xc6\xadxWadP\xde\x13\xcd$\xc2\xed\xe1\xd7\xfb\xb5\xfb\x98i\xea\xeeB\x9f\xe1\xda\xfeb\xf0zw0\xf4\x05l\xbem?!a\xac\x95\xe7~p\xaf\x83\xc9;\x85\xf5\xaeW\xc3}\xd3\xf2\x93d\x19\xad4\xcd\xcd\xd2s\x14\xc6\x03\xc9\xe0\x99M\x02VE-I\xe1>v\xaa\xdb\xe1\xa7\x9f\xbf\xb0Pi\xfe\xd1\xe3a\xbe\xfc\xff\x01\x00\x00\xff\xffPK\x07\x08K2\xe1#\xc70\x00\x00\xb6|\x01\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x81-xQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00 \x00deployment.yamlUT\x05\x00\x01\xa3\x9d\xbc_tP\xddN21\x10\xbd\xdf\xa7\x98\x17\x00\n_\xf8\xa2\xbd#\x9a\x18\x13%\xc4D\xef\xc72HC\xdb\xa9\xd3)q\xdf\xde,?\nkv\xae\x9a\xf33\xe7t0\xfb7\x92\xe29Y\xc0\x9c\xcbd?mv>\xad-\xdcS\x0e\xdcFJ\xdaDR\\\xa3\xa2m\x00\x12F\xb2\x10}\xf2<\xe2L\x82\xcar\x82KFG\x16\xd6\xb4\xc1\x1a\xb4)\x99\\\xe7\x10\xca\xc1;,\x16\xa6\x0d@\xa1@NY:\x06 \xa2\xba\xed\x13\xbeS(G`0@)\xe6\x80J'\xdfE\xa3n\xc2\xd5\x8a\xc1%\x00\xe7R\x877\xc9\xde;Z8\xc75\xe9r\xc8\x02\xe08)\xfaDr\x910\x1a\xce8\x8e\x8f\xf8q\xe6'\xbb\x9b\xf2\xa3\xb1\xfb\x7fc3\x9e\xdd\xf6\xb5\xab\x1a\xc2\x8a\x83w\xad\x85\xc7\xcd\x92u%T\xba\xf3\xff\xea\x84\nWqt\xd1\xe3\x08\x7fV*\xdaC\x01\\\xae\x16f\xc6\xc4\x1e\x1e)\xb2\xb4\x16f\xf3\xff\xcf\xbe\xc7Q\xdeR$\xc10*\xcar\xf8\xc2\xdc\x98+Y!W\xc5k{\xc7I\xe9K{]jZ\x94\xd7Bbaj\x8c\xf9\xcb=\x08\xd7\xcc\xf2\x8c\x1e\x8b\x8d\x89\x86\x0e\x91\xc0\xa2\xca\xf2\xf0\xbc\xe5f\xa1\xb3\xfe|l\x18U&\xdf8\xbf=~\x01\x00\x00\xff\xffPK\x07\x08\x80\xa45\xf7U\x00\x00\x00Z\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\xaf\x1c%Q\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00 \x00service.yamlUT\x05\x00\x01\xfb\x07S_|\x8e1k\xc50\x0c\x84w\xff\x8a\x83\xceoh^'\xaf\x9d\xba=(tW\x9d\xa31u,c)\x81\xfe\xfb\x92\x90,\x0dt\x94t\xdf\xa7\x93\x96?\xd8-k\x8dX\x9f\xc3w\xaec\xc4;\xfb\x9a\x13\xc3L\x97Q\\b\x00\xaa\xcc\x8c\xd0\xc6.\xae\x1dOx\x14\x8a\x11\xa3\xa2\xaa#MR\xbf\x08\x9f\xb2a\x95\xb20\x00E>Yl\x83O|\xce5\xeb\xed\x94\x1cVk\x92\xae7kL\x1b\xea?\x8d\x11\xafe1g\x7f{\x04\xa0i\xf7\xc3z\xdb\x87\x88\x97a\x18\xf6\xc5\xf9hro\x7f\x12\xf7\xfb%a\x010\x16&\xd7\xfeO\xcd\xdf\x00\x00\x00\xff\xffPK\x07\x084W.\x15\xa5\x00\x00\x00$\x01\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x85\x93\xf9P$\xaf\xb0M\xa2\x00\x00\x00\x1d\x01\x00\x00\x19\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\x00\x00\x00\x00cluster-role-binding.yamlUT\x05\x00\x01\xbay\x1c_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00E\x96\"Q\xe2\xbc\xc6/u\x01\x00\x00{\x05\x00\x00\x11\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\xf2\x00\x00\x00cluster-role.yamlUT\x05\x00\x01c\xe9O_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xc2\xb0\x83QK2\xe1#\xc70\x00\x00\xb6|\x01\x00\x1e\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\xaf\x02\x00\x00crds/minio.min.io_tenants.yamlUT\x05\x00\x01Ma\xc9_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x81-xQ\x8e~}{+\x01\x00\x00\x9d\x02\x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\xcb3\x00\x00deployment.yamlUT\x05\x00\x01\xa3\x9d\xbc_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x85\x93\xf9P\xda!v\x08C\x00\x00\x00@\x00\x00\x00\x0e\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81<5\x00\x00namespace.yamlUT\x05\x00\x01\xbay\x1c_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x85\x93\xf9P\x80\xa45\xf7U\x00\x00\x00Z\x00\x00\x00\x14\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\xc45\x00\x00service-account.yamlUT\x05\x00\x01\xbay\x1c_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xaf\x1c%Q4W.\x15\xa5\x00\x00\x00$\x01\x00\x00\x0c\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81d6\x00\x00service.yamlUT\x05\x00\x01\xfb\x07S_PK\x05\x06\x00\x00\x00\x00\x07\x00\x07\x00\x06\x02\x00\x00L7\x00\x00\x00\x00" + data := "PK\x03\x04\x14\x00\x08\x00\x08\x00IpPQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00 \x00cluster-role-binding.yamlUT\x05\x00\x01\xeb\xa7\x89_|\x8d\xbdN\xc50\x0cF\xf7<\x85_\xa0El(\x1b0\xb0\x17\x89\xddM\\0M\xed\xc8q:\xf0\xf4\xa8Ru\x97\xfb3\x7f\xe7;\x07+\x7f\x915V\x89`3\xa6\x11\xbb\xff\xa8\xf1\x1f:\xab\x8c\xebK\x1bY\x9f\xf6\xe7\xb0\xb2\xe4\x08\xef\xa57'\x9b\xb4\xd0\x1bKf\xf9\x0e\x1b9ft\x8c\x01@p\xa3\x08\x1b\x0b\xeb\xa0\x95\x0c]m\x98O\xd0\xb4\xd0D\xcb\xc1a\xe5\x0f\xd3^\x1f4\x03\xc0U\xf2^\xe10\x87\xd6\xe7_J\xde\x0e\xffp~?\xc9vN\xf4\x9a\x92v\xf1\x00p[p\x19Z\xc5D\x112-\xd8\x8b\x87\xff\x00\x00\x00\xff\xffPK\x07\x08$\xaf\xb0M\xa2\x00\x00\x00\x1d\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00IpPQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00 \x00cluster-role.yamlUT\x05\x00\x01\xeb\xa7\x89_\xcc\x941\x8f\xdb0\x0c\x85\xf7\xfc\n#c\x01'\xe8Vd\xed\xd0\xadC\x87\xee\xb4\xfc.\xc7F\x16U\x8a\xf2\xe1\xfa\xeb\x0b%\x07\x9fl\xd8i\xda\xa9\x99D\xf1E~\xdf\xa3e\x8a\xfc\x1d\x9aX\xc2\xa9\xd1\x8e\xdc\x81\xb2=\x8b\xf2/2\x96p\xb8|J\x07\x96\xe3\xf8qw\xe1\xd0\x9f\x9a\xcf>'\x83~\x13\x8f\xdd\x00\xa3\x9e\x8cN\xbb\xa6 4\xe0\xd4\x0c\x1cXZ\x89P2\xd1V\x8bJ\xb3G*\x92\xb6\xa1\xc8_Tr\xbc\x96\xe5\xd76\xfb\xfdu\xa9H\x92\xd5\xa1\xea\xc4\xe2*\x19\x82\x8d\xe2\xf3\x00\xe7\x89\x87tm\x8f\xd0\xaeR\x9ea\xd3:\xc7\x9e\x0cS\xe99\xd9\xdf?\xba\xc0\xa4H\x0ei\xdaJp\n{\xaf\xa3\xf4uSG\xae\xd5\x18\x11\xec\x8f^_\xc8\xdc\xf3T9\xc5\x8a\xf3[\xd1\xc3\xa3\xea\xddJ'\xde\xc3\x95)m\x11R\x8ci\x8b1\x19\x19\x9e\xb2O5U\x8f\xe8\xe5ux\xc4\xfc=\xbbq\x066\xc7\\\x0ch\"[\x05\xe8\xa6\xbf\xae\x10\xfc\x90\xee\xffp\xb9wP\xe3'vdHo7f\xf3\xdd\x9a\x89\xf9\x1c8\x9c\x15?3\x92\xa5\xfd#\xa2#\xc5\xa82\x92\x7fL]\xc6\x9c\xdfN^\xe4\xb4`\\DU\xa7x\x1f\x7f\x85~\x06\xff\xb5\xdc\xa6w\xf9%w\xd0\x80\"f9z\x9c\xc9\xbd\xb69\\\x82\xbc\x84\xad\xd0\n\x15tu\xda\xb780\x93n9\xbd~\x9e\x0e\x03\x87\xa5\xc5z>\x1fV\xc3\xbamo\x9d\xfao\xe7\xfd\x0e\x00\x00\xff\xffPK\x07\x08\xe2\xbc\xc6/u\x01\x00\x00{\x05\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\xb1E\x84Q\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x00 \x00crds/minio.min.io_tenants.yamlUT\x05\x00\x01/\xf7\xc9_\xec\xbd}s\xe4\xb6\x918\xfc\xbf?E\xd7&U+]4#\xfb\x97\xa7\x9e\xba\xdbK\xc5\xa5h\xd7~T\xfb\xa6Zm\xf6\xaa\x1e\xc7w\x81H\xcc\x0cN$\xc0\x00\xe0h'\xe7\xfb\xee\xbfB\x03\xe0\xcb\x0cI\x00\x94d\xaf\x93\xc1\x1f\xf6\x8a\x034\x81Fw\xa3_\xc1\xaf\x16\x8b\xc5W\xa4b\x9f\xa8TL\xf0\x17@*F?k\xca\xcd_jy\xf7\xafj\xc9\xc4\xf9\xf6\x9b\xaf\xee\x18\xcf_\xc0e\xad\xb4(?P%j\x99\xd1\x97t\xc58\xd3L\xf0\xafJ\xaaIN4y\xf1\x15\x00\xe1\\hb\x1e+\xf3'@&\xb8\x96\xa2(\xa8\\\xac)_\xde\xd5\xb7\xf4\xb6fEN%\x02\xf7\xaf>\xc9\xe9\x96\x16\xa7_\x01d\x92\xe2\xf8\x8f\xac\xa4J\x93\xb2z\x01\xbc.\x8a\xaf\x008)\xe9\x0b\xd0\x94\x13\xae\xd5\xb2d\x9c \xf3\xdf%\x13_\xa9\x8af\xe6}k)\xea\xea\x05\xf4~\xb3\x03\xddt\xecR>\"\x0c|P0\xa5_w\x1e\xbea\xca\xfeP\x15\xb5$E\xf3>|\xa66B\xeaw-\xb4\x85\xfb\xd5\xfe\xc8\xf8\xba.\x88|\xd1>T\x99\xa8\xe8\x0b\xc0\x11\x15\xc9h\xfe\x15\x80[2BX\x00\xc9sD\")\xae%\xe3\x9a\xcaKQ\xd4%o\xe0\xff\xb7\x12\xfc\x9a\xe8\xcd\x0bX*Mt\xad\x96Y-%\xe5\xfaF\x13M\xb1\x93GL\xf7\x89\xde\x99\xf7*-\x19_\x1fB\xf2\x1b\xb6<\xc0u\x0f\xe0\xc5\xba\x0f.\xf7\xf0\xed\xcf\xdbo\xec\xb2\xb3\x0d-\xc9\x0b\xd7ST\x94_\\_}\xfa\xfdM\xef1@NU&Y\xa5q\xb7-\xaa\x81) `\xb6\x8e\xadX\x86\x13\x81\x95\x90@\xe0-\xe3W\xefA:Rk`TRTTj\xe6\xd1o[\x87\x82;O\xf7\xde\xf8\xdcL\xca\xf6\x82\xdc\x90.U\xa07\xd4\xef\x06\xcd\xdd:@\xac@o\x98\x02I+I\x15\xe5\x96\x98{\x80\xc1t\"\x1c\xc4\xed\x7f\xd3L/\xe1\x86J\x03\xc6PG]\xe4\x86\xe2\xb7Tj\x904\x13k\xce\xfe\xde\xc0V\xa0\x05\xbe\xb4 \x9a:*k\x1b\xee>'\x05lIQ\xd33 <\x87\x92\xec@R\xf3\x16\xa8y\x07\x1evQKx+$\x05\xc6W\xe2\x05l\xb4\xae\xd4\x8b\xf3\xf35\xd3\x9es3Q\x965gzw\x8eL\xc8nk-\xa4:GN;Wl\xbd 2\xdb0M3]KzN*\xb6\xc0\xa9s\xe4\xdee\x99\xff\xc6o\x80z\xde\x9b\xeb\x01q\xd9\x86\xac5\xb1\x03\x86\xcb\xdc\x96\xe3P\xbb\x8a\x16\xd1\xe6\x91\xc1\xce\x87W7\x1f\x9b\xbd\xc7\xcd\xd8\xc7>\xe2\xbd\x1d\xa8\xda-0\x08c|E\xa5\xdd\xc4\x95\x14%\xc2\xa4<\xaf\x04\xe3\x1a\xff\xc8\nF\xf9>\xfaU}[2m\xf6\xfdo5U\xda\xec\xd5\x12.Q\x9c\xc1-\x85\xba2\xd4\x9f/\xe1\x8a\xc3%)iqI\x14}\xf2\x0d0\x98V\x0b\x83\xd8\xb8-\xe8J\xe2\xfd\xce\x16k\x9d\x1f\x0cQ\xe6uA\xe5\xc4\xa6YF\xbd\xf1=\xcd\xf6\x19\x0c\x1a\x9eu\xac\xeaX\xb9\x01\xd6\x835\xcc\xb0\xe0E\xc8\xde\xb3\xbdw7o5\xe2\xb3\xc7\xb4f\xb0\xe1\xc1\xe6\xa5\x86\xb1\xcc&)\x94\xb0\xfbM\x8b\xa6\xa7\x9fn%\xf2}\xaa\x1aE* M0I\xf7\xa8{\x81\xf3\x88\xc2\xb4;\x9d\xda6\x84d\x83\xd3Q\xfc\x1e\xc8B\x98DoF\xa5\xbe\x14|\xc5\xd6\x01$_6\x1d\x81\x14\x85\xb8W\x06\x89\x12%\x95\xa2\x1a\xa8![\xaa\xa0`w\x14.EY\nnv\xe3l\x00\xcb\xef\xe5\x9ap\xf6w\x14\x97g@\xb5]\x00\xf2\x9b\x99#Jxz0n| \x80\xca\x83\x7f\xe3\xd0\xaf\x13;f[\xceU\xe7\xb0\xdeoL\xd3r\xe4\xa7 d\xdf\x81HIv\x03\xbf\x8b\x0e2\xc6\xa7\xfft3\x18!D\xb0\n\x99\x12E\x88\xf9.m/K\x1a\xb5\xb4\x87\xb3\x91\xa8B\x1a\xc2@a]WV\xd1:w \x07fi\xba\xaf%\xa96,#\x05\x92\x96=\xe7V$K\xa5\x85\x03\xcd\xf2\xa0CG\x95\x9a\x02\x041\xc8\xed!\xe3je\xe6\xb6e9\xcd\xcf\xcc\"\x0cU+\xda\x9d\x11.\xd4\xe1\x0c\xde\x0f\xa1\xdd\xb7\xb7T\x93\xee\xc8\x89\xad\x1d\xdc>h\xb7\xf0\x86f\x92\xea\xe1%\xf6\x05\x8c9\x0b\x15\xf6\xf6\x0bQ\x86\xdd\x81\xf2-\x93\x82\x97\x94k\xd8\x12\xc9\xc8mAq-#\x93\x7f\xfd\xea\xc6\x02\xc3c\xbc$<'Z\xc8\x1d\xac\x18-\x86$ohOa\xf4$\xf0\xad\xafB\xbcs\x82\xdfH\x15IW\xd4(\xc2\x83\x87\xb013$\xa7\x9a\xe29\x9c\x8bL\x19\"\xcdh\xa5\xd5\xb9\xd8R\xb9e\xf4\xfe\xfc^\xc8;\xc6\xd7\x8b{\xa67\x0b\x8blu\x8e\xb6\xc2\xf9o\xf0\x7f\xa3\xb3\x02\xf8\xf8\xfe\xe5\xfb\x17p\x91\xe7 \xf4\x86JC\x15\xab\xba\xb0\x88P\xcb\x8eNz\x86z\xd1\x19\xd4,\xff\xf6\xf9(\xc0 =\x06(\x82\xf2m\x04\x1d\x8c\xd0q*\x15x:\x1f<\x93|\x9b\x94m\xbdY\xbd\xe2\xdbODv\xd49\xa3[\x0f\xcd \\\x87Q,2\x0e\xc4\xccN\x13\xc6\xa9\\\x8e\xf4\x0b\x93d\x88(\xf7\x16\xd0\xa5\xca\xa1y/\xe1m\xadP\x8b$\x13 \x01.\xff\xeb\xea\xe5\xabw\x1f\xaf\xbe\xbbz\xf5al\xf2\x10C,\xa6\xa1r\x1d\xbd\x84\xe7\x9f<\x8e\x1d[eT\xc1oO>]|\xf8\xafw\x17o_\x9d\x02\x91\x14\xe8\xe7\x8a\xf0|P\xc5j[\xad\xbc\x1e_I\xbae\xa2VNu\xcbG\xe8\x8cq\xd3{\x12f\xe6\xb7\x14\x8d\"\xc2w\xa0\x0c\x0bg#\xa4\xbb4\x84>\x8d\xea\x86\xa4\xb2F\xc37\xd4\\l\x0dgt\xa4KF\xdd\xfc\x80\xf1\xaa\x1e\xa7<\xd3\x9cUs\xcf\x8a\x02\x95Q\x9em\x08_\x1b\x9b\xe1\xe3\x86\xf6\x90\xa9v\\\x93\xcf\xe6\xddp;\xbdr\xaa2R\xd1\x1c\x8c\x88\x02\x02\xb9\xa8\xcd\xa4\x7f\xfb\xdb3`\xf4\x05\xfc\xb6\x03t \xaf\\\xdfv\x07'A\xe3<9\xddRif\xeb\xf7\xf6\x0c$]\x13\x99\x17T)C\xd3\xf7\x1b\x8a\xf2\x0dme\x87\xb4\xe9\x19\x7ff\xc6z\x12\x12\xb8\xd0KxIW\xa4.\xd0\x9c\x82g\xcf\x96\xe3\x120\x85\xac\xbf\x93\xa2\x8c&\xed\x1bkGzet\x88b\x9e+\x0bw\x8a\xe9\xa0k\x0c*\x9a\x03[9\x03\x96)\xb3T\xa0e\xa5wS\x10b\xe4\x0eXj_\xb1\xf5[R\xbd\xa6\xbb\x0ft5\xddy\x7f\xb1\xb40\xa7\x18\x10\xb8\xa3;tS\xc0\xa5\x077\xbd\xba\xf8\xf9\x99vGw\xe1N\x07Z\x08\xc5Y\xa1ia\xa6\x19\x9a\x10\xc4\x12\x85o!\xa9\xed\xdb\x97\xaaT\xb4-U\xbd\x88\x02:\xad\x82\xb4- \xe7\xa2\xb2:w2\xdeo\xd0\xef\xb7\xebI\x98\x86V\x8d\xfc`:\x0eW\x86\xa6Jw\xc0\xba\xa3&b\x9c]\xe4\xad\x10\x05%\xfb\xee\xbd\xfd6l\xff\x1f\xb6\x85\x99K\xa0O@\x91k\x1b\xeeu*\xff?o\x05\x00\x8e\xf7t]\x89\xfc\x05\xa8\xba\xaa\x84\xd4\xaaq\x13-\xf9\x88-\xdfo\xbd\xee\xe8\xc7>k\x9f\x15\xe4\x96\x16\xaa\xf3\xa0c\xdb\x84A\xab\x8afK.r\x8a^\x05\xfb\xa7;\xdb/\xb2L\xd4\\\xbb\x1f\xac\xef{#\x94\xbe\xba\x8e\x00k\xbbW\"\xbf\xba>\xeb\xfd\xa5&\x8f H\x14\x83c\xae\xe7\xe1\xd6\xdb)\xef\x8cv\x1b\xe4\xbc\xcf\xe6\x9f\xdf\x99\x8d\xbb&z\x13\x01\x12\xcc\xe9s/\x99\xd6\x94\xa3\xa6Bei\xce\xed3\xc3 \xed\xc1\xbb\xfd\xe6\xd9\xa3\x0b\xdb\x95\x9ff\xf2\xd2\xcd \xbfnK\xa5\xcd\x91\x10\xa3\x0d\xfa\xe6\x02\x074\x87\x8b\xeb+\xef\xc8\x7f\xe4e\xc6s\xfe*r\xd7\xa2\xf9\xdf[W\xdf=P\x0e4\x9et\x87\xf1F\x99~\x01\x82\x17!q\xd5\xceCA\xc1\xd0Cnt\xf0\xc6K~b\x1f.\xb3\xaa>s\x1d\x96%-\x85\xdc\x85\xb9\xd4u\xa7\xd5\x86\x96T\x92b\xa1\xb4\x90dM\xcf\x1a\xf0\x16l\xf3\x97\x05\x1c\x84\xdb\x9d\xe0!tk\xcb\xb8(Z\xb1\xf3R\x91\xe6\x8f*\x19\x1a,\x8f{\xff\xfa\xad\xbf}\x8d\x11\xebbm\x9e\x0eQ\x8d\xdd\x8a\xa2.i\x84t\x85\xce\xf9\x8c#)\xdf\x1a\xa5W\x85V\ni\\\x02\x90\xb3-SB\xc6,\x94\xf0\xdd\xfb 1\x83\x0d\xae\xe2\x14\x18\xd7tM\xc7\x9c\x11C#\"'=\xa8\x900\x17c\x10\xb5\xaejm\xb0V\x12\xedx'\x02\xa21\x80*\xa1\xd0\x0cs|\xb3'\x8b\xbfy\x16\x01\xa6\"ZS\xc9_\xc0\x7f\x9e\xfc\xe5w?-N\xbf=9\xf9\xe1\xeb\xc5\xbf\xfd\xf8\xbb\x93\xbf,\xf1\x1f\xffr\xfa\xed\xe9O\xfe\x8f\xdf\x9d\x9e\x9e\x9c\xfc\xf0\xfa\xed\xf7\x1f\xaf_\xfd\xc8N\x7f\xfa\x81\xd7\xe5\x9d\xfd\xeb\xa7\x93\x1f\xe8\xab\x1f#\x81\x9c\x9e~\xfb\xdb\x88\xc9}^\xb4\x9a\xf0\x82q\xbd\x10raQ\xfe\x02\xb4\xac\xc3h\xf2\xa8\x89\xa1\x82>_|\xf0\xf2\xb8\x13 \xf4g\xc7#\x13u\xbc\xe8\x9f\xf4\x83\xb5-Z\xf2[O\xed\xe3X\x7f\xce\xeb\xeb\x9c\x18\x95\xc8\x9f\x87\x95\xeaF\xcd{Dy\xf8\x10\x83\xd1\xabHv)\xad\xae\xb0\x92\xa2\\\x02:\xd7\"@\x03:\xe0\x8c\xcd\xcer\x0f\xeb\x8eNZ\xec\xbe%P\xcd\xd1\x08\x0d\xb4/\xdf\x08\xb5a\x15g\x81FXt\xb6\xfd\xc3Y\xa0\x11\xddB\xb3\x1a\x88\x90\xb7-\x08\x7f:\xc2J?\xdbt\x99KrI\xa5\x8e\x0e\x85\xbd\x1a\x18\xe6#\xdf\xc4\x06(\xb5\xf0Q\x92NHqd\x11\x97\x17\xdd\xe8\xb6Z6\xd11t\x11v\x83\x82Z\x18\x13\xc5\xd0\xda\xc777F=\xe44\x1b\x0f\x00\x82\xf5\xf8Z\xbe#UU\xb8\xfc(5,\xae\xe2\x83-oDF\x8a\xcbv\xca\x1f\x1a?w7\xc1\xc2\xe7\x1f\x8c\x92\x07\x81\xc2\x00\x9a\x0c\xed\xdb\x16sH\x84Df\x94,\xc0N\x0f\x03\xf2E\xd0\xf3,j\x8e\xa1e\xde\xbccd\x05\x9d\xcdD\x1b\xaa\x92lk\xfemN\xc9C\xc2\xa6\x9c\xdc\x16\x8c\xaf\x91\x9e\x0f2\xe4|\xf3\xe4o\xe0m\x8820\x85dz\x07\xe6\xac\x82\x8bZ\x0b3\xf7a\xaa\x0e\x93\xce4\xe1D\xec\xf84\xd1\x04\x01L\x13\xcc\x04\xb9\x04\x88\x85\x95d=2\xaf~@\xd7\xf4\xebq\xaeK\x17\xf2h\x7f)\xb2;*-\xbca$\x07\xd6\x88#\xaf\xeb\xa2\xb8\x16\x05\xcbFt\xb8\x819UuQ@\x85c\x96\xf0\x9e\xa3nsQ\xdc\x93\x9d:\x83wtK\xe5\x19\\\xad\xde }mC\xbacZX\x93l`D EG\x91\xcd\x0d\xf5\x0b\xacD\xae\xd0\x8f\xb1\x04\x14e\xf0\xba\xd1\x8f\xc6\xc4\xa1\xc8\xea\xd2\xe7u\"%\xe7T\x13V\xa8(\x15\xab\xb1\xeb\xd59\xa2F\xfd\x063\x03\x8d\xb2e\xff\x9e\x83d\xebC\x1d\xc6\xed\xcf\x9e\xd5b'\x93\x98\xd0b\x07\xcd!u.rj\xed\x961\xf7\xc1\xcf\x8e\x81\xee\x94\x12\xf1\xd0\x1d:\x07\x1b\x92\xe2Q?\xb2\xbe\xde\xe4?\xb8\xae\x0d\xfb\xf3\xba\xbc\xa5\xd20\x1a2\x85\x99\xf8\xebW76-|U\x177t\x84\xcb\xac\x8b\x03\xfd,\xbf\xff?\x13\x93\x1e\xf7\xc34\xae\x8e\x88i\x8f\xe0\xbcq(\x9a\x83\x02\x1d\x83\xb8\x80\xac\xaa\xcf'\xbd~\x8d\x1b\xc0\x9c{\xd9P\xae\xb6m\xe1\xb3\xc4z#\xc7\x0f\x83\x142\x84\x18?W\xbc\x7f+\xda\xaf\xf5E\xba\x8df\xbb\x8b\xfa\x16\xf2\x1b\xeb}\xb6\x0fo\xddqW\x92\xcf\xac\xacK \xa5\xa89\xba\xe92QV\xf5\xa86\n=\x876\xeaJ4O\xb6\xb3\xb3nV\xe4yI8Y\xd3\x85{\xf1\xa2\x01\xbfh\xce\x8a\xf3P\xe2W\xd0\xca2\xacq$\xcd/\x954?x\xe1\xb5G\x9c\x8c?\x808\xbdn\x89\xd9L\xcd\x1b\x98\x02Q2\xad\x9d\x12N\xda@\xc3\x94\xfb\x85\xe9\x9e\x0f\xda\xb1\x12[\x81\xde\x10,\xc3\xa1\x9f\xcda\xc20\x1e\xe2\xc3jg\xd6\xfc\xbcgjj\xc2Z\x18\xcb\x82\x95UA\x1b\xadj\xe13\xbelV\xcd\x97\xcc^\x81\x0e\x87\xb1\xe8\x88#\xee\xe6`\x90\xcf\xeb\xe7\x1d/_\xbf\xd7\xc8\n\xb4\xb0g\xa4\x00Ys\xa7\xec\xae0u\xd7\xeb$\xd7\xe6\x19\xd6q\xd1\x1c\x881\xfc*\"\x0d\xb1\x8dA4\x1a\xb5\xb5\x12f\x18\x04\xe3\x06\xcf\xa2\x9f\x95|\xf0\xfb\x04\xa23Is5f\xf3\x86\x94\x876\xb3\x99X\x1c\x1bh\x94kF\x9c\x12\xdb\xa9\xf5\xeb\xb7Fux\xef\xc9\xdc\xd9\x16\n\x8b\x89\x1cR\x15\xe4;NJ\x96\xf5\x00WX\xac7\xe4\xe5\x13\xbc\x0fEi\"u]\xc1-\xe1|@\x92N\xeb%\xe3\xf6\xed\x97\xe8=N\xf5\x17O\xf8\x82'\x89p\x82\x94\x06\xf3\xa0C$4\x99\x03\x1d\xa6\x9f\x83\x9fF\xbdq}\xdfMj\xda3\xb0a\xd56\x90\xf2\x1c\xd2|\xa7|(\xbd '\xa49G\xa52\x07\x15\x87\xc9\x14\xe6>\x03\xa4\xa4/\xdb\x14\xe5\xf1##5u\xb9=\x82Ga&\xa4-\xef\xa7&\x8f\xc2\x8cLY\x1eOK\x1e\x85<\x99\xae<\x9d\x92<\n3\x94\xaa\x1c\x91\x8e<\n{$Myf*r\x1cYN\xa5 \xf7\x95\x81\x84\xf4c\x97b<\xb5\xe5\xe9\xa9\xc7!\xfe\x87\xb4\x94\xe3P\xc09*\xdd8fN\x10\x175\x1e\x8c\x18G\xa7\x18\x077\xdb\xb7P\x88\x02\xbe\xd03\xb9m\x8fx:\xb7-\x1a\x7f\xb1\x11\xda`tv?E8\"\xe0\x99\x1a\x9c\xb5\x8b\n\x07fC\xe1\"\x88\x08\xc8\x06\x0d\x14\x88L\x05\xee\x13\xdfc\xa7\x01?Q\n\xf0\x13\xa4\xff\xceM\xfd\x8d\x15I\xf1)\xbf\xbd\x1d\x89H\xf7\x85\x83\x8b\x0e\x0e\xdb\xa3\xa4\xfaF3mt\x8aoo\xa9\xe1\xf4\xde\xd6\xc7\x10\\pBjo\xe4\xb2\xe2\xb86&\x9d7\x8awS\xd2x\xc7x\xf8!)\xbcO\x93\xbe\xfb\x14\xa9\xbbO\x91\xb6\x1b\xcb\xd5I\xe9\xba\xfdmz\x9cT\xddYi\xba\x91\x14\x1f\x9d\x9e\x1b\xf4\x0bC\x92o\x18R\xfc\xc30|\xf8O\xa5\xe3\xfaT\xdb rg\xa7\xe2~\x91Nkx\x88\xe3\x1a\x12\xd2o\x0f\x9d\xdcsSo#i N4G\xa4\xdbFI\xe6\xd84\xdb\x90\xc53\x90b\x1b\x95B\x1b+\x9b\xe6\x1aA\x8f\x916;+e6r\xb7\x8fF\xd5H\x8b\xc6\xdf\xa3\x19U\x07)\xafh1\x05W\xffk\xb5\xa8\x82I\x18\xe3\xb3\x18\xcd\xe9\x9a\x84i\x7f\x1cJ\xfd\x8bKc\xed;\x8e\x1f/\x855\x9c\xbejc\x19)\xc9\xab\xd1\x89\xabqn\xf2\xb4\x84U\x9f\x98:\xb8\xf1\xd3\xc9\xaa!q<%\xac\x82\x1c\x8b\x1d\xe6\x0d\xfeE\xa81\x99\x16#(Qpj$L)\xe4\xd0\x8c\x91\xb0:\xb4\xb8\x9f\x81:D\x9c\xdd\x14\xd41J\xbcyw\xe5m\x85\xfd\xd8\xdc\x91$g\x0e\xfeEH\x12/mL'\xcc\xbda\x87\xe4\xa9\xdcy\x98\xe1\xf5\xb6#B\x12\xa1tw\xeb,\"C\xda\x88\xdeA\xfc\x1d\x82S-mb@\x7f\xb1\xf8c\x0b\xe7\xf5\xab\x1b \xb5\xdeP\xae\x9d4=\xa4\xdc\xb9q\xe4\xc0N\x8f\x13\xc9\xe4\xc0\xa94\x81A\xf2\x98 \x8e\x91\\\xe8~Pw,\x0fz:\xffyb\x0d\xc1\xbc\xe7\x81\xf7?B\xce\xf3h\xbe\xf3D\x9es?\xa3y\x00\xe8\xd3\xe78\xc7 2\x8am\xaf\xfa\xbd\xfb\x02\xb51d|\x1c\xcc,\xac\xb2wC\xef7|\xad\xbd\xff\x954l:M\x0dsY\xe8K\xb4P\x1e\xd1.\x99d\xf4 \xbe\xbd\x1b\xc2c\x0fWF\xae\x8d])yg4\x00\xe5\x88\xff\xf5\xdb\xc3\xe3\xfd\xd7~Y\xa4Y|8\x9f\xfc\xa1\x17E\x06\x0fM\xd8\x9f~\xfc\x81I\xc6\x8fL\xd3\xa4\x10{'\xe6\xe1\xb1\x87\x87\xa8{\xdc=K\xc7\xa8z\xf8\x84\x1d;O\x0d\x8a\xfdA:\x02q\xf8x\x05\xb2&\x8c+\x0d\x9fH]\xa0Yl\xb9\xe8\xf5\xdb\x1b\x9b1\xe9Ch#P\xcb\x8fon\x8e%M\xfd\x16cZ\xc0\x1c\xf3\"\xa8\xbf\xc1\x81\xa1{\xa0\xbc\x81\xbd\xa7V\xd4\x95\xaf\xc0@2\xb8\xb9ys\xdc\xc6~{pe\x9a\xe1\xb6\x7f\xc0\xaa4\xb3\xac\x87\xe8h\xf0\xb3\xe8i\x10F\xed\x1d\x1dM\xc5\x85CO3S\xed\x00kU\xab&\x0f\xb7wu\xb4\x13\xb4!\x84\x1e\xef\x14~\x1c\xa5\x0d\xc2\x1b\x1dd\xf5/\xb5*\xb1\xd5\x9cPG\x1ay\xeb?vEb\x9c\xf6\xf8\xcfY\x8d\xf8\xe5\xd6l\x18\x04\x8c\xd6k\x0c}\xe9\xc4\xb7'\xa9\xd7h\x04\xf7\xc1o\x13dQ\x88\xd0\x17%\xde\x88\xb5\xfb\xa0\x84'\x85\xfeIP\x11IJ\xaa\xa9\xb4D\xf1F\xacaE\x89\xae\x07\xbc\xc2\x01\x1b\xaf\xceY\xcc)ua\xfa\xb9)mD\x91\xefO\x08\x0d \xd3\xc7,\xce~3f\x8c\xa9\x8c5:\xf8[\xf8H\xca\x99\xba\xbb$\x15\xc9\x98\xde}\xff\xa7\xc8\xc3\xe9eoPO\x9d2\xf0 s\xbf\x01\xe3\xf0\xfd\x9fFa\x02\x90-a\x05&E\x1b\x8dY\x9b\xc3\xad]\xf2\xe8\xb8\x10\xa7\x05\x05\xc8|m\xd1~B\xeb\xb92\xf4qC\x89\xcc6\x17\xd7W\xc1L\xfb\xb9\x1a\xe5\xc42\xb0vo8\x07\xae\xb7\x84\xb7X\xe3W\x11\xbd\xe9\xc4\xcdl\xfa\x0f\x9c\\\x7f:\xed\xe7\x9f\x9f\xd3\xcf\xc6\x80\x1c\x99\xc8\xe0,+\x91\xbf\xc5R8\xa3FFy%\xafE\x0e\xed\x10\xb0c\xac\xd3L\xe4\x8d\x0c\xba\xddu\x85r\xda\x8c\xc4\x90~\xd0\xa7\xe0\xe63q\xf8\xe2\xcb\xa2V\x1a?\x02\x02k\xb6\xa5\xde\xe7\x9d\xd9\xc7\x07\xa0\xe2\xe21\xd7B\x14c\xa1\x17\xefS\x17CN\xc2\x10\xd7\x92\x15N~4\xfdb\xff\xe8\xee\x94N\xfa\xa1\xb6\xae\xc1N\xae\x93\x1f\xe2\xbeG4\x15\xe0\xcf\x04WZ\x12\xc6G\xdd\x0c\xa1\xe9\x83Sf.\x02\xcb\x80\xc3MS\xae\x8c\xd5\x0co\xd7\xd2\xce\x1ad=\xfd\x8d\x08\xdb\xdc\x82\x1f\xa3\x14\xa0B\xdd\\\xd2\xfcemH\xf1\xa6\x99\xca\xd5\x9a\x8b\xe6\xf1\xab\xcf4\xabq\x11\x93\xc0\x0e\xec\x18\xda\xf9\x96\x14\xee\x98}\x1dt?\x1d5\xf8\xcd\xa8\xfd\xa6\x05\xe2L9?\x11\xd1L\xadv\x88\x87\x06\x8b\xf4s%\xa9\xc2o\x00&$\xc2\xde\xee\xdc'\xcd\x8c5p\x06\xb7\xb5\x06\xa6\xf1{g\xd9F\x08E\xc1\xaa{\xf6\xbd[&\xf0\x1bsA\xa8\x9d\x98l'\xa9\xceO\xcf~\xb9\xa0\x05\xcb\x14\x94\"\"/\xa4\xd9+\xafC\x99\xd7`4\xd6\xfc\xb1\xb6u\x95\x1aT]b\xed\x0ee\xeb\x8d\x8e\xc8\x91dK\xba\xb4q_\x92m:\xd3*)\xd5\xf6{6\x9d\xec\xea\x00w\xf9\xe6\x14\xa4\x12\x0b\xf0N\x9a\xcc6\x97\x87z\xd6(P\xfbT\x17\x04<\xb4\xdd\xf8Y\xac\xe5\xe9\x99\xaf\x03\x07\x828\xb8\xdd\x19A'\xd1r\x0f\xc2\xd5\x1b)\xea\xb5\xc5$-\xdc\xc4\xfdG\x0bm\xba5V\x9bY\xcf\xe83\x8b\xdcP\x9e#\xd2-b\xae.mY\xb8\xdb\xf6\x92\xe8lC\xbdA/%U\x95\xe0\x08\x19\x7fy\xd5\xae\xed\xdf\xc3\xafp@O\xd4iK\x0c\x1b\xb6\xdexZ \xd2\x8aHCc-\x0d\x85\xb2\xcd&\xef>k[_%\xe4\xb6f\xaaC\xa9\x1d\xd9\xa6\xa9,\xfd\xca\x83p\xc1\x12\x9e\xb5\xf4\xed\xbaXi\x8b\xe9\x1de\xc3\xd7p\x82\xa4\xcb\x8c>3\xfd]\x12\xdb\xb8X\x88\xeat \x17\xf8\xe5\xd3G\x99$\x17\xcd\x1c\xddd\x0c\xc7(\x81b\x03\xdf\x16\x04\x12+\xa9}o\x9f\x15\x11\xd3{\x7f\x7f,\xf5)o\xf2\x9a\xc5\x9e\x01QJd\x8c\x0c\xd7]\x0f\xb5\x86\xca\xfa\xa4k\xb7%\xbc`H^\xb4i\xfb\x8c\x11;\xee\x00\x05\x05Sh\x17\xf6Q\xd1\x15X\xd1\x90\xf1\xf80p\x9e+\xe7\x18\x89[=\xc4\xf3W\xdb&w\xb23\xfd\x04\x90\xe0\xbe\x1b\xda\xd0\x83\x11\xfb\xce\x18p\xc5\x93\xea,\x8a\xb5\xdavGwg\xae0\x17\xcc\x1e\x93\x06\xb0\xa4xxB\xec\x8d\xcf\xbe\xdd\xd1\x1d\x02t_gM\x18\x9bNe\xb6E\xa4\x06\xef\xb7\x03\xc5\x07\xe9\xc1VM\x9a\xc5\xa7.\x1a\xd0\xe3\xe2\xf6\xc5:\xc4\xf1\xdb\xa9\x89@\x82n\xb2\xb1\xe6\xb7\xeeAx\xf8\xd0)\xc27\xa8x\xae,\x11\x18\xfe\xdd\xb0*\x11\xb4\xbd\x14\x05\xbf\x9f)V\xcd\xb7z?a\x16\xb5\x9fn\n\xef\xdafN\xc7+~\x06\xef\x846\xff{\x85\xc5\xcdg\xf0RP\xf5Nh\xfc3\x15\xe9\x00\xdfk\xcb\x03o\x92\xc7\xce\xde0\x8b\x8f\x07m\xd7\x05\xb7\xa9b\x06\xbdv\x063x\xce\xb6+\xab\xec4\x02\x80)\xb8\xe2F%vh\x9e\xc3\x0ev.n\x8a\xbe\xf4\x94\x0b\xbe\xb0u\xdap5v7\xcbx\xdb\x9f\xe3\xab\xa6\xb4\xbd\xbb\xffa\x15z\xbfi\xac\x97\x1f\x98\xee\xe3M\xf5{\x0c\xa0\xbf\xd1g\x9d\x97%\x03\xedLnC\xb6\xa883\xbe.\x1a\x158}\xe5\xf7\x1b\x96m\x9a[\x11\xf0\xa3\xa4\x95\xa4\xde)\xcb\xbd\xd7+\x9d\xa20\x96e\xe7k?#^\x90\x8c\xe6\x90\xa3\x01a?~M4]\xb3,\x19rI\xe5\x9aBe\xf4\x8b\xd4i%\x1f\xe2\xb6\xcdfr?t\xec\xb6\xdb\xb1\x16S\x00\xb0\xdfB\x05\x01\xfbm\xd1\x90g\xc2\xa0\x80\xa3s\xb8\xa5\xe3\x00\x95G,\x15M\xd8\xad\x9fGota\xc8\xe8\xb1\xc9$w\xd4\x1b\x93\xcf\xb0\xa3\xde8[B\x1d\xf5\xc6\xa3\xdex\xd4\x1b\x8fzc\x08\xc2~;\xea\x8d\x11m6\x93\xcf\xd1\x99\xe0\x9f^oL|\x89\xf5\x7f\xc6\xa1\xaa'?\xff\xc3\xfa\xb3[?\xac\xf5\xb0\xa2\xd2\xea\xbe\xfa\x1d\x05\x14\xf6\x1c\xb2\xdd<\xa5\x8f\xe8\xeau\xc5\xf4\x92\xf0u,\xc8o\x16\xdf|\xfdu\x1c}\x87s\x8c\xf6[8\x13\xa2\xdb\xe2\xa9q\xd1\xf1\x93Gt\xb6;\x17\xec\x98@\x0f\xb1\xa46\x16\x07{\x84\xe8\xab;J\x9b\x80Y/$73@\x8aZ\x0f\x17\x1aJ\xaa\x81\xe8^\xe0\x84\x954\xee|\xaeD\xee\xae%\xb4\x9f\xfd\xf6\x91\xe0\x1c\x04w\xf12C\xb9\xcb\xfd\x15\x04\x01\x0f\xafpo\x05\x19%6\x8b\xec\x96\x9aU\x04\x81\x9aU\x8a\x92B%\x18\xd7\xfe\xd80K\xa0~W\xe0\x84.\xd7K\xc8kjom\x0e\x82\xc4tbzjO`\xb5S\x9a\x96\x18q\x16\x12\xffg\xd0\xa2%\xde\xb6G\xb7\x94\xeb\x9a\x14\x11\xdf\x13\xa5[\x96\xa1\xb9\x80\x93\xc3\n-\xa6m\xa6A\x88{S\xcc\x9d}\x99\x121\xe4@\xb9\xf7\x17p\x8f\xd9\xd4x\x05Wh\xd2\xb6}\xc4\x9c&Y*\xa4\xcc\xf7\x1f\xc2qMH;~\xf7\xad\xe7\xba(\xcc>\xd90\xe7\xe1\xb4\xa3`B\x13\xffm\xc3\x876'\xa0G\xc16\xea\x1e\x0b\xd2\xac\xff\xe2\xddK\x83W\x03\xe9\xa3\xa8D!\xd6\xbb\xee^\xa1Tj\xef\x14\x8fU\xfb\x08\xa8\xfa\xd6YO\x86\xbe\xde\xed\x91@\x0c\xc6\xd3\x88\xcc\xb6c\xc4\xef\xe8\xb9I\xb5\"\xd3\xa9\xcc\xb6\xa3\xe7\xe6\xe8\xb99zn\x8e\x9e\x9b\xa3\xe7&\x19\xe2\xd1s\x13\xd1f3y\xbc)\xd9o\xf1\xb6r\xdb\xfeq<7\xc7\x88\xdfQoL\xc0\xf0Qo|\x80\x84:\xea\x8dG\xbd\xf1\xa87\x1e\xf5\xc6\x10\x84\xfdv\xd4\x1b#\xdal&\x9f\xa33\xc1?\xbd\xde\x98\xf8\x92x\xf0\xb1h]\x1c:\xd8\x03#\"\xa7\x1c\xd5\xad\x12\xf9\x03\x8a\x1a+\x91O\xd44b\x90dr-\x99X\xe0\xb7\x86\xdd\xe7\x07\x0d8\xff]\x0bR\xda\x98\xd0\x19\xfc]pj\xeb\xbd\x8c\x98Pb\xe4\xba\x1d\xdf\xec\x8d\x1f\x95\xc8O\xd4\xe9d-N\xac\x02x\xac\x97<\xd6K\x1e\xeb%\x7f\xeez\xc9\x0dQ\xf6\xc6\x0f\xab4t\xca'\x83\x10\xfb)\x11\x1d g\x84\xeb\xbf7\xaf\xe8VO\x06a\xfe2\xd5\x95\x86 \x1c\x91\xfa\x9bO\x1c\xa1Y|\xe4.\x91\x84\xe6\xd7\xfdU\x06_\xe3>Id\x83\xa8$\xcfi\x0e\x15\x95\x0bK\xda\x02V\x8c\xe7\x03k\x8c\x00\xeb0\x1b\xec\x19+}]\xef\xfe\xf2b\x86L\xc4\xa0{\xc7\xd6\xaf\xa9\"\x12\xfd\x06\xd37*\x0d\xb5}'\x17z\x1f\xfeVS\xb9\x03\xb1\xa5\xb2\xb5\x9b\xdb\xcf\xbbD\xc3\x06{b3\x05\x19Q\xf6\xa8\x8a[=\xcc\xc2\x00<(J\x0c\xfb\xc8\xd8\x07e}^\x05\x8b8j\xfaM\xac\x1cZ\x07\x9d\x86x\x9c%B\xec\x9d\x0fm\xa8? J\xa4\xcc\xe9\xb7Ajy\xb03\x11\xe2\x1c\x8a\xc90I\xd8\xa9\x98\x0cS\xbb\xef\xbe\xccs,\xc2l\xc2\xb6m\x86\x83\x11\xf6\xb7\xcd\xcc\xdei@\x8d\xafq\x06Lh\xfc\x93\x8f\xe1o\x84\x87Y\xb7\xf3\xfd\x8e\xb0\x8f\x9e\x86L\xdaoF\xcf\x00 \x83\x8e\xcb\xc6\x119\x0b\xe2\xb8\xf3\xd2\xc8\x80Y \x0f\x1c\x98H\xd7\x0f\xf3a>p#\xe7\xf9#a\x7f\x1b\x9d\x17\x8d\xa1\xf3(\xc6&\x1fn\x07\x1e\xcd}\x0f\xe5,\xa8\x03^\xcd\x9e\xdbo\x16\xd0A\xcf\xe6\xa3\xccu\xc4\xbb\x19\xa5\x1c\x0f\xb5)\x0f\xe7\xc7\xf1\xfb\xf9\xa6\xdb\x93\xb8\xf8\xe0an>\x98{\xce\xda\xf6 >J\xf1G\xed\xb7X\xff\xd4~Ku\xfd\xc1\\\xf7\x1f\xc4\xfa\xb0\x86\xda<\xbc\xa0:\xf8f\xe2\xb6\xd6\xb1\x96r\x8f\xe9X\x9bM \x87\x1a\xad]\x02\xb8{\x80+#\xe1\xfe\xc7\xa8I\xc8\x94\xff\x9b\x04\x1c\xa0\"L*c69\xf7\x7f\x07\x92\xf7\xd6u^\x9a\x08\xdc\xcc\x8e)0\xb4\xb8%\x05\xe5\xda&T{\x07\x83\x99\xf9\xbe\x8e\x9e\xaa#\xdeo\x84rw\x93\xa3\x93\x82)xvGw\xcf\xce\x1e\"7\x0d\x90+\xfe\xcc*\x9e\x07\x11\x1d\xaf\xd5&\x02\x15\xbc\xd8\xc13\x84\xf4l ;x\xa6\x110\x8b\x87f\x0cj\xbe\xd4\x98@\xf9=\xd2m\x014\xdeI\xef\xfei\x7f\x8a\x06\x0d\xad\xf6{s\xa8\xbb\xc2\x89\xf7(\xb9/\x14\x9c\x86\xaf\xddj[?'\x1c\x93FJJ\xb8\x82g\xde\x8f\xdd\xfdre\xd8\x07\xe6[\xf292Kf\xa4\xcbF\xedR\xcb_\xa7\x98&{\x9e,\xe7\xdfW\x1bQ\x17\xb9Q\x06\x1a\xe7\x7f\xac\xcb\xc5\xb4\x13\xef\xb795\xf8\xe7Bw\xc0\xc0 \xe1\x9a-\x9a\x1e `\x1bo\x0e\xba\x1c\xbbeX}\nJ\x00\xb9\xff\x81\xee\x0e\x0d\x9f\xc1\xfd\x86\xca\x99\x18`\xfefh\x8c\x9a\xca\x9as3S\xc1\xbd\x1b\xde\x8a;\x14\" P\x9d[\xd1\x1a\x8b\x88\x0d\xccNi\xf7=\xe1\x864\xdf\xd0v\x14+ \xdc\xd5M\x08\xee\xd8\xd9\xaaj0\x9b\x84\x01\xdc#\xd6\xac} \xaf\x90\x0d\xbb\x93e\xca\xd0F\x02L\xfc\x18F\x8adM\xe6\xbc4}k\xd1]N\xd4\x88D\x89=\xbbt\xf1\xfe\x89J\x17\xf7\\\xbc\xffT\x95\x8b\x89\xce\xfbc\xf9\xe2T;\x96/&\x96/\x06!\x9a\xc1\xf6d\x88\xaec\x0c\xc2l\xeb\x1c'\xeb\x18\xe1?6\x14\xe5@\x84\xf3\xcbluY\x17\x9aUm\x92\x92\xb2S-\xacsc\xe5B\xe4=\xc9\x13\x84\xab\x85\x8d\xfb\xee\xb1)\xbe\x0f\x93\x98\x14\x9e`g6LL\x06\xbf\xa2\xb7\x07\x11\xeb\x17\xbdW\xc4\xc6\xeaY\xf8\xf4\x89T\x0f\xf7\x925\xecm\xdeM\x8c\x07O\xcf\x13\xa3\x8c\x14\x86\xcc\x8c\xb2\xe0ew\x10\xf2\x90Nm}\x9f[\xea\x03\xb9\xf66\xf2F\xd99Q\xa71\x8a\x98\xf33O(\x89}\xd5/\x02\xe4\xb4r\x88\xa7\xd6,E,A\x01sJN\x04\xd0=\xc5\xeb\x0f\x9d\xd3\xff\x8f\x9d\xe0w\xa3PE\x80\xdcS\xb9\x10\xb1\x8d\xd2\xd5\x92B\xabH\x05a\xa6E5f\x04+\x9f.P93H\x99\xb6bxPp220 \"%?4\x14\x94\x9c[\xdb0\xc3\x17\x11)\xbd\xda\xf64\x81\xc8\x88 d\xc4\x91\xd8m\xc1\x00d\xa4\x0ch\xdb\xfc\xe0c:\xc1\xda6#\xe8\x18\x0c8\"\x0e\x12\x81\xc2c\x05\x1b\x93\xed3\xdf\xe6\x06\x19C\x01F\x1f,L\x04\x0b\xc3\xc1\xc5\x83@a2\xd8^`q8H\x98\x0c\xf3!A\xc5\xd9\x1b6/\x98\x18\x08$\xb6A\xc1D\xb80\x16D\xdc\x0f\x08&\xc3=\xf02\x1f\x06\x03\x93a\x0e\xcc\xf1\xe7*s\x98\x15\x04|\x92\x00\xe0\x03\x82\x7f\xc9g\x9am\xb3i=\xdeN\xef\xb7xoD\xdbR\x03}\xb3\x82| \x1e\x8a\xb6\xa5\xe3`V`\xef\xa1A\xbdY\xbb\xfc\x84\xc1\xbc'\x0b\xe4=q\x10/.\x80\x07I\xe2$\"x\x87\xe1\xb8\x14\x90\x8f\x19\xb8K\xe6\x8b\xc4\x01\xa9\xc1\xba'\x0b\xd4=M\x90\xee)\x02tI\xb2>\x99\xf7\xd3dZr@.>\x18\xd7\xf1\xb3DA\x86p \xae\x1f^\x8b\x84:\x1e\x84;\x08\xadEB\x9c\n\xc0\x0d{u\"\x01O\xf9~\xf6<;\x91\x10\x07\x02o\xe3\xe1\xb4H\x98\x03A\xb7\x88PZ$p\x1bpK\x0b\xa3%\xf1H\xbc\x06\x93\x16:K\x90\x9bq,\x1a\x05\xb0\x12\xf9\x05\xd7\xec\xa1\xa5w].;\xa8\xbf\x9b\\\x8d\x8d\x00\x90\xad`9T\xb5\xd6\x96\xd1\"j\xf0&\xa1\xba\xfa\xbcc\x0d\xdea\x0d^o\xab:\x95YA\x98#a\xa1\xf1B\xbc \xc4^\xa1^L!^\x10\xe2A\xa1^d!^\x10\xf0^\xa1^\xb8\x10/\x08\xf1\xa0P/T\x88\x17\x848\x16\x11\x1d\xdf\xf30\xcc`\xb5\xde`5^\x10l\xb0Z\xef\xb0\x1a/\x083P\xad\x17\xa8\xc6\x0b\x82\xd7_\xce\xb7\x0e\x8f\xd5x\xbe\xf7\xb1\x1a\x0f\xe6\x05\xb8\xe0I\x83\\0?\xd0\x05\xb30\x00\x0f\nxA|\xd0+ \xe6\xb1\x1a/\xaaE\x04\xc2\x92a\x1e\xab\xf1\\\x0b\x06\xc7f\xc0\x8a\xf5\x10\x0d\xb5x\xf7V\xbf\xa5\x06\xe9`n\xa0\x0eb][Cm\x1e^f\x05\xed\xe0\x11\x02w\xf0\x10Jx\xc2\x00\x1e\x90\x07\xd1\xc1\xbcD\xa0\xc7j\xbc\x83\x96\x1a\xe0\x83\xa7\x0c\xf2\xc1\x93\x05\xfa\xe0\x89\x82}0\xe7\x1c\x99%3\xd2ecr\xf0\x0f\x92\x02\x80\xd1 \x8f\xd5xI\xc9\xe0 P\x8f\xd5x aD\x98\xc3yi\xfaVZH\x11\xd2%\xf6\xb1\x1a\xefX\x8dw\xd85|(\xfc\x0c\xd5x\xbd \xd6\xaf\xb7$\xaf\xbb\x8c \xf4c]\xde\xb1.\xefX\x97\x07p\xac\xcb;\xd6\xe5\xc1\x93\x86,g\x86+\xd3V\x0c\x0f\nSF\x86(\x8fuy\x0f\x0bIF\x84##\x8e\xc4n\x0b\x86\"#e@\xdb\xe6\x87!\xd3 \xd6\xb6\x19\xe1\xc7`\xe8\xf1X\x97w\xac\xcb\x8bo\xb37l^X\xf1X\x97\x07\xc7\xba<\xdb\x1e\x10\x06L>\xd3l\x9bM\xeb\xf1\x16{\xbf\xc5\xfb%\xda\x96\x1a\xf2\x9b\x15\xeeK\xf0U\xb4-\x1d\x07\xb3B|\x0f\x0d\xef\xcd\xda\xe5'\x0c\xeb=YH\xef\x89\xc3yq\xa1\xbcc]^\xca\x80\xd4\xb0\xdd\x93\x85\xec\x9e&\\\xf7\x14\xa1\xba$Y\x9f\xcc\xfbi2-94\x17\x1f\x96;\xd6\xe5\x1d\xeb\xf2R\xa3P\xc7\xba\xbc\xfd^\x93\x00\x83]\x0c\xa5\x8e-\xb4\xc7\xc9\xefH\xd9\x10Z%\xc4\x98\xe79\x88i\xde\xf94\xe0\xd8\x8b\xd3\xd4\xa1\xe0+\xf7V\xf2\xfc]g\n{N\x1aW\xec\xe3\xec\x07-'b\xdc+t\xbd\xd8H\x02V\xb4\xe8\x96;\x97p3\x00\x11\xd9k\xc2\xe3cF>\x7f\xae,\x1f\xab\xfd\x17\xec\x85\x84,\x93\xda\x97\xbd\x15\x131\x0b\xc6W\xe2\x05l\xb4\xae\xd4\x8b\xf3\xf3\xbb\xfa\x96JN5UK&\xces\x91\xa9\xf3L\xf0\x8cV\x1a\xff\xb1b\xebZ\xa2\x0f\xe0\x9c(\xc5\xd6|Q\x89\x1c\xabv\xce\x9f\xcf%\xb1\xc6\x83\x1aEgW+\xa8\xa4\xd8\xb2\x9c\xe6gP+\xac\x84RM\xed\x9a\xcd-.X\xc94\xe2'\xab\xea\xf3\x92\x96B\x8e\xf3IS\xfef$F\x86k\x1b\xe9\x1b\xe3\xd1\xc2WO\x9e\xcdi\xc4\x0bV\\\xbe_MwY$D\x87\x171\x1ca[E\xb4\xa6\x92\xbf\x80\xff<\xf9\xcb\xef~Z\x9c~{r\xf2\xc3\xd7\x8b\x7f\xfb\xf1w'\x7fY\xe2?\xfe\xe5\xf4\xdb\xd3\x9f\xfc\x1f\xbf;==9\xf9\xe1\xf5\xdb\xef?^\xbf\xfa\x91\x9d\xfe\xf4\x03\xaf\xcb;\xfb\xd7O'?\xd0W?F\x029=\xfd\xf6\xb7\x93\xd3\xfa\xbch\xc9t\xc1\xb8^\x08\xb9\xb0\xaby1\xcd\x93\xfb\x9c\xfe\x06w\xcb=\xbcu\xe5{%\xf9\xcc\xca\xba\x04R\x8a\xda\x9a\x0c\xae(qrN\x0d\x157'\x0f\xb2\xddl\xf6* 'k\xbap\xaf^4\xe0\x17\xce(\xa0r\x94\xe3 \x86\xeb\xc0\x9dd\x86i\x8e\xe4\xfa\xeb \xd7\x0f^\xc8\xed\x11,\xe3\x0f\"X\xd9\x94&^\xad\xa0y\x07S J\xa6\x8dnf$)\x81\x86\xf0\xa6-f\xa6\x8d\xfaJ\xeaB\xa3\xe1\xe4X\x0cKkm\xb54\xfd\\\x15,c\xba\xd8\xb5z\xf34H,\xae\xbfg6\xf7\x80p`ee\xedyd\x95\x85\xd7\x96Q\xd9\xed\xb2\xdd$\xd0/\x91%\x83]\x14\x95[*\xe3N\xcawuyK\xa5!\x87\x1b;\xca[+\x13\xeaYLVR\x98u\xb5(\xa8\xc5Y\xdcL?\xb6\xfd\xad\xf4T\xe6d\x97H?\x8aj\xa0\\Kc\x87\x17\xec\x8e\x02]\xadh6\xe1\x05\xc6\x18\x98w\xc5\x9c9\xa2\x18\xe9\x1d0\xa4\x0fj\xa1Q\xd52&k;cT\x10\xb5&X\x0d\xad\x85_\xfb\xa4\xd7\xc1\xd8?\x86`\xb4+\xe5\xef\xd4\x8ek\x899#\x7fh\x1cbgv\xbd\x7f\x84ZM\x8b\xbf\xc6i\x869\x00\xde\x15\xf5\x07\xff\xaf?\x8e[B1z\x0d8\xbcO\xf3T\x0fa\xafp\x000\x9e\xb3\xcc\xc7\x1e\xdd\xb2-,\x83\xae2\xc6\xd7mMA\xeb6qJrQ\xf4@)\x97\x9e\x13)P\x9a|\xcb\xd6\xdfF\xe1\x9dp\xd9d\xf4\x0c\xae\xb1\xe2\xbc}\x12\x11\x83z'l\xd6\xd9(\xb1\xd9\x16y\x98\x05\xa3\xa0=T\xbfnc\x9e\x16+>\xe6i\x1f5\xc4\x1aBJ\x1b\xe3\x9c\xc4\xf9\x1d\xdd5Q\xa5\x00H\x17\x8dE\xefW\xcb\x96\x8d\x05eC<\xff\xee2\"Dy\xcbx\xccD\xed\xb4<\xf9\xe0\xcc\xfcF\xf2\x1c\xff\xc4)>\xc6F\xc4\x05a{\xbb\xf1~<\xe4\xda\x0b\xa1\x06\x16\xe9\xb2\x98\xdc\xa96P\x8d\xd9-\xa7|\xf5\xb7\x9a\x14!>z\xd99\x97\xed\x00\x0f\xe2\xc0g~\xcf\x8a<#2D\xf4F3\xb0b\n\x94\xb0\x14g\xd3{2\xc2\x1bQ\xd8R\x8e\n\xa7\x8c\x10\xa8\x88\xd4,\xab\x0b\"\xc1\xc8\x8d\xb5\x90\x81pb\xe4N\xb6lpC3\xc1\xf3\x80\x1a;rB\xb9\xb1\xdd\xbd\xc53\x95J\x86YM\xa1Me%\xddcJ8\xe9{\x15\xc4\xca\xcb\xc7F\xa4\x84\xa4YGAj\xb35\x99\x02f\x93bO\xdbS\xa9\x95\x11!b\xf9\xd3\xce\xebqgF\xa7sn5E\xf5\x99\xf7Y8&t\x9b\x1c\x96\x05Vx\xac\x84\xa4[*\xe1$\x17\x08\x11s.O\x97\xf0\xffS)\x90\x949]\xdb4>\xcb\xd2\x01\xa0\x98\x12\x8b\xbe\x18\x8a\xdeS\xa2\xe0k8\xb1\x89\x9c\xac,i\xce\x88\xa6\xc5\xee\xd4\xa6\xb2\xfaT\xd1\xe9\xc5w\xb4\xa0\xff\xf7\xff\x89 \xbd\xb0\x19\x83KI\xa0\xb7O\xe8\xb7\xed\x89t\xeb\xca\xdd#\x9d\xb8\xa2\x08#\xcfG\xe3\xeb\x9d\xca\xe0\x8e\x17\xde\n\xech\xb2\xfboC\xbb\x04$]#\xdfZ^|\x04\xae\x0d*\xc4a_\xe8V\x14uI/\x0b\xc2\xca\x8f\xb4\xac\n\xa2\xe3\x1c\x9a\x9f\x0e\xc7y\xe5\x94\xa0z\x8a\xda)\xea\x1b;\xd8\x88\xfb\xd15\xd8 \x18\xed[\xb1\x9c\x02\x81\x8f\x94\x93\xd1T\xb1\x18e\x8cT\xec\x13\x95*\x90\xdf\xde\xb7\x1d/\xae\xaf\xdc\x18\x17]\xb0\xb4\xb5\xb5\xcfh\x8e\xce\xc3\x92\x84$\x18\xca\x97F\xf6Y\"\xc4H\x80\xdb\xa4ecl8Z\xca\x04\xdfR9\xed\xd0\x964\x13k\xce\xfe\xde\xccB\xf9\xc3\x0f\x93\xd6\xb4\xcdm\xe6\xa4\xf0g\x8d\x11\x13e\xb0P\xc0\xcc\x07j\xde\x81\xee\x13b\x06<3k\xa6\x97w\xff\x8a6`&\xca\xb2\xe6L\xef\x8c\xfd\xa7%\xbb\xad\xcd\x89{\x9e\xd3--\xce\x15[/\x88\xcc6L\xd3L\xd7\x92\x9e\x93\x8a-p\x91\x1c\xcf\xf5e\x99\xff\xa6\xb1\x0c\xc3\xe6`\x80\xfe\xef\x18\x9f\x8c3\xf4\xf7\xf85\xe3\xb9sXw\xee\x13h\xb7\xcb\xc7\xb0>\xbc\xba\xf9\x18\xc0\x9d\xf3\x89\xe2v\xdb\x9d\xed\x9cx\xed&\x97dg\xf0h\x98!\x94D\x83\xd9\xf4\xe6\xed\x94\xe7\xb6 \xc0\xfc\x91\x15\xcch\x1c\xaa\xbeE7A\xe3\xc65\"\xeb\x92\xf0P\x11\xd5-u\x85\x00\xf9\x12\xae8\\\x92\x92\x16\x97D\xd1'\xdfb\xb3{ja\xb6\xe7\xe1\x9b\\RMr\xa2I\xfcF\xdfh\xc2s\"s\xb75\xcf\x9f\xab\x06\xc8\x93\xaf\xdc\xbf(\xbc\xec\x80\xf7\xd1\xc8\xce\x84%W4\xebI\xae\x9c*&i\x0e\xd9\x86H\x92i*\x99\xd2,\x0bj\x98\xc4\xc9cOj\xb6\xc8\xc5*\xad\xa4\xd6\x1b!\x93\x1d\xb7J\x0bI\xd6\xf4\xbc2\xb2Ti\xca\xf5\xc2\xc9\xfc\xdf\xb4\x8f\xec\x93\xcc\x1c'\x93\x14\x13#\xffM#YF\x95z+\xf2P\xc7\x83\x83\xa0\x1d\xd8&\x98t\x11j!\x07`\x02\x94\xee\xdaG\xea\x11\xea\x04\xfe\x86l\x87\xd9o&\n\xedt\x16\xf8\xba\xc57S\xa8\x83\xb0G\xc7\xb7(\xbe\xecv\x0d\xc5Z\x01\x0cO\xdc\xa0\xd4\x0c\xbd\xbe\xbf\x1f\x1f;\xf5U\x84\xa3DS\xd6\x95\xe4\x95\x0b\xca\x8c\x9e\x15\x82\n\xf0/p\xc1\x81\x1a\xa5\xce\x08z\xab\xbf\xdcpR\xa9\x8d\xd0^\x88\x9f(\xf7`\xe9P\xee\xe5B\xbf{\xf0]\x0b\xf8\x13\xd5\xe4t\xef\x9d\xd7\x9f.\xe1\xe4\xba\xd9\xc3\x8e\n\x15\xce\xe0\xe8C\xcaj\xa5E\xd9\x1cD\xe7n\xfa\xd6\x87\xec\xdd\xbfa\"5\x9b\x02\x95\xa8\xea\xc2\x99Z\x17E\xb5!\xa76\xfd5\xb7:\\\xad($\xae\xde\xcf\xc6\x1c\x02V\x7f&\x95a\\i\x8c\x0dXQb\x84'\xac\xcd\x1f\xce\xaa\x0b\x82\xa4\x9c\xdc\x164\x87\x93\xfeT^6T\x05B\xc2\x05\xdf\xd9\x9f\xdb\xc7a\xc4:\xcd\x1f\xa3\xa6\xa8\xebI\x03\x8a\x18d;\xad\nO\x02Q\x14T\" \xaa\xba\xaaD@e\x03\xe7qlK\x05\x11\xd5v\xb7\xd0`D\xc3,C\xab\x0c\x08pz\xef\xe4D\x10\xec-Q>\x82Mqj\xd4:\x0e\xc6\xdf\x172e\x1b\x1c\x0c\x8enL[\xbbl\x9a\xc7\xd5c:\xa9\xd7-\xc9\xcc\xbc\x0d\xea\x92\xf9V\x84\x15\x86\x10\x9c\x8d\x1a\x04)\xa9\x9d\x801b\xcd\xfe\x98c\x17\xf5\x1a\x04V\x1b\xa2:\x83{\nU\x81\xde\x95\xe8\x8d\xc2\x9bn\xbb+F\xc2m\xa6yK7d\xcb\x84l\xd27ZJ \x83\xc6\xbbx _\xd3eH4\xc7\x9el`-\x9c\xef\xa5\xa8\xabp\xcf\xfd\xe2\x9c\xeb+\x1c\xe8m\xe75\xfe\xe1S%\xbc8\x89\x80jtK{W\xee\x8aJ\xca3\x17\x1e\xeb\xc2G\xa2\x89u8\xdb\xd6'B\xd4\xd7\xbd\xdb\x87y\x82\x97\xd4\xbc\xc5\xce\x98\xa3\x85\xd9b\xc5\xf2\x08\xe66\x14q\xcb\xf0\x86\x97\x90\xd2\x9dr\xe2\xcf\xb9\xdf\xa1\xb7\xbc\xc9\x9b\x1d\xec\xd2#@B\xec\x9d\x0ei\xc5g\x91\x8e<\x18\xdb\xb3\xa1I\xe1\x02\xa3@B\xf0^\x86\xee]\x0b\x91 God\x98u\xcbB\n\xa9\xd8\x16\xcc)\xea\xb6\x1eRG\xefT\x88\xf2\x94\xb4\xedA\xb7)$\x9f\x8e\xb1\xc9;\xdd\xd6[\xf6\xc4\xdd )\x89<\xdd6zk\xc2\xec\x8b\xd6\x1f\xf3z\xf5\x19(N\xbd\xf3\xa0\x87\xe0G\xba\xed\xe0\xf1\xef9\xd0\xe1\x1b\x0e\xe2\xf2\xdf\xba-\xe2n\x83D\x88\xa1[\x0d\x9a[\n\x12`N\xdcg0\xef~\x82\x04In\xdb\x0c*\x8c\x0f\xd3\xf8\x16\xeb\x03\xb1-\xfe\x06\x82\xc4\xbb\x07\xa2\x15\x98n\xf7\xb8U&\xde40\xdf.J\xdc\xafC\x1d\xe4\x11\xee\x15x\x82\x1b\x05\x9e\xec.\x81\xe8[\x04\xec\xdd\x00Q0\xc3\xf7\x07\xf4n\x05\x88\x829_yK\xa0\xea\xe8\xae\xce\xa1vY\x10\xa5\xdeE8e\xfb\x96c\xb7<\xf5\xa6\x03\xa9\x91\x03.?0\xb88\x8c\xe0'\xdbI\x13\xde\xc0\xccL#\x1c\xd8\x8ef2\x0b\xf7\xad\xc8\xd30\xd4\x0ek\xb2,\xeeQ\xc1sN\xf9\xc8\xe0\x1d;\xc0\xa8\xc7\xd8'_\x8a\xfe\x1d+\xa8\xbb\xb0\x93)4Gc\n\xe7\xef7\x94c\xc4\x85\xf1\xac\xa8s\x8a\xdf\xecD\xd0h\x10\x87\xa82\x11}\xc9\x04\xf6\xa9\x19\xe6\x15eg\xf1\xb5N\xfc\x18\x1b\xdd\x0c\xdc\x8f\x9f\xc3-\xc9\xee\x9a\xaf\x95Zl>\xcej\xa3xOi\xa2\xeb\xc9\x93\xe0 7I\xd7\x07~\xf8\xac\x96\x12-0n\x93k\x99\xe0\xe7\x16\xf2\xe4R\xc4\n\x08\xb4L\xe3\x1d\xf3\x8e\xa4>P\x92/\x8cl{L~\xfc5\xa5\xec\x90L\xd7\xa4\x98\x9d\xb1\xd3\x12\x16\xc5\xd4\x8d\x0d\x19\xce\x8d\x9c\x89\xc9_K\xe6NF*\x92\x05\xbeI\x0c\xb35\xa4H\xafq\xaa\xc78\xd1[\xfc\x05{\x8a\x1f\xe8%\xee\xb1\xca\x87\xbe\xd4q\xfc\xd1zx#o\xc1\xadyNe\xb1\xc3\x14Z$\xe68\x81\x1b\xa1\xc5d\x82[\"\nRNo]\x97N|^\xfa\xe1xi\xee\xbe\\\x0c\xae\xcb\xc9\xcd\xabUw\x85\x87\xe2\x95\xa9&\xf9A\xb1\xbfG\x1c\xce\xda]\x8d\xdd\x99\x9f\xaf\xcbP\x14\xf5\xe6\xe7\x1f\x10\xd4\x8d&R\xd3\xfcy\x08\x9f\x91\xc2\xa0\x87\xa3\xc1\xbc\xb3vBVpF\xe9\xfe9\xc5\x9e@nE\xad\xf1\x00D\xc5\xa5\xda\x86o\xf4\x8b=\x0bl+\x88\xd2\xd7R\xdc\xd2\x8f,\xaco\xd8\xd6[\xf2\x1b\xa2\xb4-)\xba\xc7\xb4\x9d[\x9a\xbb$\x12\xb7\xea\x10\x9em\xf3\xf5.9\xd1ta\xc0E\x8dJ\x92?v\xad\x1f%\xe1\n'\xf6\xe0\x05\xf7\x96 \xba\x01\x1cA\xad\xb6a>\xba\xe0\xd4)8\xd6\xb8\xc3\x80\xca\x17\x84\xb4\x92*E\xd6s0\xf5\xff\xd5%\xe1\x0bIINn\x0b\xea\x01\xf9j\xdc\xb8\xb7\xc3\x01/\x14\x88\xff\x06\xd9q\x98J\\\xb3\xa4D\x85\xbf\xdc`[o\xc9\x7f\xe6\xeco5~M\x81\xa9N)\x131\xff\x96\xfa\x0cJ\x92m\x18\x8f\xdb'w\x06(L\xb47\x08t\x15\x15\xe8\xf4^\xb3\xadS\xa4\xec\\#!\xe2\x854\x9ed\xf1\x1e\x9f>2\x8d\\f\xdae\x01\xc6\xc8)\xd3\x9e\xf5\x04\xeb3\xffqx\xe24\xc4A9\x1f z\xe44x\x92M\x0f[\x19mK\x04\x8d\xdd#\xfa%\x1d'\x1fwU,!\xa1[k\x8b>\xfe\xe6:\xb6i\xe0\xcbh\xe8I\xa8\x88wy. \xc26\x83F\x0b\x0dv\x8bV\x8f\xe2\x95\xf6jCTp[\xfb\x1bjF\x8c\xd9\xa5\x08ntgB$\x1f\xb9\x0d\x11h\x08vq\xc6\xd55\x95\xb6\x06k\x0c\x05\xfd|\xc4\xe6*\x90\x03e\xcf\xdd\xe6\xe7\xd55\x7f\x95\xc5\xe8***\xdd-$#]\x1e\xe3\n\x91)J]\xf8KP\x06\x7f\x1b\xa8\xf6\x9c\xe8\xd7\xa2q\xa0\xd3\xe4V\x8c\x93i%\x99\x90L\xef&\x1c\x95}\xb2\xdc\xef\xbfwc\xc6\xb5\xc8\x1b\x98\xe8\xe6\xddP>\x98\xc1\xccJsn\x10\x9eQ\xeb61\x03\xbb\x9fD\xb1\xd9\xc1\xd7\"W.8d\x04\x13\xc6a\xb1\xda\xe4-\xe3W\xef\x07\xc0\xe2\xc5\x8c\xd6\xc9\xf2\x81\xae\xa8\x84\xd7\x8d\xb5\x06\xb9\xc8\xea&\x95\x04\xcf7\xaf.\xc4\xb8\x0e\xfa\xc9#\x95\xc8\x17~\x9d\x8bJRZ\"\x82\xce\x7f\xe3\x1f\xa2\xa3td#\x06Y\xcfe\x85]\xd4Z\\R9pu\xc9`r\x91\xef\xde\xbd\x89\x06?\xbc\x83\x05\x1a\xdd\xd5c\xa1\xc2\x00\xc6>\xbe\xb9\x81\xcc@XS\xee\x0b\xb5\xcd\xc6)\xb6\xc6\x0f\xb4\x10\x9b\xceC0\xeffC%\x9d\xf4\xb4h\xa2\xee\xd4\xb9.\x94M\xafa|\xbd\xd0\x851\x94\x17d\x91\x15\xb5\xd2\x83Y5\x16-\xb7B\x14\xf4 ?A\xfd>\x80\x8a\x9b\xdf\xbb\xec\x84\xdc\xd7\xb2(_\x9b\x943e\xebT\x84lJVT\x9dm\x80\x0c\xf1\xe3_o\xeb\xec\x8e\xea\x97\xefn\xfe\nT\x0f8i\xa7\xcd\xa5f\xf4\xb0\x90\xeb\xcd\xf9O\xbe/\xb0\x15<\xd7\xb2\xa6\xcf\x9d\x1ad\x7fiV`\xbdR\xa3\x12\x0e\xaf\xd9\x81\xbf\xfe\xc1\xbe\xfb\x8f\xcb\x92q&\x96.\x81k\xa9\xb6\xd9\xd2!}Y\x88\x8c\x14\x7f\x1d\x043\x85\xfd)\xe9\xb6h\x97<\xb2\xa3\x83\xe2H\xd1\xacF\x11\"\xb8\xa6\x9fC\x84~\xe3z\x83\xeb\xbeO\xe8\x077.\xc9\x9a_\xa8?\xab\xe1\x8b\xbf*\xc9\xb6\xac\xa0k\nTe\xc4\x95Y\xcd\xd8\xeb\x95\x9a(\xf8\xe8\xcd\xff\xd9\x85M\x81#\x05\x16\xc0\xb8d\xb6\xc2\x95z\xd8;H\xda\x8b\x9b\xc7?\x82\xd5$\xa5\xe1\xc5XX\x01\xba\x84\x1bQ6\xeeQm\xabd\x0cvP\x12\x1b\xd6/\xd0\x9d1\x06\x11\x0bal\x14\xef\xde\x00\xde\xb0\xca\xba\x9cH\xe3[\xb17u\x9a\x9f\x9b\x00I%FU\xb2\xbfp\xf8\xc6fR\x89{\x94\x1d\xdf_\xbdl\xaf\xbc\xd8P\xf8\xee\xc6\x16v\xfc\x1f\xdbKQ\xbdf9\xdc\xe2\x85\x1d#0\xcd\xfe\x9epz\x0f+V\x18\xc6vEK.J\xda-k\xeaN\xd4\xbdh\xac\xdc\xec\xf7\xf6\xfd\x15\x95%\xc3X\xa8\x99\x83\x8d\x1a\xbe\xff\xf0\xdc}\xa3Q\xde/\xe4\xfdb\xb1X\x98u\xa1\x13J\xd1\xd1\x9b\xbc\xba\x18o\x8a\xacJ\x91\xb3\xd5n\x0f\xc3F\xb6\xb6/\x9e\xa8\x00&|\xe7\xfdy\xc3\x17m\x87/\xfe\x08i.\x8e\x8c/\x91\x12\xaeE\xc1\xb2\x11\xb7r\xff\xec\x19\x18\xd6\x84\xe1\xba\xe5YHa\xe3J\xe6\x18N|\xe4\xd3\xfb\xfd\xe9JHW\x88b\x8e\"1.\x0e\xdd\xa5\x15\xd7\x867:\x95\xaa\xb8!\x18U6\xac\xb63T\xddc\x9a\xa9\xdb\xa0]\xd5\x9aG\x95\xaf\xf7\xf3S?\xd9\xdb\xce\xd3%\\9\n\xd8\x90\xed\x98\xad\xc1\x85\xbf4\xc7\x88\x9fjCK*I\xd1\x9f\x94;\xa7^\x18y)\xa9>\x03\xab\x80\x94\xa4\x1ac\x153\x15L\xa7\xc9\x99\xf4yZ\x9d\x1b\xc3\x9e\xbd\xe7\x1f\x84\xd0o\x99\xc2D\x80g\xd8\xff\xd9EqOv\xea\xd9\x98\xcdp\xb5\xea\x17\x8e\xf5\x92\x83\x9b\xc1\xc3\xd1\x92\x80\x9d\x81\x82:V\x8c\x1av5\xd2D\x0b3\x0e\xc9\xc3H\xfd\x9d\xbd\x9b\xc1\x11L##\x8d\xf46\xe7\xe6\xd8\xaa\xfe\xac(\xde\xdd\x8d\xbe9\xb7\"s\x12#\x8b/\xe1-\xd9\x01)\x94\xf0\x1ea\xc6\x9bc\xc8\x9dBK\x83\x99 \x89\xc58\xdc\n\xbd\xd9\x1f\x86(\xbf\x16\xf9\xde\xe3\xce\xa56c0\x1b\xfc\x1f\xce\x054\xb9\xa3\n*I3\x9ac\xe8v\xb5\x97\x08:\xe6$|\xb8\x00\xc1=|'\x90\xb0\"v\xf1\xaac+\xb8\xeb\xde\xda=\xc3\x8c0\xb3\xb9D\xe1\xc5\xd3|!\xc5hu\xb39\xfemR\x9b\xb4N\xb4=\xf1\x8b\x1e\x0cw\xd1\x13\xb0\x92\xac\x8d\xb1\xe8\xb7|L\x86\x1b\xb5Y\xd5\x92\xba\x86\x98\xbbU\xfb\x89\xba>\x04\xfb\xc8\xf3\x08\x05W'\xaf\xc9XL\xea\x04\xc1\x98\xe04\xab\xdc3\x9e\x8b{\x95\xa6\xd8\xfd\x87\x1d\xe4\xf5\x91\xcc H3\xbeV\x8f\xa3\xdc ;\x19\xe4\"t\xbev\xc5Y\x9c\xaa\xec\xc5\x96\xe1\xdae@\x85\x1fS\xc7&8=\xac\xc2G\x9a[aFZ\x97\x8a\\J\x03C3R\xdcL^\x8b\xd8\xdb\xa8\xef\xdf\xde\\\xf4\x07\x9a#\xd6~P\xce\xac\xc1\xfc\x0e$w\x9e\xb4 \xfa\xbe\xa7\xb7\x1b!\xee\xe0\xa4sa\xe4\xa6\xbe]f\xa2\xec\x84\xa4\x16\x8a\xad\xd5\xb9#\xa7\x85\x99\xf5\xd4\xe5c\x8c\x17\xcd]\x8d\xfb\xb7x\xe1\xc4\xb2f\xe6\x88f\xe4\x8f\x1cn'\xbfh\xe6\xc6\xf6\x17\x8d\x92\x05\xfd\x92\x0f\xd0\x08\x86\xb6a\xba\n \xb0\x15Cw\x00\xf9\xf9O,q\x1f+\xd6\x14~\xd0\xc2\x1a\x83>a=h\xd8\xbb!\x86\xf6\xbd<\x184\xf4'\x963\xea\x02\xe8\x19\xfb\xa6K\xdf\xe0\x9f$\xac\x80+`\xc8\xac;d\xfe\xa9\x9c\x8ey\xd2\x04\xa6S\x8b\x1fM\xa2@\xcc\xb6Gd/\x8c\xc4\x12\xe5\x96e\xf4\"\xcbD\xcduD\xfe\xc2\xcd\xc1\x80!\xaa\xef\xf7\x1a\x98\xb1\xbb\x88\xd1\xd1\x97M:X\xe1 \x83\x89 V\xe9\xca\xdaK\xde\xedw\x02,x\xa6\xdc\x9d\xda\x87\xf8\x9a\xc0\x93\xaao\xaf\x89\xde\x84\x96W\xdfVDo| \xc4~b\xc9\xad-\xdcS\x0e\xdcFJ\xdaDR\\\xa3\xa2m\x00\x12F\xb2\x10}\xf2<\xe2L\x82\xcar\x82KFG\x16\xd6\xb4\xc1\x1a\xb4)\x99\\\xe7\x10\xca\xc1;,\x16\xa6\x0d@\xa1@NY:\x06 \xa2\xba\xed\x13\xbeS(G`0@)\xe6\x80J'\xdfE\xa3n\xc2\xd5\x8a\xc1%\x00\xe7R\x877\xc9\xde;Z8\xc75\xe9r\xc8\x02\xe08)\xfaDr\x910\x1a\xce8\x8e\x8f\xf8q\xe6'\xbb\x9b\xf2\xa3\xb1\xfb\x7fc3\x9e\xdd\xf6\xb5\xab\x1a\xc2\x8a\x83w\xad\x85\xc7\xcd\x92u%T\xba\xf3\xff\xea\x84\nWqt\xd1\xe3\x08\x7fV*\xdaC\x01\\\xae\x16f\xc6\xc4\x1e\x1e)\xb2\xb4\x16f\xf3\xff\xcf\xbe\xc7Q\xdeR$\xc10*\xcar\xf8\xc2\xdc\x98+Y!W\xc5k{\xc7I\xe9K{]jZ\x94\xd7Bbaj\x8c\xf9\xcb=\x08\xd7\xcc\xf2\x8c\x1e\x8b\x8d\x89\x86\x0e\x91\xc0\xa2\xca\xf2\xf0\xbc\xe5f\xa1\xb3\xfe|l\x18U&\xdf8\xbf=~\x01\x00\x00\xff\xffPK\x07\x08\x80\xa45\xf7U\x00\x00\x00Z\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00IpPQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00 \x00service.yamlUT\x05\x00\x01\xeb\xa7\x89_|\x8e1k\xc50\x0c\x84w\xff\x8a\x83\xceoh^'\xaf\x9d\xba=(tW\x9d\xa31u,c)\x81\xfe\xfb\x92\x90,\x0dt\x94t\xdf\xa7\x93\x96?\xd8-k\x8dX\x9f\xc3w\xaec\xc4;\xfb\x9a\x13\xc3L\x97Q\\b\x00\xaa\xcc\x8c\xd0\xc6.\xae\x1dOx\x14\x8a\x11\xa3\xa2\xaa#MR\xbf\x08\x9f\xb2a\x95\xb20\x00E>Yl\x83O|\xce5\xeb\xed\x94\x1cVk\x92\xae7kL\x1b\xea?\x8d\x11\xafe1g\x7f{\x04\xa0i\xf7\xc3z\xdb\x87\x88\x97a\x18\xf6\xc5\xf9hro\x7f\x12\xf7\xfb%a\x010\x16&\xd7\xfeO\xcd\xdf\x00\x00\x00\xff\xffPK\x07\x084W.\x15\xa5\x00\x00\x00$\x01\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00IpPQ$\xaf\xb0M\xa2\x00\x00\x00\x1d\x01\x00\x00\x19\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\x00\x00\x00\x00cluster-role-binding.yamlUT\x05\x00\x01\xeb\xa7\x89_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00IpPQ\xe2\xbc\xc6/u\x01\x00\x00{\x05\x00\x00\x11\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\xf2\x00\x00\x00cluster-role.yamlUT\x05\x00\x01\xeb\xa7\x89_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xb1E\x84Q\x02\xcb\x05\xd3\xf90\x00\x00\x08\x8c\x01\x00\x1e\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\xaf\x02\x00\x00crds/minio.min.io_tenants.yamlUT\x05\x00\x01/\xf7\xc9_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00M used for KES authentication. - properties: - name: - type: string - type: - type: string - required: - - name - type: object - image: - description: Image defines the Tenant Docker image. - type: string - imagePullPolicy: - description: Image pull policy. One of Always, Never, IfNotPresent. - This is applied to MinIO pods only. Refer Kubernetes documentation - for details https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - imagePullSecret: - description: ImagePullSecret defines the secret to be used for pull - image from a private Docker image. - properties: - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?' - type: string - type: object - kes: - description: KES is for setting up minio/kes as MinIO KMS - properties: - annotations: - additionalProperties: - type: string - description: If provided, use these annotations for KES Object Meta - annotations - type: object - clientCertSecret: - description: ClientCertSecret allows a user to specify a custom - root certificate, client certificate and client private key. This - is used for adding client certificates on KES --> used for KES - authentication against Vault or other KMS that supports mTLS. + env: + description: If provided, use these environment variables for Tenant + resource + items: + description: EnvVar represents an environment variable present in + a Container. properties: name: + description: Name of the environment variable. Must be a C_IDENTIFIER. type: string - type: + value: + description: 'Variable references $(VAR_NAME) are expanded using + the previous defined environment variables in the container + and any service environment variables. If a variable cannot + be resolved, the reference in the input string will be unchanged. + The $(VAR_NAME) syntax can be escaped with a double $$, ie: + $$(VAR_NAME). Escaped references will never be expanded, regardless + of whether the variable exists or not. Defaults to "".' type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, metadata.labels, metadata.annotations, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object required: - name type: object - externalCertSecret: - description: ExternalCertSecret allows a user to specify custom - CA certificate, and private key for group replication SSL. + type: array + externalCaCertSecret: + description: ExternalCaCertSecret allows a user to provide additional + CA certificates. This is used for MinIO to verify TLS connections + with other applications. + items: + description: LocalCertificateReference defines the spec for a local + certificate properties: name: type: string @@ -491,1172 +414,1269 @@ spec: required: - name type: object - image: - description: Image defines the Tenant KES Docker image. - type: string - imagePullPolicy: - description: Image pull policy. One of Always, Never, IfNotPresent. - This is applied to KES pods only. Refer Kubernetes documentation - for details https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - kesSecret: - description: This kesSecret serves as the configuration for KES - This is a mandatory field + type: array + externalCertSecret: + description: ExternalCertSecret allows a user to provide one or more + TLS certificates and private keys. This is used for enabling TLS + with SNI support on MinIO server. + items: + description: LocalCertificateReference defines the spec for a local + certificate properties: name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?' type: string + type: + type: string + required: + - name type: object - labels: - additionalProperties: + type: array + externalClientCertSecret: + description: ExternalClientCertSecret allows a user to specify custom + CA client certificate, and private key. This is used for adding + client certificates on MinIO Pods --> used for KES authentication. + properties: + name: type: string - description: If provided, use these labels for KES Object Meta labels - type: object - nodeSelector: - additionalProperties: + type: type: string - description: If provided, use these nodeSelector for KES Object - Meta nodeSelector - type: object - replicas: - description: Replicas defines number of pods for KES StatefulSet. - format: int32 - type: integer - serviceAccountName: - description: ServiceAccountName is the name of the ServiceAccount - to use to run pods of all KES Pods created as a part of this Tenant. - type: string - required: - - kesSecret - type: object - log: - description: LogConfig defines configuration parameters for Log feature - properties: - audit: - description: AuditConfig holds configuration for audit logs from - MinIO - properties: - diskCapacityGB: - description: DiskCapacityGB defines the disk capacity in GB - available to store audit logs - type: integer - type: object - image: - description: Image defines the tenant's LogSearchAPI container image. - type: string - type: object - mountPath: - description: Mount path for MinIO volume (PV). Defaults to /export - type: string - podManagementPolicy: - description: Pod Management Policy for pod created by StatefulSet - type: string - pools: - description: Definition for Cluster in given MinIO cluster - items: - description: Pool defines the spec for a MinIO Pool + required: + - name + type: object + image: + description: Image defines the Tenant Docker image. + type: string + imagePullPolicy: + description: Image pull policy. One of Always, Never, IfNotPresent. + This is applied to MinIO pods only. Refer Kubernetes documentation + for details https://kubernetes.io/docs/concepts/containers/images#updating-images + type: string + imagePullSecret: + description: ImagePullSecret defines the secret to be used for pull + image from a private Docker image. properties: - affinity: - description: If specified, affinity will define the pod's scheduling - constraints + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + kes: + description: KES is for setting up minio/kes as MinIO KMS + properties: + annotations: + additionalProperties: + type: string + description: If provided, use these annotations for KES Object + Meta annotations + type: object + clientCertSecret: + description: ClientCertSecret allows a user to specify a custom + root certificate, client certificate and client private key. + This is used for adding client certificates on KES --> used + for KES authentication against Vault or other KMS that supports + mTLS. properties: - nodeAffinity: - description: Describes node affinity scheduling rules for - the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods - to nodes that satisfy the affinity expressions specified - by this field, but it may choose a node that violates - one or more of the expressions. The node that is most - preferred is the one with the greatest sum of weights, - i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node matches the corresponding matchExpressions; - the node(s) with the highest sum are the most preferred. - items: - description: An empty preferred scheduling term matches - all objects with implicit weight 0 (i.e. it's a no-op). - A null preferred scheduling term matches no objects - (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated with - the corresponding weight. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: + name: + type: string + type: + type: string + required: + - name + type: object + externalCertSecret: + description: ExternalCertSecret allows a user to specify custom + CA certificate, and private key for group replication SSL. + properties: + name: + type: string + type: + type: string + required: + - name + type: object + image: + description: Image defines the Tenant KES Docker image. + type: string + imagePullPolicy: + description: Image pull policy. One of Always, Never, IfNotPresent. + This is applied to KES pods only. Refer Kubernetes documentation + for details https://kubernetes.io/docs/concepts/containers/images#updating-images + type: string + kesSecret: + description: This kesSecret serves as the configuration for KES + This is a mandatory field + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + labels: + additionalProperties: + type: string + description: If provided, use these labels for KES Object Meta + labels + type: object + nodeSelector: + additionalProperties: + type: string + description: If provided, use these nodeSelector for KES Object + Meta nodeSelector + type: object + replicas: + description: Replicas defines number of pods for KES StatefulSet. + format: int32 + type: integer + serviceAccountName: + description: ServiceAccountName is the name of the ServiceAccount + to use to run pods of all KES Pods created as a part of this + Tenant. + type: string + required: + - kesSecret + type: object + log: + description: LogConfig defines configuration parameters for Log feature + properties: + audit: + description: AuditConfig holds configuration for audit logs from + MinIO + properties: + diskCapacityGB: + description: DiskCapacityGB defines the disk capacity in GB + available to store audit logs + type: integer + type: object + image: + description: Image defines the tenant's LogSearchAPI container + image. + type: string + type: object + mountPath: + description: Mount path for MinIO volume (PV). Defaults to /export + type: string + podManagementPolicy: + description: Pod Management Policy for pod created by StatefulSet + type: string + pools: + description: Definition for Cluster in given MinIO cluster + items: + description: Pool defines the spec for a MinIO Pool + properties: + affinity: + description: If specified, affinity will define the pod's scheduling + constraints + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a + no-op). A null preferred scheduling term matches + no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: The label key that the + selector applies to. type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - weight: - description: Weight associated with matching the - corresponding nodeSelectorTerm, in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by - this field are not met at scheduling time, the pod will - not be scheduled onto the node. If the affinity requirements - specified by this field cease to be met at some point - during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from - its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. - The terms are ORed. - items: - description: A null or empty node selector term - matches no objects. The requirements of them are - ANDed. The TopologySelectorTerm type implements - a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If + the operator is Exists or DoesNotExist, + the values array must be empty. If + the operator is Gt or Lt, the values + array must have a single element, + which will be interpreted as an integer. + This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: The label key that the + selector applies to. type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: A node selector requirement is - a selector that contains values, a key, - and an operator that relates the key and - values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators - are In, NotIn, Exists, DoesNotExist. - Gt, and Lt. - type: string - values: - description: An array of string values. - If the operator is In or NotIn, the - values array must be non-empty. If the - operator is Exists or DoesNotExist, - the values array must be empty. If the - operator is Gt or Lt, the values array - must have a single element, which will - be interpreted as an integer. This array - is replaced during a strategic merge - patch. - items: + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - type: array - required: - - nodeSelectorTerms - type: object - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. - co-locate this pod in the same node, zone, etc. as some - other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods - to nodes that satisfy the affinity expressions specified - by this field, but it may choose a node that violates - one or more of the expressions. The node that is most - preferred is the one with the greatest sum of weights, - i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node has pods which matches the corresponding - podAffinityTerm; the node(s) with the highest sum are - the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If + the operator is Exists or DoesNotExist, + the values array must be empty. If + the operator is Gt or Lt, the values + array must have a single element, + which will be interpreted as an integer. + This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range + 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an + update), the system may or may not try to eventually + evict the pod from its node. properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key - that the selector applies to. + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If + the operator is Exists or DoesNotExist, + the values array must be empty. If + the operator is Gt or Lt, the values + array must have a single element, + which will be interpreted as an integer. + This array is replaced during a strategic + merge patch. + items: type: string - operator: - description: operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If + the operator is Exists or DoesNotExist, + the values array must be empty. If + the operator is Gt or Lt, the values + array must have a single element, + which will be interpreted as an integer. + This array is replaced during a strategic + merge patch. + items: type: string - values: - description: values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. + type: array + required: + - key + - operator type: object - type: object - namespaces: - description: namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the - pods matching the labelSelector in the specified - namespaces, where co-located is defined as - running on a node whose value of the label - with key topologyKey matches that of any node - on which any of the selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: weight associated with matching the - corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer + type: array + type: object + type: array required: - - podAffinityTerm - - weight + - nodeSelectorTerms type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by - this field are not met at scheduling time, the pod will - not be scheduled onto the node. If the affinity requirements - specified by this field cease to be met at some point - during pod execution (e.g. due to a pod label update), - the system may or may not try to eventually evict the - pod from its node. When there are multiple elements, - the lists of nodes corresponding to each podAffinityTerm - are intersected, i.e. all terms must be satisfied. - items: - description: Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) - that this pod should be co-located (affinity) or not - co-located (anti-affinity) with, where co-located - is defined as running on a node whose value of the - label with key matches that of any node - on which a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the + corresponding podAffinityTerm; the node(s) with the + highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. items: - type: string + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object type: array - required: - - key - - operator + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object type: object - type: array - matchLabels: - additionalProperties: + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose value + of the label with key topologyKey matches + that of any node on which any of the selected + pods is running. Empty topologyKey is not + allowed. type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey - matches that of any node on which any of the selected - pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules - (e.g. avoid putting this pod in the same node, zone, etc. - as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods - to nodes that satisfy the anti-affinity expressions - specified by this field, but it may choose a node that - violates one or more of the expressions. The node that - is most preferred is the one with the greatest sum of - weights, i.e. for each node that meets all of the scheduling - requirements (resource request, requiredDuringScheduling - anti-affinity expressions, etc.), compute a sum by iterating - through the elements of this field and adding "weight" - to the sum if the node has pods which matches the corresponding - podAffinityTerm; the node(s) with the highest sum are - the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range + 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a + pod label update), the system may or may not try to + eventually evict the pod from its node. When there + are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or + not co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any + node on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of + label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: type: string - values: - description: values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. + type: array + required: + - key + - operator type: object - type: object - namespaces: - description: namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - items: - type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the - pods matching the labelSelector in the specified - namespaces, where co-located is defined as - running on a node whose value of the label - with key topologyKey matches that of any node - on which any of the selected pods is running. - Empty topologyKey is not allowed. + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only + "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: type: string - required: - - topologyKey - type: object - weight: - description: weight associated with matching the - corresponding podAffinityTerm, in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified - by this field are not met at scheduling time, the pod - will not be scheduled onto the node. If the anti-affinity - requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod - label update), the system may or may not try to eventually - evict the pod from its node. When there are multiple - elements, the lists of nodes corresponding to each podAffinityTerm - are intersected, i.e. all terms must be satisfied. - items: - description: Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) - that this pod should be co-located (affinity) or not - co-located (anti-affinity) with, where co-located - is defined as running on a node whose value of the - label with key matches that of any node - on which a pod of the set of pods is running - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: A label selector requirement - is a selector that contains values, a key, - and an operator that relates the key and - values. + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified + namespaces, where co-located is defined as running + on a node whose value of the label with key + topologyKey matches that of any node on which + any of the selected pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the greatest + sum of weights, i.e. for each node that meets all + of the scheduling requirements (resource request, + requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if the + node has pods which matches the corresponding podAffinityTerm; + the node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and - DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. - If the operator is Exists or DoesNotExist, - the values array must be empty. This - array is replaced during a strategic - merge patch. + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. items: - type: string + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object type: array - required: - - key - - operator + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object type: object - type: array - matchLabels: - additionalProperties: + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose value + of the label with key topologyKey matches + that of any node on which any of the selected + pods is running. Empty topologyKey is not + allowed. type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is - "In", and the values array contains only "value". - The requirements are ANDed. - type: object - type: object - namespaces: - description: namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - items: + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range + 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a + pod label update), the system may or may not try to + eventually evict the pod from its node. When there + are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or + not co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any + node on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of + label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only + "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified + namespaces, where co-located is defined as running + on a node whose value of the label with key + topologyKey matches that of any node on which + any of the selected pods is running. Empty topologyKey + is not allowed. type: string - type: array - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey - matches that of any node on which any of the selected - pods is running. Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - name: - description: Name of the pool - type: string - nodeSelector: - additionalProperties: + required: + - topologyKey + type: object + type: array + type: object + type: object + name: + description: Name of the pool type: string - description: 'NodeSelector is a selector which must be true for - the pod to fit on a node. Selector which must match a node''s - labels for the pod to be scheduled on that node. More info: - https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' - type: object - resources: - description: If provided, use these requests and limit for cpu/memory - resource allocation - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute - resources required. If Requests is omitted for a container, - it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - servers: - description: Number of Servers in the pool - format: int32 - type: integer - tolerations: - description: Tolerations allows users to set entries like effect, - key, operator, value. - items: - description: The pod this Toleration is attached to tolerates - any taint that matches the triple using - the matching operator . + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true + for the pod to fit on a node. Selector which must match a + node''s labels for the pod to be scheduled on that node. More + info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + resources: + description: If provided, use these requests and limit for cpu/memory + resource allocation properties: - effect: - description: Effect indicates the taint effect to match. - Empty means match all taint effects. When specified, allowed - values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies - to. Empty means match all taint keys. If the key is empty, - operator must be Exists; this combination means to match - all values and all keys. - type: string - operator: - description: Operator represents a key's relationship to - the value. Valid operators are Exists and Equal. Defaults - to Equal. Exists is equivalent to wildcard for value, - so that a pod can tolerate all taints of a particular - category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of - time the toleration (which must be of effect NoExecute, - otherwise this field is ignored) tolerates the taint. - By default, it is not set, which means tolerate the taint - forever (do not evict). Zero and negative values will - be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: Value is the taint value the toleration matches - to. If the operator is Exists, the value should be empty, - otherwise just a regular string. - type: string + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. More info: + https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object type: object - type: array - volumeClaimTemplate: - description: VolumeClaimTemplate allows a user to specify how - volumes inside a Tenant - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this - representation of an object. Servers should convert recognized - schemas to the latest internal value, and may reject unrecognized - values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST - resource this object represents. Servers may infer this - from the endpoint the client submits requests to. Cannot - be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' - type: object - spec: - description: 'Spec defines the desired characteristics of - a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + servers: + description: Number of Servers in the pool + format: int32 + type: integer + tolerations: + description: Tolerations allows users to set entries like effect, + key, operator, value. + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . properties: - accessModes: - description: 'AccessModes contains the desired access - modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' - items: - type: string - type: array - dataSource: - description: 'This field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot - - Beta) * An existing PVC (PersistentVolumeClaim) * - An existing custom resource/object that implements data - population (Alpha) In order to use VolumeSnapshot object - types, the appropriate feature gate must be enabled - (VolumeSnapshotDataSource or AnyVolumeDataSource) If - the provisioner or an external controller can support - the specified data source, it will create a new volume - based on the contents of the specified data source. - If the specified data source is not supported, the volume - will not be created and the failure will be reported - as an event. In the future, we plan to support more - data source types and the behavior of the provisioner - may change.' - properties: - apiGroup: - description: APIGroup is the group for the resource - being referenced. If APIGroup is not specified, - the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - resources: - description: 'Resources represents the minimum resources - the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount - of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount - of compute resources required. If Requests is omitted - for a container, it defaults to Limits if that is - explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - selector: - description: A label query over volumes to consider for - binding. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. - If the operator is In or NotIn, the values - array must be non-empty. If the operator is - Exists or DoesNotExist, the values array must - be empty. This array is replaced during a - strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. - A single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field - is "key", the operator is "In", and the values array - contains only "value". The requirements are ANDed. - type: object - type: object - storageClassName: - description: 'Name of the StorageClass required by the - claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, + allowed values are NoSchedule, PreferNoSchedule and + NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. If the + key is empty, operator must be Exists; this combination + means to match all values and all keys. type: string - volumeMode: - description: volumeMode defines what type of volume is - required by the claim. Value of Filesystem is implied - when not included in claim spec. + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and Equal. + Defaults to Equal. Exists is equivalent to wildcard + for value, so that a pod can tolerate all taints of + a particular category. type: string - volumeName: - description: VolumeName is the binding reference to the - PersistentVolume backing this claim. + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the + taint forever (do not evict). Zero and negative values + will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. type: string type: object - status: - description: 'Status represents the current information/status - of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' - properties: - accessModes: - description: 'AccessModes contains the actual access modes - the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' - items: - type: string - type: array - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Represents the actual resources of the underlying - volume. - type: object - conditions: - description: Current Condition of persistent volume claim. - If underlying persistent volume is being resized then - the Condition will be set to 'ResizeStarted'. - items: - description: PersistentVolumeClaimCondition contails - details about state of pvc + type: array + volumeClaimTemplate: + description: VolumeClaimTemplate allows a user to specify how + volumes inside a Tenant + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of + this representation of an object. Servers should convert + recognized schemas to the latest internal value, and may + reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + spec: + description: 'Spec defines the desired characteristics of + a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'AccessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'This field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot + - Beta) * An existing PVC (PersistentVolumeClaim) + * An existing custom resource/object that implements + data population (Alpha) In order to use VolumeSnapshot + object types, the appropriate feature gate must be + enabled (VolumeSnapshotDataSource or AnyVolumeDataSource) + If the provisioner or an external controller can support + the specified data source, it will create a new volume + based on the contents of the specified data source. + If the specified data source is not supported, the + volume will not be created and the failure will be + reported as an event. In the future, we plan to support + more data source types and the behavior of the provisioner + may change.' properties: - lastProbeTime: - description: Last time we probed the condition. - format: date-time - type: string - lastTransitionTime: - description: Last time the condition transitioned - from one status to another. - format: date-time + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. type: string - message: - description: Human-readable message indicating details - about last transition. + kind: + description: Kind is the type of resource being + referenced type: string - reason: - description: Unique, this should be a short, machine - understandable string that gives the reason for - condition's last transition. If it reports "ResizeStarted" - that means the underlying persistent volume is - being resized. - type: string - status: - type: string - type: - description: PersistentVolumeClaimConditionType - is a valid value of PersistentVolumeClaimCondition.Type + name: + description: Name is the name of resource being + referenced type: string required: - - status - - type + - kind + - name type: object - type: array - phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - type: object - type: object - volumesPerServer: - description: Number of persistent volumes that will be attached - per server - format: int32 - type: integer + resources: + description: 'Resources represents the minimum resources + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is + omitted for a container, it defaults to Limits + if that is explicitly specified, otherwise to + an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + selector: + description: A label query over volumes to consider + for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + storageClassName: + description: 'Name of the StorageClass required by the + claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume + is required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: VolumeName is the binding reference to + the PersistentVolume backing this claim. + type: string + type: object + status: + description: 'Status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'AccessModes contains the actual access + modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Represents the actual resources of the + underlying volume. + type: object + conditions: + description: Current Condition of persistent volume + claim. If underlying persistent volume is being resized + then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contails + details about state of pvc + properties: + lastProbeTime: + description: Last time we probed the condition. + format: date-time + type: string + lastTransitionTime: + description: Last time the condition transitioned + from one status to another. + format: date-time + type: string + message: + description: Human-readable message indicating + details about last transition. + type: string + reason: + description: Unique, this should be a short, machine + understandable string that gives the reason + for condition's last transition. If it reports + "ResizeStarted" that means the underlying persistent + volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: Phase represents the current phase of PersistentVolumeClaim. + type: string + type: object + type: object + volumesPerServer: + description: Number of persistent volumes that will be attached + per server + format: int32 + type: integer + required: + - servers + - volumeClaimTemplate + - volumesPerServer + type: object + type: array + priorityClassName: + description: PriorityClassName indicates the Pod priority and hence + importance of a Pod relative to other Pods. This is applied to MinIO + pods only. Refer Kubernetes documentation for details https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass + type: string + requestAutoCert: + description: 'RequestAutoCert allows user to enable Kubernetes based + TLS cert generation and signing as explained here: https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/' + type: boolean + s3: + description: S3 related features can be disabled or enabled such as + `bucketDNS` etc. + properties: + bucketDNS: + description: BucketDNS if 'true' means Buckets can be accessed + using `.minio.default.svc.cluster.local` + type: boolean required: - - servers - - volumeClaimTemplate - - volumesPerServer + - bucketDNS type: object - type: array - priorityClassName: - description: PriorityClassName indicates the Pod priority and hence - importance of a Pod relative to other Pods. This is applied to MinIO - pods only. Refer Kubernetes documentation for details https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass - type: string - requestAutoCert: - description: 'RequestAutoCert allows user to enable Kubernetes based - TLS cert generation and signing as explained here: https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/' - type: boolean - s3: - description: S3 related features can be disabled or enabled such as - `bucketDNS` etc. - properties: - bucketDNS: - description: BucketDNS if 'true' means Buckets can be accessed using - `.minio.default.svc.cluster.local` - type: boolean - required: - - bucketDNS - type: object - securityContext: - description: Security Context allows user to set entries like runAsUser, - privilege escalation etc. - properties: - fsGroup: - description: "A special supplemental group that applies to all containers - in a pod. Some volume types allow the Kubelet to change the ownership - of that volume to be owned by the pod: \n 1. The owning GID will - be the FSGroup 2. The setgid bit is set (new files created in - the volume will be owned by FSGroup) 3. The permission bits are - OR'd with rw-rw---- \n If unset, the Kubelet will not modify the - ownership and permissions of any volume." - format: int64 - type: integer - fsGroupChangePolicy: - description: 'fsGroupChangePolicy defines behavior of changing ownership - and permission of the volume before being exposed inside Pod. - This field will only apply to volume types which support fsGroup - based ownership(and permissions). It will have no effect on ephemeral - volume types such as: secret, configmaps and emptydir. Valid values - are "OnRootMismatch" and "Always". If not specified defaults to - "Always".' - type: string - runAsGroup: - description: The GID to run the entrypoint of the container process. - Uses runtime default if unset. May also be set in SecurityContext. If - set in both SecurityContext and PodSecurityContext, the value - specified in SecurityContext takes precedence for that container. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root - user. If true, the Kubelet will validate the image at runtime - to ensure that it does not run as UID 0 (root) and fail to start - the container if it does. If unset or false, no such validation - will be performed. May also be set in SecurityContext. If set - in both SecurityContext and PodSecurityContext, the value specified - in SecurityContext takes precedence. - type: boolean - runAsUser: - description: The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. May - also be set in SecurityContext. If set in both SecurityContext - and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux - context for each container. May also be set in SecurityContext. If - set in both SecurityContext and PodSecurityContext, the value - specified in SecurityContext takes precedence for that container. - properties: - level: - description: Level is SELinux level label that applies to the - container. - type: string - role: - description: Role is a SELinux role label that applies to the - container. - type: string - type: - description: Type is a SELinux type label that applies to the - container. - type: string - user: - description: User is a SELinux user label that applies to the - container. - type: string - type: object - supplementalGroups: - description: A list of groups applied to the first process run in - each container, in addition to the container's primary GID. If - unspecified, no groups will be added to any container. - items: + securityContext: + description: Security Context allows user to set entries like runAsUser, + privilege escalation etc. + properties: + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume." format: int64 type: integer - type: array - sysctls: - description: Sysctls hold a list of namespaced sysctls used for - the pod. Pods with unsupported sysctls (by the container runtime) - might fail to launch. - items: - description: Sysctl defines a kernel parameter to be set + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified defaults to "Always".' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. properties: - name: - description: Name of a property to set + level: + description: Level is SELinux level label that applies to + the container. type: string - value: - description: Value of a property to set + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. type: string - required: - - name - - value type: object - type: array - windowsOptions: - description: The Windows specific settings applied to all containers. - If unspecified, the options within a container's SecurityContext - will be used. If set in both SecurityContext and PodSecurityContext, - the value specified in SecurityContext takes precedence. - properties: - gmsaCredentialSpec: - description: GMSACredentialSpec is where the GMSA admission - webhook (https://github.com/kubernetes-sigs/windows-gmsa) - inlines the contents of the GMSA credential spec named by - the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the GMSA - credential spec to use. - type: string - runAsUserName: - description: The UserName in Windows to run the entrypoint of - the container process. Defaults to the user specified in image - metadata if unspecified. May also be set in PodSecurityContext. - If set in both SecurityContext and PodSecurityContext, the - value specified in SecurityContext takes precedence. - type: string - type: object - type: object - serviceAccountName: - description: ServiceAccountName is the name of the ServiceAccount to - use to run pods of all MinIO Pods created as a part of this Tenant. - type: string - subPath: - description: Subpath inside mount path. This is the directory where - MinIO stores data. Default to "" (empty) - type: string - required: - - pools - type: object - status: - description: Status provides details of the state of the Tenant - properties: - availableReplicas: - format: int32 - type: integer - currentState: - type: string - required: - - availableReplicas - - currentState - type: object - required: - - spec - type: object - version: v1 - versions: - - name: v1 + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID. If + unspecified, no groups will be added to any container. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + serviceAccountName: + description: ServiceAccountName is the name of the ServiceAccount + to use to run pods of all MinIO Pods created as a part of this Tenant. + type: string + subPath: + description: Subpath inside mount path. This is the directory where + MinIO stores data. Default to "" (empty) + type: string + required: + - pools + type: object + status: + description: Status provides details of the state of the Tenant + properties: + availableReplicas: + format: int32 + type: integer + currentState: + type: string + required: + - availableReplicas + - currentState + type: object + required: + - spec + type: object served: true storage: true + subresources: + status: {} status: acceptedNames: kind: "" diff --git a/pkg/resources/services/service.go b/pkg/resources/services/service.go index e6df1c043db..94b74e8cb2e 100644 --- a/pkg/resources/services/service.go +++ b/pkg/resources/services/service.go @@ -29,14 +29,11 @@ import ( // NewClusterIPForMinIO will return a new headless Kubernetes service for a Tenant func NewClusterIPForMinIO(t *miniov1.Tenant) *corev1.Service { - var port int32 - var name string + var port int32 = miniov1.MinIOPortLoadBalancerSVC + var name string = miniov1.MinIOServiceHTTPPortName if t.TLS() { port = miniov1.MinIOTLSPortLoadBalancerSVC name = miniov1.MinIOServiceHTTPSPortName - } else { - port = miniov1.MinIOPortLoadBalancerSVC - name = miniov1.MinIOServiceHTTPPortName } minioPort := corev1.ServicePort{ Port: port, @@ -62,14 +59,11 @@ func NewClusterIPForMinIO(t *miniov1.Tenant) *corev1.Service { // ServiceForBucket will return a external name based service func ServiceForBucket(t *miniov1.Tenant, bucket string) *corev1.Service { - var port int32 - var name string + var port int32 = miniov1.MinIOPortLoadBalancerSVC + var name string = miniov1.MinIOServiceHTTPPortName if t.TLS() { port = miniov1.MinIOTLSPortLoadBalancerSVC name = miniov1.MinIOServiceHTTPSPortName - } else { - port = miniov1.MinIOPortLoadBalancerSVC - name = miniov1.MinIOServiceHTTPPortName } minioPort := corev1.ServicePort{ Port: port, @@ -157,7 +151,9 @@ func NewHeadlessForLog(t *miniov1.Tenant) *corev1.Service { // NewClusterIPForConsole will return a new cluster IP service for Console Deployment func NewClusterIPForConsole(t *miniov1.Tenant) *corev1.Service { consolePort := corev1.ServicePort{Port: miniov1.ConsolePort, Name: miniov1.ConsoleServicePortName} - consoleTLSPort := corev1.ServicePort{Port: miniov1.ConsoleTLSPort, Name: miniov1.ConsoleServiceTLSPortName} + if t.TLS() { + consolePort = corev1.ServicePort{Port: miniov1.ConsoleTLSPort, Name: miniov1.ConsoleServiceTLSPortName} + } svc := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Labels: t.ConsolePodLabels(), @@ -168,7 +164,6 @@ func NewClusterIPForConsole(t *miniov1.Tenant) *corev1.Service { Spec: corev1.ServiceSpec{ Ports: []corev1.ServicePort{ consolePort, - consoleTLSPort, }, Selector: t.ConsolePodLabels(), Type: corev1.ServiceTypeClusterIP, From 81875405de30ab96a5fdb2f0b527bd90dec08a45 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 4 Dec 2020 13:53:30 -0800 Subject: [PATCH 2/2] Apply suggestions from code review --- pkg/resources/services/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/resources/services/service.go b/pkg/resources/services/service.go index 94b74e8cb2e..0b221e1ba0b 100644 --- a/pkg/resources/services/service.go +++ b/pkg/resources/services/service.go @@ -151,7 +151,7 @@ func NewHeadlessForLog(t *miniov1.Tenant) *corev1.Service { // NewClusterIPForConsole will return a new cluster IP service for Console Deployment func NewClusterIPForConsole(t *miniov1.Tenant) *corev1.Service { consolePort := corev1.ServicePort{Port: miniov1.ConsolePort, Name: miniov1.ConsoleServicePortName} - if t.TLS() { + if t.TLS() || t.ConsoleExternalCert() { consolePort = corev1.ServicePort{Port: miniov1.ConsoleTLSPort, Name: miniov1.ConsoleServiceTLSPortName} } svc := &corev1.Service{