From 10751e54e6f01ed771a8fb75abd90346ee4ab501 Mon Sep 17 00:00:00 2001 From: YuxiJin-tobeyjin Date: Wed, 25 Oct 2017 16:20:32 +0800 Subject: [PATCH 01/58] Should use Fatalf while need to format the output --- staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go index d7c7f0f10d3..dbf97feeb4e 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go @@ -1161,7 +1161,7 @@ func testPropogateStore(ctx context.Context, t *testing.T, store *store, obj *ex key := "/testkey" err := store.unconditionalDelete(ctx, key, &example.Pod{}) if err != nil && !storage.IsNotFound(err) { - t.Fatal("Cleanup failed: %v", err) + t.Fatalf("Cleanup failed: %v", err) } setOutput := &example.Pod{} if err := store.Create(ctx, key, obj, setOutput, 0); err != nil { From 2e177ef9b28dab0b6eccc5d673d6ab32fdeddf46 Mon Sep 17 00:00:00 2001 From: Fabian Ruff Date: Wed, 22 Nov 2017 23:44:07 +0100 Subject: [PATCH 02/58] return routes for unknown next hops --- pkg/cloudprovider/providers/openstack/openstack_routes.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/pkg/cloudprovider/providers/openstack/openstack_routes.go b/pkg/cloudprovider/providers/openstack/openstack_routes.go index c5f0974dadd..a73001b0086 100644 --- a/pkg/cloudprovider/providers/openstack/openstack_routes.go +++ b/pkg/cloudprovider/providers/openstack/openstack_routes.go @@ -77,15 +77,9 @@ func (r *Routes) ListRoutes(clusterName string) ([]*cloudprovider.Route, error) var routes []*cloudprovider.Route for _, item := range router.Routes { - nodeName, ok := nodeNamesByAddr[item.NextHop] - if !ok { - // Not one of our routes? - glog.V(4).Infof("Skipping route with unknown nexthop %v", item.NextHop) - continue - } route := cloudprovider.Route{ Name: item.DestinationCIDR, - TargetNode: nodeName, + TargetNode: nodeNamesByAddr[item.NextHop], //empty if NextHop is unknown DestinationCIDR: item.DestinationCIDR, } routes = append(routes, &route) From 51a367f8061f638354023474e7d31eb34dc99ac7 Mon Sep 17 00:00:00 2001 From: Fabian Ruff Date: Wed, 29 Nov 2017 16:24:00 +0100 Subject: [PATCH 03/58] relax server list option, set Blackhole field --- pkg/cloudprovider/providers/openstack/openstack_routes.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/cloudprovider/providers/openstack/openstack_routes.go b/pkg/cloudprovider/providers/openstack/openstack_routes.go index a73001b0086..7b2796799c7 100644 --- a/pkg/cloudprovider/providers/openstack/openstack_routes.go +++ b/pkg/cloudprovider/providers/openstack/openstack_routes.go @@ -53,7 +53,7 @@ func (r *Routes) ListRoutes(clusterName string) ([]*cloudprovider.Route, error) glog.V(4).Infof("ListRoutes(%v)", clusterName) nodeNamesByAddr := make(map[string]types.NodeName) - err := foreachServer(r.compute, servers.ListOpts{Status: "ACTIVE"}, func(srv *servers.Server) (bool, error) { + err := foreachServer(r.compute, servers.ListOpts{}, func(srv *servers.Server) (bool, error) { addrs, err := nodeAddresses(srv) if err != nil { return false, err @@ -77,9 +77,11 @@ func (r *Routes) ListRoutes(clusterName string) ([]*cloudprovider.Route, error) var routes []*cloudprovider.Route for _, item := range router.Routes { + nodeName, foundNode := nodeNamesByAddr[item.NextHop] route := cloudprovider.Route{ Name: item.DestinationCIDR, - TargetNode: nodeNamesByAddr[item.NextHop], //empty if NextHop is unknown + TargetNode: nodeName, //empty if NextHop is unknown + Blackhole: !foundNode, DestinationCIDR: item.DestinationCIDR, } routes = append(routes, &route) From 63e2eacd22b5050140f9630d8ec430a54361d228 Mon Sep 17 00:00:00 2001 From: Ryan Phillips Date: Tue, 19 Dec 2017 15:04:56 -0600 Subject: [PATCH 04/58] add semver metadata regex * supports v1.9.0+stable.0 --- hack/lib/version.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/lib/version.sh b/hack/lib/version.sh index 1e819b6e51a..f8cf2ea2b9c 100644 --- a/hack/lib/version.sh +++ b/hack/lib/version.sh @@ -89,7 +89,7 @@ kube::version::get_version_vars() { # Try to match the "git describe" output to a regex to try to extract # the "major" and "minor" versions and whether this is the exact tagged # version or whether the tree is between two tagged versions. - if [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?([-].*)?$ ]]; then + if [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?([-].*)?([+].*)?$ ]]; then KUBE_GIT_MAJOR=${BASH_REMATCH[1]} KUBE_GIT_MINOR=${BASH_REMATCH[2]} if [[ -n "${BASH_REMATCH[4]}" ]]; then From ffba27d72ee3fc85766dbd0971fccaa61fe4736c Mon Sep 17 00:00:00 2001 From: Josh Horwitz Date: Sat, 25 Nov 2017 13:44:39 -0500 Subject: [PATCH 05/58] Refactor service controller to common controller pattern --- pkg/controller/service/service_controller.go | 144 +++++++----------- .../service/service_controller_test.go | 76 +++------ 2 files changed, 73 insertions(+), 147 deletions(-) diff --git a/pkg/controller/service/service_controller.go b/pkg/controller/service/service_controller.go index 3496f0681ca..4854fc4f1cf 100644 --- a/pkg/controller/service/service_controller.go +++ b/pkg/controller/service/service_controller.go @@ -60,11 +60,6 @@ const ( clientRetryCount = 5 clientRetryInterval = 5 * time.Second - retryable = true - notRetryable = false - - doNotRetry = time.Duration(0) - // LabelNodeRoleMaster specifies that a node is a master // It's copied over to kubeadm until it's merged in core: https://github.com/kubernetes/kubernetes/pull/39112 LabelNodeRoleMaster = "node-role.kubernetes.io/master" @@ -77,8 +72,6 @@ const ( type cachedService struct { // The cached state of the service state *v1.Service - // Controls error back-off - lastRetryDelay time.Duration } type serviceCache struct { @@ -86,6 +79,8 @@ type serviceCache struct { serviceMap map[string]*cachedService } +// ServiceController keeps cloud provider service resources +// (like load balancers) in sync with the registry. type ServiceController struct { cloud cloudprovider.Interface knownHosts []*v1.Node @@ -101,7 +96,7 @@ type ServiceController struct { nodeLister corelisters.NodeLister nodeListerSynced cache.InformerSynced // services that need to be synced - workingQueue workqueue.DelayingInterface + queue workqueue.RateLimitingInterface } // New returns a new service controller to keep cloud provider service resources @@ -134,7 +129,7 @@ func New( eventRecorder: recorder, nodeLister: nodeInformer.Lister(), nodeListerSynced: nodeInformer.Informer().HasSynced, - workingQueue: workqueue.NewNamedDelayingQueue("service"), + queue: workqueue.NewNamedRateLimitingQueue(workqueue.NewItemExponentialFailureRateLimiter(minRetryDelay, maxRetryDelay), "service"), } serviceInformer.Informer().AddEventHandlerWithResyncPeriod( @@ -167,7 +162,7 @@ func (s *ServiceController) enqueueService(obj interface{}) { glog.Errorf("Couldn't get key for object %#v: %v", obj, err) return } - s.workingQueue.Add(key) + s.queue.Add(key) } // Run starts a background goroutine that watches for changes to services that @@ -182,7 +177,7 @@ func (s *ServiceController) enqueueService(obj interface{}) { // object. func (s *ServiceController) Run(stopCh <-chan struct{}, workers int) { defer runtime.HandleCrash() - defer s.workingQueue.ShutDown() + defer s.queue.ShutDown() glog.Info("Starting service controller") defer glog.Info("Shutting down service controller") @@ -203,21 +198,28 @@ func (s *ServiceController) Run(stopCh <-chan struct{}, workers int) { // worker runs a worker thread that just dequeues items, processes them, and marks them done. // It enforces that the syncHandler is never invoked concurrently with the same key. func (s *ServiceController) worker() { - for { - func() { - key, quit := s.workingQueue.Get() - if quit { - return - } - defer s.workingQueue.Done(key) - err := s.syncService(key.(string)) - if err != nil { - glog.Errorf("Error syncing service: %v", err) - } - }() + for s.processNextWorkItem() { } } +func (s *ServiceController) processNextWorkItem() bool { + key, quit := s.queue.Get() + if quit { + return false + } + defer s.queue.Done(key) + + err := s.syncService(key.(string)) + if err == nil { + s.queue.Forget(key) + return true + } + + runtime.HandleError(fmt.Errorf("error processing service %v (will retry): %v", key, err)) + s.queue.AddRateLimited(key) + return true +} + func (s *ServiceController) init() error { if s.cloud == nil { return fmt.Errorf("WARNING: no cloud provider provided, services of type LoadBalancer will fail") @@ -235,31 +237,21 @@ func (s *ServiceController) init() error { // Returns an error if processing the service update failed, along with a time.Duration // indicating whether processing should be retried; zero means no-retry; otherwise // we should retry in that Duration. -func (s *ServiceController) processServiceUpdate(cachedService *cachedService, service *v1.Service, key string) (error, time.Duration) { +func (s *ServiceController) processServiceUpdate(cachedService *cachedService, service *v1.Service, key string) error { if cachedService.state != nil { if cachedService.state.UID != service.UID { - err, retry := s.processLoadBalancerDelete(cachedService, key) + err := s.processLoadBalancerDelete(cachedService, key) if err != nil { - return err, retry + return err } } } // cache the service, we need the info for service deletion cachedService.state = service - err, retry := s.createLoadBalancerIfNeeded(key, service) + err := s.createLoadBalancerIfNeeded(key, service) if err != nil { - message := "Error creating load balancer" - var retryToReturn time.Duration - if retry { - message += " (will retry): " - retryToReturn = cachedService.nextRetryDelay() - } else { - message += " (will not retry): " - retryToReturn = doNotRetry - } - message += err.Error() - s.eventRecorder.Event(service, v1.EventTypeWarning, "CreatingLoadBalancerFailed", message) - return err, retryToReturn + s.eventRecorder.Eventf(service, v1.EventTypeWarning, "CreatingLoadBalancerFailed", "Error creating load balancer (will retry): %v", err) + return err } // Always update the cache upon success. // NOTE: Since we update the cached service if and only if we successfully @@ -267,13 +259,12 @@ func (s *ServiceController) processServiceUpdate(cachedService *cachedService, s // been successfully processed. s.cache.set(key, cachedService) - cachedService.resetRetryDelay() - return nil, doNotRetry + return nil } // Returns whatever error occurred along with a boolean indicator of whether it // should be retried. -func (s *ServiceController) createLoadBalancerIfNeeded(key string, service *v1.Service) (error, bool) { +func (s *ServiceController) createLoadBalancerIfNeeded(key string, service *v1.Service) error { // Note: It is safe to just call EnsureLoadBalancer. But, on some clouds that requires a delete & create, // which may involve service interruption. Also, we would like user-friendly events. @@ -285,13 +276,13 @@ func (s *ServiceController) createLoadBalancerIfNeeded(key string, service *v1.S if !wantsLoadBalancer(service) { _, exists, err := s.balancer.GetLoadBalancer(s.clusterName, service) if err != nil { - return fmt.Errorf("error getting LB for service %s: %v", key, err), retryable + return fmt.Errorf("error getting LB for service %s: %v", key, err) } if exists { glog.Infof("Deleting existing load balancer for service %s that no longer needs a load balancer.", key) s.eventRecorder.Event(service, v1.EventTypeNormal, "DeletingLoadBalancer", "Deleting load balancer") if err := s.balancer.EnsureLoadBalancerDeleted(s.clusterName, service); err != nil { - return err, retryable + return err } s.eventRecorder.Event(service, v1.EventTypeNormal, "DeletedLoadBalancer", "Deleted load balancer") } @@ -305,7 +296,7 @@ func (s *ServiceController) createLoadBalancerIfNeeded(key string, service *v1.S s.eventRecorder.Event(service, v1.EventTypeNormal, "EnsuringLoadBalancer", "Ensuring load balancer") newState, err = s.ensureLoadBalancer(service) if err != nil { - return fmt.Errorf("failed to ensure load balancer for service %s: %v", key, err), retryable + return fmt.Errorf("failed to ensure load balancer for service %s: %v", key, err) } s.eventRecorder.Event(service, v1.EventTypeNormal, "EnsuredLoadBalancer", "Ensured load balancer") } @@ -320,13 +311,14 @@ func (s *ServiceController) createLoadBalancerIfNeeded(key string, service *v1.S service.Status.LoadBalancer = *newState if err := s.persistUpdate(service); err != nil { - return fmt.Errorf("failed to persist updated status to apiserver, even after retries. Giving up: %v", err), notRetryable + runtime.HandleError(fmt.Errorf("failed to persist service %q updated status to apiserver, even after retries. Giving up: %v", key, err)) + return nil } } else { glog.V(2).Infof("Not persisting unchanged LoadBalancerStatus for service %s to registry.", key) } - return nil, notRetryable + return nil } func (s *ServiceController) persistUpdate(service *v1.Service) error { @@ -721,31 +713,12 @@ func loadBalancerIPsAreEqual(oldService, newService *v1.Service) bool { return oldService.Spec.LoadBalancerIP == newService.Spec.LoadBalancerIP } -// Computes the next retry, using exponential backoff -// mutex must be held. -func (s *cachedService) nextRetryDelay() time.Duration { - s.lastRetryDelay = s.lastRetryDelay * 2 - if s.lastRetryDelay < minRetryDelay { - s.lastRetryDelay = minRetryDelay - } - if s.lastRetryDelay > maxRetryDelay { - s.lastRetryDelay = maxRetryDelay - } - return s.lastRetryDelay -} - -// Resets the retry exponential backoff. mutex must be held. -func (s *cachedService) resetRetryDelay() { - s.lastRetryDelay = time.Duration(0) -} - // syncService will sync the Service with the given key if it has had its expectations fulfilled, // meaning it did not expect to see any more of its pods created or deleted. This function is not meant to be // invoked concurrently with the same key. func (s *ServiceController) syncService(key string) error { startTime := time.Now() var cachedService *cachedService - var retryDelay time.Duration defer func() { glog.V(4).Infof("Finished syncing service %q (%v)", key, time.Since(startTime)) }() @@ -760,59 +733,44 @@ func (s *ServiceController) syncService(key string) error { switch { case errors.IsNotFound(err): // service absence in store means watcher caught the deletion, ensure LB info is cleaned - glog.Infof("Service has been deleted %v", key) - err, retryDelay = s.processServiceDeletion(key) + glog.Infof("Service has been deleted %v. Attempting to cleanup load balancer resources", key) + err = s.processServiceDeletion(key) case err != nil: glog.Infof("Unable to retrieve service %v from store: %v", key, err) - s.workingQueue.Add(key) - return err default: cachedService = s.cache.getOrCreate(key) - err, retryDelay = s.processServiceUpdate(cachedService, service, key) + err = s.processServiceUpdate(cachedService, service, key) } - if retryDelay != 0 { - // Add the failed service back to the queue so we'll retry it. - glog.Errorf("Failed to process service %v. Retrying in %s: %v", key, retryDelay, err) - go func(obj interface{}, delay time.Duration) { - // put back the service key to working queue, it is possible that more entries of the service - // were added into the queue during the delay, but it does not mess as when handling the retry, - // it always get the last service info from service store - s.workingQueue.AddAfter(obj, delay) - }(key, retryDelay) - } else if err != nil { - runtime.HandleError(fmt.Errorf("failed to process service %v. Not retrying: %v", key, err)) - } - return nil + return err } // Returns an error if processing the service deletion failed, along with a time.Duration // indicating whether processing should be retried; zero means no-retry; otherwise // we should retry after that Duration. -func (s *ServiceController) processServiceDeletion(key string) (error, time.Duration) { +func (s *ServiceController) processServiceDeletion(key string) error { cachedService, ok := s.cache.get(key) if !ok { - return fmt.Errorf("service %s not in cache even though the watcher thought it was. Ignoring the deletion", key), doNotRetry + glog.Errorf("service %s not in cache even though the watcher thought it was. Ignoring the deletion", key) + return nil } return s.processLoadBalancerDelete(cachedService, key) } -func (s *ServiceController) processLoadBalancerDelete(cachedService *cachedService, key string) (error, time.Duration) { +func (s *ServiceController) processLoadBalancerDelete(cachedService *cachedService, key string) error { service := cachedService.state // delete load balancer info only if the service type is LoadBalancer if !wantsLoadBalancer(service) { - return nil, doNotRetry + return nil } s.eventRecorder.Event(service, v1.EventTypeNormal, "DeletingLoadBalancer", "Deleting load balancer") err := s.balancer.EnsureLoadBalancerDeleted(s.clusterName, service) if err != nil { - message := "Error deleting load balancer (will retry): " + err.Error() - s.eventRecorder.Event(service, v1.EventTypeWarning, "DeletingLoadBalancerFailed", message) - return err, cachedService.nextRetryDelay() + s.eventRecorder.Eventf(service, v1.EventTypeWarning, "DeletingLoadBalancerFailed", "Error deleting load balancer (will retry): %v", err) + return err } s.eventRecorder.Event(service, v1.EventTypeNormal, "DeletedLoadBalancer", "Deleted load balancer") s.cache.delete(key) - cachedService.resetRetryDelay() - return nil, doNotRetry + return nil } diff --git a/pkg/controller/service/service_controller_test.go b/pkg/controller/service/service_controller_test.go index 0c4990adb1a..0241cb1d22d 100644 --- a/pkg/controller/service/service_controller_test.go +++ b/pkg/controller/service/service_controller_test.go @@ -20,7 +20,6 @@ import ( "fmt" "reflect" "testing" - "time" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -129,7 +128,7 @@ func TestCreateExternalLoadBalancer(t *testing.T) { for _, item := range table { controller, cloud, client := newController() - err, _ := controller.createLoadBalancerIfNeeded("foo/bar", item.service) + err := controller.createLoadBalancerIfNeeded("foo/bar", item.service) if !item.expectErr && err != nil { t.Errorf("unexpected error: %v", err) } else if item.expectErr && err == nil { @@ -320,7 +319,7 @@ func TestProcessServiceUpdate(t *testing.T) { key string updateFn func(*v1.Service) *v1.Service //Manipulate the structure svc *v1.Service - expectedFn func(*v1.Service, error, time.Duration) error //Error comparision function + expectedFn func(*v1.Service, error) error //Error comparision function }{ { testName: "If updating a valid service", @@ -333,15 +332,8 @@ func TestProcessServiceUpdate(t *testing.T) { return svc }, - expectedFn: func(svc *v1.Service, err error, retryDuration time.Duration) error { - - if err != nil { - return err - } - if retryDuration != doNotRetry { - return fmt.Errorf("retryDuration Expected=%v Obtained=%v", doNotRetry, retryDuration) - } - return nil + expectedFn: func(svc *v1.Service, err error) error { + return err }, }, { @@ -358,9 +350,9 @@ func TestProcessServiceUpdate(t *testing.T) { cachedServiceTest.state = svc controller.cache.set(keyExpected, cachedServiceTest) - keyGot, quit := controller.workingQueue.Get() + keyGot, quit := controller.queue.Get() if quit { - t.Fatalf("get no workingQueue element") + t.Fatalf("get no queue element") } if keyExpected != keyGot.(string) { t.Fatalf("get service key error, expected: %s, got: %s", keyExpected, keyGot.(string)) @@ -372,20 +364,17 @@ func TestProcessServiceUpdate(t *testing.T) { return newService }, - expectedFn: func(svc *v1.Service, err error, retryDuration time.Duration) error { + expectedFn: func(svc *v1.Service, err error) error { if err != nil { return err } - if retryDuration != doNotRetry { - return fmt.Errorf("retryDuration Expected=%v Obtained=%v", doNotRetry, retryDuration) - } keyExpected := svc.GetObjectMeta().GetNamespace() + "/" + svc.GetObjectMeta().GetName() cachedServiceGot, exist := controller.cache.get(keyExpected) if !exist { - return fmt.Errorf("update service error, workingQueue should contain service: %s", keyExpected) + return fmt.Errorf("update service error, queue should contain service: %s", keyExpected) } if cachedServiceGot.state.Spec.LoadBalancerIP != newLBIP { return fmt.Errorf("update LoadBalancerIP error, expected: %s, got: %s", newLBIP, cachedServiceGot.state.Spec.LoadBalancerIP) @@ -398,8 +387,8 @@ func TestProcessServiceUpdate(t *testing.T) { for _, tc := range testCases { newSvc := tc.updateFn(tc.svc) svcCache := controller.cache.getOrCreate(tc.key) - obtErr, retryDuration := controller.processServiceUpdate(svcCache, newSvc, tc.key) - if err := tc.expectedFn(newSvc, obtErr, retryDuration); err != nil { + obtErr := controller.processServiceUpdate(svcCache, newSvc, tc.key) + if err := tc.expectedFn(newSvc, obtErr); err != nil { t.Errorf("%v processServiceUpdate() %v", tc.testName, err) } } @@ -491,33 +480,21 @@ func TestProcessServiceDeletion(t *testing.T) { var controller *ServiceController var cloud *fakecloud.FakeCloud - //Add a global svcKey name + // Add a global svcKey name svcKey := "external-balancer" testCases := []struct { testName string - updateFn func(*ServiceController) //Update function used to manupulate srv and controller values - expectedFn func(svcErr error, retryDuration time.Duration) error //Function to check if the returned value is expected + updateFn func(*ServiceController) // Update function used to manupulate srv and controller values + expectedFn func(svcErr error) error // Function to check if the returned value is expected }{ { testName: "If an non-existant service is deleted", updateFn: func(controller *ServiceController) { - //Does not do anything + // Does not do anything }, - expectedFn: func(svcErr error, retryDuration time.Duration) error { - - expectedError := "service external-balancer not in cache even though the watcher thought it was. Ignoring the deletion" - if svcErr == nil || svcErr.Error() != expectedError { - //cannot be nil or Wrong error message - return fmt.Errorf("Expected=%v Obtained=%v", expectedError, svcErr) - } - - if retryDuration != doNotRetry { - //Retry duration should match - return fmt.Errorf("RetryDuration Expected=%v Obtained=%v", doNotRetry, retryDuration) - } - - return nil + expectedFn: func(svcErr error) error { + return svcErr }, }, { @@ -529,7 +506,7 @@ func TestProcessServiceDeletion(t *testing.T) { cloud.Err = fmt.Errorf("Error Deleting the Loadbalancer") }, - expectedFn: func(svcErr error, retryDuration time.Duration) error { + expectedFn: func(svcErr error) error { expectedError := "Error Deleting the Loadbalancer" @@ -537,9 +514,6 @@ func TestProcessServiceDeletion(t *testing.T) { return fmt.Errorf("Expected=%v Obtained=%v", expectedError, svcErr) } - if retryDuration != minRetryDelay { - return fmt.Errorf("RetryDuration Expected=%v Obtained=%v", minRetryDelay, retryDuration) - } return nil }, }, @@ -554,21 +528,15 @@ func TestProcessServiceDeletion(t *testing.T) { controller.cache.set(svcKey, svc) }, - expectedFn: func(svcErr error, retryDuration time.Duration) error { - + expectedFn: func(svcErr error) error { if svcErr != nil { return fmt.Errorf("Expected=nil Obtained=%v", svcErr) } - if retryDuration != doNotRetry { - //Retry duration should match - return fmt.Errorf("RetryDuration Expected=%v Obtained=%v", doNotRetry, retryDuration) - } - - //It should no longer be in the workqueue. + // It should no longer be in the workqueue. _, exist := controller.cache.get(svcKey) if exist { - return fmt.Errorf("delete service error, workingQueue should not contain service: %s any more", svcKey) + return fmt.Errorf("delete service error, queue should not contain service: %s any more", svcKey) } return nil @@ -580,8 +548,8 @@ func TestProcessServiceDeletion(t *testing.T) { //Create a new controller. controller, cloud, _ = newController() tc.updateFn(controller) - obtainedErr, retryDuration := controller.processServiceDeletion(svcKey) - if err := tc.expectedFn(obtainedErr, retryDuration); err != nil { + obtainedErr := controller.processServiceDeletion(svcKey) + if err := tc.expectedFn(obtainedErr); err != nil { t.Errorf("%v processServiceDeletion() %v", tc.testName, err) } } From ddf97084f5a7259656084094a2ffb81a4f58d869 Mon Sep 17 00:00:00 2001 From: Di Xu Date: Mon, 20 Nov 2017 12:40:51 +0800 Subject: [PATCH 06/58] update vendor spf13/cobra to enforce required flags --- Godeps/Godeps.json | 4 +- .../Godeps/Godeps.json | 2 +- .../k8s.io/kube-aggregator/Godeps/Godeps.json | 2 +- .../sample-apiserver/Godeps/Godeps.json | 2 +- vendor/github.com/spf13/cobra/.travis.yml | 13 +- vendor/github.com/spf13/cobra/BUILD | 2 + vendor/github.com/spf13/cobra/README.md | 851 +++++++--------- vendor/github.com/spf13/cobra/args.go | 89 ++ .../spf13/cobra/bash_completions.go | 315 +++--- .../spf13/cobra/bash_completions.md | 4 +- vendor/github.com/spf13/cobra/cobra.go | 74 +- vendor/github.com/spf13/cobra/command.go | 936 ++++++++++-------- vendor/github.com/spf13/cobra/command_win.go | 8 +- vendor/github.com/spf13/cobra/doc/BUILD | 3 + vendor/github.com/spf13/cobra/doc/man_docs.go | 75 +- vendor/github.com/spf13/cobra/doc/man_docs.md | 11 +- vendor/github.com/spf13/cobra/doc/md_docs.go | 94 +- vendor/github.com/spf13/cobra/doc/md_docs.md | 23 +- .../github.com/spf13/cobra/doc/rest_docs.go | 185 ++++ .../github.com/spf13/cobra/doc/rest_docs.md | 114 +++ vendor/github.com/spf13/cobra/doc/util.go | 17 +- .../github.com/spf13/cobra/doc/yaml_docs.go | 169 ++++ .../github.com/spf13/cobra/doc/yaml_docs.md | 112 +++ .../github.com/spf13/cobra/zsh_completions.go | 126 +++ 24 files changed, 1977 insertions(+), 1254 deletions(-) create mode 100644 vendor/github.com/spf13/cobra/args.go create mode 100644 vendor/github.com/spf13/cobra/doc/rest_docs.go create mode 100644 vendor/github.com/spf13/cobra/doc/rest_docs.md create mode 100644 vendor/github.com/spf13/cobra/doc/yaml_docs.go create mode 100644 vendor/github.com/spf13/cobra/doc/yaml_docs.md create mode 100644 vendor/github.com/spf13/cobra/zsh_completions.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 691bd76f46e..592545de505 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -2470,11 +2470,11 @@ }, { "ImportPath": "github.com/spf13/cobra", - "Rev": "f62e98d28ab7ad31d707ba837a966378465c7b57" + "Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f" }, { "ImportPath": "github.com/spf13/cobra/doc", - "Rev": "f62e98d28ab7ad31d707ba837a966378465c7b57" + "Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f" }, { "ImportPath": "github.com/spf13/jwalterweatherman", diff --git a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json index 08607c1ddcf..f792000d584 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json @@ -328,7 +328,7 @@ }, { "ImportPath": "github.com/spf13/cobra", - "Rev": "f62e98d28ab7ad31d707ba837a966378465c7b57" + "Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f" }, { "ImportPath": "github.com/spf13/pflag", diff --git a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json index ec78f699e49..32d1debb00a 100644 --- a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json +++ b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json @@ -308,7 +308,7 @@ }, { "ImportPath": "github.com/spf13/cobra", - "Rev": "f62e98d28ab7ad31d707ba837a966378465c7b57" + "Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f" }, { "ImportPath": "github.com/spf13/pflag", diff --git a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json index 3281bf2fb31..a8c8d2a5cad 100644 --- a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json @@ -296,7 +296,7 @@ }, { "ImportPath": "github.com/spf13/cobra", - "Rev": "f62e98d28ab7ad31d707ba837a966378465c7b57" + "Rev": "19e54c4a2b8a78c9d54b2bed61b1a6c5e1bfcf6f" }, { "ImportPath": "github.com/spf13/pflag", diff --git a/vendor/github.com/spf13/cobra/.travis.yml b/vendor/github.com/spf13/cobra/.travis.yml index 6e84be54d16..68efa136331 100644 --- a/vendor/github.com/spf13/cobra/.travis.yml +++ b/vendor/github.com/spf13/cobra/.travis.yml @@ -1,11 +1,10 @@ language: go -go: - - 1.4.3 - - 1.5.4 - - 1.6.3 - - tip matrix: + include: + - go: 1.7.6 + - go: 1.8.3 + - go: tip allow_failures: - go: tip @@ -16,3 +15,7 @@ before_install: script: - PATH=$PATH:$PWD/bin go test -v ./... - go build + - diff -u <(echo -n) <(gofmt -d -s .) + - if [ -z $NOVET ]; then + diff -u <(echo -n) <(go tool vet . 2>&1 | grep -vE 'ExampleCommand|bash_completions.*Fprint'); + fi diff --git a/vendor/github.com/spf13/cobra/BUILD b/vendor/github.com/spf13/cobra/BUILD index 5c16bacbce2..158c8f10692 100644 --- a/vendor/github.com/spf13/cobra/BUILD +++ b/vendor/github.com/spf13/cobra/BUILD @@ -3,9 +3,11 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ + "args.go", "bash_completions.go", "cobra.go", "command.go", + "zsh_completions.go", ] + select({ "@io_bazel_rules_go//go/platform:android": [ "command_notwin.go", diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md index b338a0e4424..d7279e4f9f9 100644 --- a/vendor/github.com/spf13/cobra/README.md +++ b/vendor/github.com/spf13/cobra/README.md @@ -8,6 +8,7 @@ Many of the most widely used Go projects are built using Cobra including: * [Hugo](http://gohugo.io) * [rkt](https://github.com/coreos/rkt) * [etcd](https://github.com/coreos/etcd) +* [Moby (former Docker)](https://github.com/moby/moby) * [Docker (distribution)](https://github.com/docker/distribution) * [OpenShift](https://www.openshift.com/) * [Delve](https://github.com/derekparker/delve) @@ -15,16 +16,36 @@ Many of the most widely used Go projects are built using Cobra including: * [CockroachDB](http://www.cockroachlabs.com/) * [Bleve](http://www.blevesearch.com/) * [ProjectAtomic (enterprise)](http://www.projectatomic.io/) -* [Parse (CLI)](https://parse.com/) * [GiantSwarm's swarm](https://github.com/giantswarm/cli) * [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack) - +* [rclone](http://rclone.org/) +* [nehm](https://github.com/bogem/nehm) [![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra) [![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra) -[![GoDoc](https://godoc.org/github.com/spf13/cobra?status.svg)](https://godoc.org/github.com/spf13/cobra) +[![GoDoc](https://godoc.org/github.com/spf13/cobra?status.svg)](https://godoc.org/github.com/spf13/cobra) -![cobra](https://cloud.githubusercontent.com/assets/173412/10911369/84832a8e-8212-11e5-9f82-cc96660a4794.gif) +# Table of Contents + +- [Overview](#overview) +- [Concepts](#concepts) + * [Commands](#commands) + * [Flags](#flags) +- [Installing](#installing) +- [Getting Started](#getting-started) + * [Using the Cobra Generator](#using-the-cobra-generator) + * [Using the Cobra Library](#using-the-cobra-library) + * [Working with Flags](#working-with-flags) + * [Positional and Custom Arguments](#positional-and-custom-arguments) + * [Example](#example) + * [Help Command](#help-command) + * [Usage Message](#usage-message) + * [PreRun and PostRun Hooks](#prerun-and-postrun-hooks) + * [Suggestions when "unknown command" happens](#suggestions-when-unknown-command-happens) + * [Generating documentation for your command](#generating-documentation-for-your-command) + * [Generating bash completions](#generating-bash-completions) +- [Contributing](#contributing) +- [License](#license) # Overview @@ -39,27 +60,16 @@ Cobra provides: * Fully POSIX-compliant flags (including short & long versions) * Nested subcommands * Global, local and cascading flags -* Easy generation of applications & commands with `cobra create appname` & `cobra add cmdname` +* Easy generation of applications & commands with `cobra init appname` & `cobra add cmdname` * Intelligent suggestions (`app srver`... did you mean `app server`?) * Automatic help generation for commands and flags -* Automatic detailed help for `app help [command]` * Automatic help flag recognition of `-h`, `--help`, etc. * Automatically generated bash autocomplete for your application * Automatically generated man pages for your application * Command aliases so you can change things without breaking them -* The flexibilty to define your own help, usage, etc. +* The flexibility to define your own help, usage, etc. * Optional tight integration with [viper](http://github.com/spf13/viper) for 12-factor apps -Cobra has an exceptionally clean interface and simple design without needless -constructors or initialization methods. - -Applications built with Cobra commands are designed to be as user-friendly as -possible. Flags can be placed before or after the command (as long as a -confusing space isn’t provided). Both short and long flags can be used. A -command need not even be fully typed. Help is automatically generated and -available for the application or for a specific command using either the help -command or the `--help` flag. - # Concepts Cobra is built on a structure of commands, arguments & flags. @@ -78,11 +88,11 @@ A few good real world examples may better illustrate this point. In the following example, 'server' is a command, and 'port' is a flag: - > hugo server --port=1313 + hugo server --port=1313 In this command we are telling Git to clone the url bare. - > git clone URL --bare + git clone URL --bare ## Commands @@ -92,20 +102,11 @@ have children commands and optionally run an action. In the example above, 'server' is the command. -A Command has the following structure: - -```go -type Command struct { - Use string // The one-line usage message. - Short string // The short description shown in the 'help' output. - Long string // The long message shown in the 'help ' output. - Run func(cmd *Command, args []string) // Run runs the command. -} -``` +[More about cobra.Command](https://godoc.org/github.com/spf13/cobra#Command) ## Flags -A Flag is a way to modify the behavior of a command. Cobra supports +A flag is a way to modify the behavior of a command. Cobra supports fully POSIX-compliant flags as well as the Go [flag package](https://golang.org/pkg/flag/). A Cobra command can define flags that persist through to children commands and flags that are only available to that command. @@ -113,23 +114,15 @@ and flags that are only available to that command. In the example above, 'port' is the flag. Flag functionality is provided by the [pflag -library](https://github.com/ogier/pflag), a fork of the flag standard library +library](https://github.com/spf13/pflag), a fork of the flag standard library which maintains the same interface while adding POSIX compliance. -## Usage - -Cobra works by creating a set of commands and then organizing them into a tree. -The tree defines the structure of the application. - -Once each command is defined with its corresponding flags, then the -tree is assigned to the commander which is finally executed. - # Installing Using Cobra is easy. First, use `go get` to install the latest version -of the library. This command will install the `cobra` generator executible -along with the library: +of the library. This command will install the `cobra` generator executable +along with the library and its dependencies: - > go get -v github.com/spf13/cobra/cobra + go get -u github.com/spf13/cobra/cobra Next, include Cobra in your application: @@ -139,8 +132,8 @@ import "github.com/spf13/cobra" # Getting Started -While you are welcome to provide your own organization, typically a Cobra based -application will follow the following organizational structure. +While you are welcome to provide your own organization, typically a Cobra-based +application will follow the following organizational structure: ``` ▾ appName/ @@ -152,18 +145,23 @@ application will follow the following organizational structure. main.go ``` -In a Cobra app, typically the main.go file is very bare. It serves, one purpose, to initialize Cobra. +In a Cobra app, typically the main.go file is very bare. It serves one purpose: initializing Cobra. ```go package main -import "{pathToYourApp}/cmd" +import ( + "fmt" + "os" + + "{pathToYourApp}/cmd" +) func main() { - if err := cmd.RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(-1) - } + if err := cmd.RootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } } ``` @@ -172,99 +170,14 @@ func main() { Cobra provides its own program that will create your application and add any commands you want. It's the easiest way to incorporate Cobra into your application. -In order to use the cobra command, compile it using the following command: +[Here](https://github.com/spf13/cobra/blob/master/cobra/README.md) you can find more information about it. - > go install github.com/spf13/cobra/cobra +## Using the Cobra Library -This will create the cobra executable under your go path bin directory! - -### cobra init - -The `cobra init [yourApp]` command will create your initial application code -for you. It is a very powerful application that will populate your program with -the right structure so you can immediately enjoy all the benefits of Cobra. It -will also automatically apply the license you specify to your application. - -Cobra init is pretty smart. You can provide it a full path, or simply a path -similar to what is expected in the import. - -``` -cobra init github.com/spf13/newAppName -``` - -### cobra add - -Once an application is initialized Cobra can create additional commands for you. -Let's say you created an app and you wanted the following commands for it: - -* app serve -* app config -* app config create - -In your project directory (where your main.go file is) you would run the following: - -``` -cobra add serve -cobra add config -cobra add create -p 'configCmd' -``` - -Once you have run these three commands you would have an app structure that would look like: - -``` - ▾ app/ - ▾ cmd/ - serve.go - config.go - create.go - main.go -``` - -at this point you can run `go run main.go` and it would run your app. `go run -main.go serve`, `go run main.go config`, `go run main.go config create` along -with `go run main.go help serve`, etc would all work. - -Obviously you haven't added your own code to these yet, the commands are ready -for you to give them their tasks. Have fun. - -### Configuring the cobra generator - -The cobra generator will be easier to use if you provide a simple configuration -file which will help you eliminate providing a bunch of repeated information in -flags over and over. - -An example ~/.cobra.yaml file: - -```yaml -author: Steve Francia -license: MIT -``` - -You can specify no license by setting `license` to `none` or you can specify -a custom license: - -```yaml -license: - header: This file is part of {{ .appName }}. - text: | - {{ .copyright }} - - This is my license. There are many like it, but this one is mine. - My license is my best friend. It is my life. I must master it as I must - master my life. -``` - -## Manually implementing Cobra - -To manually implement cobra you need to create a bare main.go file and a RootCmd file. +To manually implement Cobra you need to create a bare main.go file and a RootCmd file. You will optionally provide additional commands as you see fit. -### Create the root command - -The root command represents your binary itself. - - -#### Manually create rootCmd +### Create rootCmd Cobra doesn't require any special constructors. Simply create your commands. @@ -272,34 +185,67 @@ Ideally you place this in app/cmd/root.go: ```go var RootCmd = &cobra.Command{ - Use: "hugo", - Short: "Hugo is a very fast static site generator", - Long: `A Fast and Flexible Static Site Generator built with + Use: "hugo", + Short: "Hugo is a very fast static site generator", + Long: `A Fast and Flexible Static Site Generator built with love by spf13 and friends in Go. Complete documentation is available at http://hugo.spf13.com`, - Run: func(cmd *cobra.Command, args []string) { - // Do Stuff Here - }, + Run: func(cmd *cobra.Command, args []string) { + // Do Stuff Here + }, } ``` You will additionally define flags and handle configuration in your init() function. -for example cmd/root.go: +For example cmd/root.go: ```go +import ( + "fmt" + "os" + + homedir "github.com/mitchellh/go-homedir" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + func init() { - cobra.OnInitialize(initConfig) - RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") - RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/") - RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution") - RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)") - RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration") - viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author")) - viper.BindPFlag("projectbase", RootCmd.PersistentFlags().Lookup("projectbase")) - viper.BindPFlag("useViper", RootCmd.PersistentFlags().Lookup("viper")) - viper.SetDefault("author", "NAME HERE ") - viper.SetDefault("license", "apache") + cobra.OnInitialize(initConfig) + RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") + RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/") + RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution") + RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)") + RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration") + viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author")) + viper.BindPFlag("projectbase", RootCmd.PersistentFlags().Lookup("projectbase")) + viper.BindPFlag("useViper", RootCmd.PersistentFlags().Lookup("viper")) + viper.SetDefault("author", "NAME HERE ") + viper.SetDefault("license", "apache") +} + +func initConfig() { + // Don't forget to read config either from cfgFile or from home directory! + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := homedir.Dir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // Search config in home directory with name ".cobra" (without extension). + viper.AddConfigPath(home) + viper.SetConfigName(".cobra") + } + + if err := viper.ReadInConfig(); err != nil { + fmt.Println("Can't read config:", err) + os.Exit(1) + } } ``` @@ -313,17 +259,21 @@ In a Cobra app, typically the main.go file is very bare. It serves, one purpose, ```go package main -import "{pathToYourApp}/cmd" +import ( + "fmt" + "os" + + "{pathToYourApp}/cmd" +) func main() { - if err := cmd.RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(-1) - } + if err := cmd.RootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } } ``` - ### Create additional commands Additional commands can be defined and typically are each given their own file @@ -336,47 +286,24 @@ populate it with the following: package cmd import ( - "github.com/spf13/cobra" + "github.com/spf13/cobra" + "fmt" ) func init() { - RootCmd.AddCommand(versionCmd) + RootCmd.AddCommand(versionCmd) } var versionCmd = &cobra.Command{ - Use: "version", - Short: "Print the version number of Hugo", - Long: `All software has versions. This is Hugo's`, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") - }, + Use: "version", + Short: "Print the version number of Hugo", + Long: `All software has versions. This is Hugo's`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") + }, } ``` -### Attach command to its parent - - -If you notice in the above example we attach the command to its parent. In -this case the parent is the rootCmd. In this example we are attaching it to the -root, but commands can be attached at any level. - -```go -RootCmd.AddCommand(versionCmd) -``` - -### Remove a command from its parent - -Removing a command is not a common action in simple programs, but it allows 3rd -parties to customize an existing command tree. - -In this example, we remove the existing `VersionCmd` command of an existing -root command, and we replace it with our own version: - -```go -mainlib.RootCmd.RemoveCommand(mainlib.VersionCmd) -mainlib.RootCmd.AddCommand(versionCmd) -``` - ## Working with Flags Flags provide modifiers to control how the action command operates. @@ -412,6 +339,71 @@ A flag can also be assigned locally which will only apply to that specific comma RootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") ``` +### Local Flag on Parent Commands + +By default Cobra only parses local flags on the target command, any local flags on +parent commands are ignored. By enabling `Command.TraverseChildren` Cobra will +parse local flags on each command before executing the target command. + +```go +command := cobra.Command{ + Use: "print [OPTIONS] [COMMANDS]", + TraverseChildren: true, +} +``` + +### Bind Flags with Config + +You can also bind your flags with [viper](https://github.com/spf13/viper): +```go +var author string + +func init() { + RootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution") + viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author")) +} +``` + +In this example the persistent flag `author` is bound with `viper`. +**Note**, that the variable `author` will not be set to the value from config, +when the `--author` flag is not provided by user. + +More in [viper documentation](https://github.com/spf13/viper#working-with-flags). + +## Positional and Custom Arguments + +Validation of positional arguments can be specified using the `Args` field +of `Command`. + +The following validators are built in: + +- `NoArgs` - the command will report an error if there are any positional args. +- `ArbitraryArgs` - the command will accept any args. +- `OnlyValidArgs` - the command will report an error if there are any positional args that are not in the `ValidArgs` field of `Command`. +- `MinimumNArgs(int)` - the command will report an error if there are not at least N positional args. +- `MaximumNArgs(int)` - the command will report an error if there are more than N positional args. +- `ExactArgs(int)` - the command will report an error if there are not exactly N positional args. +- `RangeArgs(min, max)` - the command will report an error if the number of args is not between the minimum and maximum number of expected args. + +An example of setting the custom validator: + +```go +var cmd = &cobra.Command{ + Short: "hello", + Args: func(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return errors.New("requires at least one arg") + } + if myapp.IsValidColor(args[0]) { + return nil + } + return fmt.Errorf("invalid color specified: %s", args[0]) + }, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Hello, World!") + }, +} +``` ## Example @@ -428,62 +420,62 @@ More documentation about flags is available at https://github.com/spf13/pflag package main import ( - "fmt" - "strings" + "fmt" + "strings" - "github.com/spf13/cobra" + "github.com/spf13/cobra" ) func main() { + var echoTimes int - var echoTimes int + var cmdPrint = &cobra.Command{ + Use: "print [string to print]", + Short: "Print anything to the screen", + Long: `print is for printing anything back to the screen. +For many years people have printed back to the screen.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Print: " + strings.Join(args, " ")) + }, + } - var cmdPrint = &cobra.Command{ - Use: "print [string to print]", - Short: "Print anything to the screen", - Long: `print is for printing anything back to the screen. - For many years people have printed back to the screen. - `, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Print: " + strings.Join(args, " ")) - }, - } + var cmdEcho = &cobra.Command{ + Use: "echo [string to echo]", + Short: "Echo anything to the screen", + Long: `echo is for echoing anything back. +Echo works a lot like print, except it has a child command.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Print: " + strings.Join(args, " ")) + }, + } - var cmdEcho = &cobra.Command{ - Use: "echo [string to echo]", - Short: "Echo anything to the screen", - Long: `echo is for echoing anything back. - Echo works a lot like print, except it has a child command. - `, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Print: " + strings.Join(args, " ")) - }, - } + var cmdTimes = &cobra.Command{ + Use: "times [# times] [string to echo]", + Short: "Echo anything to the screen more times", + Long: `echo things multiple times back to the user by providing +a count and a string.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + for i := 0; i < echoTimes; i++ { + fmt.Println("Echo: " + strings.Join(args, " ")) + } + }, + } - var cmdTimes = &cobra.Command{ - Use: "times [# times] [string to echo]", - Short: "Echo anything to the screen more times", - Long: `echo things multiple times back to the user by providing - a count and a string.`, - Run: func(cmd *cobra.Command, args []string) { - for i := 0; i < echoTimes; i++ { - fmt.Println("Echo: " + strings.Join(args, " ")) - } - }, - } + cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") - cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") - - var rootCmd = &cobra.Command{Use: "app"} - rootCmd.AddCommand(cmdPrint, cmdEcho) - cmdEcho.AddCommand(cmdTimes) - rootCmd.Execute() + var rootCmd = &cobra.Command{Use: "app"} + rootCmd.AddCommand(cmdPrint, cmdEcho) + cmdEcho.AddCommand(cmdTimes) + rootCmd.Execute() } ``` For a more complete example of a larger application, please checkout [Hugo](http://gohugo.io/). -## The Help Command +## Help Command Cobra automatically adds a help command to your application when you have subcommands. This will be called when a user runs 'app help'. Additionally, help will also @@ -496,60 +488,28 @@ create' is called. Every command will automatically have the '--help' flag adde The following output is automatically generated by Cobra. Nothing beyond the command and flag definitions are needed. - > hugo help + $ cobra help - hugo is the main command, used to build your Hugo site. - - Hugo is a Fast and Flexible Static Site Generator - built with love by spf13 and friends in Go. - - Complete documentation is available at http://gohugo.io/. + Cobra is a CLI library for Go that empowers applications. + This application is a tool to generate the needed files + to quickly create a Cobra application. Usage: - hugo [flags] - hugo [command] + cobra [command] Available Commands: - server Hugo runs its own webserver to render the files - version Print the version number of Hugo - config Print the site configuration - check Check content in the source directory - benchmark Benchmark hugo by building a site a number of times. - convert Convert your content to different formats - new Create new content for your site - list Listing out various types of content - undraft Undraft changes the content's draft status from 'True' to 'False' - genautocomplete Generate shell autocompletion script for Hugo - gendoc Generate Markdown documentation for the Hugo CLI. - genman Generate man page for Hugo - import Import your site from others. + add Add a command to a Cobra Application + help Help about any command + init Initialize a Cobra Application Flags: - -b, --baseURL="": hostname (and path) to the root, e.g. http://spf13.com/ - -D, --buildDrafts[=false]: include content marked as draft - -F, --buildFuture[=false]: include content with publishdate in the future - --cacheDir="": filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/ - --canonifyURLs[=false]: if true, all relative URLs will be canonicalized using baseURL - --config="": config file (default is path/config.yaml|json|toml) - -d, --destination="": filesystem path to write files to - --disableRSS[=false]: Do not build RSS files - --disableSitemap[=false]: Do not build Sitemap file - --editor="": edit new content with this editor, if provided - --ignoreCache[=false]: Ignores the cache directory for reading but still writes to it - --log[=false]: Enable Logging - --logFile="": Log File path (if set, logging enabled automatically) - --noTimes[=false]: Don't sync modification time of files - --pluralizeListTitles[=true]: Pluralize titles in lists using inflect - --preserveTaxonomyNames[=false]: Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu") - -s, --source="": filesystem path to read files relative from - --stepAnalysis[=false]: display memory and timing of different steps of the program - -t, --theme="": theme to use (located in /themes/THEMENAME/) - --uglyURLs[=false]: if true, use /filename.html instead of /filename/ - -v, --verbose[=false]: verbose output - --verboseLog[=false]: verbose logging - -w, --watch[=false]: watch filesystem for changes and recreate as needed + -a, --author string author name for copyright attribution (default "YOUR NAME") + --config string config file (default is $HOME/.cobra.yaml) + -h, --help help for cobra + -l, --license string name of license for the project + --viper use Viper for configuration (default true) - Use "hugo [command] --help" for more information about a command. + Use "cobra [command] --help" for more information about a command. Help is just a command like any other. There is no special logic or behavior @@ -557,38 +517,18 @@ around it. In fact, you can provide your own if you want. ### Defining your own help -You can provide your own Help command or your own template for the default command to use. - -The default help command is +You can provide your own Help command or your own template for the default command to use +with following functions: ```go -func (c *Command) initHelp() { - if c.helpCommand == nil { - c.helpCommand = &Command{ - Use: "help [command]", - Short: "Help about any command", - Long: `Help provides help for any command in the application. - Simply type ` + c.Name() + ` help [path to command] for full details.`, - Run: c.HelpFunc(), - } - } - c.AddCommand(c.helpCommand) -} -``` - -You can provide your own command, function or template through the following methods: - -```go -command.SetHelpCommand(cmd *Command) - -command.SetHelpFunc(f func(*Command, []string)) - -command.SetHelpTemplate(s string) +cmd.SetHelpCommand(cmd *Command) +cmd.SetHelpFunc(f func(*Command, []string)) +cmd.SetHelpTemplate(s string) ``` The latter two will also apply to any children commands. -## Usage +## Usage Message When the user provides an invalid flag or invalid command, Cobra responds by showing the user the 'usage'. @@ -597,73 +537,37 @@ showing the user the 'usage'. You may recognize this from the help above. That's because the default help embeds the usage as part of its output. + $ cobra --invalid + Error: unknown flag: --invalid Usage: - hugo [flags] - hugo [command] + cobra [command] Available Commands: - server Hugo runs its own webserver to render the files - version Print the version number of Hugo - config Print the site configuration - check Check content in the source directory - benchmark Benchmark hugo by building a site a number of times. - convert Convert your content to different formats - new Create new content for your site - list Listing out various types of content - undraft Undraft changes the content's draft status from 'True' to 'False' - genautocomplete Generate shell autocompletion script for Hugo - gendoc Generate Markdown documentation for the Hugo CLI. - genman Generate man page for Hugo - import Import your site from others. + add Add a command to a Cobra Application + help Help about any command + init Initialize a Cobra Application Flags: - -b, --baseURL="": hostname (and path) to the root, e.g. http://spf13.com/ - -D, --buildDrafts[=false]: include content marked as draft - -F, --buildFuture[=false]: include content with publishdate in the future - --cacheDir="": filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/ - --canonifyURLs[=false]: if true, all relative URLs will be canonicalized using baseURL - --config="": config file (default is path/config.yaml|json|toml) - -d, --destination="": filesystem path to write files to - --disableRSS[=false]: Do not build RSS files - --disableSitemap[=false]: Do not build Sitemap file - --editor="": edit new content with this editor, if provided - --ignoreCache[=false]: Ignores the cache directory for reading but still writes to it - --log[=false]: Enable Logging - --logFile="": Log File path (if set, logging enabled automatically) - --noTimes[=false]: Don't sync modification time of files - --pluralizeListTitles[=true]: Pluralize titles in lists using inflect - --preserveTaxonomyNames[=false]: Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu") - -s, --source="": filesystem path to read files relative from - --stepAnalysis[=false]: display memory and timing of different steps of the program - -t, --theme="": theme to use (located in /themes/THEMENAME/) - --uglyURLs[=false]: if true, use /filename.html instead of /filename/ - -v, --verbose[=false]: verbose output - --verboseLog[=false]: verbose logging - -w, --watch[=false]: watch filesystem for changes and recreate as needed + -a, --author string author name for copyright attribution (default "YOUR NAME") + --config string config file (default is $HOME/.cobra.yaml) + -h, --help help for cobra + -l, --license string name of license for the project + --viper use Viper for configuration (default true) + + Use "cobra [command] --help" for more information about a command. ### Defining your own usage You can provide your own usage function or template for Cobra to use. - -The default usage function is: - -```go -return func(c *Command) error { - err := tmpl(c.Out(), c.UsageTemplate(), c) - return err -} -``` - Like help, the function and template are overridable through public methods: ```go -command.SetUsageFunc(f func(*Command) error) - -command.SetUsageTemplate(s string) +cmd.SetUsageFunc(f func(*Command) error) +cmd.SetUsageTemplate(s string) ``` -## PreRun or PostRun Hooks +## PreRun and PostRun Hooks -It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherrited by children if they do not declare their own. These function are run in the following order: +It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order: - `PersistentPreRun` - `PreRun` @@ -677,105 +581,73 @@ An example of two commands which use all of these features is below. When the s package main import ( - "fmt" + "fmt" - "github.com/spf13/cobra" + "github.com/spf13/cobra" ) func main() { - var rootCmd = &cobra.Command{ - Use: "root [sub]", - Short: "My root command", - PersistentPreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args) - }, - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args) - }, - } + var rootCmd = &cobra.Command{ + Use: "root [sub]", + Short: "My root command", + PersistentPreRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args) + }, + PreRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PreRun with args: %v\n", args) + }, + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd Run with args: %v\n", args) + }, + PostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PostRun with args: %v\n", args) + }, + PersistentPostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args) + }, + } - var subCmd = &cobra.Command{ - Use: "sub [no options!]", - Short: "My subcommand", - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args) - }, - } + var subCmd = &cobra.Command{ + Use: "sub [no options!]", + Short: "My subcommand", + PreRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd PreRun with args: %v\n", args) + }, + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd Run with args: %v\n", args) + }, + PostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd PostRun with args: %v\n", args) + }, + PersistentPostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args) + }, + } - rootCmd.AddCommand(subCmd) + rootCmd.AddCommand(subCmd) - rootCmd.SetArgs([]string{""}) - _ = rootCmd.Execute() - fmt.Print("\n") - rootCmd.SetArgs([]string{"sub", "arg1", "arg2"}) - _ = rootCmd.Execute() + rootCmd.SetArgs([]string{""}) + rootCmd.Execute() + fmt.Println() + rootCmd.SetArgs([]string{"sub", "arg1", "arg2"}) + rootCmd.Execute() } ``` +Output: +``` +Inside rootCmd PersistentPreRun with args: [] +Inside rootCmd PreRun with args: [] +Inside rootCmd Run with args: [] +Inside rootCmd PostRun with args: [] +Inside rootCmd PersistentPostRun with args: [] -## Alternative Error Handling - -Cobra also has functions where the return signature is an error. This allows for errors to bubble up to the top, -providing a way to handle the errors in one location. The current list of functions that return an error is: - -* PersistentPreRunE -* PreRunE -* RunE -* PostRunE -* PersistentPostRunE - -If you would like to silence the default `error` and `usage` output in favor of your own, you can set `SilenceUsage` -and `SilenceErrors` to `false` on the command. A child command respects these flags if they are set on the parent -command. - -**Example Usage using RunE:** - -```go -package main - -import ( - "errors" - "log" - - "github.com/spf13/cobra" -) - -func main() { - var rootCmd = &cobra.Command{ - Use: "hugo", - Short: "Hugo is a very fast static site generator", - Long: `A Fast and Flexible Static Site Generator built with - love by spf13 and friends in Go. - Complete documentation is available at http://hugo.spf13.com`, - RunE: func(cmd *cobra.Command, args []string) error { - // Do Stuff Here - return errors.New("some random error") - }, - } - - if err := rootCmd.Execute(); err != nil { - log.Fatal(err) - } -} +Inside rootCmd PersistentPreRun with args: [arg1 arg2] +Inside subCmd PreRun with args: [arg1 arg2] +Inside subCmd Run with args: [arg1 arg2] +Inside subCmd PostRun with args: [arg1 arg2] +Inside subCmd PersistentPostRun with args: [arg1 arg2] ``` ## Suggestions when "unknown command" happens @@ -818,81 +690,28 @@ Did you mean this? Run 'kubectl help' for usage. ``` -## Generating Markdown-formatted documentation for your command +## Generating documentation for your command -Cobra can generate a Markdown-formatted document based on the subcommands, flags, etc. A simple example of how to do this for your command can be found in [Markdown Docs](doc/md_docs.md). +Cobra can generate documentation based on subcommands, flags, etc. in the following formats: -## Generating man pages for your command +- [Markdown](doc/md_docs.md) +- [ReStructured Text](doc/rest_docs.md) +- [Man Page](doc/man_docs.md) -Cobra can generate a man page based on the subcommands, flags, etc. A simple example of how to do this for your command can be found in [Man Docs](doc/man_docs.md). - -## Generating bash completions for your command +## Generating bash completions Cobra can generate a bash-completion file. If you add more information to your command, these completions can be amazingly powerful and flexible. Read more about it in [Bash Completions](bash_completions.md). -## Debugging - -Cobra provides a ‘DebugFlags’ method on a command which, when called, will print -out everything Cobra knows about the flags for each command. - -### Example - -```go -command.DebugFlags() -``` - -## Release Notes -* **0.9.0** June 17, 2014 - * flags can appears anywhere in the args (provided they are unambiguous) - * --help prints usage screen for app or command - * Prefix matching for commands - * Cleaner looking help and usage output - * Extensive test suite -* **0.8.0** Nov 5, 2013 - * Reworked interface to remove commander completely - * Command now primary structure - * No initialization needed - * Usage & Help templates & functions definable at any level - * Updated Readme -* **0.7.0** Sept 24, 2013 - * Needs more eyes - * Test suite - * Support for automatic error messages - * Support for help command - * Support for printing to any io.Writer instead of os.Stderr - * Support for persistent flags which cascade down tree - * Ready for integration into Hugo -* **0.1.0** Sept 3, 2013 - * Implement first draft - -## Extensions - -Libraries for extending Cobra: - -* [cmdns](https://github.com/gosuri/cmdns): Enables name spacing a command's immediate children. It provides an alternative way to structure subcommands, similar to `heroku apps:create` and `ovrclk clusters:launch`. - -## ToDo -* Launch proper documentation site - -## Contributing +# Contributing 1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request +2. Download your fork to your PC (`git clone https://github.com/your_username/cobra && cd cobra`) +3. Create your feature branch (`git checkout -b my-new-feature`) +4. Make changes and add them (`git add .`) +5. Commit your changes (`git commit -m 'Add some feature'`) +6. Push to the branch (`git push origin my-new-feature`) +7. Create new pull request -## Contributors - -Names in no particular order: - -* [spf13](https://github.com/spf13), -[eparis](https://github.com/eparis), -[bep](https://github.com/bep), and many more! - -## License +# License Cobra is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/cobra/blob/master/LICENSE.txt) - - -[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/spf13/cobra/trend.png)](https://bitdeli.com/free "Bitdeli Badge") diff --git a/vendor/github.com/spf13/cobra/args.go b/vendor/github.com/spf13/cobra/args.go new file mode 100644 index 00000000000..a5d8a9273ea --- /dev/null +++ b/vendor/github.com/spf13/cobra/args.go @@ -0,0 +1,89 @@ +package cobra + +import ( + "fmt" +) + +type PositionalArgs func(cmd *Command, args []string) error + +// Legacy arg validation has the following behaviour: +// - root commands with no subcommands can take arbitrary arguments +// - root commands with subcommands will do subcommand validity checking +// - subcommands will always accept arbitrary arguments +func legacyArgs(cmd *Command, args []string) error { + // no subcommand, always take args + if !cmd.HasSubCommands() { + return nil + } + + // root command with subcommands, do subcommand checking. + if !cmd.HasParent() && len(args) > 0 { + return fmt.Errorf("unknown command %q for %q%s", args[0], cmd.CommandPath(), cmd.findSuggestions(args[0])) + } + return nil +} + +// NoArgs returns an error if any args are included. +func NoArgs(cmd *Command, args []string) error { + if len(args) > 0 { + return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath()) + } + return nil +} + +// OnlyValidArgs returns an error if any args are not in the list of ValidArgs. +func OnlyValidArgs(cmd *Command, args []string) error { + if len(cmd.ValidArgs) > 0 { + for _, v := range args { + if !stringInSlice(v, cmd.ValidArgs) { + return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0])) + } + } + } + return nil +} + +// ArbitraryArgs never returns an error. +func ArbitraryArgs(cmd *Command, args []string) error { + return nil +} + +// MinimumNArgs returns an error if there is not at least N args. +func MinimumNArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) < n { + return fmt.Errorf("requires at least %d arg(s), only received %d", n, len(args)) + } + return nil + } +} + +// MaximumNArgs returns an error if there are more than N args. +func MaximumNArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) > n { + return fmt.Errorf("accepts at most %d arg(s), received %d", n, len(args)) + } + return nil + } +} + +// ExactArgs returns an error if there are not exactly n args. +func ExactArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) != n { + return fmt.Errorf("accepts %d arg(s), received %d", n, len(args)) + } + return nil + } +} + +// RangeArgs returns an error if the number of args is not within the expected range. +func RangeArgs(min int, max int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) < min || len(args) > max { + return fmt.Errorf("accepts between %d and %d arg(s), received %d", min, max, len(args)) + } + return nil + } +} diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go index 236dee67f21..c19fe7a068b 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.go +++ b/vendor/github.com/spf13/cobra/bash_completions.go @@ -1,6 +1,7 @@ package cobra import ( + "bytes" "fmt" "io" "os" @@ -10,19 +11,17 @@ import ( "github.com/spf13/pflag" ) +// Annotations for Bash completion. const ( - BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extentions" + BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions" BashCompCustom = "cobra_annotation_bash_completion_custom" BashCompOneRequiredFlag = "cobra_annotation_bash_completion_one_required_flag" BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir" ) -func preamble(out io.Writer, name string) error { - _, err := fmt.Fprintf(out, "# bash completion for %-36s -*- shell-script -*-\n", name) - if err != nil { - return err - } - _, err = fmt.Fprint(out, ` +func writePreamble(buf *bytes.Buffer, name string) { + buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name)) + buf.WriteString(` __debug() { if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then @@ -87,13 +86,13 @@ __handle_reply() local index flag flag="${cur%%=*}" __index_of_word "${flag}" "${flags_with_completion[@]}" + COMPREPLY=() if [[ ${index} -ge 0 ]]; then - COMPREPLY=() PREFIX="" cur="${cur#*=}" ${flags_completion[${index}]} if [ -n "${ZSH_VERSION}" ]; then - # zfs completion needs --flag= prefix + # zsh completion needs --flag= prefix eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )" fi fi @@ -133,7 +132,10 @@ __handle_reply() declare -F __custom_func >/dev/null && __custom_func fi - __ltrim_colon_completions "$cur" + # available in bash-completion >= 2, not always present on macOS + if declare -F __ltrim_colon_completions >/dev/null; then + __ltrim_colon_completions "$cur" + fi } # The arguments should be in the form "ext1|ext2|extn" @@ -224,7 +226,7 @@ __handle_command() fi c=$((c+1)) __debug "${FUNCNAME[0]}: looking for ${next_command}" - declare -F $next_command >/dev/null && $next_command + declare -F "$next_command" >/dev/null && $next_command } __handle_word() @@ -247,16 +249,12 @@ __handle_word() } `) - return err } -func postscript(w io.Writer, name string) error { +func writePostscript(buf *bytes.Buffer, name string) { name = strings.Replace(name, ":", "__", -1) - _, err := fmt.Fprintf(w, "__start_%s()\n", name) - if err != nil { - return err - } - _, err = fmt.Fprintf(w, `{ + buf.WriteString(fmt.Sprintf("__start_%s()\n", name)) + buf.WriteString(fmt.Sprintf(`{ local cur prev words cword declare -A flaghash 2>/dev/null || : if declare -F _init_completion >/dev/null 2>&1; then @@ -280,318 +278,227 @@ func postscript(w io.Writer, name string) error { __handle_word } -`, name) - if err != nil { - return err - } - _, err = fmt.Fprintf(w, `if [[ $(type -t compopt) = "builtin" ]]; then +`, name)) + buf.WriteString(fmt.Sprintf(`if [[ $(type -t compopt) = "builtin" ]]; then complete -o default -F __start_%s %s else complete -o default -o nospace -F __start_%s %s fi -`, name, name, name, name) - if err != nil { - return err - } - _, err = fmt.Fprintf(w, "# ex: ts=4 sw=4 et filetype=sh\n") - return err +`, name, name, name, name)) + buf.WriteString("# ex: ts=4 sw=4 et filetype=sh\n") } -func writeCommands(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " commands=()\n"); err != nil { - return err - } +func writeCommands(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" commands=()\n") for _, c := range cmd.Commands() { if !c.IsAvailableCommand() || c == cmd.helpCommand { continue } - if _, err := fmt.Fprintf(w, " commands+=(%q)\n", c.Name()); err != nil { - return err - } + buf.WriteString(fmt.Sprintf(" commands+=(%q)\n", c.Name())) } - _, err := fmt.Fprintf(w, "\n") - return err + buf.WriteString("\n") } -func writeFlagHandler(name string, annotations map[string][]string, w io.Writer) error { +func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string) { for key, value := range annotations { switch key { case BashCompFilenameExt: - _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) - if err != nil { - return err - } + buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + var ext string if len(value) > 0 { - ext := "__handle_filename_extension_flag " + strings.Join(value, "|") - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) + ext = "__handle_filename_extension_flag " + strings.Join(value, "|") } else { - ext := "_filedir" - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) - } - if err != nil { - return err + ext = "_filedir" } + buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext)) case BashCompCustom: - _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) - if err != nil { - return err - } + buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) if len(value) > 0 { handlers := strings.Join(value, "; ") - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", handlers) + buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", handlers)) } else { - _, err = fmt.Fprintf(w, " flags_completion+=(:)\n") - } - if err != nil { - return err + buf.WriteString(" flags_completion+=(:)\n") } case BashCompSubdirsInDir: - _, err := fmt.Fprintf(w, " flags_with_completion+=(%q)\n", name) + buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + var ext string if len(value) == 1 { - ext := "__handle_subdirs_in_dir_flag " + value[0] - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) + ext = "__handle_subdirs_in_dir_flag " + value[0] } else { - ext := "_filedir -d" - _, err = fmt.Fprintf(w, " flags_completion+=(%q)\n", ext) - } - if err != nil { - return err + ext = "_filedir -d" } + buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext)) } } - return nil } -func writeShortFlag(flag *pflag.Flag, w io.Writer) error { - b := (len(flag.NoOptDefVal) > 0) +func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag) { name := flag.Shorthand format := " " - if !b { + if len(flag.NoOptDefVal) == 0 { format += "two_word_" } format += "flags+=(\"-%s\")\n" - if _, err := fmt.Fprintf(w, format, name); err != nil { - return err - } - return writeFlagHandler("-"+name, flag.Annotations, w) + buf.WriteString(fmt.Sprintf(format, name)) + writeFlagHandler(buf, "-"+name, flag.Annotations) } -func writeFlag(flag *pflag.Flag, w io.Writer) error { - b := (len(flag.NoOptDefVal) > 0) +func writeFlag(buf *bytes.Buffer, flag *pflag.Flag) { name := flag.Name format := " flags+=(\"--%s" - if !b { + if len(flag.NoOptDefVal) == 0 { format += "=" } format += "\")\n" - if _, err := fmt.Fprintf(w, format, name); err != nil { - return err - } - return writeFlagHandler("--"+name, flag.Annotations, w) + buf.WriteString(fmt.Sprintf(format, name)) + writeFlagHandler(buf, "--"+name, flag.Annotations) } -func writeLocalNonPersistentFlag(flag *pflag.Flag, w io.Writer) error { - b := (len(flag.NoOptDefVal) > 0) +func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) { name := flag.Name format := " local_nonpersistent_flags+=(\"--%s" - if !b { + if len(flag.NoOptDefVal) == 0 { format += "=" } format += "\")\n" - if _, err := fmt.Fprintf(w, format, name); err != nil { - return err - } - return nil + buf.WriteString(fmt.Sprintf(format, name)) } -func writeFlags(cmd *Command, w io.Writer) error { - _, err := fmt.Fprintf(w, ` flags=() +func writeFlags(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(` flags=() two_word_flags=() local_nonpersistent_flags=() flags_with_completion=() flags_completion=() `) - if err != nil { - return err - } localNonPersistentFlags := cmd.LocalNonPersistentFlags() - var visitErr error cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { - if err := writeFlag(flag, w); err != nil { - visitErr = err + if nonCompletableFlag(flag) { return } + writeFlag(buf, flag) if len(flag.Shorthand) > 0 { - if err := writeShortFlag(flag, w); err != nil { - visitErr = err - return - } + writeShortFlag(buf, flag) } if localNonPersistentFlags.Lookup(flag.Name) != nil { - if err := writeLocalNonPersistentFlag(flag, w); err != nil { - visitErr = err - return - } + writeLocalNonPersistentFlag(buf, flag) } }) - if visitErr != nil { - return visitErr - } cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { - if err := writeFlag(flag, w); err != nil { - visitErr = err + if nonCompletableFlag(flag) { return } + writeFlag(buf, flag) if len(flag.Shorthand) > 0 { - if err := writeShortFlag(flag, w); err != nil { - visitErr = err - return - } + writeShortFlag(buf, flag) } }) - if visitErr != nil { - return visitErr - } - _, err = fmt.Fprintf(w, "\n") - return err + buf.WriteString("\n") } -func writeRequiredFlag(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " must_have_one_flag=()\n"); err != nil { - return err - } +func writeRequiredFlag(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" must_have_one_flag=()\n") flags := cmd.NonInheritedFlags() - var visitErr error flags.VisitAll(func(flag *pflag.Flag) { + if nonCompletableFlag(flag) { + return + } for key := range flag.Annotations { switch key { case BashCompOneRequiredFlag: format := " must_have_one_flag+=(\"--%s" - b := (flag.Value.Type() == "bool") - if !b { + if flag.Value.Type() != "bool" { format += "=" } format += "\")\n" - if _, err := fmt.Fprintf(w, format, flag.Name); err != nil { - visitErr = err - return - } + buf.WriteString(fmt.Sprintf(format, flag.Name)) if len(flag.Shorthand) > 0 { - if _, err := fmt.Fprintf(w, " must_have_one_flag+=(\"-%s\")\n", flag.Shorthand); err != nil { - visitErr = err - return - } + buf.WriteString(fmt.Sprintf(" must_have_one_flag+=(\"-%s\")\n", flag.Shorthand)) } } } }) - return visitErr } -func writeRequiredNouns(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " must_have_one_noun=()\n"); err != nil { - return err - } +func writeRequiredNouns(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" must_have_one_noun=()\n") sort.Sort(sort.StringSlice(cmd.ValidArgs)) for _, value := range cmd.ValidArgs { - if _, err := fmt.Fprintf(w, " must_have_one_noun+=(%q)\n", value); err != nil { - return err - } + buf.WriteString(fmt.Sprintf(" must_have_one_noun+=(%q)\n", value)) } - return nil } -func writeArgAliases(cmd *Command, w io.Writer) error { - if _, err := fmt.Fprintf(w, " noun_aliases=()\n"); err != nil { - return err - } +func writeArgAliases(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" noun_aliases=()\n") sort.Sort(sort.StringSlice(cmd.ArgAliases)) for _, value := range cmd.ArgAliases { - if _, err := fmt.Fprintf(w, " noun_aliases+=(%q)\n", value); err != nil { - return err - } + buf.WriteString(fmt.Sprintf(" noun_aliases+=(%q)\n", value)) } - return nil } -func gen(cmd *Command, w io.Writer) error { +func gen(buf *bytes.Buffer, cmd *Command) { for _, c := range cmd.Commands() { if !c.IsAvailableCommand() || c == cmd.helpCommand { continue } - if err := gen(c, w); err != nil { - return err - } + gen(buf, c) } commandName := cmd.CommandPath() commandName = strings.Replace(commandName, " ", "_", -1) commandName = strings.Replace(commandName, ":", "__", -1) - if _, err := fmt.Fprintf(w, "_%s()\n{\n", commandName); err != nil { - return err - } - if _, err := fmt.Fprintf(w, " last_command=%q\n", commandName); err != nil { - return err - } - if err := writeCommands(cmd, w); err != nil { - return err - } - if err := writeFlags(cmd, w); err != nil { - return err - } - if err := writeRequiredFlag(cmd, w); err != nil { - return err - } - if err := writeRequiredNouns(cmd, w); err != nil { - return err - } - if err := writeArgAliases(cmd, w); err != nil { - return err - } - if _, err := fmt.Fprintf(w, "}\n\n"); err != nil { - return err - } - return nil + buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName)) + buf.WriteString(fmt.Sprintf(" last_command=%q\n", commandName)) + writeCommands(buf, cmd) + writeFlags(buf, cmd) + writeRequiredFlag(buf, cmd) + writeRequiredNouns(buf, cmd) + writeArgAliases(buf, cmd) + buf.WriteString("}\n\n") } -func (cmd *Command) GenBashCompletion(w io.Writer) error { - if err := preamble(w, cmd.Name()); err != nil { - return err +// GenBashCompletion generates bash completion file and writes to the passed writer. +func (c *Command) GenBashCompletion(w io.Writer) error { + buf := new(bytes.Buffer) + writePreamble(buf, c.Name()) + if len(c.BashCompletionFunction) > 0 { + buf.WriteString(c.BashCompletionFunction + "\n") } - if len(cmd.BashCompletionFunction) > 0 { - if _, err := fmt.Fprintf(w, "%s\n", cmd.BashCompletionFunction); err != nil { - return err - } - } - if err := gen(cmd, w); err != nil { - return err - } - return postscript(w, cmd.Name()) + gen(buf, c) + writePostscript(buf, c.Name()) + + _, err := buf.WriteTo(w) + return err } -func (cmd *Command) GenBashCompletionFile(filename string) error { +func nonCompletableFlag(flag *pflag.Flag) bool { + return flag.Hidden || len(flag.Deprecated) > 0 +} + +// GenBashCompletionFile generates bash completion file. +func (c *Command) GenBashCompletionFile(filename string) error { outFile, err := os.Create(filename) if err != nil { return err } defer outFile.Close() - return cmd.GenBashCompletion(outFile) + return c.GenBashCompletion(outFile) } // MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists. -func (cmd *Command) MarkFlagRequired(name string) error { - return MarkFlagRequired(cmd.Flags(), name) +func (c *Command) MarkFlagRequired(name string) error { + return MarkFlagRequired(c.Flags(), name) } // MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag, if it exists. -func (cmd *Command) MarkPersistentFlagRequired(name string) error { - return MarkFlagRequired(cmd.PersistentFlags(), name) +func (c *Command) MarkPersistentFlagRequired(name string) error { + return MarkFlagRequired(c.PersistentFlags(), name) } // MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag in the flag set, if it exists. @@ -601,20 +508,20 @@ func MarkFlagRequired(flags *pflag.FlagSet, name string) error { // MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists. // Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. -func (cmd *Command) MarkFlagFilename(name string, extensions ...string) error { - return MarkFlagFilename(cmd.Flags(), name, extensions...) +func (c *Command) MarkFlagFilename(name string, extensions ...string) error { + return MarkFlagFilename(c.Flags(), name, extensions...) } // MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. // Generated bash autocompletion will call the bash function f for the flag. -func (cmd *Command) MarkFlagCustom(name string, f string) error { - return MarkFlagCustom(cmd.Flags(), name, f) +func (c *Command) MarkFlagCustom(name string, f string) error { + return MarkFlagCustom(c.Flags(), name, f) } // MarkPersistentFlagFilename adds the BashCompFilenameExt annotation to the named persistent flag, if it exists. // Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. -func (cmd *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { - return MarkFlagFilename(cmd.PersistentFlags(), name, extensions...) +func (c *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { + return MarkFlagFilename(c.PersistentFlags(), name, extensions...) } // MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists. diff --git a/vendor/github.com/spf13/cobra/bash_completions.md b/vendor/github.com/spf13/cobra/bash_completions.md index 6e3b71f13d5..52bd39ddb1d 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.md +++ b/vendor/github.com/spf13/cobra/bash_completions.md @@ -18,7 +18,7 @@ func main() { } ``` -That will get you completions of subcommands and flags. If you make additional annotations to your code, you can get even more intelligent and flexible behavior. +`out.sh` will get you completions of subcommands and flags. Copy it to `/etc/bash_completion.d/` as described [here](https://debian-administration.org/article/316/An_introduction_to_bash_completion_part_1) and reset your terminal to use autocompletion. If you make additional annotations to your code, you can get even more intelligent and flexible behavior. ## Creating your own custom functions @@ -106,7 +106,7 @@ node pod replicationcontroller service If your nouns have a number of aliases, you can define them alongside `ValidArgs` using `ArgAliases`: -```go` +```go argAliases []string = { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" } cmd := &cobra.Command{ diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go index 93a2c0f3a77..e4b910c5d7a 100644 --- a/vendor/github.com/spf13/cobra/cobra.go +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -27,48 +27,59 @@ import ( ) var templateFuncs = template.FuncMap{ - "trim": strings.TrimSpace, - "trimRightSpace": trimRightSpace, - "appendIfNotPresent": appendIfNotPresent, - "rpad": rpad, - "gt": Gt, - "eq": Eq, + "trim": strings.TrimSpace, + "trimRightSpace": trimRightSpace, + "trimTrailingWhitespaces": trimRightSpace, + "appendIfNotPresent": appendIfNotPresent, + "rpad": rpad, + "gt": Gt, + "eq": Eq, } var initializers []func() -// automatic prefix matching can be a dangerous thing to automatically enable in CLI tools. -// Set this to true to enable it +// EnablePrefixMatching allows to set automatic prefix matching. Automatic prefix matching can be a dangerous thing +// to automatically enable in CLI tools. +// Set this to true to enable it. var EnablePrefixMatching = false -//EnableCommandSorting controls sorting of the slice of commands, which is turned on by default. -//To disable sorting, set it to false. +// EnableCommandSorting controls sorting of the slice of commands, which is turned on by default. +// To disable sorting, set it to false. var EnableCommandSorting = true -//AddTemplateFunc adds a template function that's available to Usage and Help -//template generation. +// MousetrapHelpText enables an information splash screen on Windows +// if the CLI is started from explorer.exe. +// To disable the mousetrap, just set this variable to blank string (""). +// Works only on Microsoft Windows. +var MousetrapHelpText string = `This is a command line tool. + +You need to open cmd.exe and run it from there. +` + +// AddTemplateFunc adds a template function that's available to Usage and Help +// template generation. func AddTemplateFunc(name string, tmplFunc interface{}) { templateFuncs[name] = tmplFunc } -//AddTemplateFuncs adds multiple template functions availalble to Usage and -//Help template generation. +// AddTemplateFuncs adds multiple template functions that are available to Usage and +// Help template generation. func AddTemplateFuncs(tmplFuncs template.FuncMap) { for k, v := range tmplFuncs { templateFuncs[k] = v } } -//OnInitialize takes a series of func() arguments and appends them to a slice of func(). +// OnInitialize takes a series of func() arguments and appends them to a slice of func(). func OnInitialize(y ...func()) { - for _, x := range y { - initializers = append(initializers, x) - } + initializers = append(initializers, y...) } -//Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans, -//Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as -//ints and then compared. +// FIXME Gt is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans, +// Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as +// ints and then compared. func Gt(a interface{}, b interface{}) bool { var left, right int64 av := reflect.ValueOf(a) @@ -96,7 +107,9 @@ func Gt(a interface{}, b interface{}) bool { return left > right } -//Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic. +// FIXME Eq is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic. func Eq(a interface{}, b interface{}) bool { av := reflect.ValueOf(a) bv := reflect.ValueOf(b) @@ -116,7 +129,9 @@ func trimRightSpace(s string) string { return strings.TrimRightFunc(s, unicode.IsSpace) } -// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s +// FIXME appendIfNotPresent is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s. func appendIfNotPresent(s, stringToAppend string) string { if strings.Contains(s, stringToAppend) { return s @@ -124,7 +139,7 @@ func appendIfNotPresent(s, stringToAppend string) string { return s + " " + stringToAppend } -//rpad adds padding to the right of a string +// rpad adds padding to the right of a string. func rpad(s string, padding int) string { template := fmt.Sprintf("%%-%ds", padding) return fmt.Sprintf(template, s) @@ -138,7 +153,7 @@ func tmpl(w io.Writer, text string, data interface{}) error { return t.Execute(w, data) } -// ld compares two strings and returns the levenshtein distance between them +// ld compares two strings and returns the levenshtein distance between them. func ld(s, t string, ignoreCase bool) int { if ignoreCase { s = strings.ToLower(s) @@ -173,3 +188,12 @@ func ld(s, t string, ignoreCase bool) int { } return d[len(s)][len(t)] } + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go index 083e4ea7f47..eb311a7373a 100644 --- a/vendor/github.com/spf13/cobra/command.go +++ b/vendor/github.com/spf13/cobra/command.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces. -//In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code. +// Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces. +// In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code. package cobra import ( @@ -28,107 +28,158 @@ import ( ) // Command is just that, a command for your application. -// eg. 'go run' ... 'run' is the command. Cobra requires +// E.g. 'go run ...' - 'run' is the command. Cobra requires // you to define the usage and description as part of your command // definition to ensure usability. type Command struct { - // Name is the command name, usually the executable's name. - name string - // The one-line usage message. + // Use is the one-line usage message. Use string - // An array of aliases that can be used instead of the first word in Use. + + // Aliases is an array of aliases that can be used instead of the first word in Use. Aliases []string - // An array of command names for which this command will be suggested - similar to aliases but only suggests. + + // SuggestFor is an array of command names for which this command will be suggested - + // similar to aliases but only suggests. SuggestFor []string - // The short description shown in the 'help' output. + + // Short is the short description shown in the 'help' output. Short string - // The long message shown in the 'help ' output. + + // Long is the long message shown in the 'help ' output. Long string - // Examples of how to use the command + + // Example is examples of how to use the command. Example string - // List of all valid non-flag arguments that are accepted in bash completions + + // ValidArgs is list of all valid non-flag arguments that are accepted in bash completions ValidArgs []string - // List of aliases for ValidArgs. These are not suggested to the user in the bash - // completion, but accepted if entered manually. + + // Expected arguments + Args PositionalArgs + + // ArgAliases is List of aliases for ValidArgs. + // These are not suggested to the user in the bash completion, + // but accepted if entered manually. ArgAliases []string - // Custom functions used by the bash autocompletion generator + + // BashCompletionFunction is custom functions used by the bash autocompletion generator. BashCompletionFunction string - // Is this command deprecated and should print this string when used? + + // Deprecated defines, if this command is deprecated and should print this string when used. Deprecated string - // Is this command hidden and should NOT show up in the list of available commands? + + // Hidden defines, if this command is hidden and should NOT show up in the list of available commands. Hidden bool - // Full set of flags - flags *flag.FlagSet - // Set of flags childrens of this command will inherit - pflags *flag.FlagSet - // Flags that are declared specifically by this command (not inherited). - lflags *flag.FlagSet - // SilenceErrors is an option to quiet errors down stream - SilenceErrors bool - // Silence Usage is an option to silence usage when an error occurs. - SilenceUsage bool + + // Annotations are key/value pairs that can be used by applications to identify or + // group commands. + Annotations map[string]string + // The *Run functions are executed in the following order: // * PersistentPreRun() // * PreRun() // * Run() // * PostRun() // * PersistentPostRun() - // All functions get the same args, the arguments after the command name - // PersistentPreRun: children of this command will inherit and execute + // All functions get the same args, the arguments after the command name. + // + // PersistentPreRun: children of this command will inherit and execute. PersistentPreRun func(cmd *Command, args []string) - // PersistentPreRunE: PersistentPreRun but returns an error + // PersistentPreRunE: PersistentPreRun but returns an error. PersistentPreRunE func(cmd *Command, args []string) error // PreRun: children of this command will not inherit. PreRun func(cmd *Command, args []string) - // PreRunE: PreRun but returns an error + // PreRunE: PreRun but returns an error. PreRunE func(cmd *Command, args []string) error - // Run: Typically the actual work function. Most commands will only implement this + // Run: Typically the actual work function. Most commands will only implement this. Run func(cmd *Command, args []string) - // RunE: Run but returns an error + // RunE: Run but returns an error. RunE func(cmd *Command, args []string) error // PostRun: run after the Run command. PostRun func(cmd *Command, args []string) - // PostRunE: PostRun but returns an error + // PostRunE: PostRun but returns an error. PostRunE func(cmd *Command, args []string) error - // PersistentPostRun: children of this command will inherit and execute after PostRun + // PersistentPostRun: children of this command will inherit and execute after PostRun. PersistentPostRun func(cmd *Command, args []string) - // PersistentPostRunE: PersistentPostRun but returns an error + // PersistentPostRunE: PersistentPostRun but returns an error. PersistentPostRunE func(cmd *Command, args []string) error - // DisableAutoGenTag remove + + // SilenceErrors is an option to quiet errors down stream. + SilenceErrors bool + + // SilenceUsage is an option to silence usage when an error occurs. + SilenceUsage bool + + // DisableFlagParsing disables the flag parsing. + // If this is true all flags will be passed to the command as arguments. + DisableFlagParsing bool + + // DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...") + // will be printed by generating docs for this command. DisableAutoGenTag bool - // Commands is the list of commands supported by this program. + + // DisableFlagsInUseLine will disable the addition of [flags] to the usage + // line of a command when printing help or generating docs + DisableFlagsInUseLine bool + + // DisableSuggestions disables the suggestions based on Levenshtein distance + // that go along with 'unknown command' messages. + DisableSuggestions bool + // SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions. + // Must be > 0. + SuggestionsMinimumDistance int + + // TraverseChildren parses flags on all parents before executing child command. + TraverseChildren bool + + // commands is the list of commands supported by this program. commands []*Command - // Parent Command for this command + // parent is a parent command for this command. parent *Command - // max lengths of commands' string lengths for use in padding + // Max lengths of commands' string lengths for use in padding. commandsMaxUseLen int commandsMaxCommandPathLen int commandsMaxNameLen int - // is commands slice are sorted or not + // commandsAreSorted defines, if command slice are sorted or not. commandsAreSorted bool + // args is actual args parsed from flags. + args []string + // flagErrorBuf contains all error messages from pflag. flagErrorBuf *bytes.Buffer - - args []string // actual args parsed from flags - output *io.Writer // out writer if set in SetOutput(w) - usageFunc func(*Command) error // Usage can be defined by application - usageTemplate string // Can be defined by Application - helpTemplate string // Can be defined by Application - helpFunc func(*Command, []string) // Help can be defined by application - helpCommand *Command // The help command - // The global normalization function that we can use on every pFlag set and children commands + // flags is full set of flags. + flags *flag.FlagSet + // pflags contains persistent flags. + pflags *flag.FlagSet + // lflags contains local flags. + lflags *flag.FlagSet + // iflags contains inherited flags. + iflags *flag.FlagSet + // parentsPflags is all persistent flags of cmd's parents. + parentsPflags *flag.FlagSet + // globNormFunc is the global normalization function + // that we can use on every pflag set and children commands globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName - // Disable the suggestions based on Levenshtein distance that go along with 'unknown command' messages - DisableSuggestions bool - // If displaying suggestions, allows to set the minimum levenshtein distance to display, must be > 0 - SuggestionsMinimumDistance int - - // Disable the flag parsing. If this is true all flags will be passed to the command as arguments. - DisableFlagParsing bool + // output is an output writer defined by user. + output io.Writer + // usageFunc is usage func defined by user. + usageFunc func(*Command) error + // usageTemplate is usage template defined by user. + usageTemplate string + // flagErrorFunc is func defined by user and it's called when the parsing of + // flags returns an error. + flagErrorFunc func(*Command, error) error + // helpTemplate is help template defined by user. + helpTemplate string + // helpFunc is help func defined by user. + helpFunc func(*Command, []string) + // helpCommand is command with usage 'help'. If it's not defined by user, + // cobra uses default help command. + helpCommand *Command } -// os.Args[1:] by default, if desired, can be overridden +// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden // particularly useful when testing. func (c *Command) SetArgs(a []string) { c.args = a @@ -137,29 +188,36 @@ func (c *Command) SetArgs(a []string) { // SetOutput sets the destination for usage and error messages. // If output is nil, os.Stderr is used. func (c *Command) SetOutput(output io.Writer) { - c.output = &output + c.output = output } -// Usage can be defined by application +// SetUsageFunc sets usage function. Usage can be defined by application. func (c *Command) SetUsageFunc(f func(*Command) error) { c.usageFunc = f } -// Can be defined by Application +// SetUsageTemplate sets usage template. Can be defined by Application. func (c *Command) SetUsageTemplate(s string) { c.usageTemplate = s } -// Can be defined by Application +// SetFlagErrorFunc sets a function to generate an error when flag parsing +// fails. +func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) { + c.flagErrorFunc = f +} + +// SetHelpFunc sets help function. Can be defined by Application. func (c *Command) SetHelpFunc(f func(*Command, []string)) { c.helpFunc = f } +// SetHelpCommand sets help command. func (c *Command) SetHelpCommand(cmd *Command) { c.helpCommand = cmd } -// Can be defined by Application +// SetHelpTemplate sets help template to be used. Application can use it to set custom template. func (c *Command) SetHelpTemplate(s string) { c.helpTemplate = s } @@ -176,17 +234,19 @@ func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string } } +// OutOrStdout returns output to stdout. func (c *Command) OutOrStdout() io.Writer { return c.getOut(os.Stdout) } +// OutOrStderr returns output to stderr func (c *Command) OutOrStderr() io.Writer { return c.getOut(os.Stderr) } func (c *Command) getOut(def io.Writer) io.Writer { if c.output != nil { - return *c.output + return c.output } if c.HasParent() { return c.parent.getOut(def) @@ -195,14 +255,13 @@ func (c *Command) getOut(def io.Writer) io.Writer { } // UsageFunc returns either the function set by SetUsageFunc for this command -// or a parent, or it returns a default usage function +// or a parent, or it returns a default usage function. func (c *Command) UsageFunc() (f func(*Command) error) { if c.usageFunc != nil { return c.usageFunc } - if c.HasParent() { - return c.parent.UsageFunc() + return c.Parent().UsageFunc() } return func(c *Command) error { c.mergePersistentFlags() @@ -214,24 +273,23 @@ func (c *Command) UsageFunc() (f func(*Command) error) { } } -// Output the usage for the command -// Used when a user provides invalid input -// Can be defined by user by overriding UsageFunc +// Usage puts out the usage for the command. +// Used when a user provides invalid input. +// Can be defined by user by overriding UsageFunc. func (c *Command) Usage() error { return c.UsageFunc()(c) } // HelpFunc returns either the function set by SetHelpFunc for this command -// or a parent, or it returns a function with default help behavior +// or a parent, or it returns a function with default help behavior. func (c *Command) HelpFunc() func(*Command, []string) { - cmd := c - for cmd != nil { - if cmd.helpFunc != nil { - return cmd.helpFunc - } - cmd = cmd.parent + if c.helpFunc != nil { + return c.helpFunc } - return func(*Command, []string) { + if c.HasParent() { + return c.Parent().HelpFunc() + } + return func(c *Command, a []string) { c.mergePersistentFlags() err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c) if err != nil { @@ -240,14 +298,15 @@ func (c *Command) HelpFunc() func(*Command, []string) { } } -// Output the help for the command -// Used when a user calls help [command] -// Can be defined by user by overriding HelpFunc +// Help puts out the help for the command. +// Used when a user calls help [command]. +// Can be defined by user by overriding HelpFunc. func (c *Command) Help() error { c.HelpFunc()(c, []string{}) return nil } +// UsageString return usage string. func (c *Command) UsageString() string { tmpOutput := c.output bb := new(bytes.Buffer) @@ -257,8 +316,25 @@ func (c *Command) UsageString() string { return bb.String() } +// FlagErrorFunc returns either the function set by SetFlagErrorFunc for this +// command or a parent, or it returns a function which returns the original +// error. +func (c *Command) FlagErrorFunc() (f func(*Command, error) error) { + if c.flagErrorFunc != nil { + return c.flagErrorFunc + } + + if c.HasParent() { + return c.parent.FlagErrorFunc() + } + return func(c *Command, err error) error { + return err + } +} + var minUsagePadding = 25 +// UsagePadding return padding for the usage. func (c *Command) UsagePadding() int { if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen { return minUsagePadding @@ -268,7 +344,7 @@ func (c *Command) UsagePadding() int { var minCommandPathPadding = 11 -// +// CommandPathPadding return padding for the command path. func (c *Command) CommandPathPadding() int { if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen { return minCommandPathPadding @@ -278,6 +354,7 @@ func (c *Command) CommandPathPadding() int { var minNamePadding = 11 +// NamePadding returns padding for the name. func (c *Command) NamePadding() int { if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen { return minNamePadding @@ -285,6 +362,7 @@ func (c *Command) NamePadding() int { return c.parent.commandsMaxNameLen } +// UsageTemplate returns usage template for the command. func (c *Command) UsageTemplate() string { if c.usageTemplate != "" { return c.usageTemplate @@ -294,32 +372,32 @@ func (c *Command) UsageTemplate() string { return c.parent.UsageTemplate() } return `Usage:{{if .Runnable}} - {{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}} - {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}} + {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} + {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}} Aliases: - {{.NameAndAliases}} -{{end}}{{if .HasExample}} + {{.NameAndAliases}}{{end}}{{if .HasExample}} Examples: -{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}} +{{.Example}}{{end}}{{if .HasAvailableSubCommands}} -Available Commands:{{range .Commands}}{{if .IsAvailableCommand}} - {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}} +Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} Flags: -{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}} +{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}} Global Flags: -{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}} +{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}} -Additional help topics:{{range .Commands}}{{if .IsHelpCommand}} - {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }} +Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}} + {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}} Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}} ` } +// HelpTemplate return help template for the command. func (c *Command) HelpTemplate() string { if c.helpTemplate != "" { return c.helpTemplate @@ -328,72 +406,60 @@ func (c *Command) HelpTemplate() string { if c.HasParent() { return c.parent.HelpTemplate() } - return `{{with or .Long .Short }}{{. | trim}} + return `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}} {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` } -// Really only used when casting a command to a commander -func (c *Command) resetChildrensParents() { - for _, x := range c.commands { - x.parent = c - } -} - -// Test if the named flag is a boolean flag. -func isBooleanFlag(name string, f *flag.FlagSet) bool { - flag := f.Lookup(name) +func hasNoOptDefVal(name string, fs *flag.FlagSet) bool { + flag := fs.Lookup(name) if flag == nil { return false } - return flag.Value.Type() == "bool" + return flag.NoOptDefVal != "" } -// Test if the named flag is a boolean flag. -func isBooleanShortFlag(name string, f *flag.FlagSet) bool { - result := false - f.VisitAll(func(f *flag.Flag) { - if f.Shorthand == name && f.Value.Type() == "bool" { - result = true - } - }) - return result +func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool { + if len(name) == 0 { + return false + } + + flag := fs.ShorthandLookup(name[:1]) + if flag == nil { + return false + } + return flag.NoOptDefVal != "" } func stripFlags(args []string, c *Command) []string { - if len(args) < 1 { + if len(args) == 0 { return args } c.mergePersistentFlags() commands := []string{} + flags := c.Flags() - inQuote := false - inFlag := false - for _, y := range args { - if !inQuote { - switch { - case strings.HasPrefix(y, "\""): - inQuote = true - case strings.Contains(y, "=\""): - inQuote = true - case strings.HasPrefix(y, "--") && !strings.Contains(y, "="): - // TODO: this isn't quite right, we should really check ahead for 'true' or 'false' - inFlag = !isBooleanFlag(y[2:], c.Flags()) - case strings.HasPrefix(y, "-") && !strings.Contains(y, "=") && len(y) == 2 && !isBooleanShortFlag(y[1:], c.Flags()): - inFlag = true - case inFlag: - inFlag = false - case y == "": - // strip empty commands, as the go tests expect this to be ok.... - case !strings.HasPrefix(y, "-"): - commands = append(commands, y) - inFlag = false +Loop: + for len(args) > 0 { + s := args[0] + args = args[1:] + switch { + case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): + // If '--flag arg' then + // delete arg from args. + fallthrough // (do the same as below) + case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): + // If '-f arg' then + // delete 'arg' from args or break the loop if len(args) <= 1. + if len(args) <= 1 { + break Loop + } else { + args = args[1:] + continue } - } - - if strings.HasSuffix(y, "\"") && !strings.HasSuffix(y, "\\\"") { - inQuote = false + case s != "" && !strings.HasPrefix(s, "-"): + commands = append(commands, s) } } @@ -414,13 +480,14 @@ func argsMinusFirstX(args []string, x string) []string { return args } -// find the target command given the args and command tree +func isFlagArg(arg string) bool { + return ((len(arg) >= 3 && arg[1] == '-') || + (len(arg) >= 2 && arg[0] == '-' && arg[1] != '-')) +} + +// Find the target command given the args and command tree // Meant to be run on the highest node. Only searches down. func (c *Command) Find(args []string) (*Command, []string, error) { - if c == nil { - return nil, nil, fmt.Errorf("Called find() on a nil Command") - } - var innerfind func(*Command, []string) (*Command, []string) innerfind = func(c *Command, innerArgs []string) (*Command, []string) { @@ -429,59 +496,99 @@ func (c *Command) Find(args []string) (*Command, []string, error) { return c, innerArgs } nextSubCmd := argsWOflags[0] - matches := make([]*Command, 0) - for _, cmd := range c.commands { - if cmd.Name() == nextSubCmd || cmd.HasAlias(nextSubCmd) { // exact name or alias match - return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd)) - } - if EnablePrefixMatching { - if strings.HasPrefix(cmd.Name(), nextSubCmd) { // prefix match - matches = append(matches, cmd) - } - for _, x := range cmd.Aliases { - if strings.HasPrefix(x, nextSubCmd) { - matches = append(matches, cmd) - } - } - } - } - // only accept a single prefix match - multiple matches would be ambiguous - if len(matches) == 1 { - return innerfind(matches[0], argsMinusFirstX(innerArgs, argsWOflags[0])) + cmd := c.findNext(nextSubCmd) + if cmd != nil { + return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd)) } - return c, innerArgs } commandFound, a := innerfind(c, args) - argsWOflags := stripFlags(a, commandFound) - - // no subcommand, always take args - if !commandFound.HasSubCommands() { - return commandFound, a, nil + if commandFound.Args == nil { + return commandFound, a, legacyArgs(commandFound, stripFlags(a, commandFound)) } - - // root command with subcommands, do subcommand checking - if commandFound == c && len(argsWOflags) > 0 { - suggestionsString := "" - if !c.DisableSuggestions { - if c.SuggestionsMinimumDistance <= 0 { - c.SuggestionsMinimumDistance = 2 - } - if suggestions := c.SuggestionsFor(argsWOflags[0]); len(suggestions) > 0 { - suggestionsString += "\n\nDid you mean this?\n" - for _, s := range suggestions { - suggestionsString += fmt.Sprintf("\t%v\n", s) - } - } - } - return commandFound, a, fmt.Errorf("unknown command %q for %q%s", argsWOflags[0], commandFound.CommandPath(), suggestionsString) - } - return commandFound, a, nil } +func (c *Command) findSuggestions(arg string) string { + if c.DisableSuggestions { + return "" + } + if c.SuggestionsMinimumDistance <= 0 { + c.SuggestionsMinimumDistance = 2 + } + suggestionsString := "" + if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 { + suggestionsString += "\n\nDid you mean this?\n" + for _, s := range suggestions { + suggestionsString += fmt.Sprintf("\t%v\n", s) + } + } + return suggestionsString +} + +func (c *Command) findNext(next string) *Command { + matches := make([]*Command, 0) + for _, cmd := range c.commands { + if cmd.Name() == next || cmd.HasAlias(next) { + return cmd + } + if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) { + matches = append(matches, cmd) + } + } + + if len(matches) == 1 { + return matches[0] + } + return nil +} + +// Traverse the command tree to find the command, and parse args for +// each parent. +func (c *Command) Traverse(args []string) (*Command, []string, error) { + flags := []string{} + inFlag := false + + for i, arg := range args { + switch { + // A long flag with a space separated value + case strings.HasPrefix(arg, "--") && !strings.Contains(arg, "="): + // TODO: this isn't quite right, we should really check ahead for 'true' or 'false' + inFlag = !hasNoOptDefVal(arg[2:], c.Flags()) + flags = append(flags, arg) + continue + // A short flag with a space separated value + case strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") && len(arg) == 2 && !shortHasNoOptDefVal(arg[1:], c.Flags()): + inFlag = true + flags = append(flags, arg) + continue + // The value for a flag + case inFlag: + inFlag = false + flags = append(flags, arg) + continue + // A flag without a value, or with an `=` separated value + case isFlagArg(arg): + flags = append(flags, arg) + continue + } + + cmd := c.findNext(arg) + if cmd == nil { + return c, args, nil + } + + if err := c.ParseFlags(flags); err != nil { + return nil, args, err + } + return cmd.Traverse(args[i+1:]) + } + return c, args, nil +} + +// SuggestionsFor provides suggestions for the typedName. func (c *Command) SuggestionsFor(typedName string) []string { suggestions := []string{} for _, cmd := range c.commands { @@ -502,38 +609,24 @@ func (c *Command) SuggestionsFor(typedName string) []string { return suggestions } +// VisitParents visits all parents of the command and invokes fn on each parent. func (c *Command) VisitParents(fn func(*Command)) { - var traverse func(*Command) *Command - - traverse = func(x *Command) *Command { - if x != c { - fn(x) - } - if x.HasParent() { - return traverse(x.parent) - } - return x + if c.HasParent() { + fn(c.Parent()) + c.Parent().VisitParents(fn) } - traverse(c) } +// Root finds root command. func (c *Command) Root() *Command { - var findRoot func(*Command) *Command - - findRoot = func(x *Command) *Command { - if x.HasParent() { - return findRoot(x.parent) - } - return x + if c.HasParent() { + return c.Parent().Root() } - - return findRoot(c) + return c } -// ArgsLenAtDash will return the length of f.Args at the moment when a -- was -// found during arg parsing. This allows your program to know which args were -// before the -- and which came after. (Description from -// https://godoc.org/github.com/spf13/pflag#FlagSet.ArgsLenAtDash). +// ArgsLenAtDash will return the length of c.Flags().Args at the moment +// when a -- was found during args parsing. func (c *Command) ArgsLenAtDash() int { return c.Flags().ArgsLenAtDash() } @@ -549,18 +642,19 @@ func (c *Command) execute(a []string) (err error) { // initialize help flag as the last point possible to allow for user // overriding - c.initHelpFlag() + c.InitDefaultHelpFlag() err = c.ParseFlags(a) if err != nil { - return err + return c.FlagErrorFunc()(c, err) } - // If help is called, regardless of other flags, return we want help + + // If help is called, regardless of other flags, return we want help. // Also say we need help if the command isn't runnable. helpVal, err := c.Flags().GetBool("help") if err != nil { // should be impossible to get here as we always declare a help - // flag in initHelpFlag() + // flag in InitDefaultHelpFlag() c.Println("\"help\" flag declared as non-bool. Please correct your code") return err } @@ -576,6 +670,10 @@ func (c *Command) execute(a []string) (err error) { argWoFlags = a } + if err := c.ValidateArgs(argWoFlags); err != nil { + return err + } + for p := c; p != nil; p = p.Parent() { if p.PersistentPreRunE != nil { if err := p.PersistentPreRunE(c, argWoFlags); err != nil { @@ -595,6 +693,9 @@ func (c *Command) execute(a []string) (err error) { c.PreRun(c, argWoFlags) } + if err := c.validateRequiredFlags(); err != nil { + return err + } if c.RunE != nil { if err := c.RunE(c, argWoFlags); err != nil { return err @@ -630,18 +731,7 @@ func (c *Command) preRun() { } } -func (c *Command) errorMsgFromParse() string { - s := c.flagErrorBuf.String() - - x := strings.Split(s, "\n") - - if len(x) > 0 { - return x[0] - } - return "" -} - -// Call execute to use the args (os.Args[1:] by default) +// Execute uses the args (os.Args[1:] by default) // and run through the command tree finding appropriate matches // for commands and then corresponding flags. func (c *Command) Execute() error { @@ -649,8 +739,8 @@ func (c *Command) Execute() error { return err } +// ExecuteC executes the command. func (c *Command) ExecuteC() (cmd *Command, err error) { - // Regardless of what command execute is called on, run on Root only if c.HasParent() { return c.Root().ExecuteC() @@ -663,7 +753,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { // initialize help as the last point possible to allow for user // overriding - c.initHelpCmd() + c.InitDefaultHelpCmd() var args []string @@ -674,7 +764,12 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { args = c.args } - cmd, flags, err := c.Find(args) + var flags []string + if c.TraverseChildren { + cmd, flags, err = c.Traverse(args) + } else { + cmd, flags, err = c.Find(args) + } if err != nil { // If found parse to a subcommand and then failed, talk about the subcommand if cmd != nil { @@ -686,6 +781,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { } return c, err } + err = cmd.execute(flags) if err != nil { // Always show help if requested, even if SilenceErrors is in @@ -706,52 +802,92 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { if !cmd.SilenceUsage && !c.SilenceUsage { c.Println(cmd.UsageString()) } - return cmd, err } - return cmd, nil + return cmd, err } -func (c *Command) initHelpFlag() { - if c.Flags().Lookup("help") == nil { - c.Flags().BoolP("help", "h", false, "help for "+c.Name()) +func (c *Command) ValidateArgs(args []string) error { + if c.Args == nil { + return nil } + return c.Args(c, args) } -func (c *Command) initHelpCmd() { - if c.helpCommand == nil { - if !c.HasSubCommands() { +func (c *Command) validateRequiredFlags() error { + flags := c.Flags() + missingFlagNames := []string{} + flags.VisitAll(func(pflag *flag.Flag) { + requiredAnnotation, found := pflag.Annotations[BashCompOneRequiredFlag] + if !found { return } + if (requiredAnnotation[0] == "true") && !pflag.Changed { + missingFlagNames = append(missingFlagNames, pflag.Name) + } + }) + if len(missingFlagNames) > 0 { + return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`)) + } + return nil +} + +// InitDefaultHelpFlag adds default help flag to c. +// It is called automatically by executing the c or by calling help and usage. +// If c already has help flag, it will do nothing. +func (c *Command) InitDefaultHelpFlag() { + c.mergePersistentFlags() + if c.Flags().Lookup("help") == nil { + usage := "help for " + if c.Name() == "" { + usage += "this command" + } else { + usage += c.Name() + } + c.Flags().BoolP("help", "h", false, usage) + } +} + +// InitDefaultHelpCmd adds default help command to c. +// It is called automatically by executing the c or by calling help and usage. +// If c already has help command or c has no subcommands, it will do nothing. +func (c *Command) InitDefaultHelpCmd() { + if !c.HasSubCommands() { + return + } + + if c.helpCommand == nil { c.helpCommand = &Command{ Use: "help [command]", Short: "Help about any command", Long: `Help provides help for any command in the application. - Simply type ` + c.Name() + ` help [path to command] for full details.`, - PersistentPreRun: func(cmd *Command, args []string) {}, - PersistentPostRun: func(cmd *Command, args []string) {}, +Simply type ` + c.Name() + ` help [path to command] for full details.`, Run: func(c *Command, args []string) { cmd, _, e := c.Root().Find(args) if cmd == nil || e != nil { - c.Printf("Unknown help topic %#q.", args) + c.Printf("Unknown help topic %#q\n", args) c.Root().Usage() } else { + cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown cmd.Help() } }, } } + c.RemoveCommand(c.helpCommand) c.AddCommand(c.helpCommand) } -// Used for testing +// ResetCommands delete parent, subcommand and help command from c. func (c *Command) ResetCommands() { + c.parent = nil c.commands = nil c.helpCommand = nil + c.parentsPflags = nil } -// Sorts commands by their names +// Sorts commands by their names. type commandSorterByName []*Command func (c commandSorterByName) Len() int { return len(c) } @@ -831,45 +967,48 @@ main: } } -// Print is a convenience method to Print to the defined output, fallback to Stderr if not set +// Print is a convenience method to Print to the defined output, fallback to Stderr if not set. func (c *Command) Print(i ...interface{}) { fmt.Fprint(c.OutOrStderr(), i...) } -// Println is a convenience method to Println to the defined output, fallback to Stderr if not set +// Println is a convenience method to Println to the defined output, fallback to Stderr if not set. func (c *Command) Println(i ...interface{}) { - str := fmt.Sprintln(i...) - c.Print(str) + c.Print(fmt.Sprintln(i...)) } -// Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set +// Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set. func (c *Command) Printf(format string, i ...interface{}) { - str := fmt.Sprintf(format, i...) - c.Print(str) + c.Print(fmt.Sprintf(format, i...)) } // CommandPath returns the full path to this command. func (c *Command) CommandPath() string { - str := c.Name() - x := c - for x.HasParent() { - str = x.parent.Name() + " " + str - x = x.parent - } - return str -} - -//The full usage for a given command (including parents) -func (c *Command) UseLine() string { - str := "" if c.HasParent() { - str = c.parent.CommandPath() + " " + return c.Parent().CommandPath() + " " + c.Name() } - return str + c.Use + return c.Name() } -// For use in determining which flags have been assigned to which commands -// and which persist +// UseLine puts out the full usage for a given command (including parents). +func (c *Command) UseLine() string { + var useline string + if c.HasParent() { + useline = c.parent.CommandPath() + " " + c.Use + } else { + useline = c.Use + } + if c.DisableFlagsInUseLine { + return useline + } + if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") { + useline += " [flags]" + } + return useline +} + +// DebugFlags used to determine which flags have been assigned to which commands +// and which persist. func (c *Command) DebugFlags() { c.Println("DebugFlags called on", c.Name()) var debugflags func(*Command) @@ -880,12 +1019,8 @@ func (c *Command) DebugFlags() { } if x.HasFlags() { x.flags.VisitAll(func(f *flag.Flag) { - if x.HasPersistentFlags() { - if x.persistentFlag(f.Name) == nil { - c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]") - } else { - c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]") - } + if x.HasPersistentFlags() && x.persistentFlag(f.Name) != nil { + c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]") } else { c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]") } @@ -915,9 +1050,6 @@ func (c *Command) DebugFlags() { // Name returns the command's name: the first word in the use line. func (c *Command) Name() string { - if c.name != "" { - return c.name - } name := c.Use i := strings.Index(name, " ") if i >= 0 { @@ -936,26 +1068,42 @@ func (c *Command) HasAlias(s string) bool { return false } +// hasNameOrAliasPrefix returns true if the Name or any of aliases start +// with prefix +func (c *Command) hasNameOrAliasPrefix(prefix string) bool { + if strings.HasPrefix(c.Name(), prefix) { + return true + } + for _, alias := range c.Aliases { + if strings.HasPrefix(alias, prefix) { + return true + } + } + return false +} + +// NameAndAliases returns a list of the command name and all aliases func (c *Command) NameAndAliases() string { return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ") } +// HasExample determines if the command has example. func (c *Command) HasExample() bool { return len(c.Example) > 0 } -// Runnable determines if the command is itself runnable +// Runnable determines if the command is itself runnable. func (c *Command) Runnable() bool { return c.Run != nil || c.RunE != nil } -// HasSubCommands determines if the command has children commands +// HasSubCommands determines if the command has children commands. func (c *Command) HasSubCommands() bool { return len(c.commands) > 0 } // IsAvailableCommand determines if a command is available as a non-help command -// (this includes all non deprecated/hidden commands) +// (this includes all non deprecated/hidden commands). func (c *Command) IsAvailableCommand() bool { if len(c.Deprecated) != 0 || c.Hidden { return false @@ -972,11 +1120,12 @@ func (c *Command) IsAvailableCommand() bool { return false } -// IsHelpCommand determines if a command is a 'help' command; a help command is -// determined by the fact that it is NOT runnable/hidden/deprecated, and has no -// sub commands that are runnable/hidden/deprecated -func (c *Command) IsHelpCommand() bool { - +// IsAdditionalHelpTopicCommand determines if a command is an additional +// help topic command; additional help topic command is determined by the +// fact that it is NOT runnable/hidden/deprecated, and has no sub commands that +// are runnable/hidden/deprecated. +// Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924. +func (c *Command) IsAdditionalHelpTopicCommand() bool { // if a command is runnable, deprecated, or hidden it is not a 'help' command if c.Runnable() || len(c.Deprecated) != 0 || c.Hidden { return false @@ -984,7 +1133,7 @@ func (c *Command) IsHelpCommand() bool { // if any non-help sub commands are found, the command is not a 'help' command for _, sub := range c.commands { - if !sub.IsHelpCommand() { + if !sub.IsAdditionalHelpTopicCommand() { return false } } @@ -993,14 +1142,13 @@ func (c *Command) IsHelpCommand() bool { return true } -// HasHelpSubCommands determines if a command has any avilable 'help' sub commands +// HasHelpSubCommands determines if a command has any available 'help' sub commands // that need to be shown in the usage/help default template under 'additional help -// topics' +// topics'. func (c *Command) HasHelpSubCommands() bool { - // return true on the first found available 'help' sub command for _, sub := range c.commands { - if sub.IsHelpCommand() { + if sub.IsAdditionalHelpTopicCommand() { return true } } @@ -1010,9 +1158,8 @@ func (c *Command) HasHelpSubCommands() bool { } // HasAvailableSubCommands determines if a command has available sub commands that -// need to be shown in the usage/help default template under 'available commands' +// need to be shown in the usage/help default template under 'available commands'. func (c *Command) HasAvailableSubCommands() bool { - // return true on the first found available (non deprecated/help/hidden) // sub command for _, sub := range c.commands { @@ -1021,22 +1168,23 @@ func (c *Command) HasAvailableSubCommands() bool { } } - // the command either has no sub comamnds, or no available (non deprecated/help/hidden) + // the command either has no sub commands, or no available (non deprecated/help/hidden) // sub commands return false } -// Determine if the command is a child command +// HasParent determines if the command is a child command. func (c *Command) HasParent() bool { return c.parent != nil } -// GlobalNormalizationFunc returns the global normalization function or nil if doesn't exists +// GlobalNormalizationFunc returns the global normalization function or nil if doesn't exists. func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName { return c.globNormFunc } -// Get the complete FlagSet that applies to this command (local and persistent declared here and by all parents) +// Flags returns the complete FlagSet that applies +// to this command (local and persistent declared here and by all parents). func (c *Command) Flags() *flag.FlagSet { if c.flags == nil { c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) @@ -1045,10 +1193,11 @@ func (c *Command) Flags() *flag.FlagSet { } c.flags.SetOutput(c.flagErrorBuf) } + return c.flags } -// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands +// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands. func (c *Command) LocalNonPersistentFlags() *flag.FlagSet { persistentFlags := c.PersistentFlags() @@ -1061,59 +1210,63 @@ func (c *Command) LocalNonPersistentFlags() *flag.FlagSet { return out } -// Get the local FlagSet specifically set in the current command +// LocalFlags returns the local FlagSet specifically set in the current command. func (c *Command) LocalFlags() *flag.FlagSet { c.mergePersistentFlags() - local := flag.NewFlagSet(c.Name(), flag.ContinueOnError) - c.lflags.VisitAll(func(f *flag.Flag) { - local.AddFlag(f) - }) - if !c.HasParent() { - flag.CommandLine.VisitAll(func(f *flag.Flag) { - if local.Lookup(f.Name) == nil { - local.AddFlag(f) - } - }) + if c.lflags == nil { + c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + c.lflags.SetOutput(c.flagErrorBuf) } - return local + c.lflags.SortFlags = c.Flags().SortFlags + if c.globNormFunc != nil { + c.lflags.SetNormalizeFunc(c.globNormFunc) + } + + addToLocal := func(f *flag.Flag) { + if c.lflags.Lookup(f.Name) == nil && c.parentsPflags.Lookup(f.Name) == nil { + c.lflags.AddFlag(f) + } + } + c.Flags().VisitAll(addToLocal) + c.PersistentFlags().VisitAll(addToLocal) + return c.lflags } -// All Flags which were inherited from parents commands +// InheritedFlags returns all flags which were inherited from parents commands. func (c *Command) InheritedFlags() *flag.FlagSet { c.mergePersistentFlags() - inherited := flag.NewFlagSet(c.Name(), flag.ContinueOnError) + if c.iflags == nil { + c.iflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + c.iflags.SetOutput(c.flagErrorBuf) + } + local := c.LocalFlags() - - var rmerge func(x *Command) - - rmerge = func(x *Command) { - if x.HasPersistentFlags() { - x.PersistentFlags().VisitAll(func(f *flag.Flag) { - if inherited.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil { - inherited.AddFlag(f) - } - }) - } - if x.HasParent() { - rmerge(x.parent) - } + if c.globNormFunc != nil { + c.iflags.SetNormalizeFunc(c.globNormFunc) } - if c.HasParent() { - rmerge(c.parent) - } - - return inherited + c.parentsPflags.VisitAll(func(f *flag.Flag) { + if c.iflags.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil { + c.iflags.AddFlag(f) + } + }) + return c.iflags } -// All Flags which were not inherited from parent commands +// NonInheritedFlags returns all flags which were not inherited from parent commands. func (c *Command) NonInheritedFlags() *flag.FlagSet { return c.LocalFlags() } -// Get the Persistent FlagSet specifically set in the current command +// PersistentFlags returns the persistent FlagSet specifically set in the current command. func (c *Command) PersistentFlags() *flag.FlagSet { if c.pflags == nil { c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) @@ -1125,7 +1278,7 @@ func (c *Command) PersistentFlags() *flag.FlagSet { return c.pflags } -// For use in testing +// ResetFlags deletes all flags from command. func (c *Command) ResetFlags() { c.flagErrorBuf = new(bytes.Buffer) c.flagErrorBuf.Reset() @@ -1133,52 +1286,56 @@ func (c *Command) ResetFlags() { c.flags.SetOutput(c.flagErrorBuf) c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) c.pflags.SetOutput(c.flagErrorBuf) + + c.lflags = nil + c.iflags = nil + c.parentsPflags = nil } -// Does the command contain any flags (local plus persistent from the entire structure) +// HasFlags checks if the command contains any flags (local plus persistent from the entire structure). func (c *Command) HasFlags() bool { return c.Flags().HasFlags() } -// Does the command contain persistent flags +// HasPersistentFlags checks if the command contains persistent flags. func (c *Command) HasPersistentFlags() bool { return c.PersistentFlags().HasFlags() } -// Does the command has flags specifically declared locally +// HasLocalFlags checks if the command has flags specifically declared locally. func (c *Command) HasLocalFlags() bool { return c.LocalFlags().HasFlags() } -// Does the command have flags inherited from its parent command +// HasInheritedFlags checks if the command has flags inherited from its parent command. func (c *Command) HasInheritedFlags() bool { return c.InheritedFlags().HasFlags() } -// Does the command contain any flags (local plus persistent from the entire -// structure) which are not hidden or deprecated +// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire +// structure) which are not hidden or deprecated. func (c *Command) HasAvailableFlags() bool { return c.Flags().HasAvailableFlags() } -// Does the command contain persistent flags which are not hidden or deprecated +// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated. func (c *Command) HasAvailablePersistentFlags() bool { return c.PersistentFlags().HasAvailableFlags() } -// Does the command has flags specifically declared locally which are not hidden -// or deprecated +// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden +// or deprecated. func (c *Command) HasAvailableLocalFlags() bool { return c.LocalFlags().HasAvailableFlags() } -// Does the command have flags inherited from its parent command which are -// not hidden or deprecated +// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are +// not hidden or deprecated. func (c *Command) HasAvailableInheritedFlags() bool { return c.InheritedFlags().HasAvailableFlags() } -// Flag climbs up the command tree looking for matching flag +// Flag climbs up the command tree looking for matching flag. func (c *Command) Flag(name string) (flag *flag.Flag) { flag = c.Flags().Lookup(name) @@ -1189,68 +1346,69 @@ func (c *Command) Flag(name string) (flag *flag.Flag) { return } -// recursively find matching persistent flag +// Recursively find matching persistent flag. func (c *Command) persistentFlag(name string) (flag *flag.Flag) { if c.HasPersistentFlags() { flag = c.PersistentFlags().Lookup(name) } - if flag == nil && c.HasParent() { - flag = c.parent.persistentFlag(name) + if flag == nil { + c.updateParentsPflags() + flag = c.parentsPflags.Lookup(name) } return } -// ParseFlags parses persistent flag tree & local flags -func (c *Command) ParseFlags(args []string) (err error) { +// ParseFlags parses persistent flag tree and local flags. +func (c *Command) ParseFlags(args []string) error { if c.DisableFlagParsing { return nil } + + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + beforeErrorBufLen := c.flagErrorBuf.Len() c.mergePersistentFlags() - err = c.Flags().Parse(args) - return + err := c.Flags().Parse(args) + // Print warnings if they occurred (e.g. deprecated flag messages). + if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil { + c.Print(c.flagErrorBuf.String()) + } + + return err } -// Parent returns a commands parent command +// Parent returns a commands parent command. func (c *Command) Parent() *Command { return c.parent } +// mergePersistentFlags merges c.PersistentFlags() to c.Flags() +// and adds missing persistent flags of all parents. func (c *Command) mergePersistentFlags() { - var rmerge func(x *Command) - - // Save the set of local flags - if c.lflags == nil { - c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) - if c.flagErrorBuf == nil { - c.flagErrorBuf = new(bytes.Buffer) - } - c.lflags.SetOutput(c.flagErrorBuf) - addtolocal := func(f *flag.Flag) { - c.lflags.AddFlag(f) - } - c.Flags().VisitAll(addtolocal) - c.PersistentFlags().VisitAll(addtolocal) - } - rmerge = func(x *Command) { - if !x.HasParent() { - flag.CommandLine.VisitAll(func(f *flag.Flag) { - if x.PersistentFlags().Lookup(f.Name) == nil { - x.PersistentFlags().AddFlag(f) - } - }) - } - if x.HasPersistentFlags() { - x.PersistentFlags().VisitAll(func(f *flag.Flag) { - if c.Flags().Lookup(f.Name) == nil { - c.Flags().AddFlag(f) - } - }) - } - if x.HasParent() { - rmerge(x.parent) - } - } - - rmerge(c) + c.updateParentsPflags() + c.Flags().AddFlagSet(c.PersistentFlags()) + c.Flags().AddFlagSet(c.parentsPflags) +} + +// updateParentsPflags updates c.parentsPflags by adding +// new persistent flags of all parents. +// If c.parentsPflags == nil, it makes new. +func (c *Command) updateParentsPflags() { + if c.parentsPflags == nil { + c.parentsPflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.parentsPflags.SetOutput(c.flagErrorBuf) + c.parentsPflags.SortFlags = false + } + + if c.globNormFunc != nil { + c.parentsPflags.SetNormalizeFunc(c.globNormFunc) + } + + c.Root().PersistentFlags().AddFlagSet(flag.CommandLine) + + c.VisitParents(func(parent *Command) { + c.parentsPflags.AddFlagSet(parent.PersistentFlags()) + }) } diff --git a/vendor/github.com/spf13/cobra/command_win.go b/vendor/github.com/spf13/cobra/command_win.go index 4b0eaa1b6bc..edec728e4f5 100644 --- a/vendor/github.com/spf13/cobra/command_win.go +++ b/vendor/github.com/spf13/cobra/command_win.go @@ -11,14 +11,8 @@ import ( var preExecHookFn = preExecHook -// enables an information splash screen on Windows if the CLI is started from explorer.exe. -var MousetrapHelpText string = `This is a command line tool - -You need to open cmd.exe and run it from there. -` - func preExecHook(c *Command) { - if mousetrap.StartedByExplorer() { + if MousetrapHelpText != "" && mousetrap.StartedByExplorer() { c.Print(MousetrapHelpText) time.Sleep(5 * time.Second) os.Exit(1) diff --git a/vendor/github.com/spf13/cobra/doc/BUILD b/vendor/github.com/spf13/cobra/doc/BUILD index 1820193cc00..52fbc08c1ef 100644 --- a/vendor/github.com/spf13/cobra/doc/BUILD +++ b/vendor/github.com/spf13/cobra/doc/BUILD @@ -5,7 +5,9 @@ go_library( srcs = [ "man_docs.go", "md_docs.go", + "rest_docs.go", "util.go", + "yaml_docs.go", ], importpath = "github.com/spf13/cobra/doc", visibility = ["//visibility:public"], @@ -13,6 +15,7 @@ go_library( "//vendor/github.com/cpuguy83/go-md2man/md2man:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/gopkg.in/yaml.v2:go_default_library", ], ) diff --git a/vendor/github.com/spf13/cobra/doc/man_docs.go b/vendor/github.com/spf13/cobra/doc/man_docs.go index b202029d1e0..ce92332dd17 100644 --- a/vendor/github.com/spf13/cobra/doc/man_docs.go +++ b/vendor/github.com/spf13/cobra/doc/man_docs.go @@ -23,21 +23,21 @@ import ( "strings" "time" - mangen "github.com/cpuguy83/go-md2man/md2man" + "github.com/cpuguy83/go-md2man/md2man" "github.com/spf13/cobra" "github.com/spf13/pflag" ) // GenManTree will generate a man page for this command and all descendants // in the directory given. The header may be nil. This function may not work -// correctly if your command names have - in them. If you have `cmd` with two -// subcmds, `sub` and `sub-third`. And `sub` has a subcommand called `third` +// correctly if your command names have `-` in them. If you have `cmd` with two +// subcmds, `sub` and `sub-third`, and `sub` has a subcommand called `third` // it is undefined which help output will be in the file `cmd-sub-third.1`. func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error { return GenManTreeFromOpts(cmd, GenManTreeOptions{ Header: header, Path: dir, - CommandSeparator: "_", + CommandSeparator: "-", }) } @@ -49,7 +49,7 @@ func GenManTreeFromOpts(cmd *cobra.Command, opts GenManTreeOptions) error { header = &GenManHeader{} } for _, c := range cmd.Commands() { - if !c.IsAvailableCommand() || c.IsHelpCommand() { + if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { continue } if err := GenManTreeFromOpts(c, opts); err != nil { @@ -66,7 +66,7 @@ func GenManTreeFromOpts(cmd *cobra.Command, opts GenManTreeOptions) error { separator = opts.CommandSeparator } basename := strings.Replace(cmd.CommandPath(), " ", separator, -1) - filename := filepath.Join(opts.Path, basename + "." + section) + filename := filepath.Join(opts.Path, basename+"."+section) f, err := os.Create(filename) if err != nil { return err @@ -77,6 +77,8 @@ func GenManTreeFromOpts(cmd *cobra.Command, opts GenManTreeOptions) error { return GenMan(cmd, &headerCopy, f) } +// GenManTreeOptions is the options for generating the man pages. +// Used only in GenManTreeFromOpts. type GenManTreeOptions struct { Header *GenManHeader Path string @@ -105,7 +107,7 @@ func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error { fillHeader(header, cmd.CommandPath()) b := genMan(cmd, header) - _, err := w.Write(mangen.Render(b)) + _, err := w.Write(md2man.Render(b)) return err } @@ -126,25 +128,25 @@ func fillHeader(header *GenManHeader, name string) { } } -func manPreamble(out io.Writer, header *GenManHeader, cmd *cobra.Command, dashedName string) { +func manPreamble(buf *bytes.Buffer, header *GenManHeader, cmd *cobra.Command, dashedName string) { description := cmd.Long if len(description) == 0 { description = cmd.Short } - fmt.Fprintf(out, `%% %s(%s)%s + buf.WriteString(fmt.Sprintf(`%% %s(%s)%s %% %s %% %s # NAME -`, header.Title, header.Section, header.date, header.Source, header.Manual) - fmt.Fprintf(out, "%s \\- %s\n\n", dashedName, cmd.Short) - fmt.Fprintf(out, "# SYNOPSIS\n") - fmt.Fprintf(out, "**%s**\n\n", cmd.UseLine()) - fmt.Fprintf(out, "# DESCRIPTION\n") - fmt.Fprintf(out, "%s\n\n", description) +`, header.Title, header.Section, header.date, header.Source, header.Manual)) + buf.WriteString(fmt.Sprintf("%s \\- %s\n\n", dashedName, cmd.Short)) + buf.WriteString("# SYNOPSIS\n") + buf.WriteString(fmt.Sprintf("**%s**\n\n", cmd.UseLine())) + buf.WriteString("# DESCRIPTION\n") + buf.WriteString(description + "\n\n") } -func manPrintFlags(out io.Writer, flags *pflag.FlagSet) { +func manPrintFlags(buf *bytes.Buffer, flags *pflag.FlagSet) { flags.VisitAll(func(flag *pflag.Flag) { if len(flag.Deprecated) > 0 || flag.Hidden { return @@ -156,38 +158,41 @@ func manPrintFlags(out io.Writer, flags *pflag.FlagSet) { format = fmt.Sprintf("**--%s**", flag.Name) } if len(flag.NoOptDefVal) > 0 { - format = format + "[" + format += "[" } if flag.Value.Type() == "string" { // put quotes on the value - format = format + "=%q" + format += "=%q" } else { - format = format + "=%s" + format += "=%s" } if len(flag.NoOptDefVal) > 0 { - format = format + "]" + format += "]" } - format = format + "\n\t%s\n\n" - fmt.Fprintf(out, format, flag.DefValue, flag.Usage) + format += "\n\t%s\n\n" + buf.WriteString(fmt.Sprintf(format, flag.DefValue, flag.Usage)) }) } -func manPrintOptions(out io.Writer, command *cobra.Command) { +func manPrintOptions(buf *bytes.Buffer, command *cobra.Command) { flags := command.NonInheritedFlags() if flags.HasFlags() { - fmt.Fprintf(out, "# OPTIONS\n") - manPrintFlags(out, flags) - fmt.Fprintf(out, "\n") + buf.WriteString("# OPTIONS\n") + manPrintFlags(buf, flags) + buf.WriteString("\n") } flags = command.InheritedFlags() if flags.HasFlags() { - fmt.Fprintf(out, "# OPTIONS INHERITED FROM PARENT COMMANDS\n") - manPrintFlags(out, flags) - fmt.Fprintf(out, "\n") + buf.WriteString("# OPTIONS INHERITED FROM PARENT COMMANDS\n") + manPrintFlags(buf, flags) + buf.WriteString("\n") } } func genMan(cmd *cobra.Command, header *GenManHeader) []byte { + cmd.InitDefaultHelpCmd() + cmd.InitDefaultHelpFlag() + // something like `rootcmd-subcmd1-subcmd2` dashCommandName := strings.Replace(cmd.CommandPath(), " ", "-", -1) @@ -196,11 +201,11 @@ func genMan(cmd *cobra.Command, header *GenManHeader) []byte { manPreamble(buf, header, cmd, dashCommandName) manPrintOptions(buf, cmd) if len(cmd.Example) > 0 { - fmt.Fprintf(buf, "# EXAMPLE\n") - fmt.Fprintf(buf, "```\n%s\n```\n", cmd.Example) + buf.WriteString("# EXAMPLE\n") + buf.WriteString(fmt.Sprintf("```\n%s\n```\n", cmd.Example)) } if hasSeeAlso(cmd) { - fmt.Fprintf(buf, "# SEE ALSO\n") + buf.WriteString("# SEE ALSO\n") seealsos := make([]string, 0) if cmd.HasParent() { parentPath := cmd.Parent().CommandPath() @@ -216,16 +221,16 @@ func genMan(cmd *cobra.Command, header *GenManHeader) []byte { children := cmd.Commands() sort.Sort(byName(children)) for _, c := range children { - if !c.IsAvailableCommand() || c.IsHelpCommand() { + if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { continue } seealso := fmt.Sprintf("**%s-%s(%s)**", dashCommandName, c.Name(), header.Section) seealsos = append(seealsos, seealso) } - fmt.Fprintf(buf, "%s\n", strings.Join(seealsos, ", ")) + buf.WriteString(strings.Join(seealsos, ", ") + "\n") } if !cmd.DisableAutoGenTag { - fmt.Fprintf(buf, "# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006")) + buf.WriteString(fmt.Sprintf("# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006"))) } return buf.Bytes() } diff --git a/vendor/github.com/spf13/cobra/doc/man_docs.md b/vendor/github.com/spf13/cobra/doc/man_docs.md index 5fe957a3558..3709160f34f 100644 --- a/vendor/github.com/spf13/cobra/doc/man_docs.md +++ b/vendor/github.com/spf13/cobra/doc/man_docs.md @@ -6,6 +6,8 @@ Generating man pages from a cobra command is incredibly easy. An example is as f package main import ( + "log" + "github.com/spf13/cobra" "github.com/spf13/cobra/doc" ) @@ -15,12 +17,15 @@ func main() { Use: "test", Short: "my test program", } - header := &cobra.GenManHeader{ + header := &doc.GenManHeader{ Title: "MINE", Section: "3", } - doc.GenManTree(cmd, header, "/tmp") + err := doc.GenManTree(cmd, header, "/tmp") + if err != nil { + log.Fatal(err) + } } ``` -That will get you a man page `/tmp/test.1` +That will get you a man page `/tmp/test.3` diff --git a/vendor/github.com/spf13/cobra/doc/md_docs.go b/vendor/github.com/spf13/cobra/doc/md_docs.go index fa136318049..68cf5bf6487 100644 --- a/vendor/github.com/spf13/cobra/doc/md_docs.go +++ b/vendor/github.com/spf13/cobra/doc/md_docs.go @@ -14,6 +14,7 @@ package doc import ( + "bytes" "fmt" "io" "os" @@ -25,38 +26,36 @@ import ( "github.com/spf13/cobra" ) -func printOptions(w io.Writer, cmd *cobra.Command, name string) error { +func printOptions(buf *bytes.Buffer, cmd *cobra.Command, name string) error { flags := cmd.NonInheritedFlags() - flags.SetOutput(w) + flags.SetOutput(buf) if flags.HasFlags() { - if _, err := fmt.Fprintf(w, "### Options\n\n```\n"); err != nil { - return err - } + buf.WriteString("### Options\n\n```\n") flags.PrintDefaults() - if _, err := fmt.Fprintf(w, "```\n\n"); err != nil { - return err - } + buf.WriteString("```\n\n") } parentFlags := cmd.InheritedFlags() - parentFlags.SetOutput(w) + parentFlags.SetOutput(buf) if parentFlags.HasFlags() { - if _, err := fmt.Fprintf(w, "### Options inherited from parent commands\n\n```\n"); err != nil { - return err - } + buf.WriteString("### Options inherited from parent commands\n\n```\n") parentFlags.PrintDefaults() - if _, err := fmt.Fprintf(w, "```\n\n"); err != nil { - return err - } + buf.WriteString("```\n\n") } return nil } +// GenMarkdown creates markdown output. func GenMarkdown(cmd *cobra.Command, w io.Writer) error { return GenMarkdownCustom(cmd, w, func(s string) string { return s }) } +// GenMarkdownCustom creates custom markdown output. func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error { + cmd.InitDefaultHelpCmd() + cmd.InitDefaultHelpFlag() + + buf := new(bytes.Buffer) name := cmd.CommandPath() short := cmd.Short @@ -65,49 +64,31 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) long = short } - if _, err := fmt.Fprintf(w, "## %s\n\n", name); err != nil { - return err - } - if _, err := fmt.Fprintf(w, "%s\n\n", short); err != nil { - return err - } - if _, err := fmt.Fprintf(w, "### Synopsis\n\n"); err != nil { - return err - } - if _, err := fmt.Fprintf(w, "\n%s\n\n", long); err != nil { - return err - } + buf.WriteString("## " + name + "\n\n") + buf.WriteString(short + "\n\n") + buf.WriteString("### Synopsis\n\n") + buf.WriteString("\n" + long + "\n\n") if cmd.Runnable() { - if _, err := fmt.Fprintf(w, "```\n%s\n```\n\n", cmd.UseLine()); err != nil { - return err - } + buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine())) } if len(cmd.Example) > 0 { - if _, err := fmt.Fprintf(w, "### Examples\n\n"); err != nil { - return err - } - if _, err := fmt.Fprintf(w, "```\n%s\n```\n\n", cmd.Example); err != nil { - return err - } + buf.WriteString("### Examples\n\n") + buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.Example)) } - if err := printOptions(w, cmd, name); err != nil { + if err := printOptions(buf, cmd, name); err != nil { return err } if hasSeeAlso(cmd) { - if _, err := fmt.Fprintf(w, "### SEE ALSO\n"); err != nil { - return err - } + buf.WriteString("### SEE ALSO\n") if cmd.HasParent() { parent := cmd.Parent() pname := parent.CommandPath() link := pname + ".md" link = strings.Replace(link, " ", "_", -1) - if _, err := fmt.Fprintf(w, "* [%s](%s)\t - %s\n", pname, linkHandler(link), parent.Short); err != nil { - return err - } + buf.WriteString(fmt.Sprintf("* [%s](%s)\t - %s\n", pname, linkHandler(link), parent.Short)) cmd.VisitParents(func(c *cobra.Command) { if c.DisableAutoGenTag { cmd.DisableAutoGenTag = c.DisableAutoGenTag @@ -119,37 +100,40 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) sort.Sort(byName(children)) for _, child := range children { - if !child.IsAvailableCommand() || child.IsHelpCommand() { + if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { continue } cname := name + " " + child.Name() link := cname + ".md" link = strings.Replace(link, " ", "_", -1) - if _, err := fmt.Fprintf(w, "* [%s](%s)\t - %s\n", cname, linkHandler(link), child.Short); err != nil { - return err - } - } - if _, err := fmt.Fprintf(w, "\n"); err != nil { - return err + buf.WriteString(fmt.Sprintf("* [%s](%s)\t - %s\n", cname, linkHandler(link), child.Short)) } + buf.WriteString("\n") } if !cmd.DisableAutoGenTag { - if _, err := fmt.Fprintf(w, "###### Auto generated by spf13/cobra on %s\n", time.Now().Format("2-Jan-2006")); err != nil { - return err - } + buf.WriteString("###### Auto generated by spf13/cobra on " + time.Now().Format("2-Jan-2006") + "\n") } - return nil + _, err := buf.WriteTo(w) + return err } +// GenMarkdownTree will generate a markdown page for this command and all +// descendants in the directory given. The header may be nil. +// This function may not work correctly if your command names have `-` in them. +// If you have `cmd` with two subcmds, `sub` and `sub-third`, +// and `sub` has a subcommand called `third`, it is undefined which +// help output will be in the file `cmd-sub-third.1`. func GenMarkdownTree(cmd *cobra.Command, dir string) error { identity := func(s string) string { return s } emptyStr := func(s string) string { return "" } return GenMarkdownTreeCustom(cmd, dir, emptyStr, identity) } +// GenMarkdownTreeCustom is the the same as GenMarkdownTree, but +// with custom filePrepender and linkHandler. func GenMarkdownTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error { for _, c := range cmd.Commands() { - if !c.IsAvailableCommand() || c.IsHelpCommand() { + if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { continue } if err := GenMarkdownTreeCustom(c, dir, filePrepender, linkHandler); err != nil { diff --git a/vendor/github.com/spf13/cobra/doc/md_docs.md b/vendor/github.com/spf13/cobra/doc/md_docs.md index 0c3b96e2718..56ce9fe819e 100644 --- a/vendor/github.com/spf13/cobra/doc/md_docs.md +++ b/vendor/github.com/spf13/cobra/doc/md_docs.md @@ -6,6 +6,8 @@ Generating man pages from a cobra command is incredibly easy. An example is as f package main import ( + "log" + "github.com/spf13/cobra" "github.com/spf13/cobra/doc" ) @@ -15,7 +17,10 @@ func main() { Use: "test", Short: "my test program", } - doc.GenMarkdownTree(cmd, "/tmp") + err := doc.GenMarkdownTree(cmd, "/tmp") + if err != nil { + log.Fatal(err) + } } ``` @@ -29,18 +34,22 @@ This program can actually generate docs for the kubectl command in the kubernete package main import ( + "log" "io/ioutil" "os" - kubectlcmd "k8s.io/kubernetes/pkg/kubectl/cmd" + "k8s.io/kubernetes/pkg/kubectl/cmd" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra/doc" ) func main() { - cmd := kubectlcmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) - doc.GenMarkdownTree(cmd, "./") + kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) + err := doc.GenMarkdownTree(kubectl, "./") + if err != nil { + log.Fatal(err) + } } ``` @@ -52,7 +61,10 @@ You may wish to have more control over the output, or only generate for a single ```go out := new(bytes.Buffer) - doc.GenMarkdown(cmd, out) + err := doc.GenMarkdown(cmd, out) + if err != nil { + log.Fatal(err) + } ``` This will write the markdown doc for ONLY "cmd" into the out, buffer. @@ -101,4 +113,3 @@ linkHandler := func(name string) string { return "/commands/" + strings.ToLower(base) + "/" } ``` - diff --git a/vendor/github.com/spf13/cobra/doc/rest_docs.go b/vendor/github.com/spf13/cobra/doc/rest_docs.go new file mode 100644 index 00000000000..4913e3ee2ea --- /dev/null +++ b/vendor/github.com/spf13/cobra/doc/rest_docs.go @@ -0,0 +1,185 @@ +//Copyright 2015 Red Hat Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package doc + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strings" + "time" + + "github.com/spf13/cobra" +) + +func printOptionsReST(buf *bytes.Buffer, cmd *cobra.Command, name string) error { + flags := cmd.NonInheritedFlags() + flags.SetOutput(buf) + if flags.HasFlags() { + buf.WriteString("Options\n") + buf.WriteString("~~~~~~~\n\n::\n\n") + flags.PrintDefaults() + buf.WriteString("\n") + } + + parentFlags := cmd.InheritedFlags() + parentFlags.SetOutput(buf) + if parentFlags.HasFlags() { + buf.WriteString("Options inherited from parent commands\n") + buf.WriteString("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n::\n\n") + parentFlags.PrintDefaults() + buf.WriteString("\n") + } + return nil +} + +// linkHandler for default ReST hyperlink markup +func defaultLinkHandler(name, ref string) string { + return fmt.Sprintf("`%s <%s.rst>`_", name, ref) +} + +// GenReST creates reStructured Text output. +func GenReST(cmd *cobra.Command, w io.Writer) error { + return GenReSTCustom(cmd, w, defaultLinkHandler) +} + +// GenReSTCustom creates custom reStructured Text output. +func GenReSTCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string, string) string) error { + cmd.InitDefaultHelpCmd() + cmd.InitDefaultHelpFlag() + + buf := new(bytes.Buffer) + name := cmd.CommandPath() + + short := cmd.Short + long := cmd.Long + if len(long) == 0 { + long = short + } + ref := strings.Replace(name, " ", "_", -1) + + buf.WriteString(".. _" + ref + ":\n\n") + buf.WriteString(name + "\n") + buf.WriteString(strings.Repeat("-", len(name)) + "\n\n") + buf.WriteString(short + "\n\n") + buf.WriteString("Synopsis\n") + buf.WriteString("~~~~~~~~\n\n") + buf.WriteString("\n" + long + "\n\n") + + if cmd.Runnable() { + buf.WriteString(fmt.Sprintf("::\n\n %s\n\n", cmd.UseLine())) + } + + if len(cmd.Example) > 0 { + buf.WriteString("Examples\n") + buf.WriteString("~~~~~~~~\n\n") + buf.WriteString(fmt.Sprintf("::\n\n%s\n\n", indentString(cmd.Example, " "))) + } + + if err := printOptionsReST(buf, cmd, name); err != nil { + return err + } + if hasSeeAlso(cmd) { + buf.WriteString("SEE ALSO\n") + buf.WriteString("~~~~~~~~\n\n") + if cmd.HasParent() { + parent := cmd.Parent() + pname := parent.CommandPath() + ref = strings.Replace(pname, " ", "_", -1) + buf.WriteString(fmt.Sprintf("* %s \t - %s\n", linkHandler(pname, ref), parent.Short)) + cmd.VisitParents(func(c *cobra.Command) { + if c.DisableAutoGenTag { + cmd.DisableAutoGenTag = c.DisableAutoGenTag + } + }) + } + + children := cmd.Commands() + sort.Sort(byName(children)) + + for _, child := range children { + if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { + continue + } + cname := name + " " + child.Name() + ref = strings.Replace(cname, " ", "_", -1) + buf.WriteString(fmt.Sprintf("* %s \t - %s\n", linkHandler(cname, ref), child.Short)) + } + buf.WriteString("\n") + } + if !cmd.DisableAutoGenTag { + buf.WriteString("*Auto generated by spf13/cobra on " + time.Now().Format("2-Jan-2006") + "*\n") + } + _, err := buf.WriteTo(w) + return err +} + +// GenReSTTree will generate a ReST page for this command and all +// descendants in the directory given. +// This function may not work correctly if your command names have `-` in them. +// If you have `cmd` with two subcmds, `sub` and `sub-third`, +// and `sub` has a subcommand called `third`, it is undefined which +// help output will be in the file `cmd-sub-third.1`. +func GenReSTTree(cmd *cobra.Command, dir string) error { + emptyStr := func(s string) string { return "" } + return GenReSTTreeCustom(cmd, dir, emptyStr, defaultLinkHandler) +} + +// GenReSTTreeCustom is the the same as GenReSTTree, but +// with custom filePrepender and linkHandler. +func GenReSTTreeCustom(cmd *cobra.Command, dir string, filePrepender func(string) string, linkHandler func(string, string) string) error { + for _, c := range cmd.Commands() { + if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { + continue + } + if err := GenReSTTreeCustom(c, dir, filePrepender, linkHandler); err != nil { + return err + } + } + + basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".rst" + filename := filepath.Join(dir, basename) + f, err := os.Create(filename) + if err != nil { + return err + } + defer f.Close() + + if _, err := io.WriteString(f, filePrepender(filename)); err != nil { + return err + } + if err := GenReSTCustom(cmd, f, linkHandler); err != nil { + return err + } + return nil +} + +// adapted from: https://github.com/kr/text/blob/main/indent.go +func indentString(s, p string) string { + var res []byte + b := []byte(s) + prefix := []byte(p) + bol := true + for _, c := range b { + if bol && c != '\n' { + res = append(res, prefix...) + } + res = append(res, c) + bol = c == '\n' + } + return string(res) +} diff --git a/vendor/github.com/spf13/cobra/doc/rest_docs.md b/vendor/github.com/spf13/cobra/doc/rest_docs.md new file mode 100644 index 00000000000..6098430eff6 --- /dev/null +++ b/vendor/github.com/spf13/cobra/doc/rest_docs.md @@ -0,0 +1,114 @@ +# Generating ReStructured Text Docs For Your Own cobra.Command + +Generating ReST pages from a cobra command is incredibly easy. An example is as follows: + +```go +package main + +import ( + "log" + + "github.com/spf13/cobra" + "github.com/spf13/cobra/doc" +) + +func main() { + cmd := &cobra.Command{ + Use: "test", + Short: "my test program", + } + err := doc.GenReSTTree(cmd, "/tmp") + if err != nil { + log.Fatal(err) + } +} +``` + +That will get you a ReST document `/tmp/test.rst` + +## Generate ReST docs for the entire command tree + +This program can actually generate docs for the kubectl command in the kubernetes project + +```go +package main + +import ( + "log" + "io/ioutil" + "os" + + "k8s.io/kubernetes/pkg/kubectl/cmd" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + + "github.com/spf13/cobra/doc" +) + +func main() { + kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) + err := doc.GenReSTTree(kubectl, "./") + if err != nil { + log.Fatal(err) + } +} +``` + +This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./") + +## Generate ReST docs for a single command + +You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenReST` instead of `GenReSTTree` + +```go + out := new(bytes.Buffer) + err := doc.GenReST(cmd, out) + if err != nil { + log.Fatal(err) + } +``` + +This will write the ReST doc for ONLY "cmd" into the out, buffer. + +## Customize the output + +Both `GenReST` and `GenReSTTree` have alternate versions with callbacks to get some control of the output: + +```go +func GenReSTTreeCustom(cmd *Command, dir string, filePrepender func(string) string, linkHandler func(string, string) string) error { + //... +} +``` + +```go +func GenReSTCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string, string) string) error { + //... +} +``` + +The `filePrepender` will prepend the return value given the full filepath to the rendered ReST file. A common use case is to add front matter to use the generated documentation with [Hugo](http://gohugo.io/): + +```go +const fmTemplate = `--- +date: %s +title: "%s" +slug: %s +url: %s +--- +` +filePrepender := func(filename string) string { + now := time.Now().Format(time.RFC3339) + name := filepath.Base(filename) + base := strings.TrimSuffix(name, path.Ext(name)) + url := "/commands/" + strings.ToLower(base) + "/" + return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url) +} +``` + +The `linkHandler` can be used to customize the rendered links to the commands, given a command name and reference. This is useful while converting rst to html or while generating documentation with tools like Sphinx where `:ref:` is used: + +```go +// Sphinx cross-referencing format +linkHandler := func(name, ref string) string { + return fmt.Sprintf(":ref:`%s <%s>`", name, ref) +} +``` diff --git a/vendor/github.com/spf13/cobra/doc/util.go b/vendor/github.com/spf13/cobra/doc/util.go index a1c6b89ba6c..8d3dbecec82 100644 --- a/vendor/github.com/spf13/cobra/doc/util.go +++ b/vendor/github.com/spf13/cobra/doc/util.go @@ -13,7 +13,11 @@ package doc -import "github.com/spf13/cobra" +import ( + "strings" + + "github.com/spf13/cobra" +) // Test to see if we have a reason to print See Also information in docs // Basically this is a test for a parent commend or a subcommand which is @@ -23,7 +27,7 @@ func hasSeeAlso(cmd *cobra.Command) bool { return true } for _, c := range cmd.Commands() { - if !c.IsAvailableCommand() || c.IsHelpCommand() { + if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { continue } return true @@ -31,6 +35,15 @@ func hasSeeAlso(cmd *cobra.Command) bool { return false } +// Temporary workaround for yaml lib generating incorrect yaml with long strings +// that do not contain \n. +func forceMultiLine(s string) string { + if len(s) > 60 && !strings.Contains(s, "\n") { + s = s + "\n" + } + return s +} + type byName []*cobra.Command func (s byName) Len() int { return len(s) } diff --git a/vendor/github.com/spf13/cobra/doc/yaml_docs.go b/vendor/github.com/spf13/cobra/doc/yaml_docs.go new file mode 100644 index 00000000000..ea00af07e81 --- /dev/null +++ b/vendor/github.com/spf13/cobra/doc/yaml_docs.go @@ -0,0 +1,169 @@ +// Copyright 2016 French Ben. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package doc + +import ( + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "gopkg.in/yaml.v2" +) + +type cmdOption struct { + Name string + Shorthand string `yaml:",omitempty"` + DefaultValue string `yaml:"default_value,omitempty"` + Usage string `yaml:",omitempty"` +} + +type cmdDoc struct { + Name string + Synopsis string `yaml:",omitempty"` + Description string `yaml:",omitempty"` + Options []cmdOption `yaml:",omitempty"` + InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"` + Example string `yaml:",omitempty"` + SeeAlso []string `yaml:"see_also,omitempty"` +} + +// GenYamlTree creates yaml structured ref files for this command and all descendants +// in the directory given. This function may not work +// correctly if your command names have `-` in them. If you have `cmd` with two +// subcmds, `sub` and `sub-third`, and `sub` has a subcommand called `third` +// it is undefined which help output will be in the file `cmd-sub-third.1`. +func GenYamlTree(cmd *cobra.Command, dir string) error { + identity := func(s string) string { return s } + emptyStr := func(s string) string { return "" } + return GenYamlTreeCustom(cmd, dir, emptyStr, identity) +} + +// GenYamlTreeCustom creates yaml structured ref files. +func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error { + for _, c := range cmd.Commands() { + if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { + continue + } + if err := GenYamlTreeCustom(c, dir, filePrepender, linkHandler); err != nil { + return err + } + } + + basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".yaml" + filename := filepath.Join(dir, basename) + f, err := os.Create(filename) + if err != nil { + return err + } + defer f.Close() + + if _, err := io.WriteString(f, filePrepender(filename)); err != nil { + return err + } + if err := GenYamlCustom(cmd, f, linkHandler); err != nil { + return err + } + return nil +} + +// GenYaml creates yaml output. +func GenYaml(cmd *cobra.Command, w io.Writer) error { + return GenYamlCustom(cmd, w, func(s string) string { return s }) +} + +// GenYamlCustom creates custom yaml output. +func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error { + cmd.InitDefaultHelpCmd() + cmd.InitDefaultHelpFlag() + + yamlDoc := cmdDoc{} + yamlDoc.Name = cmd.CommandPath() + + yamlDoc.Synopsis = forceMultiLine(cmd.Short) + yamlDoc.Description = forceMultiLine(cmd.Long) + + if len(cmd.Example) > 0 { + yamlDoc.Example = cmd.Example + } + + flags := cmd.NonInheritedFlags() + if flags.HasFlags() { + yamlDoc.Options = genFlagResult(flags) + } + flags = cmd.InheritedFlags() + if flags.HasFlags() { + yamlDoc.InheritedOptions = genFlagResult(flags) + } + + if hasSeeAlso(cmd) { + result := []string{} + if cmd.HasParent() { + parent := cmd.Parent() + result = append(result, parent.CommandPath()+" - "+parent.Short) + } + children := cmd.Commands() + sort.Sort(byName(children)) + for _, child := range children { + if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { + continue + } + result = append(result, child.Name()+" - "+child.Short) + } + yamlDoc.SeeAlso = result + } + + final, err := yaml.Marshal(&yamlDoc) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + if _, err := w.Write(final); err != nil { + return err + } + return nil +} + +func genFlagResult(flags *pflag.FlagSet) []cmdOption { + var result []cmdOption + + flags.VisitAll(func(flag *pflag.Flag) { + // Todo, when we mark a shorthand is deprecated, but specify an empty message. + // The flag.ShorthandDeprecated is empty as the shorthand is deprecated. + // Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok. + if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 { + opt := cmdOption{ + flag.Name, + flag.Shorthand, + flag.DefValue, + forceMultiLine(flag.Usage), + } + result = append(result, opt) + } else { + opt := cmdOption{ + Name: flag.Name, + DefaultValue: forceMultiLine(flag.DefValue), + Usage: forceMultiLine(flag.Usage), + } + result = append(result, opt) + } + }) + + return result +} diff --git a/vendor/github.com/spf13/cobra/doc/yaml_docs.md b/vendor/github.com/spf13/cobra/doc/yaml_docs.md new file mode 100644 index 00000000000..1a9b7c6a3c9 --- /dev/null +++ b/vendor/github.com/spf13/cobra/doc/yaml_docs.md @@ -0,0 +1,112 @@ +# Generating Yaml Docs For Your Own cobra.Command + +Generating yaml files from a cobra command is incredibly easy. An example is as follows: + +```go +package main + +import ( + "log" + + "github.com/spf13/cobra" + "github.com/spf13/cobra/doc" +) + +func main() { + cmd := &cobra.Command{ + Use: "test", + Short: "my test program", + } + err := doc.GenYamlTree(cmd, "/tmp") + if err != nil { + log.Fatal(err) + } +} +``` + +That will get you a Yaml document `/tmp/test.yaml` + +## Generate yaml docs for the entire command tree + +This program can actually generate docs for the kubectl command in the kubernetes project + +```go +package main + +import ( + "io/ioutil" + "log" + "os" + + "k8s.io/kubernetes/pkg/kubectl/cmd" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + + "github.com/spf13/cobra/doc" +) + +func main() { + kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) + err := doc.GenYamlTree(kubectl, "./") + if err != nil { + log.Fatal(err) + } +} +``` + +This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./") + +## Generate yaml docs for a single command + +You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenYaml` instead of `GenYamlTree` + +```go + out := new(bytes.Buffer) + doc.GenYaml(cmd, out) +``` + +This will write the yaml doc for ONLY "cmd" into the out, buffer. + +## Customize the output + +Both `GenYaml` and `GenYamlTree` have alternate versions with callbacks to get some control of the output: + +```go +func GenYamlTreeCustom(cmd *Command, dir string, filePrepender, linkHandler func(string) string) error { + //... +} +``` + +```go +func GenYamlCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string) string) error { + //... +} +``` + +The `filePrepender` will prepend the return value given the full filepath to the rendered Yaml file. A common use case is to add front matter to use the generated documentation with [Hugo](http://gohugo.io/): + +```go +const fmTemplate = `--- +date: %s +title: "%s" +slug: %s +url: %s +--- +` + +filePrepender := func(filename string) string { + now := time.Now().Format(time.RFC3339) + name := filepath.Base(filename) + base := strings.TrimSuffix(name, path.Ext(name)) + url := "/commands/" + strings.ToLower(base) + "/" + return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url) +} +``` + +The `linkHandler` can be used to customize the rendered internal links to the commands, given a filename: + +```go +linkHandler := func(name string) string { + base := strings.TrimSuffix(name, path.Ext(name)) + return "/commands/" + strings.ToLower(base) + "/" +} +``` diff --git a/vendor/github.com/spf13/cobra/zsh_completions.go b/vendor/github.com/spf13/cobra/zsh_completions.go new file mode 100644 index 00000000000..889c22e273c --- /dev/null +++ b/vendor/github.com/spf13/cobra/zsh_completions.go @@ -0,0 +1,126 @@ +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" + "strings" +) + +// GenZshCompletionFile generates zsh completion file. +func (c *Command) GenZshCompletionFile(filename string) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() + + return c.GenZshCompletion(outFile) +} + +// GenZshCompletion generates a zsh completion file and writes to the passed writer. +func (c *Command) GenZshCompletion(w io.Writer) error { + buf := new(bytes.Buffer) + + writeHeader(buf, c) + maxDepth := maxDepth(c) + writeLevelMapping(buf, maxDepth) + writeLevelCases(buf, maxDepth, c) + + _, err := buf.WriteTo(w) + return err +} + +func writeHeader(w io.Writer, cmd *Command) { + fmt.Fprintf(w, "#compdef %s\n\n", cmd.Name()) +} + +func maxDepth(c *Command) int { + if len(c.Commands()) == 0 { + return 0 + } + maxDepthSub := 0 + for _, s := range c.Commands() { + subDepth := maxDepth(s) + if subDepth > maxDepthSub { + maxDepthSub = subDepth + } + } + return 1 + maxDepthSub +} + +func writeLevelMapping(w io.Writer, numLevels int) { + fmt.Fprintln(w, `_arguments \`) + for i := 1; i <= numLevels; i++ { + fmt.Fprintf(w, ` '%d: :->level%d' \`, i, i) + fmt.Fprintln(w) + } + fmt.Fprintf(w, ` '%d: :%s'`, numLevels+1, "_files") + fmt.Fprintln(w) +} + +func writeLevelCases(w io.Writer, maxDepth int, root *Command) { + fmt.Fprintln(w, "case $state in") + defer fmt.Fprintln(w, "esac") + + for i := 1; i <= maxDepth; i++ { + fmt.Fprintf(w, " level%d)\n", i) + writeLevel(w, root, i) + fmt.Fprintln(w, " ;;") + } + fmt.Fprintln(w, " *)") + fmt.Fprintln(w, " _arguments '*: :_files'") + fmt.Fprintln(w, " ;;") +} + +func writeLevel(w io.Writer, root *Command, i int) { + fmt.Fprintf(w, " case $words[%d] in\n", i) + defer fmt.Fprintln(w, " esac") + + commands := filterByLevel(root, i) + byParent := groupByParent(commands) + + for p, c := range byParent { + names := names(c) + fmt.Fprintf(w, " %s)\n", p) + fmt.Fprintf(w, " _arguments '%d: :(%s)'\n", i, strings.Join(names, " ")) + fmt.Fprintln(w, " ;;") + } + fmt.Fprintln(w, " *)") + fmt.Fprintln(w, " _arguments '*: :_files'") + fmt.Fprintln(w, " ;;") + +} + +func filterByLevel(c *Command, l int) []*Command { + cs := make([]*Command, 0) + if l == 0 { + cs = append(cs, c) + return cs + } + for _, s := range c.Commands() { + cs = append(cs, filterByLevel(s, l-1)...) + } + return cs +} + +func groupByParent(commands []*Command) map[string][]*Command { + m := make(map[string][]*Command) + for _, c := range commands { + parent := c.Parent() + if parent == nil { + continue + } + m[parent.Name()] = append(m[parent.Name()], c) + } + return m +} + +func names(commands []*Command) []string { + ns := make([]string, len(commands)) + for i, c := range commands { + ns[i] = c.Name() + } + return ns +} From 6c54ec59ee7e6e1fa9f1dc311762ab98dc1b3d0a Mon Sep 17 00:00:00 2001 From: Di Xu Date: Mon, 20 Nov 2017 13:21:27 +0800 Subject: [PATCH 07/58] bump pflag --- Godeps/Godeps.json | 2 +- staging/src/k8s.io/api/Godeps/Godeps.json | 2 +- .../Godeps/Godeps.json | 2 +- .../k8s.io/apimachinery/Godeps/Godeps.json | 2 +- .../src/k8s.io/apiserver/Godeps/Godeps.json | 2 +- .../src/k8s.io/client-go/Godeps/Godeps.json | 2 +- .../k8s.io/code-generator/Godeps/Godeps.json | 2 +- .../k8s.io/kube-aggregator/Godeps/Godeps.json | 2 +- staging/src/k8s.io/metrics/Godeps/Godeps.json | 2 +- .../sample-apiserver/Godeps/Godeps.json | 2 +- .../sample-controller/Godeps/Godeps.json | 2 +- vendor/github.com/spf13/pflag/.travis.yml | 21 +- vendor/github.com/spf13/pflag/BUILD | 1 + vendor/github.com/spf13/pflag/README.md | 25 +- vendor/github.com/spf13/pflag/count.go | 16 +- vendor/github.com/spf13/pflag/flag.go | 286 ++++++++++++------ vendor/github.com/spf13/pflag/int16.go | 88 ++++++ 17 files changed, 332 insertions(+), 127 deletions(-) create mode 100644 vendor/github.com/spf13/pflag/int16.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 592545de505..b66024cfb79 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -2482,7 +2482,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + "Rev": "4c012f6dcd9546820e378d0bdda4d8fc772cdfea" }, { "ImportPath": "github.com/spf13/viper", diff --git a/staging/src/k8s.io/api/Godeps/Godeps.json b/staging/src/k8s.io/api/Godeps/Godeps.json index ffa35e2d980..488056bc433 100644 --- a/staging/src/k8s.io/api/Godeps/Godeps.json +++ b/staging/src/k8s.io/api/Godeps/Godeps.json @@ -68,7 +68,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + "Rev": "4c012f6dcd9546820e378d0bdda4d8fc772cdfea" }, { "ImportPath": "golang.org/x/net/http2", diff --git a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json index f792000d584..226a9e7fda5 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json @@ -332,7 +332,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + "Rev": "4c012f6dcd9546820e378d0bdda4d8fc772cdfea" }, { "ImportPath": "github.com/stretchr/testify/assert", diff --git a/staging/src/k8s.io/apimachinery/Godeps/Godeps.json b/staging/src/k8s.io/apimachinery/Godeps/Godeps.json index a264f944b4e..ae000e588e5 100644 --- a/staging/src/k8s.io/apimachinery/Godeps/Godeps.json +++ b/staging/src/k8s.io/apimachinery/Godeps/Godeps.json @@ -152,7 +152,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + "Rev": "4c012f6dcd9546820e378d0bdda4d8fc772cdfea" }, { "ImportPath": "github.com/stretchr/testify/assert", diff --git a/staging/src/k8s.io/apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiserver/Godeps/Godeps.json index 83c6b74dbaa..7cf45b73d5f 100644 --- a/staging/src/k8s.io/apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiserver/Godeps/Godeps.json @@ -552,7 +552,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + "Rev": "4c012f6dcd9546820e378d0bdda4d8fc772cdfea" }, { "ImportPath": "github.com/stretchr/testify/assert", diff --git a/staging/src/k8s.io/client-go/Godeps/Godeps.json b/staging/src/k8s.io/client-go/Godeps/Godeps.json index d9c1c4f0410..610ef120b88 100644 --- a/staging/src/k8s.io/client-go/Godeps/Godeps.json +++ b/staging/src/k8s.io/client-go/Godeps/Godeps.json @@ -256,7 +256,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + "Rev": "4c012f6dcd9546820e378d0bdda4d8fc772cdfea" }, { "ImportPath": "github.com/stretchr/testify/assert", diff --git a/staging/src/k8s.io/code-generator/Godeps/Godeps.json b/staging/src/k8s.io/code-generator/Godeps/Godeps.json index 239636cbe3d..fdf6be0eb3e 100644 --- a/staging/src/k8s.io/code-generator/Godeps/Godeps.json +++ b/staging/src/k8s.io/code-generator/Godeps/Godeps.json @@ -156,7 +156,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + "Rev": "4c012f6dcd9546820e378d0bdda4d8fc772cdfea" }, { "ImportPath": "golang.org/x/net/idna", diff --git a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json index 32d1debb00a..94035ad7338 100644 --- a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json +++ b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json @@ -312,7 +312,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + "Rev": "4c012f6dcd9546820e378d0bdda4d8fc772cdfea" }, { "ImportPath": "github.com/stretchr/testify/assert", diff --git a/staging/src/k8s.io/metrics/Godeps/Godeps.json b/staging/src/k8s.io/metrics/Godeps/Godeps.json index e964a638073..5d7e2f271e9 100644 --- a/staging/src/k8s.io/metrics/Godeps/Godeps.json +++ b/staging/src/k8s.io/metrics/Godeps/Godeps.json @@ -128,7 +128,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + "Rev": "4c012f6dcd9546820e378d0bdda4d8fc772cdfea" }, { "ImportPath": "golang.org/x/net/http2", diff --git a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json index a8c8d2a5cad..be93c86b50a 100644 --- a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json @@ -300,7 +300,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + "Rev": "4c012f6dcd9546820e378d0bdda4d8fc772cdfea" }, { "ImportPath": "github.com/ugorji/go/codec", diff --git a/staging/src/k8s.io/sample-controller/Godeps/Godeps.json b/staging/src/k8s.io/sample-controller/Godeps/Godeps.json index 5c0249ded73..3d061e4340e 100644 --- a/staging/src/k8s.io/sample-controller/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-controller/Godeps/Godeps.json @@ -152,7 +152,7 @@ }, { "ImportPath": "github.com/spf13/pflag", - "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + "Rev": "4c012f6dcd9546820e378d0bdda4d8fc772cdfea" }, { "ImportPath": "golang.org/x/crypto/ssh/terminal", diff --git a/vendor/github.com/spf13/pflag/.travis.yml b/vendor/github.com/spf13/pflag/.travis.yml index 707bdc39a7f..f8a63b308ba 100644 --- a/vendor/github.com/spf13/pflag/.travis.yml +++ b/vendor/github.com/spf13/pflag/.travis.yml @@ -3,18 +3,19 @@ sudo: false language: go go: - - 1.6.3 - - 1.7.3 - - tip + - 1.7.3 + - 1.8.1 + - tip matrix: - allow_failures: - - go: tip + allow_failures: + - go: tip + install: - - go get github.com/golang/lint/golint - - export PATH=$GOPATH/bin:$PATH - - go install ./... + - go get github.com/golang/lint/golint + - export PATH=$GOPATH/bin:$PATH + - go install ./... script: - - verify/all.sh -v - - go test ./... + - verify/all.sh -v + - go test ./... diff --git a/vendor/github.com/spf13/pflag/BUILD b/vendor/github.com/spf13/pflag/BUILD index e48a6b28889..cb68c486ee2 100644 --- a/vendor/github.com/spf13/pflag/BUILD +++ b/vendor/github.com/spf13/pflag/BUILD @@ -12,6 +12,7 @@ go_library( "float64.go", "golangflag.go", "int.go", + "int16.go", "int32.go", "int64.go", "int8.go", diff --git a/vendor/github.com/spf13/pflag/README.md b/vendor/github.com/spf13/pflag/README.md index eefb46dec83..b052414d129 100644 --- a/vendor/github.com/spf13/pflag/README.md +++ b/vendor/github.com/spf13/pflag/README.md @@ -246,6 +246,25 @@ It is possible to mark a flag as hidden, meaning it will still function as norma flags.MarkHidden("secretFlag") ``` +## Disable sorting of flags +`pflag` allows you to disable sorting of flags for help and usage message. + +**Example**: +```go +flags.BoolP("verbose", "v", false, "verbose output") +flags.String("coolflag", "yeaah", "it's really cool flag") +flags.Int("usefulflag", 777, "sometimes it's very useful") +flags.SortFlags = false +flags.PrintDefaults() +``` +**Output**: +``` + -v, --verbose verbose output + --coolflag string it's really cool flag (default "yeaah") + --usefulflag int sometimes it's very useful (default 777) +``` + + ## Supporting Go flags when using pflag In order to support flags defined using Go's `flag` package, they must be added to the `pflag` flagset. This is usually necessary to support flags defined by third-party dependencies (e.g. `golang/glog`). @@ -270,8 +289,8 @@ func main() { You can see the full reference documentation of the pflag package [at godoc.org][3], or through go's standard documentation system by running `godoc -http=:6060` and browsing to -[http://localhost:6060/pkg/github.com/ogier/pflag][2] after +[http://localhost:6060/pkg/github.com/spf13/pflag][2] after installation. -[2]: http://localhost:6060/pkg/github.com/ogier/pflag -[3]: http://godoc.org/github.com/ogier/pflag +[2]: http://localhost:6060/pkg/github.com/spf13/pflag +[3]: http://godoc.org/github.com/spf13/pflag diff --git a/vendor/github.com/spf13/pflag/count.go b/vendor/github.com/spf13/pflag/count.go index d22be41f29f..aa126e44d1c 100644 --- a/vendor/github.com/spf13/pflag/count.go +++ b/vendor/github.com/spf13/pflag/count.go @@ -11,13 +11,13 @@ func newCountValue(val int, p *int) *countValue { } func (i *countValue) Set(s string) error { - v, err := strconv.ParseInt(s, 0, 64) - // -1 means that no specific value was passed, so increment - if v == -1 { + // "+1" means that no specific value was passed, so increment + if s == "+1" { *i = countValue(*i + 1) - } else { - *i = countValue(v) + return nil } + v, err := strconv.ParseInt(s, 0, 0) + *i = countValue(v) return err } @@ -54,7 +54,7 @@ func (f *FlagSet) CountVar(p *int, name string, usage string) { // CountVarP is like CountVar only take a shorthand for the flag name. func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) { flag := f.VarPF(newCountValue(0, p), name, shorthand, usage) - flag.NoOptDefVal = "-1" + flag.NoOptDefVal = "+1" } // CountVar like CountVar only the flag is placed on the CommandLine instead of a given flag set @@ -83,7 +83,9 @@ func (f *FlagSet) CountP(name, shorthand string, usage string) *int { return p } -// Count like Count only the flag is placed on the CommandLine isntead of a given flag set +// Count defines a count flag with specified name, default value, and usage string. +// The return value is the address of an int variable that stores the value of the flag. +// A count flag will add 1 to its value evey time it is found on the command line func Count(name string, usage string) *int { return CommandLine.CountP(name, "", usage) } diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go index 746af6327e4..28538c0750b 100644 --- a/vendor/github.com/spf13/pflag/flag.go +++ b/vendor/github.com/spf13/pflag/flag.go @@ -16,9 +16,9 @@ pflag is a drop-in replacement of Go's native flag package. If you import pflag under the name "flag" then all code should continue to function with no changes. - import flag "github.com/ogier/pflag" + import flag "github.com/spf13/pflag" - There is one exception to this: if you directly instantiate the Flag struct +There is one exception to this: if you directly instantiate the Flag struct there is one more field "Shorthand" that you will need to set. Most code never instantiates this struct directly, and instead uses functions such as String(), BoolVar(), and Var(), and is therefore @@ -134,14 +134,21 @@ type FlagSet struct { // a custom error handler. Usage func() + // SortFlags is used to indicate, if user wants to have sorted flags in + // help/usage messages. + SortFlags bool + name string parsed bool actual map[NormalizedName]*Flag + orderedActual []*Flag + sortedActual []*Flag formal map[NormalizedName]*Flag + orderedFormal []*Flag + sortedFormal []*Flag shorthands map[byte]*Flag args []string // arguments after flags argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no -- - exitOnError bool // does the program exit if there's an error? errorHandling ErrorHandling output io.Writer // nil means stderr; use out() accessor interspersed bool // allow interspersed option/non-option args @@ -156,7 +163,7 @@ type Flag struct { Value Value // value as set DefValue string // default value (as text); for usage message Changed bool // If the user set the value (or if left to default) - NoOptDefVal string //default value (as text); if the flag is on the command line without any options + NoOptDefVal string // default value (as text); if the flag is on the command line without any options Deprecated string // If this flag is deprecated, this string is the new or now thing to use Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use @@ -194,11 +201,19 @@ func sortFlags(flags map[NormalizedName]*Flag) []*Flag { // "--getUrl" which may also be translated to "geturl" and everything will work. func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) { f.normalizeNameFunc = n - for k, v := range f.formal { - delete(f.formal, k) - nname := f.normalizeFlagName(string(k)) - f.formal[nname] = v - v.Name = string(nname) + f.sortedFormal = f.sortedFormal[:0] + for fname, flag := range f.formal { + nname := f.normalizeFlagName(flag.Name) + if fname == nname { + continue + } + flag.Name = string(nname) + delete(f.formal, fname) + f.formal[nname] = flag + if _, set := f.actual[fname]; set { + delete(f.actual, fname) + f.actual[nname] = flag + } } } @@ -229,10 +244,25 @@ func (f *FlagSet) SetOutput(output io.Writer) { f.output = output } -// VisitAll visits the flags in lexicographical order, calling fn for each. +// VisitAll visits the flags in lexicographical order or +// in primordial order if f.SortFlags is false, calling fn for each. // It visits all flags, even those not set. func (f *FlagSet) VisitAll(fn func(*Flag)) { - for _, flag := range sortFlags(f.formal) { + if len(f.formal) == 0 { + return + } + + var flags []*Flag + if f.SortFlags { + if len(f.formal) != len(f.sortedFormal) { + f.sortedFormal = sortFlags(f.formal) + } + flags = f.sortedFormal + } else { + flags = f.orderedFormal + } + + for _, flag := range flags { fn(flag) } } @@ -253,22 +283,39 @@ func (f *FlagSet) HasAvailableFlags() bool { return false } -// VisitAll visits the command-line flags in lexicographical order, calling -// fn for each. It visits all flags, even those not set. +// VisitAll visits the command-line flags in lexicographical order or +// in primordial order if f.SortFlags is false, calling fn for each. +// It visits all flags, even those not set. func VisitAll(fn func(*Flag)) { CommandLine.VisitAll(fn) } -// Visit visits the flags in lexicographical order, calling fn for each. +// Visit visits the flags in lexicographical order or +// in primordial order if f.SortFlags is false, calling fn for each. // It visits only those flags that have been set. func (f *FlagSet) Visit(fn func(*Flag)) { - for _, flag := range sortFlags(f.actual) { + if len(f.actual) == 0 { + return + } + + var flags []*Flag + if f.SortFlags { + if len(f.actual) != len(f.sortedActual) { + f.sortedActual = sortFlags(f.actual) + } + flags = f.sortedActual + } else { + flags = f.orderedActual + } + + for _, flag := range flags { fn(flag) } } -// Visit visits the command-line flags in lexicographical order, calling fn -// for each. It visits only those flags that have been set. +// Visit visits the command-line flags in lexicographical order or +// in primordial order if f.SortFlags is false, calling fn for each. +// It visits only those flags that have been set. func Visit(fn func(*Flag)) { CommandLine.Visit(fn) } @@ -278,6 +325,22 @@ func (f *FlagSet) Lookup(name string) *Flag { return f.lookup(f.normalizeFlagName(name)) } +// ShorthandLookup returns the Flag structure of the short handed flag, +// returning nil if none exists. +// It panics, if len(name) > 1. +func (f *FlagSet) ShorthandLookup(name string) *Flag { + if name == "" { + return nil + } + if len(name) > 1 { + msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name) + fmt.Fprintf(f.out(), msg) + panic(msg) + } + c := name[0] + return f.shorthands[c] +} + // lookup returns the Flag structure of the named flag, returning nil if none exists. func (f *FlagSet) lookup(name NormalizedName) *Flag { return f.formal[name] @@ -319,7 +382,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error { if flag == nil { return fmt.Errorf("flag %q does not exist", name) } - if len(usageMessage) == 0 { + if usageMessage == "" { return fmt.Errorf("deprecated message for flag %q must be set", name) } flag.Deprecated = usageMessage @@ -334,7 +397,7 @@ func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) erro if flag == nil { return fmt.Errorf("flag %q does not exist", name) } - if len(usageMessage) == 0 { + if usageMessage == "" { return fmt.Errorf("deprecated message for flag %q must be set", name) } flag.ShorthandDeprecated = usageMessage @@ -358,6 +421,12 @@ func Lookup(name string) *Flag { return CommandLine.Lookup(name) } +// ShorthandLookup returns the Flag structure of the short handed flag, +// returning nil if none exists. +func ShorthandLookup(name string) *Flag { + return CommandLine.ShorthandLookup(name) +} + // Set sets the value of the named flag. func (f *FlagSet) Set(name, value string) error { normalName := f.normalizeFlagName(name) @@ -365,17 +434,30 @@ func (f *FlagSet) Set(name, value string) error { if !ok { return fmt.Errorf("no such flag -%v", name) } + err := flag.Value.Set(value) if err != nil { - return err + var flagName string + if flag.Shorthand != "" && flag.ShorthandDeprecated == "" { + flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name) + } else { + flagName = fmt.Sprintf("--%s", flag.Name) + } + return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err) } - if f.actual == nil { - f.actual = make(map[NormalizedName]*Flag) + + if !flag.Changed { + if f.actual == nil { + f.actual = make(map[NormalizedName]*Flag) + } + f.actual[normalName] = flag + f.orderedActual = append(f.orderedActual, flag) + + flag.Changed = true } - f.actual[normalName] = flag - flag.Changed = true - if len(flag.Deprecated) > 0 { - fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) + + if flag.Deprecated != "" { + fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) } return nil } @@ -482,6 +564,14 @@ func UnquoteUsage(flag *Flag) (name string, usage string) { name = "int" case "uint64": name = "uint" + case "stringSlice": + name = "strings" + case "intSlice": + name = "ints" + case "uintSlice": + name = "uints" + case "boolSlice": + name = "bools" } return @@ -557,28 +647,28 @@ func wrap(i, w int, s string) string { // for all flags in the FlagSet. Wrapped to `cols` columns (0 for no // wrapping) func (f *FlagSet) FlagUsagesWrapped(cols int) string { - x := new(bytes.Buffer) + buf := new(bytes.Buffer) lines := make([]string, 0, len(f.formal)) maxlen := 0 f.VisitAll(func(flag *Flag) { - if len(flag.Deprecated) > 0 || flag.Hidden { + if flag.Deprecated != "" || flag.Hidden { return } line := "" - if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 { + if flag.Shorthand != "" && flag.ShorthandDeprecated == "" { line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name) } else { line = fmt.Sprintf(" --%s", flag.Name) } varname, usage := UnquoteUsage(flag) - if len(varname) > 0 { + if varname != "" { line += " " + varname } - if len(flag.NoOptDefVal) > 0 { + if flag.NoOptDefVal != "" { switch flag.Value.Type() { case "string": line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal) @@ -586,6 +676,10 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string { if flag.NoOptDefVal != "true" { line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) } + case "count": + if flag.NoOptDefVal != "+1" { + line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) + } default: line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) } @@ -601,7 +695,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string { line += usage if !flag.defaultIsZeroValue() { if flag.Value.Type() == "string" { - line += fmt.Sprintf(" (default \"%s\")", flag.DefValue) + line += fmt.Sprintf(" (default %q)", flag.DefValue) } else { line += fmt.Sprintf(" (default %s)", flag.DefValue) } @@ -614,10 +708,10 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string { sidx := strings.Index(line, "\x00") spacing := strings.Repeat(" ", maxlen-sidx) // maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx - fmt.Fprintln(x, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:])) + fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:])) } - return x.String() + return buf.String() } // FlagUsages returns a string containing the usage information for all flags in @@ -714,11 +808,10 @@ func (f *FlagSet) VarP(value Value, name, shorthand, usage string) { // AddFlag will add the flag to the FlagSet func (f *FlagSet) AddFlag(flag *Flag) { - // Call normalizeFlagName function only once normalizedFlagName := f.normalizeFlagName(flag.Name) - _, alreadythere := f.formal[normalizedFlagName] - if alreadythere { + _, alreadyThere := f.formal[normalizedFlagName] + if alreadyThere { msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name) fmt.Fprintln(f.out(), msg) panic(msg) // Happens only if flags are declared with identical names @@ -729,28 +822,31 @@ func (f *FlagSet) AddFlag(flag *Flag) { flag.Name = string(normalizedFlagName) f.formal[normalizedFlagName] = flag + f.orderedFormal = append(f.orderedFormal, flag) - if len(flag.Shorthand) == 0 { + if flag.Shorthand == "" { return } if len(flag.Shorthand) > 1 { - fmt.Fprintf(f.out(), "%s shorthand more than ASCII character: %s\n", f.name, flag.Shorthand) - panic("shorthand is more than one character") + msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand) + fmt.Fprintf(f.out(), msg) + panic(msg) } if f.shorthands == nil { f.shorthands = make(map[byte]*Flag) } c := flag.Shorthand[0] - old, alreadythere := f.shorthands[c] - if alreadythere { - fmt.Fprintf(f.out(), "%s shorthand reused: %q for %s already used for %s\n", f.name, c, flag.Name, old.Name) - panic("shorthand redefinition") + used, alreadyThere := f.shorthands[c] + if alreadyThere { + msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name) + fmt.Fprintf(f.out(), msg) + panic(msg) } f.shorthands[c] = flag } // AddFlagSet adds one FlagSet to another. If a flag is already present in f -// the flag from newSet will be ignored +// the flag from newSet will be ignored. func (f *FlagSet) AddFlagSet(newSet *FlagSet) { if newSet == nil { return @@ -781,8 +877,10 @@ func VarP(value Value, name, shorthand, usage string) { // returns the error. func (f *FlagSet) failf(format string, a ...interface{}) error { err := fmt.Errorf(format, a...) - fmt.Fprintln(f.out(), err) - f.usage() + if f.errorHandling != ContinueOnError { + fmt.Fprintln(f.out(), err) + f.usage() + } return err } @@ -798,34 +896,6 @@ func (f *FlagSet) usage() { } } -func (f *FlagSet) setFlag(flag *Flag, value string, origArg string) error { - if err := flag.Value.Set(value); err != nil { - return f.failf("invalid argument %q for %s: %v", value, origArg, err) - } - // mark as visited for Visit() - if f.actual == nil { - f.actual = make(map[NormalizedName]*Flag) - } - f.actual[f.normalizeFlagName(flag.Name)] = flag - flag.Changed = true - if len(flag.Deprecated) > 0 { - fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) - } - if len(flag.ShorthandDeprecated) > 0 && containsShorthand(origArg, flag.Shorthand) { - fmt.Fprintf(os.Stderr, "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) - } - return nil -} - -func containsShorthand(arg, shorthand string) bool { - // filter out flags -- - if strings.HasPrefix(arg, "-") { - return false - } - arg = strings.SplitN(arg, "=", 2)[0] - return strings.Contains(arg, shorthand) -} - func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) { a = args name := s[2:] @@ -833,10 +903,11 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin err = f.failf("bad flag syntax: %s", s) return } + split := strings.SplitN(name, "=", 2) name = split[0] - flag, alreadythere := f.formal[f.normalizeFlagName(name)] - if !alreadythere { + flag, exists := f.formal[f.normalizeFlagName(name)] + if !exists { if name == "help" { // special case for nice help message. f.usage() return a, ErrHelp @@ -844,11 +915,12 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin err = f.failf("unknown flag: --%s", name) return } + var value string if len(split) == 2 { // '--flag=arg' value = split[1] - } else if len(flag.NoOptDefVal) > 0 { + } else if flag.NoOptDefVal != "" { // '--flag' (arg was optional) value = flag.NoOptDefVal } else if len(a) > 0 { @@ -860,7 +932,11 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin err = f.failf("flag needs an argument: %s", s) return } - err = fn(flag, value, s) + + err = fn(flag, value) + if err != nil { + f.failf(err.Error()) + } return } @@ -868,38 +944,52 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse if strings.HasPrefix(shorthands, "test.") { return } + outArgs = args outShorts = shorthands[1:] c := shorthands[0] - flag, alreadythere := f.shorthands[c] - if !alreadythere { + flag, exists := f.shorthands[c] + if !exists { if c == 'h' { // special case for nice help message. f.usage() err = ErrHelp return } - //TODO continue on error err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands) return } + var value string if len(shorthands) > 2 && shorthands[1] == '=' { + // '-f=arg' value = shorthands[2:] outShorts = "" - } else if len(flag.NoOptDefVal) > 0 { + } else if flag.NoOptDefVal != "" { + // '-f' (arg was optional) value = flag.NoOptDefVal } else if len(shorthands) > 1 { + // '-farg' value = shorthands[1:] outShorts = "" } else if len(args) > 0 { + // '-f arg' value = args[0] outArgs = args[1:] } else { + // '-f' (arg was required) err = f.failf("flag needs an argument: %q in -%s", c, shorthands) return } - err = fn(flag, value, shorthands) + + if flag.ShorthandDeprecated != "" { + fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) + } + + err = fn(flag, value) + if err != nil { + f.failf(err.Error()) + } return } @@ -907,6 +997,7 @@ func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []stri a = args shorthands := s[1:] + // "shorthands" can be a series of shorthand letters of flags (e.g. "-vvv"). for len(shorthands) > 0 { shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn) if err != nil { @@ -954,18 +1045,24 @@ func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) { // The return value will be ErrHelp if -help was set but not defined. func (f *FlagSet) Parse(arguments []string) error { f.parsed = true - f.args = make([]string, 0, len(arguments)) - assign := func(flag *Flag, value, origArg string) error { - return f.setFlag(flag, value, origArg) + if len(arguments) < 0 { + return nil } - err := f.parseArgs(arguments, assign) + f.args = make([]string, 0, len(arguments)) + + set := func(flag *Flag, value string) error { + return f.Set(flag.Name, value) + } + + err := f.parseArgs(arguments, set) if err != nil { switch f.errorHandling { case ContinueOnError: return err case ExitOnError: + fmt.Println(err) os.Exit(2) case PanicOnError: panic(err) @@ -974,7 +1071,7 @@ func (f *FlagSet) Parse(arguments []string) error { return nil } -type parseFunc func(flag *Flag, value, origArg string) error +type parseFunc func(flag *Flag, value string) error // ParseAll parses flag definitions from the argument list, which should not // include the command name. The arguments for fn are flag and value. Must be @@ -985,11 +1082,7 @@ func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) f.parsed = true f.args = make([]string, 0, len(arguments)) - assign := func(flag *Flag, value, origArg string) error { - return fn(flag, value) - } - - err := f.parseArgs(arguments, assign) + err := f.parseArgs(arguments, fn) if err != nil { switch f.errorHandling { case ContinueOnError: @@ -1036,14 +1129,15 @@ func Parsed() bool { // CommandLine is the default set of command-line flags, parsed from os.Args. var CommandLine = NewFlagSet(os.Args[0], ExitOnError) -// NewFlagSet returns a new, empty flag set with the specified name and -// error handling property. +// NewFlagSet returns a new, empty flag set with the specified name, +// error handling property and SortFlags set to true. func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { f := &FlagSet{ name: name, errorHandling: errorHandling, argsLenAtDash: -1, interspersed: true, + SortFlags: true, } return f } diff --git a/vendor/github.com/spf13/pflag/int16.go b/vendor/github.com/spf13/pflag/int16.go new file mode 100644 index 00000000000..f1a01d05e69 --- /dev/null +++ b/vendor/github.com/spf13/pflag/int16.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- int16 Value +type int16Value int16 + +func newInt16Value(val int16, p *int16) *int16Value { + *p = val + return (*int16Value)(p) +} + +func (i *int16Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 16) + *i = int16Value(v) + return err +} + +func (i *int16Value) Type() string { + return "int16" +} + +func (i *int16Value) String() string { return strconv.FormatInt(int64(*i), 10) } + +func int16Conv(sval string) (interface{}, error) { + v, err := strconv.ParseInt(sval, 0, 16) + if err != nil { + return 0, err + } + return int16(v), nil +} + +// GetInt16 returns the int16 value of a flag with the given name +func (f *FlagSet) GetInt16(name string) (int16, error) { + val, err := f.getFlagType(name, "int16", int16Conv) + if err != nil { + return 0, err + } + return val.(int16), nil +} + +// Int16Var defines an int16 flag with specified name, default value, and usage string. +// The argument p points to an int16 variable in which to store the value of the flag. +func (f *FlagSet) Int16Var(p *int16, name string, value int16, usage string) { + f.VarP(newInt16Value(value, p), name, "", usage) +} + +// Int16VarP is like Int16Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int16VarP(p *int16, name, shorthand string, value int16, usage string) { + f.VarP(newInt16Value(value, p), name, shorthand, usage) +} + +// Int16Var defines an int16 flag with specified name, default value, and usage string. +// The argument p points to an int16 variable in which to store the value of the flag. +func Int16Var(p *int16, name string, value int16, usage string) { + CommandLine.VarP(newInt16Value(value, p), name, "", usage) +} + +// Int16VarP is like Int16Var, but accepts a shorthand letter that can be used after a single dash. +func Int16VarP(p *int16, name, shorthand string, value int16, usage string) { + CommandLine.VarP(newInt16Value(value, p), name, shorthand, usage) +} + +// Int16 defines an int16 flag with specified name, default value, and usage string. +// The return value is the address of an int16 variable that stores the value of the flag. +func (f *FlagSet) Int16(name string, value int16, usage string) *int16 { + p := new(int16) + f.Int16VarP(p, name, "", value, usage) + return p +} + +// Int16P is like Int16, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int16P(name, shorthand string, value int16, usage string) *int16 { + p := new(int16) + f.Int16VarP(p, name, shorthand, value, usage) + return p +} + +// Int16 defines an int16 flag with specified name, default value, and usage string. +// The return value is the address of an int16 variable that stores the value of the flag. +func Int16(name string, value int16, usage string) *int16 { + return CommandLine.Int16P(name, "", value, usage) +} + +// Int16P is like Int16, but accepts a shorthand letter that can be used after a single dash. +func Int16P(name, shorthand string, value int16, usage string) *int16 { + return CommandLine.Int16P(name, shorthand, value, usage) +} From 1c715d51c42cafb042b4bb8b03e82a52c5070409 Mon Sep 17 00:00:00 2001 From: Di Xu Date: Wed, 11 Oct 2017 14:26:02 +0800 Subject: [PATCH 08/58] some code change fix wrong required flags disable the addition of [flags] to the usage, use customized useline fix function rename --- cmd/genkubedocs/postprocessing.go | 2 +- cmd/kubeadm/app/cmd/join.go | 2 +- cmd/kubeadm/app/cmd/token.go | 6 +++-- cmd/kubeadm/app/cmd/upgrade/apply.go | 3 ++- pkg/kubectl/cmd/annotate.go | 3 ++- pkg/kubectl/cmd/apply.go | 3 ++- pkg/kubectl/cmd/apply_edit_last_applied.go | 3 ++- pkg/kubectl/cmd/apply_set_last_applied.go | 3 ++- pkg/kubectl/cmd/apply_view_last_applied.go | 3 ++- pkg/kubectl/cmd/attach.go | 3 ++- pkg/kubectl/cmd/auth/cani.go | 3 ++- pkg/kubectl/cmd/auth/reconcile.go | 3 ++- pkg/kubectl/cmd/autoscale.go | 3 ++- pkg/kubectl/cmd/certificates.go | 9 ++++--- pkg/kubectl/cmd/completion.go | 3 ++- pkg/kubectl/cmd/config/config.go | 3 ++- pkg/kubectl/cmd/config/create_authinfo.go | 3 ++- pkg/kubectl/cmd/config/create_cluster.go | 3 ++- pkg/kubectl/cmd/config/create_context.go | 3 ++- pkg/kubectl/cmd/config/delete_cluster.go | 3 ++- pkg/kubectl/cmd/config/delete_context.go | 3 ++- pkg/kubectl/cmd/config/get_contexts.go | 3 ++- pkg/kubectl/cmd/config/rename_context.go | 3 ++- pkg/kubectl/cmd/config/set.go | 3 ++- pkg/kubectl/cmd/config/unset.go | 3 ++- pkg/kubectl/cmd/config/use_context.go | 3 ++- pkg/kubectl/cmd/convert.go | 3 ++- pkg/kubectl/cmd/cp.go | 3 ++- pkg/kubectl/cmd/create.go | 3 ++- pkg/kubectl/cmd/create_clusterrole.go | 3 ++- pkg/kubectl/cmd/create_clusterrolebinding.go | 3 ++- pkg/kubectl/cmd/create_configmap.go | 11 ++++---- pkg/kubectl/cmd/create_deployment.go | 11 ++++---- pkg/kubectl/cmd/create_namespace.go | 11 ++++---- pkg/kubectl/cmd/create_pdb.go | 11 ++++---- pkg/kubectl/cmd/create_priorityclass.go | 11 ++++---- pkg/kubectl/cmd/create_quota.go | 11 ++++---- pkg/kubectl/cmd/create_role.go | 3 ++- pkg/kubectl/cmd/create_rolebinding.go | 3 ++- pkg/kubectl/cmd/create_secret.go | 9 ++++--- pkg/kubectl/cmd/create_service.go | 12 ++++++--- pkg/kubectl/cmd/create_serviceaccount.go | 11 ++++---- pkg/kubectl/cmd/delete.go | 3 ++- pkg/kubectl/cmd/delete_test.go | 1 + pkg/kubectl/cmd/describe.go | 3 ++- pkg/kubectl/cmd/describe_test.go | 28 ++++++++++++++++++++ pkg/kubectl/cmd/diff.go | 3 ++- pkg/kubectl/cmd/drain.go | 9 ++++--- pkg/kubectl/cmd/edit.go | 3 ++- pkg/kubectl/cmd/exec.go | 3 ++- pkg/kubectl/cmd/explain.go | 3 ++- pkg/kubectl/cmd/expose.go | 3 ++- pkg/kubectl/cmd/help.go | 3 ++- pkg/kubectl/cmd/label.go | 3 ++- pkg/kubectl/cmd/logs.go | 3 ++- pkg/kubectl/cmd/patch.go | 3 ++- pkg/kubectl/cmd/plugin.go | 3 ++- pkg/kubectl/cmd/portforward.go | 3 ++- pkg/kubectl/cmd/proxy.go | 3 ++- pkg/kubectl/cmd/replace.go | 3 ++- pkg/kubectl/cmd/resource/get.go | 3 ++- pkg/kubectl/cmd/rollingupdate.go | 5 ++-- pkg/kubectl/cmd/rollout/rollout.go | 3 ++- pkg/kubectl/cmd/rollout/rollout_history.go | 3 ++- pkg/kubectl/cmd/rollout/rollout_pause.go | 3 ++- pkg/kubectl/cmd/rollout/rollout_resume.go | 3 ++- pkg/kubectl/cmd/rollout/rollout_status.go | 3 ++- pkg/kubectl/cmd/rollout/rollout_undo.go | 3 ++- pkg/kubectl/cmd/run.go | 3 ++- pkg/kubectl/cmd/scale.go | 3 ++- pkg/kubectl/cmd/set/set.go | 3 ++- pkg/kubectl/cmd/set/set_env.go | 3 ++- pkg/kubectl/cmd/set/set_image.go | 3 ++- pkg/kubectl/cmd/set/set_resources.go | 3 ++- pkg/kubectl/cmd/set/set_selector.go | 3 ++- pkg/kubectl/cmd/set/set_serviceaccount.go | 11 ++++---- pkg/kubectl/cmd/set/set_subject.go | 3 ++- pkg/kubectl/cmd/taint.go | 3 ++- pkg/kubectl/cmd/top_node.go | 3 ++- pkg/kubectl/cmd/top_pod.go | 3 ++- 80 files changed, 235 insertions(+), 122 deletions(-) diff --git a/cmd/genkubedocs/postprocessing.go b/cmd/genkubedocs/postprocessing.go index 57b6d95e058..c51e1443bc3 100644 --- a/cmd/genkubedocs/postprocessing.go +++ b/cmd/genkubedocs/postprocessing.go @@ -27,7 +27,7 @@ import ( // MarkdownPostProcessing goes though the generated files func MarkdownPostProcessing(cmd *cobra.Command, dir string, processor func(string) string) error { for _, c := range cmd.Commands() { - if !c.IsAvailableCommand() || c.IsHelpCommand() { + if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { continue } if err := MarkdownPostProcessing(c, dir, processor); err != nil { diff --git a/cmd/kubeadm/app/cmd/join.go b/cmd/kubeadm/app/cmd/join.go index 2bc32fe4d72..14d7acce072 100644 --- a/cmd/kubeadm/app/cmd/join.go +++ b/cmd/kubeadm/app/cmd/join.go @@ -111,7 +111,7 @@ func NewCmdJoin(out io.Writer) *cobra.Command { var ignorePreflightErrors []string cmd := &cobra.Command{ - Use: "join [flags]", + Use: "join", Short: "Run this on any machine you wish to join an existing cluster", Long: joinLongDescription, Run: func(cmd *cobra.Command, args []string) { diff --git a/cmd/kubeadm/app/cmd/token.go b/cmd/kubeadm/app/cmd/token.go index 87b8d077750..3c3799857a7 100644 --- a/cmd/kubeadm/app/cmd/token.go +++ b/cmd/kubeadm/app/cmd/token.go @@ -101,7 +101,8 @@ func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command { var description string var printJoinCommand bool createCmd := &cobra.Command{ - Use: "create [token]", + Use: "create [token]", + DisableFlagsInUseLine: true, Short: "Create bootstrap tokens on the server.", Long: dedent.Dedent(` This command will create a bootstrap token for you. @@ -155,7 +156,8 @@ func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command { tokenCmd.AddCommand(listCmd) deleteCmd := &cobra.Command{ - Use: "delete [token-value]", + Use: "delete [token-value]", + DisableFlagsInUseLine: true, Short: "Delete bootstrap tokens on the server.", Long: dedent.Dedent(` This command will delete a given bootstrap token for you. diff --git a/cmd/kubeadm/app/cmd/upgrade/apply.go b/cmd/kubeadm/app/cmd/upgrade/apply.go index 08629ef2b78..12101083c1b 100644 --- a/cmd/kubeadm/app/cmd/upgrade/apply.go +++ b/cmd/kubeadm/app/cmd/upgrade/apply.go @@ -69,7 +69,8 @@ func NewCmdApply(parentFlags *cmdUpgradeFlags) *cobra.Command { } cmd := &cobra.Command{ - Use: "apply [version]", + Use: "apply [version]", + DisableFlagsInUseLine: true, Short: "Upgrade your Kubernetes cluster to the specified version.", Run: func(cmd *cobra.Command, args []string) { var err error diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index 09541ea0e24..0637528d7e7 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -113,7 +113,8 @@ func NewCmdAnnotate(f cmdutil.Factory, out io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "annotate [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]", + Use: "annotate [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]", + DisableFlagsInUseLine: true, Short: i18n.T("Update the annotations on a resource"), Long: annotateLong + "\n\n" + cmdutil.ValidResourceTypeList(f), Example: annotateExample, diff --git a/pkg/kubectl/cmd/apply.go b/pkg/kubectl/cmd/apply.go index e132743231c..9bb6d194f81 100644 --- a/pkg/kubectl/cmd/apply.go +++ b/pkg/kubectl/cmd/apply.go @@ -105,7 +105,8 @@ func NewCmdApply(baseName string, f cmdutil.Factory, out, errOut io.Writer) *cob options.cmdBaseName = baseName cmd := &cobra.Command{ - Use: "apply -f FILENAME", + Use: "apply -f FILENAME", + DisableFlagsInUseLine: true, Short: i18n.T("Apply a configuration to a resource by filename or stdin"), Long: applyLong, Example: applyExample, diff --git a/pkg/kubectl/cmd/apply_edit_last_applied.go b/pkg/kubectl/cmd/apply_edit_last_applied.go index ca4868fa5b8..f12bb981e87 100644 --- a/pkg/kubectl/cmd/apply_edit_last_applied.go +++ b/pkg/kubectl/cmd/apply_edit_last_applied.go @@ -76,7 +76,8 @@ func NewCmdApplyEditLastApplied(f cmdutil.Factory, out, errOut io.Writer) *cobra } cmd := &cobra.Command{ - Use: "edit-last-applied (RESOURCE/NAME | -f FILENAME)", + Use: "edit-last-applied (RESOURCE/NAME | -f FILENAME)", + DisableFlagsInUseLine: true, Short: "Edit latest last-applied-configuration annotations of a resource/object", Long: applyEditLastAppliedLong, Example: applyEditLastAppliedExample, diff --git a/pkg/kubectl/cmd/apply_set_last_applied.go b/pkg/kubectl/cmd/apply_set_last_applied.go index 640009b2788..cc455f6a4c3 100644 --- a/pkg/kubectl/cmd/apply_set_last_applied.go +++ b/pkg/kubectl/cmd/apply_set_last_applied.go @@ -84,7 +84,8 @@ var ( func NewCmdApplySetLastApplied(f cmdutil.Factory, out, err io.Writer) *cobra.Command { options := &SetLastAppliedOptions{Out: out, ErrOut: err} cmd := &cobra.Command{ - Use: "set-last-applied -f FILENAME", + Use: "set-last-applied -f FILENAME", + DisableFlagsInUseLine: true, Short: i18n.T("Set the last-applied-configuration annotation on a live object to match the contents of a file."), Long: applySetLastAppliedLong, Example: applySetLastAppliedExample, diff --git a/pkg/kubectl/cmd/apply_view_last_applied.go b/pkg/kubectl/cmd/apply_view_last_applied.go index 7282ae6265f..b0ebb1af820 100644 --- a/pkg/kubectl/cmd/apply_view_last_applied.go +++ b/pkg/kubectl/cmd/apply_view_last_applied.go @@ -60,7 +60,8 @@ var ( func NewCmdApplyViewLastApplied(f cmdutil.Factory, out, err io.Writer) *cobra.Command { options := &ViewLastAppliedOptions{Out: out, ErrOut: err} cmd := &cobra.Command{ - Use: "view-last-applied (TYPE [NAME | -l label] | TYPE/NAME | -f FILENAME)", + Use: "view-last-applied (TYPE [NAME | -l label] | TYPE/NAME | -f FILENAME)", + DisableFlagsInUseLine: true, Short: i18n.T("View latest last-applied-configuration annotations of a resource/object"), Long: applyViewLastAppliedLong, Example: applyViewLastAppliedExample, diff --git a/pkg/kubectl/cmd/attach.go b/pkg/kubectl/cmd/attach.go index 7bc49ca06da..1b188d10853 100644 --- a/pkg/kubectl/cmd/attach.go +++ b/pkg/kubectl/cmd/attach.go @@ -71,7 +71,8 @@ func NewCmdAttach(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) Attach: &DefaultRemoteAttach{}, } cmd := &cobra.Command{ - Use: "attach (POD | TYPE/NAME) -c CONTAINER", + Use: "attach (POD | TYPE/NAME) -c CONTAINER", + DisableFlagsInUseLine: true, Short: i18n.T("Attach to a running container"), Long: "Attach to a process that is already running inside an existing container.", Example: attachExample, diff --git a/pkg/kubectl/cmd/auth/cani.go b/pkg/kubectl/cmd/auth/cani.go index 97e461a46fc..7484cab1895 100644 --- a/pkg/kubectl/cmd/auth/cani.go +++ b/pkg/kubectl/cmd/auth/cani.go @@ -88,7 +88,8 @@ func NewCmdCanI(f cmdutil.Factory, out, err io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "can-i VERB [TYPE | TYPE/NAME | NONRESOURCEURL]", + Use: "can-i VERB [TYPE | TYPE/NAME | NONRESOURCEURL]", + DisableFlagsInUseLine: true, Short: "Check whether an action is allowed", Long: canILong, Example: canIExample, diff --git a/pkg/kubectl/cmd/auth/reconcile.go b/pkg/kubectl/cmd/auth/reconcile.go index 0c65c954c38..377d241a00b 100644 --- a/pkg/kubectl/cmd/auth/reconcile.go +++ b/pkg/kubectl/cmd/auth/reconcile.go @@ -64,7 +64,8 @@ func NewCmdReconcile(f cmdutil.Factory, out, err io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "reconcile -f FILENAME", + Use: "reconcile -f FILENAME", + DisableFlagsInUseLine: true, Short: "Reconciles rules for RBAC Role, RoleBinding, ClusterRole, and ClusterRole binding objects", Long: reconcileLong, Example: reconcileExample, diff --git a/pkg/kubectl/cmd/autoscale.go b/pkg/kubectl/cmd/autoscale.go index 30406934fce..d87146cd073 100644 --- a/pkg/kubectl/cmd/autoscale.go +++ b/pkg/kubectl/cmd/autoscale.go @@ -52,7 +52,8 @@ func NewCmdAutoscale(f cmdutil.Factory, out io.Writer) *cobra.Command { argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ - Use: "autoscale (-f FILENAME | TYPE NAME | TYPE/NAME) [--min=MINPODS] --max=MAXPODS [--cpu-percent=CPU] [flags]", + Use: "autoscale (-f FILENAME | TYPE NAME | TYPE/NAME) [--min=MINPODS] --max=MAXPODS [--cpu-percent=CPU]", + DisableFlagsInUseLine: true, Short: i18n.T("Auto-scale a Deployment, ReplicaSet, or ReplicationController"), Long: autoscaleLong, Example: autoscaleExample, diff --git a/pkg/kubectl/cmd/certificates.go b/pkg/kubectl/cmd/certificates.go index bc2974322c2..ee51e4b266c 100644 --- a/pkg/kubectl/cmd/certificates.go +++ b/pkg/kubectl/cmd/certificates.go @@ -32,7 +32,8 @@ import ( func NewCmdCertificate(f cmdutil.Factory, out io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "certificate SUBCOMMAND", + Use: "certificate SUBCOMMAND", + DisableFlagsInUseLine: true, Short: i18n.T("Modify certificate resources."), Long: "Modify certificate resources.", Run: func(cmd *cobra.Command, args []string) { @@ -68,7 +69,8 @@ func (options *CertificateOptions) Validate() error { func NewCmdCertificateApprove(f cmdutil.Factory, out io.Writer) *cobra.Command { options := CertificateOptions{} cmd := &cobra.Command{ - Use: "approve (-f FILENAME | NAME)", + Use: "approve (-f FILENAME | NAME)", + DisableFlagsInUseLine: true, Short: i18n.T("Approve a certificate signing request"), Long: templates.LongDesc(` Approve a certificate signing request. @@ -118,7 +120,8 @@ func (options *CertificateOptions) RunCertificateApprove(f cmdutil.Factory, out func NewCmdCertificateDeny(f cmdutil.Factory, out io.Writer) *cobra.Command { options := CertificateOptions{} cmd := &cobra.Command{ - Use: "deny (-f FILENAME | NAME)", + Use: "deny (-f FILENAME | NAME)", + DisableFlagsInUseLine: true, Short: i18n.T("Deny a certificate signing request"), Long: templates.LongDesc(` Deny a certificate signing request. diff --git a/pkg/kubectl/cmd/completion.go b/pkg/kubectl/cmd/completion.go index d14ca66329b..d6d9a3506ca 100644 --- a/pkg/kubectl/cmd/completion.go +++ b/pkg/kubectl/cmd/completion.go @@ -97,7 +97,8 @@ func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command { } cmd := &cobra.Command{ - Use: "completion SHELL", + Use: "completion SHELL", + DisableFlagsInUseLine: true, Short: i18n.T("Output shell completion code for the specified shell (bash or zsh)"), Long: completion_long, Example: completion_example, diff --git a/pkg/kubectl/cmd/config/config.go b/pkg/kubectl/cmd/config/config.go index b63d1cf15f3..7984eb5e15f 100644 --- a/pkg/kubectl/cmd/config/config.go +++ b/pkg/kubectl/cmd/config/config.go @@ -37,7 +37,8 @@ func NewCmdConfig(f cmdutil.Factory, pathOptions *clientcmd.PathOptions, out, er } cmd := &cobra.Command{ - Use: "config SUBCOMMAND", + Use: "config SUBCOMMAND", + DisableFlagsInUseLine: true, Short: i18n.T("Modify kubeconfig files"), Long: templates.LongDesc(` Modify kubeconfig files using subcommands like "kubectl config set current-context my-context" diff --git a/pkg/kubectl/cmd/config/create_authinfo.go b/pkg/kubectl/cmd/config/create_authinfo.go index 7430a7c0bc4..368d47c0fb3 100644 --- a/pkg/kubectl/cmd/config/create_authinfo.go +++ b/pkg/kubectl/cmd/config/create_authinfo.go @@ -100,7 +100,8 @@ func NewCmdConfigSetAuthInfo(out io.Writer, configAccess clientcmd.ConfigAccess) func newCmdConfigSetAuthInfo(out io.Writer, options *createAuthInfoOptions) *cobra.Command { cmd := &cobra.Command{ - Use: fmt.Sprintf("set-credentials NAME [--%v=path/to/certfile] [--%v=path/to/keyfile] [--%v=bearer_token] [--%v=basic_user] [--%v=basic_password] [--%v=provider_name] [--%v=key=value]", clientcmd.FlagCertFile, clientcmd.FlagKeyFile, clientcmd.FlagBearerToken, clientcmd.FlagUsername, clientcmd.FlagPassword, flagAuthProvider, flagAuthProviderArg), + Use: fmt.Sprintf("set-credentials NAME [--%v=path/to/certfile] [--%v=path/to/keyfile] [--%v=bearer_token] [--%v=basic_user] [--%v=basic_password] [--%v=provider_name] [--%v=key=value]", clientcmd.FlagCertFile, clientcmd.FlagKeyFile, clientcmd.FlagBearerToken, clientcmd.FlagUsername, clientcmd.FlagPassword, flagAuthProvider, flagAuthProviderArg), + DisableFlagsInUseLine: true, Short: i18n.T("Sets a user entry in kubeconfig"), Long: create_authinfo_long, Example: create_authinfo_example, diff --git a/pkg/kubectl/cmd/config/create_cluster.go b/pkg/kubectl/cmd/config/create_cluster.go index 2b4a47a1d84..f1f2d091bca 100644 --- a/pkg/kubectl/cmd/config/create_cluster.go +++ b/pkg/kubectl/cmd/config/create_cluster.go @@ -63,7 +63,8 @@ func NewCmdConfigSetCluster(out io.Writer, configAccess clientcmd.ConfigAccess) options := &createClusterOptions{configAccess: configAccess} cmd := &cobra.Command{ - Use: fmt.Sprintf("set-cluster NAME [--%v=server] [--%v=path/to/certificate/authority] [--%v=true]", clientcmd.FlagAPIServer, clientcmd.FlagCAFile, clientcmd.FlagInsecure), + Use: fmt.Sprintf("set-cluster NAME [--%v=server] [--%v=path/to/certificate/authority] [--%v=true]", clientcmd.FlagAPIServer, clientcmd.FlagCAFile, clientcmd.FlagInsecure), + DisableFlagsInUseLine: true, Short: i18n.T("Sets a cluster entry in kubeconfig"), Long: create_cluster_long, Example: create_cluster_example, diff --git a/pkg/kubectl/cmd/config/create_context.go b/pkg/kubectl/cmd/config/create_context.go index e3351488c06..d5231729165 100644 --- a/pkg/kubectl/cmd/config/create_context.go +++ b/pkg/kubectl/cmd/config/create_context.go @@ -54,7 +54,8 @@ func NewCmdConfigSetContext(out io.Writer, configAccess clientcmd.ConfigAccess) options := &createContextOptions{configAccess: configAccess} cmd := &cobra.Command{ - Use: fmt.Sprintf("set-context NAME [--%v=cluster_nickname] [--%v=user_nickname] [--%v=namespace]", clientcmd.FlagClusterName, clientcmd.FlagAuthInfoName, clientcmd.FlagNamespace), + Use: fmt.Sprintf("set-context NAME [--%v=cluster_nickname] [--%v=user_nickname] [--%v=namespace]", clientcmd.FlagClusterName, clientcmd.FlagAuthInfoName, clientcmd.FlagNamespace), + DisableFlagsInUseLine: true, Short: i18n.T("Sets a context entry in kubeconfig"), Long: create_context_long, Example: create_context_example, diff --git a/pkg/kubectl/cmd/config/delete_cluster.go b/pkg/kubectl/cmd/config/delete_cluster.go index 136524a8fc3..a9e00ce8348 100644 --- a/pkg/kubectl/cmd/config/delete_cluster.go +++ b/pkg/kubectl/cmd/config/delete_cluster.go @@ -35,7 +35,8 @@ var ( func NewCmdConfigDeleteCluster(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { cmd := &cobra.Command{ - Use: "delete-cluster NAME", + Use: "delete-cluster NAME", + DisableFlagsInUseLine: true, Short: i18n.T("Delete the specified cluster from the kubeconfig"), Long: "Delete the specified cluster from the kubeconfig", Example: delete_cluster_example, diff --git a/pkg/kubectl/cmd/config/delete_context.go b/pkg/kubectl/cmd/config/delete_context.go index 6d834841c76..d6dad310221 100644 --- a/pkg/kubectl/cmd/config/delete_context.go +++ b/pkg/kubectl/cmd/config/delete_context.go @@ -35,7 +35,8 @@ var ( func NewCmdConfigDeleteContext(out, errOut io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { cmd := &cobra.Command{ - Use: "delete-context NAME", + Use: "delete-context NAME", + DisableFlagsInUseLine: true, Short: i18n.T("Delete the specified context from the kubeconfig"), Long: "Delete the specified context from the kubeconfig", Example: delete_context_example, diff --git a/pkg/kubectl/cmd/config/get_contexts.go b/pkg/kubectl/cmd/config/get_contexts.go index b018a52dca5..b392bdb3961 100644 --- a/pkg/kubectl/cmd/config/get_contexts.go +++ b/pkg/kubectl/cmd/config/get_contexts.go @@ -61,7 +61,8 @@ func NewCmdConfigGetContexts(out io.Writer, configAccess clientcmd.ConfigAccess) options := &GetContextsOptions{configAccess: configAccess} cmd := &cobra.Command{ - Use: "get-contexts [(-o|--output=)name)]", + Use: "get-contexts [(-o|--output=)name)]", + DisableFlagsInUseLine: true, Short: i18n.T("Describe one or many contexts"), Long: getContextsLong, Example: getContextsExample, diff --git a/pkg/kubectl/cmd/config/rename_context.go b/pkg/kubectl/cmd/config/rename_context.go index 3216a7c83ea..b5fc2e728de 100644 --- a/pkg/kubectl/cmd/config/rename_context.go +++ b/pkg/kubectl/cmd/config/rename_context.go @@ -61,7 +61,8 @@ func NewCmdConfigRenameContext(out io.Writer, configAccess clientcmd.ConfigAcces options := &RenameContextOptions{configAccess: configAccess} cmd := &cobra.Command{ - Use: renameContextUse, + Use: renameContextUse, + DisableFlagsInUseLine: true, Short: renameContextShort, Long: renameContextLong, Example: renameContextExample, diff --git a/pkg/kubectl/cmd/config/set.go b/pkg/kubectl/cmd/config/set.go index 03f97580a08..4374b74b201 100644 --- a/pkg/kubectl/cmd/config/set.go +++ b/pkg/kubectl/cmd/config/set.go @@ -56,7 +56,8 @@ func NewCmdConfigSet(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra. options := &setOptions{configAccess: configAccess} cmd := &cobra.Command{ - Use: "set PROPERTY_NAME PROPERTY_VALUE", + Use: "set PROPERTY_NAME PROPERTY_VALUE", + DisableFlagsInUseLine: true, Short: i18n.T("Sets an individual value in a kubeconfig file"), Long: set_long, Run: func(cmd *cobra.Command, args []string) { diff --git a/pkg/kubectl/cmd/config/unset.go b/pkg/kubectl/cmd/config/unset.go index 3d62038301b..201c6f9d313 100644 --- a/pkg/kubectl/cmd/config/unset.go +++ b/pkg/kubectl/cmd/config/unset.go @@ -44,7 +44,8 @@ func NewCmdConfigUnset(out io.Writer, configAccess clientcmd.ConfigAccess) *cobr options := &unsetOptions{configAccess: configAccess} cmd := &cobra.Command{ - Use: "unset PROPERTY_NAME", + Use: "unset PROPERTY_NAME", + DisableFlagsInUseLine: true, Short: i18n.T("Unsets an individual value in a kubeconfig file"), Long: unset_long, Run: func(cmd *cobra.Command, args []string) { diff --git a/pkg/kubectl/cmd/config/use_context.go b/pkg/kubectl/cmd/config/use_context.go index 38f77eea2c3..f19a92cce0d 100644 --- a/pkg/kubectl/cmd/config/use_context.go +++ b/pkg/kubectl/cmd/config/use_context.go @@ -45,7 +45,8 @@ func NewCmdConfigUseContext(out io.Writer, configAccess clientcmd.ConfigAccess) options := &useContextOptions{configAccess: configAccess} cmd := &cobra.Command{ - Use: "use-context CONTEXT_NAME", + Use: "use-context CONTEXT_NAME", + DisableFlagsInUseLine: true, Short: i18n.T("Sets the current-context in a kubeconfig file"), Aliases: []string{"use"}, Long: `Sets the current-context in a kubeconfig file`, diff --git a/pkg/kubectl/cmd/convert.go b/pkg/kubectl/cmd/convert.go index 285b726011d..aa5b31cdb1c 100644 --- a/pkg/kubectl/cmd/convert.go +++ b/pkg/kubectl/cmd/convert.go @@ -65,7 +65,8 @@ func NewCmdConvert(f cmdutil.Factory, out io.Writer) *cobra.Command { options := &ConvertOptions{} cmd := &cobra.Command{ - Use: "convert -f FILENAME", + Use: "convert -f FILENAME", + DisableFlagsInUseLine: true, Short: i18n.T("Convert config files between different API versions"), Long: convert_long, Example: convert_example, diff --git a/pkg/kubectl/cmd/cp.go b/pkg/kubectl/cmd/cp.go index a5d67de3f96..acbb2eff38a 100644 --- a/pkg/kubectl/cmd/cp.go +++ b/pkg/kubectl/cmd/cp.go @@ -64,7 +64,8 @@ var ( // NewCmdCp creates a new Copy command. func NewCmdCp(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "cp ", + Use: "cp ", + DisableFlagsInUseLine: true, Short: i18n.T("Copy files and directories to and from containers."), Long: "Copy files and directories to and from containers.", Example: cpExample, diff --git a/pkg/kubectl/cmd/create.go b/pkg/kubectl/cmd/create.go index 5c00d69acd3..b23dee7b7c8 100644 --- a/pkg/kubectl/cmd/create.go +++ b/pkg/kubectl/cmd/create.go @@ -65,7 +65,8 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { var options CreateOptions cmd := &cobra.Command{ - Use: "create -f FILENAME", + Use: "create -f FILENAME", + DisableFlagsInUseLine: true, Short: i18n.T("Create a resource from a file or from stdin."), Long: createLong, Example: createExample, diff --git a/pkg/kubectl/cmd/create_clusterrole.go b/pkg/kubectl/cmd/create_clusterrole.go index 5ed01ce3c33..8f8db8ccb70 100644 --- a/pkg/kubectl/cmd/create_clusterrole.go +++ b/pkg/kubectl/cmd/create_clusterrole.go @@ -66,7 +66,8 @@ func NewCmdCreateClusterRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command }, } cmd := &cobra.Command{ - Use: "clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run]", + Use: "clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run]", + DisableFlagsInUseLine: true, Short: clusterRoleLong, Long: clusterRoleLong, Example: clusterRoleExample, diff --git a/pkg/kubectl/cmd/create_clusterrolebinding.go b/pkg/kubectl/cmd/create_clusterrolebinding.go index d79a18bea9b..c7ce180c343 100644 --- a/pkg/kubectl/cmd/create_clusterrolebinding.go +++ b/pkg/kubectl/cmd/create_clusterrolebinding.go @@ -39,7 +39,8 @@ var ( // ClusterRoleBinding is a command to ease creating ClusterRoleBindings. func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", + Use: "clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", + DisableFlagsInUseLine: true, Short: i18n.T("Create a ClusterRoleBinding for a particular ClusterRole"), Long: clusterRoleBindingLong, Example: clusterRoleBindingExample, diff --git a/pkg/kubectl/cmd/create_configmap.go b/pkg/kubectl/cmd/create_configmap.go index b9f17adede8..cb80b83e9f9 100644 --- a/pkg/kubectl/cmd/create_configmap.go +++ b/pkg/kubectl/cmd/create_configmap.go @@ -60,11 +60,12 @@ var ( // ConfigMap is a command to ease creating ConfigMaps. func NewCmdCreateConfigMap(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]", - Aliases: []string{"cm"}, - Short: i18n.T("Create a configmap from a local file, directory or literal value"), - Long: configMapLong, - Example: configMapExample, + Use: "configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]", + DisableFlagsInUseLine: true, + Aliases: []string{"cm"}, + Short: i18n.T("Create a configmap from a local file, directory or literal value"), + Long: configMapLong, + Example: configMapExample, Run: func(cmd *cobra.Command, args []string) { err := CreateConfigMap(f, cmdOut, cmd, args) cmdutil.CheckErr(err) diff --git a/pkg/kubectl/cmd/create_deployment.go b/pkg/kubectl/cmd/create_deployment.go index 08e1c9dec0d..cde03d1b76c 100644 --- a/pkg/kubectl/cmd/create_deployment.go +++ b/pkg/kubectl/cmd/create_deployment.go @@ -41,11 +41,12 @@ var ( // Note that this command overlaps significantly with the `kubectl run` command. func NewCmdCreateDeployment(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "deployment NAME --image=image [--dry-run]", - Aliases: []string{"deploy"}, - Short: i18n.T("Create a deployment with the specified name."), - Long: deploymentLong, - Example: deploymentExample, + Use: "deployment NAME --image=image [--dry-run]", + DisableFlagsInUseLine: true, + Aliases: []string{"deploy"}, + Short: i18n.T("Create a deployment with the specified name."), + Long: deploymentLong, + Example: deploymentExample, Run: func(cmd *cobra.Command, args []string) { err := createDeployment(f, cmdOut, cmdErr, cmd, args) cmdutil.CheckErr(err) diff --git a/pkg/kubectl/cmd/create_namespace.go b/pkg/kubectl/cmd/create_namespace.go index 955cf1f84af..7a0f2ec327f 100644 --- a/pkg/kubectl/cmd/create_namespace.go +++ b/pkg/kubectl/cmd/create_namespace.go @@ -39,11 +39,12 @@ var ( // NewCmdCreateNamespace is a macro command to create a new namespace func NewCmdCreateNamespace(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "namespace NAME [--dry-run]", - Aliases: []string{"ns"}, - Short: i18n.T("Create a namespace with the specified name"), - Long: namespaceLong, - Example: namespaceExample, + Use: "namespace NAME [--dry-run]", + DisableFlagsInUseLine: true, + Aliases: []string{"ns"}, + Short: i18n.T("Create a namespace with the specified name"), + Long: namespaceLong, + Example: namespaceExample, Run: func(cmd *cobra.Command, args []string) { err := CreateNamespace(f, cmdOut, cmd, args) cmdutil.CheckErr(err) diff --git a/pkg/kubectl/cmd/create_pdb.go b/pkg/kubectl/cmd/create_pdb.go index 310a55e275b..39938f64152 100644 --- a/pkg/kubectl/cmd/create_pdb.go +++ b/pkg/kubectl/cmd/create_pdb.go @@ -44,11 +44,12 @@ var ( // NewCmdCreatePodDisruptionBudget is a macro command to create a new pod disruption budget. func NewCmdCreatePodDisruptionBudget(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "poddisruptionbudget NAME --selector=SELECTOR --min-available=N [--dry-run]", - Aliases: []string{"pdb"}, - Short: i18n.T("Create a pod disruption budget with the specified name."), - Long: pdbLong, - Example: pdbExample, + Use: "poddisruptionbudget NAME --selector=SELECTOR --min-available=N [--dry-run]", + DisableFlagsInUseLine: true, + Aliases: []string{"pdb"}, + Short: i18n.T("Create a pod disruption budget with the specified name."), + Long: pdbLong, + Example: pdbExample, Run: func(cmd *cobra.Command, args []string) { err := CreatePodDisruptionBudget(f, cmdOut, cmd, args) cmdutil.CheckErr(err) diff --git a/pkg/kubectl/cmd/create_priorityclass.go b/pkg/kubectl/cmd/create_priorityclass.go index 7f3561ae614..99c17866732 100644 --- a/pkg/kubectl/cmd/create_priorityclass.go +++ b/pkg/kubectl/cmd/create_priorityclass.go @@ -42,11 +42,12 @@ var ( // NewCmdCreatePriorityClass is a macro command to create a new priorityClass. func NewCmdCreatePriorityClass(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "priorityclass NAME --value=VALUE --global-default=BOOL [--dry-run]", - Aliases: []string{"pc"}, - Short: i18n.T("Create a priorityclass with the specified name."), - Long: pcLong, - Example: pcExample, + Use: "priorityclass NAME --value=VALUE --global-default=BOOL [--dry-run]", + DisableFlagsInUseLine: true, + Aliases: []string{"pc"}, + Short: i18n.T("Create a priorityclass with the specified name."), + Long: pcLong, + Example: pcExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(CreatePriorityClass(f, cmdOut, cmd, args)) }, diff --git a/pkg/kubectl/cmd/create_quota.go b/pkg/kubectl/cmd/create_quota.go index cbd5dc741d3..48eed9993a1 100644 --- a/pkg/kubectl/cmd/create_quota.go +++ b/pkg/kubectl/cmd/create_quota.go @@ -42,11 +42,12 @@ var ( // NewCmdCreateQuota is a macro command to create a new quota func NewCmdCreateQuota(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "quota NAME [--hard=key1=value1,key2=value2] [--scopes=Scope1,Scope2] [--dry-run=bool]", - Aliases: []string{"resourcequota"}, - Short: i18n.T("Create a quota with the specified name."), - Long: quotaLong, - Example: quotaExample, + Use: "quota NAME [--hard=key1=value1,key2=value2] [--scopes=Scope1,Scope2] [--dry-run=bool]", + DisableFlagsInUseLine: true, + Aliases: []string{"resourcequota"}, + Short: i18n.T("Create a quota with the specified name."), + Long: quotaLong, + Example: quotaExample, Run: func(cmd *cobra.Command, args []string) { err := CreateQuota(f, cmdOut, cmd, args) cmdutil.CheckErr(err) diff --git a/pkg/kubectl/cmd/create_role.go b/pkg/kubectl/cmd/create_role.go index 0a881e779c7..1710a4de32e 100644 --- a/pkg/kubectl/cmd/create_role.go +++ b/pkg/kubectl/cmd/create_role.go @@ -121,7 +121,8 @@ func NewCmdCreateRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { Out: cmdOut, } cmd := &cobra.Command{ - Use: "role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run]", + Use: "role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run]", + DisableFlagsInUseLine: true, Short: roleLong, Long: roleLong, Example: roleExample, diff --git a/pkg/kubectl/cmd/create_rolebinding.go b/pkg/kubectl/cmd/create_rolebinding.go index 35cb8dc02c8..49eca5706f5 100644 --- a/pkg/kubectl/cmd/create_rolebinding.go +++ b/pkg/kubectl/cmd/create_rolebinding.go @@ -39,7 +39,8 @@ var ( // RoleBinding is a command to ease creating RoleBindings. func NewCmdCreateRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", + Use: "rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", + DisableFlagsInUseLine: true, Short: i18n.T("Create a RoleBinding for a particular Role or ClusterRole"), Long: roleBindingLong, Example: roleBindingExample, diff --git a/pkg/kubectl/cmd/create_secret.go b/pkg/kubectl/cmd/create_secret.go index f49048bf9a3..5a5b99015b6 100644 --- a/pkg/kubectl/cmd/create_secret.go +++ b/pkg/kubectl/cmd/create_secret.go @@ -76,7 +76,8 @@ var ( // NewCmdCreateSecretGeneric is a command to create generic secrets from files, directories, or literal values func NewCmdCreateSecretGeneric(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]", + Use: "generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]", + DisableFlagsInUseLine: true, Short: i18n.T("Create a secret from a local file, directory or literal value"), Long: secretLong, Example: secretExample, @@ -149,7 +150,8 @@ var ( // NewCmdCreateSecretDockerRegistry is a macro command for creating secrets to work with Docker registries func NewCmdCreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "docker-registry NAME --docker-username=user --docker-password=password --docker-email=email [--docker-server=string] [--from-literal=key1=value1] [--dry-run]", + Use: "docker-registry NAME --docker-username=user --docker-password=password --docker-email=email [--docker-server=string] [--from-literal=key1=value1] [--dry-run]", + DisableFlagsInUseLine: true, Short: i18n.T("Create a secret for use with a Docker registry"), Long: secretForDockerRegistryLong, Example: secretForDockerRegistryExample, @@ -223,7 +225,8 @@ var ( // NewCmdCreateSecretTLS is a macro command for creating secrets to work with Docker registries func NewCmdCreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "tls NAME --cert=path/to/cert/file --key=path/to/key/file [--dry-run]", + Use: "tls NAME --cert=path/to/cert/file --key=path/to/key/file [--dry-run]", + DisableFlagsInUseLine: true, Short: i18n.T("Create a TLS secret"), Long: secretForTLSLong, Example: secretForTLSExample, diff --git a/pkg/kubectl/cmd/create_service.go b/pkg/kubectl/cmd/create_service.go index 52496a03b5e..a35d210de27 100644 --- a/pkg/kubectl/cmd/create_service.go +++ b/pkg/kubectl/cmd/create_service.go @@ -64,7 +64,8 @@ func addPortFlags(cmd *cobra.Command) { // NewCmdCreateServiceClusterIP is a command to create a ClusterIP service func NewCmdCreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "clusterip NAME [--tcp=:] [--dry-run]", + Use: "clusterip NAME [--tcp=:] [--dry-run]", + DisableFlagsInUseLine: true, Short: i18n.T("Create a ClusterIP service."), Long: serviceClusterIPLong, Example: serviceClusterIPExample, @@ -124,7 +125,8 @@ var ( // NewCmdCreateServiceNodePort is a macro command for creating a NodePort service func NewCmdCreateServiceNodePort(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "nodeport NAME [--tcp=port:targetPort] [--dry-run]", + Use: "nodeport NAME [--tcp=port:targetPort] [--dry-run]", + DisableFlagsInUseLine: true, Short: i18n.T("Create a NodePort service."), Long: serviceNodePortLong, Example: serviceNodePortExample, @@ -181,7 +183,8 @@ var ( // NewCmdCreateServiceLoadBalancer is a macro command for creating a LoadBalancer service func NewCmdCreateServiceLoadBalancer(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "loadbalancer NAME [--tcp=port:targetPort] [--dry-run]", + Use: "loadbalancer NAME [--tcp=port:targetPort] [--dry-run]", + DisableFlagsInUseLine: true, Short: i18n.T("Create a LoadBalancer service."), Long: serviceLoadBalancerLong, Example: serviceLoadBalancerExample, @@ -240,7 +243,8 @@ var ( // NewCmdCreateServiceExternalName is a macro command for creating an ExternalName service func NewCmdCreateServiceExternalName(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "externalname NAME --external-name external.name [--dry-run]", + Use: "externalname NAME --external-name external.name [--dry-run]", + DisableFlagsInUseLine: true, Short: i18n.T("Create an ExternalName service."), Long: serviceExternalNameLong, Example: serviceExternalNameExample, diff --git a/pkg/kubectl/cmd/create_serviceaccount.go b/pkg/kubectl/cmd/create_serviceaccount.go index 99dfde9dd1a..c4302c64cc7 100644 --- a/pkg/kubectl/cmd/create_serviceaccount.go +++ b/pkg/kubectl/cmd/create_serviceaccount.go @@ -39,11 +39,12 @@ var ( // NewCmdCreateServiceAccount is a macro command to create a new service account func NewCmdCreateServiceAccount(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "serviceaccount NAME [--dry-run]", - Aliases: []string{"sa"}, - Short: i18n.T("Create a service account with the specified name"), - Long: serviceAccountLong, - Example: serviceAccountExample, + Use: "serviceaccount NAME [--dry-run]", + DisableFlagsInUseLine: true, + Aliases: []string{"sa"}, + Short: i18n.T("Create a service account with the specified name"), + Long: serviceAccountLong, + Example: serviceAccountExample, Run: func(cmd *cobra.Command, args []string) { err := CreateServiceAccount(f, cmdOut, cmd, args) cmdutil.CheckErr(err) diff --git a/pkg/kubectl/cmd/delete.go b/pkg/kubectl/cmd/delete.go index 80a9bd49920..60ac7d5b43c 100644 --- a/pkg/kubectl/cmd/delete.go +++ b/pkg/kubectl/cmd/delete.go @@ -127,7 +127,8 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])", + Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])", + DisableFlagsInUseLine: true, Short: i18n.T("Delete resources by filenames, stdin, resources and names, or by resources and label selector"), Long: delete_long, Example: delete_example, diff --git a/pkg/kubectl/cmd/delete_test.go b/pkg/kubectl/cmd/delete_test.go index 5b78ba09761..220dd288909 100644 --- a/pkg/kubectl/cmd/delete_test.go +++ b/pkg/kubectl/cmd/delete_test.go @@ -44,6 +44,7 @@ var unstructuredSerializer = dynamic.ContentConfig().NegotiatedSerializer var fakecmd = &cobra.Command{ Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])", + DisableFlagsInUseLine: true, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) }, diff --git a/pkg/kubectl/cmd/describe.go b/pkg/kubectl/cmd/describe.go index f77304ec599..f1b75ccd0e6 100644 --- a/pkg/kubectl/cmd/describe.go +++ b/pkg/kubectl/cmd/describe.go @@ -79,7 +79,8 @@ func NewCmdDescribe(f cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command { argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ - Use: "describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)", + Use: "describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)", + DisableFlagsInUseLine: true, Short: i18n.T("Show details of a specific resource or group of resources"), Long: describeLong + "\n\n" + cmdutil.ValidResourceTypeList(f), Example: describeExample, diff --git a/pkg/kubectl/cmd/describe_test.go b/pkg/kubectl/cmd/describe_test.go index 2c3ec49c5c8..5c068609d35 100644 --- a/pkg/kubectl/cmd/describe_test.go +++ b/pkg/kubectl/cmd/describe_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "net/http" + "strings" "testing" "k8s.io/client-go/rest/fake" @@ -168,3 +169,30 @@ func TestDescribeObjectSkipEvents(t *testing.T) { t.Errorf("ShowEvents = false expected, got ShowEvents = %v", d.Settings.ShowEvents) } } + +func TestDescribeHelpMessage(t *testing.T) { + f, _, _, _ := cmdtesting.NewAPIFactory() + + buf := bytes.NewBuffer([]byte{}) + buferr := bytes.NewBuffer([]byte{}) + cmd := NewCmdDescribe(f, buf, buferr) + cmd.SetArgs([]string{"-h"}) + cmd.SetOutput(buf) + _, err := cmd.ExecuteC() + + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + got := buf.String() + + expected := `describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)` + if !strings.Contains(got, expected) { + t.Errorf("Expected to contain: \n %v\nGot:\n %v\n", expected, got) + } + + unexpected := `describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME) [flags]` + if strings.Contains(got, unexpected) { + t.Errorf("Expected not to contain: \n %v\nGot:\n %v\n", unexpected, got) + } +} diff --git a/pkg/kubectl/cmd/diff.go b/pkg/kubectl/cmd/diff.go index e536069952d..422ec70dc36 100644 --- a/pkg/kubectl/cmd/diff.go +++ b/pkg/kubectl/cmd/diff.go @@ -109,7 +109,8 @@ func NewCmdDiff(f cmdutil.Factory, stdout, stderr io.Writer) *cobra.Command { Stderr: stderr, } cmd := &cobra.Command{ - Use: "diff -f FILENAME", + Use: "diff -f FILENAME", + DisableFlagsInUseLine: true, Short: i18n.T("Diff different versions of configurations"), Long: diffLong, Example: diffExample, diff --git a/pkg/kubectl/cmd/drain.go b/pkg/kubectl/cmd/drain.go index ba5ae1f1a72..3226d54a646 100644 --- a/pkg/kubectl/cmd/drain.go +++ b/pkg/kubectl/cmd/drain.go @@ -105,7 +105,8 @@ func NewCmdCordon(f cmdutil.Factory, out io.Writer) *cobra.Command { options := &DrainOptions{Factory: f, Out: out} cmd := &cobra.Command{ - Use: "cordon NODE", + Use: "cordon NODE", + DisableFlagsInUseLine: true, Short: i18n.T("Mark node as unschedulable"), Long: cordon_long, Example: cordon_example, @@ -132,7 +133,8 @@ func NewCmdUncordon(f cmdutil.Factory, out io.Writer) *cobra.Command { options := &DrainOptions{Factory: f, Out: out} cmd := &cobra.Command{ - Use: "uncordon NODE", + Use: "uncordon NODE", + DisableFlagsInUseLine: true, Short: i18n.T("Mark node as schedulable"), Long: uncordon_long, Example: uncordon_example, @@ -184,7 +186,8 @@ func NewCmdDrain(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { options := &DrainOptions{Factory: f, Out: out, ErrOut: errOut, backOff: clockwork.NewRealClock()} cmd := &cobra.Command{ - Use: "drain NODE", + Use: "drain NODE", + DisableFlagsInUseLine: true, Short: i18n.T("Drain node in preparation for maintenance"), Long: drain_long, Example: drain_example, diff --git a/pkg/kubectl/cmd/edit.go b/pkg/kubectl/cmd/edit.go index 11ef23c6bd5..1883c11895c 100644 --- a/pkg/kubectl/cmd/edit.go +++ b/pkg/kubectl/cmd/edit.go @@ -87,7 +87,8 @@ func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "edit (RESOURCE/NAME | -f FILENAME)", + Use: "edit (RESOURCE/NAME | -f FILENAME)", + DisableFlagsInUseLine: true, Short: i18n.T("Edit a resource on the server"), Long: editLong, Example: fmt.Sprintf(editExample), diff --git a/pkg/kubectl/cmd/exec.go b/pkg/kubectl/cmd/exec.go index cca3d61a928..e13675029bb 100644 --- a/pkg/kubectl/cmd/exec.go +++ b/pkg/kubectl/cmd/exec.go @@ -73,7 +73,8 @@ func NewCmdExec(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c Executor: &DefaultRemoteExecutor{}, } cmd := &cobra.Command{ - Use: "exec POD [-c CONTAINER] -- COMMAND [args...]", + Use: "exec POD [-c CONTAINER] -- COMMAND [args...]", + DisableFlagsInUseLine: true, Short: i18n.T("Execute a command in a container"), Long: "Execute a command in a container.", Example: exec_example, diff --git a/pkg/kubectl/cmd/explain.go b/pkg/kubectl/cmd/explain.go index d1ecf3d65d4..47472c3c466 100644 --- a/pkg/kubectl/cmd/explain.go +++ b/pkg/kubectl/cmd/explain.go @@ -53,7 +53,8 @@ var ( // NewCmdExplain returns a cobra command for swagger docs func NewCmdExplain(f cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "explain RESOURCE", + Use: "explain RESOURCE", + DisableFlagsInUseLine: true, Short: i18n.T("Documentation of resources"), Long: explainLong + "\n\n" + cmdutil.ValidResourceTypeList(f), Example: explainExamples, diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index ed84c1d76b7..51ccd43225d 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -83,7 +83,8 @@ func NewCmdExposeService(f cmdutil.Factory, out io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UDP] [--target-port=number-or-name] [--name=name] [--external-ip=external-ip-of-service] [--type=type]", + Use: "expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UDP] [--target-port=number-or-name] [--name=name] [--external-ip=external-ip-of-service] [--type=type]", + DisableFlagsInUseLine: true, Short: i18n.T("Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service"), Long: exposeLong, Example: exposeExample, diff --git a/pkg/kubectl/cmd/help.go b/pkg/kubectl/cmd/help.go index 569abb9fd88..783a87c64db 100644 --- a/pkg/kubectl/cmd/help.go +++ b/pkg/kubectl/cmd/help.go @@ -31,7 +31,8 @@ var helpLong = templates.LongDesc(i18n.T(` func NewCmdHelp() *cobra.Command { cmd := &cobra.Command{ - Use: "help [command] | STRING_TO_SEARCH", + Use: "help [command] | STRING_TO_SEARCH", + DisableFlagsInUseLine: true, Short: i18n.T("Help about any command"), Long: helpLong, diff --git a/pkg/kubectl/cmd/label.go b/pkg/kubectl/cmd/label.go index 786fbe6afcb..32574853234 100644 --- a/pkg/kubectl/cmd/label.go +++ b/pkg/kubectl/cmd/label.go @@ -111,7 +111,8 @@ func NewCmdLabel(f cmdutil.Factory, out io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]", + Use: "label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]", + DisableFlagsInUseLine: true, Short: i18n.T("Update the labels on a resource"), Long: fmt.Sprintf(labelLong, validation.LabelValueMaxLength), Example: labelExample, diff --git a/pkg/kubectl/cmd/logs.go b/pkg/kubectl/cmd/logs.go index cccceb154bc..8091cf8251a 100644 --- a/pkg/kubectl/cmd/logs.go +++ b/pkg/kubectl/cmd/logs.go @@ -89,7 +89,8 @@ type LogsOptions struct { func NewCmdLogs(f cmdutil.Factory, out io.Writer) *cobra.Command { o := &LogsOptions{} cmd := &cobra.Command{ - Use: "logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER]", + Use: "logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER]", + DisableFlagsInUseLine: true, Short: i18n.T("Print the logs for a container in a pod"), Long: "Print the logs for a container in a pod or specified resource. If the pod has only one container, the container name is optional.", Example: logsExample, diff --git a/pkg/kubectl/cmd/patch.go b/pkg/kubectl/cmd/patch.go index 325c2584722..daf67ef56bb 100644 --- a/pkg/kubectl/cmd/patch.go +++ b/pkg/kubectl/cmd/patch.go @@ -95,7 +95,8 @@ func NewCmdPatch(f cmdutil.Factory, out io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "patch (-f FILENAME | TYPE NAME) -p PATCH", + Use: "patch (-f FILENAME | TYPE NAME) -p PATCH", + DisableFlagsInUseLine: true, Short: i18n.T("Update field(s) of a resource using strategic merge patch"), Long: patchLong, Example: patchExample, diff --git a/pkg/kubectl/cmd/plugin.go b/pkg/kubectl/cmd/plugin.go index b69e7a89c68..d34e78733a4 100644 --- a/pkg/kubectl/cmd/plugin.go +++ b/pkg/kubectl/cmd/plugin.go @@ -50,7 +50,8 @@ func NewCmdPlugin(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Co } cmd := &cobra.Command{ - Use: "plugin NAME", + Use: "plugin NAME", + DisableFlagsInUseLine: true, Short: i18n.T("Runs a command-line plugin"), Long: plugin_long, Run: func(cmd *cobra.Command, args []string) { diff --git a/pkg/kubectl/cmd/portforward.go b/pkg/kubectl/cmd/portforward.go index cedb93bb232..cf39bf637ab 100644 --- a/pkg/kubectl/cmd/portforward.go +++ b/pkg/kubectl/cmd/portforward.go @@ -70,7 +70,8 @@ func NewCmdPortForward(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Comma }, } cmd := &cobra.Command{ - Use: "port-forward POD [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N]", + Use: "port-forward POD [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N]", + DisableFlagsInUseLine: true, Short: i18n.T("Forward one or more local ports to a pod"), Long: "Forward one or more local ports to a pod.", Example: portforwardExample, diff --git a/pkg/kubectl/cmd/proxy.go b/pkg/kubectl/cmd/proxy.go index 7bc82ec7f45..027dfbf1ee8 100644 --- a/pkg/kubectl/cmd/proxy.go +++ b/pkg/kubectl/cmd/proxy.go @@ -71,7 +71,8 @@ var ( func NewCmdProxy(f cmdutil.Factory, out io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "proxy [--port=PORT] [--www=static-dir] [--www-prefix=prefix] [--api-prefix=prefix]", + Use: "proxy [--port=PORT] [--www=static-dir] [--www-prefix=prefix] [--api-prefix=prefix]", + DisableFlagsInUseLine: true, Short: i18n.T("Run a proxy to the Kubernetes API server"), Long: proxyLong, Example: proxyExample, diff --git a/pkg/kubectl/cmd/replace.go b/pkg/kubectl/cmd/replace.go index 16b80ae3247..fe75e2b211b 100644 --- a/pkg/kubectl/cmd/replace.go +++ b/pkg/kubectl/cmd/replace.go @@ -64,7 +64,8 @@ func NewCmdReplace(f cmdutil.Factory, out io.Writer) *cobra.Command { options := &resource.FilenameOptions{} cmd := &cobra.Command{ - Use: "replace -f FILENAME", + Use: "replace -f FILENAME", + DisableFlagsInUseLine: true, Short: i18n.T("Replace a resource by filename or stdin"), Long: replaceLong, Example: replaceExample, diff --git a/pkg/kubectl/cmd/resource/get.go b/pkg/kubectl/cmd/resource/get.go index 4013cb42874..386c1eb97ac 100644 --- a/pkg/kubectl/cmd/resource/get.go +++ b/pkg/kubectl/cmd/resource/get.go @@ -139,7 +139,8 @@ func NewCmdGet(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comman } cmd := &cobra.Command{ - Use: "get [(-o|--output=)json|yaml|wide|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=...] (TYPE [NAME | -l label] | TYPE/NAME ...) [flags]", + Use: "get [(-o|--output=)json|yaml|wide|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=...] (TYPE [NAME | -l label] | TYPE/NAME ...) [flags]", + DisableFlagsInUseLine: true, Short: i18n.T("Display one or many resources"), Long: getLong + "\n\n" + cmdutil.ValidResourceTypeList(f), Example: getExample, diff --git a/pkg/kubectl/cmd/rollingupdate.go b/pkg/kubectl/cmd/rollingupdate.go index 117cacbfb10..e27037e6662 100644 --- a/pkg/kubectl/cmd/rollingupdate.go +++ b/pkg/kubectl/cmd/rollingupdate.go @@ -79,7 +79,8 @@ func NewCmdRollingUpdate(f cmdutil.Factory, out io.Writer) *cobra.Command { options := &resource.FilenameOptions{} cmd := &cobra.Command{ - Use: "rolling-update OLD_CONTROLLER_NAME ([NEW_CONTROLLER_NAME] --image=NEW_CONTAINER_IMAGE | -f NEW_CONTROLLER_SPEC)", + Use: "rolling-update OLD_CONTROLLER_NAME ([NEW_CONTROLLER_NAME] --image=NEW_CONTAINER_IMAGE | -f NEW_CONTROLLER_SPEC)", + DisableFlagsInUseLine: true, Short: i18n.T("Perform a rolling update of the given ReplicationController"), Long: rollingUpdateLong, Example: rollingUpdateExample, @@ -93,9 +94,7 @@ func NewCmdRollingUpdate(f cmdutil.Factory, out io.Writer) *cobra.Command { cmd.Flags().Duration("timeout", timeout, `Max time to wait for a replication controller to update before giving up. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`) usage := "Filename or URL to file to use to create the new replication controller." kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmd.MarkFlagRequired("filename") cmd.Flags().String("image", "", i18n.T("Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f")) - cmd.MarkFlagRequired("image") cmd.Flags().String("deployment-label-key", "deployment", i18n.T("The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise")) cmd.Flags().String("container", "", i18n.T("Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod")) cmd.Flags().String("image-pull-policy", "", i18n.T("Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.")) diff --git a/pkg/kubectl/cmd/rollout/rollout.go b/pkg/kubectl/cmd/rollout/rollout.go index a65ed4d8df5..941b585c11d 100644 --- a/pkg/kubectl/cmd/rollout/rollout.go +++ b/pkg/kubectl/cmd/rollout/rollout.go @@ -49,7 +49,8 @@ var ( func NewCmdRollout(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "rollout SUBCOMMAND", + Use: "rollout SUBCOMMAND", + DisableFlagsInUseLine: true, Short: i18n.T("Manage the rollout of a resource"), Long: rollout_long, Example: rollout_example, diff --git a/pkg/kubectl/cmd/rollout/rollout_history.go b/pkg/kubectl/cmd/rollout/rollout_history.go index 91b5711f1d2..fb6ccbe90e7 100644 --- a/pkg/kubectl/cmd/rollout/rollout_history.go +++ b/pkg/kubectl/cmd/rollout/rollout_history.go @@ -48,7 +48,8 @@ func NewCmdRolloutHistory(f cmdutil.Factory, out io.Writer) *cobra.Command { argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ - Use: "history (TYPE NAME | TYPE/NAME) [flags]", + Use: "history (TYPE NAME | TYPE/NAME) [flags]", + DisableFlagsInUseLine: true, Short: i18n.T("View rollout history"), Long: history_long, Example: history_example, diff --git a/pkg/kubectl/cmd/rollout/rollout_pause.go b/pkg/kubectl/cmd/rollout/rollout_pause.go index 5a9f3bd4b7f..17b8d3e80ce 100644 --- a/pkg/kubectl/cmd/rollout/rollout_pause.go +++ b/pkg/kubectl/cmd/rollout/rollout_pause.go @@ -71,7 +71,8 @@ func NewCmdRolloutPause(f cmdutil.Factory, out io.Writer) *cobra.Command { argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ - Use: "pause RESOURCE", + Use: "pause RESOURCE", + DisableFlagsInUseLine: true, Short: i18n.T("Mark the provided resource as paused"), Long: pause_long, Example: pause_example, diff --git a/pkg/kubectl/cmd/rollout/rollout_resume.go b/pkg/kubectl/cmd/rollout/rollout_resume.go index 427fac9acfa..3e0d07e9c77 100644 --- a/pkg/kubectl/cmd/rollout/rollout_resume.go +++ b/pkg/kubectl/cmd/rollout/rollout_resume.go @@ -69,7 +69,8 @@ func NewCmdRolloutResume(f cmdutil.Factory, out io.Writer) *cobra.Command { argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ - Use: "resume RESOURCE", + Use: "resume RESOURCE", + DisableFlagsInUseLine: true, Short: i18n.T("Resume a paused resource"), Long: resume_long, Example: resume_example, diff --git a/pkg/kubectl/cmd/rollout/rollout_status.go b/pkg/kubectl/cmd/rollout/rollout_status.go index 6655c7c92f5..4abf6b4ee9e 100644 --- a/pkg/kubectl/cmd/rollout/rollout_status.go +++ b/pkg/kubectl/cmd/rollout/rollout_status.go @@ -54,7 +54,8 @@ func NewCmdRolloutStatus(f cmdutil.Factory, out io.Writer) *cobra.Command { argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ - Use: "status (TYPE NAME | TYPE/NAME) [flags]", + Use: "status (TYPE NAME | TYPE/NAME) [flags]", + DisableFlagsInUseLine: true, Short: i18n.T("Show the status of the rollout"), Long: status_long, Example: status_example, diff --git a/pkg/kubectl/cmd/rollout/rollout_undo.go b/pkg/kubectl/cmd/rollout/rollout_undo.go index fb5c7dc09cc..3eb40ea42a4 100644 --- a/pkg/kubectl/cmd/rollout/rollout_undo.go +++ b/pkg/kubectl/cmd/rollout/rollout_undo.go @@ -69,7 +69,8 @@ func NewCmdRolloutUndo(f cmdutil.Factory, out io.Writer) *cobra.Command { argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ - Use: "undo (TYPE NAME | TYPE/NAME) [flags]", + Use: "undo (TYPE NAME | TYPE/NAME) [flags]", + DisableFlagsInUseLine: true, Short: i18n.T("Undo a previous rollout"), Long: undo_long, Example: undo_example, diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index 087e8d40b85..516624e8666 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -96,7 +96,8 @@ type RunObject struct { func NewCmdRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "run NAME --image=image [--env=\"key=value\"] [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json] [--command] -- [COMMAND] [args...]", + Use: "run NAME --image=image [--env=\"key=value\"] [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json] [--command] -- [COMMAND] [args...]", + DisableFlagsInUseLine: true, Short: i18n.T("Run a particular image on the cluster"), Long: runLong, Example: runExample, diff --git a/pkg/kubectl/cmd/scale.go b/pkg/kubectl/cmd/scale.go index be722abc962..90233f499f6 100644 --- a/pkg/kubectl/cmd/scale.go +++ b/pkg/kubectl/cmd/scale.go @@ -64,7 +64,8 @@ func NewCmdScale(f cmdutil.Factory, out io.Writer) *cobra.Command { argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ - Use: "scale [--resource-version=version] [--current-replicas=count] --replicas=COUNT (-f FILENAME | TYPE NAME)", + Use: "scale [--resource-version=version] [--current-replicas=count] --replicas=COUNT (-f FILENAME | TYPE NAME)", + DisableFlagsInUseLine: true, Short: i18n.T("Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job"), Long: scaleLong, Example: scaleExample, diff --git a/pkg/kubectl/cmd/set/set.go b/pkg/kubectl/cmd/set/set.go index e905c3fb5b7..dfc69c1049d 100644 --- a/pkg/kubectl/cmd/set/set.go +++ b/pkg/kubectl/cmd/set/set.go @@ -34,7 +34,8 @@ var ( func NewCmdSet(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command { cmd := &cobra.Command{ - Use: "set SUBCOMMAND", + Use: "set SUBCOMMAND", + DisableFlagsInUseLine: true, Short: i18n.T("Set specific features on objects"), Long: set_long, Run: cmdutil.DefaultSubCommandRun(err), diff --git a/pkg/kubectl/cmd/set/set_env.go b/pkg/kubectl/cmd/set/set_env.go index 36c3b810050..bb7234dbbb7 100644 --- a/pkg/kubectl/cmd/set/set_env.go +++ b/pkg/kubectl/cmd/set/set_env.go @@ -135,7 +135,8 @@ func NewCmdEnv(f cmdutil.Factory, in io.Reader, out, errout io.Writer) *cobra.Co In: in, } cmd := &cobra.Command{ - Use: "env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N", + Use: "env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N", + DisableFlagsInUseLine: true, Short: "Update environment variables on a pod template", Long: envLong, Example: fmt.Sprintf(envExample), diff --git a/pkg/kubectl/cmd/set/set_image.go b/pkg/kubectl/cmd/set/set_image.go index 09bff8302ee..4f940cf8804 100644 --- a/pkg/kubectl/cmd/set/set_image.go +++ b/pkg/kubectl/cmd/set/set_image.go @@ -92,7 +92,8 @@ func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N", + Use: "image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N", + DisableFlagsInUseLine: true, Short: i18n.T("Update image of a pod template"), Long: image_long, Example: image_example, diff --git a/pkg/kubectl/cmd/set/set_resources.go b/pkg/kubectl/cmd/set/set_resources.go index 5284e52ac58..a6b85994f2a 100644 --- a/pkg/kubectl/cmd/set/set_resources.go +++ b/pkg/kubectl/cmd/set/set_resources.go @@ -98,7 +98,8 @@ func NewCmdResources(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra. } cmd := &cobra.Command{ - Use: "resources (-f FILENAME | TYPE NAME) ([--limits=LIMITS & --requests=REQUESTS]", + Use: "resources (-f FILENAME | TYPE NAME) ([--limits=LIMITS & --requests=REQUESTS]", + DisableFlagsInUseLine: true, Short: i18n.T("Update resource requests/limits on objects with pod templates"), Long: fmt.Sprintf(resources_long, strings.Join(resourceTypesWithPodTemplate, ", ")), Example: resources_example, diff --git a/pkg/kubectl/cmd/set/set_selector.go b/pkg/kubectl/cmd/set/set_selector.go index 3579f63cf4b..8dca8f45751 100644 --- a/pkg/kubectl/cmd/set/set_selector.go +++ b/pkg/kubectl/cmd/set/set_selector.go @@ -79,7 +79,8 @@ func NewCmdSelector(f cmdutil.Factory, out io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-version=version]", + Use: "selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-version=version]", + DisableFlagsInUseLine: true, Short: i18n.T("Set the selector on a resource"), Long: fmt.Sprintf(selectorLong, validation.LabelValueMaxLength), Example: selectorExample, diff --git a/pkg/kubectl/cmd/set/set_serviceaccount.go b/pkg/kubectl/cmd/set/set_serviceaccount.go index 65ac0d166c3..535fd32b64b 100644 --- a/pkg/kubectl/cmd/set/set_serviceaccount.go +++ b/pkg/kubectl/cmd/set/set_serviceaccount.go @@ -83,11 +83,12 @@ func NewCmdServiceAccount(f cmdutil.Factory, out, err io.Writer) *cobra.Command } cmd := &cobra.Command{ - Use: "serviceaccount (-f FILENAME | TYPE NAME) SERVICE_ACCOUNT", - Aliases: []string{"sa"}, - Short: i18n.T("Update ServiceAccount of a resource"), - Long: serviceaccountLong, - Example: serviceaccountExample, + Use: "serviceaccount (-f FILENAME | TYPE NAME) SERVICE_ACCOUNT", + DisableFlagsInUseLine: true, + Aliases: []string{"sa"}, + Short: i18n.T("Update ServiceAccount of a resource"), + Long: serviceaccountLong, + Example: serviceaccountExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(saConfig.Complete(f, cmd, args)) cmdutil.CheckErr(saConfig.Run()) diff --git a/pkg/kubectl/cmd/set/set_subject.go b/pkg/kubectl/cmd/set/set_subject.go index c71a664b00e..3e8c204de65 100644 --- a/pkg/kubectl/cmd/set/set_subject.go +++ b/pkg/kubectl/cmd/set/set_subject.go @@ -84,7 +84,8 @@ func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Co } cmd := &cobra.Command{ - Use: "subject (-f FILENAME | TYPE NAME) [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", + Use: "subject (-f FILENAME | TYPE NAME) [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]", + DisableFlagsInUseLine: true, Short: i18n.T("Update User, Group or ServiceAccount in a RoleBinding/ClusterRoleBinding"), Long: subject_long, Example: subject_example, diff --git a/pkg/kubectl/cmd/taint.go b/pkg/kubectl/cmd/taint.go index 239aba71634..9ef8bc10c14 100644 --- a/pkg/kubectl/cmd/taint.go +++ b/pkg/kubectl/cmd/taint.go @@ -85,7 +85,8 @@ func NewCmdTaint(f cmdutil.Factory, out io.Writer) *cobra.Command { argAliases := kubectl.ResourceAliases(validArgs) cmd := &cobra.Command{ - Use: "taint NODE NAME KEY_1=VAL_1:TAINT_EFFECT_1 ... KEY_N=VAL_N:TAINT_EFFECT_N", + Use: "taint NODE NAME KEY_1=VAL_1:TAINT_EFFECT_1 ... KEY_N=VAL_N:TAINT_EFFECT_N", + DisableFlagsInUseLine: true, Short: i18n.T("Update the taints on one or more nodes"), Long: fmt.Sprintf(taintLong, validation.DNS1123SubdomainMaxLength, validation.LabelValueMaxLength), Example: taintExample, diff --git a/pkg/kubectl/cmd/top_node.go b/pkg/kubectl/cmd/top_node.go index dace2918d69..610a542b7f3 100644 --- a/pkg/kubectl/cmd/top_node.go +++ b/pkg/kubectl/cmd/top_node.go @@ -89,7 +89,8 @@ func NewCmdTopNode(f cmdutil.Factory, options *TopNodeOptions, out io.Writer) *c } cmd := &cobra.Command{ - Use: "node [NAME | -l label]", + Use: "node [NAME | -l label]", + DisableFlagsInUseLine: true, Short: i18n.T("Display Resource (CPU/Memory/Storage) usage of nodes"), Long: topNodeLong, Example: topNodeExample, diff --git a/pkg/kubectl/cmd/top_pod.go b/pkg/kubectl/cmd/top_pod.go index 2ffdc6dff8e..669f95cd3cf 100644 --- a/pkg/kubectl/cmd/top_pod.go +++ b/pkg/kubectl/cmd/top_pod.go @@ -78,7 +78,8 @@ func NewCmdTopPod(f cmdutil.Factory, options *TopPodOptions, out io.Writer) *cob } cmd := &cobra.Command{ - Use: "pod [NAME | -l label]", + Use: "pod [NAME | -l label]", + DisableFlagsInUseLine: true, Short: i18n.T("Display Resource (CPU/Memory/Storage) usage of pods"), Long: topPodLong, Example: topPodExample, From 45d21ee36b1a49e3b86d99810a7875b7496da30a Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Mon, 8 Jan 2018 14:01:33 +0100 Subject: [PATCH 09/58] Fixed TearDown of NFS with root squash. NFS plugin should not use IsLikelyNotMountPoint(), as it uses lstat() / stat() to determine if the NFS volume is still mounted - NFS server may use root_squash and kubelet may not be allowed to do lstat() / stat() there. It must use slower IsNotMountPoint() instead, including TearDown() function. --- pkg/util/mount/mount.go | 7 +++++++ pkg/volume/nfs/nfs.go | 11 +++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/pkg/util/mount/mount.go b/pkg/util/mount/mount.go index 953b571900a..d2069ec7861 100644 --- a/pkg/util/mount/mount.go +++ b/pkg/util/mount/mount.go @@ -19,6 +19,7 @@ limitations under the License. package mount import ( + "os" "path/filepath" ) @@ -208,6 +209,12 @@ func IsNotMountPoint(mounter Interface, file string) (bool, error) { // IsLikelyNotMountPoint provides a quick check // to determine whether file IS A mountpoint notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file) + if notMntErr != nil && os.IsPermission(notMntErr) { + // We were not allowed to do the simple stat() check, e.g. on NFS with + // root_squash. Fall back to /proc/mounts check below. + notMnt = true + notMntErr = nil + } if notMntErr != nil { return notMnt, notMntErr } diff --git a/pkg/volume/nfs/nfs.go b/pkg/volume/nfs/nfs.go index f61fbd25944..26db61d729a 100644 --- a/pkg/volume/nfs/nfs.go +++ b/pkg/volume/nfs/nfs.go @@ -233,7 +233,7 @@ func (b *nfsMounter) SetUp(fsGroup *int64) error { } func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error { - notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) + notMnt, err := b.mounter.IsNotMountPoint(dir) glog.V(4).Infof("NFS mount set up: %s %v %v", dir, !notMnt, err) if err != nil && !os.IsNotExist(err) { return err @@ -252,7 +252,7 @@ func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error { mountOptions := volume.JoinMountOptions(b.mountOptions, options) err = b.mounter.Mount(source, dir, "nfs", mountOptions) if err != nil { - notMnt, mntErr := b.mounter.IsLikelyNotMountPoint(dir) + notMnt, mntErr := b.mounter.IsNotMountPoint(dir) if mntErr != nil { glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr) return err @@ -262,7 +262,7 @@ func (b *nfsMounter) SetUpAt(dir string, fsGroup *int64) error { glog.Errorf("Failed to unmount: %v", mntErr) return err } - notMnt, mntErr := b.mounter.IsLikelyNotMountPoint(dir) + notMnt, mntErr := b.mounter.IsNotMountPoint(dir) if mntErr != nil { glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr) return err @@ -290,7 +290,10 @@ func (c *nfsUnmounter) TearDown() error { } func (c *nfsUnmounter) TearDownAt(dir string) error { - return util.UnmountPath(dir, c.mounter) + // Use extensiveMountPointCheck to consult /proc/mounts. We can't use faster + // IsLikelyNotMountPoint (lstat()), since there may be root_squash on the + // NFS server and kubelet may not be able to do lstat/stat() there. + return util.UnmountMountPoint(dir, c.mounter, true /* extensiveMountPointCheck */) } func getVolumeSource(spec *volume.Spec) (*v1.NFSVolumeSource, bool, error) { From da1eec2853098b2e60b50b14415303d1c8123bc7 Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Mon, 8 Jan 2018 14:19:22 +0100 Subject: [PATCH 10/58] Add jsafrane as util/mount approver. --- pkg/util/mount/OWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/util/mount/OWNERS b/pkg/util/mount/OWNERS index 556119c4471..0c7ea81089b 100644 --- a/pkg/util/mount/OWNERS +++ b/pkg/util/mount/OWNERS @@ -4,4 +4,5 @@ reviewers: approvers: - jingxu97 - saad-ali + - jsafrane From 3a461afaf59085e587a91430db756bc68ff9182b Mon Sep 17 00:00:00 2001 From: Slava Semushin Date: Mon, 8 Jan 2018 15:26:03 +0100 Subject: [PATCH 11/58] pkg/securitycontext/util_test.go(TestAddNoNewPrivileges): update tests. - remove irrelevant test cases - add test case for AllowPrivilegeEscalation: nil - explicitly specify input and expected outcome --- pkg/securitycontext/util_test.go | 45 ++++++++++---------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/pkg/securitycontext/util_test.go b/pkg/securitycontext/util_test.go index 1b89adcd893..5cc3fa71ada 100644 --- a/pkg/securitycontext/util_test.go +++ b/pkg/securitycontext/util_test.go @@ -178,56 +178,39 @@ func TestHasRootRunAsUser(t *testing.T) { } func TestAddNoNewPrivileges(t *testing.T) { - var nonRoot int64 = 1000 - var root int64 = 0 pfalse := false ptrue := true tests := map[string]struct { - sc v1.SecurityContext + sc *v1.SecurityContext expect bool }{ - "allowPrivilegeEscalation nil security context nil": {}, - "allowPrivilegeEscalation nil nonRoot": { - sc: v1.SecurityContext{ - RunAsUser: &nonRoot, - }, + "allowPrivilegeEscalation nil security context nil": { + sc: nil, + expect: false, }, - "allowPrivilegeEscalation nil root": { - sc: v1.SecurityContext{ - RunAsUser: &root, + "allowPrivilegeEscalation nil": { + sc: &v1.SecurityContext{ + AllowPrivilegeEscalation: nil, }, + expect: false, }, - "allowPrivilegeEscalation false nonRoot": { - sc: v1.SecurityContext{ - RunAsUser: &nonRoot, + "allowPrivilegeEscalation false": { + sc: &v1.SecurityContext{ AllowPrivilegeEscalation: &pfalse, }, expect: true, }, - "allowPrivilegeEscalation false root": { - sc: v1.SecurityContext{ - RunAsUser: &root, - AllowPrivilegeEscalation: &pfalse, - }, - expect: true, - }, - "allowPrivilegeEscalation true nonRoot": { - sc: v1.SecurityContext{ - RunAsUser: &nonRoot, - AllowPrivilegeEscalation: &ptrue, - }, - }, - "allowPrivilegeEscalation true root": { - sc: v1.SecurityContext{ - RunAsUser: &root, + "allowPrivilegeEscalation true": { + sc: &v1.SecurityContext{ AllowPrivilegeEscalation: &ptrue, }, + expect: false, }, } for k, v := range tests { - actual := AddNoNewPrivileges(&v.sc) + actual := AddNoNewPrivileges(v.sc) if actual != v.expect { t.Errorf("%s failed, expected %t but received %t", k, v.expect, actual) } From 31ff8c6b9a08d1168502e423bdd3fdbe4f2f729b Mon Sep 17 00:00:00 2001 From: Ryan Phillips Date: Tue, 19 Dec 2017 10:04:23 -0600 Subject: [PATCH 12/58] etcd client: add keepalive --- .../pkg/storage/storagebackend/factory/etcd3.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go b/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go index a5ccbf2fdd4..48bba73110b 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go @@ -17,6 +17,8 @@ limitations under the License. package factory import ( + "time" + "github.com/coreos/etcd/clientv3" "github.com/coreos/etcd/pkg/transport" "golang.org/x/net/context" @@ -27,6 +29,13 @@ import ( "k8s.io/apiserver/pkg/storage/value" ) +// The short keepalive timeout and interval have been chosen to aggressively +// detect a failed etcd server without introducing much overhead. +var ( + keepaliveTime = 30 * time.Second + keepaliveTimeout = 10 * time.Second +) + func newETCD3Storage(c storagebackend.Config) (storage.Interface, DestroyFunc, error) { tlsInfo := transport.TLSInfo{ CertFile: c.CertFile, @@ -43,8 +52,10 @@ func newETCD3Storage(c storagebackend.Config) (storage.Interface, DestroyFunc, e tlsConfig = nil } cfg := clientv3.Config{ - Endpoints: c.ServerList, - TLS: tlsConfig, + DialKeepAliveTime: keepaliveTime, + DialKeepAliveTimeout: keepaliveTimeout, + Endpoints: c.ServerList, + TLS: tlsConfig, } client, err := clientv3.New(cfg) if err != nil { From 032fa206af76666c10fd763d5b6ba4165ba810ff Mon Sep 17 00:00:00 2001 From: Balaji Subramaniam Date: Mon, 18 Dec 2017 10:00:26 -0800 Subject: [PATCH 13/58] Fix policy conflict in the CPU manager node e2e test. --- test/e2e_node/cpu_manager_test.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/test/e2e_node/cpu_manager_test.go b/test/e2e_node/cpu_manager_test.go index 9ac0bfca4a6..61a3b66cb5d 100644 --- a/test/e2e_node/cpu_manager_test.go +++ b/test/e2e_node/cpu_manager_test.go @@ -26,7 +26,6 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/features" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig" "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager" @@ -137,7 +136,16 @@ func getCPUSiblingList(cpuRes int64) string { return string(out) } +func deleteStateFile() { + err := exec.Command("/bin/sh", "-c", "rm -f /var/lib/kubelet/cpu_manager_state").Run() + framework.ExpectNoError(err, "error deleting state file") +} + func setOldKubeletConfig(f *framework.Framework, oldCfg *kubeletconfig.KubeletConfiguration) { + // Delete the CPU Manager state file so that the old Kubelet configuration + // can take effect.i + deleteStateFile() + if oldCfg != nil { framework.ExpectNoError(setKubeletConfiguration(f, oldCfg)) } @@ -155,8 +163,15 @@ func enableCPUManagerInKubelet(f *framework.Framework) (oldCfg *kubeletconfig.Ku newCfg.FeatureGates = make(map[string]bool) } - // Enable CPU Manager using feature gate. - newCfg.FeatureGates[string(features.CPUManager)] = true + // After graduation of the CPU Manager feature to Beta, the CPU Manager + // "none" policy is ON by default. But when we set the CPU Manager policy to + // "static" in this test and the Kubelet is restarted so that "static" + // policy can take effect, there will always be a conflict with the state + // checkpointed in the disk (i.e., the policy checkpointed in the disk will + // be "none" whereas we are trying to restart Kubelet with "static" + // policy). Therefore, we delete the state file so that we can proceed + // with the tests. + deleteStateFile() // Set the CPU Manager policy to static. newCfg.CPUManagerPolicy = string(cpumanager.PolicyStatic) From 9abb3160061c95a516ecc855518f1102225fdd87 Mon Sep 17 00:00:00 2001 From: Lion-Wei Date: Fri, 5 Jan 2018 11:42:39 +0800 Subject: [PATCH 14/58] fix ipvs proxy mode kubeadm usage --- pkg/proxy/ipvs/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/proxy/ipvs/README.md b/pkg/proxy/ipvs/README.md index 52297b7c90b..6a89697772f 100644 --- a/pkg/proxy/ipvs/README.md +++ b/pkg/proxy/ipvs/README.md @@ -39,9 +39,11 @@ Then the configuration file is similar to: kind: MasterConfiguration apiVersion: kubeadm.k8s.io/v1alpha1 ... -featureGates: - SupportIPVSProxyMode: true -mode: ipvs +kubeProxy: + config: + featureGates: SupportIPVSProxyMode=true + mode: ipvs +... ``` ## Debug From 988c4ae6baed8fcf5e06fc55e1ec031bf3d3815c Mon Sep 17 00:00:00 2001 From: m1093782566 Date: Wed, 10 Jan 2018 10:06:33 +0800 Subject: [PATCH 15/58] fix windows ut for proxy mode --- .../apis/kubeproxyconfig/validation/validation_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go b/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go index aaf5e9f4a91..8815e0af077 100644 --- a/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go +++ b/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go @@ -30,6 +30,12 @@ import ( ) func TestValidateKubeProxyConfiguration(t *testing.T) { + var proxyMode kubeproxyconfig.ProxyMode + if runtime.GOOS == "windows" { + proxyMode = kubeproxyconfig.ProxyModeKernelspace + } else { + proxyMode = kubeproxyconfig.ProxyModeIPVS + } successCases := []kubeproxyconfig.KubeProxyConfiguration{ { BindAddress: "192.168.59.103", @@ -43,7 +49,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) { SyncPeriod: metav1.Duration{Duration: 5 * time.Second}, MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second}, }, - Mode: kubeproxyconfig.ProxyModeIPVS, + Mode: proxyMode, IPVS: kubeproxyconfig.KubeProxyIPVSConfiguration{ SyncPeriod: metav1.Duration{Duration: 10 * time.Second}, MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second}, From d7c9ad97e8f41c42496e71b36afe30ca25193e33 Mon Sep 17 00:00:00 2001 From: Di Xu Date: Sun, 14 Jan 2018 16:38:31 +0800 Subject: [PATCH 16/58] Enable ValidatingAdmissionWebhook and MutatingAdmissionWebhook in kubeadm from v1.9 --- cmd/kubeadm/app/phases/controlplane/manifests.go | 4 ++-- cmd/kubeadm/app/phases/controlplane/manifests_test.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/kubeadm/app/phases/controlplane/manifests.go b/cmd/kubeadm/app/phases/controlplane/manifests.go index f1ae775f864..ac6ef16f2a2 100644 --- a/cmd/kubeadm/app/phases/controlplane/manifests.go +++ b/cmd/kubeadm/app/phases/controlplane/manifests.go @@ -43,8 +43,8 @@ const ( DefaultCloudConfigPath = "/etc/kubernetes/cloud-config" defaultV18AdmissionControl = "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota" - deprecatedV19AdmissionControl = "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota" - defaultV19AdmissionControl = "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota" + deprecatedV19AdmissionControl = "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota" + defaultV19AdmissionControl = "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota" ) // CreateInitStaticPodManifestFiles will write all static pod manifest files needed to bring up the control plane. diff --git a/cmd/kubeadm/app/phases/controlplane/manifests_test.go b/cmd/kubeadm/app/phases/controlplane/manifests_test.go index 4764bf534f5..366033a6c85 100644 --- a/cmd/kubeadm/app/phases/controlplane/manifests_test.go +++ b/cmd/kubeadm/app/phases/controlplane/manifests_test.go @@ -364,7 +364,7 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota", + "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -401,7 +401,7 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota", + "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -437,7 +437,7 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota", + "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -473,7 +473,7 @@ func TestGetAPIServerCommand(t *testing.T) { expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota", + "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", From f4f8e6fc30978f4da2de9d6c684d1ccd9b293b8a Mon Sep 17 00:00:00 2001 From: lcfang Date: Mon, 15 Jan 2018 09:49:52 +0800 Subject: [PATCH 17/58] fix some bad url --- api/openapi-spec/swagger.json | 6 +++--- api/swagger-spec/scheduling.k8s.io_v1alpha1.json | 4 ++-- api/swagger-spec/v1.json | 2 +- cmd/kubeadm/app/phases/etcd/spec/spec.go | 2 +- .../scheduling.k8s.io/v1alpha1/definitions.html | 4 ++-- docs/api-reference/v1/definitions.html | 2 +- staging/src/k8s.io/api/core/v1/generated.proto | 2 +- staging/src/k8s.io/api/core/v1/types.go | 2 +- .../src/k8s.io/api/core/v1/types_swagger_doc_generated.go | 2 +- staging/src/k8s.io/api/scheduling/v1alpha1/generated.proto | 4 ++-- staging/src/k8s.io/api/scheduling/v1alpha1/types.go | 4 ++-- .../api/scheduling/v1alpha1/types_swagger_doc_generated.go | 4 ++-- 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 795486975c8..cbe0e50f498 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -77568,7 +77568,7 @@ "type": "string" }, "qosClass": { - "description": "The Quality of Service (QOS) classification assigned to the pod based on resource requirements See PodQOSClass type for available QOS classes More info: https://github.com/kubernetes/kubernetes/blob/master/docs/design/resource-qos.md", + "description": "The Quality of Service (QOS) classification assigned to the pod based on resource requirements See PodQOSClass type for available QOS classes More info: https://git.k8s.io/community/contributors/design-proposals/node/resource-qos.md", "type": "string" }, "reason": { @@ -82131,7 +82131,7 @@ "type": "string" }, "metadata": { - "description": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata", + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" }, "value": { @@ -82170,7 +82170,7 @@ "type": "string" }, "metadata": { - "description": "Standard list metadata More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata", + "description": "Standard list metadata More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" } }, diff --git a/api/swagger-spec/scheduling.k8s.io_v1alpha1.json b/api/swagger-spec/scheduling.k8s.io_v1alpha1.json index 76bec8c02df..7b3abc4f7b9 100644 --- a/api/swagger-spec/scheduling.k8s.io_v1alpha1.json +++ b/api/swagger-spec/scheduling.k8s.io_v1alpha1.json @@ -744,7 +744,7 @@ }, "metadata": { "$ref": "v1.ListMeta", - "description": "Standard list metadata More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata" + "description": "Standard list metadata More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" }, "items": { "type": "array", @@ -790,7 +790,7 @@ }, "metadata": { "$ref": "v1.ObjectMeta", - "description": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata" + "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata" }, "value": { "type": "integer", diff --git a/api/swagger-spec/v1.json b/api/swagger-spec/v1.json index cc2cebe67cf..81a814e10f4 100644 --- a/api/swagger-spec/v1.json +++ b/api/swagger-spec/v1.json @@ -23155,7 +23155,7 @@ }, "qosClass": { "type": "string", - "description": "The Quality of Service (QOS) classification assigned to the pod based on resource requirements See PodQOSClass type for available QOS classes More info: https://github.com/kubernetes/kubernetes/blob/master/docs/design/resource-qos.md" + "description": "The Quality of Service (QOS) classification assigned to the pod based on resource requirements See PodQOSClass type for available QOS classes More info: https://git.k8s.io/community/contributors/design-proposals/node/resource-qos.md" } } }, diff --git a/cmd/kubeadm/app/phases/etcd/spec/spec.go b/cmd/kubeadm/app/phases/etcd/spec/spec.go index 4cc587a5b6c..622075478b1 100644 --- a/cmd/kubeadm/app/phases/etcd/spec/spec.go +++ b/cmd/kubeadm/app/phases/etcd/spec/spec.go @@ -68,7 +68,7 @@ func AddKnownTypes(s *runtime.Scheme) error { type EtcdClusterList struct { metav1.TypeMeta `json:",inline"` // Standard list metadata - // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata metav1.ListMeta `json:"metadata,omitempty"` Items []EtcdCluster `json:"items"` } diff --git a/docs/api-reference/scheduling.k8s.io/v1alpha1/definitions.html b/docs/api-reference/scheduling.k8s.io/v1alpha1/definitions.html index ae3e0927564..5c480a3ca0f 100755 --- a/docs/api-reference/scheduling.k8s.io/v1alpha1/definitions.html +++ b/docs/api-reference/scheduling.k8s.io/v1alpha1/definitions.html @@ -1272,7 +1272,7 @@ Examples:

metadata

-

Standard list metadata More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata

+

Standard list metadata More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

false

v1.ListMeta

@@ -1327,7 +1327,7 @@ Examples:

metadata

-

Standard object’s metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata

+

Standard object’s metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata

false

v1.ObjectMeta

diff --git a/docs/api-reference/v1/definitions.html b/docs/api-reference/v1/definitions.html index cbb2f013aad..7d7d2ee02d0 100755 --- a/docs/api-reference/v1/definitions.html +++ b/docs/api-reference/v1/definitions.html @@ -9068,7 +9068,7 @@ Examples:

qosClass

-

The Quality of Service (QOS) classification assigned to the pod based on resource requirements See PodQOSClass type for available QOS classes More info: https://github.com/kubernetes/kubernetes/blob/master/docs/design/resource-qos.md

+

The Quality of Service (QOS) classification assigned to the pod based on resource requirements See PodQOSClass type for available QOS classes More info: https://git.k8s.io/community/contributors/design-proposals/node/resource-qos.md

false

string

diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index 6bef759dece..84327e89d93 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -3179,7 +3179,7 @@ message PodStatus { // The Quality of Service (QOS) classification assigned to the pod based on resource requirements // See PodQOSClass type for available QOS classes - // More info: https://github.com/kubernetes/kubernetes/blob/master/docs/design/resource-qos.md + // More info: https://git.k8s.io/community/contributors/design-proposals/node/resource-qos.md // +optional optional string qosClass = 9; } diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index 49ef6109276..a5ce97a7bbd 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -3042,7 +3042,7 @@ type PodStatus struct { ContainerStatuses []ContainerStatus `json:"containerStatuses,omitempty" protobuf:"bytes,8,rep,name=containerStatuses"` // The Quality of Service (QOS) classification assigned to the pod based on resource requirements // See PodQOSClass type for available QOS classes - // More info: https://github.com/kubernetes/kubernetes/blob/master/docs/design/resource-qos.md + // More info: https://git.k8s.io/community/contributors/design-proposals/node/resource-qos.md // +optional QOSClass PodQOSClass `json:"qosClass,omitempty" protobuf:"bytes,9,rep,name=qosClass"` } diff --git a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go index 80cacc974e5..079e0823cb1 100644 --- a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go @@ -1531,7 +1531,7 @@ var map_PodStatus = map[string]string{ "startTime": "RFC 3339 date and time at which the object was acknowledged by the Kubelet. This is before the Kubelet pulled the container image(s) for the pod.", "initContainerStatuses": "The list has one entry per init container in the manifest. The most recent successful init container will have ready = true, the most recently started container will have startTime set. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status", "containerStatuses": "The list has one entry per container in the manifest. Each entry is currently the output of `docker inspect`. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status", - "qosClass": "The Quality of Service (QOS) classification assigned to the pod based on resource requirements See PodQOSClass type for available QOS classes More info: https://github.com/kubernetes/kubernetes/blob/master/docs/design/resource-qos.md", + "qosClass": "The Quality of Service (QOS) classification assigned to the pod based on resource requirements See PodQOSClass type for available QOS classes More info: https://git.k8s.io/community/contributors/design-proposals/node/resource-qos.md", } func (PodStatus) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/scheduling/v1alpha1/generated.proto b/staging/src/k8s.io/api/scheduling/v1alpha1/generated.proto index 75b4968cc31..588ef9718b0 100644 --- a/staging/src/k8s.io/api/scheduling/v1alpha1/generated.proto +++ b/staging/src/k8s.io/api/scheduling/v1alpha1/generated.proto @@ -33,7 +33,7 @@ option go_package = "v1alpha1"; // integer value. The value can be any valid integer. message PriorityClass { // Standard object's metadata. - // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; @@ -55,7 +55,7 @@ message PriorityClass { // PriorityClassList is a collection of priority classes. message PriorityClassList { // Standard list metadata - // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; diff --git a/staging/src/k8s.io/api/scheduling/v1alpha1/types.go b/staging/src/k8s.io/api/scheduling/v1alpha1/types.go index bca0f3471f2..07bf337fb14 100644 --- a/staging/src/k8s.io/api/scheduling/v1alpha1/types.go +++ b/staging/src/k8s.io/api/scheduling/v1alpha1/types.go @@ -29,7 +29,7 @@ import ( type PriorityClass struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. - // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata // +optional metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` @@ -54,7 +54,7 @@ type PriorityClass struct { type PriorityClassList struct { metav1.TypeMeta `json:",inline"` // Standard list metadata - // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata // +optional metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` diff --git a/staging/src/k8s.io/api/scheduling/v1alpha1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/scheduling/v1alpha1/types_swagger_doc_generated.go index c6187398dc3..4b68bf04a47 100644 --- a/staging/src/k8s.io/api/scheduling/v1alpha1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/scheduling/v1alpha1/types_swagger_doc_generated.go @@ -29,7 +29,7 @@ package v1alpha1 // AUTO-GENERATED FUNCTIONS START HERE var map_PriorityClass = map[string]string{ "": "PriorityClass defines mapping from a priority class name to the priority integer value. The value can be any valid integer.", - "metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata", + "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", "value": "The value of this priority class. This is the actual priority that pods receive when they have the name of this class in their pod spec.", "globalDefault": "globalDefault specifies whether this PriorityClass should be considered as the default priority for pods that do not have any priority class.", "description": "description is an arbitrary string that usually provides guidelines on when this priority class should be used.", @@ -41,7 +41,7 @@ func (PriorityClass) SwaggerDoc() map[string]string { var map_PriorityClassList = map[string]string{ "": "PriorityClassList is a collection of priority classes.", - "metadata": "Standard list metadata More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata", + "metadata": "Standard list metadata More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", "items": "items is the list of PriorityClasses", } From fa8afc1d393300803480e5faf4b6545916cd5ccf Mon Sep 17 00:00:00 2001 From: linweibin Date: Mon, 15 Jan 2018 16:02:35 +0800 Subject: [PATCH 18/58] Remove unused code in UT files in pkg/ --- .../providers/azure/azure_test.go | 50 ------------------- pkg/kubectl/cmd/BUILD | 1 - pkg/kubectl/cmd/attach_test.go | 6 +-- pkg/kubectl/cmd/drain_test.go | 16 ------ pkg/kubectl/cmd/exec_test.go | 6 +-- pkg/kubectl/cmd/logs_test.go | 4 +- pkg/kubectl/cmd/portforward_test.go | 8 +-- pkg/kubectl/cmd/resource/get_test.go | 11 ---- pkg/kubectl/cmd/taint_test.go | 1 - pkg/kubectl/cmd/top_pod_test.go | 2 - pkg/kubectl/namespace_test.go | 1 - pkg/kubectl/rolling_updater_test.go | 1 - pkg/kubelet/cm/cpumanager/BUILD | 1 - pkg/kubelet/cm/cpumanager/cpu_manager_test.go | 37 -------------- pkg/kubelet/cm/deviceplugin/manager_test.go | 5 -- pkg/kubelet/eviction/helpers_test.go | 18 +------ pkg/kubelet/kubelet_test.go | 2 - .../kuberuntime/kuberuntime_gc_test.go | 1 - .../kuberuntime/kuberuntime_manager_test.go | 6 --- pkg/kubelet/remote/remote_runtime_test.go | 7 --- pkg/kubelet/rkt/fake_rkt_interface_test.go | 1 - pkg/kubelet/stats/cri_stats_provider_test.go | 1 - pkg/kubelet/stats/stats_provider_test.go | 1 - pkg/master/BUILD | 5 -- pkg/master/master_test.go | 31 ------------ pkg/printers/humanreadable_test.go | 11 ---- pkg/printers/internalversion/describe_test.go | 4 +- .../apps/statefulset/storage/storage_test.go | 11 ---- pkg/registry/batch/cronjob/strategy_test.go | 6 --- .../core/endpoint/storage/storage_test.go | 10 ---- pkg/registry/core/event/strategy_test.go | 13 ----- .../persistentvolume/storage/storage_test.go | 5 -- pkg/registry/core/pod/strategy_test.go | 5 -- .../controller/storage/storage_test.go | 11 ---- .../storage/storage_test.go | 11 ---- .../storageclass/storage/storage_test.go | 4 -- .../volumeattachment/storage/storage_test.go | 4 -- pkg/security/podsecuritypolicy/group/BUILD | 5 +- .../podsecuritypolicy/group/mustrunas_test.go | 2 - pkg/serviceaccount/jwt_test.go | 11 ---- pkg/util/dbus/dbus_test.go | 7 +-- 41 files changed, 18 insertions(+), 325 deletions(-) diff --git a/pkg/cloudprovider/providers/azure/azure_test.go b/pkg/cloudprovider/providers/azure/azure_test.go index 40a1153680b..c42b9be3d08 100644 --- a/pkg/cloudprovider/providers/azure/azure_test.go +++ b/pkg/cloudprovider/providers/azure/azure_test.go @@ -1000,23 +1000,6 @@ func getBackendPort(port int32) int32 { return port + 10000 } -func getTestPublicFipConfigurationProperties() network.FrontendIPConfigurationPropertiesFormat { - return network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("/this/is/a/public/ip/address/id")}, - } -} - -func getTestInternalFipConfigurationProperties(expectedSubnetName *string) network.FrontendIPConfigurationPropertiesFormat { - var expectedSubnet *network.Subnet - if expectedSubnetName != nil { - expectedSubnet = &network.Subnet{Name: expectedSubnetName} - } - return network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("/this/is/a/public/ip/address/id")}, - Subnet: expectedSubnet, - } -} - func getTestService(identifier string, proto v1.Protocol, requestedPorts ...int32) v1.Service { ports := []v1.ServicePort{} for _, port := range requestedPorts { @@ -1056,39 +1039,6 @@ func setLoadBalancerAutoModeAnnotation(service *v1.Service) { setLoadBalancerModeAnnotation(service, ServiceAnnotationLoadBalancerAutoModeValue) } -func getTestLoadBalancer(services ...v1.Service) network.LoadBalancer { - rules := []network.LoadBalancingRule{} - probes := []network.Probe{} - - for _, service := range services { - for _, port := range service.Spec.Ports { - ruleName := getLoadBalancerRuleName(&service, port, nil) - rules = append(rules, network.LoadBalancingRule{ - Name: to.StringPtr(ruleName), - LoadBalancingRulePropertiesFormat: &network.LoadBalancingRulePropertiesFormat{ - FrontendPort: to.Int32Ptr(port.Port), - BackendPort: to.Int32Ptr(port.Port), - }, - }) - probes = append(probes, network.Probe{ - Name: to.StringPtr(ruleName), - ProbePropertiesFormat: &network.ProbePropertiesFormat{ - Port: to.Int32Ptr(port.NodePort), - }, - }) - } - } - - lb := network.LoadBalancer{ - LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{ - LoadBalancingRules: &rules, - Probes: &probes, - }, - } - - return lb -} - func getServiceSourceRanges(service *v1.Service) []string { if len(service.Spec.LoadBalancerSourceRanges) == 0 { if !requiresInternalLoadBalancer(service) { diff --git a/pkg/kubectl/cmd/BUILD b/pkg/kubectl/cmd/BUILD index 0bf32689830..d6cba425fec 100644 --- a/pkg/kubectl/cmd/BUILD +++ b/pkg/kubectl/cmd/BUILD @@ -207,7 +207,6 @@ go_test( importpath = "k8s.io/kubernetes/pkg/kubectl/cmd", deps = [ "//pkg/api/legacyscheme:go_default_library", - "//pkg/api/ref:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/api/testing:go_default_library", "//pkg/apis/batch:go_default_library", diff --git a/pkg/kubectl/cmd/attach_test.go b/pkg/kubectl/cmd/attach_test.go index 42801a9b257..f4d9b1d5cd7 100644 --- a/pkg/kubectl/cmd/attach_test.go +++ b/pkg/kubectl/cmd/attach_test.go @@ -286,9 +286,9 @@ func TestAttach(t *testing.T) { func TestAttachWarnings(t *testing.T) { version := legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion.Version tests := []struct { - name, container, version, podPath, fetchPodPath, expectedErr, expectedOut string - pod *api.Pod - stdin, tty bool + name, container, version, podPath, fetchPodPath, expectedErr string + pod *api.Pod + stdin, tty bool }{ { name: "fallback tty if not supported", diff --git a/pkg/kubectl/cmd/drain_test.go b/pkg/kubectl/cmd/drain_test.go index f9996314406..8efe31f8db7 100644 --- a/pkg/kubectl/cmd/drain_test.go +++ b/pkg/kubectl/cmd/drain_test.go @@ -44,7 +44,6 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/rest/fake" "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/api/ref" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/apis/batch" api "k8s.io/kubernetes/pkg/apis/core" @@ -882,18 +881,3 @@ func (m *MyReq) isFor(method string, path string) bool { req.URL.Path == strings.Join([]string{"/apis/extensions/v1beta1", path}, "") || req.URL.Path == strings.Join([]string{"/apis/batch/v1", path}, "")) } - -func refJson(t *testing.T, o runtime.Object) string { - ref, err := ref.GetReference(legacyscheme.Scheme, o) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - _, _, codec, _ := cmdtesting.NewAPIFactory() - json, err := runtime.Encode(codec, &api.SerializedReference{Reference: *ref}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - return string(json) -} diff --git a/pkg/kubectl/cmd/exec_test.go b/pkg/kubectl/cmd/exec_test.go index afa52ca634b..c327b731b0d 100644 --- a/pkg/kubectl/cmd/exec_test.go +++ b/pkg/kubectl/cmd/exec_test.go @@ -163,9 +163,9 @@ func TestPodAndContainer(t *testing.T) { func TestExec(t *testing.T) { version := "v1" tests := []struct { - name, podPath, execPath, container string - pod *api.Pod - execErr bool + name, podPath, execPath string + pod *api.Pod + execErr bool }{ { name: "pod exec", diff --git a/pkg/kubectl/cmd/logs_test.go b/pkg/kubectl/cmd/logs_test.go index be3dc7cab11..026b899f7c1 100644 --- a/pkg/kubectl/cmd/logs_test.go +++ b/pkg/kubectl/cmd/logs_test.go @@ -34,8 +34,8 @@ import ( func TestLog(t *testing.T) { tests := []struct { - name, version, podPath, logPath, container string - pod *api.Pod + name, version, podPath, logPath string + pod *api.Pod }{ { name: "v1 - pod log", diff --git a/pkg/kubectl/cmd/portforward_test.go b/pkg/kubectl/cmd/portforward_test.go index dcb6f1da82d..e2437bcb620 100644 --- a/pkg/kubectl/cmd/portforward_test.go +++ b/pkg/kubectl/cmd/portforward_test.go @@ -47,10 +47,10 @@ func testPortForward(t *testing.T, flags map[string]string, args []string) { version := "v1" tests := []struct { - name string - podPath, pfPath, container string - pod *api.Pod - pfErr bool + name string + podPath, pfPath string + pod *api.Pod + pfErr bool }{ { name: "pod portforward", diff --git a/pkg/kubectl/cmd/resource/get_test.go b/pkg/kubectl/cmd/resource/get_test.go index 9d30530aa96..14a02d9e135 100644 --- a/pkg/kubectl/cmd/resource/get_test.go +++ b/pkg/kubectl/cmd/resource/get_test.go @@ -83,17 +83,6 @@ func defaultClientConfig() *restclient.Config { } } -func defaultClientConfigForVersion(version *schema.GroupVersion) *restclient.Config { - return &restclient.Config{ - APIPath: "/api", - ContentConfig: restclient.ContentConfig{ - NegotiatedSerializer: scheme.Codecs, - ContentType: runtime.ContentTypeJSON, - GroupVersion: version, - }, - } -} - type testPrinter struct { Objects []runtime.Object Err error diff --git a/pkg/kubectl/cmd/taint_test.go b/pkg/kubectl/cmd/taint_test.go index 8e901364943..172be9d309f 100644 --- a/pkg/kubectl/cmd/taint_test.go +++ b/pkg/kubectl/cmd/taint_test.go @@ -84,7 +84,6 @@ func TestTaint(t *testing.T) { args []string expectFatal bool expectTaint bool - selector bool }{ // success cases { diff --git a/pkg/kubectl/cmd/top_pod_test.go b/pkg/kubectl/cmd/top_pod_test.go index 94bca7ec3ed..a839454e2f1 100644 --- a/pkg/kubectl/cmd/top_pod_test.go +++ b/pkg/kubectl/cmd/top_pod_test.go @@ -41,7 +41,6 @@ func TestTopPod(t *testing.T) { testNS := "testns" testCases := []struct { name string - namespace string flags map[string]string args []string expectedPath string @@ -176,7 +175,6 @@ func TestTopPodCustomDefaults(t *testing.T) { testNS := "custom-namespace" testCases := []struct { name string - namespace string flags map[string]string args []string expectedPath string diff --git a/pkg/kubectl/namespace_test.go b/pkg/kubectl/namespace_test.go index 2a017ba806f..23b214225a8 100644 --- a/pkg/kubectl/namespace_test.go +++ b/pkg/kubectl/namespace_test.go @@ -29,7 +29,6 @@ func TestNamespaceGenerate(t *testing.T) { params map[string]interface{} expected *v1.Namespace expectErr bool - index int }{ { params: map[string]interface{}{ diff --git a/pkg/kubectl/rolling_updater_test.go b/pkg/kubectl/rolling_updater_test.go index 0bd04c6b184..3620ed0712e 100644 --- a/pkg/kubectl/rolling_updater_test.go +++ b/pkg/kubectl/rolling_updater_test.go @@ -1260,7 +1260,6 @@ func TestFindSourceController(t *testing.T) { tests := []struct { list *api.ReplicationControllerList expectedController *api.ReplicationController - err error name string expectError bool }{ diff --git a/pkg/kubelet/cm/cpumanager/BUILD b/pkg/kubelet/cm/cpumanager/BUILD index d3330084825..a270b6a0527 100644 --- a/pkg/kubelet/cm/cpumanager/BUILD +++ b/pkg/kubelet/cm/cpumanager/BUILD @@ -47,7 +47,6 @@ go_test( "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", ], ) diff --git a/pkg/kubelet/cm/cpumanager/cpu_manager_test.go b/pkg/kubelet/cm/cpumanager/cpu_manager_test.go index 9381ea470bc..704060fb38e 100644 --- a/pkg/kubelet/cm/cpumanager/cpu_manager_test.go +++ b/pkg/kubelet/cm/cpumanager/cpu_manager_test.go @@ -28,7 +28,6 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state" @@ -118,28 +117,6 @@ func (psp mockPodStatusProvider) GetPodStatus(uid types.UID) (v1.PodStatus, bool return psp.podStatus, psp.found } -type mockPodKiller struct { - killedPods []*v1.Pod -} - -func (f *mockPodKiller) killPodNow(pod *v1.Pod, status v1.PodStatus, gracePeriodOverride *int64) error { - f.killedPods = append(f.killedPods, pod) - return nil -} - -type mockPodProvider struct { - pods []*v1.Pod -} - -func (f *mockPodProvider) getPods() []*v1.Pod { - return f.pods -} - -type mockRecorder struct{} - -func (r *mockRecorder) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args ...interface{}) { -} - func makePod(cpuRequest, cpuLimit string) *v1.Pod { return &v1.Pod{ Spec: v1.PodSpec{ @@ -161,20 +138,6 @@ func makePod(cpuRequest, cpuLimit string) *v1.Pod { } } -// CpuAllocatable must be <= CpuCapacity -func prepareCPUNodeStatus(CPUCapacity, CPUAllocatable string) v1.NodeStatus { - nodestatus := v1.NodeStatus{ - Capacity: make(v1.ResourceList, 1), - Allocatable: make(v1.ResourceList, 1), - } - cpucap, _ := resource.ParseQuantity(CPUCapacity) - cpuall, _ := resource.ParseQuantity(CPUAllocatable) - - nodestatus.Capacity[v1.ResourceCPU] = cpucap - nodestatus.Allocatable[v1.ResourceCPU] = cpuall - return nodestatus -} - func TestCPUManagerAdd(t *testing.T) { testCases := []struct { description string diff --git a/pkg/kubelet/cm/deviceplugin/manager_test.go b/pkg/kubelet/cm/deviceplugin/manager_test.go index 124f690acf7..8fef628b86c 100644 --- a/pkg/kubelet/cm/deviceplugin/manager_test.go +++ b/pkg/kubelet/cm/deviceplugin/manager_test.go @@ -233,11 +233,6 @@ func TestUpdateCapacityAllocatable(t *testing.T) { } -type stringPairType struct { - value1 string - value2 string -} - func constructDevices(devices []string) sets.String { ret := sets.NewString() for _, dev := range devices { diff --git a/pkg/kubelet/eviction/helpers_test.go b/pkg/kubelet/eviction/helpers_test.go index 727e0be14b9..7b8f5580665 100644 --- a/pkg/kubelet/eviction/helpers_test.go +++ b/pkg/kubelet/eviction/helpers_test.go @@ -1645,7 +1645,7 @@ func TestGetStarvedResources(t *testing.T) { } } -func testParsePercentage(t *testing.T) { +func TestParsePercentage(t *testing.T) { testCases := map[string]struct { hasError bool value float32 @@ -1674,7 +1674,7 @@ func testParsePercentage(t *testing.T) { } } -func testCompareThresholdValue(t *testing.T) { +func TestCompareThresholdValue(t *testing.T) { testCases := []struct { a, b evictionapi.ThresholdValue equal bool @@ -1831,20 +1831,6 @@ func newResourceList(cpu, memory, disk string) v1.ResourceList { return res } -func newEphemeralStorageResourceList(ephemeral, cpu, memory string) v1.ResourceList { - res := v1.ResourceList{} - if ephemeral != "" { - res[v1.ResourceEphemeralStorage] = resource.MustParse(ephemeral) - } - if cpu != "" { - res[v1.ResourceCPU] = resource.MustParse(cpu) - } - if memory != "" { - res[v1.ResourceMemory] = resource.MustParse("1Mi") - } - return res -} - func newResourceRequirements(requests, limits v1.ResourceList) v1.ResourceRequirements { res := v1.ResourceRequirements{} res.Requests = requests diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index c1061355baa..ea0172ce147 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -334,8 +334,6 @@ func newTestPods(count int) []*v1.Pod { return pods } -var emptyPodUIDs map[types.UID]kubetypes.SyncPodType - func TestSyncLoopAbort(t *testing.T) { testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) defer testKubelet.Cleanup() diff --git a/pkg/kubelet/kuberuntime/kuberuntime_gc_test.go b/pkg/kubelet/kuberuntime/kuberuntime_gc_test.go index 780d47f9b75..ebd306fd75a 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_gc_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_gc_test.go @@ -65,7 +65,6 @@ func TestSandboxGC(t *testing.T) { description string // description of the test case sandboxes []sandboxTemplate // templates of sandboxes containers []containerTemplate // templates of containers - minAge time.Duration // sandboxMinGCAge remain []int // template indexes of remaining sandboxes evictTerminatedPods bool }{ diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go b/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go index 85a06794eeb..b8e3e55d863 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go @@ -225,12 +225,6 @@ func verifyFakeContainerList(fakeRuntime *apitest.FakeRuntimeService, expected s return actual, actual.Equal(expected) } -type containerRecord struct { - container *v1.Container - attempt uint32 - state runtimeapi.ContainerState -} - // Only extract the fields of interests. type cRecord struct { name string diff --git a/pkg/kubelet/remote/remote_runtime_test.go b/pkg/kubelet/remote/remote_runtime_test.go index db5b31b6bf6..2f26efc3da0 100644 --- a/pkg/kubelet/remote/remote_runtime_test.go +++ b/pkg/kubelet/remote/remote_runtime_test.go @@ -50,13 +50,6 @@ func createRemoteRuntimeService(endpoint string, t *testing.T) internalapi.Runti return runtimeService } -func createRemoteImageService(endpoint string, t *testing.T) internalapi.ImageManagerService { - imageService, err := NewRemoteImageService(endpoint, defaultConnectionTimeout) - assert.NoError(t, err) - - return imageService -} - func TestVersion(t *testing.T) { fakeRuntime, endpoint := createAndStartFakeRemoteRuntime(t) defer fakeRuntime.Stop() diff --git a/pkg/kubelet/rkt/fake_rkt_interface_test.go b/pkg/kubelet/rkt/fake_rkt_interface_test.go index 19b3665685d..2ee7bdcdd65 100644 --- a/pkg/kubelet/rkt/fake_rkt_interface_test.go +++ b/pkg/kubelet/rkt/fake_rkt_interface_test.go @@ -195,7 +195,6 @@ func (f *fakePodDeletionProvider) IsPodDeleted(uid types.UID) bool { type fakeUnitGetter struct { networkNamespace kubecontainer.ContainerID - callServices []string } func newfakeUnitGetter() *fakeUnitGetter { diff --git a/pkg/kubelet/stats/cri_stats_provider_test.go b/pkg/kubelet/stats/cri_stats_provider_test.go index 5cff0ac7e90..931b368ec5d 100644 --- a/pkg/kubelet/stats/cri_stats_provider_test.go +++ b/pkg/kubelet/stats/cri_stats_provider_test.go @@ -38,7 +38,6 @@ import ( func TestCRIListPodStats(t *testing.T) { const ( seedRoot = 0 - seedRuntime = 100 seedKubelet = 200 seedMisc = 300 seedSandbox0 = 1000 diff --git a/pkg/kubelet/stats/stats_provider_test.go b/pkg/kubelet/stats/stats_provider_test.go index 6f02704ed59..1ff7f6524b4 100644 --- a/pkg/kubelet/stats/stats_provider_test.go +++ b/pkg/kubelet/stats/stats_provider_test.go @@ -59,7 +59,6 @@ const ( offsetFsTotalUsageBytes offsetFsBaseUsageBytes offsetFsInodeUsage - offsetVolume ) var ( diff --git a/pkg/master/BUILD b/pkg/master/BUILD index 3162a764c33..fadfc10b42b 100644 --- a/pkg/master/BUILD +++ b/pkg/master/BUILD @@ -145,13 +145,8 @@ go_test( "//vendor/github.com/go-openapi/strfmt:go_default_library", "//vendor/github.com/go-openapi/validate:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", - "//vendor/k8s.io/api/apps/v1beta1:go_default_library", - "//vendor/k8s.io/api/autoscaling/v1:go_default_library", - "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/pkg/master/master_test.go b/pkg/master/master_test.go index 506b81f9f6e..2d8d8c4f3e7 100644 --- a/pkg/master/master_test.go +++ b/pkg/master/master_test.go @@ -27,13 +27,8 @@ import ( "strings" "testing" - appsapiv1beta1 "k8s.io/api/apps/v1beta1" - autoscalingapiv1 "k8s.io/api/autoscaling/v1" - batchapiv1 "k8s.io/api/batch/v1" - batchapiv1beta1 "k8s.io/api/batch/v1beta1" certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1" apiv1 "k8s.io/api/core/v1" - extensionsapiv1beta1 "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -194,32 +189,6 @@ func newMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *ass return master, etcdserver, config, assert } -// limitedAPIResourceConfigSource only enables the core group, the extensions group, the batch group, and the autoscaling group. -func limitedAPIResourceConfigSource() *serverstorage.ResourceConfig { - ret := serverstorage.NewResourceConfig() - ret.EnableVersions( - apiv1.SchemeGroupVersion, - extensionsapiv1beta1.SchemeGroupVersion, - batchapiv1.SchemeGroupVersion, - batchapiv1beta1.SchemeGroupVersion, - appsapiv1beta1.SchemeGroupVersion, - autoscalingapiv1.SchemeGroupVersion, - ) - return ret -} - -// newLimitedMaster only enables the core group, the extensions group, the batch group, and the autoscaling group. -func newLimitedMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) { - etcdserver, config, sharedInformers, assert := setUp(t) - config.ExtraConfig.APIResourceConfigSource = limitedAPIResourceConfigSource() - master, err := config.Complete(sharedInformers).New(genericapiserver.EmptyDelegate) - if err != nil { - t.Fatalf("Error in bringing up the master: %v", err) - } - - return master, etcdserver, config, assert -} - // TestVersion tests /version func TestVersion(t *testing.T) { s, etcdserver, _, _ := newMaster(t) diff --git a/pkg/printers/humanreadable_test.go b/pkg/printers/humanreadable_test.go index 7c45b868e3a..779f6b748c8 100644 --- a/pkg/printers/humanreadable_test.go +++ b/pkg/printers/humanreadable_test.go @@ -45,17 +45,6 @@ func testPrintNamespace(obj *api.Namespace, options PrintOptions) ([]metav1alpha return []metav1alpha1.TableRow{row}, nil } -func testPrintNamespaceList(list *api.NamespaceList, options PrintOptions) ([]metav1alpha1.TableRow, error) { - rows := make([]metav1alpha1.TableRow, 0, len(list.Items)) - for i := range list.Items { - r, err := testPrintNamespace(&list.Items[i], options) - if err != nil { - return nil, err - } - rows = append(rows, r...) - } - return rows, nil -} func TestPrintRowsForHandlerEntry(t *testing.T) { printFunc := reflect.ValueOf(testPrintNamespace) diff --git a/pkg/printers/internalversion/describe_test.go b/pkg/printers/internalversion/describe_test.go index 71dfd3f05f4..54947d5974f 100644 --- a/pkg/printers/internalversion/describe_test.go +++ b/pkg/printers/internalversion/describe_test.go @@ -783,8 +783,8 @@ func TestDefaultDescribers(t *testing.T) { func TestGetPodsTotalRequests(t *testing.T) { testCases := []struct { - pods *api.PodList - expectedReqs, expectedLimits map[api.ResourceName]resource.Quantity + pods *api.PodList + expectedReqs map[api.ResourceName]resource.Quantity }{ { pods: &api.PodList{ diff --git a/pkg/registry/apps/statefulset/storage/storage_test.go b/pkg/registry/apps/statefulset/storage/storage_test.go index 1e2d13ed848..ad98dd1ed43 100644 --- a/pkg/registry/apps/statefulset/storage/storage_test.go +++ b/pkg/registry/apps/statefulset/storage/storage_test.go @@ -44,17 +44,6 @@ func newStorage(t *testing.T) (StatefulSetStorage, *etcdtesting.EtcdTestServer) return storage, server } -// createStatefulSet is a helper function that returns a StatefulSet with the updated resource version. -func createStatefulSet(storage *REST, ps apps.StatefulSet, t *testing.T) (apps.StatefulSet, error) { - ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), ps.Namespace) - obj, err := storage.Create(ctx, &ps, rest.ValidateAllObjectFunc, false) - if err != nil { - t.Errorf("Failed to create StatefulSet, %v", err) - } - newPS := obj.(*apps.StatefulSet) - return *newPS, nil -} - func validNewStatefulSet() *apps.StatefulSet { return &apps.StatefulSet{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/registry/batch/cronjob/strategy_test.go b/pkg/registry/batch/cronjob/strategy_test.go index 6cf9b60b589..0b46ac9f861 100644 --- a/pkg/registry/batch/cronjob/strategy_test.go +++ b/pkg/registry/batch/cronjob/strategy_test.go @@ -26,12 +26,6 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" ) -func newBool(a bool) *bool { - r := new(bool) - *r = a - return r -} - func TestCronJobStrategy(t *testing.T) { ctx := genericapirequest.NewDefaultContext() if !Strategy.NamespaceScoped() { diff --git a/pkg/registry/core/endpoint/storage/storage_test.go b/pkg/registry/core/endpoint/storage/storage_test.go index a511424a098..bf7b366f102 100644 --- a/pkg/registry/core/endpoint/storage/storage_test.go +++ b/pkg/registry/core/endpoint/storage/storage_test.go @@ -54,16 +54,6 @@ func validNewEndpoints() *api.Endpoints { } } -func validChangedEndpoints() *api.Endpoints { - endpoints := validNewEndpoints() - endpoints.ResourceVersion = "1" - endpoints.Subsets = []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}}, - Ports: []api.EndpointPort{{Port: 80, Protocol: "TCP"}}, - }} - return endpoints -} - func TestCreate(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) diff --git a/pkg/registry/core/event/strategy_test.go b/pkg/registry/core/event/strategy_test.go index e95df8a0f85..fe1763798bc 100644 --- a/pkg/registry/core/event/strategy_test.go +++ b/pkg/registry/core/event/strategy_test.go @@ -31,19 +31,6 @@ import ( _ "k8s.io/kubernetes/pkg/api/testapi" ) -func testEvent(name string) *api.Event { - return &api.Event{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: "default", - }, - InvolvedObject: api.ObjectReference{ - Namespace: "default", - }, - Reason: "forTesting", - } -} - func TestGetAttrs(t *testing.T) { eventA := &api.Event{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/registry/core/persistentvolume/storage/storage_test.go b/pkg/registry/core/persistentvolume/storage/storage_test.go index 95c90eede9c..489569cca4e 100644 --- a/pkg/registry/core/persistentvolume/storage/storage_test.go +++ b/pkg/registry/core/persistentvolume/storage/storage_test.go @@ -77,11 +77,6 @@ func validNewPersistentVolume(name string) *api.PersistentVolume { return pv } -func validChangedPersistentVolume() *api.PersistentVolume { - pv := validNewPersistentVolume("foo") - return pv -} - func TestCreate(t *testing.T) { storage, _, server := newStorage(t) defer server.Terminate(t) diff --git a/pkg/registry/core/pod/strategy_test.go b/pkg/registry/core/pod/strategy_test.go index 8d10e6a6eeb..d013292635b 100644 --- a/pkg/registry/core/pod/strategy_test.go +++ b/pkg/registry/core/pod/strategy_test.go @@ -138,11 +138,6 @@ func getResourceList(cpu, memory string) api.ResourceList { return res } -func addResource(rName, value string, rl api.ResourceList) api.ResourceList { - rl[api.ResourceName(rName)] = resource.MustParse(value) - return rl -} - func getResourceRequirements(requests, limits api.ResourceList) api.ResourceRequirements { res := api.ResourceRequirements{} res.Requests = requests diff --git a/pkg/registry/extensions/controller/storage/storage_test.go b/pkg/registry/extensions/controller/storage/storage_test.go index 62689035fb4..c969bb5c3eb 100644 --- a/pkg/registry/extensions/controller/storage/storage_test.go +++ b/pkg/registry/extensions/controller/storage/storage_test.go @@ -74,17 +74,6 @@ var validController = api.ReplicationController{ Spec: validControllerSpec, } -var validScale = autoscaling.Scale{ - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test"}, - Spec: autoscaling.ScaleSpec{ - Replicas: validReplicas, - }, - Status: autoscaling.ScaleStatus{ - Replicas: 0, - Selector: "a=b", - }, -} - func TestGet(t *testing.T) { storage, _, si, destroyFunc := newStorage(t) defer destroyFunc() diff --git a/pkg/registry/policy/poddisruptionbudget/storage/storage_test.go b/pkg/registry/policy/poddisruptionbudget/storage/storage_test.go index 4c67d4ca3da..c11b5798754 100644 --- a/pkg/registry/policy/poddisruptionbudget/storage/storage_test.go +++ b/pkg/registry/policy/poddisruptionbudget/storage/storage_test.go @@ -39,17 +39,6 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) return podDisruptionBudgetStorage, statusStorage, server } -// createPodDisruptionBudget is a helper function that returns a PodDisruptionBudget with the updated resource version. -func createPodDisruptionBudget(storage *REST, pdb policy.PodDisruptionBudget, t *testing.T) (policy.PodDisruptionBudget, error) { - ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), pdb.Namespace) - obj, err := storage.Create(ctx, &pdb, rest.ValidateAllObjectFunc, false) - if err != nil { - t.Errorf("Failed to create PodDisruptionBudget, %v", err) - } - newPS := obj.(*policy.PodDisruptionBudget) - return *newPS, nil -} - func validNewPodDisruptionBudget() *policy.PodDisruptionBudget { minAvailable := intstr.FromInt(7) return &policy.PodDisruptionBudget{ diff --git a/pkg/registry/storage/storageclass/storage/storage_test.go b/pkg/registry/storage/storageclass/storage/storage_test.go index 9a5dd866950..aaca94134f1 100644 --- a/pkg/registry/storage/storageclass/storage/storage_test.go +++ b/pkg/registry/storage/storageclass/storage/storage_test.go @@ -57,10 +57,6 @@ func validNewStorageClass(name string) *storageapi.StorageClass { } } -func validChangedStorageClass() *storageapi.StorageClass { - return validNewStorageClass("foo") -} - func TestCreate(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) diff --git a/pkg/registry/storage/volumeattachment/storage/storage_test.go b/pkg/registry/storage/volumeattachment/storage/storage_test.go index 669e319155c..540255de895 100644 --- a/pkg/registry/storage/volumeattachment/storage/storage_test.go +++ b/pkg/registry/storage/volumeattachment/storage/storage_test.go @@ -60,10 +60,6 @@ func validNewVolumeAttachment(name string) *storageapi.VolumeAttachment { } } -func validChangedVolumeAttachment() *storageapi.VolumeAttachment { - return validNewVolumeAttachment("foo") -} - func TestCreate(t *testing.T) { if *testapi.Storage.GroupVersion() != storageapiv1alpha1.SchemeGroupVersion { // skip the test for all versions exception v1alpha1 diff --git a/pkg/security/podsecuritypolicy/group/BUILD b/pkg/security/podsecuritypolicy/group/BUILD index 601e7476dee..95be9751975 100644 --- a/pkg/security/podsecuritypolicy/group/BUILD +++ b/pkg/security/podsecuritypolicy/group/BUILD @@ -31,10 +31,7 @@ go_test( ], embed = [":go_default_library"], importpath = "k8s.io/kubernetes/pkg/security/podsecuritypolicy/group", - deps = [ - "//pkg/apis/core:go_default_library", - "//pkg/apis/extensions:go_default_library", - ], + deps = ["//pkg/apis/extensions:go_default_library"], ) filegroup( diff --git a/pkg/security/podsecuritypolicy/group/mustrunas_test.go b/pkg/security/podsecuritypolicy/group/mustrunas_test.go index 395ffd80eb0..c0347672e69 100644 --- a/pkg/security/podsecuritypolicy/group/mustrunas_test.go +++ b/pkg/security/podsecuritypolicy/group/mustrunas_test.go @@ -17,7 +17,6 @@ limitations under the License. package group import ( - api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/extensions" "testing" ) @@ -110,7 +109,6 @@ func TestGenerate(t *testing.T) { func TestValidate(t *testing.T) { tests := map[string]struct { ranges []extensions.GroupIDRange - pod *api.Pod groups []int64 pass bool }{ diff --git a/pkg/serviceaccount/jwt_test.go b/pkg/serviceaccount/jwt_test.go index 076f4ade98a..e21af9584da 100644 --- a/pkg/serviceaccount/jwt_test.go +++ b/pkg/serviceaccount/jwt_test.go @@ -80,17 +80,6 @@ X024wzbiw1q07jFCyfQmODzURAx1VNT7QVUMdz/N8vy47/H40AZJ -----END RSA PRIVATE KEY----- ` -// openssl ecparam -name prime256v1 -genkey -out ecdsa256params.pem -const ecdsaPrivateKeyWithParams = `-----BEGIN EC PARAMETERS----- -BggqhkjOPQMBBw== ------END EC PARAMETERS----- ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIJ9LWDj3ZWe9CksPV7mZjD2dYXG9icfzxadCRwd3vr1toAoGCCqGSM49 -AwEHoUQDQgAEaLNEpzbaaNTCkKjBVj7sxpfJ1ifJQGNvcck4nrzcwFRuujwVDDJh -95iIGwKCQeSg+yhdN6Q/p2XaxNIZlYmUhg== ------END EC PRIVATE KEY----- -` - // openssl ecparam -name prime256v1 -genkey -noout -out ecdsa256.pem const ecdsaPrivateKey = `-----BEGIN EC PRIVATE KEY----- MHcCAQEEIEZmTmUhuanLjPA2CLquXivuwBDHTt5XYwgIr/kA1LtRoAoGCCqGSM49 diff --git a/pkg/util/dbus/dbus_test.go b/pkg/util/dbus/dbus_test.go index 3f22d5982f9..359f6fbd86f 100644 --- a/pkg/util/dbus/dbus_test.go +++ b/pkg/util/dbus/dbus_test.go @@ -25,21 +25,16 @@ import ( ) const ( - DBusNameFlagAllowReplacement uint32 = 1 << (iota + 1) - DBusNameFlagReplaceExisting - DBusNameFlagDoNotQueue + DBusNameFlagDoNotQueue uint32 = 1 << (iota + 1) ) const ( DBusRequestNameReplyPrimaryOwner uint32 = iota + 1 - DBusRequestNameReplyInQueue - DBusRequestNameReplyExists DBusRequestNameReplyAlreadyOwner ) const ( DBusReleaseNameReplyReleased uint32 = iota + 1 - DBusReleaseNameReplyNonExistent DBusReleaseNameReplyNotOwner ) From fd520aef61996c213a960e1ea933def56dec17f6 Mon Sep 17 00:00:00 2001 From: Michal Fojtik Date: Mon, 15 Jan 2018 13:02:31 +0100 Subject: [PATCH 19/58] Show findmt command output in case of error --- pkg/util/mount/nsenter_mount.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/util/mount/nsenter_mount.go b/pkg/util/mount/nsenter_mount.go index a6c7869b0d8..99e81837fde 100644 --- a/pkg/util/mount/nsenter_mount.go +++ b/pkg/util/mount/nsenter_mount.go @@ -165,7 +165,7 @@ func (n *NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) { glog.V(5).Infof("nsenter findmnt args: %v", args) out, err := n.ne.Exec("findmnt", args).CombinedOutput() if err != nil { - glog.V(2).Infof("Failed findmnt command for path %s: %v", file, err) + glog.V(2).Infof("Failed findmnt command for path %s: %s %v", file, out, err) // Different operating systems behave differently for paths which are not mount points. // On older versions (e.g. 2.20.1) we'd get error, on newer ones (e.g. 2.26.2) we'd get "/". // It's safer to assume that it's not a mount point. From fa51acbda35d329fbaa354145ecb04518910b936 Mon Sep 17 00:00:00 2001 From: Srini Brahmaroutu Date: Thu, 21 Sep 2017 11:58:19 -0700 Subject: [PATCH 20/58] Create Conformance document to display all tests that belong to Conformance suite --- test/conformance/BUILD | 10 +- test/conformance/cf_header.md | 41 +++++++ test/conformance/walk.go | 222 +++++++++++++++++++++++++++++++--- test/conformance/walk_test.go | 95 +++++++++++++++ 4 files changed, 351 insertions(+), 17 deletions(-) create mode 100644 test/conformance/cf_header.md create mode 100644 test/conformance/walk_test.go diff --git a/test/conformance/BUILD b/test/conformance/BUILD index 3d3b8018c8c..a91182f13e3 100644 --- a/test/conformance/BUILD +++ b/test/conformance/BUILD @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test") go_library( name = "go_default_library", @@ -48,3 +48,11 @@ sh_test( ":list_conformance_tests", ], ) + +go_test( + name = "go_default_test", + srcs = ["walk_test.go"], + data = glob(["testdata/**"]), + embed = [":go_default_library"], + importpath = "k8s.io/kubernetes/test/conformance", +) diff --git a/test/conformance/cf_header.md b/test/conformance/cf_header.md new file mode 100644 index 00000000000..e4bef5c46e9 --- /dev/null +++ b/test/conformance/cf_header.md @@ -0,0 +1,41 @@ +# Kubernetes Conformance Test Suite - v1.9 + +## **Summary** +This document provides a summary of the tests included in the Kubernetes conformance test suite. +Each test lists a set of formal requirements that a platform that meets conformance requirements must adhere to. + +The tests are a subset of the "e2e" tests that make up the Kubernetes testing infrastructure. +Each test is identified by the presence of the `[Conformance]` keyword in the ginkgo descriptive function calls. +The contents of this document are extracted from comments preceding those `[Conformance]` keywords +and those comments are expected to include a descriptive overview of what the test is validating using +RFC2119 keywords. This will provide a clear distinction between which bits of code in the tests are +there for the purposes of validating the platform rather than simply infrastructure logic used to setup, or +clean up the tests. + +Example: +``` +/* + Testname: Kubelet-OutputToLogs + Description: By default the stdout and stderr from the process + being executed in a pod MUST be sent to the pod's logs. +*/ +// Note this test needs to be fixed to also test for stderr +It("it should print the output to logs [Conformance]", func() { +``` + +would generate the following documentation for the test. Note that the "TestName" from the Documentation above will +be used to document the test which make it more human readable. The "Description" field will be used as the +documentation for that test. + +### **Output:** +## [Kubelet-OutputToLogs](https://github.com/kubernetes/kubernetes/blob/release-1.9/test/e2e_node/kubelet_test.go#L42) + +By default the stdout and stderr from the process +being executed in a pod MUST be sent to the pod's logs. +Note this test needs to be fixed to also test for stderr + +Notational Conventions when documenting the tests with the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119). + +Note: Please see the Summary at the end of this document to find the number of tests documented for conformance. + +## **List of Tests** diff --git a/test/conformance/walk.go b/test/conformance/walk.go index 9637620f182..a4bd553ce83 100644 --- a/test/conformance/walk.go +++ b/test/conformance/walk.go @@ -24,17 +24,89 @@ limitations under the License. package main import ( + "flag" "fmt" "go/ast" "go/parser" "go/token" + "io/ioutil" "os" "path/filepath" + "regexp" + "strconv" "strings" ) +var ( + baseURL = flag.String("url", "https://github.com/kubernetes/kubernetes/tree/master/", "location of the current source") + confDoc = flag.Bool("conformance", false, "write a conformance document") + totalConfTests, totalLegacyTests, missingComments int +) + +const regexDescribe = "Describe|KubeDescribe|SIGDescribe" +const regexContext = "Context" + type visitor struct { - FileSet *token.FileSet + FileSet *token.FileSet + lastDescribe describe + cMap ast.CommentMap + //list of all the conformance tests in the path + tests []conformanceData +} + +//describe contains text associated with ginkgo describe container +type describe struct { + text string + lastContext context +} + +//context contain the text associated with the Context clause +type context struct { + text string +} + +type conformanceData struct { + // A URL to the line of code in the kube src repo for the test + URL string + // Extracted from the "Testname:" comment before the test + TestName string + // Extracted from the "Description:" comment before the test + Description string +} + +func (v *visitor) convertToConformanceData(at *ast.BasicLit) { + cd := conformanceData{} + + comment := v.comment(at) + pos := v.FileSet.Position(at.Pos()) + cd.URL = fmt.Sprintf("%s%s#L%d", *baseURL, pos.Filename, pos.Line) + + lines := strings.Split(comment, "\n") + cd.Description = "" + for _, line := range lines { + line = strings.TrimSpace(line) + if strings.HasPrefix(line, "Testname:") { + line = strings.TrimSpace(line[9:]) + cd.TestName = line + continue + } + if strings.HasPrefix(line, "Description:") { + line = strings.TrimSpace(line[12:]) + } + cd.Description += line + "\n" + } + + if cd.TestName == "" { + testName := v.getDescription(at.Value) + i := strings.Index(testName, "[Conformance]") + if i > 0 { + cd.TestName = strings.TrimSpace(testName[:i]) + } else { + cd.TestName = testName + } + } + + v.tests = append(v.tests, cd) } func newVisitor() *visitor { @@ -84,7 +156,16 @@ func (v *visitor) isLegacyItCall(call *ast.CallExpr) bool { func (v *visitor) failf(expr ast.Expr, format string, a ...interface{}) { msg := fmt.Sprintf(format, a...) fmt.Fprintf(os.Stderr, "ERROR at %v: %s\n", v.FileSet.Position(expr.Pos()), msg) - os.Exit(65) +} + +func (v *visitor) comment(x *ast.BasicLit) string { + for _, comm := range v.cMap.Comments() { + testOffset := int(x.Pos()-comm.End()) - len("framework.ConformanceIt(\"") + if 0 < testOffset && testOffset < 3 { + return comm.Text() + } + } + return "" } func (v *visitor) emit(arg ast.Expr) { @@ -94,13 +175,94 @@ func (v *visitor) emit(arg ast.Expr) { v.failf(at, "framework.ConformanceIt() called with non-string argument") return } - fmt.Printf("%s: %s\n", v.FileSet.Position(at.Pos()).Filename, at.Value) + + if *confDoc { + v.convertToConformanceData(at) + } else { + fmt.Printf("%s: %s\n", v.FileSet.Position(at.Pos()).Filename, at.Value) + } default: v.failf(at, "framework.ConformanceIt() called with non-literal argument") fmt.Fprintf(os.Stderr, "ERROR: non-literal argument %v at %v\n", arg, v.FileSet.Position(arg.Pos())) } } +func (v *visitor) getDescription(value string) string { + if len(v.lastDescribe.lastContext.text) > 0 { + return strings.Trim(v.lastDescribe.text, "\"") + + " " + strings.Trim(v.lastDescribe.lastContext.text, "\"") + + " " + strings.Trim(value, "\"") + } + return strings.Trim(v.lastDescribe.text, "\"") + + " " + strings.Trim(value, "\"") +} + +// funcName converts a selectorExpr with two idents into a string, +// x.y -> "x.y" +func funcName(n ast.Expr) string { + if sel, ok := n.(*ast.SelectorExpr); ok { + if x, ok := sel.X.(*ast.Ident); ok { + return x.String() + "." + sel.Sel.String() + } + } + return "" +} + +// isSprintf returns whether the given node is a call to fmt.Sprintf +func isSprintf(n ast.Expr) bool { + call, ok := n.(*ast.CallExpr) + return ok && funcName(call.Fun) == "fmt.Sprintf" && len(call.Args) != 0 +} + +// firstArg attempts to statically determine the value of the first +// argument. It only handles strings, and converts any unknown values +// (fmt.Sprintf interpolations) into *. +func (v *visitor) firstArg(n *ast.CallExpr) string { + if len(n.Args) == 0 { + return "" + } + var lit *ast.BasicLit + if isSprintf(n.Args[0]) { + return v.firstArg(n.Args[0].(*ast.CallExpr)) + } + lit, ok := n.Args[0].(*ast.BasicLit) + if ok && lit.Kind == token.STRING { + val, err := strconv.Unquote(lit.Value) + if err != nil { + panic(err) + } + if strings.Contains(val, "%") { + val = strings.Replace(val, "%d", "*", -1) + val = strings.Replace(val, "%v", "*", -1) + val = strings.Replace(val, "%s", "*", -1) + } + return val + } + if ident, ok := n.Args[0].(*ast.Ident); ok { + return ident.String() + } + return "*" +} + +// matchFuncName returns the first argument of a function if it's +// a Ginkgo-relevant function (Describe/KubeDescribe/Context), +// and the empty string otherwise. +func (v *visitor) matchFuncName(n *ast.CallExpr, pattern string) string { + switch x := n.Fun.(type) { + case *ast.SelectorExpr: + if match, err := regexp.MatchString(pattern, x.Sel.Name); err == nil && match { + return v.firstArg(n) + } + case *ast.Ident: + if match, err := regexp.MatchString(pattern, x.Name); err == nil && match { + return v.firstArg(n) + } + default: + return "" + } + return "" +} + // Visit visits each node looking for either calls to framework.ConformanceIt, // which it will emit in its list of conformance tests, or legacy calls to // It() with a manually embedded [Conformance] tag, which it will complain @@ -108,9 +270,16 @@ func (v *visitor) emit(arg ast.Expr) { func (v *visitor) Visit(node ast.Node) (w ast.Visitor) { switch t := node.(type) { case *ast.CallExpr: - if v.isConformanceCall(t) { + if name := v.matchFuncName(t, regexDescribe); name != "" && len(t.Args) >= 2 { + v.lastDescribe = describe{text: name} + } else if name := v.matchFuncName(t, regexContext); name != "" && len(t.Args) >= 2 { + v.lastDescribe.lastContext = context{text: name} + } else if v.isConformanceCall(t) { + totalConfTests++ v.emit(t.Args[0]) + return nil } else if v.isLegacyItCall(t) { + totalLegacyTests++ v.failf(t, "Using It() with manual [Conformance] tag is no longer allowed. Use framework.ConformanceIt() instead.") return nil } @@ -120,7 +289,7 @@ func (v *visitor) Visit(node ast.Node) (w ast.Visitor) { func scandir(dir string) { v := newVisitor() - pkg, err := parser.ParseDir(v.FileSet, dir, nil, 0) + pkg, err := parser.ParseDir(v.FileSet, dir, nil, parser.ParseComments) if err != nil { panic(err) } @@ -130,37 +299,58 @@ func scandir(dir string) { } } -func scanfile(path string) { +func scanfile(path string, src interface{}) []conformanceData { v := newVisitor() - file, err := parser.ParseFile(v.FileSet, path, nil, 0) + file, err := parser.ParseFile(v.FileSet, path, src, parser.ParseComments) if err != nil { panic(err) } + v.cMap = ast.NewCommentMap(v.FileSet, file, file.Comments) + ast.Walk(v, file) + return v.tests } func main() { - args := os.Args[1:] - if len(args) < 1 { + flag.Parse() + + if len(flag.Args()) < 1 { fmt.Fprintf(os.Stderr, "USAGE: %s [...]\n", os.Args[0]) os.Exit(64) } - for _, arg := range args { + if *confDoc { + // Note: this assumes that you're running from the root of the kube src repo + header, err := ioutil.ReadFile("test/conformance/cf_header.md") + if err == nil { + fmt.Printf("%s\n\n", header) + } + } + + totalConfTests = 0 + totalLegacyTests = 0 + missingComments = 0 + for _, arg := range flag.Args() { filepath.Walk(arg, func(path string, info os.FileInfo, err error) error { if err != nil { return err } - if info.IsDir() { - scandir(path) - } else { - // TODO(mml): Remove this once we have all-go-srcs build rules. See https://github.com/kubernetes/repo-infra/pull/45 - if strings.HasSuffix(path, ".go") { - scanfile(path) + if strings.HasSuffix(path, ".go") { + tests := scanfile(path, nil) + for _, cd := range tests { + fmt.Printf("## [%s](%s)\n\n", cd.TestName, cd.URL) + fmt.Printf("%s\n\n", cd.Description) + if len(cd.Description) < 10 { + missingComments++ + } } } return nil }) } + if *confDoc { + fmt.Println("\n## **Summary**") + fmt.Printf("\nTotal Conformance Tests: %d, total legacy tests that need conversion: %d, while total tests that need comment sections: %d\n\n", totalConfTests, totalLegacyTests, missingComments) + } } diff --git a/test/conformance/walk_test.go b/test/conformance/walk_test.go new file mode 100644 index 00000000000..8fcb8c4a156 --- /dev/null +++ b/test/conformance/walk_test.go @@ -0,0 +1,95 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "reflect" + "testing" +) + +var conformanceCases = []struct { + filename string + code string + output []conformanceData +}{ + // Go unit test + {"test/list/main_test.go", ` +var num = 3 +func Helper(x int) { return x / 0 } +var _ = Describe("Feature", func() { +/* + Testname: Kubelet-OutputToLogs + Description: By default the stdout and stderr from the process + being executed in a pod MUST be sent to the pod's logs. +*/ + framework.ConformanceIt("validates describe with ConformanceIt", func() {}) +})`, []conformanceData{{URL: "https://github.com/kubernetes/kubernetes/tree/master/test/list/main_test.go#L11", TestName: "Kubelet-OutputToLogs", + Description: `By default the stdout and stderr from the process +being executed in a pod MUST be sent to the pod's logs.` + "\n\n"}}, + }, + // Describe + It + {"e2e/foo.go", ` +var _ = Describe("Feature", func() { + //It should have comment + framework.ConformanceIt("should work properly", func() {}) +})`, []conformanceData{{URL: "https://github.com/kubernetes/kubernetes/tree/master/e2e/foo.go#L5", TestName: "Feature should work properly", Description: "It should have comment\n\n"}}, + }, + // KubeDescribe + It + {"e2e/foo.go", ` +var _ = framework.KubeDescribe("Feature", func() { + /*It should have comment*/ + framework.ConformanceIt("should work properly", func() {}) +})`, []conformanceData{{URL: "https://github.com/kubernetes/kubernetes/tree/master/e2e/foo.go#L5", TestName: "Feature should work properly", Description: "It should have comment\n\n"}}, + }, + // KubeDescribe + Context + It + {"e2e/foo.go", ` +var _ = framework.KubeDescribe("Feature", func() { + Context("when offline", func() { + //Testname: Kubelet-OutputToLogs + //Description: By default the stdout and stderr from the process + //being executed in a pod MUST be sent to the pod's logs. + framework.ConformanceIt("should work", func() {}) + }) +})`, []conformanceData{{URL: "https://github.com/kubernetes/kubernetes/tree/master/e2e/foo.go#L8", TestName: "Kubelet-OutputToLogs", + Description: `By default the stdout and stderr from the process +being executed in a pod MUST be sent to the pod's logs.` + "\n\n"}}, + }, + // KubeDescribe + Context + It + {"e2e/foo.go", ` +var _ = framework.KubeDescribe("Feature", func() { + Context("with context", func() { + //Description: By default the stdout and stderr from the process + //being executed in a pod MUST be sent to the pod's logs. + framework.ConformanceIt("should work", func() {}) + }) +})`, []conformanceData{{URL: "https://github.com/kubernetes/kubernetes/tree/master/e2e/foo.go#L7", TestName: "Feature with context should work", + Description: `By default the stdout and stderr from the process +being executed in a pod MUST be sent to the pod's logs.` + "\n\n"}}, + }, +} + +func TestConformance(t *testing.T) { + for _, test := range conformanceCases { + code := "package test\n" + test.code + *confDoc = true + tests := scanfile(test.filename, code) + if !reflect.DeepEqual(tests, test.output) { + t.Errorf("code:\n%s\ngot %v\nwant %v", + code, tests, test.output) + } + } +} From 87cebae73815fcc9a5781a42c432f62bf4d1aed0 Mon Sep 17 00:00:00 2001 From: NickrenREN Date: Fri, 12 Jan 2018 10:20:22 +0800 Subject: [PATCH 21/58] Add fsType for CSI --- pkg/apis/core/types.go | 6 ++++++ pkg/volume/csi/csi_mounter.go | 9 ++++++++- staging/src/k8s.io/api/core/v1/types.go | 6 ++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go index e036d0721b9..a1e2fd91763 100644 --- a/pkg/apis/core/types.go +++ b/pkg/apis/core/types.go @@ -1615,6 +1615,12 @@ type CSIPersistentVolumeSource struct { // Defaults to false (read/write). // +optional ReadOnly bool + + // Filesystem type to mount. + // Must be a filesystem type supported by the host operating system. + // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // +optional + FSType string } // ContainerPort represents a network port in a single container diff --git a/pkg/volume/csi/csi_mounter.go b/pkg/volume/csi/csi_mounter.go index 3009fdf47ea..62954369b65 100644 --- a/pkg/volume/csi/csi_mounter.go +++ b/pkg/volume/csi/csi_mounter.go @@ -34,6 +34,8 @@ import ( "k8s.io/kubernetes/pkg/volume/util" ) +const defaultFSType = "ext4" + //TODO (vladimirvivien) move this in a central loc later var ( volDataKey = struct { @@ -189,6 +191,11 @@ func (c *csiMountMgr) SetUpAt(dir string, fsGroup *int64) error { accessMode = c.spec.PersistentVolume.Spec.AccessModes[0] } + fsType := csiSource.FSType + if len(fsType) == 0 { + fsType = defaultFSType + } + err = csi.NodePublishVolume( ctx, c.volumeID, @@ -197,7 +204,7 @@ func (c *csiMountMgr) SetUpAt(dir string, fsGroup *int64) error { accessMode, c.volumeInfo, attribs, - "ext4", //TODO needs to be sourced from PV or somewhere else + fsType, ) if err != nil { diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index 49ef6109276..5b3147c8fe5 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -1730,6 +1730,12 @@ type CSIPersistentVolumeSource struct { // Defaults to false (read/write). // +optional ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"` + + // Filesystem type to mount. + // Must be a filesystem type supported by the host operating system. + // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // +optional + FSType string `json:"fsType,omitempty" protobuf:"bytes,4,opt,name=fsType"` } // ContainerPort represents a network port in a single container. From 37d42870eacedab76ac08bb41fec1bfb22edc1dc Mon Sep 17 00:00:00 2001 From: NickrenREN Date: Fri, 12 Jan 2018 18:58:12 +0800 Subject: [PATCH 22/58] auto generated code --- api/openapi-spec/swagger.json | 4 + api/swagger-spec/v1.json | 4 + docs/api-reference/v1/definitions.html | 7 + pkg/apis/core/v1/zz_generated.conversion.go | 2 + .../src/k8s.io/api/core/v1/generated.pb.go | 1587 +++++++++-------- .../src/k8s.io/api/core/v1/generated.proto | 6 + .../core/v1/types_swagger_doc_generated.go | 1 + 7 files changed, 836 insertions(+), 775 deletions(-) diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 795486975c8..9426d4a89a1 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -74526,6 +74526,10 @@ "description": "Driver is the name of the driver to use for this volume. Required.", "type": "string" }, + "fsType": { + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", + "type": "string" + }, "readOnly": { "description": "Optional: The value to pass to ControllerPublishVolumeRequest. Defaults to false (read/write).", "type": "boolean" diff --git a/api/swagger-spec/v1.json b/api/swagger-spec/v1.json index cc2cebe67cf..a76d0f4e5c2 100644 --- a/api/swagger-spec/v1.json +++ b/api/swagger-spec/v1.json @@ -21320,6 +21320,10 @@ "readOnly": { "type": "boolean", "description": "Optional: The value to pass to ControllerPublishVolumeRequest. Defaults to false (read/write)." + }, + "fsType": { + "type": "string", + "description": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified." } } }, diff --git a/docs/api-reference/v1/definitions.html b/docs/api-reference/v1/definitions.html index cbb2f013aad..9d411fd1e70 100755 --- a/docs/api-reference/v1/definitions.html +++ b/docs/api-reference/v1/definitions.html @@ -7857,6 +7857,13 @@ Examples:

boolean

false

+ +

fsType

+

Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.

+

false

+

string

+ + diff --git a/pkg/apis/core/v1/zz_generated.conversion.go b/pkg/apis/core/v1/zz_generated.conversion.go index e8ddfac91fb..a2be2327cc3 100644 --- a/pkg/apis/core/v1/zz_generated.conversion.go +++ b/pkg/apis/core/v1/zz_generated.conversion.go @@ -619,6 +619,7 @@ func autoConvert_v1_CSIPersistentVolumeSource_To_core_CSIPersistentVolumeSource( out.Driver = in.Driver out.VolumeHandle = in.VolumeHandle out.ReadOnly = in.ReadOnly + out.FSType = in.FSType return nil } @@ -631,6 +632,7 @@ func autoConvert_core_CSIPersistentVolumeSource_To_v1_CSIPersistentVolumeSource( out.Driver = in.Driver out.VolumeHandle = in.VolumeHandle out.ReadOnly = in.ReadOnly + out.FSType = in.FSType return nil } diff --git a/staging/src/k8s.io/api/core/v1/generated.pb.go b/staging/src/k8s.io/api/core/v1/generated.pb.go index 61aa1833f85..756e93d6294 100644 --- a/staging/src/k8s.io/api/core/v1/generated.pb.go +++ b/staging/src/k8s.io/api/core/v1/generated.pb.go @@ -1570,6 +1570,10 @@ func (m *CSIPersistentVolumeSource) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0 } i++ + dAtA[i] = 0x22 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.FSType))) + i += copy(dAtA[i:], m.FSType) return i, nil } @@ -10676,6 +10680,8 @@ func (m *CSIPersistentVolumeSource) Size() (n int) { l = len(m.VolumeHandle) n += 1 + l + sovGenerated(uint64(l)) n += 2 + l = len(m.FSType) + n += 1 + l + sovGenerated(uint64(l)) return n } @@ -14053,6 +14059,7 @@ func (this *CSIPersistentVolumeSource) String() string { `Driver:` + fmt.Sprintf("%v", this.Driver) + `,`, `VolumeHandle:` + fmt.Sprintf("%v", this.VolumeHandle) + `,`, `ReadOnly:` + fmt.Sprintf("%v", this.ReadOnly) + `,`, + `FSType:` + fmt.Sprintf("%v", this.FSType) + `,`, `}`, }, "") return s @@ -17838,6 +17845,35 @@ func (m *CSIPersistentVolumeSource) Unmarshal(dAtA []byte) error { } } m.ReadOnly = bool(v != 0) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FSType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FSType = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -49512,779 +49548,780 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 12382 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x90, 0x24, 0x47, - 0x56, 0xd8, 0x55, 0xf7, 0x7c, 0xf5, 0x9b, 0xef, 0xdc, 0x5d, 0xa9, 0x77, 0x24, 0x6d, 0xaf, 0x4a, - 0x77, 0xd2, 0xea, 0x6b, 0xe6, 0xb4, 0x92, 0x4e, 0xe2, 0x74, 0x27, 0x98, 0x99, 0x9e, 0xd9, 0x6d, - 0xed, 0xce, 0x6c, 0x2b, 0x7b, 0x76, 0xf7, 0x4e, 0x88, 0xf3, 0xd5, 0x74, 0xe7, 0xcc, 0x94, 0xa6, - 0xa6, 0xaa, 0x55, 0x55, 0x3d, 0xbb, 0xa3, 0x80, 0x08, 0x5b, 0x06, 0xfc, 0x01, 0x3f, 0x2e, 0x6c, - 0xc2, 0xc6, 0x40, 0xe0, 0x08, 0x1b, 0x07, 0x9c, 0xb1, 0x1d, 0xc6, 0x60, 0xc0, 0x80, 0x6d, 0x8c, - 0x1d, 0x0e, 0xf8, 0x83, 0xc1, 0xfe, 0x71, 0x44, 0x10, 0x1e, 0xc3, 0x40, 0xd8, 0xc1, 0x0f, 0x3b, - 0x6c, 0xf3, 0x8b, 0x31, 0x36, 0x8e, 0xfc, 0xac, 0xcc, 0xea, 0xaa, 0xee, 0x9e, 0xd5, 0xec, 0x48, - 0x5c, 0xdc, 0xbf, 0xee, 0x7c, 0x2f, 0x5f, 0x66, 0xe5, 0xc7, 0xcb, 0x97, 0x2f, 0xdf, 0x07, 0xbc, - 0xb1, 0xfb, 0x7a, 0x34, 0xef, 0x06, 0x0b, 0xbb, 0x9d, 0x4d, 0x12, 0xfa, 0x24, 0x26, 0xd1, 0xc2, - 0x3e, 0xf1, 0x5b, 0x41, 0xb8, 0x20, 0x00, 0x4e, 0xdb, 0x5d, 0x68, 0x06, 0x21, 0x59, 0xd8, 0x7f, - 0x69, 0x61, 0x9b, 0xf8, 0x24, 0x74, 0x62, 0xd2, 0x9a, 0x6f, 0x87, 0x41, 0x1c, 0x20, 0xc4, 0x71, - 0xe6, 0x9d, 0xb6, 0x3b, 0x4f, 0x71, 0xe6, 0xf7, 0x5f, 0x9a, 0x7b, 0x71, 0xdb, 0x8d, 0x77, 0x3a, - 0x9b, 0xf3, 0xcd, 0x60, 0x6f, 0x61, 0x3b, 0xd8, 0x0e, 0x16, 0x18, 0xea, 0x66, 0x67, 0x8b, 0xfd, - 0x63, 0x7f, 0xd8, 0x2f, 0x4e, 0x62, 0x6e, 0x2d, 0x69, 0x86, 0xdc, 0x8f, 0x89, 0x1f, 0xb9, 0x81, - 0x1f, 0xbd, 0xe8, 0xb4, 0xdd, 0x88, 0x84, 0xfb, 0x24, 0x5c, 0x68, 0xef, 0x6e, 0x53, 0x58, 0x64, - 0x22, 0x2c, 0xec, 0xbf, 0xb4, 0x49, 0x62, 0xa7, 0xab, 0x47, 0x73, 0xaf, 0x24, 0xe4, 0xf6, 0x9c, - 0xe6, 0x8e, 0xeb, 0x93, 0xf0, 0x40, 0xd2, 0x58, 0x08, 0x49, 0x14, 0x74, 0xc2, 0x26, 0x39, 0x51, - 0xad, 0x68, 0x61, 0x8f, 0xc4, 0x4e, 0xc6, 0xd7, 0xcf, 0x2d, 0xe4, 0xd5, 0x0a, 0x3b, 0x7e, 0xec, - 0xee, 0x75, 0x37, 0xf3, 0xb9, 0x7e, 0x15, 0xa2, 0xe6, 0x0e, 0xd9, 0x73, 0xba, 0xea, 0xbd, 0x9c, - 0x57, 0xaf, 0x13, 0xbb, 0xde, 0x82, 0xeb, 0xc7, 0x51, 0x1c, 0xa6, 0x2b, 0xd9, 0xdf, 0xb0, 0xe0, - 0xf2, 0xe2, 0xdd, 0xc6, 0x8a, 0xe7, 0x44, 0xb1, 0xdb, 0x5c, 0xf2, 0x82, 0xe6, 0x6e, 0x23, 0x0e, - 0x42, 0x72, 0x27, 0xf0, 0x3a, 0x7b, 0xa4, 0xc1, 0x06, 0x02, 0xbd, 0x00, 0x63, 0xfb, 0xec, 0x7f, - 0xad, 0x5a, 0xb6, 0x2e, 0x5b, 0x57, 0x4a, 0x4b, 0x33, 0xbf, 0x7e, 0x58, 0xf9, 0xd4, 0xd1, 0x61, - 0x65, 0xec, 0x8e, 0x28, 0xc7, 0x0a, 0x03, 0x3d, 0x0d, 0x23, 0x5b, 0xd1, 0xc6, 0x41, 0x9b, 0x94, - 0x0b, 0x0c, 0x77, 0x4a, 0xe0, 0x8e, 0xac, 0x36, 0x68, 0x29, 0x16, 0x50, 0xb4, 0x00, 0xa5, 0xb6, - 0x13, 0xc6, 0x6e, 0xec, 0x06, 0x7e, 0xb9, 0x78, 0xd9, 0xba, 0x32, 0xbc, 0x34, 0x2b, 0x50, 0x4b, - 0x75, 0x09, 0xc0, 0x09, 0x0e, 0xed, 0x46, 0x48, 0x9c, 0xd6, 0x2d, 0xdf, 0x3b, 0x28, 0x0f, 0x5d, - 0xb6, 0xae, 0x8c, 0x25, 0xdd, 0xc0, 0xa2, 0x1c, 0x2b, 0x0c, 0xfb, 0x47, 0x0a, 0x30, 0xb6, 0xb8, - 0xb5, 0xe5, 0xfa, 0x6e, 0x7c, 0x80, 0xee, 0xc0, 0x84, 0x1f, 0xb4, 0x88, 0xfc, 0xcf, 0xbe, 0x62, - 0xfc, 0xea, 0xe5, 0xf9, 0xee, 0x95, 0x39, 0xbf, 0xae, 0xe1, 0x2d, 0xcd, 0x1c, 0x1d, 0x56, 0x26, - 0xf4, 0x12, 0x6c, 0xd0, 0x41, 0x18, 0xc6, 0xdb, 0x41, 0x4b, 0x91, 0x2d, 0x30, 0xb2, 0x95, 0x2c, - 0xb2, 0xf5, 0x04, 0x6d, 0x69, 0xfa, 0xe8, 0xb0, 0x32, 0xae, 0x15, 0x60, 0x9d, 0x08, 0xda, 0x84, - 0x69, 0xfa, 0xd7, 0x8f, 0x5d, 0x45, 0xb7, 0xc8, 0xe8, 0x3e, 0x95, 0x47, 0x57, 0x43, 0x5d, 0x3a, - 0x77, 0x74, 0x58, 0x99, 0x4e, 0x15, 0xe2, 0x34, 0x41, 0xfb, 0x03, 0x98, 0x5a, 0x8c, 0x63, 0xa7, - 0xb9, 0x43, 0x5a, 0x7c, 0x06, 0xd1, 0x2b, 0x30, 0xe4, 0x3b, 0x7b, 0x44, 0xcc, 0xef, 0x65, 0x31, - 0xb0, 0x43, 0xeb, 0xce, 0x1e, 0x39, 0x3e, 0xac, 0xcc, 0xdc, 0xf6, 0xdd, 0xf7, 0x3b, 0x62, 0x55, - 0xd0, 0x32, 0xcc, 0xb0, 0xd1, 0x55, 0x80, 0x16, 0xd9, 0x77, 0x9b, 0xa4, 0xee, 0xc4, 0x3b, 0x62, - 0xbe, 0x91, 0xa8, 0x0b, 0x55, 0x05, 0xc1, 0x1a, 0x96, 0x7d, 0x1f, 0x4a, 0x8b, 0xfb, 0x81, 0xdb, - 0xaa, 0x07, 0xad, 0x08, 0xed, 0xc2, 0x74, 0x3b, 0x24, 0x5b, 0x24, 0x54, 0x45, 0x65, 0xeb, 0x72, - 0xf1, 0xca, 0xf8, 0xd5, 0x2b, 0x99, 0x1f, 0x6b, 0xa2, 0xae, 0xf8, 0x71, 0x78, 0xb0, 0xf4, 0xa8, - 0x68, 0x6f, 0x3a, 0x05, 0xc5, 0x69, 0xca, 0xf6, 0xbf, 0x2b, 0xc0, 0x85, 0xc5, 0x0f, 0x3a, 0x21, - 0xa9, 0xba, 0xd1, 0x6e, 0x7a, 0x85, 0xb7, 0xdc, 0x68, 0x77, 0x3d, 0x19, 0x01, 0xb5, 0xb4, 0xaa, - 0xa2, 0x1c, 0x2b, 0x0c, 0xf4, 0x22, 0x8c, 0xd2, 0xdf, 0xb7, 0x71, 0x4d, 0x7c, 0xf2, 0x39, 0x81, - 0x3c, 0x5e, 0x75, 0x62, 0xa7, 0xca, 0x41, 0x58, 0xe2, 0xa0, 0x35, 0x18, 0x6f, 0xb2, 0x0d, 0xb9, - 0xbd, 0x16, 0xb4, 0x08, 0x9b, 0xcc, 0xd2, 0xd2, 0xf3, 0x14, 0x7d, 0x39, 0x29, 0x3e, 0x3e, 0xac, - 0x94, 0x79, 0xdf, 0x04, 0x09, 0x0d, 0x86, 0xf5, 0xfa, 0xc8, 0x56, 0xfb, 0x6b, 0x88, 0x51, 0x82, - 0x8c, 0xbd, 0x75, 0x45, 0xdb, 0x2a, 0xc3, 0x6c, 0xab, 0x4c, 0x64, 0x6f, 0x13, 0xf4, 0x12, 0x0c, - 0xed, 0xba, 0x7e, 0xab, 0x3c, 0xc2, 0x68, 0x3d, 0x41, 0xe7, 0xfc, 0x86, 0xeb, 0xb7, 0x8e, 0x0f, - 0x2b, 0xb3, 0x46, 0x77, 0x68, 0x21, 0x66, 0xa8, 0xf6, 0x1f, 0x5b, 0x50, 0x61, 0xb0, 0x55, 0xd7, - 0x23, 0x75, 0x12, 0x46, 0x6e, 0x14, 0x13, 0x3f, 0x36, 0x06, 0xf4, 0x2a, 0x40, 0x44, 0x9a, 0x21, - 0x89, 0xb5, 0x21, 0x55, 0x0b, 0xa3, 0xa1, 0x20, 0x58, 0xc3, 0xa2, 0x0c, 0x21, 0xda, 0x71, 0x42, - 0xb6, 0xbe, 0xc4, 0xc0, 0x2a, 0x86, 0xd0, 0x90, 0x00, 0x9c, 0xe0, 0x18, 0x0c, 0xa1, 0xd8, 0x8f, - 0x21, 0xa0, 0x2f, 0xc2, 0x74, 0xd2, 0x58, 0xd4, 0x76, 0x9a, 0x72, 0x00, 0xd9, 0x96, 0x69, 0x98, - 0x20, 0x9c, 0xc6, 0xb5, 0xff, 0xa1, 0x25, 0x16, 0x0f, 0xfd, 0xea, 0x4f, 0xf8, 0xb7, 0xda, 0xbf, - 0x68, 0xc1, 0xe8, 0x92, 0xeb, 0xb7, 0x5c, 0x7f, 0x1b, 0x7d, 0x15, 0xc6, 0xe8, 0xd9, 0xd4, 0x72, - 0x62, 0x47, 0xf0, 0xbd, 0xcf, 0x6a, 0x7b, 0x4b, 0x1d, 0x15, 0xf3, 0xed, 0xdd, 0x6d, 0x5a, 0x10, - 0xcd, 0x53, 0x6c, 0xba, 0xdb, 0x6e, 0x6d, 0xbe, 0x47, 0x9a, 0xf1, 0x1a, 0x89, 0x9d, 0xe4, 0x73, - 0x92, 0x32, 0xac, 0xa8, 0xa2, 0x1b, 0x30, 0x12, 0x3b, 0xe1, 0x36, 0x89, 0x05, 0x03, 0xcc, 0x64, - 0x54, 0xbc, 0x26, 0xa6, 0x3b, 0x92, 0xf8, 0x4d, 0x92, 0x1c, 0x0b, 0x1b, 0xac, 0x2a, 0x16, 0x24, - 0xec, 0x9f, 0xb6, 0xe0, 0xe2, 0x72, 0xa3, 0x96, 0xb3, 0xae, 0x9e, 0x86, 0x91, 0x56, 0xe8, 0xee, - 0x93, 0x50, 0x8c, 0xb3, 0xa2, 0x52, 0x65, 0xa5, 0x58, 0x40, 0xd1, 0xeb, 0x30, 0xc1, 0x0f, 0xa4, - 0xeb, 0x8e, 0xdf, 0xf2, 0xe4, 0x10, 0x9f, 0x17, 0xd8, 0x13, 0x77, 0x34, 0x18, 0x36, 0x30, 0x4f, - 0x38, 0xd0, 0x4d, 0x98, 0x58, 0x76, 0xda, 0xce, 0xa6, 0xeb, 0xb9, 0xb1, 0x4b, 0x22, 0xf4, 0x0c, - 0x14, 0x9d, 0x56, 0x8b, 0xf1, 0xb0, 0xd2, 0xd2, 0x85, 0xa3, 0xc3, 0x4a, 0x71, 0xb1, 0x45, 0x37, - 0x13, 0x28, 0xac, 0x03, 0x4c, 0x31, 0xd0, 0x73, 0x30, 0xd4, 0x0a, 0x83, 0x76, 0xb9, 0xc0, 0x30, - 0x1f, 0xa1, 0xfb, 0xae, 0x1a, 0x06, 0xed, 0x14, 0x2a, 0xc3, 0xb1, 0x7f, 0xb5, 0x00, 0x8f, 0x2f, - 0x93, 0xf6, 0xce, 0x6a, 0x23, 0x67, 0x54, 0xae, 0xc0, 0xd8, 0x5e, 0xe0, 0xbb, 0x71, 0x10, 0x46, - 0xa2, 0x69, 0xb6, 0xdd, 0xd7, 0x44, 0x19, 0x56, 0x50, 0x74, 0x19, 0x86, 0xda, 0x09, 0xab, 0x9e, - 0x90, 0x6c, 0x9e, 0x31, 0x69, 0x06, 0xa1, 0x18, 0x9d, 0x88, 0x84, 0x82, 0x4d, 0x29, 0x8c, 0xdb, - 0x11, 0x09, 0x31, 0x83, 0x24, 0xeb, 0x9d, 0xee, 0x04, 0xb1, 0x87, 0x52, 0xeb, 0x9d, 0x42, 0xb0, - 0x86, 0x85, 0xea, 0x50, 0xe2, 0xff, 0x30, 0xd9, 0x62, 0x1c, 0x29, 0x67, 0x95, 0x34, 0x24, 0x92, - 0x58, 0x25, 0x93, 0x6c, 0x43, 0xc8, 0x42, 0x9c, 0x10, 0x31, 0xe6, 0x69, 0xa4, 0xef, 0x3c, 0xfd, - 0x72, 0x01, 0x10, 0x1f, 0xc2, 0x3f, 0x67, 0x03, 0x77, 0xbb, 0x7b, 0xe0, 0x32, 0x8f, 0xc6, 0x9b, - 0x41, 0xd3, 0xf1, 0xd2, 0x7b, 0xec, 0xb4, 0x46, 0xef, 0x87, 0x2d, 0x40, 0xcb, 0xae, 0xdf, 0x22, - 0xe1, 0x19, 0xc8, 0x85, 0x27, 0xdb, 0x80, 0x37, 0x61, 0x6a, 0xd9, 0x73, 0x89, 0x1f, 0xd7, 0xea, - 0xcb, 0x81, 0xbf, 0xe5, 0x6e, 0xa3, 0xcf, 0xc3, 0x14, 0x15, 0x93, 0x83, 0x4e, 0xdc, 0x20, 0xcd, - 0xc0, 0x67, 0x12, 0x05, 0x15, 0x2e, 0xd1, 0xd1, 0x61, 0x65, 0x6a, 0xc3, 0x80, 0xe0, 0x14, 0xa6, - 0xfd, 0xbb, 0xf4, 0x43, 0x83, 0xbd, 0x76, 0xe0, 0x13, 0x3f, 0x5e, 0x0e, 0xfc, 0x16, 0x97, 0x3c, - 0x3f, 0x0f, 0x43, 0x31, 0xed, 0x38, 0xff, 0xc8, 0xa7, 0xe5, 0xd4, 0xd2, 0xee, 0x1e, 0x1f, 0x56, - 0x1e, 0xe9, 0xae, 0xc1, 0x3e, 0x88, 0xd5, 0x41, 0xdf, 0x06, 0x23, 0x51, 0xec, 0xc4, 0x9d, 0x48, - 0x7c, 0xf6, 0x93, 0xf2, 0xb3, 0x1b, 0xac, 0xf4, 0xf8, 0xb0, 0x32, 0xad, 0xaa, 0xf1, 0x22, 0x2c, - 0x2a, 0xa0, 0x67, 0x61, 0x74, 0x8f, 0x44, 0x91, 0xb3, 0x2d, 0x85, 0x86, 0x69, 0x51, 0x77, 0x74, - 0x8d, 0x17, 0x63, 0x09, 0x47, 0x4f, 0xc1, 0x30, 0x09, 0xc3, 0x20, 0x14, 0xab, 0x6a, 0x52, 0x20, - 0x0e, 0xaf, 0xd0, 0x42, 0xcc, 0x61, 0xf6, 0x7f, 0xb0, 0x60, 0x5a, 0xf5, 0x95, 0xb7, 0x75, 0x06, - 0xa7, 0xc3, 0x3b, 0x00, 0x4d, 0xf9, 0x81, 0x11, 0xe3, 0x77, 0xe3, 0x57, 0x9f, 0xce, 0x5a, 0xc2, - 0xdd, 0xc3, 0x98, 0x50, 0x56, 0x45, 0x11, 0xd6, 0xa8, 0xd9, 0xff, 0xd2, 0x82, 0x73, 0xa9, 0x2f, - 0xba, 0xe9, 0x46, 0x31, 0x7a, 0xb7, 0xeb, 0xab, 0xe6, 0x07, 0xfb, 0x2a, 0x5a, 0x9b, 0x7d, 0x93, - 0x5a, 0x73, 0xb2, 0x44, 0xfb, 0xa2, 0xeb, 0x30, 0xec, 0xc6, 0x64, 0x4f, 0x7e, 0xcc, 0x53, 0x3d, - 0x3f, 0x86, 0xf7, 0x2a, 0x99, 0x91, 0x1a, 0xad, 0x89, 0x39, 0x01, 0xfb, 0x7f, 0x59, 0x50, 0xe2, - 0xcb, 0x76, 0xcd, 0x69, 0x9f, 0xc1, 0x5c, 0xd4, 0x60, 0x88, 0x51, 0xe7, 0x1d, 0x7f, 0x26, 0xbb, - 0xe3, 0xa2, 0x3b, 0xf3, 0x54, 0xf4, 0xe3, 0x22, 0xb6, 0x62, 0x66, 0xb4, 0x08, 0x33, 0x12, 0x73, - 0xaf, 0x41, 0x49, 0x21, 0xa0, 0x19, 0x28, 0xee, 0x12, 0x7e, 0xad, 0x2a, 0x61, 0xfa, 0x13, 0x9d, - 0x87, 0xe1, 0x7d, 0xc7, 0xeb, 0x88, 0xcd, 0x8e, 0xf9, 0x9f, 0xcf, 0x17, 0x5e, 0xb7, 0xec, 0x5f, - 0x62, 0x7b, 0x4c, 0x34, 0xb2, 0xe2, 0xef, 0x0b, 0x66, 0xf2, 0x01, 0x9c, 0xf7, 0x32, 0x78, 0x98, - 0x18, 0x88, 0xc1, 0x79, 0xde, 0xe3, 0xa2, 0xaf, 0xe7, 0xb3, 0xa0, 0x38, 0xb3, 0x0d, 0x7a, 0x0c, - 0x04, 0x6d, 0xba, 0xa2, 0x1c, 0x8f, 0xf5, 0x57, 0x88, 0xcb, 0xb7, 0x44, 0x19, 0x56, 0x50, 0xca, - 0x20, 0xce, 0xab, 0xce, 0xdf, 0x20, 0x07, 0x0d, 0xe2, 0x91, 0x66, 0x1c, 0x84, 0x1f, 0x6b, 0xf7, - 0x9f, 0xe0, 0xa3, 0xcf, 0xf9, 0xcb, 0xb8, 0x20, 0x50, 0xbc, 0x41, 0x0e, 0xf8, 0x54, 0xe8, 0x5f, - 0x57, 0xec, 0xf9, 0x75, 0x3f, 0x63, 0xc1, 0xa4, 0xfa, 0xba, 0x33, 0xd8, 0x48, 0x4b, 0xe6, 0x46, - 0x7a, 0xa2, 0xe7, 0x7a, 0xcc, 0xd9, 0x42, 0x7f, 0xc6, 0x58, 0x80, 0xc0, 0xa9, 0x87, 0x01, 0x1d, - 0x1a, 0xca, 0xb3, 0x3f, 0xce, 0x09, 0x19, 0xe4, 0xbb, 0x6e, 0x90, 0x83, 0x8d, 0x80, 0x8a, 0x0f, - 0xd9, 0xdf, 0x65, 0xcc, 0xda, 0x50, 0xcf, 0x59, 0xfb, 0xb9, 0x02, 0x5c, 0x50, 0x23, 0x60, 0x1c, - 0xd0, 0x7f, 0xde, 0xc7, 0xe0, 0x25, 0x18, 0x6f, 0x91, 0x2d, 0xa7, 0xe3, 0xc5, 0xea, 0xe6, 0x3c, - 0xcc, 0xb5, 0x27, 0xd5, 0xa4, 0x18, 0xeb, 0x38, 0x27, 0x18, 0xb6, 0x9f, 0x18, 0x67, 0xbc, 0x37, - 0x76, 0xe8, 0x0a, 0xa6, 0xd2, 0x9b, 0xa6, 0xff, 0x98, 0xd0, 0xf5, 0x1f, 0x42, 0xd7, 0xf1, 0x14, - 0x0c, 0xbb, 0x7b, 0xf4, 0x2c, 0x2e, 0x98, 0x47, 0x6c, 0x8d, 0x16, 0x62, 0x0e, 0x43, 0x9f, 0x81, - 0xd1, 0x66, 0xb0, 0xb7, 0xe7, 0xf8, 0xad, 0x72, 0x91, 0xc9, 0x93, 0xe3, 0xf4, 0xb8, 0x5e, 0xe6, - 0x45, 0x58, 0xc2, 0xd0, 0xe3, 0x30, 0xe4, 0x84, 0xdb, 0x51, 0x79, 0x88, 0xe1, 0x8c, 0xd1, 0x96, - 0x16, 0xc3, 0xed, 0x08, 0xb3, 0x52, 0x2a, 0x27, 0xde, 0x0b, 0xc2, 0x5d, 0xd7, 0xdf, 0xae, 0xba, - 0x21, 0x13, 0xfa, 0x34, 0x39, 0xf1, 0xae, 0x82, 0x60, 0x0d, 0x0b, 0xad, 0xc2, 0x70, 0x3b, 0x08, - 0xe3, 0xa8, 0x3c, 0xc2, 0x86, 0xfb, 0xc9, 0x9c, 0xad, 0xc4, 0xbf, 0xb6, 0x1e, 0x84, 0x71, 0xf2, - 0x01, 0xf4, 0x5f, 0x84, 0x79, 0x75, 0xf4, 0x6d, 0x50, 0x24, 0xfe, 0x7e, 0x79, 0x94, 0x51, 0x99, - 0xcb, 0xa2, 0xb2, 0xe2, 0xef, 0xdf, 0x71, 0xc2, 0x84, 0xcf, 0xac, 0xf8, 0xfb, 0x98, 0xd6, 0x41, - 0x5f, 0x86, 0x92, 0xd4, 0x9d, 0x46, 0xe5, 0xb1, 0xfc, 0x25, 0x86, 0x05, 0x12, 0x26, 0xef, 0x77, - 0xdc, 0x90, 0xec, 0x11, 0x3f, 0x8e, 0x92, 0xdb, 0xaf, 0x84, 0x46, 0x38, 0xa1, 0x86, 0xbe, 0x2c, - 0xaf, 0x73, 0x6b, 0x41, 0xc7, 0x8f, 0xa3, 0x72, 0x89, 0x75, 0x2f, 0x53, 0xd1, 0x76, 0x27, 0xc1, - 0x4b, 0xdf, 0xf7, 0x78, 0x65, 0x6c, 0x90, 0x42, 0x18, 0x26, 0x3d, 0x77, 0x9f, 0xf8, 0x24, 0x8a, - 0xea, 0x61, 0xb0, 0x49, 0xca, 0xc0, 0x7a, 0x7e, 0x31, 0x5b, 0xff, 0x14, 0x6c, 0x92, 0xa5, 0xd9, - 0xa3, 0xc3, 0xca, 0xe4, 0x4d, 0xbd, 0x0e, 0x36, 0x49, 0xa0, 0xdb, 0x30, 0x45, 0x05, 0x54, 0x37, - 0x21, 0x3a, 0xde, 0x8f, 0x28, 0x93, 0x4e, 0xb1, 0x51, 0x09, 0xa7, 0x88, 0xa0, 0xb7, 0xa0, 0xe4, - 0xb9, 0x5b, 0xa4, 0x79, 0xd0, 0xf4, 0x48, 0x79, 0x82, 0x51, 0xcc, 0xdc, 0x56, 0x37, 0x25, 0x12, - 0xbf, 0x00, 0xa8, 0xbf, 0x38, 0xa9, 0x8e, 0xee, 0xc0, 0x23, 0x31, 0x09, 0xf7, 0x5c, 0xdf, 0xa1, - 0xdb, 0x41, 0xc8, 0x93, 0x4c, 0x8b, 0x37, 0xc9, 0xd6, 0xdb, 0x25, 0x31, 0x74, 0x8f, 0x6c, 0x64, - 0x62, 0xe1, 0x9c, 0xda, 0xe8, 0x16, 0x4c, 0xb3, 0x9d, 0x50, 0xef, 0x78, 0x5e, 0x3d, 0xf0, 0xdc, - 0xe6, 0x41, 0x79, 0x8a, 0x11, 0xfc, 0x8c, 0x54, 0xd3, 0xd5, 0x4c, 0x30, 0xbd, 0xf1, 0x26, 0xff, - 0x70, 0xba, 0x36, 0xda, 0x64, 0x6a, 0x9b, 0x4e, 0xe8, 0xc6, 0x07, 0x74, 0xfd, 0x92, 0xfb, 0x71, - 0x79, 0xba, 0xe7, 0xfd, 0x51, 0x47, 0x55, 0xba, 0x1d, 0xbd, 0x10, 0xa7, 0x09, 0xd2, 0xad, 0x1d, - 0xc5, 0x2d, 0xd7, 0x2f, 0xcf, 0x30, 0x8e, 0xa1, 0x76, 0x46, 0x83, 0x16, 0x62, 0x0e, 0x63, 0x2a, - 0x1b, 0xfa, 0xe3, 0x16, 0xe5, 0xa0, 0xb3, 0x0c, 0x31, 0x51, 0xd9, 0x48, 0x00, 0x4e, 0x70, 0xe8, - 0xb1, 0x1c, 0xc7, 0x07, 0x65, 0xc4, 0x50, 0xd5, 0x76, 0xd9, 0xd8, 0xf8, 0x32, 0xa6, 0xe5, 0xe8, - 0x26, 0x8c, 0x12, 0x7f, 0x7f, 0x35, 0x0c, 0xf6, 0xca, 0xe7, 0xf2, 0xf7, 0xec, 0x0a, 0x47, 0xe1, - 0x0c, 0x3d, 0xb9, 0x00, 0x88, 0x62, 0x2c, 0x49, 0xa0, 0xfb, 0x50, 0xce, 0x98, 0x11, 0x3e, 0x01, - 0xe7, 0xd9, 0x04, 0x7c, 0x41, 0xd4, 0x2d, 0x6f, 0xe4, 0xe0, 0x1d, 0xf7, 0x80, 0xe1, 0x5c, 0xea, - 0xe8, 0xbb, 0x60, 0x92, 0x6f, 0x28, 0xae, 0xef, 0x8d, 0xca, 0x17, 0xd8, 0xd7, 0x5c, 0xce, 0xdf, - 0x9c, 0x1c, 0x71, 0xe9, 0x82, 0xe8, 0xd0, 0xa4, 0x5e, 0x1a, 0x61, 0x93, 0x9a, 0xbd, 0x09, 0x53, - 0x8a, 0x6f, 0xb1, 0xa5, 0x83, 0x2a, 0x30, 0x4c, 0x19, 0xb2, 0xbc, 0xb1, 0x97, 0xe8, 0x4c, 0x31, - 0x3d, 0x1d, 0xe6, 0xe5, 0x6c, 0xa6, 0xdc, 0x0f, 0xc8, 0xd2, 0x41, 0x4c, 0xf8, 0xad, 0xab, 0xa8, - 0xcd, 0x94, 0x04, 0xe0, 0x04, 0xc7, 0xfe, 0x7f, 0x5c, 0xee, 0x49, 0x98, 0xe3, 0x00, 0xc7, 0xc1, - 0x0b, 0x30, 0xb6, 0x13, 0x44, 0x31, 0xc5, 0x66, 0x6d, 0x0c, 0x27, 0x92, 0xce, 0x75, 0x51, 0x8e, - 0x15, 0x06, 0x7a, 0x03, 0x26, 0x9b, 0x7a, 0x03, 0xe2, 0x2c, 0x53, 0x43, 0x60, 0xb4, 0x8e, 0x4d, - 0x5c, 0xf4, 0x3a, 0x8c, 0xb1, 0xd7, 0x9a, 0x66, 0xe0, 0x89, 0xfb, 0x9d, 0x3c, 0x90, 0xc7, 0xea, - 0xa2, 0xfc, 0x58, 0xfb, 0x8d, 0x15, 0x36, 0xbd, 0x73, 0xd3, 0x2e, 0xd4, 0xea, 0xe2, 0x14, 0x51, - 0x77, 0xee, 0xeb, 0xac, 0x14, 0x0b, 0xa8, 0xfd, 0x37, 0x0a, 0xda, 0x28, 0xd3, 0x1b, 0x0b, 0x41, - 0x75, 0x18, 0xbd, 0xe7, 0xb8, 0xb1, 0xeb, 0x6f, 0x0b, 0x71, 0xe1, 0xd9, 0x9e, 0x47, 0x0a, 0xab, - 0x74, 0x97, 0x57, 0xe0, 0x87, 0x9e, 0xf8, 0x83, 0x25, 0x19, 0x4a, 0x31, 0xec, 0xf8, 0x3e, 0xa5, - 0x58, 0x18, 0x94, 0x22, 0xe6, 0x15, 0x38, 0x45, 0xf1, 0x07, 0x4b, 0x32, 0xe8, 0x5d, 0x00, 0xb9, - 0x2c, 0x49, 0x4b, 0xbc, 0x92, 0xbc, 0xd0, 0x9f, 0xe8, 0x86, 0xaa, 0xb3, 0x34, 0x45, 0x8f, 0xd4, - 0xe4, 0x3f, 0xd6, 0xe8, 0xd9, 0x31, 0x13, 0xab, 0xba, 0x3b, 0x83, 0xbe, 0x93, 0x72, 0x02, 0x27, - 0x8c, 0x49, 0x6b, 0x31, 0x16, 0x83, 0xf3, 0xdc, 0x60, 0x52, 0xf1, 0x86, 0xbb, 0x47, 0x74, 0xae, - 0x21, 0x88, 0xe0, 0x84, 0x9e, 0xfd, 0x0b, 0x45, 0x28, 0xe7, 0x75, 0x97, 0x2e, 0x3a, 0x72, 0xdf, - 0x8d, 0x97, 0xa9, 0x34, 0x64, 0x99, 0x8b, 0x6e, 0x45, 0x94, 0x63, 0x85, 0x41, 0x67, 0x3f, 0x72, - 0xb7, 0xe5, 0xa5, 0x66, 0x38, 0x99, 0xfd, 0x06, 0x2b, 0xc5, 0x02, 0x4a, 0xf1, 0x42, 0xe2, 0x44, - 0xe2, 0x19, 0x4e, 0x5b, 0x25, 0x98, 0x95, 0x62, 0x01, 0xd5, 0xf5, 0x11, 0x43, 0x7d, 0xf4, 0x11, - 0xc6, 0x10, 0x0d, 0x9f, 0xee, 0x10, 0xa1, 0xaf, 0x00, 0x6c, 0xb9, 0xbe, 0x1b, 0xed, 0x30, 0xea, - 0x23, 0x27, 0xa6, 0xae, 0x64, 0xa9, 0x55, 0x45, 0x05, 0x6b, 0x14, 0xd1, 0xab, 0x30, 0xae, 0x36, - 0x60, 0xad, 0x5a, 0x1e, 0x35, 0xdf, 0x78, 0x12, 0x6e, 0x54, 0xc5, 0x3a, 0x9e, 0xfd, 0x5e, 0x7a, - 0xbd, 0x88, 0x1d, 0xa0, 0x8d, 0xaf, 0x35, 0xe8, 0xf8, 0x16, 0x7a, 0x8f, 0xaf, 0xfd, 0x6b, 0x45, - 0x98, 0x36, 0x1a, 0xeb, 0x44, 0x03, 0xf0, 0xac, 0x6b, 0xf4, 0x9c, 0x73, 0x62, 0x22, 0xf6, 0x9f, - 0xdd, 0x7f, 0xab, 0xe8, 0x67, 0x21, 0xdd, 0x01, 0xbc, 0x3e, 0xfa, 0x0a, 0x94, 0x3c, 0x27, 0x62, - 0xba, 0x0d, 0x22, 0xf6, 0xdd, 0x20, 0xc4, 0x92, 0x7b, 0x84, 0x13, 0xc5, 0xda, 0x51, 0xc3, 0x69, - 0x27, 0x24, 0xe9, 0x81, 0x4c, 0x65, 0x1f, 0xf9, 0xce, 0xab, 0x3a, 0x41, 0x05, 0xa4, 0x03, 0xcc, - 0x61, 0xe8, 0x75, 0x98, 0x08, 0x09, 0x5b, 0x15, 0xcb, 0x54, 0x94, 0x63, 0xcb, 0x6c, 0x38, 0x91, - 0xf9, 0xb0, 0x06, 0xc3, 0x06, 0x66, 0x22, 0xca, 0x8f, 0xf4, 0x10, 0xe5, 0x9f, 0x85, 0x51, 0xf6, - 0x43, 0xad, 0x00, 0x35, 0x1b, 0x35, 0x5e, 0x8c, 0x25, 0x3c, 0xbd, 0x60, 0xc6, 0x06, 0x5c, 0x30, - 0xcf, 0xc1, 0x54, 0xd5, 0x21, 0x7b, 0x81, 0xbf, 0xe2, 0xb7, 0xda, 0x81, 0xeb, 0xc7, 0xa8, 0x0c, - 0x43, 0xec, 0x74, 0xe0, 0x7b, 0x7b, 0x88, 0x52, 0xc0, 0x43, 0x54, 0x30, 0xb7, 0x7f, 0xbb, 0x00, - 0x93, 0x55, 0xe2, 0x91, 0x98, 0xf0, 0xab, 0x4c, 0x84, 0x56, 0x01, 0x6d, 0x87, 0x4e, 0x93, 0xd4, - 0x49, 0xe8, 0x06, 0x2d, 0x5d, 0xd7, 0x59, 0x64, 0xef, 0x09, 0xe8, 0x5a, 0x17, 0x14, 0x67, 0xd4, - 0x40, 0xef, 0xc0, 0x64, 0x3b, 0x24, 0x86, 0x8a, 0xce, 0xca, 0x93, 0x46, 0xea, 0x3a, 0x22, 0x17, - 0x84, 0x8d, 0x22, 0x6c, 0x92, 0x42, 0xdf, 0x01, 0x33, 0x41, 0xd8, 0xde, 0x71, 0xfc, 0x2a, 0x69, - 0x13, 0xbf, 0x45, 0x25, 0x7d, 0xa1, 0x82, 0x38, 0x7f, 0x74, 0x58, 0x99, 0xb9, 0x95, 0x82, 0xe1, - 0x2e, 0x6c, 0xf4, 0x0e, 0xcc, 0xb6, 0xc3, 0xa0, 0xed, 0x6c, 0xb3, 0x85, 0x22, 0x04, 0x1a, 0xce, - 0x7d, 0x5e, 0x38, 0x3a, 0xac, 0xcc, 0xd6, 0xd3, 0xc0, 0xe3, 0xc3, 0xca, 0x39, 0x36, 0x50, 0xb4, - 0x24, 0x01, 0xe2, 0x6e, 0x32, 0xf6, 0x36, 0x5c, 0xa8, 0x06, 0xf7, 0xfc, 0x7b, 0x4e, 0xd8, 0x5a, - 0xac, 0xd7, 0x34, 0xdd, 0xc1, 0xba, 0xbc, 0xbb, 0xf2, 0xb7, 0xe8, 0xcc, 0x73, 0x4a, 0xab, 0xc9, - 0xe5, 0x97, 0x55, 0xd7, 0x23, 0x39, 0x3a, 0x8a, 0xbf, 0x5d, 0x30, 0x5a, 0x4a, 0xf0, 0xd5, 0xb3, - 0x82, 0x95, 0xfb, 0xac, 0xf0, 0x36, 0x8c, 0x6d, 0xb9, 0xc4, 0x6b, 0x61, 0xb2, 0x25, 0x66, 0xe6, - 0x99, 0xfc, 0xe7, 0xb5, 0x55, 0x8a, 0x29, 0x75, 0x52, 0xfc, 0xe6, 0xbb, 0x2a, 0x2a, 0x63, 0x45, - 0x06, 0xed, 0xc2, 0x8c, 0xbc, 0x5a, 0x49, 0xa8, 0xd8, 0xc4, 0xcf, 0xf6, 0xba, 0xaf, 0x99, 0xc4, - 0xd9, 0x04, 0xe2, 0x14, 0x19, 0xdc, 0x45, 0x98, 0x5e, 0x75, 0xf7, 0xe8, 0x71, 0x35, 0xc4, 0x96, - 0x34, 0xbb, 0xea, 0xb2, 0x5b, 0x3b, 0x2b, 0xb5, 0x7f, 0xcc, 0x82, 0x47, 0xbb, 0x46, 0x46, 0x68, - 0x2f, 0x4e, 0x79, 0x16, 0xd2, 0xda, 0x84, 0x42, 0x7f, 0x6d, 0x82, 0xfd, 0x8f, 0x2c, 0x38, 0xbf, - 0xb2, 0xd7, 0x8e, 0x0f, 0xaa, 0xae, 0xf9, 0xf4, 0xf1, 0x1a, 0x8c, 0xec, 0x91, 0x96, 0xdb, 0xd9, - 0x13, 0x33, 0x57, 0x91, 0x2c, 0x7d, 0x8d, 0x95, 0x1e, 0x1f, 0x56, 0x26, 0x1b, 0x71, 0x10, 0x3a, - 0xdb, 0x84, 0x17, 0x60, 0x81, 0xce, 0x0e, 0x46, 0xf7, 0x03, 0x72, 0xd3, 0xdd, 0x73, 0xe5, 0x73, - 0x69, 0x4f, 0x8d, 0xda, 0xbc, 0x1c, 0xd0, 0xf9, 0xb7, 0x3b, 0x8e, 0x1f, 0xbb, 0xf1, 0x81, 0x78, - 0xd5, 0x91, 0x44, 0x70, 0x42, 0xcf, 0xfe, 0x86, 0x05, 0xd3, 0x92, 0x97, 0x2c, 0xb6, 0x5a, 0x21, - 0x89, 0x22, 0x34, 0x07, 0x05, 0xb7, 0x2d, 0x7a, 0x09, 0xa2, 0x97, 0x85, 0x5a, 0x1d, 0x17, 0xdc, - 0x36, 0xaa, 0x43, 0x89, 0xbf, 0xba, 0x26, 0x8b, 0x6b, 0xa0, 0xb7, 0x5b, 0xd6, 0x83, 0x0d, 0x59, - 0x13, 0x27, 0x44, 0xa4, 0x54, 0xcc, 0xce, 0xa1, 0xa2, 0xf9, 0x24, 0x74, 0x5d, 0x94, 0x63, 0x85, - 0x81, 0xae, 0xc0, 0x98, 0x1f, 0xb4, 0xf8, 0x23, 0x38, 0xdf, 0xd3, 0x6c, 0xc9, 0xae, 0x8b, 0x32, - 0xac, 0xa0, 0xf6, 0x0f, 0x5a, 0x30, 0x21, 0xbf, 0x6c, 0x40, 0x01, 0x9d, 0x6e, 0xad, 0x44, 0x38, - 0x4f, 0xb6, 0x16, 0x15, 0xb0, 0x19, 0xc4, 0x90, 0xab, 0x8b, 0x27, 0x91, 0xab, 0xed, 0x1f, 0x2d, - 0xc0, 0x94, 0xec, 0x4e, 0xa3, 0xb3, 0x19, 0x91, 0x18, 0x6d, 0x40, 0xc9, 0xe1, 0x43, 0x4e, 0xe4, - 0x8a, 0x7d, 0x2a, 0xfb, 0x42, 0x67, 0xcc, 0x4f, 0x22, 0xea, 0x2c, 0xca, 0xda, 0x38, 0x21, 0x84, - 0x3c, 0x98, 0xf5, 0x83, 0x98, 0x1d, 0x7b, 0x0a, 0xde, 0xeb, 0xd9, 0x21, 0x4d, 0xfd, 0xa2, 0xa0, - 0x3e, 0xbb, 0x9e, 0xa6, 0x82, 0xbb, 0x09, 0xa3, 0x15, 0xa9, 0x44, 0x2a, 0xe6, 0x5f, 0xe1, 0xf4, - 0x59, 0xc8, 0xd6, 0x21, 0xd9, 0xbf, 0x62, 0x41, 0x49, 0xa2, 0x9d, 0xc5, 0x0b, 0xd3, 0x1a, 0x8c, - 0x46, 0x6c, 0x12, 0xe4, 0xd0, 0xd8, 0xbd, 0x3a, 0xce, 0xe7, 0x2b, 0x39, 0xcd, 0xf9, 0xff, 0x08, - 0x4b, 0x1a, 0x4c, 0x0b, 0xae, 0xba, 0xff, 0x09, 0xd1, 0x82, 0xab, 0xfe, 0xe4, 0x9c, 0x30, 0xff, - 0x8d, 0xf5, 0x59, 0x53, 0x15, 0x50, 0xa1, 0xb3, 0x1d, 0x92, 0x2d, 0xf7, 0x7e, 0x5a, 0xe8, 0xac, - 0xb3, 0x52, 0x2c, 0xa0, 0xe8, 0x5d, 0x98, 0x68, 0x4a, 0xe5, 0x71, 0xc2, 0x06, 0x9e, 0xee, 0xa9, - 0x8a, 0x57, 0xaf, 0x36, 0xdc, 0x40, 0x6e, 0x59, 0xab, 0x8f, 0x0d, 0x6a, 0xe6, 0xbb, 0x7f, 0xb1, - 0xdf, 0xbb, 0x7f, 0x42, 0x37, 0xf7, 0xe5, 0xda, 0xfe, 0x71, 0x0b, 0x46, 0xb8, 0x0a, 0x72, 0x30, - 0x9d, 0xad, 0xf6, 0x0a, 0x95, 0x8c, 0xdd, 0x1d, 0x5a, 0x28, 0x1e, 0xa5, 0xd0, 0x1a, 0x94, 0xd8, - 0x0f, 0xa6, 0x8a, 0x29, 0xe6, 0x5b, 0x06, 0xf2, 0x56, 0xf5, 0x0e, 0xde, 0x91, 0xd5, 0x70, 0x42, - 0xc1, 0xfe, 0xa1, 0x22, 0x65, 0x55, 0x09, 0xaa, 0x71, 0x82, 0x5b, 0x0f, 0xef, 0x04, 0x2f, 0x3c, - 0xac, 0x13, 0x7c, 0x1b, 0xa6, 0x9b, 0xda, 0x93, 0x57, 0x32, 0x93, 0x57, 0x7a, 0x2e, 0x12, 0xed, - 0x75, 0x8c, 0xab, 0xe1, 0x96, 0x4d, 0x22, 0x38, 0x4d, 0x15, 0x7d, 0x27, 0x4c, 0xf0, 0x79, 0x16, - 0xad, 0x0c, 0xb1, 0x56, 0x3e, 0x93, 0xbf, 0x5e, 0xf4, 0x26, 0xd8, 0x4a, 0x6c, 0x68, 0xd5, 0xb1, - 0x41, 0xcc, 0xfe, 0x85, 0x31, 0x18, 0x5e, 0xd9, 0x27, 0x7e, 0x7c, 0x06, 0x0c, 0xa9, 0x09, 0x53, - 0xae, 0xbf, 0x1f, 0x78, 0xfb, 0xa4, 0xc5, 0xe1, 0x27, 0x39, 0x5c, 0x1f, 0x11, 0xa4, 0xa7, 0x6a, - 0x06, 0x09, 0x9c, 0x22, 0xf9, 0x30, 0x6e, 0xed, 0xd7, 0x60, 0x84, 0xcf, 0xbd, 0xb8, 0xb2, 0x67, - 0x2a, 0xd8, 0xd9, 0x20, 0x8a, 0x5d, 0x90, 0x68, 0x14, 0xb8, 0x46, 0x5f, 0x54, 0x47, 0xef, 0xc1, - 0xd4, 0x96, 0x1b, 0x46, 0x31, 0xbd, 0x6e, 0x47, 0xb1, 0xb3, 0xd7, 0x7e, 0x80, 0x5b, 0xba, 0x1a, - 0x87, 0x55, 0x83, 0x12, 0x4e, 0x51, 0x46, 0xdb, 0x30, 0x49, 0x2f, 0x8e, 0x49, 0x53, 0xa3, 0x27, - 0x6e, 0x4a, 0xa9, 0xe1, 0x6e, 0xea, 0x84, 0xb0, 0x49, 0x97, 0x32, 0x93, 0x26, 0xbb, 0x68, 0x8e, - 0x31, 0x89, 0x42, 0x31, 0x13, 0x7e, 0xc3, 0xe4, 0x30, 0xca, 0x93, 0x98, 0xa9, 0x48, 0xc9, 0xe4, - 0x49, 0x9a, 0x41, 0xc8, 0x57, 0xa1, 0x44, 0xe8, 0x10, 0x52, 0xc2, 0xe2, 0xb1, 0x61, 0x61, 0xb0, - 0xbe, 0xae, 0xb9, 0xcd, 0x30, 0x30, 0xf5, 0x23, 0x2b, 0x92, 0x12, 0x4e, 0x88, 0xa2, 0x65, 0x18, - 0x89, 0x48, 0xe8, 0x92, 0x48, 0x3c, 0x3b, 0xf4, 0x98, 0x46, 0x86, 0xc6, 0x4d, 0x48, 0xf9, 0x6f, - 0x2c, 0xaa, 0xd2, 0xe5, 0xe5, 0xb0, 0xdb, 0x10, 0x7b, 0x69, 0xd0, 0x96, 0xd7, 0x22, 0x2b, 0xc5, - 0x02, 0x8a, 0xde, 0x82, 0xd1, 0x90, 0x78, 0x4c, 0x01, 0x37, 0x39, 0xf8, 0x22, 0xe7, 0xfa, 0x3c, - 0x5e, 0x0f, 0x4b, 0x02, 0xe8, 0x06, 0xa0, 0x90, 0x50, 0x19, 0xc2, 0xf5, 0xb7, 0x95, 0x01, 0x85, - 0x78, 0x3f, 0x78, 0x4c, 0xb4, 0x7f, 0x0e, 0x27, 0x18, 0x7e, 0x1c, 0x06, 0x9e, 0x47, 0x42, 0x9c, - 0x51, 0x0d, 0x5d, 0x83, 0x59, 0x55, 0x5a, 0xf3, 0xa3, 0xd8, 0xf1, 0x9b, 0x84, 0x3d, 0x1d, 0x94, - 0x12, 0xa9, 0x08, 0xa7, 0x11, 0x70, 0x77, 0x1d, 0xfb, 0xeb, 0x54, 0x9c, 0xa1, 0xa3, 0x75, 0x06, - 0xb2, 0xc0, 0x9b, 0xa6, 0x2c, 0x70, 0x31, 0x77, 0xe6, 0x72, 0xe4, 0x80, 0x23, 0x0b, 0xc6, 0xb5, - 0x99, 0x4d, 0xd6, 0xac, 0xd5, 0x63, 0xcd, 0x76, 0x60, 0x86, 0xae, 0xf4, 0x5b, 0x9b, 0xcc, 0x9b, - 0xa2, 0xc5, 0x16, 0x66, 0xe1, 0xc1, 0x16, 0x66, 0x59, 0x34, 0x30, 0x73, 0x33, 0x45, 0x10, 0x77, - 0x35, 0x81, 0x5e, 0x93, 0xda, 0xa8, 0xa2, 0x61, 0x18, 0xc5, 0x35, 0x4d, 0xc7, 0x87, 0x95, 0x19, - 0xed, 0x43, 0x74, 0xed, 0x93, 0xfd, 0x55, 0xf9, 0x8d, 0x9c, 0xd9, 0x2c, 0x40, 0xa9, 0xa9, 0x16, - 0x8b, 0x65, 0xda, 0xd2, 0xaa, 0xe5, 0x80, 0x13, 0x1c, 0xba, 0x47, 0xe9, 0x15, 0x24, 0x6d, 0xcb, - 0x47, 0x2f, 0x28, 0x98, 0x41, 0xec, 0x97, 0x01, 0x56, 0xee, 0x93, 0x26, 0x5f, 0xea, 0xfa, 0xa3, - 0xae, 0x95, 0xff, 0xa8, 0x6b, 0xff, 0x47, 0x0b, 0xa6, 0x56, 0x97, 0x8d, 0x6b, 0xe2, 0x3c, 0x00, - 0xbf, 0x1b, 0xdd, 0xbd, 0xbb, 0x2e, 0xdf, 0x2b, 0xb8, 0xca, 0x59, 0x95, 0x62, 0x0d, 0x03, 0x5d, - 0x84, 0xa2, 0xd7, 0xf1, 0xc5, 0x95, 0x65, 0xf4, 0xe8, 0xb0, 0x52, 0xbc, 0xd9, 0xf1, 0x31, 0x2d, - 0xd3, 0xcc, 0xe7, 0x8a, 0x03, 0x9b, 0xcf, 0xf5, 0xf5, 0x92, 0x40, 0x15, 0x18, 0xbe, 0x77, 0xcf, - 0x6d, 0x45, 0xe5, 0xe1, 0xe4, 0x2d, 0xe5, 0xee, 0xdd, 0x5a, 0x35, 0xc2, 0xbc, 0xdc, 0xfe, 0x5a, - 0x11, 0xe6, 0x56, 0x3d, 0x72, 0xff, 0x23, 0xda, 0xe3, 0x0e, 0x6a, 0xfc, 0x77, 0x32, 0x79, 0xf1, - 0xa4, 0x96, 0x8e, 0xfd, 0xc7, 0x63, 0x0b, 0x46, 0xb9, 0x81, 0x00, 0x1f, 0x91, 0xf1, 0xab, 0x6f, - 0x64, 0xb5, 0x9e, 0x3f, 0x20, 0xf3, 0x42, 0x3b, 0xc7, 0xed, 0xa6, 0xd4, 0x49, 0x2b, 0x4a, 0xb1, - 0x24, 0x3e, 0xf7, 0x79, 0x98, 0xd0, 0x31, 0x4f, 0x64, 0x40, 0xf5, 0x97, 0x8a, 0x30, 0x43, 0x7b, - 0xf0, 0x50, 0x27, 0xe2, 0x76, 0xf7, 0x44, 0x9c, 0xb6, 0xdd, 0x69, 0xff, 0xd9, 0x78, 0x37, 0x3d, - 0x1b, 0x2f, 0xe5, 0xcd, 0xc6, 0x59, 0xcf, 0xc1, 0x5f, 0xb6, 0xe0, 0xdc, 0xaa, 0x17, 0x34, 0x77, - 0x53, 0x26, 0xb1, 0xaf, 0xc2, 0x38, 0xe5, 0xe3, 0x91, 0xe1, 0x0c, 0x60, 0xb8, 0x87, 0x08, 0x10, - 0xd6, 0xf1, 0xb4, 0x6a, 0xb7, 0x6f, 0xd7, 0xaa, 0x59, 0x5e, 0x25, 0x02, 0x84, 0x75, 0x3c, 0xfb, - 0x37, 0x2d, 0x78, 0xe2, 0xda, 0xf2, 0x4a, 0xb2, 0x14, 0xbb, 0x1c, 0x5b, 0xe8, 0x2d, 0xb0, 0xa5, - 0x75, 0x25, 0xb9, 0x05, 0x56, 0x59, 0x2f, 0x04, 0xf4, 0x93, 0xe2, 0xb4, 0xf5, 0x53, 0x16, 0x9c, - 0xbb, 0xe6, 0xc6, 0xf4, 0x58, 0x4e, 0xbb, 0x58, 0xd0, 0x73, 0x39, 0x72, 0xe3, 0x20, 0x3c, 0x48, - 0xbb, 0x58, 0x60, 0x05, 0xc1, 0x1a, 0x16, 0x6f, 0x79, 0xdf, 0x8d, 0x68, 0x4f, 0x0b, 0xa6, 0x2a, - 0x0a, 0x8b, 0x72, 0xac, 0x30, 0xe8, 0x87, 0xb5, 0xdc, 0x90, 0x5d, 0x25, 0x0e, 0x04, 0x87, 0x55, - 0x1f, 0x56, 0x95, 0x00, 0x9c, 0xe0, 0xd8, 0x3f, 0x66, 0xc1, 0x85, 0x6b, 0x5e, 0x27, 0x8a, 0x49, - 0xb8, 0x15, 0x19, 0x9d, 0x7d, 0x19, 0x4a, 0x44, 0x5e, 0xd7, 0x45, 0x5f, 0x95, 0x80, 0xa9, 0xee, - 0xf1, 0xdc, 0xbf, 0x43, 0xe1, 0x0d, 0x60, 0x5f, 0x7e, 0x32, 0xbb, 0xe8, 0x9f, 0x2d, 0xc0, 0xe4, - 0xf5, 0x8d, 0x8d, 0xfa, 0x35, 0x12, 0x8b, 0x53, 0xac, 0xbf, 0xaa, 0x19, 0x6b, 0x1a, 0xb3, 0x5e, - 0x97, 0xa2, 0x4e, 0xec, 0x7a, 0xf3, 0xdc, 0xa1, 0x70, 0xbe, 0xe6, 0xc7, 0xb7, 0xc2, 0x46, 0x1c, - 0xba, 0xfe, 0x76, 0xa6, 0x8e, 0x4d, 0x9e, 0xb5, 0xc5, 0xbc, 0xb3, 0x16, 0xbd, 0x0c, 0x23, 0xcc, - 0xa3, 0x51, 0x5e, 0x4f, 0x1e, 0x53, 0x77, 0x0a, 0x56, 0x7a, 0x7c, 0x58, 0x29, 0xdd, 0xc6, 0x35, - 0xfe, 0x07, 0x0b, 0x54, 0x74, 0x1b, 0xc6, 0x77, 0xe2, 0xb8, 0x7d, 0x9d, 0x38, 0x2d, 0x12, 0x4a, - 0xee, 0x70, 0x29, 0x8b, 0x3b, 0xd0, 0x41, 0xe0, 0x68, 0xc9, 0x86, 0x4a, 0xca, 0x22, 0xac, 0xd3, - 0xb1, 0x1b, 0x00, 0x09, 0xec, 0x94, 0xf4, 0x0b, 0xf6, 0x1f, 0x58, 0x30, 0xca, 0x9d, 0x4b, 0x42, - 0xf4, 0x05, 0x18, 0x22, 0xf7, 0x49, 0x53, 0x48, 0x8e, 0x99, 0x1d, 0x4e, 0x04, 0x0f, 0xae, 0x2d, - 0xa7, 0xff, 0x31, 0xab, 0x85, 0xae, 0xc3, 0x28, 0xed, 0xed, 0x35, 0xe5, 0x69, 0xf3, 0x64, 0xde, - 0x17, 0xab, 0x69, 0xe7, 0xb2, 0x8a, 0x28, 0xc2, 0xb2, 0x3a, 0xd3, 0xfc, 0x36, 0xdb, 0x0d, 0xca, - 0xc0, 0xe2, 0x5e, 0xe7, 0xec, 0xc6, 0x72, 0x9d, 0x23, 0x09, 0x6a, 0x5c, 0xf3, 0x2b, 0x0b, 0x71, - 0x42, 0xc4, 0xde, 0x80, 0x12, 0x9d, 0xd4, 0x45, 0xcf, 0x75, 0x7a, 0x2b, 0x9d, 0x9f, 0x87, 0x92, - 0x54, 0x00, 0x47, 0xc2, 0xfd, 0x85, 0x51, 0x95, 0xfa, 0xe1, 0x08, 0x27, 0x70, 0x7b, 0x0b, 0xce, - 0x33, 0x6b, 0x0a, 0x27, 0xde, 0x31, 0xf6, 0x58, 0xff, 0xc5, 0xfc, 0x82, 0xb8, 0x88, 0xf1, 0x99, - 0x29, 0x6b, 0xf6, 0xfa, 0x13, 0x92, 0x62, 0x72, 0x29, 0xb3, 0xff, 0x68, 0x08, 0x1e, 0xab, 0x35, - 0xf2, 0xfd, 0x8e, 0x5e, 0x87, 0x09, 0x2e, 0xa6, 0xd1, 0xa5, 0xed, 0x78, 0xa2, 0x5d, 0xf5, 0xd6, - 0xb8, 0xa1, 0xc1, 0xb0, 0x81, 0x89, 0x9e, 0x80, 0xa2, 0xfb, 0xbe, 0x9f, 0x36, 0xce, 0xad, 0xbd, - 0xbd, 0x8e, 0x69, 0x39, 0x05, 0x53, 0x89, 0x8f, 0xb3, 0x52, 0x05, 0x56, 0x52, 0xdf, 0x9b, 0x30, - 0xe5, 0x46, 0xcd, 0xc8, 0xad, 0xf9, 0x94, 0xcf, 0x24, 0x3e, 0x6b, 0x89, 0x92, 0x80, 0x76, 0x5a, - 0x41, 0x71, 0x0a, 0x5b, 0xe3, 0xeb, 0xc3, 0x03, 0x4b, 0x8d, 0x7d, 0xfd, 0x41, 0xa8, 0x40, 0xdc, - 0x66, 0x5f, 0x17, 0x31, 0x43, 0x41, 0x21, 0x10, 0xf3, 0x0f, 0x8e, 0xb0, 0x84, 0xd1, 0x1b, 0x58, - 0x73, 0xc7, 0x69, 0x2f, 0x76, 0xe2, 0x9d, 0xaa, 0x1b, 0x35, 0x83, 0x7d, 0x12, 0x1e, 0xb0, 0xcb, - 0xf3, 0x58, 0x72, 0x03, 0x53, 0x80, 0xe5, 0xeb, 0x8b, 0x75, 0x8a, 0x89, 0xbb, 0xeb, 0x98, 0x52, - 0x21, 0x9c, 0x86, 0x54, 0xb8, 0x08, 0xd3, 0xb2, 0x99, 0x06, 0x89, 0xd8, 0x19, 0x31, 0xce, 0x3a, - 0xa6, 0xbc, 0x49, 0x45, 0xb1, 0xea, 0x56, 0x1a, 0x1f, 0xbd, 0x06, 0x93, 0xae, 0xef, 0xc6, 0xae, - 0x13, 0x07, 0x21, 0x3b, 0x61, 0xf9, 0x3d, 0x99, 0x3d, 0x8a, 0xd6, 0x74, 0x00, 0x36, 0xf1, 0xec, - 0x3f, 0x1c, 0x82, 0x59, 0x36, 0x6d, 0xdf, 0x5a, 0x61, 0x9f, 0x98, 0x15, 0x76, 0xbb, 0x7b, 0x85, - 0x9d, 0x86, 0xb8, 0xfb, 0x71, 0x2e, 0xb3, 0xf7, 0xa0, 0xa4, 0xec, 0xab, 0xa5, 0x8b, 0x80, 0x95, - 0xe3, 0x22, 0xd0, 0x5f, 0xfa, 0x90, 0xcf, 0xb8, 0xc5, 0xcc, 0x67, 0xdc, 0xbf, 0x63, 0x41, 0x62, - 0x66, 0x8a, 0xae, 0x43, 0xa9, 0x1d, 0x30, 0x53, 0x8e, 0x50, 0xda, 0x47, 0x3d, 0x96, 0x79, 0x50, - 0xf1, 0x43, 0x91, 0x8f, 0x5f, 0x5d, 0xd6, 0xc0, 0x49, 0x65, 0xb4, 0x04, 0xa3, 0xed, 0x90, 0x34, - 0x62, 0xe6, 0x28, 0xd9, 0x97, 0x0e, 0x5f, 0x23, 0x1c, 0x1f, 0xcb, 0x8a, 0xf6, 0xcf, 0x59, 0x00, - 0xfc, 0xa5, 0xd4, 0xf1, 0xb7, 0xc9, 0x19, 0x68, 0x7f, 0xab, 0x30, 0x14, 0xb5, 0x49, 0xb3, 0x97, - 0x91, 0x4d, 0xd2, 0x9f, 0x46, 0x9b, 0x34, 0x93, 0x01, 0xa7, 0xff, 0x30, 0xab, 0x6d, 0x7f, 0x1f, - 0xc0, 0x54, 0x82, 0x56, 0x8b, 0xc9, 0x1e, 0x7a, 0xd1, 0x70, 0x43, 0xbb, 0x98, 0x72, 0x43, 0x2b, - 0x31, 0x6c, 0x4d, 0xd1, 0xf8, 0x1e, 0x14, 0xf7, 0x9c, 0xfb, 0x42, 0x93, 0xf4, 0x7c, 0xef, 0x6e, - 0x50, 0xfa, 0xf3, 0x6b, 0xce, 0x7d, 0x7e, 0x67, 0x7a, 0x5e, 0x2e, 0x90, 0x35, 0xe7, 0xfe, 0x31, - 0x37, 0xa5, 0x61, 0x4c, 0xea, 0xa6, 0x1b, 0xc5, 0x1f, 0xfe, 0x97, 0xe4, 0x3f, 0x5b, 0x76, 0xb4, - 0x11, 0xd6, 0x96, 0xeb, 0x8b, 0x77, 0xc3, 0x81, 0xda, 0x72, 0xfd, 0x74, 0x5b, 0xae, 0x3f, 0x40, - 0x5b, 0xae, 0x8f, 0x3e, 0x80, 0x51, 0xf1, 0x46, 0xcf, 0xec, 0xe7, 0x4d, 0x2d, 0x55, 0x5e, 0x7b, - 0xe2, 0x89, 0x9f, 0xb7, 0xb9, 0x20, 0xef, 0x84, 0xa2, 0xb4, 0x6f, 0xbb, 0xb2, 0x41, 0xf4, 0xb7, - 0x2c, 0x98, 0x12, 0xbf, 0x31, 0x79, 0xbf, 0x43, 0xa2, 0x58, 0xc8, 0x9e, 0x9f, 0x1b, 0xbc, 0x0f, - 0xa2, 0x22, 0xef, 0xca, 0xe7, 0x24, 0x9b, 0x35, 0x81, 0x7d, 0x7b, 0x94, 0xea, 0x05, 0xfa, 0x27, - 0x16, 0x9c, 0xdf, 0x73, 0xee, 0xf3, 0x16, 0x79, 0x19, 0x76, 0x62, 0x37, 0x10, 0xfe, 0x00, 0x5f, - 0x18, 0x6c, 0xfa, 0xbb, 0xaa, 0xf3, 0x4e, 0x4a, 0xd3, 0xe1, 0xf3, 0x59, 0x28, 0x7d, 0xbb, 0x9a, - 0xd9, 0xaf, 0xb9, 0x2d, 0x18, 0x93, 0xeb, 0x2d, 0xe3, 0xe6, 0x5d, 0xd5, 0x05, 0xeb, 0x13, 0x9b, - 0x48, 0x68, 0x37, 0x75, 0xd6, 0x8e, 0x58, 0x6b, 0x0f, 0xb5, 0x9d, 0xf7, 0x60, 0x42, 0x5f, 0x63, - 0x0f, 0xb5, 0xad, 0xf7, 0xe1, 0x5c, 0xc6, 0x5a, 0x7a, 0xa8, 0x4d, 0xde, 0x83, 0x8b, 0xb9, 0xeb, - 0xe3, 0x61, 0x36, 0x6c, 0xff, 0xac, 0xa5, 0xf3, 0xc1, 0x33, 0x50, 0xc1, 0x2f, 0x9b, 0x2a, 0xf8, - 0x4b, 0xbd, 0x77, 0x4e, 0x8e, 0x1e, 0xfe, 0x5d, 0xbd, 0xd3, 0x94, 0xab, 0xa3, 0xb7, 0x60, 0xc4, - 0xa3, 0x25, 0xd2, 0x38, 0xc4, 0xee, 0xbf, 0x23, 0x13, 0x59, 0x8a, 0x95, 0x47, 0x58, 0x50, 0xb0, - 0x7f, 0xd1, 0x82, 0xa1, 0x33, 0x18, 0x09, 0x6c, 0x8e, 0xc4, 0x8b, 0xb9, 0xa4, 0x45, 0x64, 0xa2, - 0x79, 0xec, 0xdc, 0x5b, 0x91, 0xd1, 0x97, 0x72, 0x06, 0xe6, 0xff, 0x16, 0x60, 0x9c, 0x36, 0x25, - 0xad, 0x18, 0xdf, 0x80, 0x49, 0xcf, 0xd9, 0x24, 0x9e, 0x7c, 0xc7, 0x4d, 0x2b, 0x4c, 0x6e, 0xea, - 0x40, 0x6c, 0xe2, 0xd2, 0xca, 0x5b, 0xfa, 0x93, 0xb6, 0x90, 0x5f, 0x54, 0x65, 0xe3, 0xbd, 0x1b, - 0x9b, 0xb8, 0xf4, 0xee, 0x7e, 0xcf, 0x89, 0x9b, 0x3b, 0x42, 0x99, 0xa2, 0xba, 0x7b, 0x97, 0x16, - 0x62, 0x0e, 0xa3, 0x02, 0x9c, 0x5c, 0x9d, 0x77, 0xe8, 0xcd, 0x30, 0xf0, 0x85, 0x78, 0xac, 0x04, - 0x38, 0x6c, 0x82, 0x71, 0x1a, 0x3f, 0xc3, 0x1f, 0x7d, 0x98, 0xd9, 0x68, 0x0e, 0xe0, 0x8f, 0x8e, - 0xea, 0x70, 0xde, 0xf5, 0x9b, 0x5e, 0xa7, 0x45, 0x6e, 0xfb, 0x5c, 0xba, 0xf3, 0xdc, 0x0f, 0x48, - 0x4b, 0x08, 0xd0, 0xca, 0x9c, 0xb6, 0x96, 0x81, 0x83, 0x33, 0x6b, 0xda, 0x7f, 0x01, 0xce, 0xdd, - 0x0c, 0x9c, 0xd6, 0x92, 0xe3, 0x39, 0x7e, 0x93, 0x84, 0x35, 0x7f, 0xbb, 0xaf, 0x95, 0x98, 0x6e, - 0xd3, 0x55, 0xe8, 0x67, 0xd3, 0x65, 0xef, 0x00, 0xd2, 0x1b, 0x10, 0xb6, 0xc9, 0x18, 0x46, 0x5d, - 0xde, 0x94, 0x58, 0xfe, 0xcf, 0x64, 0x4b, 0xd7, 0x5d, 0x3d, 0xd3, 0xac, 0x6e, 0x79, 0x01, 0x96, - 0x84, 0xec, 0xd7, 0x21, 0xd3, 0x1f, 0xb1, 0xbf, 0xda, 0xc6, 0x7e, 0x15, 0x66, 0x59, 0xcd, 0x93, - 0xa9, 0x14, 0xec, 0xbf, 0x66, 0xc1, 0xf4, 0x7a, 0x2a, 0x82, 0xc4, 0xd3, 0xec, 0xad, 0x35, 0x43, - 0xef, 0xde, 0x60, 0xa5, 0x58, 0x40, 0x4f, 0x5d, 0xbf, 0xf7, 0x67, 0x16, 0x94, 0x54, 0x70, 0x9a, - 0x33, 0x10, 0x6a, 0x97, 0x0d, 0xa1, 0x36, 0x53, 0xef, 0xa4, 0xba, 0x93, 0x27, 0xd3, 0xa2, 0x1b, - 0x2a, 0x16, 0x42, 0x0f, 0x95, 0x53, 0x42, 0x86, 0x7b, 0xce, 0x4f, 0x99, 0x01, 0x13, 0x64, 0x74, - 0x04, 0x66, 0xa6, 0xa5, 0x70, 0x3f, 0x21, 0x66, 0x5a, 0xaa, 0x3f, 0x39, 0xdc, 0xaf, 0xae, 0x75, - 0x99, 0x9d, 0x0a, 0xdf, 0xce, 0x5c, 0x19, 0xd8, 0xde, 0x54, 0x21, 0x48, 0x2a, 0xc2, 0x35, 0x41, - 0x94, 0x1e, 0x33, 0x46, 0x26, 0xfe, 0xf1, 0x40, 0x42, 0x49, 0x15, 0xfb, 0x3a, 0x4c, 0xa7, 0x06, - 0x0c, 0xbd, 0x0a, 0xc3, 0xed, 0x1d, 0x27, 0x22, 0x29, 0xd3, 0xd4, 0xe1, 0x3a, 0x2d, 0x3c, 0x3e, - 0xac, 0x4c, 0xa9, 0x0a, 0xac, 0x04, 0x73, 0x6c, 0xfb, 0x7f, 0x5a, 0x30, 0xb4, 0x1e, 0xb4, 0xce, - 0x62, 0x31, 0xbd, 0x69, 0x2c, 0xa6, 0xc7, 0xf3, 0xc2, 0xb0, 0xe5, 0xae, 0xa3, 0xd5, 0xd4, 0x3a, - 0xba, 0x94, 0x4b, 0xa1, 0xf7, 0x12, 0xda, 0x83, 0x71, 0x16, 0xdc, 0x4d, 0x98, 0xca, 0xbe, 0x6c, - 0xdc, 0xaf, 0x2a, 0xa9, 0xfb, 0xd5, 0xb4, 0x86, 0xaa, 0xdd, 0xb2, 0x9e, 0x85, 0x51, 0x61, 0xae, - 0x99, 0x76, 0xda, 0x10, 0xb8, 0x58, 0xc2, 0xed, 0x1f, 0x2f, 0x82, 0x11, 0x4c, 0x0e, 0xfd, 0x8a, - 0x05, 0xf3, 0x21, 0xf7, 0x82, 0x6d, 0x55, 0x3b, 0xa1, 0xeb, 0x6f, 0x37, 0x9a, 0x3b, 0xa4, 0xd5, - 0xf1, 0x5c, 0x7f, 0xbb, 0xb6, 0xed, 0x07, 0xaa, 0x78, 0xe5, 0x3e, 0x69, 0x76, 0xd8, 0x9b, 0x4b, - 0x9f, 0xc8, 0x75, 0xca, 0x1c, 0xea, 0xea, 0xd1, 0x61, 0x65, 0x1e, 0x9f, 0x88, 0x36, 0x3e, 0x61, - 0x5f, 0xd0, 0x6f, 0x5a, 0xb0, 0xc0, 0x63, 0xac, 0x0d, 0xde, 0xff, 0x1e, 0xb7, 0xd1, 0xba, 0x24, - 0x95, 0x10, 0xd9, 0x20, 0xe1, 0xde, 0xd2, 0x6b, 0x62, 0x40, 0x17, 0xea, 0x27, 0x6b, 0x0b, 0x9f, - 0xb4, 0x73, 0xf6, 0xbf, 0x29, 0xc2, 0x24, 0x1d, 0xc5, 0x24, 0xf2, 0xcb, 0xab, 0xc6, 0x92, 0x78, - 0x32, 0xb5, 0x24, 0x66, 0x0d, 0xe4, 0xd3, 0x09, 0xfa, 0x12, 0xc1, 0xac, 0xe7, 0x44, 0xf1, 0x75, - 0xe2, 0x84, 0xf1, 0x26, 0x71, 0xb8, 0x99, 0x50, 0xf1, 0xc4, 0x26, 0x4d, 0x4a, 0xfd, 0x75, 0x33, - 0x4d, 0x0c, 0x77, 0xd3, 0x47, 0xfb, 0x80, 0x98, 0xad, 0x53, 0xe8, 0xf8, 0x11, 0xff, 0x16, 0x57, - 0xbc, 0xc7, 0x9c, 0xac, 0xd5, 0x39, 0xd1, 0x2a, 0xba, 0xd9, 0x45, 0x0d, 0x67, 0xb4, 0xa0, 0xd9, - 0xb0, 0x0d, 0x0f, 0x6a, 0xc3, 0x36, 0xd2, 0xc7, 0x33, 0x6a, 0x0f, 0x66, 0xc4, 0xac, 0x6c, 0xb9, - 0xdb, 0xe2, 0x90, 0xfe, 0x72, 0xca, 0xc6, 0xd5, 0x1a, 0xdc, 0x50, 0xa9, 0x8f, 0x81, 0xab, 0xfd, - 0xdd, 0x70, 0x8e, 0x36, 0x67, 0xfa, 0xf1, 0x44, 0x88, 0xc0, 0xf4, 0x6e, 0x67, 0x93, 0x78, 0x24, - 0x96, 0x65, 0xa2, 0xd1, 0x4c, 0xb1, 0xdf, 0xac, 0x9d, 0xc8, 0x96, 0x37, 0x4c, 0x12, 0x38, 0x4d, - 0xd3, 0xfe, 0x49, 0x0b, 0x98, 0xb5, 0xfc, 0x19, 0x1c, 0x7f, 0x5f, 0x34, 0x8f, 0xbf, 0x72, 0x1e, - 0x07, 0xca, 0x39, 0xf9, 0x5e, 0xe1, 0xd3, 0x52, 0x0f, 0x83, 0xfb, 0x07, 0x52, 0xf6, 0xef, 0x2f, - 0x71, 0xfd, 0x1f, 0x8b, 0x6f, 0x48, 0x15, 0x14, 0x00, 0x7d, 0x0f, 0x8c, 0x35, 0x9d, 0xb6, 0xd3, - 0xe4, 0x51, 0x3c, 0x73, 0xb5, 0x3f, 0x46, 0xa5, 0xf9, 0x65, 0x51, 0x83, 0x6b, 0x33, 0x3e, 0x2b, - 0xbf, 0x52, 0x16, 0xf7, 0xd5, 0x60, 0xa8, 0x26, 0xe7, 0x76, 0x61, 0xd2, 0x20, 0xf6, 0x50, 0xaf, - 0xbe, 0xdf, 0xc3, 0x8f, 0x0b, 0x75, 0x63, 0xd9, 0x83, 0x59, 0x5f, 0xfb, 0x4f, 0x99, 0xa3, 0x14, - 0xa7, 0x3f, 0xdd, 0xef, 0x40, 0x60, 0x9c, 0x54, 0xf3, 0x06, 0x48, 0x91, 0xc1, 0xdd, 0x94, 0xed, - 0xbf, 0x67, 0xc1, 0xa3, 0x3a, 0xa2, 0x16, 0xaf, 0xa1, 0x9f, 0x3e, 0xb9, 0x0a, 0x63, 0x41, 0x9b, - 0x84, 0x4e, 0x72, 0x27, 0xbb, 0x22, 0x07, 0xfd, 0x96, 0x28, 0x3f, 0x3e, 0xac, 0x9c, 0xd7, 0xa9, - 0xcb, 0x72, 0xac, 0x6a, 0x22, 0x1b, 0x46, 0xd8, 0x60, 0x44, 0x22, 0x96, 0x06, 0x33, 0x53, 0x64, - 0x4f, 0xab, 0x11, 0x16, 0x10, 0xfb, 0xfb, 0x2c, 0xbe, 0xb0, 0xf4, 0xae, 0xa3, 0xf7, 0x61, 0x66, - 0x8f, 0x5e, 0xdf, 0x56, 0xee, 0xb7, 0x43, 0xae, 0x46, 0x97, 0xe3, 0xf4, 0x7c, 0xbf, 0x71, 0xd2, - 0x3e, 0x32, 0x31, 0x66, 0x5b, 0x4b, 0x11, 0xc3, 0x5d, 0xe4, 0xed, 0x3f, 0x29, 0xf0, 0x9d, 0xc8, - 0xa4, 0xba, 0x67, 0x61, 0xb4, 0x1d, 0xb4, 0x96, 0x6b, 0x55, 0x2c, 0x46, 0x48, 0xb1, 0xab, 0x3a, - 0x2f, 0xc6, 0x12, 0x8e, 0xae, 0x02, 0x90, 0xfb, 0x31, 0x09, 0x7d, 0xc7, 0x53, 0x86, 0x1f, 0x4a, - 0x78, 0x5a, 0x51, 0x10, 0xac, 0x61, 0xd1, 0x3a, 0xed, 0x30, 0xd8, 0x77, 0x5b, 0xcc, 0xdb, 0xb0, - 0x68, 0xd6, 0xa9, 0x2b, 0x08, 0xd6, 0xb0, 0xe8, 0x55, 0xb9, 0xe3, 0x47, 0xfc, 0x00, 0x74, 0x36, - 0x45, 0xf8, 0xb9, 0xb1, 0xe4, 0xaa, 0x7c, 0x5b, 0x07, 0x62, 0x13, 0x17, 0x2d, 0xc2, 0x48, 0xec, - 0x30, 0x73, 0x86, 0xe1, 0x7c, 0xb3, 0xc4, 0x0d, 0x8a, 0xa1, 0x87, 0x75, 0xa4, 0x15, 0xb0, 0xa8, - 0x88, 0xde, 0x91, 0x2c, 0x98, 0xb3, 0x64, 0x61, 0x0f, 0x9c, 0xbb, 0x6c, 0x75, 0xf6, 0xad, 0xf3, - 0x60, 0x61, 0x67, 0x6c, 0xd0, 0xb2, 0xbf, 0xb7, 0x04, 0x90, 0x48, 0x7b, 0xe8, 0x83, 0x2e, 0x16, - 0xf1, 0x42, 0x6f, 0xf9, 0xf0, 0xf4, 0xf8, 0x03, 0xfa, 0x7e, 0x0b, 0xc6, 0x1d, 0xcf, 0x0b, 0x9a, - 0x4e, 0xcc, 0x46, 0xb9, 0xd0, 0x9b, 0x45, 0x89, 0xf6, 0x17, 0x93, 0x1a, 0xbc, 0x0b, 0x2f, 0x4b, - 0x4b, 0x05, 0x0d, 0xd2, 0xb7, 0x17, 0x7a, 0xc3, 0xe8, 0xb3, 0xf2, 0x12, 0xc0, 0x97, 0xc7, 0x5c, - 0xfa, 0x12, 0x50, 0x62, 0xdc, 0x58, 0x93, 0xff, 0xd1, 0x6d, 0x23, 0x4e, 0xdb, 0x50, 0x7e, 0x48, - 0x0a, 0x43, 0xe8, 0xe9, 0x17, 0xa2, 0x0d, 0xd5, 0x75, 0xbf, 0xa8, 0xe1, 0xfc, 0xb8, 0x2d, 0x9a, - 0x74, 0xdd, 0xc7, 0x27, 0xea, 0x3d, 0x98, 0x6e, 0x99, 0xc7, 0xad, 0x58, 0x4d, 0xcf, 0xe4, 0xd1, - 0x4d, 0x9d, 0xce, 0xc9, 0x01, 0x9b, 0x02, 0xe0, 0x34, 0x61, 0x54, 0xe7, 0x1e, 0x6a, 0x35, 0x7f, - 0x2b, 0x10, 0x76, 0xe5, 0x76, 0xee, 0x5c, 0x1e, 0x44, 0x31, 0xd9, 0xa3, 0x98, 0xc9, 0x39, 0xba, - 0x2e, 0xea, 0x62, 0x45, 0x05, 0xbd, 0x05, 0x23, 0xcc, 0x6d, 0x38, 0x2a, 0x8f, 0xe5, 0xeb, 0x01, - 0xcd, 0x88, 0x17, 0xc9, 0xa6, 0x62, 0x7f, 0x23, 0x2c, 0x28, 0xa0, 0xeb, 0x32, 0x2c, 0x4e, 0x54, - 0xf3, 0x6f, 0x47, 0x84, 0x85, 0xc5, 0x29, 0x2d, 0x7d, 0x3a, 0x89, 0x78, 0xc3, 0xcb, 0x33, 0x03, - 0x38, 0x1b, 0x35, 0xa9, 0xbc, 0x22, 0xfe, 0xcb, 0xb8, 0xd0, 0x65, 0xc8, 0xef, 0x9e, 0x19, 0x3b, - 0x3a, 0x19, 0xce, 0x3b, 0x26, 0x09, 0x9c, 0xa6, 0x79, 0xa6, 0xc7, 0xe7, 0x9c, 0x0f, 0x33, 0xe9, - 0x8d, 0xf5, 0x50, 0x8f, 0xeb, 0x3f, 0x18, 0x82, 0x29, 0x73, 0x21, 0xa0, 0x05, 0x28, 0x09, 0x22, - 0x2a, 0x44, 0xa6, 0x5a, 0xdb, 0x6b, 0x12, 0x80, 0x13, 0x1c, 0x16, 0x22, 0x94, 0x55, 0xd7, 0xec, - 0x00, 0x93, 0x10, 0xa1, 0x0a, 0x82, 0x35, 0x2c, 0x2a, 0x44, 0x6f, 0x06, 0x41, 0xac, 0x8e, 0x02, - 0xb5, 0x5a, 0x96, 0x58, 0x29, 0x16, 0x50, 0x7a, 0x04, 0xec, 0x92, 0xd0, 0x27, 0x9e, 0xa9, 0xc9, - 0x54, 0x47, 0xc0, 0x0d, 0x1d, 0x88, 0x4d, 0x5c, 0x7a, 0xa4, 0x05, 0x11, 0x5b, 0x7e, 0x42, 0x54, - 0x4f, 0xec, 0x2a, 0x1b, 0xdc, 0x6d, 0x5e, 0xc2, 0xd1, 0x97, 0xe1, 0x51, 0xe5, 0xe5, 0x8e, 0xb9, - 0x66, 0x58, 0xb6, 0x38, 0x62, 0xdc, 0xac, 0x1f, 0x5d, 0xce, 0x46, 0xc3, 0x79, 0xf5, 0xd1, 0x9b, - 0x30, 0x25, 0x44, 0x60, 0x49, 0x71, 0xd4, 0x34, 0x56, 0xb8, 0x61, 0x40, 0x71, 0x0a, 0x1b, 0x55, - 0x61, 0x86, 0x96, 0x30, 0x29, 0x54, 0x52, 0xe0, 0xde, 0xfa, 0xea, 0xac, 0xbf, 0x91, 0x82, 0xe3, - 0xae, 0x1a, 0x68, 0x11, 0xa6, 0xb9, 0x8c, 0x42, 0xef, 0x94, 0x6c, 0x1e, 0x84, 0xbb, 0x87, 0xda, - 0x08, 0xb7, 0x4c, 0x30, 0x4e, 0xe3, 0xa3, 0xd7, 0x61, 0xc2, 0x09, 0x9b, 0x3b, 0x6e, 0x4c, 0x9a, - 0x71, 0x27, 0xe4, 0x7e, 0x20, 0x9a, 0xb5, 0xc7, 0xa2, 0x06, 0xc3, 0x06, 0xa6, 0xfd, 0x01, 0x9c, - 0xcb, 0xf0, 0x14, 0xa3, 0x0b, 0xc7, 0x69, 0xbb, 0xf2, 0x9b, 0x52, 0x16, 0x92, 0x8b, 0xf5, 0x9a, - 0xfc, 0x1a, 0x0d, 0x8b, 0xae, 0x4e, 0xa6, 0x12, 0xd7, 0x82, 0xb7, 0xab, 0xd5, 0xb9, 0x2a, 0x01, - 0x38, 0xc1, 0xb1, 0x7f, 0x03, 0x40, 0x53, 0xe8, 0x0c, 0x60, 0x1f, 0xf7, 0x3a, 0x4c, 0xc8, 0x8c, - 0x03, 0x5a, 0xa4, 0x6b, 0xf5, 0x99, 0xd7, 0x34, 0x18, 0x36, 0x30, 0x69, 0xdf, 0x7c, 0x15, 0xa7, - 0x3b, 0x65, 0x8f, 0x99, 0x44, 0xe9, 0x4e, 0x70, 0xd0, 0x0b, 0x30, 0x16, 0x11, 0x6f, 0xeb, 0xa6, - 0xeb, 0xef, 0x8a, 0x85, 0xad, 0xb8, 0x70, 0x43, 0x94, 0x63, 0x85, 0x81, 0x96, 0xa0, 0xd8, 0x71, - 0x5b, 0x62, 0x29, 0xcb, 0x03, 0xbf, 0x78, 0xbb, 0x56, 0x3d, 0x3e, 0xac, 0x3c, 0x99, 0x97, 0x48, - 0x81, 0x5e, 0xed, 0xa3, 0x79, 0xba, 0xfd, 0x68, 0xe5, 0xac, 0xb7, 0x81, 0x91, 0x13, 0xbe, 0x0d, - 0x5c, 0x05, 0x10, 0x5f, 0x2d, 0xd7, 0x72, 0x31, 0x99, 0xb5, 0x6b, 0x0a, 0x82, 0x35, 0x2c, 0x14, - 0xc1, 0x6c, 0x33, 0x24, 0x8e, 0xbc, 0x43, 0x73, 0x9f, 0xa7, 0xb1, 0x07, 0x57, 0x10, 0x2c, 0xa7, - 0x89, 0xe1, 0x6e, 0xfa, 0x28, 0x80, 0xd9, 0x96, 0x08, 0xaa, 0x90, 0x34, 0x5a, 0x3a, 0xb9, 0xa3, - 0x15, 0x33, 0xc8, 0x49, 0x13, 0xc2, 0xdd, 0xb4, 0xd1, 0x57, 0x60, 0x4e, 0x16, 0x76, 0xc7, 0xb1, - 0x60, 0xdb, 0xa5, 0xb8, 0x74, 0xe9, 0xe8, 0xb0, 0x32, 0x57, 0xcd, 0xc5, 0xc2, 0x3d, 0x28, 0x20, - 0x0c, 0x23, 0xec, 0x2d, 0x29, 0x2a, 0x8f, 0xb3, 0x73, 0xee, 0xb9, 0x7c, 0x65, 0x00, 0x5d, 0xeb, - 0xf3, 0xec, 0x1d, 0x4a, 0x98, 0x94, 0x27, 0xcf, 0x72, 0xac, 0x10, 0x0b, 0x4a, 0x68, 0x0b, 0xc6, - 0x1d, 0xdf, 0x0f, 0x62, 0x87, 0x8b, 0x50, 0x13, 0xf9, 0xb2, 0x9f, 0x46, 0x78, 0x31, 0xa9, 0xc1, - 0xa9, 0x2b, 0x2b, 0x55, 0x0d, 0x82, 0x75, 0xc2, 0xe8, 0x1e, 0x4c, 0x07, 0xf7, 0x28, 0x73, 0x94, - 0x5a, 0x8a, 0xa8, 0x3c, 0xc9, 0xda, 0x7a, 0x65, 0x40, 0x3d, 0xad, 0x51, 0x59, 0xe3, 0x5a, 0x26, - 0x51, 0x9c, 0x6e, 0x05, 0xcd, 0x1b, 0xda, 0xea, 0xa9, 0xc4, 0x9d, 0x25, 0xd1, 0x56, 0xeb, 0xca, - 0x69, 0x16, 0x17, 0x85, 0x9b, 0x48, 0xb3, 0xdd, 0x3f, 0x9d, 0x8a, 0x8b, 0x92, 0x80, 0xb0, 0x8e, - 0x87, 0x76, 0x60, 0x22, 0x79, 0xb2, 0x0a, 0x23, 0x16, 0x95, 0x6d, 0xfc, 0xea, 0xd5, 0xc1, 0x3e, - 0xae, 0xa6, 0xd5, 0xe4, 0x37, 0x07, 0xbd, 0x04, 0x1b, 0x94, 0xe7, 0xbe, 0x0d, 0xc6, 0xb5, 0x89, - 0x3d, 0x89, 0x07, 0xc0, 0xdc, 0x9b, 0x30, 0x93, 0x9e, 0xba, 0x13, 0x79, 0x10, 0xfc, 0xef, 0x02, - 0x4c, 0x67, 0xbc, 0x5c, 0xb1, 0x64, 0x0c, 0x29, 0x86, 0x9a, 0xe4, 0x5e, 0x30, 0xd9, 0x62, 0x61, - 0x00, 0xb6, 0x28, 0x79, 0x74, 0x31, 0x97, 0x47, 0x0b, 0x56, 0x38, 0xf4, 0x51, 0x58, 0xa1, 0x79, - 0xfa, 0x0c, 0x0f, 0x74, 0xfa, 0x9c, 0x02, 0xfb, 0x34, 0x0e, 0xb0, 0xd1, 0x01, 0x0e, 0xb0, 0x1f, - 0x2a, 0xc0, 0x4c, 0xda, 0xc2, 0xf7, 0x0c, 0xde, 0x3b, 0xde, 0x32, 0xde, 0x3b, 0xb2, 0x53, 0x9b, - 0xa4, 0xed, 0x8e, 0xf3, 0xde, 0x3e, 0x70, 0xea, 0xed, 0xe3, 0xb9, 0x81, 0xa8, 0xf5, 0x7e, 0x07, - 0xf9, 0xfb, 0x05, 0xb8, 0x90, 0xae, 0xb2, 0xec, 0x39, 0xee, 0xde, 0x19, 0x8c, 0xcd, 0x2d, 0x63, - 0x6c, 0x5e, 0x1c, 0xe4, 0x6b, 0x58, 0xd7, 0x72, 0x07, 0xe8, 0x6e, 0x6a, 0x80, 0x16, 0x06, 0x27, - 0xd9, 0x7b, 0x94, 0xbe, 0x51, 0x84, 0x4b, 0x99, 0xf5, 0x92, 0xe7, 0x82, 0x55, 0xe3, 0xb9, 0xe0, - 0x6a, 0xea, 0xb9, 0xc0, 0xee, 0x5d, 0xfb, 0x74, 0xde, 0x0f, 0x84, 0x3b, 0x34, 0x8b, 0x18, 0xfa, - 0x80, 0x6f, 0x07, 0x86, 0x3b, 0xb4, 0x22, 0x84, 0x4d, 0xba, 0xdf, 0x4c, 0x6f, 0x06, 0xbf, 0x61, - 0xc1, 0xc5, 0xcc, 0xb9, 0x39, 0x03, 0xbd, 0xfa, 0xba, 0xa9, 0x57, 0x7f, 0x76, 0xe0, 0xd5, 0x9a, - 0xa3, 0x68, 0xff, 0xc3, 0x62, 0xce, 0xb7, 0x30, 0xcd, 0xe4, 0x2d, 0x18, 0x77, 0x9a, 0x4d, 0x12, - 0x45, 0x6b, 0x41, 0x4b, 0x45, 0xd0, 0x7c, 0x91, 0x49, 0x1b, 0x49, 0xf1, 0xf1, 0x61, 0x65, 0x2e, - 0x4d, 0x22, 0x01, 0x63, 0x9d, 0x82, 0x19, 0xf4, 0xb7, 0x70, 0xaa, 0x41, 0x7f, 0xaf, 0x02, 0xec, - 0x2b, 0x7d, 0x45, 0x5a, 0xcd, 0xa9, 0x69, 0x32, 0x34, 0x2c, 0xf4, 0x5d, 0xec, 0x16, 0xc0, 0x8d, - 0x81, 0xf8, 0x52, 0x7c, 0x79, 0xc0, 0xb9, 0xd2, 0x0d, 0x8b, 0x78, 0xdc, 0x0d, 0xa5, 0x12, 0x56, - 0x24, 0xd1, 0x77, 0xc0, 0x4c, 0xc4, 0xc3, 0x3a, 0x2d, 0x7b, 0x4e, 0xc4, 0x9c, 0xb8, 0xc4, 0x2a, - 0x64, 0xc1, 0x34, 0x1a, 0x29, 0x18, 0xee, 0xc2, 0x46, 0xab, 0xf2, 0xa3, 0x58, 0x0c, 0x2a, 0xbe, - 0x30, 0x9f, 0x4e, 0x3e, 0x48, 0xa4, 0x82, 0x3a, 0x9f, 0x1e, 0x7e, 0x36, 0xf0, 0x5a, 0x4d, 0xfb, - 0x87, 0x86, 0xe0, 0xb1, 0x1e, 0x4c, 0x0c, 0x2d, 0x9a, 0x46, 0x00, 0xcf, 0xa7, 0xf5, 0x7f, 0x73, - 0x99, 0x95, 0x0d, 0x85, 0x60, 0x6a, 0xad, 0x14, 0x3e, 0xf2, 0x5a, 0xf9, 0x01, 0x4b, 0xd3, 0xcc, - 0x72, 0x53, 0xe1, 0x2f, 0x9e, 0x90, 0x39, 0x9f, 0xa2, 0xaa, 0x76, 0x2b, 0x43, 0xdf, 0x79, 0x75, - 0xe0, 0xee, 0x0c, 0xac, 0x00, 0x3d, 0xdb, 0x27, 0xa3, 0x0f, 0x2d, 0x78, 0x32, 0xb3, 0xbf, 0x86, - 0xd1, 0xd2, 0x02, 0x94, 0x9a, 0xb4, 0x50, 0x73, 0x0c, 0x4d, 0x3c, 0xe6, 0x25, 0x00, 0x27, 0x38, - 0x86, 0x6d, 0x52, 0xa1, 0xaf, 0x6d, 0xd2, 0xbf, 0xb6, 0xa0, 0x6b, 0x01, 0x9f, 0x01, 0x27, 0xad, - 0x99, 0x9c, 0xf4, 0xd3, 0x83, 0xcc, 0x65, 0x0e, 0x13, 0xfd, 0xdd, 0x69, 0x78, 0x24, 0xc7, 0x13, - 0x6c, 0x1f, 0x66, 0xb7, 0x9b, 0xc4, 0x74, 0xb9, 0x15, 0x1f, 0x93, 0xe9, 0x9d, 0xdc, 0xd3, 0x3f, - 0x97, 0x5f, 0x88, 0xbb, 0x50, 0x70, 0x77, 0x13, 0xe8, 0x43, 0x0b, 0xce, 0x3b, 0xf7, 0xa2, 0xae, - 0x4c, 0x8d, 0x62, 0xcd, 0xbc, 0x92, 0xa9, 0xa7, 0xed, 0x93, 0xd9, 0x91, 0xb9, 0xc5, 0x9d, 0xcf, - 0xc2, 0xc2, 0x99, 0x6d, 0x21, 0x2c, 0x82, 0x1e, 0x53, 0x79, 0xbb, 0x87, 0x53, 0x78, 0x96, 0xcb, - 0x1e, 0xe7, 0xa9, 0x12, 0x82, 0x15, 0x1d, 0x74, 0x07, 0x4a, 0xdb, 0xd2, 0x8f, 0x56, 0xf0, 0xec, - 0xcc, 0x43, 0x30, 0xd3, 0xd9, 0x96, 0xfb, 0x8e, 0x28, 0x10, 0x4e, 0x48, 0xa1, 0x37, 0xa1, 0xe8, - 0x6f, 0x45, 0xbd, 0x92, 0x4d, 0xa5, 0x6c, 0xf9, 0x78, 0xc0, 0x85, 0xf5, 0xd5, 0x06, 0xa6, 0x15, - 0xd1, 0x75, 0x28, 0x86, 0x9b, 0x2d, 0xf1, 0xb4, 0x90, 0x29, 0x97, 0xe2, 0xa5, 0x6a, 0xf6, 0x22, - 0xe1, 0x94, 0xf0, 0x52, 0x15, 0x53, 0x12, 0xa8, 0x0e, 0xc3, 0xcc, 0x69, 0x4a, 0xbc, 0x20, 0x64, - 0x0a, 0xa4, 0x3d, 0x9c, 0x0f, 0x79, 0x54, 0x06, 0x86, 0x80, 0x39, 0x21, 0xf4, 0x16, 0x8c, 0x34, - 0x59, 0x3e, 0x26, 0xa1, 0xf8, 0xc9, 0x0e, 0xd7, 0xd5, 0x95, 0xb1, 0x89, 0xbf, 0xa0, 0xf2, 0x72, - 0x2c, 0x28, 0xa0, 0x0d, 0x18, 0x69, 0x92, 0xf6, 0xce, 0x56, 0x24, 0xf4, 0x39, 0x9f, 0xcd, 0xa4, - 0xd5, 0x23, 0xfd, 0x98, 0xa0, 0xca, 0x30, 0xb0, 0xa0, 0x85, 0x3e, 0x0f, 0x85, 0xad, 0xa6, 0xf0, - 0xa4, 0xca, 0x7c, 0x43, 0x30, 0x23, 0x65, 0x2c, 0x8d, 0x1c, 0x1d, 0x56, 0x0a, 0xab, 0xcb, 0xb8, - 0xb0, 0xd5, 0x44, 0xeb, 0x30, 0xba, 0xc5, 0x7d, 0xeb, 0x45, 0x00, 0x9b, 0x67, 0xb2, 0xdd, 0xfe, - 0xbb, 0xdc, 0xef, 0xb9, 0x07, 0x90, 0x00, 0x60, 0x49, 0x84, 0xc5, 0x0b, 0x56, 0x31, 0x02, 0x44, - 0xe0, 0xfc, 0xf9, 0x93, 0xc5, 0x75, 0x10, 0x6a, 0x0e, 0x45, 0x05, 0x6b, 0x14, 0xd1, 0x57, 0xa1, - 0xe4, 0xc8, 0xcc, 0x80, 0x22, 0x08, 0xce, 0xcb, 0x99, 0xdb, 0xb1, 0x77, 0xd2, 0x44, 0xbe, 0x96, - 0x15, 0x12, 0x4e, 0x88, 0xa2, 0x5d, 0x98, 0xdc, 0x8f, 0xda, 0x3b, 0x44, 0x6e, 0x5f, 0x16, 0x13, - 0x27, 0xe7, 0xb8, 0xba, 0x23, 0x10, 0xdd, 0x30, 0xee, 0x38, 0x5e, 0x17, 0xc7, 0x61, 0x8e, 0x63, - 0x77, 0x74, 0x62, 0xd8, 0xa4, 0x4d, 0x87, 0xff, 0xfd, 0x4e, 0xb0, 0x79, 0x10, 0x13, 0x11, 0x69, - 0x3f, 0x73, 0xf8, 0xdf, 0xe6, 0x28, 0xdd, 0xc3, 0x2f, 0x00, 0x58, 0x12, 0xa1, 0x1b, 0xdc, 0x91, - 0x59, 0x37, 0x85, 0x2e, 0xe7, 0xd9, 0xdc, 0xe1, 0xe9, 0xea, 0x6f, 0x32, 0x28, 0x8c, 0x33, 0x26, - 0xa4, 0x18, 0x47, 0x6c, 0xef, 0x04, 0x71, 0xe0, 0xa7, 0xb8, 0xf1, 0x6c, 0x3e, 0x47, 0xac, 0x67, - 0xe0, 0x77, 0x73, 0xc4, 0x2c, 0x2c, 0x9c, 0xd9, 0x16, 0x6a, 0xc1, 0x54, 0x3b, 0x08, 0xe3, 0x7b, - 0x41, 0x28, 0xd7, 0x17, 0xea, 0x71, 0xc9, 0x37, 0x30, 0x45, 0x8b, 0xcc, 0x0e, 0xdc, 0x84, 0xe0, - 0x14, 0x4d, 0xf4, 0x25, 0x18, 0x8d, 0x9a, 0x8e, 0x47, 0x6a, 0xb7, 0xca, 0xe7, 0xf2, 0x8f, 0x9a, - 0x06, 0x47, 0xc9, 0x59, 0x5d, 0x6c, 0x72, 0x04, 0x0a, 0x96, 0xe4, 0xd0, 0x2a, 0x0c, 0xb3, 0xf4, - 0x2d, 0x2c, 0x49, 0x40, 0x4e, 0xb0, 0xb5, 0x2e, 0x5b, 0x69, 0xce, 0x91, 0x58, 0x31, 0xe6, 0xd5, - 0xe9, 0x1e, 0x10, 0xb2, 0x6e, 0x10, 0x95, 0x2f, 0xe4, 0xef, 0x01, 0x21, 0x22, 0xdf, 0x6a, 0xf4, - 0xda, 0x03, 0x0a, 0x09, 0x27, 0x44, 0x29, 0x3f, 0xa6, 0x3c, 0xf4, 0x91, 0x7c, 0x7e, 0x9c, 0xcf, - 0x41, 0x19, 0x3f, 0xa6, 0xfc, 0x93, 0x92, 0xb0, 0x3f, 0x1c, 0xed, 0x96, 0x4f, 0xd8, 0xed, 0xe8, - 0x7b, 0xad, 0x2e, 0xd3, 0x81, 0xcf, 0x0d, 0xaa, 0xac, 0x39, 0x45, 0xc9, 0xf4, 0x43, 0x0b, 0x1e, - 0x69, 0x67, 0x7e, 0x88, 0x38, 0xec, 0x07, 0xd3, 0xf9, 0xf0, 0x4f, 0x57, 0x89, 0x3c, 0xb2, 0xe1, - 0x38, 0xa7, 0xa5, 0xb4, 0xf4, 0x5f, 0xfc, 0xc8, 0xd2, 0xff, 0x1a, 0x8c, 0x31, 0x81, 0x32, 0x89, - 0xec, 0x37, 0x90, 0x01, 0x1e, 0x13, 0x1b, 0x96, 0x45, 0x45, 0xac, 0x48, 0xa0, 0x1f, 0xb4, 0xe0, - 0x89, 0x74, 0xd7, 0x31, 0x61, 0x60, 0x11, 0x25, 0x9a, 0x5f, 0xcc, 0x56, 0xc5, 0xf7, 0x3f, 0x51, - 0xef, 0x85, 0x7c, 0xdc, 0x0f, 0x01, 0xf7, 0x6e, 0x0c, 0x55, 0x33, 0x6e, 0x86, 0x23, 0xe6, 0xcb, - 0xe2, 0x00, 0xb7, 0xc3, 0x57, 0x60, 0x62, 0x2f, 0xe8, 0xf8, 0xd2, 0x3b, 0x46, 0xf8, 0x3e, 0x33, - 0x2d, 0xf6, 0x9a, 0x56, 0x8e, 0x0d, 0xac, 0xd4, 0x9d, 0x72, 0xec, 0x41, 0xef, 0x94, 0x67, 0x7b, - 0x53, 0xf9, 0xba, 0x95, 0x21, 0x62, 0xf3, 0xbb, 0xeb, 0x17, 0xcc, 0xbb, 0xeb, 0xd3, 0xe9, 0xbb, - 0x6b, 0x97, 0xae, 0xd2, 0xb8, 0xb6, 0x0e, 0x1e, 0x45, 0x7f, 0xd0, 0x10, 0x8a, 0xb6, 0x07, 0x97, - 0xfb, 0x1d, 0x1c, 0xcc, 0x98, 0xb1, 0xa5, 0x5e, 0xf9, 0x13, 0x63, 0xc6, 0x56, 0xad, 0x8a, 0x19, - 0x64, 0xd0, 0x18, 0x3b, 0xf6, 0x7f, 0xb7, 0xa0, 0x58, 0x0f, 0x5a, 0x67, 0xa0, 0x7b, 0xfd, 0xa2, - 0xa1, 0x7b, 0x7d, 0x2c, 0x27, 0xbf, 0x78, 0xae, 0xa6, 0x75, 0x25, 0xa5, 0x69, 0x7d, 0x22, 0x8f, - 0x40, 0x6f, 0xbd, 0xea, 0x4f, 0x14, 0x41, 0xcf, 0x86, 0x8e, 0xfe, 0xed, 0x83, 0x58, 0xc5, 0x17, - 0x7b, 0x25, 0x48, 0x17, 0x94, 0x99, 0x0d, 0xa4, 0x74, 0xb8, 0xfd, 0x73, 0x66, 0x1c, 0x7f, 0x97, - 0xb8, 0xdb, 0x3b, 0x31, 0x69, 0xa5, 0x3f, 0xe7, 0xec, 0x8c, 0xe3, 0xff, 0xab, 0x05, 0xd3, 0xa9, - 0xd6, 0x91, 0x97, 0xe5, 0xbd, 0xf7, 0x80, 0x3a, 0xb7, 0xd9, 0xbe, 0xee, 0x7e, 0xf3, 0x00, 0xea, - 0x61, 0x4b, 0xea, 0xa3, 0x98, 0x5c, 0xae, 0x5e, 0xbe, 0x22, 0xac, 0x61, 0xa0, 0x57, 0x61, 0x3c, - 0x0e, 0xda, 0x81, 0x17, 0x6c, 0x1f, 0xdc, 0x20, 0x32, 0xaa, 0x93, 0x7a, 0x7e, 0xdc, 0x48, 0x40, - 0x58, 0xc7, 0xb3, 0x7f, 0xaa, 0x08, 0xe9, 0x0c, 0xfa, 0xdf, 0x5a, 0x93, 0x9f, 0xcc, 0x35, 0xf9, - 0x0d, 0x0b, 0x66, 0x68, 0xeb, 0xcc, 0xbe, 0x4c, 0x1e, 0x87, 0x2a, 0x9b, 0x97, 0xd5, 0x23, 0x9b, - 0xd7, 0xd3, 0x94, 0x77, 0xb5, 0x82, 0x4e, 0x2c, 0xf4, 0x59, 0x1a, 0x73, 0xa2, 0xa5, 0x58, 0x40, - 0x05, 0x1e, 0x09, 0x43, 0xe1, 0x93, 0xa7, 0xe3, 0x91, 0x30, 0xc4, 0x02, 0x2a, 0x93, 0x7d, 0x0d, - 0xe5, 0x24, 0xfb, 0x62, 0x31, 0x2a, 0x85, 0x4d, 0x93, 0x10, 0x4c, 0xb4, 0x18, 0x95, 0xd2, 0xd8, - 0x29, 0xc1, 0xb1, 0x7f, 0xb6, 0x08, 0x13, 0xf5, 0xa0, 0x95, 0x3c, 0x2d, 0xbd, 0x62, 0x3c, 0x2d, - 0x5d, 0x4e, 0x3d, 0x2d, 0xcd, 0xe8, 0xb8, 0xdf, 0x7a, 0x48, 0xfa, 0xb8, 0x1e, 0x92, 0xfe, 0x95, - 0xc5, 0x66, 0xad, 0xba, 0xde, 0x10, 0xc9, 0xa8, 0x5f, 0x82, 0x71, 0xc6, 0x90, 0x98, 0x13, 0xa8, - 0x7c, 0x6f, 0x61, 0x39, 0x27, 0xd6, 0x93, 0x62, 0xac, 0xe3, 0xa0, 0x2b, 0x30, 0x16, 0x11, 0x27, - 0x6c, 0xee, 0x28, 0x1e, 0x27, 0x5e, 0x23, 0x78, 0x19, 0x56, 0x50, 0xf4, 0x76, 0x12, 0x1e, 0xb1, - 0x98, 0x9f, 0x56, 0x59, 0xef, 0x0f, 0xdf, 0x22, 0xf9, 0x31, 0x11, 0xed, 0xbb, 0x80, 0xba, 0xf1, - 0x07, 0x30, 0xf4, 0xaa, 0x98, 0x81, 0xd0, 0x4a, 0x5d, 0x41, 0xd0, 0xfe, 0xd4, 0x82, 0xa9, 0x7a, - 0xd0, 0xa2, 0x5b, 0xf7, 0x9b, 0x69, 0x9f, 0xea, 0xb1, 0x61, 0x47, 0x7a, 0xc4, 0x86, 0xfd, 0x07, - 0x16, 0x8c, 0xd6, 0x83, 0xd6, 0x19, 0x68, 0xc1, 0xbf, 0x60, 0x6a, 0xc1, 0x1f, 0xcd, 0x59, 0x12, - 0x39, 0x8a, 0xef, 0x9f, 0x2f, 0xc2, 0x24, 0xed, 0x67, 0xb0, 0x2d, 0x67, 0xc9, 0x18, 0x11, 0x6b, - 0x80, 0x11, 0xa1, 0x62, 0x6e, 0xe0, 0x79, 0xc1, 0xbd, 0xf4, 0x8c, 0xad, 0xb2, 0x52, 0x2c, 0xa0, - 0xe8, 0x05, 0x18, 0x6b, 0x87, 0x64, 0xdf, 0x0d, 0x3a, 0x51, 0xda, 0xdf, 0xb9, 0x2e, 0xca, 0xb1, - 0xc2, 0xa0, 0x37, 0xa3, 0xc8, 0xf5, 0x9b, 0x44, 0x5a, 0x80, 0x0d, 0x31, 0x0b, 0x30, 0x1e, 0xf4, - 0x5d, 0x2b, 0xc7, 0x06, 0x16, 0xba, 0x0b, 0x25, 0xf6, 0x9f, 0x71, 0x94, 0x93, 0xa7, 0x21, 0x13, - 0x99, 0x56, 0x04, 0x01, 0x9c, 0xd0, 0x42, 0x57, 0x01, 0x62, 0x69, 0xab, 0x16, 0x09, 0x77, 0x7c, - 0x25, 0x6b, 0x2b, 0x2b, 0xb6, 0x08, 0x6b, 0x58, 0xe8, 0x79, 0x28, 0xc5, 0x8e, 0xeb, 0xdd, 0x74, - 0x7d, 0x12, 0x09, 0x5b, 0x3f, 0x91, 0x48, 0x45, 0x14, 0xe2, 0x04, 0x4e, 0x65, 0x1d, 0x16, 0xec, - 0x81, 0x27, 0x31, 0x1c, 0x63, 0xd8, 0x4c, 0xd6, 0xb9, 0xa9, 0x4a, 0xb1, 0x86, 0x61, 0xbf, 0x0e, - 0x17, 0xea, 0x41, 0xab, 0x1e, 0x84, 0xf1, 0x6a, 0x10, 0xde, 0x73, 0xc2, 0x96, 0x9c, 0xbf, 0x8a, - 0xcc, 0xe9, 0x41, 0x79, 0xcf, 0x30, 0xdf, 0x99, 0x46, 0xb6, 0x8e, 0x97, 0x99, 0xb4, 0x73, 0x42, - 0xc7, 0xac, 0x7f, 0x5f, 0x60, 0x8c, 0x22, 0x95, 0x59, 0x13, 0x7d, 0x05, 0xa6, 0x22, 0x72, 0xd3, - 0xf5, 0x3b, 0xf7, 0xe5, 0x0d, 0xb6, 0x87, 0xd7, 0x5b, 0x63, 0x45, 0xc7, 0xe4, 0x7a, 0x30, 0xb3, - 0x0c, 0xa7, 0xa8, 0xd1, 0x21, 0x0c, 0x3b, 0xfe, 0x62, 0x74, 0x3b, 0x22, 0xa1, 0xc8, 0xec, 0xc8, - 0x86, 0x10, 0xcb, 0x42, 0x9c, 0xc0, 0xe9, 0x92, 0x61, 0x7f, 0xd6, 0x03, 0x1f, 0x07, 0x41, 0x2c, - 0x17, 0x19, 0xcb, 0x0d, 0xa6, 0x95, 0x63, 0x03, 0x0b, 0xad, 0x02, 0x8a, 0x3a, 0xed, 0xb6, 0xc7, - 0x9e, 0xa8, 0x1d, 0xef, 0x5a, 0x18, 0x74, 0xda, 0xfc, 0x79, 0x50, 0xa4, 0xd5, 0x6a, 0x74, 0x41, - 0x71, 0x46, 0x0d, 0xca, 0x18, 0xb6, 0x22, 0xf6, 0x5b, 0xc4, 0x7b, 0xe0, 0xba, 0xe9, 0x06, 0x2b, - 0xc2, 0x12, 0x66, 0x7f, 0x0f, 0x3b, 0x30, 0x58, 0x42, 0xbe, 0xb8, 0x13, 0x12, 0xb4, 0x07, 0x93, - 0x6d, 0x76, 0x94, 0x8b, 0xd0, 0xe6, 0x62, 0x00, 0x1f, 0xcc, 0xb2, 0x8f, 0x27, 0xe8, 0xd2, 0xc9, - 0x61, 0x93, 0xba, 0xfd, 0x9f, 0xa6, 0x19, 0x5f, 0x6a, 0xf0, 0xeb, 0xdc, 0xa8, 0xb0, 0xd7, 0x17, - 0xb2, 0xeb, 0x5c, 0x7e, 0x0a, 0xcf, 0xe4, 0x08, 0x11, 0x36, 0xff, 0x58, 0xd6, 0x45, 0x6f, 0xb3, - 0x77, 0x55, 0xce, 0x0c, 0xfa, 0x65, 0xf6, 0xe6, 0x58, 0xc6, 0x13, 0xaa, 0xa8, 0x88, 0x35, 0x22, - 0xe8, 0x26, 0x4c, 0x8a, 0xfc, 0x6d, 0x42, 0xb5, 0x53, 0x34, 0x14, 0x03, 0x93, 0x58, 0x07, 0x1e, - 0xa7, 0x0b, 0xb0, 0x59, 0x19, 0x6d, 0xc3, 0x13, 0x5a, 0x32, 0xd3, 0x0c, 0xeb, 0x52, 0xce, 0x5b, - 0x9e, 0x3c, 0x3a, 0xac, 0x3c, 0xb1, 0xd1, 0x0b, 0x11, 0xf7, 0xa6, 0x83, 0x6e, 0xc1, 0x05, 0xa7, - 0x19, 0xbb, 0xfb, 0xa4, 0x4a, 0x9c, 0x96, 0xe7, 0xfa, 0xc4, 0x0c, 0x00, 0x72, 0xf1, 0xe8, 0xb0, - 0x72, 0x61, 0x31, 0x0b, 0x01, 0x67, 0xd7, 0x43, 0x5f, 0x80, 0x52, 0xcb, 0x8f, 0xc4, 0x18, 0x8c, - 0x18, 0x79, 0x7a, 0x4b, 0xd5, 0xf5, 0x86, 0xfa, 0xfe, 0xe4, 0x0f, 0x4e, 0x2a, 0xa0, 0x6d, 0x98, - 0xd0, 0x9d, 0xfc, 0x44, 0x8e, 0xe7, 0x17, 0x7b, 0xdc, 0xfa, 0x0d, 0xcf, 0x38, 0xae, 0xd7, 0x54, - 0xb6, 0xdb, 0x86, 0xd3, 0x9c, 0x41, 0x18, 0xbd, 0x05, 0x88, 0x0a, 0x33, 0x6e, 0x93, 0x2c, 0x36, - 0x59, 0x84, 0x79, 0xa6, 0x0d, 0x1b, 0x33, 0x1c, 0x91, 0x50, 0xa3, 0x0b, 0x03, 0x67, 0xd4, 0x42, - 0xd7, 0x29, 0x47, 0xd1, 0x4b, 0x85, 0xa9, 0xbd, 0x14, 0x80, 0xcb, 0x55, 0xd2, 0x0e, 0x49, 0xd3, - 0x89, 0x49, 0xcb, 0xa4, 0x88, 0x53, 0xf5, 0xe8, 0x79, 0xa3, 0x92, 0x4d, 0x81, 0x69, 0x20, 0xde, - 0x9d, 0x70, 0x8a, 0xde, 0x1d, 0x77, 0x82, 0x28, 0x5e, 0x27, 0xf1, 0xbd, 0x20, 0xdc, 0x15, 0x51, - 0xfb, 0x92, 0x00, 0xb2, 0x09, 0x08, 0xeb, 0x78, 0x54, 0x56, 0x64, 0x0f, 0x9b, 0xb5, 0x2a, 0x7b, - 0x67, 0x1a, 0x4b, 0xf6, 0xc9, 0x75, 0x5e, 0x8c, 0x25, 0x5c, 0xa2, 0xd6, 0xea, 0xcb, 0xec, 0xcd, - 0x28, 0x85, 0x5a, 0xab, 0x2f, 0x63, 0x09, 0x47, 0xa4, 0x3b, 0x07, 0xf2, 0x54, 0xfe, 0xbb, 0x5f, - 0x37, 0x5f, 0x1e, 0x30, 0x0d, 0xb2, 0x0f, 0x33, 0x2a, 0xfb, 0x32, 0x0f, 0x67, 0x18, 0x95, 0xa7, - 0xd9, 0x22, 0x19, 0x3c, 0x16, 0xa2, 0xd2, 0x76, 0xd6, 0x52, 0x94, 0x70, 0x17, 0x6d, 0x23, 0xb0, - 0xcc, 0x4c, 0xdf, 0x64, 0x61, 0x0b, 0x50, 0x8a, 0x3a, 0x9b, 0xad, 0x60, 0xcf, 0x71, 0x7d, 0xf6, - 0xc4, 0xa3, 0x09, 0x22, 0x0d, 0x09, 0xc0, 0x09, 0x0e, 0x5a, 0x85, 0x31, 0x47, 0x5c, 0x4b, 0xc5, - 0xa3, 0x4c, 0x66, 0xa4, 0x09, 0x79, 0x75, 0xe5, 0x62, 0xb6, 0xfc, 0x87, 0x55, 0x5d, 0xf4, 0x06, - 0x4c, 0x0a, 0x67, 0x48, 0x61, 0xc7, 0x7c, 0xce, 0xf4, 0x9b, 0x69, 0xe8, 0x40, 0x6c, 0xe2, 0xa2, - 0xef, 0x82, 0x29, 0x4a, 0x25, 0x61, 0x6c, 0xe5, 0xf3, 0x83, 0x70, 0x44, 0x2d, 0x09, 0x8c, 0x5e, - 0x19, 0xa7, 0x88, 0xa1, 0x16, 0x3c, 0xee, 0x74, 0xe2, 0x80, 0xa9, 0x83, 0xcd, 0xf5, 0xbf, 0x11, - 0xec, 0x12, 0x9f, 0xbd, 0xc4, 0x8c, 0x2d, 0x5d, 0x3e, 0x3a, 0xac, 0x3c, 0xbe, 0xd8, 0x03, 0x0f, - 0xf7, 0xa4, 0x82, 0x6e, 0xc3, 0x78, 0x1c, 0x78, 0xc2, 0x01, 0x21, 0x2a, 0x3f, 0x92, 0x1f, 0x18, - 0x6b, 0x43, 0xa1, 0xe9, 0x8a, 0x16, 0x55, 0x15, 0xeb, 0x74, 0xd0, 0x06, 0xdf, 0x63, 0x2c, 0x64, - 0x30, 0x89, 0xca, 0x8f, 0xe6, 0x0f, 0x8c, 0x8a, 0x2c, 0x6c, 0x6e, 0x41, 0x51, 0x13, 0xeb, 0x64, - 0xd0, 0x35, 0x98, 0x6d, 0x87, 0x6e, 0xc0, 0x16, 0xb6, 0x52, 0xc5, 0x97, 0xcd, 0xbc, 0x1f, 0xf5, - 0x34, 0x02, 0xee, 0xae, 0x43, 0x2f, 0x62, 0xb2, 0xb0, 0x7c, 0x91, 0x27, 0x91, 0xe3, 0xc2, 0x29, - 0x2f, 0xc3, 0x0a, 0x8a, 0xd6, 0x18, 0x5f, 0xe6, 0x57, 0xa6, 0xf2, 0x5c, 0x7e, 0x84, 0x0e, 0xfd, - 0x6a, 0xc5, 0x05, 0x17, 0xf5, 0x17, 0x27, 0x14, 0xe6, 0xbe, 0x1d, 0x66, 0xbb, 0x18, 0xef, 0x89, - 0x6c, 0xcb, 0xff, 0xe9, 0x30, 0x94, 0x94, 0xde, 0x15, 0x2d, 0x98, 0xea, 0xf4, 0x8b, 0x69, 0x75, - 0xfa, 0x18, 0x15, 0xff, 0x74, 0x0d, 0xfa, 0x86, 0x61, 0x19, 0x55, 0xc8, 0xcf, 0x05, 0xa7, 0x2b, - 0x1d, 0xfa, 0x3a, 0x82, 0x6a, 0xd7, 0xe8, 0xe2, 0xc0, 0x7a, 0xf9, 0xa1, 0x9e, 0x37, 0xf3, 0x01, - 0xd3, 0x5b, 0xd3, 0x9b, 0x66, 0x3b, 0x68, 0xd5, 0xea, 0xe9, 0x7c, 0xaf, 0x75, 0x5a, 0x88, 0x39, - 0x8c, 0xdd, 0x15, 0xa8, 0x94, 0xc0, 0xee, 0x0a, 0xa3, 0x0f, 0x78, 0x57, 0x90, 0x04, 0x70, 0x42, - 0x0b, 0x79, 0x30, 0xdb, 0x34, 0x53, 0xf5, 0x2a, 0xe7, 0xcf, 0xa7, 0xfa, 0x26, 0xcd, 0xed, 0x68, - 0x39, 0xfc, 0x96, 0xd3, 0x54, 0x70, 0x37, 0x61, 0xf4, 0x06, 0x8c, 0xbd, 0x1f, 0x44, 0x6c, 0x15, - 0x8b, 0xa3, 0x52, 0xba, 0xdb, 0x8d, 0xbd, 0x7d, 0xab, 0xc1, 0xca, 0x8f, 0x0f, 0x2b, 0xe3, 0xf5, - 0xa0, 0x25, 0xff, 0x62, 0x55, 0x01, 0xdd, 0x87, 0x0b, 0x06, 0x83, 0x51, 0xdd, 0x85, 0xc1, 0xbb, - 0xfb, 0x84, 0x68, 0xee, 0x42, 0x2d, 0x8b, 0x12, 0xce, 0x6e, 0xc0, 0xfe, 0x25, 0xae, 0x5d, 0x16, - 0x3a, 0x28, 0x12, 0x75, 0xbc, 0xb3, 0x48, 0xd4, 0xb5, 0x62, 0xa8, 0xc7, 0x1e, 0xf8, 0x05, 0xe3, - 0xd7, 0x2c, 0xf6, 0x82, 0xb1, 0x41, 0xf6, 0xda, 0x9e, 0x13, 0x9f, 0x85, 0x47, 0xc1, 0xdb, 0x30, - 0x16, 0x8b, 0xd6, 0x7a, 0xe5, 0x16, 0xd3, 0x3a, 0xc5, 0x5e, 0x71, 0xd4, 0xf9, 0x2a, 0x4b, 0xb1, - 0x22, 0x63, 0xff, 0x73, 0x3e, 0x03, 0x12, 0x72, 0x06, 0xaa, 0x8a, 0xaa, 0xa9, 0xaa, 0xa8, 0xf4, - 0xf9, 0x82, 0x1c, 0x95, 0xc5, 0x3f, 0x33, 0xfb, 0xcd, 0xae, 0x32, 0x9f, 0xf4, 0xa7, 0x33, 0xfb, - 0x47, 0x2c, 0x38, 0x9f, 0x65, 0x0d, 0x42, 0x65, 0x22, 0x7e, 0x91, 0x52, 0x4f, 0x89, 0x6a, 0x04, - 0xef, 0x88, 0x72, 0xac, 0x30, 0x06, 0x4e, 0xdb, 0x71, 0xb2, 0xd8, 0x72, 0xb7, 0xc0, 0xcc, 0xea, - 0x8c, 0xde, 0xe4, 0x2e, 0x42, 0x96, 0x4a, 0xbb, 0x7c, 0x32, 0xf7, 0x20, 0xfb, 0xa7, 0x0b, 0x70, - 0x9e, 0xbf, 0x05, 0x2c, 0xee, 0x07, 0x6e, 0xab, 0x1e, 0xb4, 0x84, 0xc3, 0xd4, 0x3b, 0x30, 0xd1, - 0xd6, 0x6e, 0xbf, 0xbd, 0xa2, 0x5b, 0xe9, 0xb7, 0xe4, 0xe4, 0x16, 0xa2, 0x97, 0x62, 0x83, 0x16, - 0x6a, 0xc1, 0x04, 0xd9, 0x77, 0x9b, 0x4a, 0xa1, 0x5c, 0x38, 0x31, 0x4b, 0x57, 0xad, 0xac, 0x68, - 0x74, 0xb0, 0x41, 0xf5, 0x21, 0x64, 0xe1, 0xb3, 0x7f, 0xd4, 0x82, 0x47, 0x73, 0x62, 0x61, 0xd1, - 0xe6, 0xee, 0xb1, 0x57, 0x17, 0x91, 0xd0, 0x4b, 0x35, 0xc7, 0xdf, 0x62, 0xb0, 0x80, 0xa2, 0x2f, - 0x01, 0xf0, 0xb7, 0x14, 0x2a, 0x94, 0x8b, 0x4f, 0x1f, 0x2c, 0x46, 0x8c, 0x16, 0x48, 0x44, 0xd6, - 0xc7, 0x1a, 0x2d, 0xfb, 0x27, 0x8b, 0x30, 0xcc, 0x74, 0xf7, 0x68, 0x15, 0x46, 0x77, 0x78, 0xe4, - 0xed, 0x41, 0x82, 0x7c, 0x27, 0xb7, 0x1b, 0x5e, 0x80, 0x65, 0x65, 0xb4, 0x06, 0xe7, 0x84, 0x53, - 0x5e, 0x95, 0x78, 0xce, 0x81, 0xbc, 0x24, 0xf3, 0x24, 0x58, 0x2a, 0xed, 0x5b, 0xad, 0x1b, 0x05, - 0x67, 0xd5, 0x43, 0x6f, 0x76, 0xc5, 0xdb, 0xe4, 0x31, 0xcb, 0x95, 0x48, 0xdd, 0x27, 0xe6, 0xe6, - 0x1b, 0x30, 0xd9, 0xee, 0x52, 0x07, 0x0c, 0x27, 0xe2, 0xbe, 0xa9, 0x02, 0x30, 0x71, 0x99, 0x19, - 0x48, 0x87, 0x19, 0xbd, 0x6c, 0xec, 0x84, 0x24, 0xda, 0x09, 0xbc, 0x96, 0xc8, 0x4b, 0x9f, 0x98, - 0x81, 0xa4, 0xe0, 0xb8, 0xab, 0x06, 0xa5, 0xb2, 0xe5, 0xb8, 0x5e, 0x27, 0x24, 0x09, 0x95, 0x11, - 0x93, 0xca, 0x6a, 0x0a, 0x8e, 0xbb, 0x6a, 0xd0, 0x75, 0x74, 0x41, 0x24, 0x35, 0x97, 0xa1, 0x1a, - 0x94, 0x6d, 0xcf, 0xa8, 0x74, 0xd9, 0xe8, 0x11, 0x3e, 0x48, 0xd8, 0x56, 0xa8, 0xb4, 0xe8, 0x5a, - 0xca, 0x5c, 0xe1, 0xac, 0x21, 0xa9, 0x3c, 0x48, 0x6a, 0xed, 0xdf, 0xb3, 0xe0, 0x5c, 0x86, 0x0d, - 0x21, 0x67, 0x55, 0xdb, 0x6e, 0x14, 0xab, 0x44, 0x3f, 0x1a, 0xab, 0xe2, 0xe5, 0x58, 0x61, 0xd0, - 0xfd, 0xc0, 0x99, 0x61, 0x9a, 0x01, 0x0a, 0x1b, 0x1d, 0x01, 0x3d, 0x19, 0x03, 0x44, 0x97, 0x61, - 0xa8, 0x13, 0x91, 0x50, 0xe6, 0xa4, 0x96, 0xfc, 0x9b, 0x29, 0x18, 0x19, 0x84, 0x4a, 0x94, 0xdb, - 0x4a, 0xb7, 0xa7, 0x49, 0x94, 0x5c, 0xbb, 0xc7, 0x61, 0xf6, 0xd7, 0x8a, 0x70, 0x31, 0xd7, 0x46, - 0x98, 0x76, 0x69, 0x2f, 0xf0, 0xdd, 0x38, 0x50, 0xef, 0x42, 0x3c, 0xce, 0x0d, 0x69, 0xef, 0xac, - 0x89, 0x72, 0xac, 0x30, 0xd0, 0xd3, 0x30, 0xcc, 0xee, 0xcf, 0x5d, 0xa9, 0x8c, 0x96, 0xaa, 0x3c, - 0xfc, 0x02, 0x07, 0x0f, 0x9c, 0x26, 0xee, 0x29, 0x18, 0x6a, 0x07, 0x81, 0x97, 0x66, 0x46, 0xb4, - 0xbb, 0x41, 0xe0, 0x61, 0x06, 0x44, 0x9f, 0x11, 0xe3, 0x90, 0x7a, 0x08, 0xc1, 0x4e, 0x2b, 0x88, - 0xb4, 0xc1, 0x78, 0x16, 0x46, 0x77, 0xc9, 0x41, 0xe8, 0xfa, 0xdb, 0xe9, 0x07, 0xb2, 0x1b, 0xbc, - 0x18, 0x4b, 0xb8, 0x99, 0xc9, 0x63, 0xf4, 0xb4, 0xf3, 0xbb, 0x8d, 0xf5, 0x3d, 0xda, 0x7e, 0xa0, - 0x08, 0xd3, 0x78, 0xa9, 0xfa, 0xad, 0x89, 0xb8, 0xdd, 0x3d, 0x11, 0xa7, 0x9d, 0xdf, 0xad, 0xff, - 0x6c, 0xfc, 0xbc, 0x05, 0xd3, 0x2c, 0xda, 0xb5, 0x88, 0xd3, 0xe2, 0x06, 0xfe, 0x19, 0x88, 0x6e, - 0x4f, 0xc1, 0x70, 0x48, 0x1b, 0x4d, 0x27, 0x6d, 0x62, 0x3d, 0xc1, 0x1c, 0x86, 0x1e, 0x87, 0x21, - 0xd6, 0x05, 0x3a, 0x79, 0x13, 0x3c, 0xdf, 0x45, 0xd5, 0x89, 0x1d, 0xcc, 0x4a, 0x99, 0xc3, 0x2c, - 0x26, 0x6d, 0xcf, 0xe5, 0x9d, 0x4e, 0x14, 0xea, 0x9f, 0x0c, 0x87, 0xd9, 0xcc, 0xae, 0x7d, 0x34, - 0x87, 0xd9, 0x6c, 0x92, 0xbd, 0xaf, 0x45, 0xff, 0xa3, 0x00, 0x97, 0x32, 0xeb, 0x0d, 0xec, 0x30, - 0xdb, 0xbb, 0xf6, 0xe9, 0xd8, 0x39, 0x64, 0x9b, 0x1f, 0x14, 0xcf, 0xd0, 0xfc, 0x60, 0x68, 0x50, - 0xc9, 0x71, 0x78, 0x00, 0x3f, 0xd6, 0xcc, 0x21, 0xfb, 0x84, 0xf8, 0xb1, 0x66, 0xf6, 0x2d, 0xe7, - 0x5a, 0xf7, 0x67, 0x85, 0x9c, 0x6f, 0x61, 0x17, 0xbc, 0x2b, 0x94, 0xcf, 0x30, 0x60, 0x24, 0x24, - 0xe1, 0x09, 0xce, 0x63, 0x78, 0x19, 0x56, 0x50, 0xe4, 0x6a, 0x1e, 0xa1, 0x85, 0xfc, 0x94, 0x9e, - 0xb9, 0x4d, 0xcd, 0x9b, 0xef, 0x1f, 0x7a, 0x50, 0x99, 0xb4, 0x77, 0xe8, 0x9a, 0x76, 0x29, 0x2f, - 0x0e, 0x7e, 0x29, 0x9f, 0xc8, 0xbe, 0x90, 0xa3, 0x45, 0x98, 0xde, 0x73, 0x7d, 0xca, 0x36, 0x0f, - 0x4c, 0x51, 0x54, 0x05, 0x48, 0x58, 0x33, 0xc1, 0x38, 0x8d, 0x3f, 0xf7, 0x06, 0x4c, 0x3e, 0xb8, - 0x16, 0xf1, 0x1b, 0x45, 0x78, 0xac, 0xc7, 0xb6, 0xe7, 0xbc, 0xde, 0x98, 0x03, 0x8d, 0xd7, 0x77, - 0xcd, 0x43, 0x1d, 0xce, 0x6f, 0x75, 0x3c, 0xef, 0x80, 0x59, 0xf8, 0x91, 0x96, 0xc4, 0x10, 0xb2, - 0xa2, 0x0a, 0x65, 0xbf, 0x9a, 0x81, 0x83, 0x33, 0x6b, 0xa2, 0xb7, 0x00, 0x05, 0x22, 0x9f, 0x70, - 0x12, 0x2a, 0x87, 0x0d, 0x7c, 0x31, 0xd9, 0x8c, 0xb7, 0xba, 0x30, 0x70, 0x46, 0x2d, 0x2a, 0xf4, - 0xd3, 0x53, 0xe9, 0x40, 0x75, 0x2b, 0x25, 0xf4, 0x63, 0x1d, 0x88, 0x4d, 0x5c, 0x74, 0x0d, 0x66, - 0x9d, 0x7d, 0xc7, 0xe5, 0xa1, 0x13, 0x25, 0x01, 0x2e, 0xf5, 0x2b, 0xdd, 0xdd, 0x62, 0x1a, 0x01, - 0x77, 0xd7, 0x49, 0xb9, 0xa4, 0x8e, 0xe4, 0xbb, 0xa4, 0xf6, 0xe6, 0x8b, 0xfd, 0x54, 0xb1, 0xf6, - 0x7f, 0xb6, 0xe8, 0xf1, 0xa5, 0xa5, 0xf9, 0xd7, 0x33, 0x2a, 0x28, 0x95, 0xa2, 0xe6, 0x1d, 0xaa, - 0xc6, 0x61, 0x59, 0x07, 0x62, 0x13, 0x97, 0x2f, 0x88, 0x28, 0x71, 0x54, 0x30, 0x44, 0x77, 0xe1, - 0xfe, 0xad, 0x30, 0xd0, 0x97, 0x61, 0xb4, 0xe5, 0xee, 0xbb, 0x51, 0x10, 0x8a, 0xcd, 0x72, 0x42, - 0x63, 0xf2, 0x84, 0x0f, 0x56, 0x39, 0x19, 0x2c, 0xe9, 0xd9, 0x3f, 0x50, 0x80, 0x49, 0xd9, 0xe2, - 0xdb, 0x9d, 0x20, 0x76, 0xce, 0xe0, 0x58, 0xbe, 0x66, 0x1c, 0xcb, 0x9f, 0xe9, 0xe5, 0x03, 0xcf, - 0xba, 0x94, 0x7b, 0x1c, 0xdf, 0x4a, 0x1d, 0xc7, 0xcf, 0xf4, 0x27, 0xd5, 0xfb, 0x18, 0xfe, 0x17, - 0x16, 0xcc, 0x1a, 0xf8, 0x67, 0x70, 0x1a, 0xac, 0x9a, 0xa7, 0xc1, 0x93, 0x7d, 0xbf, 0x21, 0xe7, - 0x14, 0xf8, 0x7a, 0x21, 0xd5, 0x77, 0xc6, 0xfd, 0xdf, 0x87, 0xa1, 0x1d, 0x27, 0x6c, 0xf5, 0x0a, - 0x00, 0xdc, 0x55, 0x69, 0xfe, 0xba, 0x13, 0xb6, 0x38, 0x0f, 0x7f, 0x41, 0x65, 0x21, 0x75, 0xc2, - 0x56, 0x5f, 0xbf, 0x1c, 0xd6, 0x14, 0x7a, 0x1d, 0x46, 0xa2, 0x66, 0xd0, 0x56, 0x36, 0x79, 0x97, - 0x79, 0x86, 0x52, 0x5a, 0x72, 0x7c, 0x58, 0x41, 0x66, 0x73, 0xb4, 0x18, 0x0b, 0xfc, 0xb9, 0x6d, - 0x28, 0xa9, 0xa6, 0x1f, 0xaa, 0x47, 0xc5, 0x6f, 0x17, 0xe1, 0x5c, 0xc6, 0xba, 0x40, 0x91, 0x31, - 0x5a, 0x2f, 0x0d, 0xb8, 0x9c, 0x3e, 0xe2, 0x78, 0x45, 0xec, 0xc6, 0xd2, 0x12, 0xf3, 0x3f, 0x70, - 0xa3, 0xb7, 0x23, 0x92, 0x6e, 0x94, 0x16, 0xf5, 0x6f, 0x94, 0x36, 0x76, 0x66, 0x43, 0x4d, 0x1b, - 0x52, 0x3d, 0x7d, 0xa8, 0x73, 0xfa, 0xc7, 0x45, 0x38, 0x9f, 0x15, 0x3a, 0x03, 0x7d, 0x77, 0x2a, - 0x9d, 0xd0, 0x2b, 0x83, 0x06, 0xdd, 0xe0, 0x39, 0x86, 0x44, 0xac, 0xb1, 0x79, 0x33, 0xc1, 0x50, - 0xdf, 0x61, 0x16, 0x6d, 0x32, 0x47, 0xb9, 0x90, 0xa7, 0x81, 0x92, 0x5b, 0xfc, 0x73, 0x03, 0x77, - 0x40, 0xe4, 0x8f, 0x8a, 0x52, 0x8e, 0x72, 0xb2, 0xb8, 0xbf, 0xa3, 0x9c, 0x6c, 0x79, 0xce, 0x85, - 0x71, 0xed, 0x6b, 0x1e, 0xea, 0x8c, 0xef, 0xd2, 0x13, 0x45, 0xeb, 0xf7, 0x43, 0x9d, 0xf5, 0x1f, - 0xb5, 0x20, 0x65, 0x09, 0xa7, 0x54, 0x52, 0x56, 0xae, 0x4a, 0xea, 0x32, 0x0c, 0x85, 0x81, 0x47, - 0xd2, 0x19, 0x66, 0x70, 0xe0, 0x11, 0xcc, 0x20, 0x14, 0x23, 0x4e, 0x14, 0x12, 0x13, 0xfa, 0x65, - 0x4b, 0x5c, 0xa3, 0x9e, 0x82, 0x61, 0x8f, 0xec, 0x13, 0xa9, 0x8d, 0x50, 0x3c, 0xf9, 0x26, 0x2d, - 0xc4, 0x1c, 0x66, 0xff, 0xfc, 0x10, 0x3c, 0xd1, 0xd3, 0xd5, 0x94, 0x5e, 0x59, 0xb6, 0x9d, 0x98, - 0xdc, 0x73, 0x0e, 0xd2, 0xf1, 0xaf, 0xaf, 0xf1, 0x62, 0x2c, 0xe1, 0xcc, 0x6e, 0x97, 0x87, 0xd0, - 0x4c, 0x29, 0xf0, 0x44, 0xe4, 0x4c, 0x01, 0x35, 0x15, 0x47, 0xc5, 0xd3, 0x50, 0x1c, 0x5d, 0x05, - 0x88, 0x22, 0x6f, 0xc5, 0xa7, 0x12, 0x58, 0x4b, 0x18, 0x04, 0x27, 0xa1, 0x56, 0x1b, 0x37, 0x05, - 0x04, 0x6b, 0x58, 0xa8, 0x0a, 0x33, 0xed, 0x30, 0x88, 0xb9, 0x3e, 0xb4, 0xca, 0x4d, 0x51, 0x86, - 0x4d, 0x2f, 0xbf, 0x7a, 0x0a, 0x8e, 0xbb, 0x6a, 0xa0, 0x57, 0x61, 0x5c, 0x78, 0xfe, 0xd5, 0x83, - 0xc0, 0x13, 0xaa, 0x1a, 0x65, 0xd8, 0xd0, 0x48, 0x40, 0x58, 0xc7, 0xd3, 0xaa, 0x31, 0x25, 0xeb, - 0x68, 0x66, 0x35, 0xae, 0x68, 0xd5, 0xf0, 0x52, 0x61, 0x74, 0xc6, 0x06, 0x0a, 0xa3, 0x93, 0x28, - 0xaf, 0x4a, 0x03, 0xbf, 0x2b, 0x41, 0x5f, 0x75, 0xcf, 0xcf, 0x0c, 0xc1, 0x39, 0xb1, 0x70, 0x1e, - 0xf6, 0x72, 0xb9, 0xdd, 0xbd, 0x5c, 0x4e, 0x43, 0xbd, 0xf5, 0xad, 0x35, 0x73, 0xd6, 0x6b, 0xe6, - 0x97, 0x8a, 0x30, 0xc2, 0xa7, 0xe2, 0x0c, 0x64, 0xf8, 0x55, 0xa1, 0xf4, 0xeb, 0x11, 0x40, 0x86, - 0xf7, 0x65, 0xbe, 0xea, 0xc4, 0x0e, 0x3f, 0xbf, 0x14, 0x1b, 0x4d, 0xd4, 0x83, 0x68, 0xde, 0x60, - 0xb4, 0x73, 0x29, 0xad, 0x16, 0x70, 0x1a, 0x1a, 0xdb, 0xfd, 0x0a, 0x40, 0xc4, 0x52, 0xe8, 0x53, - 0x1a, 0x22, 0x14, 0xd1, 0x73, 0x3d, 0x5a, 0x6f, 0x28, 0x64, 0xde, 0x87, 0x64, 0x09, 0x2a, 0x00, - 0xd6, 0x28, 0xce, 0xbd, 0x06, 0x25, 0x85, 0xdc, 0x4f, 0x05, 0x30, 0xa1, 0x9f, 0x7a, 0x5f, 0x84, - 0xe9, 0x54, 0x5b, 0x27, 0xd2, 0x20, 0xfc, 0x82, 0x05, 0xd3, 0xbc, 0xcb, 0x2b, 0xfe, 0xbe, 0xd8, - 0xec, 0x1f, 0xc0, 0x79, 0x2f, 0x63, 0xd3, 0x89, 0x19, 0x1d, 0x7c, 0x93, 0x2a, 0x8d, 0x41, 0x16, - 0x14, 0x67, 0xb6, 0x81, 0xae, 0xc0, 0x18, 0x77, 0x74, 0x71, 0x3c, 0xe1, 0x9c, 0x30, 0xc1, 0x53, - 0x52, 0xf0, 0x32, 0xac, 0xa0, 0xf6, 0xef, 0x58, 0x30, 0xcb, 0x7b, 0x7e, 0x83, 0x1c, 0xa8, 0xdb, - 0xf1, 0xc7, 0xd9, 0x77, 0x91, 0x71, 0xa3, 0x90, 0x93, 0x71, 0x43, 0xff, 0xb4, 0x62, 0xcf, 0x4f, - 0xfb, 0x69, 0x0b, 0xc4, 0x0a, 0x3c, 0x83, 0x7b, 0xe0, 0xb7, 0x9b, 0xf7, 0xc0, 0xb9, 0xfc, 0x45, - 0x9d, 0x73, 0x01, 0xfc, 0x53, 0x0b, 0x66, 0x38, 0x42, 0xf2, 0x10, 0xf9, 0xb1, 0xce, 0xc3, 0x20, - 0x69, 0xe0, 0x54, 0xde, 0xed, 0xec, 0x8f, 0x32, 0x26, 0x6b, 0xa8, 0xe7, 0x64, 0xb5, 0xe4, 0x06, - 0x3a, 0x41, 0x7a, 0xc3, 0x13, 0x07, 0x89, 0xb5, 0xff, 0xc8, 0x02, 0xc4, 0x9b, 0x31, 0xce, 0x65, - 0x7a, 0xda, 0xb1, 0x52, 0x4d, 0x13, 0x94, 0xb0, 0x1a, 0x05, 0xc1, 0x1a, 0xd6, 0xa9, 0x0c, 0x4f, - 0xea, 0x35, 0xb9, 0xd8, 0xff, 0x35, 0xf9, 0x04, 0x23, 0xfa, 0xd7, 0x87, 0x20, 0x6d, 0x09, 0x8d, - 0xee, 0xc0, 0x44, 0xd3, 0x69, 0x3b, 0x9b, 0xae, 0xe7, 0xc6, 0x2e, 0x89, 0x7a, 0x99, 0xa1, 0x2c, - 0x6b, 0x78, 0xe2, 0x9d, 0x50, 0x2b, 0xc1, 0x06, 0x1d, 0x34, 0x0f, 0xd0, 0x0e, 0xdd, 0x7d, 0xd7, - 0x23, 0xdb, 0xec, 0x2a, 0xcc, 0xdc, 0xa1, 0xb8, 0x6d, 0x85, 0x2c, 0xc5, 0x1a, 0x46, 0x86, 0xfb, - 0x4c, 0xf1, 0xe1, 0xb9, 0xcf, 0x0c, 0x9d, 0xd0, 0x7d, 0x66, 0x78, 0x20, 0xf7, 0x19, 0x0c, 0x8f, - 0xc8, 0xb3, 0x9b, 0xfe, 0x5f, 0x75, 0x3d, 0x22, 0x04, 0x36, 0xee, 0x24, 0x35, 0x77, 0x74, 0x58, - 0x79, 0x04, 0x67, 0x62, 0xe0, 0x9c, 0x9a, 0xe8, 0x4b, 0x50, 0x76, 0x3c, 0x2f, 0xb8, 0xa7, 0x46, - 0x6d, 0x25, 0x6a, 0x3a, 0x5e, 0x12, 0x33, 0x7d, 0x6c, 0xe9, 0xf1, 0xa3, 0xc3, 0x4a, 0x79, 0x31, - 0x07, 0x07, 0xe7, 0xd6, 0xb6, 0x77, 0xe1, 0x5c, 0x83, 0x84, 0x32, 0x63, 0xaa, 0xda, 0x62, 0x1b, - 0x50, 0x0a, 0x53, 0x4c, 0x65, 0xa0, 0x58, 0x25, 0x5a, 0x3c, 0x4b, 0xc9, 0x44, 0x12, 0x42, 0xf6, - 0x9f, 0x58, 0x30, 0x2a, 0xac, 0xab, 0xcf, 0x40, 0x96, 0x59, 0x34, 0xf4, 0x91, 0x95, 0x6c, 0xc6, - 0xcb, 0x3a, 0x93, 0xab, 0x89, 0xac, 0xa5, 0x34, 0x91, 0x4f, 0xf6, 0x22, 0xd2, 0x5b, 0x07, 0xf9, - 0xc3, 0x45, 0x98, 0x32, 0x2d, 0xcb, 0xcf, 0x60, 0x08, 0xd6, 0x61, 0x34, 0x12, 0x6e, 0x0c, 0x85, - 0x7c, 0xfb, 0xd5, 0xf4, 0x24, 0x26, 0x56, 0x2e, 0xc2, 0x71, 0x41, 0x12, 0xc9, 0xf4, 0x8f, 0x28, - 0x3e, 0x44, 0xff, 0x88, 0x7e, 0xc6, 0xfd, 0x43, 0xa7, 0x61, 0xdc, 0x6f, 0xff, 0x32, 0x63, 0xfe, - 0x7a, 0xf9, 0x19, 0xc8, 0x05, 0xd7, 0xcc, 0x63, 0xc2, 0xee, 0xb1, 0xb2, 0x44, 0xa7, 0x72, 0xe4, - 0x83, 0x7f, 0x6c, 0xc1, 0xb8, 0x40, 0x3c, 0x83, 0x6e, 0x7f, 0x87, 0xd9, 0xed, 0xc7, 0x7a, 0x74, - 0x3b, 0xa7, 0xbf, 0x7f, 0xb7, 0xa0, 0xfa, 0x5b, 0x0f, 0xc2, 0x78, 0xa0, 0x1c, 0x1a, 0x63, 0xf4, - 0x36, 0x18, 0x34, 0x03, 0x4f, 0x1c, 0xe6, 0x8f, 0x27, 0x7e, 0xb2, 0xbc, 0xfc, 0x58, 0xfb, 0x8d, - 0x15, 0x36, 0x73, 0xe3, 0x0c, 0xc2, 0x58, 0x1c, 0xa0, 0x89, 0x1b, 0x67, 0x10, 0xc6, 0x98, 0x41, - 0x50, 0x0b, 0x20, 0x76, 0xc2, 0x6d, 0x12, 0xd3, 0x32, 0xe1, 0x72, 0x9f, 0xbf, 0x0b, 0x3b, 0xb1, - 0xeb, 0xcd, 0xbb, 0x7e, 0x1c, 0xc5, 0xe1, 0x7c, 0xcd, 0x8f, 0x6f, 0x85, 0xfc, 0x6e, 0xa0, 0x39, - 0xbe, 0x2a, 0x5a, 0x58, 0xa3, 0x2b, 0x3d, 0xaf, 0x58, 0x1b, 0xc3, 0xe6, 0x43, 0xe1, 0xba, 0x28, - 0xc7, 0x0a, 0xc3, 0x7e, 0x8d, 0xf1, 0x64, 0x36, 0x40, 0x27, 0xf3, 0x49, 0xfd, 0xcd, 0x31, 0x35, - 0xb4, 0xec, 0x95, 0xa0, 0xaa, 0x7b, 0xbe, 0xf6, 0x66, 0x81, 0xb4, 0x61, 0xdd, 0x2d, 0x20, 0x71, - 0x8f, 0x45, 0xdf, 0xd9, 0xf5, 0x7e, 0xfc, 0x62, 0x1f, 0x5e, 0x7a, 0x82, 0x17, 0x63, 0x16, 0x88, - 0x95, 0x05, 0xac, 0xac, 0xd5, 0xd3, 0x59, 0x4e, 0x96, 0x25, 0x00, 0x27, 0x38, 0x68, 0x41, 0xdc, - 0x2c, 0xb9, 0x7e, 0xee, 0xb1, 0xd4, 0xcd, 0x52, 0x7e, 0xbe, 0x76, 0xb5, 0x7c, 0x09, 0xc6, 0x55, - 0xe6, 0xb8, 0x3a, 0x4f, 0xc0, 0x25, 0x02, 0x10, 0xac, 0x24, 0xc5, 0x58, 0xc7, 0x41, 0x1b, 0x30, - 0x1d, 0xf1, 0xb4, 0x76, 0xd2, 0x19, 0x4a, 0xe8, 0x0d, 0x9e, 0x93, 0xef, 0xce, 0x0d, 0x13, 0x7c, - 0xcc, 0x8a, 0xf8, 0x66, 0x95, 0xee, 0x53, 0x69, 0x12, 0xe8, 0x4d, 0x98, 0xf2, 0xf4, 0xf4, 0xde, - 0x75, 0xa1, 0x56, 0x50, 0x66, 0x99, 0x46, 0xf2, 0xef, 0x3a, 0x4e, 0x61, 0x53, 0x21, 0x40, 0x2f, - 0x11, 0xd1, 0xcb, 0x1c, 0x7f, 0x9b, 0x44, 0x22, 0xef, 0x15, 0x13, 0x02, 0x6e, 0xe6, 0xe0, 0xe0, - 0xdc, 0xda, 0xe8, 0x75, 0x98, 0x90, 0x9f, 0xaf, 0x39, 0x07, 0x26, 0xc6, 0xbf, 0x1a, 0x0c, 0x1b, - 0x98, 0xe8, 0x1e, 0x5c, 0x90, 0xff, 0x37, 0x42, 0x67, 0x6b, 0xcb, 0x6d, 0x0a, 0xdf, 0xcc, 0x71, - 0x46, 0x62, 0x51, 0x7a, 0x42, 0xac, 0x64, 0x21, 0x1d, 0x1f, 0x56, 0x2e, 0x8b, 0x51, 0xcb, 0x84, - 0xb3, 0x49, 0xcc, 0xa6, 0x8f, 0xd6, 0xe0, 0xdc, 0x0e, 0x71, 0xbc, 0x78, 0x67, 0x79, 0x87, 0x34, - 0x77, 0xe5, 0x26, 0x62, 0x2e, 0x87, 0x9a, 0xc9, 0xec, 0xf5, 0x6e, 0x14, 0x9c, 0x55, 0x0f, 0xbd, - 0x0b, 0xe5, 0x76, 0x67, 0xd3, 0x73, 0xa3, 0x9d, 0xf5, 0x20, 0x66, 0x4f, 0xdd, 0x2a, 0xf1, 0x9a, - 0xf0, 0x4d, 0x54, 0xee, 0x96, 0xf5, 0x1c, 0x3c, 0x9c, 0x4b, 0x01, 0x7d, 0x00, 0x17, 0x52, 0x8b, - 0x41, 0x78, 0x4a, 0x4d, 0xe5, 0xc7, 0x82, 0x6c, 0x64, 0x55, 0xe0, 0x1e, 0xb3, 0x99, 0x20, 0x9c, - 0xdd, 0xc4, 0x47, 0x33, 0x80, 0x78, 0x9f, 0x56, 0xd6, 0xa4, 0x1b, 0xf4, 0x55, 0x98, 0xd0, 0x57, - 0x91, 0x38, 0x60, 0x9e, 0xee, 0x97, 0xca, 0x5e, 0xc8, 0x46, 0x6a, 0x45, 0xe9, 0x30, 0x6c, 0x50, - 0xb4, 0x09, 0x64, 0x7f, 0x1f, 0xba, 0x09, 0x63, 0x4d, 0xcf, 0x25, 0x7e, 0x5c, 0xab, 0xf7, 0xf2, - 0xa9, 0x5f, 0x16, 0x38, 0x62, 0xc0, 0x44, 0xf0, 0x3c, 0x5e, 0x86, 0x15, 0x05, 0xfb, 0x57, 0x0b, - 0x50, 0xe9, 0x13, 0x89, 0x31, 0xa5, 0x03, 0xb4, 0x06, 0xd2, 0x01, 0x2e, 0xca, 0x34, 0x72, 0xeb, - 0xa9, 0xfb, 0x67, 0x2a, 0x45, 0x5c, 0x72, 0x0b, 0x4d, 0xe3, 0x0f, 0x6c, 0x37, 0xa9, 0xab, 0x11, - 0x87, 0xfa, 0x5a, 0xf4, 0x1a, 0xcf, 0x07, 0xc3, 0x83, 0x4b, 0xf4, 0xb9, 0xaa, 0x60, 0xfb, 0x97, - 0x0b, 0x70, 0x41, 0x0d, 0xe1, 0x37, 0xef, 0xc0, 0xdd, 0xee, 0x1e, 0xb8, 0x53, 0x50, 0xa4, 0xdb, - 0xb7, 0x60, 0xa4, 0x71, 0x10, 0x35, 0x63, 0x6f, 0x00, 0x01, 0xe8, 0x29, 0x33, 0xb6, 0x8c, 0x3a, - 0xa6, 0x8d, 0xf8, 0x32, 0x7f, 0xc5, 0x82, 0xe9, 0x8d, 0xe5, 0x7a, 0x23, 0x68, 0xee, 0x92, 0x78, - 0x91, 0xab, 0x89, 0xb0, 0x90, 0x7f, 0xac, 0x07, 0x94, 0x6b, 0xb2, 0x24, 0xa6, 0xcb, 0x30, 0xb4, - 0x13, 0x44, 0x71, 0xfa, 0x95, 0xed, 0x7a, 0x10, 0xc5, 0x98, 0x41, 0xec, 0xdf, 0xb5, 0x60, 0x98, - 0x25, 0x3f, 0xed, 0x97, 0x24, 0x77, 0x90, 0xef, 0x42, 0xaf, 0xc2, 0x08, 0xd9, 0xda, 0x22, 0xcd, - 0x58, 0xcc, 0xaa, 0xf4, 0xae, 0x1b, 0x59, 0x61, 0xa5, 0xf4, 0xd0, 0x67, 0x8d, 0xf1, 0xbf, 0x58, - 0x20, 0xa3, 0xbb, 0x50, 0x8a, 0xdd, 0x3d, 0xb2, 0xd8, 0x6a, 0x89, 0x77, 0x8a, 0x07, 0x70, 0x66, - 0xdc, 0x90, 0x04, 0x70, 0x42, 0xcb, 0xfe, 0x5a, 0x01, 0x20, 0x71, 0xe8, 0xed, 0xf7, 0x89, 0x4b, - 0x5d, 0x79, 0x80, 0x9f, 0xce, 0xc8, 0x03, 0x8c, 0x12, 0x82, 0x19, 0x59, 0x80, 0xd5, 0x30, 0x15, - 0x07, 0x1a, 0xa6, 0xa1, 0x93, 0x0c, 0xd3, 0x32, 0xcc, 0x26, 0x0e, 0xc9, 0x66, 0x74, 0x06, 0x16, - 0x99, 0x7d, 0x23, 0x0d, 0xc4, 0xdd, 0xf8, 0xf6, 0xf7, 0x5b, 0x20, 0xdc, 0x0d, 0x06, 0x58, 0xcc, - 0xef, 0xc8, 0x94, 0x9d, 0x46, 0x40, 0xd7, 0xcb, 0xf9, 0xfe, 0x17, 0x22, 0x8c, 0xab, 0x3a, 0x3c, - 0x8c, 0xe0, 0xad, 0x06, 0x2d, 0xbb, 0x05, 0x02, 0x5a, 0x25, 0x4c, 0xc9, 0xd0, 0xbf, 0x37, 0x57, - 0x01, 0x5a, 0x0c, 0x57, 0x4b, 0x01, 0xa8, 0x58, 0x55, 0x55, 0x41, 0xb0, 0x86, 0x65, 0xff, 0xcd, - 0x02, 0x8c, 0xcb, 0x00, 0xa2, 0xf4, 0x1e, 0xdf, 0xbf, 0x95, 0x13, 0x65, 0x0f, 0x60, 0x39, 0x33, - 0x29, 0x61, 0x15, 0x64, 0x5e, 0xcf, 0x99, 0x29, 0x01, 0x38, 0xc1, 0x41, 0xcf, 0xc2, 0x68, 0xd4, - 0xd9, 0x64, 0xe8, 0x29, 0x23, 0xfa, 0x06, 0x2f, 0xc6, 0x12, 0x8e, 0xbe, 0x04, 0x33, 0xbc, 0x5e, - 0x18, 0xb4, 0x9d, 0x6d, 0xae, 0x41, 0x1a, 0x56, 0x5e, 0x6d, 0x33, 0x6b, 0x29, 0xd8, 0xf1, 0x61, - 0xe5, 0x7c, 0xba, 0x8c, 0xe9, 0x1e, 0xbb, 0xa8, 0xd0, 0x7d, 0x31, 0x93, 0x76, 0x98, 0x41, 0xd7, - 0x61, 0x84, 0xb3, 0x3c, 0xc1, 0x82, 0x7a, 0xbc, 0x28, 0x69, 0x6e, 0x36, 0x2c, 0x9c, 0xba, 0xe0, - 0x9a, 0xa2, 0x3e, 0x7a, 0x17, 0xc6, 0x5b, 0xc1, 0x3d, 0xff, 0x9e, 0x13, 0xb6, 0x16, 0xeb, 0x35, - 0xb1, 0x6a, 0x32, 0x25, 0xa7, 0x6a, 0x82, 0xa6, 0xbb, 0xee, 0x30, 0xed, 0x69, 0x02, 0xc2, 0x3a, - 0x39, 0xb4, 0xc1, 0x62, 0x3c, 0xf1, 0xa4, 0xf6, 0xbd, 0xac, 0xce, 0x54, 0x1e, 0x7c, 0x8d, 0xf2, - 0xa4, 0x08, 0x04, 0x25, 0x52, 0xe2, 0x27, 0x84, 0xec, 0x0f, 0xcf, 0x81, 0xb1, 0x5a, 0x8d, 0xec, - 0x01, 0xd6, 0x29, 0x65, 0x0f, 0xc0, 0x30, 0x46, 0xf6, 0xda, 0xf1, 0x41, 0xd5, 0x0d, 0x7b, 0xa5, - 0x9f, 0x59, 0x11, 0x38, 0xdd, 0x34, 0x25, 0x04, 0x2b, 0x3a, 0xd9, 0x29, 0x1e, 0x8a, 0x1f, 0x63, - 0x8a, 0x87, 0xa1, 0x33, 0x4c, 0xf1, 0xb0, 0x0e, 0xa3, 0xdb, 0x6e, 0x8c, 0x49, 0x3b, 0x10, 0xc7, - 0x7d, 0xe6, 0x4a, 0xb8, 0xc6, 0x51, 0xba, 0x03, 0x8c, 0x0b, 0x00, 0x96, 0x44, 0xd0, 0x5b, 0x6a, - 0x0f, 0x8c, 0xe4, 0x4b, 0xcb, 0xdd, 0x8f, 0x0f, 0x99, 0xbb, 0x40, 0xa4, 0x74, 0x18, 0x7d, 0xd0, - 0x94, 0x0e, 0xab, 0x32, 0x11, 0xc3, 0x58, 0xbe, 0x91, 0x26, 0xcb, 0xb3, 0xd0, 0x27, 0xfd, 0x82, - 0x91, 0xb2, 0xa2, 0x74, 0x7a, 0x29, 0x2b, 0xbe, 0xdf, 0x82, 0x0b, 0xed, 0xac, 0xec, 0x2d, 0x22, - 0x91, 0xc2, 0xab, 0x03, 0xa7, 0xa7, 0x31, 0x1a, 0x64, 0xd7, 0xa6, 0x4c, 0x34, 0x9c, 0xdd, 0x1c, - 0x1d, 0xe8, 0x70, 0xb3, 0x25, 0xb2, 0x2f, 0x3c, 0x95, 0x93, 0xfb, 0xa2, 0x47, 0xc6, 0x8b, 0x8d, - 0x8c, 0x8c, 0x0b, 0x9f, 0xce, 0xcb, 0xb8, 0x30, 0x70, 0x9e, 0x85, 0x24, 0xeb, 0xc5, 0xe4, 0x47, - 0xce, 0x7a, 0xf1, 0x96, 0xca, 0x7a, 0xd1, 0x23, 0x92, 0x0e, 0xcf, 0x69, 0xd1, 0x37, 0xd7, 0x85, - 0x96, 0xaf, 0x62, 0xfa, 0x74, 0xf2, 0x55, 0x18, 0xcc, 0x9e, 0xa7, 0x4c, 0x78, 0xbe, 0x0f, 0xb3, - 0x37, 0xe8, 0xf6, 0x66, 0xf7, 0x3c, 0x37, 0xc7, 0xec, 0x03, 0xe5, 0xe6, 0xb8, 0xa3, 0xe7, 0xba, - 0x40, 0x7d, 0x92, 0x39, 0x50, 0xa4, 0x01, 0x33, 0x5c, 0xdc, 0xd1, 0x8f, 0xa0, 0x73, 0xf9, 0x74, - 0xd5, 0x49, 0xd3, 0x4d, 0x37, 0xeb, 0x10, 0xea, 0xce, 0x9c, 0x71, 0xfe, 0x6c, 0x32, 0x67, 0x5c, - 0x38, 0xf5, 0xcc, 0x19, 0x8f, 0x9c, 0x41, 0xe6, 0x8c, 0x47, 0x3f, 0xd6, 0xcc, 0x19, 0xe5, 0x87, - 0x90, 0x39, 0x63, 0x3d, 0xc9, 0x9c, 0x71, 0x31, 0x7f, 0x4a, 0x32, 0xac, 0xd2, 0x72, 0xf2, 0x65, - 0xdc, 0x81, 0x52, 0x5b, 0xfa, 0x54, 0x8b, 0x50, 0x3f, 0xd9, 0x29, 0xfb, 0xb2, 0x1c, 0xaf, 0xf9, - 0x94, 0x28, 0x10, 0x4e, 0x48, 0x51, 0xba, 0x49, 0xfe, 0x8c, 0xc7, 0x7a, 0x28, 0xc6, 0xb2, 0x54, - 0x0e, 0xf9, 0x59, 0x33, 0xec, 0xbf, 0x5a, 0x80, 0x4b, 0xbd, 0xd7, 0x75, 0xa2, 0xaf, 0xa8, 0x27, - 0xfa, 0xf5, 0x94, 0xbe, 0x82, 0x5f, 0x02, 0x12, 0xac, 0x81, 0x03, 0x4f, 0x5c, 0x83, 0x59, 0x65, - 0x8e, 0xe6, 0xb9, 0xcd, 0x03, 0x2d, 0x95, 0x9f, 0x72, 0x8d, 0x69, 0xa4, 0x11, 0x70, 0x77, 0x1d, - 0xb4, 0x08, 0xd3, 0x46, 0x61, 0xad, 0x2a, 0x84, 0x7d, 0xa5, 0x20, 0x69, 0x98, 0x60, 0x9c, 0xc6, - 0xb7, 0xbf, 0x6e, 0xc1, 0xa3, 0x39, 0x21, 0xab, 0x07, 0x8e, 0xab, 0xb0, 0x05, 0xd3, 0x6d, 0xb3, - 0x6a, 0x9f, 0xf0, 0x2b, 0x46, 0x60, 0x6c, 0xd5, 0xd7, 0x14, 0x00, 0xa7, 0x89, 0x2e, 0x5d, 0xf9, - 0xf5, 0xdf, 0xbf, 0xf4, 0xa9, 0xdf, 0xfa, 0xfd, 0x4b, 0x9f, 0xfa, 0x9d, 0xdf, 0xbf, 0xf4, 0xa9, - 0xbf, 0x78, 0x74, 0xc9, 0xfa, 0xf5, 0xa3, 0x4b, 0xd6, 0x6f, 0x1d, 0x5d, 0xb2, 0x7e, 0xe7, 0xe8, - 0x92, 0xf5, 0x7b, 0x47, 0x97, 0xac, 0xaf, 0xfd, 0xc1, 0xa5, 0x4f, 0xbd, 0x53, 0xd8, 0x7f, 0xe9, - 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0x18, 0x48, 0x7e, 0xc6, 0x9b, 0xdf, 0x00, 0x00, + // 12392 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x6b, 0x90, 0x24, 0x57, + 0x56, 0x18, 0xbc, 0x59, 0xd5, 0xaf, 0x3a, 0xfd, 0xbe, 0x33, 0x23, 0xd5, 0xb4, 0xa4, 0xa9, 0x51, + 0x6a, 0x77, 0x34, 0x7a, 0x75, 0xaf, 0x46, 0xd2, 0x6a, 0x58, 0xed, 0x0a, 0xba, 0xbb, 0xba, 0x67, + 0x4a, 0x33, 0xdd, 0x53, 0xba, 0xd5, 0x33, 0xb3, 0x2b, 0xc4, 0x7e, 0x9b, 0x5d, 0x75, 0xbb, 0x3b, + 0xd5, 0xd9, 0x99, 0xa5, 0xcc, 0xac, 0x9e, 0x69, 0x05, 0x44, 0x7c, 0x96, 0x01, 0x3f, 0xe0, 0xc7, + 0x86, 0x4d, 0xd8, 0x18, 0x08, 0x1c, 0x61, 0xe3, 0x80, 0x35, 0xb6, 0xc3, 0x18, 0x0c, 0x18, 0xb0, + 0x8d, 0xb1, 0xc3, 0x01, 0x7f, 0x30, 0x98, 0x1f, 0x4b, 0x04, 0xe1, 0x36, 0x0c, 0x84, 0x1d, 0xfc, + 0xb0, 0xc3, 0x36, 0xbf, 0x68, 0x63, 0xe3, 0xb8, 0xcf, 0xbc, 0x37, 0x2b, 0xb3, 0xaa, 0x7a, 0xd4, + 0xd3, 0x12, 0x1b, 0xfb, 0xaf, 0xea, 0x9e, 0x73, 0xcf, 0xbd, 0x79, 0x1f, 0xe7, 0x9e, 0x7b, 0xee, + 0x79, 0xc0, 0x1b, 0xbb, 0x57, 0xa3, 0x79, 0x37, 0x58, 0xd8, 0xed, 0x6c, 0x92, 0xd0, 0x27, 0x31, + 0x89, 0x16, 0xf6, 0x89, 0xdf, 0x0a, 0xc2, 0x05, 0x01, 0x70, 0xda, 0xee, 0x42, 0x33, 0x08, 0xc9, + 0xc2, 0xfe, 0xcb, 0x0b, 0xdb, 0xc4, 0x27, 0xa1, 0x13, 0x93, 0xd6, 0x7c, 0x3b, 0x0c, 0xe2, 0x00, + 0x21, 0x8e, 0x33, 0xef, 0xb4, 0xdd, 0x79, 0x8a, 0x33, 0xbf, 0xff, 0xf2, 0xdc, 0x4b, 0xdb, 0x6e, + 0xbc, 0xd3, 0xd9, 0x9c, 0x6f, 0x06, 0x7b, 0x0b, 0xdb, 0xc1, 0x76, 0xb0, 0xc0, 0x50, 0x37, 0x3b, + 0x5b, 0xec, 0x1f, 0xfb, 0xc3, 0x7e, 0x71, 0x12, 0x73, 0x6b, 0x49, 0x33, 0xe4, 0x7e, 0x4c, 0xfc, + 0xc8, 0x0d, 0xfc, 0xe8, 0x25, 0xa7, 0xed, 0x46, 0x24, 0xdc, 0x27, 0xe1, 0x42, 0x7b, 0x77, 0x9b, + 0xc2, 0x22, 0x13, 0x61, 0x61, 0xff, 0xe5, 0x4d, 0x12, 0x3b, 0x5d, 0x3d, 0x9a, 0x7b, 0x35, 0x21, + 0xb7, 0xe7, 0x34, 0x77, 0x5c, 0x9f, 0x84, 0x07, 0x92, 0xc6, 0x42, 0x48, 0xa2, 0xa0, 0x13, 0x36, + 0xc9, 0xb1, 0x6a, 0x45, 0x0b, 0x7b, 0x24, 0x76, 0x32, 0xbe, 0x7e, 0x6e, 0x21, 0xaf, 0x56, 0xd8, + 0xf1, 0x63, 0x77, 0xaf, 0xbb, 0x99, 0xcf, 0xf5, 0xab, 0x10, 0x35, 0x77, 0xc8, 0x9e, 0xd3, 0x55, + 0xef, 0x95, 0xbc, 0x7a, 0x9d, 0xd8, 0xf5, 0x16, 0x5c, 0x3f, 0x8e, 0xe2, 0x30, 0x5d, 0xc9, 0xfe, + 0x86, 0x05, 0x17, 0x17, 0xef, 0x36, 0x56, 0x3c, 0x27, 0x8a, 0xdd, 0xe6, 0x92, 0x17, 0x34, 0x77, + 0x1b, 0x71, 0x10, 0x92, 0x3b, 0x81, 0xd7, 0xd9, 0x23, 0x0d, 0x36, 0x10, 0xe8, 0x45, 0x18, 0xdb, + 0x67, 0xff, 0x6b, 0xd5, 0xb2, 0x75, 0xd1, 0xba, 0x5c, 0x5a, 0x9a, 0xf9, 0xf5, 0xc3, 0xca, 0xa7, + 0x1e, 0x1c, 0x56, 0xc6, 0xee, 0x88, 0x72, 0xac, 0x30, 0xd0, 0x25, 0x18, 0xd9, 0x8a, 0x36, 0x0e, + 0xda, 0xa4, 0x5c, 0x60, 0xb8, 0x53, 0x02, 0x77, 0x64, 0xb5, 0x41, 0x4b, 0xb1, 0x80, 0xa2, 0x05, + 0x28, 0xb5, 0x9d, 0x30, 0x76, 0x63, 0x37, 0xf0, 0xcb, 0xc5, 0x8b, 0xd6, 0xe5, 0xe1, 0xa5, 0x59, + 0x81, 0x5a, 0xaa, 0x4b, 0x00, 0x4e, 0x70, 0x68, 0x37, 0x42, 0xe2, 0xb4, 0x6e, 0xf9, 0xde, 0x41, + 0x79, 0xe8, 0xa2, 0x75, 0x79, 0x2c, 0xe9, 0x06, 0x16, 0xe5, 0x58, 0x61, 0xd8, 0x3f, 0x52, 0x80, + 0xb1, 0xc5, 0xad, 0x2d, 0xd7, 0x77, 0xe3, 0x03, 0x74, 0x07, 0x26, 0xfc, 0xa0, 0x45, 0xe4, 0x7f, + 0xf6, 0x15, 0xe3, 0x57, 0x2e, 0xce, 0x77, 0xaf, 0xcc, 0xf9, 0x75, 0x0d, 0x6f, 0x69, 0xe6, 0xc1, + 0x61, 0x65, 0x42, 0x2f, 0xc1, 0x06, 0x1d, 0x84, 0x61, 0xbc, 0x1d, 0xb4, 0x14, 0xd9, 0x02, 0x23, + 0x5b, 0xc9, 0x22, 0x5b, 0x4f, 0xd0, 0x96, 0xa6, 0x1f, 0x1c, 0x56, 0xc6, 0xb5, 0x02, 0xac, 0x13, + 0x41, 0x9b, 0x30, 0x4d, 0xff, 0xfa, 0xb1, 0xab, 0xe8, 0x16, 0x19, 0xdd, 0x67, 0xf2, 0xe8, 0x6a, + 0xa8, 0x4b, 0x67, 0x1e, 0x1c, 0x56, 0xa6, 0x53, 0x85, 0x38, 0x4d, 0xd0, 0xfe, 0x00, 0xa6, 0x16, + 0xe3, 0xd8, 0x69, 0xee, 0x90, 0x16, 0x9f, 0x41, 0xf4, 0x2a, 0x0c, 0xf9, 0xce, 0x1e, 0x11, 0xf3, + 0x7b, 0x51, 0x0c, 0xec, 0xd0, 0xba, 0xb3, 0x47, 0x8e, 0x0e, 0x2b, 0x33, 0xb7, 0x7d, 0xf7, 0xfd, + 0x8e, 0x58, 0x15, 0xb4, 0x0c, 0x33, 0x6c, 0x74, 0x05, 0xa0, 0x45, 0xf6, 0xdd, 0x26, 0xa9, 0x3b, + 0xf1, 0x8e, 0x98, 0x6f, 0x24, 0xea, 0x42, 0x55, 0x41, 0xb0, 0x86, 0x65, 0xdf, 0x87, 0xd2, 0xe2, + 0x7e, 0xe0, 0xb6, 0xea, 0x41, 0x2b, 0x42, 0xbb, 0x30, 0xdd, 0x0e, 0xc9, 0x16, 0x09, 0x55, 0x51, + 0xd9, 0xba, 0x58, 0xbc, 0x3c, 0x7e, 0xe5, 0x72, 0xe6, 0xc7, 0x9a, 0xa8, 0x2b, 0x7e, 0x1c, 0x1e, + 0x2c, 0x3d, 0x2e, 0xda, 0x9b, 0x4e, 0x41, 0x71, 0x9a, 0xb2, 0xfd, 0xef, 0x0a, 0x70, 0x6e, 0xf1, + 0x83, 0x4e, 0x48, 0xaa, 0x6e, 0xb4, 0x9b, 0x5e, 0xe1, 0x2d, 0x37, 0xda, 0x5d, 0x4f, 0x46, 0x40, + 0x2d, 0xad, 0xaa, 0x28, 0xc7, 0x0a, 0x03, 0xbd, 0x04, 0xa3, 0xf4, 0xf7, 0x6d, 0x5c, 0x13, 0x9f, + 0x7c, 0x46, 0x20, 0x8f, 0x57, 0x9d, 0xd8, 0xa9, 0x72, 0x10, 0x96, 0x38, 0x68, 0x0d, 0xc6, 0x9b, + 0x6c, 0x43, 0x6e, 0xaf, 0x05, 0x2d, 0xc2, 0x26, 0xb3, 0xb4, 0xf4, 0x02, 0x45, 0x5f, 0x4e, 0x8a, + 0x8f, 0x0e, 0x2b, 0x65, 0xde, 0x37, 0x41, 0x42, 0x83, 0x61, 0xbd, 0x3e, 0xb2, 0xd5, 0xfe, 0x1a, + 0x62, 0x94, 0x20, 0x63, 0x6f, 0x5d, 0xd6, 0xb6, 0xca, 0x30, 0xdb, 0x2a, 0x13, 0xd9, 0xdb, 0x04, + 0xbd, 0x0c, 0x43, 0xbb, 0xae, 0xdf, 0x2a, 0x8f, 0x30, 0x5a, 0x4f, 0xd1, 0x39, 0xbf, 0xe1, 0xfa, + 0xad, 0xa3, 0xc3, 0xca, 0xac, 0xd1, 0x1d, 0x5a, 0x88, 0x19, 0xaa, 0xfd, 0x27, 0x16, 0x54, 0x18, + 0x6c, 0xd5, 0xf5, 0x48, 0x9d, 0x84, 0x91, 0x1b, 0xc5, 0xc4, 0x8f, 0x8d, 0x01, 0xbd, 0x02, 0x10, + 0x91, 0x66, 0x48, 0x62, 0x6d, 0x48, 0xd5, 0xc2, 0x68, 0x28, 0x08, 0xd6, 0xb0, 0x28, 0x43, 0x88, + 0x76, 0x9c, 0x90, 0xad, 0x2f, 0x31, 0xb0, 0x8a, 0x21, 0x34, 0x24, 0x00, 0x27, 0x38, 0x06, 0x43, + 0x28, 0xf6, 0x63, 0x08, 0xe8, 0x8b, 0x30, 0x9d, 0x34, 0x16, 0xb5, 0x9d, 0xa6, 0x1c, 0x40, 0xb6, + 0x65, 0x1a, 0x26, 0x08, 0xa7, 0x71, 0xed, 0x7f, 0x68, 0x89, 0xc5, 0x43, 0xbf, 0xfa, 0x13, 0xfe, + 0xad, 0xf6, 0x2f, 0x5a, 0x30, 0xba, 0xe4, 0xfa, 0x2d, 0xd7, 0xdf, 0x46, 0x5f, 0x85, 0x31, 0x7a, + 0x36, 0xb5, 0x9c, 0xd8, 0x11, 0x7c, 0xef, 0xb3, 0xda, 0xde, 0x52, 0x47, 0xc5, 0x7c, 0x7b, 0x77, + 0x9b, 0x16, 0x44, 0xf3, 0x14, 0x9b, 0xee, 0xb6, 0x5b, 0x9b, 0xef, 0x91, 0x66, 0xbc, 0x46, 0x62, + 0x27, 0xf9, 0x9c, 0xa4, 0x0c, 0x2b, 0xaa, 0xe8, 0x06, 0x8c, 0xc4, 0x4e, 0xb8, 0x4d, 0x62, 0xc1, + 0x00, 0x33, 0x19, 0x15, 0xaf, 0x89, 0xe9, 0x8e, 0x24, 0x7e, 0x93, 0x24, 0xc7, 0xc2, 0x06, 0xab, + 0x8a, 0x05, 0x09, 0xfb, 0x77, 0x2c, 0x38, 0xbf, 0xdc, 0xa8, 0xe5, 0xac, 0xab, 0x4b, 0x30, 0xd2, + 0x0a, 0xdd, 0x7d, 0x12, 0x8a, 0x71, 0x56, 0x54, 0xaa, 0xac, 0x14, 0x0b, 0x28, 0xba, 0x0a, 0x13, + 0xfc, 0x40, 0xba, 0xee, 0xf8, 0x2d, 0x4f, 0x0e, 0xf1, 0x59, 0x81, 0x3d, 0x71, 0x47, 0x83, 0x61, + 0x03, 0xf3, 0x98, 0x8b, 0xea, 0x52, 0x6a, 0x33, 0xe6, 0x1c, 0x76, 0x76, 0x13, 0x26, 0x96, 0x9d, + 0xb6, 0xb3, 0xe9, 0x7a, 0x6e, 0xec, 0x92, 0x08, 0x3d, 0x0b, 0x45, 0xa7, 0xd5, 0x62, 0xbc, 0xae, + 0xb4, 0x74, 0xee, 0xc1, 0x61, 0xa5, 0xb8, 0xd8, 0xa2, 0x9b, 0x0e, 0x14, 0xd6, 0x01, 0xa6, 0x18, + 0xe8, 0x79, 0x18, 0x6a, 0x85, 0x41, 0xbb, 0x5c, 0x60, 0x98, 0x8f, 0xd1, 0xfd, 0x59, 0x0d, 0x83, + 0x76, 0x0a, 0x95, 0xe1, 0xd8, 0xbf, 0x5a, 0x80, 0x27, 0x97, 0x49, 0x7b, 0x67, 0xb5, 0x91, 0x33, + 0x7a, 0x97, 0x61, 0x6c, 0x2f, 0xf0, 0xdd, 0x38, 0x08, 0x23, 0xd1, 0x34, 0x63, 0x0b, 0x6b, 0xa2, + 0x0c, 0x2b, 0x28, 0xba, 0x08, 0x43, 0xed, 0x84, 0xa5, 0x4f, 0xc8, 0xe3, 0x80, 0x31, 0x73, 0x06, + 0xa1, 0x18, 0x9d, 0x88, 0x84, 0x82, 0x9d, 0x29, 0x8c, 0xdb, 0x11, 0x09, 0x31, 0x83, 0x24, 0xfb, + 0x82, 0xee, 0x18, 0x31, 0x3e, 0xa9, 0x7d, 0x41, 0x21, 0x58, 0xc3, 0x42, 0x75, 0x28, 0xf1, 0x7f, + 0x98, 0x6c, 0x31, 0xce, 0x95, 0xb3, 0x9a, 0x1a, 0x12, 0x49, 0xac, 0xa6, 0x49, 0xb6, 0x71, 0x64, + 0x21, 0x4e, 0x88, 0x18, 0xf3, 0x39, 0xd2, 0x77, 0xe3, 0xfc, 0x72, 0x01, 0x10, 0x1f, 0xc2, 0xbf, + 0x60, 0x03, 0x77, 0xbb, 0x7b, 0xe0, 0x32, 0x8f, 0xd0, 0x9b, 0x41, 0xd3, 0xf1, 0xd2, 0x7b, 0xf1, + 0xa4, 0x46, 0xef, 0x87, 0x2d, 0x40, 0xcb, 0xae, 0xdf, 0x22, 0xe1, 0x29, 0xc8, 0x8f, 0xc7, 0xe3, + 0x88, 0x37, 0x61, 0x6a, 0xd9, 0x73, 0x89, 0x1f, 0xd7, 0xea, 0xcb, 0x81, 0xbf, 0xe5, 0x6e, 0xa3, + 0xcf, 0xc3, 0x14, 0x15, 0xa7, 0x83, 0x4e, 0xdc, 0x20, 0xcd, 0xc0, 0x67, 0x92, 0x07, 0x15, 0x42, + 0xd1, 0x83, 0xc3, 0xca, 0xd4, 0x86, 0x01, 0xc1, 0x29, 0x4c, 0xfb, 0xf7, 0xe8, 0x87, 0x06, 0x7b, + 0xed, 0xc0, 0x27, 0x7e, 0xbc, 0x1c, 0xf8, 0x2d, 0x2e, 0xa1, 0x7e, 0x1e, 0x86, 0x62, 0xda, 0x71, + 0xfe, 0x91, 0x97, 0xe4, 0xd4, 0xd2, 0xee, 0x1e, 0x1d, 0x56, 0x1e, 0xeb, 0xae, 0xc1, 0x3e, 0x88, + 0xd5, 0x41, 0xdf, 0x06, 0x23, 0x51, 0xec, 0xc4, 0x9d, 0x48, 0x7c, 0xf6, 0xd3, 0xf2, 0xb3, 0x1b, + 0xac, 0xf4, 0xe8, 0xb0, 0x32, 0xad, 0xaa, 0xf1, 0x22, 0x2c, 0x2a, 0xa0, 0xe7, 0x60, 0x74, 0x8f, + 0x44, 0x91, 0xb3, 0x2d, 0x85, 0x8b, 0x69, 0x51, 0x77, 0x74, 0x8d, 0x17, 0x63, 0x09, 0x47, 0xcf, + 0xc0, 0x30, 0x09, 0xc3, 0x20, 0x14, 0xab, 0x6a, 0x52, 0x20, 0x0e, 0xaf, 0xd0, 0x42, 0xcc, 0x61, + 0xf6, 0x7f, 0xb0, 0x60, 0x5a, 0xf5, 0x95, 0xb7, 0x75, 0x0a, 0xa7, 0xc8, 0x3b, 0x00, 0x4d, 0xf9, + 0x81, 0x11, 0xe3, 0x77, 0xe3, 0x57, 0x2e, 0x65, 0x2d, 0xe1, 0xee, 0x61, 0x4c, 0x28, 0xab, 0xa2, + 0x08, 0x6b, 0xd4, 0xec, 0x7f, 0x69, 0xc1, 0x99, 0xd4, 0x17, 0xdd, 0x74, 0xa3, 0x18, 0xbd, 0xdb, + 0xf5, 0x55, 0xf3, 0x83, 0x7d, 0x15, 0xad, 0xcd, 0xbe, 0x49, 0xad, 0x39, 0x59, 0xa2, 0x7d, 0xd1, + 0x75, 0x18, 0x76, 0x63, 0xb2, 0x27, 0x3f, 0xe6, 0x99, 0x9e, 0x1f, 0xc3, 0x7b, 0x95, 0xcc, 0x48, + 0x8d, 0xd6, 0xc4, 0x9c, 0x80, 0xfd, 0x3f, 0x2d, 0x28, 0xf1, 0x65, 0xbb, 0xe6, 0xb4, 0x4f, 0x61, + 0x2e, 0x6a, 0x30, 0xc4, 0xa8, 0xf3, 0x8e, 0x3f, 0x9b, 0xdd, 0x71, 0xd1, 0x9d, 0x79, 0x2a, 0x22, + 0x72, 0x51, 0x5c, 0x31, 0x33, 0x5a, 0x84, 0x19, 0x89, 0xb9, 0xd7, 0xa1, 0xa4, 0x10, 0xd0, 0x0c, + 0x14, 0x77, 0x09, 0xbf, 0x7e, 0x95, 0x30, 0xfd, 0x89, 0xce, 0xc2, 0xf0, 0xbe, 0xe3, 0x75, 0xc4, + 0x66, 0xc7, 0xfc, 0xcf, 0xe7, 0x0b, 0x57, 0x2d, 0xfb, 0x97, 0xd8, 0x1e, 0x13, 0x8d, 0xac, 0xf8, + 0xfb, 0x82, 0x99, 0x7c, 0x00, 0x67, 0xbd, 0x0c, 0x1e, 0x26, 0x06, 0x62, 0x70, 0x9e, 0xf7, 0xa4, + 0xe8, 0xeb, 0xd9, 0x2c, 0x28, 0xce, 0x6c, 0x83, 0x1e, 0x03, 0x41, 0x9b, 0xae, 0x28, 0xc7, 0x63, + 0xfd, 0x15, 0x62, 0xf5, 0x2d, 0x51, 0x86, 0x15, 0x94, 0x32, 0x88, 0xb3, 0xaa, 0xf3, 0x37, 0xc8, + 0x41, 0x83, 0x78, 0xa4, 0x19, 0x07, 0xe1, 0xc7, 0xda, 0xfd, 0xa7, 0xf8, 0xe8, 0x73, 0xfe, 0x32, + 0x2e, 0x08, 0x14, 0x6f, 0x90, 0x03, 0x3e, 0x15, 0xfa, 0xd7, 0x15, 0x7b, 0x7e, 0xdd, 0xcf, 0x58, + 0x30, 0xa9, 0xbe, 0xee, 0x14, 0x36, 0xd2, 0x92, 0xb9, 0x91, 0x9e, 0xea, 0xb9, 0x1e, 0x73, 0xb6, + 0xd0, 0x9f, 0x33, 0x16, 0x20, 0x70, 0xea, 0x61, 0x40, 0x87, 0x86, 0xf2, 0xec, 0x8f, 0x73, 0x42, + 0x06, 0xf9, 0xae, 0x1b, 0xe4, 0x60, 0x23, 0xa0, 0xe2, 0x43, 0xf6, 0x77, 0x19, 0xb3, 0x36, 0xd4, + 0x73, 0xd6, 0x7e, 0xae, 0x00, 0xe7, 0xd4, 0x08, 0x18, 0x07, 0xf4, 0x5f, 0xf4, 0x31, 0x78, 0x19, + 0xc6, 0x5b, 0x64, 0xcb, 0xe9, 0x78, 0xb1, 0xba, 0x61, 0x0f, 0x73, 0x2d, 0x4b, 0x35, 0x29, 0xc6, + 0x3a, 0xce, 0x31, 0x86, 0xed, 0x27, 0xc6, 0x19, 0xef, 0x8d, 0x1d, 0xba, 0x82, 0xa9, 0xf4, 0xa6, + 0xe9, 0x49, 0x26, 0x74, 0x3d, 0x89, 0xd0, 0x89, 0x3c, 0x03, 0xc3, 0xee, 0x1e, 0x3d, 0x8b, 0x0b, + 0xe6, 0x11, 0x5b, 0xa3, 0x85, 0x98, 0xc3, 0xd0, 0x67, 0x60, 0xb4, 0x19, 0xec, 0xed, 0x39, 0x7e, + 0xab, 0x5c, 0x64, 0xf2, 0xe4, 0x38, 0x3d, 0xae, 0x97, 0x79, 0x11, 0x96, 0x30, 0xf4, 0x24, 0x0c, + 0x39, 0xe1, 0x76, 0x54, 0x1e, 0x62, 0x38, 0x63, 0xb4, 0xa5, 0xc5, 0x70, 0x3b, 0xc2, 0xac, 0x94, + 0xca, 0x89, 0xf7, 0x82, 0x70, 0xd7, 0xf5, 0xb7, 0xab, 0x6e, 0xc8, 0x84, 0x3e, 0x4d, 0x4e, 0xbc, + 0xab, 0x20, 0x58, 0xc3, 0x42, 0xab, 0x30, 0xdc, 0x0e, 0xc2, 0x38, 0x2a, 0x8f, 0xb0, 0xe1, 0x7e, + 0x3a, 0x67, 0x2b, 0xf1, 0xaf, 0xad, 0x07, 0x61, 0x9c, 0x7c, 0x00, 0xfd, 0x17, 0x61, 0x5e, 0x1d, + 0x7d, 0x1b, 0x14, 0x89, 0xbf, 0x5f, 0x1e, 0x65, 0x54, 0xe6, 0xb2, 0xa8, 0xac, 0xf8, 0xfb, 0x77, + 0x9c, 0x30, 0xe1, 0x33, 0x2b, 0xfe, 0x3e, 0xa6, 0x75, 0xd0, 0x97, 0xa1, 0x24, 0x75, 0xac, 0x51, + 0x79, 0x2c, 0x7f, 0x89, 0x61, 0x81, 0x84, 0xc9, 0xfb, 0x1d, 0x37, 0x24, 0x7b, 0xc4, 0x8f, 0xa3, + 0xe4, 0x96, 0x2c, 0xa1, 0x11, 0x4e, 0xa8, 0xa1, 0x2f, 0xcb, 0x6b, 0xdf, 0x5a, 0xd0, 0xf1, 0xe3, + 0xa8, 0x5c, 0x62, 0xdd, 0xcb, 0x54, 0xc8, 0xdd, 0x49, 0xf0, 0xd2, 0xf7, 0x42, 0x5e, 0x19, 0x1b, + 0xa4, 0x10, 0x86, 0x49, 0xcf, 0xdd, 0x27, 0x3e, 0x89, 0xa2, 0x7a, 0x18, 0x6c, 0x92, 0x32, 0xb0, + 0x9e, 0x9f, 0xcf, 0xd6, 0x53, 0x05, 0x9b, 0x64, 0x69, 0xf6, 0xc1, 0x61, 0x65, 0xf2, 0xa6, 0x5e, + 0x07, 0x9b, 0x24, 0xd0, 0x6d, 0x98, 0xa2, 0x02, 0xaa, 0x9b, 0x10, 0x1d, 0xef, 0x47, 0x94, 0x49, + 0xa7, 0xd8, 0xa8, 0x84, 0x53, 0x44, 0xd0, 0x5b, 0x50, 0xf2, 0xdc, 0x2d, 0xd2, 0x3c, 0x68, 0x7a, + 0xa4, 0x3c, 0xc1, 0x28, 0x66, 0x6e, 0xab, 0x9b, 0x12, 0x89, 0x5f, 0x00, 0xd4, 0x5f, 0x9c, 0x54, + 0x47, 0x77, 0xe0, 0xb1, 0x98, 0x84, 0x7b, 0xae, 0xef, 0xd0, 0xed, 0x20, 0xe4, 0x49, 0xa6, 0xed, + 0x9b, 0x64, 0xeb, 0xed, 0x82, 0x18, 0xba, 0xc7, 0x36, 0x32, 0xb1, 0x70, 0x4e, 0x6d, 0x74, 0x0b, + 0xa6, 0xd9, 0x4e, 0xa8, 0x77, 0x3c, 0xaf, 0x1e, 0x78, 0x6e, 0xf3, 0xa0, 0x3c, 0xc5, 0x08, 0x7e, + 0x46, 0xaa, 0xf3, 0x6a, 0x26, 0x98, 0xde, 0x78, 0x93, 0x7f, 0x38, 0x5d, 0x1b, 0x6d, 0x32, 0xf5, + 0x4e, 0x27, 0x74, 0xe3, 0x03, 0xba, 0x7e, 0xc9, 0xfd, 0xb8, 0x3c, 0xdd, 0xf3, 0xfe, 0xa8, 0xa3, + 0x2a, 0x1d, 0x90, 0x5e, 0x88, 0xd3, 0x04, 0xe9, 0xd6, 0x8e, 0xe2, 0x96, 0xeb, 0x97, 0x67, 0x18, + 0xc7, 0x50, 0x3b, 0xa3, 0x41, 0x0b, 0x31, 0x87, 0x31, 0xd5, 0x0e, 0xfd, 0x71, 0x8b, 0x72, 0xd0, + 0x59, 0x86, 0x98, 0xa8, 0x76, 0x24, 0x00, 0x27, 0x38, 0xf4, 0x58, 0x8e, 0xe3, 0x83, 0x32, 0x62, + 0xa8, 0x6a, 0xbb, 0x6c, 0x6c, 0x7c, 0x19, 0xd3, 0x72, 0x74, 0x13, 0x46, 0x89, 0xbf, 0xbf, 0x1a, + 0x06, 0x7b, 0xe5, 0x33, 0xf9, 0x7b, 0x76, 0x85, 0xa3, 0x70, 0x86, 0x9e, 0x5c, 0x00, 0x44, 0x31, + 0x96, 0x24, 0xd0, 0x7d, 0x28, 0x67, 0xcc, 0x08, 0x9f, 0x80, 0xb3, 0x6c, 0x02, 0xbe, 0x20, 0xea, + 0x96, 0x37, 0x72, 0xf0, 0x8e, 0x7a, 0xc0, 0x70, 0x2e, 0x75, 0xf4, 0x5d, 0x30, 0xc9, 0x37, 0x14, + 0xd7, 0x0b, 0x47, 0xe5, 0x73, 0xec, 0x6b, 0x2e, 0xe6, 0x6f, 0x4e, 0x8e, 0xb8, 0x74, 0x4e, 0x74, + 0x68, 0x52, 0x2f, 0x8d, 0xb0, 0x49, 0xcd, 0xde, 0x84, 0x29, 0xc5, 0xb7, 0xd8, 0xd2, 0x41, 0x15, + 0x18, 0xa6, 0x0c, 0x59, 0xde, 0xd8, 0x4b, 0x74, 0xa6, 0x98, 0x3e, 0x0f, 0xf3, 0x72, 0x36, 0x53, + 0xee, 0x07, 0x64, 0xe9, 0x20, 0x26, 0xfc, 0xd6, 0x55, 0xd4, 0x66, 0x4a, 0x02, 0x70, 0x82, 0x63, + 0xff, 0x5f, 0x2e, 0xf7, 0x24, 0xcc, 0x71, 0x80, 0xe3, 0xe0, 0x45, 0x18, 0xdb, 0x09, 0xa2, 0x98, + 0x62, 0xb3, 0x36, 0x86, 0x13, 0x49, 0xe7, 0xba, 0x28, 0xc7, 0x0a, 0x03, 0xbd, 0x01, 0x93, 0x4d, + 0xbd, 0x01, 0x71, 0x96, 0xa9, 0x21, 0x30, 0x5a, 0xc7, 0x26, 0x2e, 0xba, 0x0a, 0x63, 0xec, 0x55, + 0xa7, 0x19, 0x78, 0xe2, 0x7e, 0x27, 0x0f, 0xe4, 0xb1, 0xba, 0x28, 0x3f, 0xd2, 0x7e, 0x63, 0x85, + 0x4d, 0xef, 0xdc, 0xb4, 0x0b, 0xb5, 0xba, 0x38, 0x45, 0xd4, 0x9d, 0xfb, 0x3a, 0x2b, 0xc5, 0x02, + 0x6a, 0xff, 0x8d, 0x82, 0x36, 0xca, 0xf4, 0xc6, 0x42, 0x50, 0x1d, 0x46, 0xef, 0x39, 0x6e, 0xec, + 0xfa, 0xdb, 0x42, 0x5c, 0x78, 0xae, 0xe7, 0x91, 0xc2, 0x2a, 0xdd, 0xe5, 0x15, 0xf8, 0xa1, 0x27, + 0xfe, 0x60, 0x49, 0x86, 0x52, 0x0c, 0x3b, 0xbe, 0x4f, 0x29, 0x16, 0x06, 0xa5, 0x88, 0x79, 0x05, + 0x4e, 0x51, 0xfc, 0xc1, 0x92, 0x0c, 0x7a, 0x17, 0x40, 0x2e, 0x4b, 0xd2, 0x12, 0xaf, 0x29, 0x2f, + 0xf6, 0x27, 0xba, 0xa1, 0xea, 0x2c, 0x4d, 0xd1, 0x23, 0x35, 0xf9, 0x8f, 0x35, 0x7a, 0x76, 0xcc, + 0xc4, 0xaa, 0xee, 0xce, 0xa0, 0xef, 0xa4, 0x9c, 0xc0, 0x09, 0x63, 0xd2, 0x5a, 0x8c, 0xc5, 0xe0, + 0x3c, 0x3f, 0x98, 0x54, 0xbc, 0xe1, 0xee, 0x11, 0x9d, 0x6b, 0x08, 0x22, 0x38, 0xa1, 0x67, 0xff, + 0x42, 0x11, 0xca, 0x79, 0xdd, 0xa5, 0x8b, 0x8e, 0xdc, 0x77, 0xe3, 0x65, 0x2a, 0x0d, 0x59, 0xe6, + 0xa2, 0x5b, 0x11, 0xe5, 0x58, 0x61, 0xd0, 0xd9, 0x8f, 0xdc, 0x6d, 0x79, 0xa9, 0x19, 0x4e, 0x66, + 0xbf, 0xc1, 0x4a, 0xb1, 0x80, 0x52, 0xbc, 0x90, 0x38, 0x91, 0x78, 0xae, 0xd3, 0x56, 0x09, 0x66, + 0xa5, 0x58, 0x40, 0x75, 0x7d, 0xc4, 0x50, 0x1f, 0x7d, 0x84, 0x31, 0x44, 0xc3, 0x27, 0x3b, 0x44, + 0xe8, 0x2b, 0x00, 0x5b, 0xae, 0xef, 0x46, 0x3b, 0x8c, 0xfa, 0xc8, 0xb1, 0xa9, 0x2b, 0x59, 0x6a, + 0x55, 0x51, 0xc1, 0x1a, 0x45, 0xf4, 0x1a, 0x8c, 0xab, 0x0d, 0x58, 0xab, 0x96, 0x47, 0xcd, 0xb7, + 0xa0, 0x84, 0x1b, 0x55, 0xb1, 0x8e, 0x67, 0xbf, 0x97, 0x5e, 0x2f, 0x62, 0x07, 0x68, 0xe3, 0x6b, + 0x0d, 0x3a, 0xbe, 0x85, 0xde, 0xe3, 0x6b, 0xff, 0x5a, 0x11, 0xa6, 0x8d, 0xc6, 0x3a, 0xd1, 0x00, + 0x3c, 0xeb, 0x1a, 0x3d, 0xe7, 0x9c, 0x98, 0x88, 0xfd, 0x67, 0xf7, 0xdf, 0x2a, 0xfa, 0x59, 0x48, + 0x77, 0x00, 0xaf, 0x8f, 0xbe, 0x02, 0x25, 0xcf, 0x89, 0x98, 0x6e, 0x83, 0x88, 0x7d, 0x37, 0x08, + 0xb1, 0xe4, 0x1e, 0xe1, 0x44, 0xb1, 0x76, 0xd4, 0x70, 0xda, 0x09, 0x49, 0x7a, 0x20, 0x53, 0xd9, + 0x47, 0xbe, 0x07, 0xab, 0x4e, 0x50, 0x01, 0xe9, 0x00, 0x73, 0x18, 0xba, 0x0a, 0x13, 0x21, 0x61, + 0xab, 0x62, 0x99, 0x8a, 0x72, 0x6c, 0x99, 0x0d, 0x27, 0x32, 0x1f, 0xd6, 0x60, 0xd8, 0xc0, 0x4c, + 0x44, 0xf9, 0x91, 0x1e, 0xa2, 0xfc, 0x73, 0x30, 0xca, 0x7e, 0xa8, 0x15, 0xa0, 0x66, 0xa3, 0xc6, + 0x8b, 0xb1, 0x84, 0xa7, 0x17, 0xcc, 0xd8, 0x80, 0x0b, 0xe6, 0x79, 0x98, 0xaa, 0x3a, 0x64, 0x2f, + 0xf0, 0x57, 0xfc, 0x56, 0x3b, 0x70, 0xfd, 0x18, 0x95, 0x61, 0x88, 0x9d, 0x0e, 0x7c, 0x6f, 0x0f, + 0x51, 0x0a, 0x78, 0x88, 0x0a, 0xe6, 0xf6, 0x6f, 0x17, 0x60, 0xb2, 0x4a, 0x3c, 0x12, 0x13, 0x7e, + 0x95, 0x89, 0xd0, 0x2a, 0xa0, 0xed, 0xd0, 0x69, 0x92, 0x3a, 0x09, 0xdd, 0xa0, 0xa5, 0xeb, 0x3a, + 0x8b, 0xec, 0x3d, 0x01, 0x5d, 0xeb, 0x82, 0xe2, 0x8c, 0x1a, 0xe8, 0x1d, 0x98, 0x6c, 0x87, 0xc4, + 0x50, 0xd1, 0x59, 0x79, 0xd2, 0x48, 0x5d, 0x47, 0xe4, 0x82, 0xb0, 0x51, 0x84, 0x4d, 0x52, 0xe8, + 0x3b, 0x60, 0x26, 0x08, 0xdb, 0x3b, 0x8e, 0x5f, 0x25, 0x6d, 0xe2, 0xb7, 0xa8, 0xa4, 0x2f, 0x54, + 0x10, 0x67, 0x1f, 0x1c, 0x56, 0x66, 0x6e, 0xa5, 0x60, 0xb8, 0x0b, 0x1b, 0xbd, 0x03, 0xb3, 0xed, + 0x30, 0x68, 0x3b, 0xdb, 0x6c, 0xa1, 0x08, 0x81, 0x86, 0x73, 0x9f, 0x17, 0x1f, 0x1c, 0x56, 0x66, + 0xeb, 0x69, 0xe0, 0xd1, 0x61, 0xe5, 0x0c, 0x1b, 0x28, 0x5a, 0x92, 0x00, 0x71, 0x37, 0x19, 0x7b, + 0x1b, 0xce, 0x55, 0x83, 0x7b, 0xfe, 0x3d, 0x27, 0x6c, 0x2d, 0xd6, 0x6b, 0x9a, 0xee, 0x60, 0x5d, + 0xde, 0x5d, 0xf9, 0x9b, 0x75, 0xe6, 0x39, 0xa5, 0xd5, 0xe4, 0xf2, 0xcb, 0xaa, 0xeb, 0x91, 0x1c, + 0x1d, 0xc5, 0xdf, 0x2e, 0x18, 0x2d, 0x25, 0xf8, 0xea, 0x59, 0xc1, 0xca, 0x7d, 0x56, 0x78, 0x1b, + 0xc6, 0xb6, 0x5c, 0xe2, 0xb5, 0x30, 0xd9, 0x12, 0x33, 0xf3, 0x6c, 0xfe, 0x33, 0xdc, 0x2a, 0xc5, + 0x94, 0x3a, 0x29, 0x7e, 0xf3, 0x5d, 0x15, 0x95, 0xb1, 0x22, 0x83, 0x76, 0x61, 0x46, 0x5e, 0xad, + 0x24, 0x54, 0x6c, 0xe2, 0xe7, 0x7a, 0xdd, 0xd7, 0x4c, 0xe2, 0x6c, 0x02, 0x71, 0x8a, 0x0c, 0xee, + 0x22, 0x4c, 0xaf, 0xba, 0x7b, 0xf4, 0xb8, 0x1a, 0x62, 0x4b, 0x9a, 0x5d, 0x75, 0xd9, 0xad, 0x9d, + 0x95, 0xda, 0x3f, 0x66, 0xc1, 0xe3, 0x5d, 0x23, 0x23, 0xb4, 0x17, 0x27, 0x3c, 0x0b, 0x69, 0x6d, + 0x42, 0xa1, 0xbf, 0x36, 0xc1, 0xfe, 0x47, 0x16, 0x9c, 0x5d, 0xd9, 0x6b, 0xc7, 0x07, 0x55, 0xd7, + 0x7c, 0xfa, 0x78, 0x1d, 0x46, 0xf6, 0x48, 0xcb, 0xed, 0xec, 0x89, 0x99, 0xab, 0x48, 0x96, 0xbe, + 0xc6, 0x4a, 0x8f, 0x0e, 0x2b, 0x93, 0x8d, 0x38, 0x08, 0x9d, 0x6d, 0xc2, 0x0b, 0xb0, 0x40, 0x67, + 0x07, 0xa3, 0xfb, 0x01, 0xb9, 0xe9, 0xee, 0xb9, 0xf2, 0x59, 0xb5, 0xa7, 0x46, 0x6d, 0x5e, 0x0e, + 0xe8, 0xfc, 0xdb, 0x1d, 0xc7, 0x8f, 0xdd, 0xf8, 0x40, 0xbc, 0xea, 0x48, 0x22, 0x38, 0xa1, 0x67, + 0x7f, 0xc3, 0x82, 0x69, 0xc9, 0x4b, 0x16, 0x5b, 0xad, 0x90, 0x44, 0x11, 0x9a, 0x83, 0x82, 0xdb, + 0x16, 0xbd, 0x04, 0xd1, 0xcb, 0x42, 0xad, 0x8e, 0x0b, 0x6e, 0x1b, 0xd5, 0xa1, 0xc4, 0x5f, 0x67, + 0x93, 0xc5, 0x35, 0xd0, 0x1b, 0x2f, 0xeb, 0xc1, 0x86, 0xac, 0x89, 0x13, 0x22, 0x52, 0x2a, 0x66, + 0xe7, 0x50, 0xd1, 0x7c, 0x12, 0xba, 0x2e, 0xca, 0xb1, 0xc2, 0x40, 0x97, 0x61, 0xcc, 0x0f, 0x5a, + 0xfc, 0xb1, 0x9c, 0xef, 0x69, 0xb6, 0x64, 0xd7, 0x45, 0x19, 0x56, 0x50, 0xfb, 0x07, 0x2d, 0x98, + 0x90, 0x5f, 0x36, 0xa0, 0x80, 0x4e, 0xb7, 0x56, 0x22, 0x9c, 0x27, 0x5b, 0x8b, 0x0a, 0xd8, 0x0c, + 0x62, 0xc8, 0xd5, 0xc5, 0xe3, 0xc8, 0xd5, 0xf6, 0x8f, 0x16, 0x60, 0x4a, 0x76, 0xa7, 0xd1, 0xd9, + 0x8c, 0x48, 0x8c, 0x36, 0xa0, 0xe4, 0xf0, 0x21, 0x27, 0x72, 0xc5, 0x3e, 0x93, 0x7d, 0xa1, 0x33, + 0xe6, 0x27, 0x11, 0x75, 0x16, 0x65, 0x6d, 0x9c, 0x10, 0x42, 0x1e, 0xcc, 0xfa, 0x41, 0xcc, 0x8e, + 0x3d, 0x05, 0xef, 0xf5, 0xec, 0x90, 0xa6, 0x7e, 0x5e, 0x50, 0x9f, 0x5d, 0x4f, 0x53, 0xc1, 0xdd, + 0x84, 0xd1, 0x8a, 0x54, 0x22, 0x15, 0xf3, 0xaf, 0x70, 0xfa, 0x2c, 0x64, 0xeb, 0x90, 0xec, 0x5f, + 0xb1, 0xa0, 0x24, 0xd1, 0x4e, 0xe3, 0x85, 0x69, 0x0d, 0x46, 0x23, 0x36, 0x09, 0x72, 0x68, 0xec, + 0x5e, 0x1d, 0xe7, 0xf3, 0x95, 0x9c, 0xe6, 0xfc, 0x7f, 0x84, 0x25, 0x0d, 0xa6, 0x05, 0x57, 0xdd, + 0xff, 0x84, 0x68, 0xc1, 0x55, 0x7f, 0x72, 0x4e, 0x98, 0xff, 0xca, 0xfa, 0xac, 0xa9, 0x0a, 0xa8, + 0xd0, 0xd9, 0x0e, 0xc9, 0x96, 0x7b, 0x3f, 0x2d, 0x74, 0xd6, 0x59, 0x29, 0x16, 0x50, 0xf4, 0x2e, + 0x4c, 0x34, 0xa5, 0xf2, 0x38, 0x61, 0x03, 0x97, 0x7a, 0xaa, 0xe2, 0xd5, 0xab, 0x0d, 0x37, 0xa4, + 0x5b, 0xd6, 0xea, 0x63, 0x83, 0x9a, 0xf9, 0xee, 0x5f, 0xec, 0xf7, 0xee, 0x9f, 0xd0, 0xcd, 0x7d, + 0xb9, 0xb6, 0x7f, 0xdc, 0x82, 0x11, 0xae, 0x82, 0x1c, 0x4c, 0x67, 0xab, 0xbd, 0x42, 0x25, 0x63, + 0x77, 0x87, 0x16, 0x8a, 0x47, 0x29, 0xb4, 0x06, 0x25, 0xf6, 0x83, 0xa9, 0x62, 0x8a, 0xf9, 0x16, + 0x84, 0xbc, 0x55, 0xbd, 0x83, 0x77, 0x64, 0x35, 0x9c, 0x50, 0xb0, 0x7f, 0xa8, 0x48, 0x59, 0x55, + 0x82, 0x6a, 0x9c, 0xe0, 0xd6, 0xa3, 0x3b, 0xc1, 0x0b, 0x8f, 0xea, 0x04, 0xdf, 0x86, 0xe9, 0xa6, + 0xf6, 0xe4, 0x95, 0xcc, 0xe4, 0xe5, 0x9e, 0x8b, 0x44, 0x7b, 0x1d, 0xe3, 0x6a, 0xb8, 0x65, 0x93, + 0x08, 0x4e, 0x53, 0x45, 0xdf, 0x09, 0x13, 0x7c, 0x9e, 0x45, 0x2b, 0x43, 0xac, 0x95, 0xcf, 0xe4, + 0xaf, 0x17, 0xbd, 0x09, 0xb6, 0x12, 0x1b, 0x5a, 0x75, 0x6c, 0x10, 0xb3, 0x7f, 0x61, 0x0c, 0x86, + 0x57, 0xf6, 0x89, 0x1f, 0x9f, 0x02, 0x43, 0x6a, 0xc2, 0x94, 0xeb, 0xef, 0x07, 0xde, 0x3e, 0x69, + 0x71, 0xf8, 0x71, 0x0e, 0xd7, 0xc7, 0x04, 0xe9, 0xa9, 0x9a, 0x41, 0x02, 0xa7, 0x48, 0x3e, 0x8a, + 0x5b, 0xfb, 0x35, 0x18, 0xe1, 0x73, 0x2f, 0xae, 0xec, 0x99, 0x0a, 0x76, 0x36, 0x88, 0x62, 0x17, + 0x24, 0x1a, 0x05, 0xae, 0xd1, 0x17, 0xd5, 0xd1, 0x7b, 0x30, 0xb5, 0xe5, 0x86, 0x51, 0x4c, 0xaf, + 0xdb, 0x51, 0xec, 0xec, 0xb5, 0x1f, 0xe2, 0x96, 0xae, 0xc6, 0x61, 0xd5, 0xa0, 0x84, 0x53, 0x94, + 0xd1, 0x36, 0x4c, 0xd2, 0x8b, 0x63, 0xd2, 0xd4, 0xe8, 0xb1, 0x9b, 0x52, 0x6a, 0xb8, 0x9b, 0x3a, + 0x21, 0x6c, 0xd2, 0xa5, 0xcc, 0xa4, 0xc9, 0x2e, 0x9a, 0x63, 0x4c, 0xa2, 0x50, 0xcc, 0x84, 0xdf, + 0x30, 0x39, 0x8c, 0xf2, 0x24, 0x66, 0x2a, 0x52, 0x32, 0x79, 0x92, 0x66, 0x10, 0xf2, 0x55, 0x28, + 0x11, 0x3a, 0x84, 0x94, 0xb0, 0x78, 0x6c, 0x58, 0x18, 0xac, 0xaf, 0x6b, 0x6e, 0x33, 0x0c, 0x4c, + 0xfd, 0xc8, 0x8a, 0xa4, 0x84, 0x13, 0xa2, 0x68, 0x19, 0x46, 0x22, 0x12, 0xba, 0x24, 0x12, 0xcf, + 0x0e, 0x3d, 0xa6, 0x91, 0xa1, 0x71, 0x53, 0x53, 0xfe, 0x1b, 0x8b, 0xaa, 0x74, 0x79, 0x39, 0xec, + 0x36, 0xc4, 0x5e, 0x1a, 0xb4, 0xe5, 0xb5, 0xc8, 0x4a, 0xb1, 0x80, 0xa2, 0xb7, 0x60, 0x34, 0x24, + 0x1e, 0x53, 0xc0, 0x4d, 0x0e, 0xbe, 0xc8, 0xb9, 0x3e, 0x8f, 0xd7, 0xc3, 0x92, 0x00, 0xba, 0x01, + 0x28, 0x24, 0x54, 0x86, 0x70, 0xfd, 0x6d, 0x65, 0x40, 0x21, 0xde, 0x0f, 0x9e, 0x10, 0xed, 0x9f, + 0xc1, 0x09, 0x86, 0x1f, 0x87, 0x81, 0xe7, 0x91, 0x10, 0x67, 0x54, 0x43, 0xd7, 0x60, 0x56, 0x95, + 0xd6, 0xfc, 0x28, 0x76, 0xfc, 0x26, 0x61, 0x4f, 0x07, 0xa5, 0x44, 0x2a, 0xc2, 0x69, 0x04, 0xdc, + 0x5d, 0xc7, 0xfe, 0x3a, 0x15, 0x67, 0xe8, 0x68, 0x9d, 0x82, 0x2c, 0xf0, 0xa6, 0x29, 0x0b, 0x9c, + 0xcf, 0x9d, 0xb9, 0x1c, 0x39, 0xe0, 0x81, 0x05, 0xe3, 0xda, 0xcc, 0x26, 0x6b, 0xd6, 0xea, 0xb1, + 0x66, 0x3b, 0x30, 0x43, 0x57, 0xfa, 0xad, 0x4d, 0xe6, 0x75, 0xd1, 0x62, 0x0b, 0xb3, 0xf0, 0x70, + 0x0b, 0xb3, 0x2c, 0x1a, 0x98, 0xb9, 0x99, 0x22, 0x88, 0xbb, 0x9a, 0x40, 0xaf, 0x4b, 0x6d, 0x54, + 0xd1, 0x30, 0x8c, 0xe2, 0x9a, 0xa6, 0xa3, 0xc3, 0xca, 0x8c, 0xf6, 0x21, 0xba, 0xf6, 0xc9, 0xfe, + 0xaa, 0xfc, 0x46, 0xce, 0x6c, 0x16, 0xa0, 0xd4, 0x54, 0x8b, 0xc5, 0x32, 0x6d, 0x6e, 0xd5, 0x72, + 0xc0, 0x09, 0x0e, 0xdd, 0xa3, 0xf4, 0x0a, 0x92, 0xb6, 0xe5, 0xa3, 0x17, 0x14, 0xcc, 0x20, 0xf6, + 0x2b, 0x00, 0x2b, 0xf7, 0x49, 0x93, 0x2f, 0x75, 0xfd, 0x51, 0xd7, 0xca, 0x7f, 0xd4, 0xb5, 0xff, + 0xa3, 0x05, 0x53, 0xab, 0xcb, 0xc6, 0x35, 0x71, 0x1e, 0x80, 0xdf, 0x8d, 0xee, 0xde, 0x5d, 0x97, + 0xef, 0x15, 0x5c, 0xe5, 0xac, 0x4a, 0xb1, 0x86, 0x81, 0xce, 0x43, 0xd1, 0xeb, 0xf8, 0xe2, 0xca, + 0x32, 0xfa, 0xe0, 0xb0, 0x52, 0xbc, 0xd9, 0xf1, 0x31, 0x2d, 0xd3, 0xcc, 0xe7, 0x8a, 0x03, 0x9b, + 0xcf, 0xf5, 0xf5, 0xa6, 0x40, 0x15, 0x18, 0xbe, 0x77, 0xcf, 0x6d, 0x45, 0xe5, 0xe1, 0xe4, 0x2d, + 0xe5, 0xee, 0xdd, 0x5a, 0x35, 0xc2, 0xbc, 0xdc, 0xfe, 0x5a, 0x11, 0xe6, 0x56, 0x3d, 0x72, 0xff, + 0x23, 0xda, 0xed, 0x0e, 0x6a, 0xfc, 0x77, 0x3c, 0x79, 0xf1, 0xb8, 0x96, 0x8e, 0xfd, 0xc7, 0x63, + 0x0b, 0x46, 0xb9, 0x81, 0x00, 0x1f, 0x91, 0xf1, 0x2b, 0x6f, 0x64, 0xb5, 0x9e, 0x3f, 0x20, 0xf3, + 0x42, 0x3b, 0xc7, 0xed, 0xa6, 0xd4, 0x49, 0x2b, 0x4a, 0xb1, 0x24, 0x3e, 0xf7, 0x79, 0x98, 0xd0, + 0x31, 0x8f, 0x65, 0x40, 0xf5, 0x97, 0x8a, 0x30, 0x43, 0x7b, 0xf0, 0x48, 0x27, 0xe2, 0x76, 0xf7, + 0x44, 0x9c, 0xb4, 0xdd, 0x69, 0xff, 0xd9, 0x78, 0x37, 0x3d, 0x1b, 0x2f, 0xe7, 0xcd, 0xc6, 0x69, + 0xcf, 0xc1, 0x5f, 0xb6, 0xe0, 0xcc, 0xaa, 0x17, 0x34, 0x77, 0x53, 0x26, 0xb1, 0xaf, 0xc1, 0x38, + 0xe5, 0xe3, 0x91, 0xe1, 0x34, 0x60, 0xb8, 0x91, 0x08, 0x10, 0xd6, 0xf1, 0xb4, 0x6a, 0xb7, 0x6f, + 0xd7, 0xaa, 0x59, 0xde, 0x27, 0x02, 0x84, 0x75, 0x3c, 0xfb, 0x37, 0x2d, 0x78, 0xea, 0xda, 0xf2, + 0x4a, 0xb2, 0x14, 0xbb, 0x1c, 0x60, 0xe8, 0x2d, 0xb0, 0xa5, 0x75, 0x25, 0xb9, 0x05, 0x56, 0x59, + 0x2f, 0x04, 0xf4, 0x93, 0xe2, 0xdc, 0xf5, 0x53, 0x16, 0x9c, 0xb9, 0xe6, 0xc6, 0xf4, 0x58, 0x4e, + 0xbb, 0x62, 0xd0, 0x73, 0x39, 0x72, 0xe3, 0x20, 0x3c, 0x48, 0xbb, 0x62, 0x60, 0x05, 0xc1, 0x1a, + 0x16, 0x6f, 0x79, 0xdf, 0x8d, 0x68, 0x4f, 0x0b, 0xa6, 0x2a, 0x0a, 0x8b, 0x72, 0xac, 0x30, 0xe8, + 0x87, 0xb5, 0xdc, 0x90, 0x5d, 0x25, 0x0e, 0x04, 0x87, 0x55, 0x1f, 0x56, 0x95, 0x00, 0x9c, 0xe0, + 0xd8, 0x3f, 0x66, 0xc1, 0xb9, 0x6b, 0x5e, 0x27, 0x8a, 0x49, 0xb8, 0x15, 0x19, 0x9d, 0x7d, 0x05, + 0x4a, 0x44, 0x5e, 0xd7, 0x45, 0x5f, 0x95, 0x80, 0xa9, 0xee, 0xf1, 0xdc, 0x0f, 0x44, 0xe1, 0x0d, + 0x60, 0x5f, 0x7e, 0x3c, 0xbb, 0xe8, 0x9f, 0x2d, 0xc0, 0xe4, 0xf5, 0x8d, 0x8d, 0xfa, 0x35, 0x12, + 0x8b, 0x53, 0xac, 0xbf, 0xaa, 0x19, 0x6b, 0x1a, 0xb3, 0x5e, 0x97, 0xa2, 0x4e, 0xec, 0x7a, 0xf3, + 0xdc, 0xf1, 0x70, 0xbe, 0xe6, 0xc7, 0xb7, 0xc2, 0x46, 0x1c, 0xba, 0xfe, 0x76, 0xa6, 0x8e, 0x4d, + 0x9e, 0xb5, 0xc5, 0xbc, 0xb3, 0x16, 0xbd, 0x02, 0x23, 0xcc, 0xf3, 0x51, 0x5e, 0x4f, 0x9e, 0x50, + 0x77, 0x0a, 0x56, 0x7a, 0x74, 0x58, 0x29, 0xdd, 0xc6, 0x35, 0xfe, 0x07, 0x0b, 0x54, 0x74, 0x1b, + 0xc6, 0x77, 0xe2, 0xb8, 0x7d, 0x9d, 0x38, 0x2d, 0x12, 0x4a, 0xee, 0x70, 0x21, 0x8b, 0x3b, 0xd0, + 0x41, 0xe0, 0x68, 0xc9, 0x86, 0x4a, 0xca, 0x22, 0xac, 0xd3, 0xb1, 0x1b, 0x00, 0x09, 0xec, 0x84, + 0xf4, 0x0b, 0xf6, 0x1f, 0x5a, 0x30, 0xca, 0x9d, 0x50, 0x42, 0xf4, 0x05, 0x18, 0x22, 0xf7, 0x49, + 0x53, 0x48, 0x8e, 0x99, 0x1d, 0x4e, 0x04, 0x0f, 0xae, 0x2d, 0xa7, 0xff, 0x31, 0xab, 0x85, 0xae, + 0xc3, 0x28, 0xed, 0xed, 0x35, 0xe5, 0x91, 0xf3, 0x74, 0xde, 0x17, 0xab, 0x69, 0xe7, 0xb2, 0x8a, + 0x28, 0xc2, 0xb2, 0x3a, 0xd3, 0xfc, 0x36, 0xdb, 0x0d, 0xca, 0xc0, 0xe2, 0x5e, 0xe7, 0xec, 0xc6, + 0x72, 0x9d, 0x23, 0x09, 0x6a, 0x5c, 0xf3, 0x2b, 0x0b, 0x71, 0x42, 0xc4, 0xde, 0x80, 0x12, 0x9d, + 0xd4, 0x45, 0xcf, 0x75, 0x7a, 0x2b, 0x9d, 0x5f, 0x80, 0x92, 0x54, 0x00, 0x47, 0xc2, 0xfd, 0x85, + 0x51, 0x95, 0xfa, 0xe1, 0x08, 0x27, 0x70, 0x7b, 0x0b, 0xce, 0x32, 0x6b, 0x0a, 0x27, 0xde, 0x31, + 0xf6, 0x58, 0xff, 0xc5, 0xfc, 0xa2, 0xb8, 0x88, 0xf1, 0x99, 0x29, 0x6b, 0xf6, 0xfa, 0x13, 0x92, + 0x62, 0x72, 0x29, 0xb3, 0xff, 0x78, 0x08, 0x9e, 0xa8, 0x35, 0xf2, 0xfd, 0x93, 0xae, 0xc2, 0x04, + 0x17, 0xd3, 0xe8, 0xd2, 0x76, 0x3c, 0xd1, 0xae, 0x7a, 0x6b, 0xdc, 0xd0, 0x60, 0xd8, 0xc0, 0x44, + 0x4f, 0x41, 0xd1, 0x7d, 0xdf, 0x4f, 0x1b, 0xe7, 0xd6, 0xde, 0x5e, 0xc7, 0xb4, 0x9c, 0x82, 0xa9, + 0xc4, 0xc7, 0x59, 0xa9, 0x02, 0x2b, 0xa9, 0xef, 0x4d, 0x98, 0x72, 0xa3, 0x66, 0xe4, 0xd6, 0x7c, + 0xca, 0x67, 0x12, 0xdf, 0xb6, 0x44, 0x49, 0x40, 0x3b, 0xad, 0xa0, 0x38, 0x85, 0xad, 0xf1, 0xf5, + 0xe1, 0x81, 0xa5, 0xc6, 0xbe, 0xfe, 0x20, 0x54, 0x20, 0x6e, 0xb3, 0xaf, 0x8b, 0x98, 0xa1, 0xa0, + 0x10, 0x88, 0xf9, 0x07, 0x47, 0x58, 0xc2, 0xe8, 0x0d, 0xac, 0xb9, 0xe3, 0xb4, 0x17, 0x3b, 0xf1, + 0x4e, 0xd5, 0x8d, 0x9a, 0xc1, 0x3e, 0x09, 0x0f, 0xd8, 0xe5, 0x79, 0x2c, 0xb9, 0x81, 0x29, 0xc0, + 0xf2, 0xf5, 0xc5, 0x3a, 0xc5, 0xc4, 0xdd, 0x75, 0x4c, 0xa9, 0x10, 0x4e, 0x42, 0x2a, 0x5c, 0x84, + 0x69, 0xd9, 0x4c, 0x83, 0x44, 0xec, 0x8c, 0x18, 0x67, 0x1d, 0x53, 0x5e, 0xa7, 0xa2, 0x58, 0x75, + 0x2b, 0x8d, 0x8f, 0x5e, 0x87, 0x49, 0xd7, 0x77, 0x63, 0xd7, 0x89, 0x83, 0x90, 0x9d, 0xb0, 0xfc, + 0x9e, 0xcc, 0x1e, 0x45, 0x6b, 0x3a, 0x00, 0x9b, 0x78, 0xf6, 0x1f, 0x0d, 0xc1, 0x2c, 0x9b, 0xb6, + 0x6f, 0xad, 0xb0, 0x4f, 0xcc, 0x0a, 0xbb, 0xdd, 0xbd, 0xc2, 0x4e, 0x42, 0xdc, 0xfd, 0x38, 0x97, + 0xd9, 0x7b, 0x50, 0x52, 0xf6, 0xd5, 0xd2, 0x45, 0xc0, 0xca, 0x71, 0x11, 0xe8, 0x2f, 0x7d, 0xc8, + 0x67, 0xdc, 0x62, 0xe6, 0x33, 0xee, 0xdf, 0xb1, 0x20, 0x31, 0x33, 0x45, 0xd7, 0xa1, 0xd4, 0x0e, + 0x98, 0x29, 0x47, 0x28, 0xed, 0xa3, 0x9e, 0xc8, 0x3c, 0xa8, 0xf8, 0xa1, 0xc8, 0xc7, 0xaf, 0x2e, + 0x6b, 0xe0, 0xa4, 0x32, 0x5a, 0x82, 0xd1, 0x76, 0x48, 0x1a, 0x31, 0x73, 0x94, 0xec, 0x4b, 0x87, + 0xaf, 0x11, 0x8e, 0x8f, 0x65, 0x45, 0xfb, 0xe7, 0x2c, 0x00, 0xfe, 0x52, 0xea, 0xf8, 0xdb, 0xe4, + 0x14, 0xb4, 0xbf, 0x55, 0x18, 0x8a, 0xda, 0xa4, 0xd9, 0xcb, 0xc8, 0x26, 0xe9, 0x4f, 0xa3, 0x4d, + 0x9a, 0xc9, 0x80, 0xd3, 0x7f, 0x98, 0xd5, 0xb6, 0xbf, 0x0f, 0x60, 0x2a, 0x41, 0xab, 0xc5, 0x64, + 0x0f, 0xbd, 0x64, 0xb8, 0xa1, 0x9d, 0x4f, 0xb9, 0xa1, 0x95, 0x18, 0xb6, 0xa6, 0x68, 0x7c, 0x0f, + 0x8a, 0x7b, 0xce, 0x7d, 0xa1, 0x49, 0x7a, 0xa1, 0x77, 0x37, 0x28, 0xfd, 0xf9, 0x35, 0xe7, 0x3e, + 0xbf, 0x33, 0xbd, 0x20, 0x17, 0xc8, 0x9a, 0x73, 0xff, 0x88, 0x9b, 0xd2, 0x30, 0x26, 0x75, 0xd3, + 0x8d, 0xe2, 0x0f, 0xff, 0x73, 0xf2, 0x9f, 0x2d, 0x3b, 0xda, 0x08, 0x6b, 0xcb, 0xf5, 0xc5, 0xbb, + 0xe1, 0x40, 0x6d, 0xb9, 0x7e, 0xba, 0x2d, 0xd7, 0x1f, 0xa0, 0x2d, 0xd7, 0x47, 0x1f, 0xc0, 0xa8, + 0x78, 0xa3, 0x67, 0xf6, 0xf3, 0xa6, 0x96, 0x2a, 0xaf, 0x3d, 0xf1, 0xc4, 0xcf, 0xdb, 0x5c, 0x90, + 0x77, 0x42, 0x51, 0xda, 0xb7, 0x5d, 0xd9, 0x20, 0xfa, 0x5b, 0x16, 0x4c, 0x89, 0xdf, 0x98, 0xbc, + 0xdf, 0x21, 0x51, 0x2c, 0x64, 0xcf, 0xcf, 0x0d, 0xde, 0x07, 0x51, 0x91, 0x77, 0xe5, 0x73, 0x92, + 0xcd, 0x9a, 0xc0, 0xbe, 0x3d, 0x4a, 0xf5, 0x02, 0xfd, 0x13, 0x0b, 0xce, 0xee, 0x39, 0xf7, 0x79, + 0x8b, 0xbc, 0x0c, 0x3b, 0xb1, 0x1b, 0x08, 0x7f, 0x80, 0x2f, 0x0c, 0x36, 0xfd, 0x5d, 0xd5, 0x79, + 0x27, 0xa5, 0xe9, 0xf0, 0xd9, 0x2c, 0x94, 0xbe, 0x5d, 0xcd, 0xec, 0xd7, 0xdc, 0x16, 0x8c, 0xc9, + 0xf5, 0x96, 0x71, 0xf3, 0xae, 0xea, 0x82, 0xf5, 0xb1, 0x4d, 0x24, 0xb4, 0x9b, 0x3a, 0x6b, 0x47, + 0xac, 0xb5, 0x47, 0xda, 0xce, 0x7b, 0x30, 0xa1, 0xaf, 0xb1, 0x47, 0xda, 0xd6, 0xfb, 0x70, 0x26, + 0x63, 0x2d, 0x3d, 0xd2, 0x26, 0xef, 0xc1, 0xf9, 0xdc, 0xf5, 0xf1, 0x28, 0x1b, 0xb6, 0x7f, 0xd6, + 0xd2, 0xf9, 0xe0, 0x29, 0xa8, 0xe0, 0x97, 0x4d, 0x15, 0xfc, 0x85, 0xde, 0x3b, 0x27, 0x47, 0x0f, + 0xff, 0xae, 0xde, 0x69, 0xca, 0xd5, 0xd1, 0x5b, 0x30, 0xe2, 0xd1, 0x12, 0x69, 0x1c, 0x62, 0xf7, + 0xdf, 0x91, 0x89, 0x2c, 0xc5, 0xca, 0x23, 0x2c, 0x28, 0xd8, 0xbf, 0x68, 0xc1, 0xd0, 0x29, 0x8c, + 0x04, 0x36, 0x47, 0xe2, 0xa5, 0x5c, 0xd2, 0x22, 0x82, 0xd1, 0x3c, 0x76, 0xee, 0xad, 0xc8, 0x28, + 0x4d, 0x39, 0x03, 0xf3, 0x7f, 0x0a, 0x30, 0x4e, 0x9b, 0x92, 0x56, 0x8c, 0x6f, 0xc0, 0xa4, 0xe7, + 0x6c, 0x12, 0x4f, 0xbe, 0xe3, 0xa6, 0x15, 0x26, 0x37, 0x75, 0x20, 0x36, 0x71, 0x69, 0xe5, 0x2d, + 0xfd, 0x49, 0x5b, 0xc8, 0x2f, 0xaa, 0xb2, 0xf1, 0xde, 0x8d, 0x4d, 0x5c, 0x7a, 0x77, 0xbf, 0xe7, + 0xc4, 0xcd, 0x1d, 0xa1, 0x4c, 0x51, 0xdd, 0xbd, 0x4b, 0x0b, 0x31, 0x87, 0x51, 0x01, 0x4e, 0xae, + 0xce, 0x3b, 0xf4, 0x66, 0x18, 0xf8, 0x42, 0x3c, 0x56, 0x02, 0x1c, 0x36, 0xc1, 0x38, 0x8d, 0x9f, + 0xe1, 0x8f, 0x3e, 0xcc, 0x6c, 0x34, 0x07, 0xf0, 0x47, 0x47, 0x75, 0x38, 0xeb, 0xfa, 0x4d, 0xaf, + 0xd3, 0x22, 0xb7, 0x7d, 0x2e, 0xdd, 0x79, 0xee, 0x07, 0xa4, 0x25, 0x04, 0x68, 0x65, 0x4e, 0x5b, + 0xcb, 0xc0, 0xc1, 0x99, 0x35, 0xed, 0xff, 0x0f, 0xce, 0xdc, 0x0c, 0x9c, 0xd6, 0x92, 0xe3, 0x39, + 0x7e, 0x93, 0x84, 0x35, 0x7f, 0xbb, 0xaf, 0x95, 0x98, 0x6e, 0xd3, 0x55, 0xe8, 0x67, 0xd3, 0x65, + 0xef, 0x00, 0xd2, 0x1b, 0x10, 0xb6, 0xc9, 0x18, 0x46, 0x5d, 0xde, 0x94, 0x58, 0xfe, 0xcf, 0x66, + 0x4b, 0xd7, 0x5d, 0x3d, 0xd3, 0xac, 0x6e, 0x79, 0x01, 0x96, 0x84, 0xec, 0xab, 0x90, 0xe9, 0x8f, + 0xd8, 0x5f, 0x6d, 0x63, 0xbf, 0x06, 0xb3, 0xac, 0xe6, 0xf1, 0x54, 0x0a, 0xf6, 0x5f, 0xb3, 0x60, + 0x7a, 0x3d, 0x15, 0x41, 0xe2, 0x12, 0x7b, 0x6b, 0xcd, 0xd0, 0xbb, 0x37, 0x58, 0x29, 0x16, 0xd0, + 0x13, 0xd7, 0xef, 0xfd, 0xb9, 0x05, 0x25, 0x15, 0xc4, 0xe6, 0x14, 0x84, 0xda, 0x65, 0x43, 0xa8, + 0xcd, 0xd4, 0x3b, 0xa9, 0xee, 0xe4, 0xc9, 0xb4, 0xe8, 0x86, 0x8a, 0x85, 0xd0, 0x43, 0xe5, 0x94, + 0x90, 0xe1, 0x9e, 0xf3, 0x53, 0x66, 0xc0, 0x04, 0x19, 0x1d, 0x81, 0x99, 0x69, 0x29, 0xdc, 0x4f, + 0x88, 0x99, 0x96, 0xea, 0x4f, 0x0e, 0xf7, 0xab, 0x6b, 0x5d, 0x66, 0xa7, 0xc2, 0xb7, 0x33, 0x57, + 0x06, 0xb6, 0x37, 0x55, 0x08, 0x92, 0x8a, 0x70, 0x4d, 0x10, 0xa5, 0x47, 0x8c, 0x91, 0x89, 0x7f, + 0x3c, 0xe0, 0x50, 0x52, 0xc5, 0xbe, 0x0e, 0xd3, 0xa9, 0x01, 0x43, 0xaf, 0xc1, 0x70, 0x7b, 0xc7, + 0x89, 0x48, 0xca, 0x34, 0x75, 0xb8, 0x4e, 0x0b, 0x8f, 0x0e, 0x2b, 0x53, 0xaa, 0x02, 0x2b, 0xc1, + 0x1c, 0xdb, 0xfe, 0x1f, 0x16, 0x0c, 0xad, 0x07, 0xad, 0xd3, 0x58, 0x4c, 0x6f, 0x1a, 0x8b, 0xe9, + 0xc9, 0xbc, 0x70, 0x6d, 0xb9, 0xeb, 0x68, 0x35, 0xb5, 0x8e, 0x2e, 0xe4, 0x52, 0xe8, 0xbd, 0x84, + 0xf6, 0x60, 0x9c, 0x05, 0x81, 0x13, 0xa6, 0xb2, 0xaf, 0x18, 0xf7, 0xab, 0x4a, 0xea, 0x7e, 0x35, + 0xad, 0xa1, 0x6a, 0xb7, 0xac, 0xe7, 0x60, 0x54, 0x98, 0x6b, 0xa6, 0x9d, 0x36, 0x04, 0x2e, 0x96, + 0x70, 0xfb, 0xc7, 0x8b, 0x60, 0x04, 0x9d, 0x43, 0xbf, 0x62, 0xc1, 0x7c, 0xc8, 0xbd, 0x60, 0x5b, + 0xd5, 0x4e, 0xe8, 0xfa, 0xdb, 0x8d, 0xe6, 0x0e, 0x69, 0x75, 0x3c, 0xd7, 0xdf, 0xae, 0x6d, 0xfb, + 0x81, 0x2a, 0x5e, 0xb9, 0x4f, 0x9a, 0x1d, 0xf6, 0xe6, 0xd2, 0x27, 0xc2, 0x9d, 0x32, 0x87, 0xba, + 0xf2, 0xe0, 0xb0, 0x32, 0x8f, 0x8f, 0x45, 0x1b, 0x1f, 0xb3, 0x2f, 0xe8, 0x37, 0x2d, 0x58, 0xe0, + 0xb1, 0xd8, 0x06, 0xef, 0x7f, 0x8f, 0xdb, 0x68, 0x5d, 0x92, 0x4a, 0x88, 0x6c, 0x90, 0x70, 0x6f, + 0xe9, 0x75, 0x31, 0xa0, 0x0b, 0xf5, 0xe3, 0xb5, 0x85, 0x8f, 0xdb, 0x39, 0xfb, 0xdf, 0x14, 0x61, + 0x92, 0x8e, 0x62, 0x12, 0xf9, 0xe5, 0x35, 0x63, 0x49, 0x3c, 0x9d, 0x5a, 0x12, 0xb3, 0x06, 0xf2, + 0xc9, 0x04, 0x7d, 0x89, 0x60, 0xd6, 0x73, 0xa2, 0xf8, 0x3a, 0x71, 0xc2, 0x78, 0x93, 0x38, 0xdc, + 0x4c, 0xa8, 0x78, 0x6c, 0x93, 0x26, 0xa5, 0xfe, 0xba, 0x99, 0x26, 0x86, 0xbb, 0xe9, 0xa3, 0x7d, + 0x40, 0xcc, 0xd6, 0x29, 0x74, 0xfc, 0x88, 0x7f, 0x8b, 0x2b, 0xde, 0x63, 0x8e, 0xd7, 0xea, 0x9c, + 0x68, 0x15, 0xdd, 0xec, 0xa2, 0x86, 0x33, 0x5a, 0xd0, 0x6c, 0xd8, 0x86, 0x07, 0xb5, 0x61, 0x1b, + 0xe9, 0xe3, 0x19, 0xb5, 0x07, 0x33, 0x62, 0x56, 0xb6, 0xdc, 0x6d, 0x71, 0x48, 0x7f, 0x39, 0x65, + 0xe3, 0x6a, 0x0d, 0x6e, 0xa8, 0xd4, 0xc7, 0xc0, 0xd5, 0xfe, 0x6e, 0x38, 0x43, 0x9b, 0x33, 0xfd, + 0x78, 0x22, 0x44, 0x60, 0x7a, 0xb7, 0xb3, 0x49, 0x3c, 0x12, 0xcb, 0x32, 0xd1, 0x68, 0xa6, 0xd8, + 0x6f, 0xd6, 0x4e, 0x64, 0xcb, 0x1b, 0x26, 0x09, 0x9c, 0xa6, 0x69, 0xff, 0xa4, 0x05, 0xcc, 0x5a, + 0xfe, 0x14, 0x8e, 0xbf, 0x2f, 0x9a, 0xc7, 0x5f, 0x39, 0x8f, 0x03, 0xe5, 0x9c, 0x7c, 0xaf, 0xf2, + 0x69, 0xa9, 0x87, 0xc1, 0xfd, 0x03, 0x29, 0xfb, 0xf7, 0x97, 0xb8, 0xfe, 0xb7, 0xc5, 0x37, 0xa4, + 0x0a, 0x0a, 0x80, 0xbe, 0x07, 0xc6, 0x9a, 0x4e, 0xdb, 0x69, 0xf2, 0x68, 0x9f, 0xb9, 0xda, 0x1f, + 0xa3, 0xd2, 0xfc, 0xb2, 0xa8, 0xc1, 0xb5, 0x19, 0x9f, 0x95, 0x5f, 0x29, 0x8b, 0xfb, 0x6a, 0x30, + 0x54, 0x93, 0x73, 0xbb, 0x30, 0x69, 0x10, 0x7b, 0xa4, 0x57, 0xdf, 0xef, 0xe1, 0xc7, 0x85, 0xba, + 0xb1, 0xec, 0xc1, 0xac, 0xaf, 0xfd, 0xa7, 0xcc, 0x51, 0x8a, 0xd3, 0x9f, 0xee, 0x77, 0x20, 0x30, + 0x4e, 0xaa, 0x79, 0x03, 0xa4, 0xc8, 0xe0, 0x6e, 0xca, 0xf6, 0xdf, 0xb3, 0xe0, 0x71, 0x1d, 0x51, + 0x8b, 0xd7, 0xd0, 0x4f, 0x9f, 0x5c, 0x85, 0xb1, 0xa0, 0x4d, 0x42, 0x27, 0xb9, 0x93, 0x5d, 0x96, + 0x83, 0x7e, 0x4b, 0x94, 0x1f, 0x1d, 0x56, 0xce, 0xea, 0xd4, 0x65, 0x39, 0x56, 0x35, 0x91, 0x0d, + 0x23, 0x6c, 0x30, 0x22, 0x11, 0x4b, 0x83, 0x99, 0x29, 0xb2, 0xa7, 0xd5, 0x08, 0x0b, 0x88, 0xfd, + 0x7d, 0x16, 0x5f, 0x58, 0x7a, 0xd7, 0xd1, 0xfb, 0x30, 0xb3, 0x47, 0xaf, 0x6f, 0x2b, 0xf7, 0xdb, + 0x21, 0x57, 0xa3, 0xcb, 0x71, 0x7a, 0xa1, 0xdf, 0x38, 0x69, 0x1f, 0x99, 0x18, 0xb3, 0xad, 0xa5, + 0x88, 0xe1, 0x2e, 0xf2, 0xf6, 0x9f, 0x16, 0xf8, 0x4e, 0x64, 0x52, 0xdd, 0x73, 0x30, 0xda, 0x0e, + 0x5a, 0xcb, 0xb5, 0x2a, 0x16, 0x23, 0xa4, 0xd8, 0x55, 0x9d, 0x17, 0x63, 0x09, 0x47, 0x57, 0x00, + 0xc8, 0xfd, 0x98, 0x84, 0xbe, 0xe3, 0x29, 0xc3, 0x0f, 0x25, 0x3c, 0xad, 0x28, 0x08, 0xd6, 0xb0, + 0x68, 0x9d, 0x76, 0x18, 0xec, 0xbb, 0x2d, 0xe6, 0x6d, 0x58, 0x34, 0xeb, 0xd4, 0x15, 0x04, 0x6b, + 0x58, 0xf4, 0xaa, 0xdc, 0xf1, 0x23, 0x7e, 0x00, 0x3a, 0x9b, 0x22, 0xfc, 0xdc, 0x58, 0x72, 0x55, + 0xbe, 0xad, 0x03, 0xb1, 0x89, 0x8b, 0x16, 0x61, 0x24, 0x76, 0x98, 0x39, 0xc3, 0x70, 0xbe, 0x59, + 0xe2, 0x06, 0xc5, 0xd0, 0xc3, 0x3f, 0xd2, 0x0a, 0x58, 0x54, 0x44, 0xef, 0x48, 0x16, 0xcc, 0x59, + 0xb2, 0xb0, 0x07, 0xce, 0x5d, 0xb6, 0x3a, 0xfb, 0xd6, 0x79, 0xb0, 0xb0, 0x33, 0x36, 0x68, 0xd9, + 0xdf, 0x5b, 0x02, 0x48, 0xa4, 0x3d, 0xf4, 0x41, 0x17, 0x8b, 0x78, 0xb1, 0xb7, 0x7c, 0x78, 0x72, + 0xfc, 0x01, 0x7d, 0xbf, 0x05, 0xe3, 0x8e, 0xe7, 0x05, 0x4d, 0x27, 0x66, 0xa3, 0x5c, 0xe8, 0xcd, + 0xa2, 0x44, 0xfb, 0x8b, 0x49, 0x0d, 0xde, 0x85, 0x57, 0xa4, 0xa5, 0x82, 0x06, 0xe9, 0xdb, 0x0b, + 0xbd, 0x61, 0xf4, 0x59, 0x79, 0x09, 0xe0, 0xcb, 0x63, 0x2e, 0x7d, 0x09, 0x28, 0x31, 0x6e, 0xac, + 0xc9, 0xff, 0xe8, 0xb6, 0x11, 0xa7, 0x6d, 0x28, 0x3f, 0x24, 0x85, 0x21, 0xf4, 0xf4, 0x0b, 0xd1, + 0x86, 0xea, 0xba, 0x5f, 0xd4, 0x70, 0x7e, 0xdc, 0x16, 0x4d, 0xba, 0xee, 0xe3, 0x13, 0xf5, 0x1e, + 0x4c, 0xb7, 0xcc, 0xe3, 0x56, 0xac, 0xa6, 0x67, 0xf3, 0xe8, 0xa6, 0x4e, 0xe7, 0xe4, 0x80, 0x4d, + 0x01, 0x70, 0x9a, 0x30, 0xaa, 0x73, 0x0f, 0xb5, 0x9a, 0xbf, 0x15, 0x08, 0xbb, 0x72, 0x3b, 0x77, + 0x2e, 0x0f, 0xa2, 0x98, 0xec, 0x51, 0xcc, 0xe4, 0x1c, 0x5d, 0x17, 0x75, 0xb1, 0xa2, 0x82, 0xde, + 0x82, 0x11, 0xe6, 0x36, 0x1c, 0x95, 0xc7, 0xf2, 0xf5, 0x80, 0x66, 0xc4, 0x8b, 0x64, 0x53, 0xb1, + 0xbf, 0x11, 0x16, 0x14, 0xd0, 0x75, 0x19, 0x16, 0x27, 0xaa, 0xf9, 0xb7, 0x23, 0xc2, 0xc2, 0xe2, + 0x94, 0x96, 0x3e, 0x9d, 0x44, 0xbc, 0xe1, 0xe5, 0x99, 0x81, 0x9e, 0x8d, 0x9a, 0x54, 0x5e, 0x11, + 0xff, 0x65, 0xfc, 0xe8, 0x32, 0xe4, 0x77, 0xcf, 0x8c, 0x31, 0x9d, 0x0c, 0xe7, 0x1d, 0x93, 0x04, + 0x4e, 0xd3, 0x3c, 0xd5, 0xe3, 0x73, 0xce, 0x87, 0x99, 0xf4, 0xc6, 0x7a, 0xa4, 0xc7, 0xf5, 0x1f, + 0x0e, 0xc1, 0x94, 0xb9, 0x10, 0xd0, 0x02, 0x94, 0x04, 0x11, 0x15, 0x22, 0x53, 0xad, 0xed, 0x35, + 0x09, 0xc0, 0x09, 0x0e, 0x0b, 0x11, 0xca, 0xaa, 0x6b, 0x76, 0x80, 0x49, 0x88, 0x50, 0x05, 0xc1, + 0x1a, 0x16, 0x15, 0xa2, 0x37, 0x83, 0x20, 0x56, 0x47, 0x81, 0x5a, 0x2d, 0x4b, 0xac, 0x14, 0x0b, + 0x28, 0x3d, 0x02, 0x76, 0x49, 0xe8, 0x13, 0xcf, 0xd4, 0x64, 0xaa, 0x23, 0xe0, 0x86, 0x0e, 0xc4, + 0x26, 0x2e, 0x3d, 0xd2, 0x82, 0x88, 0x2d, 0x3f, 0x21, 0xaa, 0x27, 0x76, 0x95, 0x0d, 0xee, 0x36, + 0x2f, 0xe1, 0xe8, 0xcb, 0xf0, 0xb8, 0xf2, 0x72, 0xc7, 0x5c, 0x33, 0x2c, 0x5b, 0x1c, 0x31, 0x6e, + 0xd6, 0x8f, 0x2f, 0x67, 0xa3, 0xe1, 0xbc, 0xfa, 0xe8, 0x4d, 0x98, 0x12, 0x22, 0xb0, 0xa4, 0x38, + 0x6a, 0x1a, 0x2b, 0xdc, 0x30, 0xa0, 0x38, 0x85, 0x8d, 0xaa, 0x30, 0x43, 0x4b, 0x98, 0x14, 0x2a, + 0x29, 0x70, 0x6f, 0x7d, 0x75, 0xd6, 0xdf, 0x48, 0xc1, 0x71, 0x57, 0x0d, 0xb4, 0x08, 0xd3, 0x5c, + 0x46, 0xa1, 0x77, 0x4a, 0x36, 0x0f, 0xc2, 0xdd, 0x43, 0x6d, 0x84, 0x5b, 0x26, 0x18, 0xa7, 0xf1, + 0xd1, 0x55, 0x98, 0x70, 0xc2, 0xe6, 0x8e, 0x1b, 0x93, 0x66, 0xdc, 0x09, 0xb9, 0x1f, 0x88, 0x66, + 0xed, 0xb1, 0xa8, 0xc1, 0xb0, 0x81, 0x69, 0x7f, 0x00, 0x67, 0x32, 0x3c, 0xc5, 0xe8, 0xc2, 0x71, + 0xda, 0xae, 0xfc, 0xa6, 0x94, 0x85, 0xe4, 0x62, 0xbd, 0x26, 0xbf, 0x46, 0xc3, 0xa2, 0xab, 0x93, + 0xa9, 0xc4, 0xb5, 0x20, 0xef, 0x6a, 0x75, 0xae, 0x4a, 0x00, 0x4e, 0x70, 0xec, 0xdf, 0x00, 0xd0, + 0x14, 0x3a, 0x03, 0xd8, 0xc7, 0x5d, 0x85, 0x09, 0x99, 0x99, 0x40, 0x8b, 0x88, 0xad, 0x3e, 0xf3, + 0x9a, 0x06, 0xc3, 0x06, 0x26, 0xed, 0x9b, 0xaf, 0xe2, 0x79, 0xa7, 0xec, 0x31, 0x93, 0x68, 0xde, + 0x09, 0x0e, 0x7a, 0x11, 0xc6, 0x22, 0xe2, 0x6d, 0xdd, 0x74, 0xfd, 0x5d, 0xb1, 0xb0, 0x15, 0x17, + 0x6e, 0x88, 0x72, 0xac, 0x30, 0xd0, 0x12, 0x14, 0x3b, 0x6e, 0x4b, 0x2c, 0x65, 0x79, 0xe0, 0x17, + 0x6f, 0xd7, 0xaa, 0x47, 0x87, 0x95, 0xa7, 0xf3, 0x12, 0x2e, 0xd0, 0xab, 0x7d, 0x34, 0x4f, 0xb7, + 0x1f, 0xad, 0x9c, 0xf5, 0x36, 0x30, 0x72, 0xcc, 0xb7, 0x81, 0x2b, 0x00, 0xe2, 0xab, 0xe5, 0x5a, + 0x2e, 0x26, 0xb3, 0x76, 0x4d, 0x41, 0xb0, 0x86, 0x85, 0x22, 0x98, 0x6d, 0x86, 0xc4, 0x91, 0x77, + 0x68, 0xee, 0xf3, 0x34, 0xf6, 0xf0, 0x0a, 0x82, 0xe5, 0x34, 0x31, 0xdc, 0x4d, 0x1f, 0x05, 0x30, + 0xdb, 0x12, 0x41, 0x15, 0x92, 0x46, 0x4b, 0xc7, 0x77, 0xb4, 0x62, 0x06, 0x39, 0x69, 0x42, 0xb8, + 0x9b, 0x36, 0xfa, 0x0a, 0xcc, 0xc9, 0xc2, 0xee, 0x38, 0x16, 0x6c, 0xbb, 0x14, 0x97, 0x2e, 0x3c, + 0x38, 0xac, 0xcc, 0x55, 0x73, 0xb1, 0x70, 0x0f, 0x0a, 0x08, 0xc3, 0x08, 0x7b, 0x4b, 0x8a, 0xca, + 0xe3, 0xec, 0x9c, 0x7b, 0x3e, 0x5f, 0x19, 0x40, 0xd7, 0xfa, 0x3c, 0x7b, 0x87, 0x12, 0x26, 0xe5, + 0xc9, 0xb3, 0x1c, 0x2b, 0xc4, 0x82, 0x12, 0xda, 0x82, 0x71, 0xc7, 0xf7, 0x83, 0xd8, 0xe1, 0x22, + 0xd4, 0x44, 0xbe, 0xec, 0xa7, 0x11, 0x5e, 0x4c, 0x6a, 0x70, 0xea, 0xca, 0x4a, 0x55, 0x83, 0x60, + 0x9d, 0x30, 0xba, 0x07, 0xd3, 0xc1, 0x3d, 0xca, 0x1c, 0xa5, 0x96, 0x22, 0x2a, 0x4f, 0xb2, 0xb6, + 0x5e, 0x1d, 0x50, 0x4f, 0x6b, 0x54, 0xd6, 0xb8, 0x96, 0x49, 0x14, 0xa7, 0x5b, 0x41, 0xf3, 0x86, + 0xb6, 0x7a, 0x2a, 0x71, 0x67, 0x49, 0xb4, 0xd5, 0xba, 0x72, 0x9a, 0xc5, 0x45, 0xe1, 0x26, 0xd2, + 0x6c, 0xf7, 0x4f, 0xa7, 0xe2, 0xa2, 0x24, 0x20, 0xac, 0xe3, 0xa1, 0x1d, 0x98, 0x48, 0x9e, 0xac, + 0xc2, 0x88, 0x45, 0x65, 0x1b, 0xbf, 0x72, 0x65, 0xb0, 0x8f, 0xab, 0x69, 0x35, 0xf9, 0xcd, 0x41, + 0x2f, 0xc1, 0x06, 0xe5, 0xb9, 0x6f, 0x83, 0x71, 0x6d, 0x62, 0x8f, 0xe3, 0x01, 0x30, 0xf7, 0x26, + 0xcc, 0xa4, 0xa7, 0xee, 0x58, 0x1e, 0x04, 0xff, 0xab, 0x00, 0xd3, 0x19, 0x2f, 0x57, 0x2c, 0x69, + 0x43, 0x8a, 0xa1, 0x26, 0x39, 0x1a, 0x4c, 0xb6, 0x58, 0x18, 0x80, 0x2d, 0x4a, 0x1e, 0x5d, 0xcc, + 0xe5, 0xd1, 0x82, 0x15, 0x0e, 0x7d, 0x14, 0x56, 0x68, 0x9e, 0x3e, 0xc3, 0x03, 0x9d, 0x3e, 0x27, + 0xc0, 0x3e, 0x8d, 0x03, 0x6c, 0x74, 0x80, 0x03, 0xec, 0x87, 0x0a, 0x30, 0x93, 0xb6, 0xf0, 0x3d, + 0x85, 0xf7, 0x8e, 0xb7, 0x8c, 0xf7, 0x8e, 0xec, 0x14, 0x28, 0x69, 0xbb, 0xe3, 0xbc, 0xb7, 0x0f, + 0x9c, 0x7a, 0xfb, 0x78, 0x7e, 0x20, 0x6a, 0xbd, 0xdf, 0x41, 0xfe, 0x7e, 0x01, 0xce, 0xa5, 0xab, + 0x2c, 0x7b, 0x8e, 0xbb, 0x77, 0x0a, 0x63, 0x73, 0xcb, 0x18, 0x9b, 0x97, 0x06, 0xf9, 0x1a, 0xd6, + 0xb5, 0xdc, 0x01, 0xba, 0x9b, 0x1a, 0xa0, 0x85, 0xc1, 0x49, 0xf6, 0x1e, 0xa5, 0x6f, 0x14, 0xe1, + 0x42, 0x66, 0xbd, 0xe4, 0xb9, 0x60, 0xd5, 0x78, 0x2e, 0xb8, 0x92, 0x7a, 0x2e, 0xb0, 0x7b, 0xd7, + 0x3e, 0x99, 0xf7, 0x03, 0xe1, 0x0e, 0xcd, 0x22, 0x86, 0x3e, 0xe4, 0xdb, 0x81, 0xe1, 0x0e, 0xad, + 0x08, 0x61, 0x93, 0xee, 0x37, 0xd3, 0x9b, 0xc1, 0x6f, 0x58, 0x70, 0x3e, 0x73, 0x6e, 0x4e, 0x41, + 0xaf, 0xbe, 0x6e, 0xea, 0xd5, 0x9f, 0x1b, 0x78, 0xb5, 0xe6, 0x28, 0xda, 0xff, 0xa8, 0x98, 0xf3, + 0x2d, 0x4c, 0x33, 0x79, 0x0b, 0xc6, 0x9d, 0x66, 0x93, 0x44, 0xd1, 0x5a, 0xd0, 0x52, 0x11, 0x34, + 0x5f, 0x62, 0xd2, 0x46, 0x52, 0x7c, 0x74, 0x58, 0x99, 0x4b, 0x93, 0x48, 0xc0, 0x58, 0xa7, 0x60, + 0x06, 0xfd, 0x2d, 0x9c, 0x68, 0xd0, 0xdf, 0x2b, 0x00, 0xfb, 0x4a, 0x5f, 0x91, 0x56, 0x73, 0x6a, + 0x9a, 0x0c, 0x0d, 0x0b, 0x7d, 0x17, 0xbb, 0x05, 0x70, 0x63, 0x20, 0xbe, 0x14, 0x5f, 0x19, 0x70, + 0xae, 0x74, 0xc3, 0x22, 0x1e, 0x77, 0x43, 0xa9, 0x84, 0x15, 0x49, 0xf4, 0x1d, 0x30, 0x13, 0xf1, + 0xb0, 0x4e, 0xcb, 0x9e, 0x13, 0x31, 0x27, 0x2e, 0xb1, 0x0a, 0x59, 0x30, 0x8d, 0x46, 0x0a, 0x86, + 0xbb, 0xb0, 0xd1, 0xaa, 0xfc, 0x28, 0x16, 0x83, 0x8a, 0x2f, 0xcc, 0x4b, 0xc9, 0x07, 0x89, 0x94, + 0x51, 0x67, 0xd3, 0xc3, 0xcf, 0x06, 0x5e, 0xab, 0x69, 0xff, 0xd0, 0x10, 0x3c, 0xd1, 0x83, 0x89, + 0xa1, 0x45, 0xd3, 0x08, 0xe0, 0x85, 0xb4, 0xfe, 0x6f, 0x2e, 0xb3, 0xb2, 0xa1, 0x10, 0x4c, 0xad, + 0x95, 0xc2, 0x47, 0x5e, 0x2b, 0x3f, 0x60, 0x69, 0x9a, 0x59, 0x6e, 0x2a, 0xfc, 0xc5, 0x63, 0x32, + 0xe7, 0x13, 0x54, 0xd5, 0x6e, 0x65, 0xe8, 0x3b, 0xaf, 0x0c, 0xdc, 0x9d, 0x81, 0x15, 0xa0, 0xa7, + 0xfb, 0x64, 0xf4, 0xa1, 0x05, 0x4f, 0x67, 0xf6, 0xd7, 0x30, 0x5a, 0x5a, 0x80, 0x52, 0x93, 0x16, + 0x6a, 0x8e, 0xa1, 0x89, 0xc7, 0xbc, 0x04, 0xe0, 0x04, 0xc7, 0xb0, 0x4d, 0x2a, 0xf4, 0xb5, 0x4d, + 0xfa, 0xd7, 0x16, 0x74, 0x2d, 0xe0, 0x53, 0xe0, 0xa4, 0x35, 0x93, 0x93, 0x7e, 0x7a, 0x90, 0xb9, + 0xcc, 0x61, 0xa2, 0xbf, 0x37, 0x0d, 0x8f, 0xe5, 0x78, 0x82, 0xed, 0xc3, 0xec, 0x76, 0x93, 0x98, + 0x2e, 0xb7, 0xe2, 0x63, 0x32, 0xbd, 0x93, 0x7b, 0xfa, 0xe7, 0xf2, 0x0b, 0x71, 0x17, 0x0a, 0xee, + 0x6e, 0x02, 0x7d, 0x68, 0xc1, 0x59, 0xe7, 0x5e, 0xd4, 0x95, 0xd1, 0x51, 0xac, 0x99, 0x57, 0x33, + 0xf5, 0xb4, 0x7d, 0x32, 0x40, 0x32, 0xb7, 0xb8, 0xb3, 0x59, 0x58, 0x38, 0xb3, 0x2d, 0x84, 0x45, + 0xd0, 0x63, 0x2a, 0x6f, 0xf7, 0x70, 0x0a, 0xcf, 0x72, 0xd9, 0xe3, 0x3c, 0x55, 0x42, 0xb0, 0xa2, + 0x83, 0xee, 0x40, 0x69, 0x5b, 0xfa, 0xd1, 0x0a, 0x9e, 0x9d, 0x79, 0x08, 0x66, 0x3a, 0xdb, 0x72, + 0xdf, 0x11, 0x05, 0xc2, 0x09, 0x29, 0xf4, 0x26, 0x14, 0xfd, 0xad, 0xa8, 0x57, 0xb2, 0xa9, 0x94, + 0x2d, 0x1f, 0x0f, 0xb8, 0xb0, 0xbe, 0xda, 0xc0, 0xb4, 0x22, 0xba, 0x0e, 0xc5, 0x70, 0xb3, 0x25, + 0x9e, 0x16, 0x32, 0xe5, 0x52, 0xbc, 0x54, 0xcd, 0x5e, 0x24, 0x9c, 0x12, 0x5e, 0xaa, 0x62, 0x4a, + 0x02, 0xd5, 0x61, 0x98, 0x39, 0x4d, 0x89, 0x17, 0x84, 0x4c, 0x81, 0xb4, 0x87, 0xf3, 0x21, 0x8f, + 0xca, 0xc0, 0x10, 0x30, 0x27, 0x84, 0xde, 0x82, 0x91, 0x26, 0xcb, 0xc7, 0x24, 0x14, 0x3f, 0xd9, + 0xe1, 0xba, 0xba, 0x32, 0x36, 0xf1, 0x17, 0x54, 0x5e, 0x8e, 0x05, 0x05, 0xb4, 0x01, 0x23, 0x4d, + 0xd2, 0xde, 0xd9, 0x8a, 0x84, 0x3e, 0xe7, 0xb3, 0x99, 0xb4, 0x7a, 0xa4, 0x1f, 0x13, 0x54, 0x19, + 0x06, 0x16, 0xb4, 0xd0, 0xe7, 0xa1, 0xb0, 0xd5, 0x14, 0x9e, 0x54, 0x99, 0x6f, 0x08, 0x66, 0xa4, + 0x8c, 0xa5, 0x91, 0x07, 0x87, 0x95, 0xc2, 0xea, 0x32, 0x2e, 0x6c, 0x35, 0xd1, 0x3a, 0x8c, 0x6e, + 0x71, 0xdf, 0x7a, 0x11, 0xc0, 0xe6, 0xd9, 0x6c, 0xb7, 0xff, 0x2e, 0xf7, 0x7b, 0xee, 0x01, 0x24, + 0x00, 0x58, 0x12, 0x61, 0xf1, 0x82, 0x55, 0x8c, 0x00, 0x11, 0x38, 0x7f, 0xfe, 0x78, 0x71, 0x1d, + 0x84, 0x9a, 0x43, 0x51, 0xc1, 0x1a, 0x45, 0xf4, 0x55, 0x28, 0x39, 0x32, 0x83, 0xa0, 0x08, 0x82, + 0xf3, 0x4a, 0xe6, 0x76, 0xec, 0x9d, 0x5c, 0x91, 0xaf, 0x65, 0x85, 0x84, 0x13, 0xa2, 0x68, 0x17, + 0x26, 0xf7, 0xa3, 0xf6, 0x0e, 0x91, 0xdb, 0x97, 0xc5, 0xc4, 0xc9, 0x39, 0xae, 0xee, 0x08, 0x44, + 0x37, 0x8c, 0x3b, 0x8e, 0xd7, 0xc5, 0x71, 0x98, 0xe3, 0xd8, 0x1d, 0x9d, 0x18, 0x36, 0x69, 0xd3, + 0xe1, 0x7f, 0xbf, 0x13, 0x6c, 0x1e, 0xc4, 0x44, 0x44, 0xda, 0xcf, 0x1c, 0xfe, 0xb7, 0x39, 0x4a, + 0xf7, 0xf0, 0x0b, 0x00, 0x96, 0x44, 0xe8, 0x06, 0x77, 0x64, 0x76, 0x4e, 0xa1, 0xcb, 0x79, 0x2e, + 0x77, 0x78, 0xba, 0xfa, 0x9b, 0x0c, 0x0a, 0xe3, 0x8c, 0x09, 0x29, 0xc6, 0x11, 0xdb, 0x3b, 0x41, + 0x1c, 0xf8, 0x29, 0x6e, 0x3c, 0x9b, 0xcf, 0x11, 0xeb, 0x19, 0xf8, 0xdd, 0x1c, 0x31, 0x0b, 0x0b, + 0x67, 0xb6, 0x85, 0x5a, 0x30, 0xd5, 0x0e, 0xc2, 0xf8, 0x5e, 0x10, 0xca, 0xf5, 0x85, 0x7a, 0x5c, + 0xf2, 0x0d, 0x4c, 0xd1, 0x22, 0xb3, 0x03, 0x37, 0x21, 0x38, 0x45, 0x13, 0x7d, 0x09, 0x46, 0xa3, + 0xa6, 0xe3, 0x91, 0xda, 0xad, 0xf2, 0x99, 0xfc, 0xa3, 0xa6, 0xc1, 0x51, 0x72, 0x56, 0x17, 0x9b, + 0x1c, 0x81, 0x82, 0x25, 0x39, 0xb4, 0x0a, 0xc3, 0x2c, 0x7d, 0x0b, 0x4b, 0x12, 0x90, 0x13, 0x6c, + 0xad, 0xcb, 0x56, 0x9a, 0x73, 0x24, 0x56, 0x8c, 0x79, 0x75, 0xba, 0x07, 0x84, 0xac, 0x1b, 0x44, + 0xe5, 0x73, 0xf9, 0x7b, 0x40, 0x88, 0xc8, 0xb7, 0x1a, 0xbd, 0xf6, 0x80, 0x42, 0xc2, 0x09, 0x51, + 0xca, 0x8f, 0x29, 0x0f, 0x7d, 0x2c, 0x9f, 0x1f, 0xe7, 0x73, 0x50, 0xc6, 0x8f, 0x29, 0xff, 0xa4, + 0x24, 0xec, 0x0f, 0x47, 0xbb, 0xe5, 0x13, 0x76, 0x3b, 0xfa, 0x5e, 0xab, 0xcb, 0x74, 0xe0, 0x73, + 0x83, 0x2a, 0x6b, 0x4e, 0x50, 0x32, 0xfd, 0xd0, 0x82, 0xc7, 0xda, 0x99, 0x1f, 0x22, 0x0e, 0xfb, + 0xc1, 0x74, 0x3e, 0xfc, 0xd3, 0x55, 0x22, 0x8f, 0x6c, 0x38, 0xce, 0x69, 0x29, 0x2d, 0xfd, 0x17, + 0x3f, 0xb2, 0xf4, 0xbf, 0x06, 0x63, 0x4c, 0xa0, 0x4c, 0x22, 0xfb, 0x0d, 0x64, 0x80, 0xc7, 0xc4, + 0x86, 0x65, 0x51, 0x11, 0x2b, 0x12, 0xe8, 0x07, 0x2d, 0x78, 0x2a, 0xdd, 0x75, 0x4c, 0x18, 0x58, + 0x44, 0x89, 0xe6, 0x17, 0xb3, 0x55, 0xf1, 0xfd, 0x4f, 0xd5, 0x7b, 0x21, 0x1f, 0xf5, 0x43, 0xc0, + 0xbd, 0x1b, 0x43, 0xd5, 0x8c, 0x9b, 0xe1, 0x88, 0xf9, 0xb2, 0x38, 0xc0, 0xed, 0xf0, 0x55, 0x98, + 0xd8, 0x0b, 0x3a, 0xbe, 0xf4, 0x8e, 0x11, 0xbe, 0xcf, 0x4c, 0x8b, 0xbd, 0xa6, 0x95, 0x63, 0x03, + 0x2b, 0x75, 0xa7, 0x1c, 0x7b, 0xd8, 0x3b, 0xe5, 0xe9, 0xde, 0x54, 0xbe, 0x6e, 0x65, 0x88, 0xd8, + 0xfc, 0xee, 0xfa, 0x05, 0xf3, 0xee, 0x7a, 0x29, 0x7d, 0x77, 0xed, 0xd2, 0x55, 0x1a, 0xd7, 0xd6, + 0xc1, 0xa3, 0xe8, 0x0f, 0x1a, 0x42, 0xd1, 0xf6, 0xe0, 0x62, 0xbf, 0x83, 0x83, 0x19, 0x33, 0xb6, + 0xd4, 0x2b, 0x7f, 0x62, 0xcc, 0xd8, 0xaa, 0x55, 0x31, 0x83, 0x0c, 0x1a, 0x63, 0xc7, 0xfe, 0x6f, + 0x16, 0x14, 0xeb, 0x41, 0xeb, 0x14, 0x74, 0xaf, 0x5f, 0x34, 0x74, 0xaf, 0x4f, 0xe4, 0xe4, 0x21, + 0xcf, 0xd5, 0xb4, 0xae, 0xa4, 0x34, 0xad, 0x4f, 0xe5, 0x11, 0xe8, 0xad, 0x57, 0xfd, 0x89, 0x22, + 0xe8, 0x59, 0xd3, 0xd1, 0xbf, 0x7d, 0x18, 0xab, 0xf8, 0x62, 0xaf, 0x44, 0xea, 0x82, 0x32, 0xb3, + 0x81, 0x94, 0x0e, 0xb7, 0x7f, 0xc1, 0x8c, 0xe3, 0xef, 0x12, 0x77, 0x7b, 0x27, 0x26, 0xad, 0xf4, + 0xe7, 0x9c, 0x9e, 0x71, 0xfc, 0x7f, 0xb1, 0x60, 0x3a, 0xd5, 0x3a, 0xf2, 0xb2, 0xbc, 0xf7, 0x1e, + 0x52, 0xe7, 0x36, 0xdb, 0xd7, 0xdd, 0x6f, 0x1e, 0x40, 0x3d, 0x6c, 0x49, 0x7d, 0x14, 0x93, 0xcb, + 0xd5, 0xcb, 0x57, 0x84, 0x35, 0x0c, 0xf4, 0x1a, 0x8c, 0xc7, 0x41, 0x3b, 0xf0, 0x82, 0xed, 0x83, + 0x1b, 0x44, 0x46, 0x75, 0x52, 0xcf, 0x8f, 0x1b, 0x09, 0x08, 0xeb, 0x78, 0xf6, 0x4f, 0x15, 0x21, + 0x9d, 0x69, 0xff, 0x5b, 0x6b, 0xf2, 0x93, 0xb9, 0x26, 0xbf, 0x61, 0xc1, 0x0c, 0x6d, 0x9d, 0xd9, + 0x97, 0xc9, 0xe3, 0x50, 0x65, 0xf3, 0xb2, 0x7a, 0x64, 0xf3, 0xba, 0x44, 0x79, 0x57, 0x2b, 0xe8, + 0xc4, 0x42, 0x9f, 0xa5, 0x31, 0x27, 0x5a, 0x8a, 0x05, 0x54, 0xe0, 0x91, 0x30, 0x14, 0x3e, 0x79, + 0x3a, 0x1e, 0x09, 0x43, 0x2c, 0xa0, 0x32, 0xd9, 0xd7, 0x50, 0x4e, 0xb2, 0x2f, 0x16, 0xa3, 0x52, + 0xd8, 0x34, 0x09, 0xc1, 0x44, 0x8b, 0x51, 0x29, 0x8d, 0x9d, 0x12, 0x1c, 0xfb, 0x67, 0x8b, 0x30, + 0x51, 0x0f, 0x5a, 0xc9, 0xd3, 0xd2, 0xab, 0xc6, 0xd3, 0xd2, 0xc5, 0xd4, 0xd3, 0xd2, 0x8c, 0x8e, + 0xfb, 0xad, 0x87, 0xa4, 0x8f, 0xeb, 0x21, 0xe9, 0x5f, 0x59, 0x6c, 0xd6, 0xaa, 0xeb, 0x0d, 0x91, + 0x8c, 0xfa, 0x65, 0x18, 0x67, 0x0c, 0x89, 0x39, 0x81, 0xca, 0xf7, 0x16, 0x96, 0x73, 0x62, 0x3d, + 0x29, 0xc6, 0x3a, 0x0e, 0xba, 0x0c, 0x63, 0x11, 0x71, 0xc2, 0xe6, 0x8e, 0xe2, 0x71, 0xe2, 0x35, + 0x82, 0x97, 0x61, 0x05, 0x45, 0x6f, 0x27, 0xe1, 0x11, 0x8b, 0xf9, 0x69, 0x95, 0xf5, 0xfe, 0xf0, + 0x2d, 0x92, 0x1f, 0x13, 0xd1, 0xbe, 0x0b, 0xa8, 0x1b, 0x7f, 0x00, 0x43, 0xaf, 0x8a, 0x19, 0x08, + 0xad, 0xd4, 0x15, 0x04, 0xed, 0xcf, 0x2c, 0x98, 0xaa, 0x07, 0x2d, 0xba, 0x75, 0xbf, 0x99, 0xf6, + 0xa9, 0x1e, 0x1b, 0x76, 0xa4, 0x47, 0x6c, 0xd8, 0x7f, 0x60, 0xc1, 0x68, 0x3d, 0x68, 0x9d, 0x82, + 0x16, 0xfc, 0x0b, 0xa6, 0x16, 0xfc, 0xf1, 0x9c, 0x25, 0x91, 0xa3, 0xf8, 0xfe, 0xf9, 0x22, 0x4c, + 0xd2, 0x7e, 0x06, 0xdb, 0x72, 0x96, 0x8c, 0x11, 0xb1, 0x06, 0x18, 0x11, 0x2a, 0xe6, 0x06, 0x9e, + 0x17, 0xdc, 0x4b, 0xcf, 0xd8, 0x2a, 0x2b, 0xc5, 0x02, 0x8a, 0x5e, 0x84, 0xb1, 0x76, 0x48, 0xf6, + 0xdd, 0xa0, 0x13, 0xa5, 0xfd, 0x9d, 0xeb, 0xa2, 0x1c, 0x2b, 0x0c, 0x7a, 0x33, 0x8a, 0x5c, 0xbf, + 0x49, 0xa4, 0x05, 0xd8, 0x10, 0xb3, 0x00, 0xe3, 0x41, 0xdf, 0xb5, 0x72, 0x6c, 0x60, 0xa1, 0xbb, + 0x50, 0x62, 0xff, 0x19, 0x47, 0x39, 0x7e, 0x1a, 0x32, 0x91, 0x69, 0x45, 0x10, 0xc0, 0x09, 0x2d, + 0x74, 0x05, 0x20, 0x96, 0xb6, 0x6a, 0x91, 0x70, 0xc7, 0x57, 0xb2, 0xb6, 0xb2, 0x62, 0x8b, 0xb0, + 0x86, 0x85, 0x5e, 0x80, 0x52, 0xec, 0xb8, 0xde, 0x4d, 0xd7, 0x27, 0x91, 0xb0, 0xf5, 0x13, 0x89, + 0x54, 0x44, 0x21, 0x4e, 0xe0, 0x54, 0xd6, 0x61, 0xc1, 0x1e, 0x78, 0x12, 0xc3, 0x31, 0x86, 0xcd, + 0x64, 0x9d, 0x9b, 0xaa, 0x14, 0x6b, 0x18, 0xf6, 0x55, 0x38, 0x57, 0x0f, 0x5a, 0xf5, 0x20, 0x8c, + 0x57, 0x83, 0xf0, 0x9e, 0x13, 0xb6, 0xe4, 0xfc, 0x55, 0x64, 0x4e, 0x0f, 0xca, 0x7b, 0x86, 0xf9, + 0xce, 0x34, 0xb2, 0x75, 0xbc, 0xc2, 0xa4, 0x9d, 0x63, 0x3a, 0x66, 0xfd, 0xfb, 0x02, 0x63, 0x14, + 0xa9, 0xcc, 0x9a, 0xe8, 0x2b, 0x30, 0x15, 0x91, 0x9b, 0xae, 0xdf, 0xb9, 0x2f, 0x6f, 0xb0, 0x3d, + 0xbc, 0xde, 0x1a, 0x2b, 0x3a, 0x26, 0xd7, 0x83, 0x99, 0x65, 0x38, 0x45, 0x8d, 0x0e, 0x61, 0xd8, + 0xf1, 0x17, 0xa3, 0xdb, 0x11, 0x09, 0x45, 0x66, 0x47, 0x36, 0x84, 0x58, 0x16, 0xe2, 0x04, 0x4e, + 0x97, 0x0c, 0xfb, 0xb3, 0x1e, 0xf8, 0x38, 0x08, 0x62, 0xb9, 0xc8, 0x58, 0x6e, 0x30, 0xad, 0x1c, + 0x1b, 0x58, 0x68, 0x15, 0x50, 0xd4, 0x69, 0xb7, 0x3d, 0xf6, 0x44, 0xed, 0x78, 0xd7, 0xc2, 0xa0, + 0xd3, 0xe6, 0xcf, 0x83, 0x22, 0xad, 0x56, 0xa3, 0x0b, 0x8a, 0x33, 0x6a, 0x50, 0xc6, 0xb0, 0x15, + 0xb1, 0xdf, 0x22, 0xde, 0x03, 0xd7, 0x4d, 0x37, 0x58, 0x11, 0x96, 0x30, 0xfb, 0x7b, 0xd8, 0x81, + 0xc1, 0x12, 0xf2, 0xc5, 0x9d, 0x90, 0xa0, 0x3d, 0x98, 0x6c, 0xb3, 0xa3, 0x5c, 0x84, 0x36, 0x17, + 0x03, 0xf8, 0x70, 0x96, 0x7d, 0x3c, 0x41, 0x97, 0x4e, 0x0e, 0x9b, 0xd4, 0xed, 0xdf, 0x99, 0x66, + 0x7c, 0xa9, 0xc1, 0xaf, 0x73, 0xa3, 0xc2, 0x5e, 0x5f, 0xc8, 0xae, 0x73, 0xf9, 0x29, 0x3c, 0x93, + 0x23, 0x44, 0xd8, 0xfc, 0x63, 0x59, 0x17, 0xbd, 0xcd, 0xde, 0x55, 0x39, 0x33, 0xe8, 0x97, 0xd9, + 0x9b, 0x63, 0x19, 0x4f, 0xa8, 0xa2, 0x22, 0xd6, 0x88, 0xa0, 0x9b, 0x30, 0x29, 0xf2, 0xb7, 0x09, + 0xd5, 0x4e, 0xd1, 0x50, 0x0c, 0x4c, 0x62, 0x1d, 0x78, 0x94, 0x2e, 0xc0, 0x66, 0x65, 0xb4, 0x0d, + 0x4f, 0x69, 0xc9, 0x4c, 0x33, 0xac, 0x4b, 0x39, 0x6f, 0x79, 0xfa, 0xc1, 0x61, 0xe5, 0xa9, 0x8d, + 0x5e, 0x88, 0xb8, 0x37, 0x1d, 0x74, 0x0b, 0xce, 0x39, 0xcd, 0xd8, 0xdd, 0x27, 0x55, 0xe2, 0xb4, + 0x3c, 0xd7, 0x27, 0x66, 0x00, 0x90, 0xf3, 0x0f, 0x0e, 0x2b, 0xe7, 0x16, 0xb3, 0x10, 0x70, 0x76, + 0x3d, 0xf4, 0x05, 0x28, 0xb5, 0xfc, 0x48, 0x8c, 0xc1, 0x88, 0x91, 0xa7, 0xb7, 0x54, 0x5d, 0x6f, + 0xa8, 0xef, 0x4f, 0xfe, 0xe0, 0xa4, 0x02, 0xda, 0x86, 0x09, 0xdd, 0xc9, 0x4f, 0xe4, 0x78, 0x7e, + 0xa9, 0xc7, 0xad, 0xdf, 0xf0, 0x8c, 0xe3, 0x7a, 0x4d, 0x65, 0xbb, 0x6d, 0x38, 0xcd, 0x19, 0x84, + 0xd1, 0x5b, 0x80, 0xa8, 0x30, 0xe3, 0x36, 0xc9, 0x62, 0x93, 0x45, 0x98, 0x67, 0xda, 0xb0, 0x31, + 0xc3, 0x11, 0x09, 0x35, 0xba, 0x30, 0x70, 0x46, 0x2d, 0x74, 0x9d, 0x72, 0x14, 0xbd, 0x54, 0x98, + 0xda, 0x4b, 0x01, 0xb8, 0x5c, 0x25, 0xed, 0x90, 0x34, 0x9d, 0x98, 0xb4, 0x4c, 0x8a, 0x38, 0x55, + 0x8f, 0x9e, 0x37, 0x2a, 0xd9, 0x14, 0x98, 0x06, 0xe2, 0xdd, 0x09, 0xa7, 0xe8, 0xdd, 0x71, 0x27, + 0x88, 0xe2, 0x75, 0x12, 0xdf, 0x0b, 0xc2, 0x5d, 0x11, 0xb5, 0x2f, 0x09, 0x20, 0x9b, 0x80, 0xb0, + 0x8e, 0x47, 0x65, 0x45, 0xf6, 0xb0, 0x59, 0xab, 0xb2, 0x77, 0xa6, 0xb1, 0x64, 0x9f, 0x5c, 0xe7, + 0xc5, 0x58, 0xc2, 0x25, 0x6a, 0xad, 0xbe, 0xcc, 0xde, 0x8c, 0x52, 0xa8, 0xb5, 0xfa, 0x32, 0x96, + 0x70, 0x44, 0xba, 0x73, 0x20, 0x4f, 0xe5, 0xbf, 0xfb, 0x75, 0xf3, 0xe5, 0x01, 0xd3, 0x20, 0xfb, + 0x30, 0xa3, 0xb2, 0x2f, 0xf3, 0x70, 0x86, 0x51, 0x79, 0x9a, 0x2d, 0x92, 0xc1, 0x63, 0x21, 0x2a, + 0x6d, 0x67, 0x2d, 0x45, 0x09, 0x77, 0xd1, 0x36, 0x02, 0xcb, 0xcc, 0xf4, 0x4d, 0x16, 0xb6, 0x00, + 0xa5, 0xa8, 0xb3, 0xd9, 0x0a, 0xf6, 0x1c, 0xd7, 0x67, 0x4f, 0x3c, 0x9a, 0x20, 0xd2, 0x90, 0x00, + 0x9c, 0xe0, 0xa0, 0x55, 0x18, 0x73, 0xc4, 0xb5, 0x54, 0x3c, 0xca, 0x64, 0x46, 0x9a, 0x90, 0x57, + 0x57, 0x2e, 0x66, 0xcb, 0x7f, 0x58, 0xd5, 0x45, 0x6f, 0xc0, 0xa4, 0x70, 0x86, 0x14, 0x76, 0xcc, + 0x67, 0x4c, 0xbf, 0x99, 0x86, 0x0e, 0xc4, 0x26, 0x2e, 0xfa, 0x2e, 0x98, 0xa2, 0x54, 0x12, 0xc6, + 0x56, 0x3e, 0x3b, 0x08, 0x47, 0xd4, 0x92, 0xc0, 0xe8, 0x95, 0x71, 0x8a, 0x18, 0x6a, 0xc1, 0x93, + 0x4e, 0x27, 0x0e, 0x98, 0x3a, 0xd8, 0x5c, 0xff, 0x1b, 0xc1, 0x2e, 0xf1, 0xd9, 0x4b, 0xcc, 0xd8, + 0xd2, 0xc5, 0x07, 0x87, 0x95, 0x27, 0x17, 0x7b, 0xe0, 0xe1, 0x9e, 0x54, 0xd0, 0x6d, 0x18, 0x8f, + 0x03, 0x4f, 0x38, 0x20, 0x44, 0xe5, 0xc7, 0xf2, 0x03, 0x63, 0x6d, 0x28, 0x34, 0x5d, 0xd1, 0xa2, + 0xaa, 0x62, 0x9d, 0x0e, 0xda, 0xe0, 0x7b, 0x8c, 0x85, 0x0c, 0x26, 0x51, 0xf9, 0xf1, 0xfc, 0x81, + 0x51, 0x91, 0x85, 0xcd, 0x2d, 0x28, 0x6a, 0x62, 0x9d, 0x0c, 0xba, 0x06, 0xb3, 0xed, 0xd0, 0x0d, + 0xd8, 0xc2, 0x56, 0xaa, 0xf8, 0xb2, 0x99, 0xf7, 0xa3, 0x9e, 0x46, 0xc0, 0xdd, 0x75, 0xe8, 0x45, + 0x4c, 0x16, 0x96, 0xcf, 0xf3, 0x24, 0x72, 0x5c, 0x38, 0xe5, 0x65, 0x58, 0x41, 0xd1, 0x1a, 0xe3, + 0xcb, 0xfc, 0xca, 0x54, 0x9e, 0xcb, 0x8f, 0xd0, 0xa1, 0x5f, 0xad, 0xb8, 0xe0, 0xa2, 0xfe, 0xe2, + 0x84, 0xc2, 0xdc, 0xb7, 0xc3, 0x6c, 0x17, 0xe3, 0x3d, 0x96, 0x6d, 0xf9, 0x3f, 0x1d, 0x86, 0x92, + 0xd2, 0xbb, 0xa2, 0x05, 0x53, 0x9d, 0x7e, 0x3e, 0xad, 0x4e, 0x1f, 0xa3, 0xe2, 0x9f, 0xae, 0x41, + 0xdf, 0x30, 0x2c, 0xa3, 0x0a, 0xf9, 0xb9, 0xe0, 0x74, 0xa5, 0x43, 0x5f, 0x47, 0x50, 0xed, 0x1a, + 0x5d, 0x1c, 0x58, 0x2f, 0x3f, 0xd4, 0xf3, 0x66, 0x3e, 0x60, 0x7a, 0x6b, 0x7a, 0xd3, 0x6c, 0x07, + 0xad, 0x5a, 0x3d, 0x9d, 0xef, 0xb5, 0x4e, 0x0b, 0x31, 0x87, 0xb1, 0xbb, 0x02, 0x95, 0x12, 0xd8, + 0x5d, 0x61, 0xf4, 0x21, 0xef, 0x0a, 0x92, 0x00, 0x4e, 0x68, 0x21, 0x0f, 0x66, 0x9b, 0x66, 0xaa, + 0x5e, 0xe5, 0xfc, 0xf9, 0x4c, 0xdf, 0xa4, 0xb9, 0x1d, 0x2d, 0x87, 0xdf, 0x72, 0x9a, 0x0a, 0xee, + 0x26, 0x8c, 0xde, 0x80, 0xb1, 0xf7, 0x83, 0x88, 0xad, 0x62, 0x71, 0x54, 0x4a, 0x77, 0xbb, 0xb1, + 0xb7, 0x6f, 0x35, 0x58, 0xf9, 0xd1, 0x61, 0x65, 0xbc, 0x1e, 0xb4, 0xe4, 0x5f, 0xac, 0x2a, 0xa0, + 0xfb, 0x70, 0xce, 0x60, 0x30, 0xaa, 0xbb, 0x30, 0x78, 0x77, 0x9f, 0x12, 0xcd, 0x9d, 0xab, 0x65, + 0x51, 0xc2, 0xd9, 0x0d, 0xd8, 0xbf, 0xc4, 0xb5, 0xcb, 0x42, 0x07, 0x45, 0xa2, 0x8e, 0x77, 0x1a, + 0x89, 0xba, 0x56, 0x0c, 0xf5, 0xd8, 0x43, 0xbf, 0x60, 0xfc, 0x9a, 0xc5, 0x5e, 0x30, 0x36, 0xc8, + 0x5e, 0xdb, 0x73, 0xe2, 0xd3, 0xf0, 0x28, 0x78, 0x1b, 0xc6, 0x62, 0xd1, 0x5a, 0xaf, 0xdc, 0x62, + 0x5a, 0xa7, 0xd8, 0x2b, 0x8e, 0x3a, 0x5f, 0x65, 0x29, 0x56, 0x64, 0xec, 0x7f, 0xce, 0x67, 0x40, + 0x42, 0x4e, 0x41, 0x55, 0x51, 0x35, 0x55, 0x15, 0x95, 0x3e, 0x5f, 0x90, 0xa3, 0xb2, 0xf8, 0x67, + 0x66, 0xbf, 0xd9, 0x55, 0xe6, 0x93, 0xfe, 0x74, 0x66, 0xff, 0x88, 0x05, 0x67, 0xb3, 0xac, 0x41, + 0xa8, 0x4c, 0xc4, 0x2f, 0x52, 0xea, 0x29, 0x51, 0x8d, 0xe0, 0x1d, 0x51, 0x8e, 0x15, 0xc6, 0xc0, + 0x69, 0x3b, 0x8e, 0x17, 0x5b, 0xee, 0x16, 0x98, 0x59, 0x9d, 0xd1, 0x9b, 0xdc, 0x45, 0xc8, 0x52, + 0x69, 0x97, 0x8f, 0xe7, 0x1e, 0x64, 0xff, 0x74, 0x01, 0xce, 0xf2, 0xb7, 0x80, 0xc5, 0xfd, 0xc0, + 0x6d, 0xd5, 0x83, 0x96, 0x70, 0x98, 0x7a, 0x07, 0x26, 0xda, 0xda, 0xed, 0xb7, 0x57, 0x74, 0x2b, + 0xfd, 0x96, 0x9c, 0xdc, 0x42, 0xf4, 0x52, 0x6c, 0xd0, 0x42, 0x2d, 0x98, 0x20, 0xfb, 0x6e, 0x53, + 0x29, 0x94, 0x0b, 0xc7, 0x66, 0xe9, 0xaa, 0x95, 0x15, 0x8d, 0x0e, 0x36, 0xa8, 0x3e, 0x82, 0x2c, + 0x7c, 0xf6, 0x8f, 0x5a, 0xf0, 0x78, 0x4e, 0x2c, 0x2c, 0xda, 0xdc, 0x3d, 0xf6, 0xea, 0x22, 0x12, + 0x7a, 0xa9, 0xe6, 0xf8, 0x5b, 0x0c, 0x16, 0x50, 0xf4, 0x25, 0x00, 0xfe, 0x96, 0x42, 0x85, 0x72, + 0xf1, 0xe9, 0x83, 0xc5, 0x88, 0xd1, 0x02, 0x89, 0xc8, 0xfa, 0x58, 0xa3, 0x65, 0xff, 0x64, 0x11, + 0x86, 0x99, 0xee, 0x1e, 0xad, 0xc2, 0xe8, 0x0e, 0x8f, 0xbc, 0x3d, 0x48, 0x90, 0xef, 0xe4, 0x76, + 0xc3, 0x0b, 0xb0, 0xac, 0x8c, 0xd6, 0xe0, 0x8c, 0x70, 0xca, 0xab, 0x12, 0xcf, 0x39, 0x90, 0x97, + 0x64, 0x9e, 0x04, 0x4b, 0xa5, 0x7d, 0xab, 0x75, 0xa3, 0xe0, 0xac, 0x7a, 0xe8, 0xcd, 0xae, 0x78, + 0x9b, 0x3c, 0x66, 0xb9, 0x12, 0xa9, 0xfb, 0xc4, 0xdc, 0x7c, 0x03, 0x26, 0xdb, 0x5d, 0xea, 0x80, + 0xe1, 0x44, 0xdc, 0x37, 0x55, 0x00, 0x26, 0x2e, 0x33, 0x03, 0xe9, 0x30, 0xa3, 0x97, 0x8d, 0x9d, + 0x90, 0x44, 0x3b, 0x81, 0xd7, 0x12, 0x79, 0xe9, 0x13, 0x33, 0x90, 0x14, 0x1c, 0x77, 0xd5, 0xa0, + 0x54, 0xb6, 0x1c, 0xd7, 0xeb, 0x84, 0x24, 0xa1, 0x32, 0x62, 0x52, 0x59, 0x4d, 0xc1, 0x71, 0x57, + 0x0d, 0xba, 0x8e, 0xce, 0x89, 0xa4, 0xe6, 0x32, 0x54, 0x83, 0xb2, 0xed, 0x19, 0x95, 0x2e, 0x1b, + 0x3d, 0xc2, 0x07, 0x09, 0xdb, 0x0a, 0x95, 0x16, 0x5d, 0x4b, 0x99, 0x2b, 0x9c, 0x35, 0x24, 0x95, + 0x87, 0x49, 0xad, 0xfd, 0xfb, 0x16, 0x9c, 0xc9, 0xb0, 0x21, 0xe4, 0xac, 0x6a, 0xdb, 0x8d, 0x62, + 0x95, 0xe8, 0x47, 0x63, 0x55, 0xbc, 0x1c, 0x2b, 0x0c, 0xba, 0x1f, 0x38, 0x33, 0x4c, 0x33, 0x40, + 0x61, 0xa3, 0x23, 0xa0, 0xc7, 0x63, 0x80, 0xe8, 0x22, 0x0c, 0x75, 0x22, 0x12, 0xca, 0x9c, 0xd4, + 0x92, 0x7f, 0x33, 0x05, 0x23, 0x83, 0x50, 0x89, 0x72, 0x5b, 0xe9, 0xf6, 0x34, 0x89, 0x92, 0x6b, + 0xf7, 0x38, 0xcc, 0xfe, 0x5a, 0x11, 0xce, 0xe7, 0xda, 0x08, 0xd3, 0x2e, 0xed, 0x05, 0xbe, 0x1b, + 0x07, 0xea, 0x5d, 0x88, 0xc7, 0xb9, 0x21, 0xed, 0x9d, 0x35, 0x51, 0x8e, 0x15, 0x06, 0xba, 0x04, + 0xc3, 0xec, 0xfe, 0xdc, 0x95, 0xca, 0x68, 0xa9, 0xca, 0xc3, 0x2f, 0x70, 0xf0, 0xc0, 0x69, 0xe2, + 0x9e, 0x81, 0xa1, 0x76, 0x10, 0x78, 0x69, 0x66, 0x44, 0xbb, 0x1b, 0x04, 0x1e, 0x66, 0x40, 0xf4, + 0x19, 0x31, 0x0e, 0xa9, 0x87, 0x10, 0xec, 0xb4, 0x82, 0x48, 0x1b, 0x8c, 0xe7, 0x60, 0x74, 0x97, + 0x1c, 0x84, 0xae, 0xbf, 0x9d, 0x7e, 0x20, 0xbb, 0xc1, 0x8b, 0xb1, 0x84, 0x9b, 0x99, 0x3c, 0x46, + 0x4f, 0x3a, 0xbf, 0xdb, 0x58, 0xdf, 0xa3, 0xed, 0x07, 0x8a, 0x30, 0x8d, 0x97, 0xaa, 0xdf, 0x9a, + 0x88, 0xdb, 0xdd, 0x13, 0x71, 0xd2, 0xf9, 0xdd, 0xfa, 0xcf, 0xc6, 0xcf, 0x5b, 0x30, 0xcd, 0xa2, + 0x5d, 0x8b, 0x38, 0x2d, 0x6e, 0xe0, 0x9f, 0x82, 0xe8, 0xf6, 0x0c, 0x0c, 0x87, 0xb4, 0xd1, 0x74, + 0xd2, 0x26, 0xd6, 0x13, 0xcc, 0x61, 0xe8, 0x49, 0x18, 0x62, 0x5d, 0xa0, 0x93, 0x37, 0xc1, 0xf3, + 0x5d, 0x54, 0x9d, 0xd8, 0xc1, 0xac, 0x94, 0x39, 0xcc, 0x62, 0xd2, 0xf6, 0x5c, 0xde, 0xe9, 0x44, + 0xa1, 0xfe, 0xc9, 0x70, 0x98, 0xcd, 0xec, 0xda, 0x47, 0x73, 0x98, 0xcd, 0x26, 0xd9, 0xfb, 0x5a, + 0xf4, 0xdf, 0x0b, 0x70, 0x21, 0xb3, 0xde, 0xc0, 0x0e, 0xb3, 0xbd, 0x6b, 0x9f, 0x8c, 0x9d, 0x43, + 0xb6, 0xf9, 0x41, 0xf1, 0x14, 0xcd, 0x0f, 0x86, 0x06, 0x95, 0x1c, 0x87, 0x07, 0xf0, 0x63, 0xcd, + 0x1c, 0xb2, 0x4f, 0x88, 0x1f, 0x6b, 0x66, 0xdf, 0x72, 0xae, 0x75, 0x7f, 0x5e, 0xc8, 0xf9, 0x16, + 0x76, 0xc1, 0xbb, 0x4c, 0xf9, 0x0c, 0x03, 0x46, 0x42, 0x12, 0x9e, 0xe0, 0x3c, 0x86, 0x97, 0x61, + 0x05, 0x45, 0xae, 0xe6, 0x11, 0x5a, 0xc8, 0x4f, 0xe9, 0x99, 0xdb, 0xd4, 0xbc, 0xf9, 0xfe, 0xa1, + 0x07, 0x95, 0x49, 0x7b, 0x87, 0xae, 0x69, 0x97, 0xf2, 0xe2, 0xe0, 0x97, 0xf2, 0x89, 0xec, 0x0b, + 0x39, 0x5a, 0x84, 0xe9, 0x3d, 0xd7, 0xa7, 0x6c, 0xf3, 0xc0, 0x14, 0x45, 0x55, 0x80, 0x84, 0x35, + 0x13, 0x8c, 0xd3, 0xf8, 0x73, 0x6f, 0xc0, 0xe4, 0xc3, 0x6b, 0x11, 0xbf, 0x51, 0x84, 0x27, 0x7a, + 0x6c, 0x7b, 0xce, 0xeb, 0x8d, 0x39, 0xd0, 0x78, 0x7d, 0xd7, 0x3c, 0xd4, 0xe1, 0xec, 0x56, 0xc7, + 0xf3, 0x0e, 0x98, 0x85, 0x1f, 0x69, 0x49, 0x0c, 0x21, 0x2b, 0xaa, 0x50, 0xf6, 0xab, 0x19, 0x38, + 0x38, 0xb3, 0x26, 0x7a, 0x0b, 0x50, 0x20, 0xf2, 0x09, 0x27, 0xa1, 0x72, 0xd8, 0xc0, 0x17, 0x93, + 0xcd, 0x78, 0xab, 0x0b, 0x03, 0x67, 0xd4, 0xa2, 0x42, 0x3f, 0x3d, 0x95, 0x0e, 0x54, 0xb7, 0x52, + 0x42, 0x3f, 0xd6, 0x81, 0xd8, 0xc4, 0x45, 0xd7, 0x60, 0xd6, 0xd9, 0x77, 0x5c, 0x1e, 0x3a, 0x51, + 0x12, 0xe0, 0x52, 0xbf, 0xd2, 0xdd, 0x2d, 0xa6, 0x11, 0x70, 0x77, 0x9d, 0x94, 0x4b, 0xea, 0x48, + 0xbe, 0x4b, 0x6a, 0x6f, 0xbe, 0xd8, 0x4f, 0x15, 0x6b, 0xff, 0x27, 0x8b, 0x1e, 0x5f, 0x5a, 0x9a, + 0x7f, 0x3d, 0xa3, 0x82, 0x52, 0x29, 0x6a, 0xde, 0xa1, 0x6a, 0x1c, 0x96, 0x75, 0x20, 0x36, 0x71, + 0xf9, 0x82, 0x88, 0x12, 0x47, 0x05, 0x43, 0x74, 0x17, 0xee, 0xdf, 0x0a, 0x03, 0x7d, 0x19, 0x46, + 0x5b, 0xee, 0xbe, 0x1b, 0x05, 0xa1, 0xd8, 0x2c, 0xc7, 0x34, 0x26, 0x4f, 0xf8, 0x60, 0x95, 0x93, + 0xc1, 0x92, 0x9e, 0xfd, 0x03, 0x05, 0x98, 0x94, 0x2d, 0xbe, 0xdd, 0x09, 0x62, 0xe7, 0x14, 0x8e, + 0xe5, 0x6b, 0xc6, 0xb1, 0xfc, 0x99, 0x5e, 0x3e, 0xf0, 0xac, 0x4b, 0xb9, 0xc7, 0xf1, 0xad, 0xd4, + 0x71, 0xfc, 0x6c, 0x7f, 0x52, 0xbd, 0x8f, 0xe1, 0x7f, 0x61, 0xc1, 0xac, 0x81, 0x7f, 0x0a, 0xa7, + 0xc1, 0xaa, 0x79, 0x1a, 0x3c, 0xdd, 0xf7, 0x1b, 0x72, 0x4e, 0x81, 0xaf, 0x17, 0x52, 0x7d, 0x67, + 0xdc, 0xff, 0x7d, 0x18, 0xda, 0x71, 0xc2, 0x56, 0xaf, 0x00, 0xc0, 0x5d, 0x95, 0xe6, 0xaf, 0x3b, + 0x61, 0x8b, 0xf3, 0xf0, 0x17, 0x55, 0x16, 0x52, 0x27, 0x6c, 0xf5, 0xf5, 0xcb, 0x61, 0x4d, 0xa1, + 0xab, 0x30, 0x12, 0x35, 0x83, 0xb6, 0xb2, 0xc9, 0xbb, 0xc8, 0x33, 0x94, 0xd2, 0x92, 0xa3, 0xc3, + 0x0a, 0x32, 0x9b, 0xa3, 0xc5, 0x58, 0xe0, 0xcf, 0x6d, 0x43, 0x49, 0x35, 0xfd, 0x48, 0x3d, 0x2a, + 0x7e, 0xbb, 0x08, 0x67, 0x32, 0xd6, 0x05, 0x8a, 0x8c, 0xd1, 0x7a, 0x79, 0xc0, 0xe5, 0xf4, 0x11, + 0xc7, 0x2b, 0x62, 0x37, 0x96, 0x96, 0x98, 0xff, 0x81, 0x1b, 0xbd, 0x1d, 0x91, 0x74, 0xa3, 0xb4, + 0xa8, 0x7f, 0xa3, 0xb4, 0xb1, 0x53, 0x1b, 0x6a, 0xda, 0x90, 0xea, 0xe9, 0x23, 0x9d, 0xd3, 0x3f, + 0x29, 0xc2, 0xd9, 0xac, 0xd0, 0x19, 0xe8, 0xbb, 0x53, 0xe9, 0x84, 0x5e, 0x1d, 0x34, 0xe8, 0x06, + 0xcf, 0x31, 0x24, 0x62, 0x8d, 0xcd, 0x9b, 0x09, 0x86, 0xfa, 0x0e, 0xb3, 0x68, 0x93, 0x39, 0xca, + 0x85, 0x3c, 0x0d, 0x94, 0xdc, 0xe2, 0x9f, 0x1b, 0xb8, 0x03, 0x22, 0x7f, 0x54, 0x94, 0x72, 0x94, + 0x93, 0xc5, 0xfd, 0x1d, 0xe5, 0x64, 0xcb, 0x73, 0x2e, 0x8c, 0x6b, 0x5f, 0xf3, 0x48, 0x67, 0x7c, + 0x97, 0x9e, 0x28, 0x5a, 0xbf, 0x1f, 0xe9, 0xac, 0xff, 0xa8, 0x05, 0x29, 0x4b, 0x38, 0xa5, 0x92, + 0xb2, 0x72, 0x55, 0x52, 0x17, 0x61, 0x28, 0x0c, 0x3c, 0x92, 0xce, 0x30, 0x83, 0x03, 0x8f, 0x60, + 0x06, 0xa1, 0x18, 0x71, 0xa2, 0x90, 0x98, 0xd0, 0x2f, 0x5b, 0xe2, 0x1a, 0xf5, 0x0c, 0x0c, 0x7b, + 0x64, 0x9f, 0x48, 0x6d, 0x84, 0xe2, 0xc9, 0x37, 0x69, 0x21, 0xe6, 0x30, 0xfb, 0xe7, 0x87, 0xe0, + 0xa9, 0x9e, 0xae, 0xa6, 0xf4, 0xca, 0xb2, 0xed, 0xc4, 0xe4, 0x9e, 0x73, 0x90, 0x8e, 0x7f, 0x7d, + 0x8d, 0x17, 0x63, 0x09, 0x67, 0x76, 0xbb, 0x3c, 0x84, 0x66, 0x4a, 0x81, 0x27, 0x22, 0x67, 0x0a, + 0xa8, 0xa9, 0x38, 0x2a, 0x9e, 0x84, 0xe2, 0xe8, 0x0a, 0x40, 0x14, 0x79, 0x2b, 0x3e, 0x95, 0xc0, + 0x5a, 0xc2, 0x20, 0x38, 0x09, 0xb5, 0xda, 0xb8, 0x29, 0x20, 0x58, 0xc3, 0x42, 0x55, 0x98, 0x69, + 0x87, 0x41, 0xcc, 0xf5, 0xa1, 0x55, 0x6e, 0x8a, 0x32, 0x6c, 0x7a, 0xf9, 0xd5, 0x53, 0x70, 0xdc, + 0x55, 0x03, 0xbd, 0x06, 0xe3, 0xc2, 0xf3, 0xaf, 0x1e, 0x04, 0x9e, 0x50, 0xd5, 0x28, 0xc3, 0x86, + 0x46, 0x02, 0xc2, 0x3a, 0x9e, 0x56, 0x8d, 0x29, 0x59, 0x47, 0x33, 0xab, 0x71, 0x45, 0xab, 0x86, + 0x97, 0x0a, 0xa3, 0x33, 0x36, 0x50, 0x18, 0x9d, 0x44, 0x79, 0x55, 0x1a, 0xf8, 0x5d, 0x09, 0xfa, + 0xaa, 0x7b, 0x7e, 0x66, 0x08, 0xce, 0x88, 0x85, 0xf3, 0xa8, 0x97, 0xcb, 0xed, 0xee, 0xe5, 0x72, + 0x12, 0xea, 0xad, 0x6f, 0xad, 0x99, 0xd3, 0x5e, 0x33, 0xbf, 0x54, 0x84, 0x11, 0x3e, 0x15, 0xa7, + 0x20, 0xc3, 0xaf, 0x0a, 0xa5, 0x5f, 0x8f, 0x00, 0x32, 0xbc, 0x2f, 0xf3, 0x55, 0x27, 0x76, 0xf8, + 0xf9, 0xa5, 0xd8, 0x68, 0xa2, 0x1e, 0x44, 0xf3, 0x06, 0xa3, 0x9d, 0x4b, 0x69, 0xb5, 0x80, 0xd3, + 0xd0, 0xd8, 0xee, 0x57, 0x00, 0x22, 0x96, 0x42, 0x9f, 0xd2, 0x10, 0xa1, 0x88, 0x9e, 0xef, 0xd1, + 0x7a, 0x43, 0x21, 0xf3, 0x3e, 0x24, 0x4b, 0x50, 0x01, 0xb0, 0x46, 0x71, 0xee, 0x75, 0x28, 0x29, + 0xe4, 0x7e, 0x2a, 0x80, 0x09, 0xfd, 0xd4, 0xfb, 0x22, 0x4c, 0xa7, 0xda, 0x3a, 0x96, 0x06, 0xe1, + 0x17, 0x2c, 0x98, 0xe6, 0x5d, 0x5e, 0xf1, 0xf7, 0xc5, 0x66, 0xff, 0x00, 0xce, 0x7a, 0x19, 0x9b, + 0x4e, 0xcc, 0xe8, 0xe0, 0x9b, 0x54, 0x69, 0x0c, 0xb2, 0xa0, 0x38, 0xb3, 0x0d, 0x74, 0x19, 0xc6, + 0xb8, 0xa3, 0x8b, 0xe3, 0x09, 0xe7, 0x84, 0x09, 0x9e, 0x92, 0x82, 0x97, 0x61, 0x05, 0xb5, 0x7f, + 0xd7, 0x82, 0x59, 0xde, 0xf3, 0x1b, 0xe4, 0x40, 0xdd, 0x8e, 0x3f, 0xce, 0xbe, 0x8b, 0x8c, 0x1b, + 0x85, 0x9c, 0x8c, 0x1b, 0xfa, 0xa7, 0x15, 0x7b, 0x7e, 0xda, 0x4f, 0x5b, 0x20, 0x56, 0xe0, 0x29, + 0xdc, 0x03, 0xbf, 0xdd, 0xbc, 0x07, 0xce, 0xe5, 0x2f, 0xea, 0x9c, 0x0b, 0xe0, 0x9f, 0x59, 0x30, + 0xc3, 0x11, 0x92, 0x87, 0xc8, 0x8f, 0x75, 0x1e, 0x06, 0x49, 0x03, 0xa7, 0xf2, 0x6e, 0x67, 0x7f, + 0x94, 0x31, 0x59, 0x43, 0x3d, 0x27, 0xab, 0x25, 0x37, 0xd0, 0x31, 0xd2, 0x1b, 0x1e, 0x3b, 0x48, + 0xac, 0xfd, 0xc7, 0x16, 0x20, 0xde, 0x8c, 0x71, 0x2e, 0xd3, 0xd3, 0x8e, 0x95, 0x6a, 0x9a, 0xa0, + 0x84, 0xd5, 0x28, 0x08, 0xd6, 0xb0, 0x4e, 0x64, 0x78, 0x52, 0xaf, 0xc9, 0xc5, 0xfe, 0xaf, 0xc9, + 0xc7, 0x18, 0xd1, 0xbf, 0x3e, 0x04, 0x69, 0x4b, 0x68, 0x74, 0x07, 0x26, 0x9a, 0x4e, 0xdb, 0xd9, + 0x74, 0x3d, 0x37, 0x76, 0x49, 0xd4, 0xcb, 0x0c, 0x65, 0x59, 0xc3, 0x13, 0xef, 0x84, 0x5a, 0x09, + 0x36, 0xe8, 0xa0, 0x79, 0x80, 0x76, 0xe8, 0xee, 0xbb, 0x1e, 0xd9, 0x66, 0x57, 0x61, 0xe6, 0x0e, + 0xc5, 0x6d, 0x2b, 0x64, 0x29, 0xd6, 0x30, 0x32, 0xdc, 0x67, 0x8a, 0x8f, 0xce, 0x7d, 0x66, 0xe8, + 0x98, 0xee, 0x33, 0xc3, 0x03, 0xb9, 0xcf, 0x60, 0x78, 0x4c, 0x9e, 0xdd, 0xf4, 0xff, 0xaa, 0xeb, + 0x11, 0x21, 0xb0, 0x71, 0x27, 0xa9, 0xb9, 0x07, 0x87, 0x95, 0xc7, 0x70, 0x26, 0x06, 0xce, 0xa9, + 0x89, 0xbe, 0x04, 0x65, 0xc7, 0xf3, 0x82, 0x7b, 0x6a, 0xd4, 0x56, 0xa2, 0xa6, 0xe3, 0x25, 0x31, + 0xd3, 0xc7, 0x96, 0x9e, 0x7c, 0x70, 0x58, 0x29, 0x2f, 0xe6, 0xe0, 0xe0, 0xdc, 0xda, 0xf6, 0x2e, + 0x9c, 0x69, 0x90, 0x50, 0x66, 0x4c, 0x55, 0x5b, 0x6c, 0x03, 0x4a, 0x61, 0x8a, 0xa9, 0x0c, 0x14, + 0xab, 0x44, 0x8b, 0x67, 0x29, 0x99, 0x48, 0x42, 0xc8, 0xfe, 0x53, 0x0b, 0x46, 0x85, 0x75, 0xf5, + 0x29, 0xc8, 0x32, 0x8b, 0x86, 0x3e, 0xb2, 0x92, 0xcd, 0x78, 0x59, 0x67, 0x72, 0x35, 0x91, 0xb5, + 0x94, 0x26, 0xf2, 0xe9, 0x5e, 0x44, 0x7a, 0xeb, 0x20, 0x7f, 0xb8, 0x08, 0x53, 0xa6, 0x65, 0xf9, + 0x29, 0x0c, 0xc1, 0x3a, 0x8c, 0x46, 0xc2, 0x8d, 0xa1, 0x90, 0x6f, 0xbf, 0x9a, 0x9e, 0xc4, 0xc4, + 0xca, 0x45, 0x38, 0x2e, 0x48, 0x22, 0x99, 0xfe, 0x11, 0xc5, 0x47, 0xe8, 0x1f, 0xd1, 0xcf, 0xb8, + 0x7f, 0xe8, 0x24, 0x8c, 0xfb, 0xed, 0x5f, 0x66, 0xcc, 0x5f, 0x2f, 0x3f, 0x05, 0xb9, 0xe0, 0x9a, + 0x79, 0x4c, 0xd8, 0x3d, 0x56, 0x96, 0xe8, 0x54, 0x8e, 0x7c, 0xf0, 0x8f, 0x2d, 0x18, 0x17, 0x88, + 0xa7, 0xd0, 0xed, 0xef, 0x30, 0xbb, 0xfd, 0x44, 0x8f, 0x6e, 0xe7, 0xf4, 0xf7, 0xef, 0x16, 0x54, + 0x7f, 0xeb, 0x41, 0x18, 0x0f, 0x94, 0x43, 0x63, 0x8c, 0xde, 0x06, 0x83, 0x66, 0xe0, 0x89, 0xc3, + 0xfc, 0xc9, 0xc4, 0x4f, 0x96, 0x97, 0x1f, 0x69, 0xbf, 0xb1, 0xc2, 0x66, 0x6e, 0x9c, 0x41, 0x18, + 0x8b, 0x03, 0x34, 0x71, 0xe3, 0x0c, 0xc2, 0x18, 0x33, 0x08, 0x6a, 0x01, 0xc4, 0x4e, 0xb8, 0x4d, + 0x62, 0x5a, 0x26, 0x5c, 0xee, 0xf3, 0x77, 0x61, 0x27, 0x76, 0xbd, 0x79, 0xd7, 0x8f, 0xa3, 0x38, + 0x9c, 0xaf, 0xf9, 0xf1, 0xad, 0x90, 0xdf, 0x0d, 0x34, 0xc7, 0x57, 0x45, 0x0b, 0x6b, 0x74, 0xa5, + 0xe7, 0x15, 0x6b, 0x63, 0xd8, 0x7c, 0x28, 0x5c, 0x17, 0xe5, 0x58, 0x61, 0xd8, 0xaf, 0x33, 0x9e, + 0xcc, 0x06, 0xe8, 0x78, 0x3e, 0xa9, 0xbf, 0x39, 0xa6, 0x86, 0x96, 0xbd, 0x12, 0x54, 0x75, 0xcf, + 0xd7, 0xde, 0x2c, 0x90, 0x36, 0xac, 0xbb, 0x05, 0x24, 0xee, 0xb1, 0xe8, 0x3b, 0xbb, 0xde, 0x8f, + 0x5f, 0xea, 0xc3, 0x4b, 0x8f, 0xf1, 0x62, 0xcc, 0x02, 0xb1, 0xb2, 0x80, 0x95, 0xb5, 0x7a, 0x3a, + 0xcb, 0xc9, 0xb2, 0x04, 0xe0, 0x04, 0x07, 0x2d, 0x88, 0x9b, 0x25, 0xd7, 0xcf, 0x3d, 0x91, 0xba, + 0x59, 0xca, 0xcf, 0xd7, 0xae, 0x96, 0x2f, 0xc3, 0xb8, 0xca, 0x1c, 0x57, 0xe7, 0x09, 0xb8, 0x44, + 0x00, 0x82, 0x95, 0xa4, 0x18, 0xeb, 0x38, 0x68, 0x03, 0xa6, 0x23, 0x9e, 0xd6, 0x4e, 0x3a, 0x43, + 0x09, 0xbd, 0xc1, 0xf3, 0xf2, 0xdd, 0xb9, 0x61, 0x82, 0x8f, 0x58, 0x11, 0xdf, 0xac, 0xd2, 0x7d, + 0x2a, 0x4d, 0x02, 0xbd, 0x09, 0x53, 0x9e, 0x9e, 0xde, 0xbb, 0x2e, 0xd4, 0x0a, 0xca, 0x2c, 0xd3, + 0x48, 0xfe, 0x5d, 0xc7, 0x29, 0x6c, 0x2a, 0x04, 0xe8, 0x25, 0x22, 0x7a, 0x99, 0xe3, 0x6f, 0x93, + 0x48, 0xe4, 0xbd, 0x62, 0x42, 0xc0, 0xcd, 0x1c, 0x1c, 0x9c, 0x5b, 0x1b, 0x5d, 0x85, 0x09, 0xf9, + 0xf9, 0x9a, 0x73, 0x60, 0x62, 0xfc, 0xab, 0xc1, 0xb0, 0x81, 0x89, 0xee, 0xc1, 0x39, 0xf9, 0x7f, + 0x23, 0x74, 0xb6, 0xb6, 0xdc, 0xa6, 0xf0, 0xcd, 0x1c, 0x67, 0x24, 0x16, 0xa5, 0x27, 0xc4, 0x4a, + 0x16, 0xd2, 0xd1, 0x61, 0xe5, 0xa2, 0x18, 0xb5, 0x4c, 0x38, 0x9b, 0xc4, 0x6c, 0xfa, 0x68, 0x0d, + 0xce, 0xec, 0x10, 0xc7, 0x8b, 0x77, 0x96, 0x77, 0x48, 0x73, 0x57, 0x6e, 0x22, 0xe6, 0x72, 0xa8, + 0x99, 0xcc, 0x5e, 0xef, 0x46, 0xc1, 0x59, 0xf5, 0xd0, 0xbb, 0x50, 0x6e, 0x77, 0x36, 0x3d, 0x37, + 0xda, 0x59, 0x0f, 0x62, 0xf6, 0xd4, 0xad, 0x12, 0xaf, 0x09, 0xdf, 0x44, 0xe5, 0x6e, 0x59, 0xcf, + 0xc1, 0xc3, 0xb9, 0x14, 0xd0, 0x07, 0x70, 0x2e, 0xb5, 0x18, 0x84, 0xa7, 0xd4, 0x54, 0x7e, 0x2c, + 0xc8, 0x46, 0x56, 0x05, 0xee, 0x31, 0x9b, 0x09, 0xc2, 0xd9, 0x4d, 0x7c, 0x34, 0x03, 0x88, 0xf7, + 0x69, 0x65, 0x4d, 0xba, 0x41, 0x5f, 0x85, 0x09, 0x7d, 0x15, 0x89, 0x03, 0xe6, 0x52, 0xbf, 0x54, + 0xf6, 0x42, 0x36, 0x52, 0x2b, 0x4a, 0x87, 0x61, 0x83, 0xa2, 0x4d, 0x20, 0xfb, 0xfb, 0xd0, 0x4d, + 0x18, 0x6b, 0x7a, 0x2e, 0xf1, 0xe3, 0x5a, 0xbd, 0x97, 0x4f, 0xfd, 0xb2, 0xc0, 0x11, 0x03, 0x26, + 0x82, 0xe7, 0xf1, 0x32, 0xac, 0x28, 0xd8, 0xbf, 0x5a, 0x80, 0x4a, 0x9f, 0x48, 0x8c, 0x29, 0x1d, + 0xa0, 0x35, 0x90, 0x0e, 0x70, 0x51, 0xa6, 0x91, 0x5b, 0x4f, 0xdd, 0x3f, 0x53, 0x29, 0xe2, 0x92, + 0x5b, 0x68, 0x1a, 0x7f, 0x60, 0xbb, 0x49, 0x5d, 0x8d, 0x38, 0xd4, 0xd7, 0xa2, 0xd7, 0x78, 0x3e, + 0x18, 0x1e, 0x5c, 0xa2, 0xcf, 0x55, 0x05, 0xdb, 0xbf, 0x5c, 0x80, 0x73, 0x6a, 0x08, 0xbf, 0x79, + 0x07, 0xee, 0x76, 0xf7, 0xc0, 0x9d, 0x80, 0x22, 0xdd, 0xbe, 0x05, 0x23, 0x8d, 0x83, 0xa8, 0x19, + 0x7b, 0x03, 0x08, 0x40, 0xcf, 0x98, 0xb1, 0x65, 0xd4, 0x31, 0x6d, 0xc4, 0x97, 0xf9, 0x2b, 0x16, + 0x4c, 0x6f, 0x2c, 0xd7, 0x1b, 0x41, 0x73, 0x97, 0xc4, 0x8b, 0x5c, 0x4d, 0x84, 0x85, 0xfc, 0x63, + 0x3d, 0xa4, 0x5c, 0x93, 0x25, 0x31, 0x5d, 0x84, 0xa1, 0x9d, 0x20, 0x8a, 0xd3, 0xaf, 0x6c, 0xd7, + 0x83, 0x28, 0xc6, 0x0c, 0x62, 0xff, 0x9e, 0x05, 0xc3, 0x2c, 0xf9, 0x69, 0xbf, 0x24, 0xb9, 0x83, + 0x7c, 0x17, 0x7a, 0x0d, 0x46, 0xc8, 0xd6, 0x16, 0x69, 0xc6, 0x62, 0x56, 0xa5, 0x77, 0xdd, 0xc8, + 0x0a, 0x2b, 0xa5, 0x87, 0x3e, 0x6b, 0x8c, 0xff, 0xc5, 0x02, 0x19, 0xdd, 0x85, 0x52, 0xec, 0xee, + 0x91, 0xc5, 0x56, 0x4b, 0xbc, 0x53, 0x3c, 0x84, 0x33, 0xe3, 0x86, 0x24, 0x80, 0x13, 0x5a, 0xf6, + 0xd7, 0x0a, 0x00, 0x89, 0x43, 0x6f, 0xbf, 0x4f, 0x5c, 0xea, 0xca, 0x03, 0x7c, 0x29, 0x23, 0x0f, + 0x30, 0x4a, 0x08, 0x66, 0x64, 0x01, 0x56, 0xc3, 0x54, 0x1c, 0x68, 0x98, 0x86, 0x8e, 0x33, 0x4c, + 0xcb, 0x30, 0x9b, 0x38, 0x24, 0x9b, 0xd1, 0x19, 0x58, 0x64, 0xf6, 0x8d, 0x34, 0x10, 0x77, 0xe3, + 0xdb, 0xdf, 0x6f, 0x81, 0x70, 0x37, 0x18, 0x60, 0x31, 0xbf, 0x23, 0x53, 0x76, 0x1a, 0x01, 0x5d, + 0x2f, 0xe6, 0xfb, 0x5f, 0x88, 0x30, 0xae, 0xea, 0xf0, 0x30, 0x82, 0xb7, 0x1a, 0xb4, 0xec, 0x16, + 0x08, 0x68, 0x95, 0x30, 0x25, 0x43, 0xff, 0xde, 0x5c, 0x01, 0x68, 0x31, 0x5c, 0x2d, 0x05, 0xa0, + 0x62, 0x55, 0x55, 0x05, 0xc1, 0x1a, 0x96, 0xfd, 0x37, 0x0b, 0x30, 0x2e, 0x03, 0x88, 0xd2, 0x7b, + 0x7c, 0xff, 0x56, 0x8e, 0x95, 0x3d, 0x80, 0xe5, 0xcc, 0xa4, 0x84, 0x55, 0x90, 0x79, 0x3d, 0x67, + 0xa6, 0x04, 0xe0, 0x04, 0x07, 0x3d, 0x07, 0xa3, 0x51, 0x67, 0x93, 0xa1, 0xa7, 0x8c, 0xe8, 0x1b, + 0xbc, 0x18, 0x4b, 0x38, 0xfa, 0x12, 0xcc, 0xf0, 0x7a, 0x61, 0xd0, 0x76, 0xb6, 0xb9, 0x06, 0x69, + 0x58, 0x79, 0xb5, 0xcd, 0xac, 0xa5, 0x60, 0x47, 0x87, 0x95, 0xb3, 0xe9, 0x32, 0xa6, 0x7b, 0xec, + 0xa2, 0x42, 0xf7, 0xc5, 0x4c, 0xda, 0x61, 0x06, 0x5d, 0x87, 0x11, 0xce, 0xf2, 0x04, 0x0b, 0xea, + 0xf1, 0xa2, 0xa4, 0xb9, 0xd9, 0xb0, 0x70, 0xea, 0x82, 0x6b, 0x8a, 0xfa, 0xe8, 0x5d, 0x18, 0x6f, + 0x05, 0xf7, 0xfc, 0x7b, 0x4e, 0xd8, 0x5a, 0xac, 0xd7, 0xc4, 0xaa, 0xc9, 0x94, 0x9c, 0xaa, 0x09, + 0x9a, 0xee, 0xba, 0xc3, 0xb4, 0xa7, 0x09, 0x08, 0xeb, 0xe4, 0xd0, 0x06, 0x8b, 0xf1, 0xc4, 0x93, + 0xda, 0xf7, 0xb2, 0x3a, 0x53, 0x79, 0xf0, 0x35, 0xca, 0x93, 0x22, 0x10, 0x94, 0x48, 0x89, 0x9f, + 0x10, 0xb2, 0x3f, 0x3c, 0x03, 0xc6, 0x6a, 0x35, 0xb2, 0x07, 0x58, 0x27, 0x94, 0x3d, 0x00, 0xc3, + 0x18, 0xd9, 0x6b, 0xc7, 0x07, 0x55, 0x37, 0xec, 0x95, 0x7e, 0x66, 0x45, 0xe0, 0x74, 0xd3, 0x94, + 0x10, 0xac, 0xe8, 0x64, 0xa7, 0x78, 0x28, 0x7e, 0x8c, 0x29, 0x1e, 0x86, 0x4e, 0x31, 0xc5, 0xc3, + 0x3a, 0x8c, 0x6e, 0xbb, 0x31, 0x26, 0xed, 0x40, 0x1c, 0xf7, 0x99, 0x2b, 0xe1, 0x1a, 0x47, 0xe9, + 0x0e, 0x30, 0x2e, 0x00, 0x58, 0x12, 0x41, 0x6f, 0xa9, 0x3d, 0x30, 0x92, 0x2f, 0x2d, 0x77, 0x3f, + 0x3e, 0x64, 0xee, 0x02, 0x91, 0xd2, 0x61, 0xf4, 0x61, 0x53, 0x3a, 0xac, 0xca, 0x44, 0x0c, 0x63, + 0xf9, 0x46, 0x9a, 0x2c, 0xcf, 0x42, 0x9f, 0xf4, 0x0b, 0x46, 0xca, 0x8a, 0xd2, 0xc9, 0xa5, 0xac, + 0xf8, 0x7e, 0x0b, 0xce, 0xb5, 0xb3, 0xb2, 0xb7, 0x88, 0x44, 0x0a, 0xaf, 0x0d, 0x9c, 0x9e, 0xc6, + 0x68, 0x90, 0x5d, 0x9b, 0x32, 0xd1, 0x70, 0x76, 0x73, 0x74, 0xa0, 0xc3, 0xcd, 0x96, 0xc8, 0xbe, + 0xf0, 0x4c, 0x4e, 0xee, 0x8b, 0x1e, 0x19, 0x2f, 0x36, 0x32, 0x32, 0x2e, 0x7c, 0x3a, 0x2f, 0xe3, + 0xc2, 0xc0, 0x79, 0x16, 0x92, 0xac, 0x17, 0x93, 0x1f, 0x39, 0xeb, 0xc5, 0x5b, 0x2a, 0xeb, 0x45, + 0x8f, 0x48, 0x3a, 0x3c, 0xa7, 0x45, 0xdf, 0x5c, 0x17, 0x5a, 0xbe, 0x8a, 0xe9, 0x93, 0xc9, 0x57, + 0x61, 0x30, 0x7b, 0x9e, 0x32, 0xe1, 0x85, 0x3e, 0xcc, 0xde, 0xa0, 0xdb, 0x9b, 0xdd, 0xf3, 0xdc, + 0x1c, 0xb3, 0x0f, 0x95, 0x9b, 0xe3, 0x8e, 0x9e, 0xeb, 0x02, 0xf5, 0x49, 0xe6, 0x40, 0x91, 0x06, + 0xcc, 0x70, 0x71, 0x47, 0x3f, 0x82, 0xce, 0xe4, 0xd3, 0x55, 0x27, 0x4d, 0x37, 0xdd, 0xac, 0x43, + 0xa8, 0x3b, 0x73, 0xc6, 0xd9, 0xd3, 0xc9, 0x9c, 0x71, 0xee, 0xc4, 0x33, 0x67, 0x3c, 0x76, 0x0a, + 0x99, 0x33, 0x1e, 0xff, 0x58, 0x33, 0x67, 0x94, 0x1f, 0x41, 0xe6, 0x8c, 0xf5, 0x24, 0x73, 0xc6, + 0xf9, 0xfc, 0x29, 0xc9, 0xb0, 0x4a, 0xcb, 0xc9, 0x97, 0x71, 0x07, 0x4a, 0x6d, 0xe9, 0x53, 0x2d, + 0x42, 0xfd, 0x64, 0xa7, 0xec, 0xcb, 0x72, 0xbc, 0xe6, 0x53, 0xa2, 0x40, 0x38, 0x21, 0x45, 0xe9, + 0x26, 0xf9, 0x33, 0x9e, 0xe8, 0xa1, 0x18, 0xcb, 0x52, 0x39, 0xe4, 0x67, 0xcd, 0xb0, 0xff, 0x6a, + 0x01, 0x2e, 0xf4, 0x5e, 0xd7, 0x89, 0xbe, 0xa2, 0x9e, 0xe8, 0xd7, 0x53, 0xfa, 0x0a, 0x7e, 0x09, + 0x48, 0xb0, 0x06, 0x0e, 0x3c, 0x71, 0x0d, 0x66, 0x95, 0x39, 0x9a, 0xe7, 0x36, 0x0f, 0xb4, 0x54, + 0x7e, 0xca, 0x35, 0xa6, 0x91, 0x46, 0xc0, 0xdd, 0x75, 0xd0, 0x22, 0x4c, 0x1b, 0x85, 0xb5, 0xaa, + 0x10, 0xf6, 0x95, 0x82, 0xa4, 0x61, 0x82, 0x71, 0x1a, 0xdf, 0xfe, 0xba, 0x05, 0x8f, 0xe7, 0x84, + 0xac, 0x1e, 0x38, 0xae, 0xc2, 0x16, 0x4c, 0xb7, 0xcd, 0xaa, 0x7d, 0xc2, 0xaf, 0x18, 0x81, 0xb1, + 0x55, 0x5f, 0x53, 0x00, 0x9c, 0x26, 0xba, 0x74, 0xf9, 0xd7, 0xff, 0xe0, 0xc2, 0xa7, 0x7e, 0xeb, + 0x0f, 0x2e, 0x7c, 0xea, 0x77, 0xff, 0xe0, 0xc2, 0xa7, 0xfe, 0xff, 0x07, 0x17, 0xac, 0x5f, 0x7f, + 0x70, 0xc1, 0xfa, 0xad, 0x07, 0x17, 0xac, 0xdf, 0x7d, 0x70, 0xc1, 0xfa, 0xfd, 0x07, 0x17, 0xac, + 0xaf, 0xfd, 0xe1, 0x85, 0x4f, 0xbd, 0x53, 0xd8, 0x7f, 0xf9, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, + 0xc2, 0x38, 0x28, 0x01, 0xc3, 0xdf, 0x00, 0x00, } diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index 6bef759dece..acd56881674 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -185,6 +185,12 @@ message CSIPersistentVolumeSource { // Defaults to false (read/write). // +optional optional bool readOnly = 3; + + // Filesystem type to mount. + // Must be a filesystem type supported by the host operating system. + // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. + // +optional + optional string fsType = 4; } // Adds and removes POSIX capabilities from running containers. diff --git a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go index 80cacc974e5..6c565486411 100644 --- a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go @@ -121,6 +121,7 @@ var map_CSIPersistentVolumeSource = map[string]string{ "driver": "Driver is the name of the driver to use for this volume. Required.", "volumeHandle": "VolumeHandle is the unique volume name returned by the CSI volume plugin’s CreateVolume to refer to the volume on all subsequent calls. Required.", "readOnly": "Optional: The value to pass to ControllerPublishVolumeRequest. Defaults to false (read/write).", + "fsType": "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", } func (CSIPersistentVolumeSource) SwaggerDoc() map[string]string { From 3660563e22f2db2d27c4b66196e4b1603dca0ebc Mon Sep 17 00:00:00 2001 From: Yanqiang Miao Date: Tue, 16 Jan 2018 15:38:24 +0800 Subject: [PATCH 23/58] Benchmark non docker specific Signed-off-by: Yanqiang Miao --- test/e2e_node/resource_collector.go | 31 ++++++++++------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/test/e2e_node/resource_collector.go b/test/e2e_node/resource_collector.go index ec256e32f1f..c98a8c2ff2f 100644 --- a/test/e2e_node/resource_collector.go +++ b/test/e2e_node/resource_collector.go @@ -85,16 +85,16 @@ func NewResourceCollector(interval time.Duration) *ResourceCollector { // Start starts resource collector and connects to the standalone Cadvisor pod // then repeatedly runs collectStats. func (r *ResourceCollector) Start() { - // Get the cgroup container names for kubelet and docker + // Get the cgroup container names for kubelet and runtime kubeletContainer, err := getContainerNameForProcess(kubeletProcessName, "") - dockerContainer, err := getContainerNameForProcess(dockerProcessName, dockerPidFile) + runtimeContainer, err := getContainerNameForProcess(framework.TestContext.ContainerRuntimeProcessName, framework.TestContext.ContainerRuntimePidFile) if err == nil { systemContainers = map[string]string{ stats.SystemContainerKubelet: kubeletContainer, - stats.SystemContainerRuntime: dockerContainer, + stats.SystemContainerRuntime: runtimeContainer, } } else { - framework.Failf("Failed to get docker container name in test-e2e-node resource collector.") + framework.Failf("Failed to get runtime container name in test-e2e-node resource collector.") } wait.Poll(1*time.Second, 1*time.Minute, func() (bool, error) { @@ -240,12 +240,11 @@ func (r *ResourceCollector) GetBasicCPUStats(containerName string) map[float64]f func formatResourceUsageStats(containerStats framework.ResourceUsagePerContainer) string { // Example output: // - // Resource usage for node "e2e-test-foo-node-abcde": - // container cpu(cores) memory(MB) - // "/" 0.363 2942.09 - // "/docker-daemon" 0.088 521.80 - // "/kubelet" 0.086 424.37 - // "/system" 0.007 119.88 + // Resource usage: + //container cpu(cores) memory_working_set(MB) memory_rss(MB) + //"kubelet" 0.068 27.92 15.43 + //"runtime" 0.664 89.88 68.13 + buf := &bytes.Buffer{} w := tabwriter.NewWriter(buf, 1, 0, 1, ' ', 0) fmt.Fprintf(w, "container\tcpu(cores)\tmemory_working_set(MB)\tmemory_rss(MB)\n") @@ -258,7 +257,7 @@ func formatResourceUsageStats(containerStats framework.ResourceUsagePerContainer func formatCPUSummary(summary framework.ContainersCPUSummary) string { // Example output for a node (the percentiles may differ): - // CPU usage of containers on node "e2e-test-foo-node-0vj7": + // CPU usage of containers: // container 5th% 50th% 90th% 95th% // "/" 0.051 0.159 0.387 0.455 // "/runtime 0.000 0.000 0.146 0.166 @@ -461,15 +460,7 @@ func (r *ResourceCollector) GetResourceTimeSeries() map[string]*perftype.Resourc return resourceSeries } -// Code for getting container name of docker, copied from pkg/kubelet/cm/container_manager_linux.go -// since they are not exposed -const ( - kubeletProcessName = "kubelet" - dockerProcessName = "docker" - dockerPidFile = "/var/run/docker.pid" - containerdProcessName = "docker-containerd" - containerdPidFile = "/run/docker/libcontainerd/docker-containerd.pid" -) +const kubeletProcessName = "kubelet" func getPidsForProcess(name, pidFile string) ([]int, error) { if len(pidFile) > 0 { From 9c847fc4d6d5f86ddc17e7717e9357e4b0a54caa Mon Sep 17 00:00:00 2001 From: vikaschoudhary16 Date: Tue, 16 Jan 2018 01:04:18 -0500 Subject: [PATCH 24/58] Call Dial in blocking mode --- pkg/kubelet/cm/deviceplugin/device_plugin_stub.go | 14 ++++++-------- pkg/kubelet/cm/deviceplugin/endpoint.go | 5 +++-- pkg/kubelet/cm/deviceplugin/manager_test.go | 3 --- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/pkg/kubelet/cm/deviceplugin/device_plugin_stub.go b/pkg/kubelet/cm/deviceplugin/device_plugin_stub.go index 08dcd5a992f..a80f16b9d19 100644 --- a/pkg/kubelet/cm/deviceplugin/device_plugin_stub.go +++ b/pkg/kubelet/cm/deviceplugin/device_plugin_stub.go @@ -86,14 +86,11 @@ func (m *Stub) Start() error { pluginapi.RegisterDevicePluginServer(m.server, m) go m.server.Serve(sock) - // Wait till grpc server is ready. - for i := 0; i < 10; i++ { - services := m.server.GetServiceInfo() - if len(services) > 0 { - break - } - time.Sleep(1 * time.Second) + _, conn, err := dial(m.socket) + if err != nil { + return err } + conn.Close() log.Println("Starting to serve on", m.socket) return nil @@ -109,7 +106,8 @@ func (m *Stub) Stop() error { // Register registers the device plugin for the given resourceName with Kubelet. func (m *Stub) Register(kubeletEndpoint, resourceName string) error { - conn, err := grpc.Dial(kubeletEndpoint, grpc.WithInsecure(), + conn, err := grpc.Dial(kubeletEndpoint, grpc.WithInsecure(), grpc.WithBlock(), + grpc.WithTimeout(10*time.Second), grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { return net.DialTimeout("unix", addr, timeout) })) diff --git a/pkg/kubelet/cm/deviceplugin/endpoint.go b/pkg/kubelet/cm/deviceplugin/endpoint.go index 523922d9dc0..f2fd8be9896 100644 --- a/pkg/kubelet/cm/deviceplugin/endpoint.go +++ b/pkg/kubelet/cm/deviceplugin/endpoint.go @@ -186,9 +186,10 @@ func (e *endpointImpl) stop() { e.clientConn.Close() } -// dial establishes the gRPC communication with the registered device plugin. +// dial establishes the gRPC communication with the registered device plugin. https://godoc.org/google.golang.org/grpc#Dial func dial(unixSocketPath string) (pluginapi.DevicePluginClient, *grpc.ClientConn, error) { - c, err := grpc.Dial(unixSocketPath, grpc.WithInsecure(), + c, err := grpc.Dial(unixSocketPath, grpc.WithInsecure(), grpc.WithBlock(), + grpc.WithTimeout(10*time.Second), grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { return net.DialTimeout("unix", addr, timeout) }), diff --git a/pkg/kubelet/cm/deviceplugin/manager_test.go b/pkg/kubelet/cm/deviceplugin/manager_test.go index 124f690acf7..783c2d48757 100644 --- a/pkg/kubelet/cm/deviceplugin/manager_test.go +++ b/pkg/kubelet/cm/deviceplugin/manager_test.go @@ -497,9 +497,6 @@ type TestResource struct { func TestPodContainerDeviceAllocation(t *testing.T) { flag.Set("alsologtostderr", fmt.Sprintf("%t", true)) - var logLevel string - flag.StringVar(&logLevel, "logLevel", "4", "test") - flag.Lookup("v").Value.Set(logLevel) res1 := TestResource{ resourceName: "domain1.com/resource1", resourceQuantity: *resource.NewQuantity(int64(2), resource.DecimalSI), From a8f7404a13f9db64606b6607fef3efd9655374d6 Mon Sep 17 00:00:00 2001 From: Huamin Chen Date: Tue, 16 Jan 2018 16:43:10 +0000 Subject: [PATCH 25/58] azure disk: if the disk is not found, immediately detach it. This prevents azure keeps the bad request and stops issuing new request Signed-off-by: Huamin Chen --- .../providers/azure/azure_controllerCommon.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/cloudprovider/providers/azure/azure_controllerCommon.go b/pkg/cloudprovider/providers/azure/azure_controllerCommon.go index ad40f3c5b85..8cef635c3bb 100644 --- a/pkg/cloudprovider/providers/azure/azure_controllerCommon.go +++ b/pkg/cloudprovider/providers/azure/azure_controllerCommon.go @@ -43,6 +43,7 @@ const ( errLeaseFailed = "AcquireDiskLeaseFailed" errLeaseIDMissing = "LeaseIdMissing" errContainerNotFound = "ContainerNotFound" + errDiskBlobNotFound = "DiskBlobNotFound" ) var defaultBackOff = kwait.Backoff{ @@ -124,9 +125,9 @@ func (c *controllerCommon) AttachDisk(isManagedDisk bool, diskName, diskURI stri if err != nil { glog.Errorf("azureDisk - azure attach failed, err: %v", err) detail := err.Error() - if strings.Contains(detail, errLeaseFailed) { - // if lease cannot be acquired, immediately detach the disk and return the original error - glog.Infof("azureDisk - failed to acquire disk lease, try detach") + if strings.Contains(detail, errLeaseFailed) || strings.Contains(detail, errDiskBlobNotFound) { + // if lease cannot be acquired or disk not found, immediately detach the disk and return the original error + glog.Infof("azureDisk - err %s, try detach", detail) c.cloud.DetachDiskByName(diskName, diskURI, nodeName) } } else { From 96b5c332833d95667239d62ea9ca274007f3645d Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Sat, 13 Jan 2018 08:18:37 -0800 Subject: [PATCH 26/58] cluster: remove centos dependency on saltbase --- .../{saltbase/salt/generate-cert => centos}/make-ca-cert.sh | 5 ----- cluster/centos/util.sh | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) rename cluster/{saltbase/salt/generate-cert => centos}/make-ca-cert.sh (92%) diff --git a/cluster/saltbase/salt/generate-cert/make-ca-cert.sh b/cluster/centos/make-ca-cert.sh similarity index 92% rename from cluster/saltbase/salt/generate-cert/make-ca-cert.sh rename to cluster/centos/make-ca-cert.sh index 41531209ed5..c86f27bba2b 100755 --- a/cluster/saltbase/salt/generate-cert/make-ca-cert.sh +++ b/cluster/centos/make-ca-cert.sh @@ -33,11 +33,6 @@ mkdir -p "$cert_dir" use_cn=false -# TODO: Add support for discovery on other providers? -if [ "$cert_ip" == "_use_gce_external_ip_" ]; then - cert_ip=$(curl -s -H Metadata-Flavor:Google http://metadata.google.internal./computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip) -fi - sans="IP:${cert_ip}" if [[ -n "${extra_sans}" ]]; then sans="${sans},${extra_sans}" diff --git a/cluster/centos/util.sh b/cluster/centos/util.sh index 88302a31a93..10378428bca 100755 --- a/cluster/centos/util.sh +++ b/cluster/centos/util.sh @@ -234,7 +234,7 @@ echo "[INFO] tear-down-node on $1" # Generate the CA certificates for k8s components function make-ca-cert() { echo "[INFO] make-ca-cert" - bash "${ROOT}/../saltbase/salt/generate-cert/make-ca-cert.sh" "${MASTER_ADVERTISE_IP}" "IP:${MASTER_ADVERTISE_IP},IP:${SERVICE_CLUSTER_IP_RANGE%.*}.1,DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster.local" + bash "${ROOT}/make-ca-cert.sh" "${MASTER_ADVERTISE_IP}" "IP:${MASTER_ADVERTISE_IP},IP:${SERVICE_CLUSTER_IP_RANGE%.*}.1,DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster.local" } # Provision master From 13116457ba6ed28f1d72061aa52c99d53fe95040 Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Sat, 13 Jan 2018 08:24:17 -0800 Subject: [PATCH 27/58] cluster: remove gce dependencies out of salt basically just: * move all manifests into the new gce/manifests dir * move limit-range into gce/addons/limit-range * move abac jsonl into gce/manifests. this is gross but we will hopefully be able to delete this config soon. it only exists to support a deprecated feature. * fix build, release, deploy to look for everything in its new home --- build/lib/release.sh | 41 +++++++++---------- cluster/BUILD | 22 +++------- cluster/gce/BUILD | 18 ++++++++ .../addons}/limit-range/limit-range.yaml | 0 cluster/gce/gci/configure-helper.sh | 8 ++-- .../manifests}/abac-authz-policy.jsonl | 0 .../manifests}/cluster-autoscaler.manifest | 0 .../manifests}/e2e-image-puller.manifest | 0 .../salt/etcd => gce/manifests}/etcd.manifest | 0 .../l7-gcp => gce/manifests}/glbc.manifest | 0 .../manifests}/kube-addon-manager.yaml | 0 .../manifests}/kube-apiserver.manifest | 0 .../kube-controller-manager.manifest | 0 .../manifests}/kube-proxy.manifest | 0 .../manifests}/kube-registry-proxy.yaml | 0 .../manifests}/kube-scheduler.manifest | 0 .../manifests}/rescheduler.manifest | 0 cluster/saltbase/BUILD | 39 ------------------ 18 files changed, 46 insertions(+), 82 deletions(-) rename cluster/{saltbase/salt/kube-admission-controls => gce/addons}/limit-range/limit-range.yaml (100%) rename cluster/{saltbase/salt/kube-apiserver => gce/manifests}/abac-authz-policy.jsonl (100%) rename cluster/{saltbase/salt/cluster-autoscaler => gce/manifests}/cluster-autoscaler.manifest (100%) rename cluster/{saltbase/salt/e2e-image-puller => gce/manifests}/e2e-image-puller.manifest (100%) rename cluster/{saltbase/salt/etcd => gce/manifests}/etcd.manifest (100%) rename cluster/{saltbase/salt/l7-gcp => gce/manifests}/glbc.manifest (100%) rename cluster/{saltbase/salt/kube-addons => gce/manifests}/kube-addon-manager.yaml (100%) rename cluster/{saltbase/salt/kube-apiserver => gce/manifests}/kube-apiserver.manifest (100%) rename cluster/{saltbase/salt/kube-controller-manager => gce/manifests}/kube-controller-manager.manifest (100%) rename cluster/{saltbase/salt/kube-proxy => gce/manifests}/kube-proxy.manifest (100%) rename cluster/{saltbase/salt/kube-registry-proxy => gce/manifests}/kube-registry-proxy.yaml (100%) rename cluster/{saltbase/salt/kube-scheduler => gce/manifests}/kube-scheduler.manifest (100%) rename cluster/{saltbase/salt/rescheduler => gce/manifests}/rescheduler.manifest (100%) diff --git a/build/lib/release.sh b/build/lib/release.sh index 9b820b1bbd3..1fd9296fd01 100644 --- a/build/lib/release.sh +++ b/build/lib/release.sh @@ -391,38 +391,35 @@ function kube::release::package_salt_tarball() { function kube::release::package_kube_manifests_tarball() { kube::log::status "Building tarball: manifests" - local salt_dir="${KUBE_ROOT}/cluster/saltbase/salt" + local src_dir="${KUBE_ROOT}/cluster/gce/manifests" local release_stage="${RELEASE_STAGE}/manifests/kubernetes" rm -rf "${release_stage}" - mkdir -p "${release_stage}" - cp "${salt_dir}/kube-registry-proxy/kube-registry-proxy.yaml" "${release_stage}/" - cp "${salt_dir}/kube-proxy/kube-proxy.manifest" "${release_stage}/" - - local gci_dst_dir="${release_stage}/gci-trusty" - mkdir -p "${gci_dst_dir}" - cp "${salt_dir}/cluster-autoscaler/cluster-autoscaler.manifest" "${gci_dst_dir}/" - cp "${salt_dir}/etcd/etcd.manifest" "${gci_dst_dir}" - cp "${salt_dir}/kube-scheduler/kube-scheduler.manifest" "${gci_dst_dir}" - cp "${salt_dir}/kube-apiserver/kube-apiserver.manifest" "${gci_dst_dir}" - cp "${salt_dir}/kube-apiserver/abac-authz-policy.jsonl" "${gci_dst_dir}" - cp "${salt_dir}/kube-controller-manager/kube-controller-manager.manifest" "${gci_dst_dir}" - cp "${salt_dir}/kube-addons/kube-addon-manager.yaml" "${gci_dst_dir}" - cp "${salt_dir}/l7-gcp/glbc.manifest" "${gci_dst_dir}" - cp "${salt_dir}/rescheduler/rescheduler.manifest" "${gci_dst_dir}/" - cp "${salt_dir}/e2e-image-puller/e2e-image-puller.manifest" "${gci_dst_dir}/" - cp "${KUBE_ROOT}/cluster/gce/gci/configure-helper.sh" "${gci_dst_dir}/gci-configure-helper.sh" - cp "${KUBE_ROOT}/cluster/gce/gci/health-monitor.sh" "${gci_dst_dir}/health-monitor.sh" - cp -r "${salt_dir}/kube-admission-controls/limit-range" "${gci_dst_dir}" + local dst_dir="${release_stage}/gci-trusty" + mkdir -p "${dst_dir}" + cp "${src_dir}/kube-registry-proxy.yaml" "${dst_dir}/" + cp "${src_dir}/kube-proxy.manifest" "${dst_dir}/" + cp "${src_dir}/cluster-autoscaler.manifest" "${dst_dir}/" + cp "${src_dir}/etcd.manifest" "${dst_dir}" + cp "${src_dir}/kube-scheduler.manifest" "${dst_dir}" + cp "${src_dir}/kube-apiserver.manifest" "${dst_dir}" + cp "${src_dir}/abac-authz-policy.jsonl" "${dst_dir}" + cp "${src_dir}/kube-controller-manager.manifest" "${dst_dir}" + cp "${src_dir}/kube-addon-manager.yaml" "${dst_dir}" + cp "${src_dir}/glbc.manifest" "${dst_dir}" + cp "${src_dir}/rescheduler.manifest" "${dst_dir}/" + cp "${src_dir}/e2e-image-puller.manifest" "${dst_dir}/" + cp "${KUBE_ROOT}/cluster/gce/gci/configure-helper.sh" "${dst_dir}/gci-configure-helper.sh" + cp "${KUBE_ROOT}/cluster/gce/gci/health-monitor.sh" "${dst_dir}/health-monitor.sh" local objects objects=$(cd "${KUBE_ROOT}/cluster/addons" && find . \( -name \*.yaml -or -name \*.yaml.in -or -name \*.json \) | grep -v demo) - tar c -C "${KUBE_ROOT}/cluster/addons" ${objects} | tar x -C "${gci_dst_dir}" + tar c -C "${KUBE_ROOT}/cluster/addons" ${objects} | tar x -C "${dst_dir}" # Merge GCE-specific addons with general purpose addons. local gce_objects gce_objects=$(cd "${KUBE_ROOT}/cluster/gce/addons" && find . \( -name \*.yaml -or -name \*.yaml.in -or -name \*.json \) \( -not -name \*demo\* \)) if [[ -n "${gce_objects}" ]]; then - tar c -C "${KUBE_ROOT}/cluster/gce/addons" ${gce_objects} | tar x -C "${gci_dst_dir}" + tar c -C "${KUBE_ROOT}/cluster/gce/addons" ${gce_objects} | tar x -C "${dst_dir}" fi kube::release::clean_cruft diff --git a/cluster/BUILD b/cluster/BUILD index 9d3ad2c9744..8dea73c4cd2 100644 --- a/cluster/BUILD +++ b/cluster/BUILD @@ -25,27 +25,15 @@ filegroup( tags = ["automanaged"], ) -# All of the manifests that are expected to be in a "gci-trusty" -# subdir of the manifests tarball. -pkg_tar( - name = "_manifests-gci-trusty", - package_dir = "gci-trusty", - visibility = ["//visibility:private"], - deps = [ - "//cluster/addons", - "//cluster/gce:gci-trusty-manifests", - "//cluster/gce/addons", - "//cluster/saltbase:gci-trusty-salt-manifests", - ], -) - pkg_tar( name = "manifests", mode = "0644", - package_dir = "kubernetes", + package_dir = "kubernetes/gci-trusty", deps = [ - ":_manifests-gci-trusty", - "//cluster/saltbase:salt-manifests", + "//cluster/addons", + "//cluster/gce:gce-master-manifests", + "//cluster/gce:gci-trusty-manifests", + "//cluster/gce/addons", ], ) diff --git a/cluster/gce/BUILD b/cluster/gce/BUILD index e297c36ef6f..9f0717fe71d 100644 --- a/cluster/gce/BUILD +++ b/cluster/gce/BUILD @@ -49,3 +49,21 @@ release_filegroup( "gci/node.yaml", ], ) + +pkg_tar( + name = "gce-master-manifests", + files = [ + "manifests/abac-authz-policy.jsonl", + "manifests/cluster-autoscaler.manifest", + "manifests/e2e-image-puller.manifest", + "manifests/etcd.manifest", + "manifests/glbc.manifest", + "manifests/kube-addon-manager.yaml", + "manifests/kube-apiserver.manifest", + "manifests/kube-controller-manager.manifest", + "manifests/kube-proxy.manifest", + "manifests/kube-scheduler.manifest", + "manifests/rescheduler.manifest", + ], + mode = "0644", +) diff --git a/cluster/saltbase/salt/kube-admission-controls/limit-range/limit-range.yaml b/cluster/gce/addons/limit-range/limit-range.yaml similarity index 100% rename from cluster/saltbase/salt/kube-admission-controls/limit-range/limit-range.yaml rename to cluster/gce/addons/limit-range/limit-range.yaml diff --git a/cluster/gce/gci/configure-helper.sh b/cluster/gce/gci/configure-helper.sh index 5d22636a5b5..53aaa48fd52 100644 --- a/cluster/gce/gci/configure-helper.sh +++ b/cluster/gce/gci/configure-helper.sh @@ -1334,7 +1334,7 @@ function prepare-kube-proxy-manifest-variables { function start-kube-proxy { echo "Start kube-proxy static pod" prepare-log-file /var/log/kube-proxy.log - local -r src_file="${KUBE_HOME}/kube-manifests/kubernetes/kube-proxy.manifest" + local -r src_file="${KUBE_HOME}/kube-manifests/kubernetes/gci-trusty/kube-proxy.manifest" prepare-kube-proxy-manifest-variables "${src_file}" cp "${src_file}" /etc/kubernetes/manifests @@ -2077,7 +2077,7 @@ EOF sed -i -e "s@{{ *pillar\['dns_server'\] *}}@${DNS_SERVER_IP}@g" "${kubedns_file}" if [[ "${ENABLE_DNS_HORIZONTAL_AUTOSCALER:-}" == "true" ]]; then - setup-addon-manifests "addons" "dns-horizontal-autoscaler" + setup-addon-manifests "addons" "dns-horizontal-autoscaler" "gce" fi } @@ -2225,7 +2225,7 @@ EOF setup-addon-manifests "addons" "node-problem-detector/standalone" "node-problem-detector" fi if echo "${ADMISSION_CONTROL:-}" | grep -q "LimitRanger"; then - setup-addon-manifests "admission-controls" "limit-range" + setup-addon-manifests "admission-controls" "limit-range" "gce" fi if [[ "${NETWORK_POLICY_PROVIDER:-}" == "calico" ]]; then setup-addon-manifests "addons" "calico-policy-controller" @@ -2260,7 +2260,7 @@ function start-image-puller { # Starts kube-registry proxy function start-kube-registry-proxy { echo "Start kube-registry-proxy" - cp "${KUBE_HOME}/kube-manifests/kubernetes/kube-registry-proxy.yaml" /etc/kubernetes/manifests + cp "${KUBE_HOME}/kube-manifests/kubernetes/gci-trusty/kube-registry-proxy.yaml" /etc/kubernetes/manifests } # Starts a l7 loadbalancing controller for ingress. diff --git a/cluster/saltbase/salt/kube-apiserver/abac-authz-policy.jsonl b/cluster/gce/manifests/abac-authz-policy.jsonl similarity index 100% rename from cluster/saltbase/salt/kube-apiserver/abac-authz-policy.jsonl rename to cluster/gce/manifests/abac-authz-policy.jsonl diff --git a/cluster/saltbase/salt/cluster-autoscaler/cluster-autoscaler.manifest b/cluster/gce/manifests/cluster-autoscaler.manifest similarity index 100% rename from cluster/saltbase/salt/cluster-autoscaler/cluster-autoscaler.manifest rename to cluster/gce/manifests/cluster-autoscaler.manifest diff --git a/cluster/saltbase/salt/e2e-image-puller/e2e-image-puller.manifest b/cluster/gce/manifests/e2e-image-puller.manifest similarity index 100% rename from cluster/saltbase/salt/e2e-image-puller/e2e-image-puller.manifest rename to cluster/gce/manifests/e2e-image-puller.manifest diff --git a/cluster/saltbase/salt/etcd/etcd.manifest b/cluster/gce/manifests/etcd.manifest similarity index 100% rename from cluster/saltbase/salt/etcd/etcd.manifest rename to cluster/gce/manifests/etcd.manifest diff --git a/cluster/saltbase/salt/l7-gcp/glbc.manifest b/cluster/gce/manifests/glbc.manifest similarity index 100% rename from cluster/saltbase/salt/l7-gcp/glbc.manifest rename to cluster/gce/manifests/glbc.manifest diff --git a/cluster/saltbase/salt/kube-addons/kube-addon-manager.yaml b/cluster/gce/manifests/kube-addon-manager.yaml similarity index 100% rename from cluster/saltbase/salt/kube-addons/kube-addon-manager.yaml rename to cluster/gce/manifests/kube-addon-manager.yaml diff --git a/cluster/saltbase/salt/kube-apiserver/kube-apiserver.manifest b/cluster/gce/manifests/kube-apiserver.manifest similarity index 100% rename from cluster/saltbase/salt/kube-apiserver/kube-apiserver.manifest rename to cluster/gce/manifests/kube-apiserver.manifest diff --git a/cluster/saltbase/salt/kube-controller-manager/kube-controller-manager.manifest b/cluster/gce/manifests/kube-controller-manager.manifest similarity index 100% rename from cluster/saltbase/salt/kube-controller-manager/kube-controller-manager.manifest rename to cluster/gce/manifests/kube-controller-manager.manifest diff --git a/cluster/saltbase/salt/kube-proxy/kube-proxy.manifest b/cluster/gce/manifests/kube-proxy.manifest similarity index 100% rename from cluster/saltbase/salt/kube-proxy/kube-proxy.manifest rename to cluster/gce/manifests/kube-proxy.manifest diff --git a/cluster/saltbase/salt/kube-registry-proxy/kube-registry-proxy.yaml b/cluster/gce/manifests/kube-registry-proxy.yaml similarity index 100% rename from cluster/saltbase/salt/kube-registry-proxy/kube-registry-proxy.yaml rename to cluster/gce/manifests/kube-registry-proxy.yaml diff --git a/cluster/saltbase/salt/kube-scheduler/kube-scheduler.manifest b/cluster/gce/manifests/kube-scheduler.manifest similarity index 100% rename from cluster/saltbase/salt/kube-scheduler/kube-scheduler.manifest rename to cluster/gce/manifests/kube-scheduler.manifest diff --git a/cluster/saltbase/salt/rescheduler/rescheduler.manifest b/cluster/gce/manifests/rescheduler.manifest similarity index 100% rename from cluster/saltbase/salt/rescheduler/rescheduler.manifest rename to cluster/gce/manifests/rescheduler.manifest diff --git a/cluster/saltbase/BUILD b/cluster/saltbase/BUILD index 13723fb63e3..484ca06ca60 100644 --- a/cluster/saltbase/BUILD +++ b/cluster/saltbase/BUILD @@ -45,42 +45,3 @@ pkg_tar( ":_salt_kube-addons", ], ) - -# The following are used in the kubernetes salt tarball. -pkg_tar( - name = "salt-manifests", - files = [ - "salt/kube-proxy/kube-proxy.manifest", - "salt/kube-registry-proxy/kube-registry-proxy.yaml", - ], - mode = "0644", -) - -pkg_tar( - name = "_kube-admission-controls", - files = glob(["salt/kube-admission-controls/limit-range/**"]), - mode = "0644", - # Maintain limit-range/ subdirectory in tarball - strip_prefix = "./salt/kube-admission-controls/", - visibility = ["//visibility:private"], -) - -pkg_tar( - name = "gci-trusty-salt-manifests", - files = [ - "salt/cluster-autoscaler/cluster-autoscaler.manifest", - "salt/e2e-image-puller/e2e-image-puller.manifest", - "salt/etcd/etcd.manifest", - "salt/kube-addons/kube-addon-manager.yaml", - "salt/kube-apiserver/abac-authz-policy.jsonl", - "salt/kube-apiserver/kube-apiserver.manifest", - "salt/kube-controller-manager/kube-controller-manager.manifest", - "salt/kube-scheduler/kube-scheduler.manifest", - "salt/l7-gcp/glbc.manifest", - "salt/rescheduler/rescheduler.manifest", - ], - mode = "0644", - deps = [ - "_kube-admission-controls", - ], -) From 5f9735de53c0a7f1334d91b59bcd87c6fbe2a06f Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Sat, 13 Jan 2018 09:14:35 -0800 Subject: [PATCH 28/58] cluster: delete saltbase and don't build kubernetes-salt.tar.gz --- build/README.md | 2 - build/lib/release.sh | 39 +- build/release-tars/BUILD | 11 - cluster/BUILD | 1 - .../fluentd-es-configmap.yaml | 11 - cluster/common.sh | 17 - cluster/gce/util.sh | 11 - cluster/saltbase/BUILD | 47 -- cluster/saltbase/README.md | 19 - cluster/saltbase/install.sh | 109 ---- cluster/saltbase/pillar/README.md | 22 - cluster/saltbase/pillar/cluster-params.sls | 4 - cluster/saltbase/pillar/docker-images.sls | 5 - cluster/saltbase/pillar/logging.sls | 1 - cluster/saltbase/pillar/mine.sls | 12 - cluster/saltbase/pillar/privilege.sls | 2 - cluster/saltbase/pillar/systemd.sls | 9 - cluster/saltbase/pillar/top.sls | 8 - cluster/saltbase/reactor/README.md | 6 - .../saltbase/reactor/highstate-masters.sls | 10 - .../saltbase/reactor/highstate-minions.sls | 10 - cluster/saltbase/reactor/highstate-new.sls | 4 - cluster/saltbase/salt/README.md | 29 -- cluster/saltbase/salt/base.sls | 46 -- cluster/saltbase/salt/calico/OWNERS | 6 - cluster/saltbase/salt/calico/node.sls | 9 - .../saltbase/salt/cluster-autoscaler/OWNERS | 12 - .../saltbase/salt/cluster-autoscaler/init.sls | 25 - cluster/saltbase/salt/cni/OWNERS | 8 - cluster/saltbase/salt/cni/init.sls | 26 - .../salt/debian-auto-upgrades/20auto-upgrades | 4 - .../salt/debian-auto-upgrades/init.sls | 13 - cluster/saltbase/salt/docker/default | 8 - cluster/saltbase/salt/docker/docker-defaults | 18 - .../saltbase/salt/docker/docker-healthcheck | 44 -- .../salt/docker/docker-healthcheck.service | 9 - .../salt/docker/docker-healthcheck.timer | 9 - cluster/saltbase/salt/docker/docker-prestart | 22 - cluster/saltbase/salt/docker/docker.list | 1 - cluster/saltbase/salt/docker/docker.service | 21 - cluster/saltbase/salt/docker/init.sls | 493 ------------------ .../saltbase/salt/e2e-image-puller/init.sls | 12 - cluster/saltbase/salt/e2e/init.sls | 28 - cluster/saltbase/salt/etcd/init.sls | 83 --- cluster/saltbase/salt/generate-cert/init.sls | 37 -- .../saltbase/salt/generate-cert/make-cert.sh | 26 - cluster/saltbase/salt/kube-addons/init.sls | 215 -------- .../salt/kube-admission-controls/init.sls | 10 - cluster/saltbase/salt/kube-apiserver/init.sls | 71 --- cluster/saltbase/salt/kube-client-tools.sls | 6 - .../salt/kube-controller-manager/init.sls | 30 -- .../saltbase/salt/kube-master-addons/init.sls | 52 -- .../saltbase/salt/kube-master-addons/initd | 95 ---- .../kube-master-addons.service | 9 - .../kube-master-addons/kube-master-addons.sh | 90 ---- .../saltbase/salt/kube-node-unpacker/init.sls | 67 --- .../saltbase/salt/kube-node-unpacker/initd | 95 ---- .../kube-node-unpacker.service | 9 - .../kube-node-unpacker/kube-node-unpacker.sh | 46 -- cluster/saltbase/salt/kube-proxy/OWNERS | 12 - cluster/saltbase/salt/kube-proxy/init.sls | 40 -- cluster/saltbase/salt/kube-proxy/kubeconfig | 0 .../salt/kube-registry-proxy/init.sls | 8 - cluster/saltbase/salt/kube-scheduler/init.sls | 30 -- cluster/saltbase/salt/kubelet/default | 192 ------- cluster/saltbase/salt/kubelet/init.sls | 106 ---- cluster/saltbase/salt/kubelet/initd | 126 ----- cluster/saltbase/salt/kubelet/kubeconfig | 0 cluster/saltbase/salt/kubelet/kubelet.service | 14 - cluster/saltbase/salt/l7-gcp/OWNERS | 6 - cluster/saltbase/salt/l7-gcp/init.sls | 17 - cluster/saltbase/salt/logrotate/conf | 13 - cluster/saltbase/salt/logrotate/cron | 2 - .../saltbase/salt/logrotate/docker-containers | 10 - cluster/saltbase/salt/logrotate/init.sls | 35 -- cluster/saltbase/salt/ntp/init.sls | 11 - .../opencontrail-networking-master/init.sls | 15 - .../opencontrail-networking-minion/init.sls | 15 - cluster/saltbase/salt/rescheduler/init.sls | 15 - cluster/saltbase/salt/salt-helpers/init.sls | 24 - cluster/saltbase/salt/salt-helpers/pkg-apt | 70 --- cluster/saltbase/salt/salt-helpers/services | 72 --- .../salt/supervisor/docker-checker.sh | 87 ---- cluster/saltbase/salt/supervisor/docker.conf | 6 - cluster/saltbase/salt/supervisor/init.sls | 102 ---- .../salt/supervisor/kube-addons-checker.sh | 34 -- .../saltbase/salt/supervisor/kube-addons.conf | 6 - .../salt/supervisor/kubelet-checker.sh | 37 -- cluster/saltbase/salt/supervisor/kubelet.conf | 6 - .../salt/supervisor/supervisor_watcher.sh | 34 -- cluster/saltbase/salt/top.sls | 73 --- 91 files changed, 3 insertions(+), 3359 deletions(-) delete mode 100644 cluster/saltbase/BUILD delete mode 100644 cluster/saltbase/README.md delete mode 100755 cluster/saltbase/install.sh delete mode 100644 cluster/saltbase/pillar/README.md delete mode 100644 cluster/saltbase/pillar/cluster-params.sls delete mode 100644 cluster/saltbase/pillar/docker-images.sls delete mode 100644 cluster/saltbase/pillar/logging.sls delete mode 100644 cluster/saltbase/pillar/mine.sls delete mode 100644 cluster/saltbase/pillar/privilege.sls delete mode 100644 cluster/saltbase/pillar/systemd.sls delete mode 100644 cluster/saltbase/pillar/top.sls delete mode 100644 cluster/saltbase/reactor/README.md delete mode 100644 cluster/saltbase/reactor/highstate-masters.sls delete mode 100644 cluster/saltbase/reactor/highstate-minions.sls delete mode 100644 cluster/saltbase/reactor/highstate-new.sls delete mode 100644 cluster/saltbase/salt/README.md delete mode 100644 cluster/saltbase/salt/base.sls delete mode 100644 cluster/saltbase/salt/calico/OWNERS delete mode 100644 cluster/saltbase/salt/calico/node.sls delete mode 100644 cluster/saltbase/salt/cluster-autoscaler/OWNERS delete mode 100644 cluster/saltbase/salt/cluster-autoscaler/init.sls delete mode 100644 cluster/saltbase/salt/cni/OWNERS delete mode 100644 cluster/saltbase/salt/cni/init.sls delete mode 100644 cluster/saltbase/salt/debian-auto-upgrades/20auto-upgrades delete mode 100644 cluster/saltbase/salt/debian-auto-upgrades/init.sls delete mode 100644 cluster/saltbase/salt/docker/default delete mode 100644 cluster/saltbase/salt/docker/docker-defaults delete mode 100755 cluster/saltbase/salt/docker/docker-healthcheck delete mode 100644 cluster/saltbase/salt/docker/docker-healthcheck.service delete mode 100644 cluster/saltbase/salt/docker/docker-healthcheck.timer delete mode 100755 cluster/saltbase/salt/docker/docker-prestart delete mode 100644 cluster/saltbase/salt/docker/docker.list delete mode 100644 cluster/saltbase/salt/docker/docker.service delete mode 100644 cluster/saltbase/salt/docker/init.sls delete mode 100644 cluster/saltbase/salt/e2e-image-puller/init.sls delete mode 100644 cluster/saltbase/salt/e2e/init.sls delete mode 100644 cluster/saltbase/salt/etcd/init.sls delete mode 100644 cluster/saltbase/salt/generate-cert/init.sls delete mode 100755 cluster/saltbase/salt/generate-cert/make-cert.sh delete mode 100644 cluster/saltbase/salt/kube-addons/init.sls delete mode 100644 cluster/saltbase/salt/kube-admission-controls/init.sls delete mode 100644 cluster/saltbase/salt/kube-apiserver/init.sls delete mode 100644 cluster/saltbase/salt/kube-client-tools.sls delete mode 100644 cluster/saltbase/salt/kube-controller-manager/init.sls delete mode 100644 cluster/saltbase/salt/kube-master-addons/init.sls delete mode 100644 cluster/saltbase/salt/kube-master-addons/initd delete mode 100644 cluster/saltbase/salt/kube-master-addons/kube-master-addons.service delete mode 100755 cluster/saltbase/salt/kube-master-addons/kube-master-addons.sh delete mode 100644 cluster/saltbase/salt/kube-node-unpacker/init.sls delete mode 100755 cluster/saltbase/salt/kube-node-unpacker/initd delete mode 100644 cluster/saltbase/salt/kube-node-unpacker/kube-node-unpacker.service delete mode 100755 cluster/saltbase/salt/kube-node-unpacker/kube-node-unpacker.sh delete mode 100644 cluster/saltbase/salt/kube-proxy/OWNERS delete mode 100644 cluster/saltbase/salt/kube-proxy/init.sls delete mode 100644 cluster/saltbase/salt/kube-proxy/kubeconfig delete mode 100644 cluster/saltbase/salt/kube-registry-proxy/init.sls delete mode 100644 cluster/saltbase/salt/kube-scheduler/init.sls delete mode 100644 cluster/saltbase/salt/kubelet/default delete mode 100644 cluster/saltbase/salt/kubelet/init.sls delete mode 100644 cluster/saltbase/salt/kubelet/initd delete mode 100644 cluster/saltbase/salt/kubelet/kubeconfig delete mode 100644 cluster/saltbase/salt/kubelet/kubelet.service delete mode 100644 cluster/saltbase/salt/l7-gcp/OWNERS delete mode 100644 cluster/saltbase/salt/l7-gcp/init.sls delete mode 100644 cluster/saltbase/salt/logrotate/conf delete mode 100755 cluster/saltbase/salt/logrotate/cron delete mode 100644 cluster/saltbase/salt/logrotate/docker-containers delete mode 100644 cluster/saltbase/salt/logrotate/init.sls delete mode 100644 cluster/saltbase/salt/ntp/init.sls delete mode 100644 cluster/saltbase/salt/opencontrail-networking-master/init.sls delete mode 100644 cluster/saltbase/salt/opencontrail-networking-minion/init.sls delete mode 100644 cluster/saltbase/salt/rescheduler/init.sls delete mode 100644 cluster/saltbase/salt/salt-helpers/init.sls delete mode 100644 cluster/saltbase/salt/salt-helpers/pkg-apt delete mode 100644 cluster/saltbase/salt/salt-helpers/services delete mode 100755 cluster/saltbase/salt/supervisor/docker-checker.sh delete mode 100644 cluster/saltbase/salt/supervisor/docker.conf delete mode 100644 cluster/saltbase/salt/supervisor/init.sls delete mode 100644 cluster/saltbase/salt/supervisor/kube-addons-checker.sh delete mode 100644 cluster/saltbase/salt/supervisor/kube-addons.conf delete mode 100755 cluster/saltbase/salt/supervisor/kubelet-checker.sh delete mode 100644 cluster/saltbase/salt/supervisor/kubelet.conf delete mode 100644 cluster/saltbase/salt/supervisor/supervisor_watcher.sh delete mode 100644 cluster/saltbase/salt/top.sls diff --git a/build/README.md b/build/README.md index 60f37fb7019..cd453e3cc42 100644 --- a/build/README.md +++ b/build/README.md @@ -100,12 +100,10 @@ The main output is a tar file: `kubernetes.tar.gz`. This includes: * Examples * Cluster deployment scripts for various clouds * Tar file containing all server binaries -* Tar file containing salt deployment tree shared across multiple cloud deployments. In addition, there are some other tar files that are created: * `kubernetes-client-*.tar.gz` Client binaries for a specific platform. * `kubernetes-server-*.tar.gz` Server binaries for a specific platform. -* `kubernetes-salt.tar.gz` The salt script/tree shared across multiple deployment scripts. When building final release tars, they are first staged into `_output/release-stage` before being tar'd up and put into `_output/release-tars`. diff --git a/build/lib/release.sh b/build/lib/release.sh index 1fd9296fd01..f02444d537c 100644 --- a/build/lib/release.sh +++ b/build/lib/release.sh @@ -78,7 +78,6 @@ function kube::release::package_tarballs() { mkdir -p "${RELEASE_TARS}" kube::release::package_src_tarball & kube::release::package_client_tarballs & - kube::release::package_salt_tarball & kube::release::package_kube_manifests_tarball & kube::util::wait-for-jobs || { kube::log::error "previous tarball phase failed"; return 1; } @@ -359,35 +358,7 @@ function kube::release::create_docker_images_for_server() { } -# Package up the salt configuration tree. This is an optional helper to getting -# a cluster up and running. -function kube::release::package_salt_tarball() { - kube::log::status "Building tarball: salt" - - local release_stage="${RELEASE_STAGE}/salt/kubernetes" - rm -rf "${release_stage}" - mkdir -p "${release_stage}" - - cp -R "${KUBE_ROOT}/cluster/saltbase" "${release_stage}/" - - # TODO(#3579): This is a temporary hack. It gathers up the yaml, - # yaml.in, json files in cluster/addons (minus any demos) and overlays - # them into kube-addons, where we expect them. (This pipeline is a - # fancy copy, stripping anything but the files we don't want.) - local objects - objects=$(cd "${KUBE_ROOT}/cluster/addons" && find . \( -name \*.yaml -or -name \*.yaml.in -or -name \*.json \) | grep -v demo) - tar c -C "${KUBE_ROOT}/cluster/addons" ${objects} | tar x -C "${release_stage}/saltbase/salt/kube-addons" - - kube::release::clean_cruft - - local package_name="${RELEASE_TARS}/kubernetes-salt.tar.gz" - kube::release::create_tarball "${package_name}" "${release_stage}/.." -} - -# This will pack kube-system manifests files for distros without using salt -# such as GCI and Ubuntu Trusty. We directly copy manifests from -# cluster/addons and cluster/saltbase/salt. The script of cluster initialization -# will remove the salt configuration and evaluate the variables in the manifests. +# This will pack kube-system manifests files for distros such as COS. function kube::release::package_kube_manifests_tarball() { kube::log::status "Building tarball: manifests" @@ -468,8 +439,7 @@ function kube::release::package_test_tarball() { # using the bundled cluster/get-kube-binaries.sh script). # Included in this tarball: # - Cluster spin up/down scripts and configs for various cloud providers -# - Tarballs for salt configs that are ready to be uploaded -# to master by whatever means appropriate. +# - Tarballs for manifest configs that are ready to be uploaded # - Examples (which may or may not still work) # - The remnants of the docs/ directory function kube::release::package_final_tarball() { @@ -488,13 +458,10 @@ Client binaries are no longer included in the Kubernetes final tarball. Run cluster/get-kube-binaries.sh to download client and server binaries. EOF - # We want everything in /cluster except saltbase. That is only needed on the - # server. + # We want everything in /cluster. cp -R "${KUBE_ROOT}/cluster" "${release_stage}/" - rm -rf "${release_stage}/cluster/saltbase" mkdir -p "${release_stage}/server" - cp "${RELEASE_TARS}/kubernetes-salt.tar.gz" "${release_stage}/server/" cp "${RELEASE_TARS}/kubernetes-manifests.tar.gz" "${release_stage}/server/" cat < "${release_stage}/server/README" Server binary tarballs are no longer included in the Kubernetes final tarball. diff --git a/build/release-tars/BUILD b/build/release-tars/BUILD index 27773468028..9b5beefdc54 100644 --- a/build/release-tars/BUILD +++ b/build/release-tars/BUILD @@ -180,7 +180,6 @@ pkg_tar( build_tar = "@io_kubernetes_build//tools/build_tar", files = [ ":kubernetes-manifests.tar.gz", - ":kubernetes-salt.tar.gz", ], package_dir = "server", visibility = ["//visibility:private"], @@ -216,15 +215,6 @@ pkg_tar( ], ) -pkg_tar( - name = "kubernetes-salt", - build_tar = "@io_kubernetes_build//tools/build_tar", - extension = "tar.gz", - deps = [ - "//cluster/saltbase:salt", - ], -) - release_filegroup( name = "release-tars", srcs = [ @@ -233,7 +223,6 @@ release_filegroup( ":kubernetes-node-%s.tar.gz" % PLATFORM_ARCH_STRING, ":kubernetes-server-%s.tar.gz" % PLATFORM_ARCH_STRING, ":kubernetes-manifests.tar.gz", - ":kubernetes-salt.tar.gz", ":kubernetes-src.tar.gz", ":kubernetes-test.tar.gz", ], diff --git a/cluster/BUILD b/cluster/BUILD index 8dea73c4cd2..ed62e839b49 100644 --- a/cluster/BUILD +++ b/cluster/BUILD @@ -20,7 +20,6 @@ filegroup( "//cluster/images/etcd/rollback:all-srcs", "//cluster/images/hyperkube:all-srcs", "//cluster/images/kubemark:all-srcs", - "//cluster/saltbase:all-srcs", ], tags = ["automanaged"], ) diff --git a/cluster/addons/fluentd-elasticsearch/fluentd-es-configmap.yaml b/cluster/addons/fluentd-elasticsearch/fluentd-es-configmap.yaml index 28ffb1c03b1..fc2079c5864 100644 --- a/cluster/addons/fluentd-elasticsearch/fluentd-es-configmap.yaml +++ b/cluster/addons/fluentd-elasticsearch/fluentd-es-configmap.yaml @@ -129,17 +129,6 @@ data: max_lines 1000 system.input.conf: |- - # Example: - # 2015-12-21 23:17:22,066 [salt.state ][INFO ] Completed state [net.ipv4.ip_forward] at time 23:17:22.066081 - - type tail - format /^(?