diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index b750baac9cb61..5e414192e0025 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -1111,6 +1111,7 @@ func RunKubelet(kubeServer *options.KubeletServer, kubeDeps *kubelet.Dependencie } else { startKubelet(k, podCfg, &kubeServer.KubeletConfiguration, kubeDeps, kubeServer.EnableCAdvisorJSONEndpoints, kubeServer.EnableServer) klog.Info("Started kubelet") + klog.Info("Kubelet compiled with user namespaces support") } return nil } diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 1cf35280df333..7c923ff7433b0 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -40,14 +40,6 @@ const ( // beta: v1.11 DynamicKubeletConfig featuregate.Feature = "DynamicKubeletConfig" - // owner: @pweil- - // alpha: v1.5 - // - // Default userns=host for containers that are using other host namespaces, host mounts, the pod - // contains a privileged container, or specific non-namespaced capabilities (MKNOD, SYS_MODULE, - // SYS_TIME). This should only be enabled if user namespace remapping is enabled in the docker daemon. - ExperimentalHostUserNamespaceDefaultingGate featuregate.Feature = "ExperimentalHostUserNamespaceDefaulting" - // owner: @jiayingz // beta: v1.10 // @@ -559,7 +551,6 @@ func init() { var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{ AppArmor: {Default: true, PreRelease: featuregate.Beta}, DynamicKubeletConfig: {Default: true, PreRelease: featuregate.Beta}, - ExperimentalHostUserNamespaceDefaultingGate: {Default: false, PreRelease: featuregate.Beta}, DevicePlugins: {Default: true, PreRelease: featuregate.Beta}, TaintBasedEvictions: {Default: true, PreRelease: featuregate.Beta}, RotateKubeletServerCertificate: {Default: true, PreRelease: featuregate.Beta}, diff --git a/pkg/kubelet/container/helpers.go b/pkg/kubelet/container/helpers.go index 71475aa9d56e7..d16d0ccd2f582 100644 --- a/pkg/kubelet/container/helpers.go +++ b/pkg/kubelet/container/helpers.go @@ -52,11 +52,14 @@ type RuntimeHelper interface { // of a pod. GetPodCgroupParent(pod *v1.Pod) string GetPodDir(podUID types.UID) string + GetPodVolumesDir(podUID types.UID) string GeneratePodHostNameAndDomain(pod *v1.Pod) (hostname string, hostDomain string, err error) // GetExtraSupplementalGroupsForPod returns a list of the extra // supplemental groups for the Pod. These extra supplemental groups come // from annotations on persistent volumes that the pod depends on. GetExtraSupplementalGroupsForPod(pod *v1.Pod) []int64 + // UserNamespaceForPod returns the mode for the user namespace of the pod passed as argument. + UserNamespaceForPod(pod *v1.Pod) (runtimeapi.NamespaceMode, error) } // ShouldContainerBeRestarted checks whether a container needs to be restarted. diff --git a/pkg/kubelet/container/helpers_test.go b/pkg/kubelet/container/helpers_test.go index 180e8632936c1..490c6b4d5a6b9 100644 --- a/pkg/kubelet/container/helpers_test.go +++ b/pkg/kubelet/container/helpers_test.go @@ -614,3 +614,95 @@ func TestHashContainer(t *testing.T) { assert.Equal(t, tc.expectedHash, hashVal, "the hash value here should not be changed.") } } + +func TestRuntimeConfigInfo(t *testing.T) { + empty := &RuntimeConfigInfo{} + single := &RuntimeConfigInfo{ + UserNamespaceConfig: UserNamespaceConfigInfo{ + UidMappings: []*UserNSMapping{ + &UserNSMapping{ + ContainerID: 0, + HostID: 100000, + Size: 65536, + }, + }, + GidMappings: []*UserNSMapping{ + &UserNSMapping{ + ContainerID: 0, + HostID: 200000, + Size: 32768, + }, + }, + }, + } + + testCases := []struct { + config *RuntimeConfigInfo + uid uint32 + gid uint32 + expectedSupported bool + expectedEnabled bool + expectedUid uint32 + expectedGid uint32 + expectedError bool + }{ + { + config: empty, + expectedSupported: false, + expectedEnabled: false, + expectedError: true, + }, + { + config: single, + expectedSupported: true, + expectedEnabled: true, + expectedError: false, + uid: 0, + expectedUid: 100000, + gid: 0, + expectedGid: 200000, + }, + { + config: single, + expectedSupported: true, + expectedEnabled: true, + expectedError: false, + uid: 65535, + expectedUid: 165535, + gid: 32767, + expectedGid: 232767, + }, + { + config: single, + expectedSupported: true, + expectedEnabled: true, + expectedError: true, + uid: 65536, + gid: 32768, + }, + } + + for _, tc := range testCases { + actualSupported := tc.config.IsUserNamespaceSupported() + assert.Equal(t, tc.expectedSupported, actualSupported) + + actualEnabled := tc.config.IsUserNamespaceEnabled() + assert.Equal(t, tc.expectedSupported, actualEnabled) + + actualUid, err := tc.config.GetHostUIDFor(tc.uid) + if tc.expectedError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.expectedUid, actualUid) + } + + actualGid, err := tc.config.GetHostGIDFor(tc.gid) + if tc.expectedError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.expectedGid, actualGid) + } + } +} diff --git a/pkg/kubelet/container/runtime.go b/pkg/kubelet/container/runtime.go index 71f6dc20f7ef6..29734f960e3a8 100644 --- a/pkg/kubelet/container/runtime.go +++ b/pkg/kubelet/container/runtime.go @@ -115,6 +115,8 @@ type Runtime interface { // This method just proxies a new runtimeConfig with the updated // CIDR value down to the runtime shim. UpdatePodCIDR(podCIDR string) error + // GetRuntimeConfigInfo returns runtime's configuration details, eg: if user-namespaces are enabled or not + GetRuntimeConfigInfo() (*RuntimeConfigInfo, error) } // StreamingRuntime is the interface implemented by runtimes that handle the serving of the @@ -422,12 +424,6 @@ type RunContainerOptions struct { ReadOnly bool // hostname for pod containers Hostname string - // EnableHostUserNamespace sets userns=host when users request host namespaces (pid, ipc, net), - // are using non-namespaced capabilities (mknod, sys_time, sys_module), the pod contains a privileged container, - // or using host path volumes. - // This should only be enabled when the container runtime is performing user remapping AND if the - // experimental behavior is desired. - EnableHostUserNamespace bool } // VolumeInfo contains information about the volume. @@ -465,6 +461,68 @@ type RuntimeStatus struct { Conditions []RuntimeCondition } +// RuntimeConfigInfo contains runtime's configuration details, eg: user-namespaces mapping between host and container +type RuntimeConfigInfo struct { + UserNamespaceConfig UserNamespaceConfigInfo +} + +// UserNamespaceConfigInfo contains runtime's user-namespace configuration +type UserNamespaceConfigInfo struct { + UidMappings []*UserNSMapping + GidMappings []*UserNSMapping +} + +// UserNSMaping represents mapping of user-namespaces between host and container +type UserNSMapping struct { + ContainerID uint32 + HostID uint32 + Size uint32 +} + +// IsUserNamespaceEnabled returns true if user-namespace feature is enabled at runtime +func (c *RuntimeConfigInfo) IsUserNamespaceEnabled() bool { + if len(c.UserNamespaceConfig.UidMappings) == 0 { + return false + } + if len(c.UserNamespaceConfig.UidMappings) == 1 && + c.UserNamespaceConfig.UidMappings[0].HostID == uint32(0) && c.UserNamespaceConfig.UidMappings[0].Size == uint32(4294967295) { + return false + } + return true +} + +// IsUserNamespaceSupported returns true if user-namespace feature is supported at runtime +func (c *RuntimeConfigInfo) IsUserNamespaceSupported() bool { + if len(c.UserNamespaceConfig.UidMappings) == 0 { + return false + } + if len(c.UserNamespaceConfig.UidMappings) == 1 && + c.UserNamespaceConfig.UidMappings[0].HostID == uint32(0) && c.UserNamespaceConfig.UidMappings[0].Size == uint32(0) { + return false + } + return true +} + +// GetHostUIDFor returns uid on host usernamespace that is mapped to the given uid in container usernamespace +func (c *RuntimeConfigInfo) GetHostUIDFor(containerUID uint32) (uint32, error) { + for _, mapping := range c.UserNamespaceConfig.UidMappings { + if containerUID >= mapping.ContainerID && containerUID < mapping.ContainerID+mapping.Size { + return mapping.HostID + (containerUID - mapping.ContainerID), nil + } + } + return 0, fmt.Errorf("IdMapping not found for container usernamespace UID %v", containerUID) +} + +// GetHostGIDFor returns gid on host usernamespace that is mapped to the given gid in container usernamespace +func (c *RuntimeConfigInfo) GetHostGIDFor(containerGID uint32) (uint32, error) { + for _, mapping := range c.UserNamespaceConfig.GidMappings { + if containerGID >= mapping.ContainerID && containerGID < mapping.ContainerID+mapping.Size { + return mapping.HostID + (containerGID - mapping.ContainerID), nil + } + } + return 0, fmt.Errorf("IdMapping not found for container usernamespace GID %v", containerGID) +} + // GetRuntimeCondition gets a specified runtime condition from the runtime status. func (r *RuntimeStatus) GetRuntimeCondition(t RuntimeConditionType) *RuntimeCondition { for i := range r.Conditions { diff --git a/pkg/kubelet/container/testing/fake_runtime.go b/pkg/kubelet/container/testing/fake_runtime.go index 1824b8b84b785..0ba67304e4e14 100644 --- a/pkg/kubelet/container/testing/fake_runtime.go +++ b/pkg/kubelet/container/testing/fake_runtime.go @@ -41,23 +41,25 @@ type FakePod struct { // FakeRuntime is a fake container runtime for testing. type FakeRuntime struct { sync.Mutex - CalledFunctions []string - PodList []*FakePod - AllPodList []*FakePod - ImageList []kubecontainer.Image - APIPodStatus v1.PodStatus - PodStatus kubecontainer.PodStatus - StartedPods []string - KilledPods []string - StartedContainers []string - KilledContainers []string - RuntimeStatus *kubecontainer.RuntimeStatus - VersionInfo string - APIVersionInfo string - RuntimeType string - Err error - InspectErr error - StatusErr error + CalledFunctions []string + PodList []*FakePod + AllPodList []*FakePod + ImageList []kubecontainer.Image + APIPodStatus v1.PodStatus + PodStatus kubecontainer.PodStatus + StartedPods []string + KilledPods []string + StartedContainers []string + KilledContainers []string + RuntimeStatus *kubecontainer.RuntimeStatus + RuntimeConfigInfo *kubecontainer.RuntimeConfigInfo + RuntimeConfigInfoErr error + VersionInfo string + APIVersionInfo string + RuntimeType string + Err error + InspectErr error + StatusErr error } const FakeHost = "localhost:12345" @@ -123,6 +125,8 @@ func (f *FakeRuntime) ClearCalls() { f.StartedContainers = []string{} f.KilledContainers = []string{} f.RuntimeStatus = nil + f.RuntimeConfigInfo = nil + f.RuntimeConfigInfoErr = nil f.VersionInfo = "" f.RuntimeType = "" f.Err = nil @@ -205,6 +209,14 @@ func (f *FakeRuntime) Status() (*kubecontainer.RuntimeStatus, error) { return f.RuntimeStatus, f.StatusErr } +func (f *FakeRuntime) GetRuntimeConfigInfo() (*kubecontainer.RuntimeConfigInfo, error) { + f.Lock() + defer f.Unlock() + + f.CalledFunctions = append(f.CalledFunctions, "GetRuntimeConfigInfo") + return f.RuntimeConfigInfo, f.RuntimeConfigInfoErr +} + func (f *FakeRuntime) GetPods(all bool) ([]*kubecontainer.Pod, error) { f.Lock() defer f.Unlock() diff --git a/pkg/kubelet/container/testing/fake_runtime_helper.go b/pkg/kubelet/container/testing/fake_runtime_helper.go index 0009ee61e0b8d..96bd879aecfa1 100644 --- a/pkg/kubelet/container/testing/fake_runtime_helper.go +++ b/pkg/kubelet/container/testing/fake_runtime_helper.go @@ -62,6 +62,14 @@ func (f *FakeRuntimeHelper) GetPodDir(podUID kubetypes.UID) string { return "/poddir/" + string(podUID) } +func (f *FakeRuntimeHelper) GetPodVolumesDir(podUID kubetypes.UID) string { + return f.GetPodDir(podUID) + "/volumes/" +} + +func (f *FakeRuntimeHelper) UserNamespaceForPod(pod *v1.Pod) (runtimeapi.NamespaceMode, error) { + return runtimeapi.NamespaceMode_NODE, nil +} + func (f *FakeRuntimeHelper) GetExtraSupplementalGroupsForPod(pod *v1.Pod) []int64 { return nil } diff --git a/pkg/kubelet/container/testing/runtime_mock.go b/pkg/kubelet/container/testing/runtime_mock.go index aa363649e30a0..a20de28f243b2 100644 --- a/pkg/kubelet/container/testing/runtime_mock.go +++ b/pkg/kubelet/container/testing/runtime_mock.go @@ -67,6 +67,11 @@ func (r *Mock) Status() (*kubecontainer.RuntimeStatus, error) { return args.Get(0).(*kubecontainer.RuntimeStatus), args.Error(0) } +func (r *Mock) GetRuntimeConfigInfo() (*kubecontainer.RuntimeConfigInfo, error) { + args := r.Called() + return args.Get(0).(*kubecontainer.RuntimeConfigInfo), args.Error(1) +} + func (r *Mock) GetPods(all bool) ([]*kubecontainer.Pod, error) { args := r.Called(all) return args.Get(0).([]*kubecontainer.Pod), args.Error(1) diff --git a/pkg/kubelet/dockershim/docker_sandbox.go b/pkg/kubelet/dockershim/docker_sandbox.go index 1824cdbadbf48..4af02c4cd9245 100644 --- a/pkg/kubelet/dockershim/docker_sandbox.go +++ b/pkg/kubelet/dockershim/docker_sandbox.go @@ -464,6 +464,7 @@ func (ds *dockerService) PodSandboxStatus(ctx context.Context, req *runtimeapi.P Network: networkNamespaceMode(r), Pid: pidNamespaceMode(r), Ipc: ipcNamespaceMode(r), + User: userNamespaceMode(r), }, }, }, @@ -690,6 +691,17 @@ func ipcNamespaceMode(container *dockertypes.ContainerJSON) runtimeapi.Namespace return runtimeapi.NamespaceMode_POD } +// userNamespaceMode returns the user runtimeapi.NamespaceMode for this container. +// Supports: POD, NODE +func userNamespaceMode(container *dockertypes.ContainerJSON) runtimeapi.NamespaceMode { + if container != nil && container.HostConfig != nil { + if string(container.HostConfig.UsernsMode) == namespaceModeHost { + return runtimeapi.NamespaceMode_NODE + } + } + return runtimeapi.NamespaceMode_POD +} + func constructPodSandboxCheckpoint(config *runtimeapi.PodSandboxConfig) checkpointmanager.Checkpoint { data := CheckpointData{} for _, pm := range config.GetPortMappings() { diff --git a/pkg/kubelet/dockershim/docker_sandbox_test.go b/pkg/kubelet/dockershim/docker_sandbox_test.go index b34c933746dcc..58e85fa3561b9 100644 --- a/pkg/kubelet/dockershim/docker_sandbox_test.go +++ b/pkg/kubelet/dockershim/docker_sandbox_test.go @@ -93,65 +93,94 @@ func TestListSandboxes(t *testing.T) { // TestSandboxStatus tests the basic lifecycle operations and verify that // the status returned reflects the operations performed. func TestSandboxStatus(t *testing.T) { - ds, fDocker, fClock := newTestDockerService() - labels := map[string]string{"label": "foobar1"} - annotations := map[string]string{"annotation": "abc"} - config := makeSandboxConfigWithLabelsAndAnnotations("foo", "bar", "1", 0, labels, annotations) - r := rand.New(rand.NewSource(0)).Uint32() - podIP := fmt.Sprintf("10.%d.%d.%d", byte(r>>16), byte(r>>8), byte(r)) - - state := runtimeapi.PodSandboxState_SANDBOX_READY - ct := int64(0) - expected := &runtimeapi.PodSandboxStatus{ - State: state, - CreatedAt: ct, - Metadata: config.Metadata, - Network: &runtimeapi.PodSandboxNetworkStatus{Ip: podIP, AdditionalIps: []*runtimeapi.PodIP{}}, - Linux: &runtimeapi.LinuxPodSandboxStatus{ - Namespaces: &runtimeapi.Namespace{ - Options: &runtimeapi.NamespaceOption{ - Pid: runtimeapi.NamespaceMode_CONTAINER, - }, - }, + testCases := []struct { + description string + labels map[string]string + annotations map[string]string + linux *runtimeapi.LinuxPodSandboxStatus + }{ + { + description: "Tests that default value of User namespace option is NamespaceMode_POD", + labels: map[string]string{"label": "foobar1"}, + annotations: map[string]string{"annotation": "abc"}, + linux: &runtimeapi.LinuxPodSandboxStatus{ + Namespaces: &runtimeapi.Namespace{ + Options: &runtimeapi.NamespaceOption{ + Pid: runtimeapi.NamespaceMode_CONTAINER, + User: runtimeapi.NamespaceMode_POD, + }, + }}, + }, + { + description: "Tests that if User namespace option is NamespaceMode_NODE, same is received back in status", + labels: map[string]string{"label": "foobar1"}, + annotations: map[string]string{"annotation": "abc"}, + linux: &runtimeapi.LinuxPodSandboxStatus{ + Namespaces: &runtimeapi.Namespace{ + Options: &runtimeapi.NamespaceOption{ + Pid: runtimeapi.NamespaceMode_CONTAINER, + User: runtimeapi.NamespaceMode_NODE, + }, + }}, }, - Labels: labels, - Annotations: annotations, } + for _, test := range testCases { + ds, fDocker, fClock := newTestDockerService() + config := makeSandboxConfigWithLabelsAndAnnotations("foo", "bar", "1", 0, test.labels, test.annotations) + config.Linux = &runtimeapi.LinuxPodSandboxConfig{ + SecurityContext: &runtimeapi.LinuxSandboxSecurityContext{ + NamespaceOptions: test.linux.Namespaces.Options, + }, + } + r := rand.New(rand.NewSource(0)).Uint32() + podIP := fmt.Sprintf("10.%d.%d.%d", byte(r>>16), byte(r>>8), byte(r)) - // Create the sandbox. - fClock.SetTime(time.Now()) - expected.CreatedAt = fClock.Now().UnixNano() - runResp, err := ds.RunPodSandbox(getTestCTX(), &runtimeapi.RunPodSandboxRequest{Config: config}) - require.NoError(t, err) - id := runResp.PodSandboxId + state := runtimeapi.PodSandboxState_SANDBOX_READY + ct := int64(0) + expected := &runtimeapi.PodSandboxStatus{ + State: state, + CreatedAt: ct, + Metadata: config.Metadata, + Network: &runtimeapi.PodSandboxNetworkStatus{Ip: podIP, AdditionalIps: []*runtimeapi.PodIP{}}, + Linux: test.linux, + Labels: test.labels, + Annotations: test.annotations, + } - // Check internal labels - c, err := fDocker.InspectContainer(id) - assert.NoError(t, err) - assert.Equal(t, c.Config.Labels[containerTypeLabelKey], containerTypeLabelSandbox) - assert.Equal(t, c.Config.Labels[types.KubernetesContainerNameLabel], sandboxContainerName) + // Create the sandbox. + fClock.SetTime(time.Now()) + expected.CreatedAt = fClock.Now().UnixNano() + runResp, err := ds.RunPodSandbox(getTestCTX(), &runtimeapi.RunPodSandboxRequest{Config: config}) + require.NoError(t, err) + id := runResp.PodSandboxId - expected.Id = id // ID is only known after the creation. - statusResp, err := ds.PodSandboxStatus(getTestCTX(), &runtimeapi.PodSandboxStatusRequest{PodSandboxId: id}) - require.NoError(t, err) - assert.Equal(t, expected, statusResp.Status) + // Check internal labels + c, err := fDocker.InspectContainer(id) + assert.NoError(t, err) + assert.Equal(t, c.Config.Labels[containerTypeLabelKey], containerTypeLabelSandbox) + assert.Equal(t, c.Config.Labels[types.KubernetesContainerNameLabel], sandboxContainerName) - // Stop the sandbox. - expected.State = runtimeapi.PodSandboxState_SANDBOX_NOTREADY - _, err = ds.StopPodSandbox(getTestCTX(), &runtimeapi.StopPodSandboxRequest{PodSandboxId: id}) - require.NoError(t, err) - // IP not valid after sandbox stop - expected.Network.Ip = "" - expected.Network.AdditionalIps = []*runtimeapi.PodIP{} - statusResp, err = ds.PodSandboxStatus(getTestCTX(), &runtimeapi.PodSandboxStatusRequest{PodSandboxId: id}) - require.NoError(t, err) - assert.Equal(t, expected, statusResp.Status) + expected.Id = id // ID is only known after the creation. + statusResp, err := ds.PodSandboxStatus(getTestCTX(), &runtimeapi.PodSandboxStatusRequest{PodSandboxId: id}) + require.NoError(t, err) + assert.Equal(t, expected, statusResp.Status) - // Remove the container. - _, err = ds.RemovePodSandbox(getTestCTX(), &runtimeapi.RemovePodSandboxRequest{PodSandboxId: id}) - require.NoError(t, err) - statusResp, err = ds.PodSandboxStatus(getTestCTX(), &runtimeapi.PodSandboxStatusRequest{PodSandboxId: id}) - assert.Error(t, err, fmt.Sprintf("status of sandbox: %+v", statusResp)) + // Stop the sandbox. + expected.State = runtimeapi.PodSandboxState_SANDBOX_NOTREADY + _, err = ds.StopPodSandbox(getTestCTX(), &runtimeapi.StopPodSandboxRequest{PodSandboxId: id}) + require.NoError(t, err) + // IP not valid after sandbox stop + expected.Network.Ip = "" + statusResp, err = ds.PodSandboxStatus(getTestCTX(), &runtimeapi.PodSandboxStatusRequest{PodSandboxId: id}) + require.NoError(t, err) + assert.Equal(t, expected, statusResp.Status) + + // Remove the container. + _, err = ds.RemovePodSandbox(getTestCTX(), &runtimeapi.RemovePodSandboxRequest{PodSandboxId: id}) + require.NoError(t, err) + statusResp, err = ds.PodSandboxStatus(getTestCTX(), &runtimeapi.PodSandboxStatusRequest{PodSandboxId: id}) + assert.Error(t, err, fmt.Sprintf("status of sandbox: %+v", statusResp)) + } } // TestSandboxStatusAfterRestart tests that retrieving sandbox status returns diff --git a/pkg/kubelet/dockershim/docker_service.go b/pkg/kubelet/dockershim/docker_service.go index 0f07a4ca23601..6ad819bbd2a08 100644 --- a/pkg/kubelet/dockershim/docker_service.go +++ b/pkg/kubelet/dockershim/docker_service.go @@ -19,9 +19,13 @@ package dockershim import ( "context" "fmt" + "io/ioutil" "net/http" "path" "path/filepath" + "regexp" + "strconv" + "strings" "sync" "time" @@ -81,6 +85,10 @@ const ( // to kubelet behavior and system settings in addition to any API flags that may be introduced. ) +var ( + linuxIDMappingRegexp = regexp.MustCompile("([aA-zZ]+):([0-9]+):([0-9]+)") +) + // CRIService includes all methods necessary for a CRI server. type CRIService interface { runtimeapi.RuntimeServiceServer @@ -319,6 +327,102 @@ type dockerService struct { // TODO: handle context. +// GetRuntimeConfigInfo returns the runtime config. +func (ds *dockerService) GetRuntimeConfigInfo(_ context.Context, r *runtimeapi.GetRuntimeConfigInfoRequest) (*runtimeapi.GetRuntimeConfigInfoResponse, error) { + dockerInfo, err := ds.client.Info() + if err != nil { + return nil, fmt.Errorf("failed to execute Info() call to the Docker client: %v", err) + } + uidMapping := &runtimeapi.LinuxIDMapping{ContainerId: uint32(0)} + gidMapping := &runtimeapi.LinuxIDMapping{ContainerId: uint32(0)} + + if isUserNsEnabled(dockerInfo) { + remappedNonRootHostID, err := getRemappedNonRootHostID(dockerInfo) + if err != nil { + return nil, fmt.Errorf("failed to get remappedNonRootHostID: %v", err) + } + uidMappingSize, gidMappingSize, err := getUserNsMappingSizes(remappedNonRootHostID) + if err != nil { + return nil, fmt.Errorf("failed to get user-namespace mapping sizes: %v", err) + } + + uidMapping.HostId = remappedNonRootHostID + gidMapping.HostId = remappedNonRootHostID + uidMapping.Size_ = uidMappingSize + gidMapping.Size_ = gidMappingSize + } else { + uidMapping.Size_ = uint32(4294967295) + gidMapping.Size_ = uint32(4294967295) + } + + linuxConfig := &runtimeapi.LinuxUserNamespaceConfig{ + UidMappings: []*runtimeapi.LinuxIDMapping{uidMapping}, + GidMappings: []*runtimeapi.LinuxIDMapping{gidMapping}, + } + activeRuntimeConfig := &runtimeapi.ActiveRuntimeConfig{UserNamespaceConfig: linuxConfig} + return &runtimeapi.GetRuntimeConfigInfoResponse{RuntimeConfig: activeRuntimeConfig}, nil +} + +// isUserNsEnabled parses docker info. Returns true if user-namespace feature is found to enabled, otherwise false +func isUserNsEnabled(dockerInfo *dockertypes.Info) bool { + for _, secOpt := range dockerInfo.SecurityOptions { + if strings.Contains(secOpt, "userns") { + return true + } + } + return false +} + +// getRemappedNonRootHostID parses docker info to determine ID on the host usernamespace which is mapped to {U/G}ID 0 in the container user-namespace +func getRemappedNonRootHostID(dockerInfo *dockertypes.Info) (uint32, error) { + remappedNonRootHostID64, err := strconv.ParseUint(strings.Split(path.Base(dockerInfo.DockerRootDir), ".")[0], 10, 0) + if err != nil { + return uint32(0), fmt.Errorf("failed to parse DockerRootDir, %v: %v", dockerInfo.DockerRootDir, err) + } + return uint32(remappedNonRootHostID64), nil +} + +// getUserNsMappingSizes return uid and gid mapping sizes +func getUserNsMappingSizes(remappedNonRootHostID uint32) (uint32, uint32, error) { + mappings, err := ioutil.ReadFile("/etc/subuid") + if err != nil { + return 0, 0, fmt.Errorf("failed to read /etc/subuid: %v", err) + } + uidMappingSize, err := getIDMappingSize(mappings, remappedNonRootHostID) + if err != nil { + return 0, 0, fmt.Errorf("failed to get uid mapping size: %v", err) + } + + mappings, err = ioutil.ReadFile("/etc/subgid") + if err != nil { + return 0, 0, fmt.Errorf("failed to read /etc/subgid: %v", err) + } + gidMappingSize, err := getIDMappingSize(mappings, remappedNonRootHostID) + if err != nil { + return 0, 0, fmt.Errorf("failed to get gid mapping size: %v", err) + } + return uidMappingSize, gidMappingSize, nil +} + +// getIDMappingSize parses input byte array and returns mapping size +func getIDMappingSize(mappings []byte, hostID uint32) (uint32, error) { + matches := linuxIDMappingRegexp.FindAllSubmatch(mappings, -1) + for _, match := range matches { + uid, err := strconv.ParseUint(string(match[2]), 10, 32) + if err != nil { + return 0, fmt.Errorf("error in parsing linux user-namespace mapping entry: %s", match) + } + if uint32(uid) == hostID { + size, err := strconv.ParseUint(string(match[3]), 10, 32) + if err != nil { + return 0, fmt.Errorf("error in parsing linux user-namespace mapping entry: %s", match) + } + return uint32(size), nil + } + } + return 0, fmt.Errorf("could not find user-namespace mapping entry for ID %v", hostID) +} + // Version returns the runtime name, runtime version and runtime API version func (ds *dockerService) Version(_ context.Context, r *runtimeapi.VersionRequest) (*runtimeapi.VersionResponse, error) { v, err := ds.getDockerVersion() diff --git a/pkg/kubelet/dockershim/security_context.go b/pkg/kubelet/dockershim/security_context.go index d1ffbf78ea852..372dab2254cb0 100644 --- a/pkg/kubelet/dockershim/security_context.go +++ b/pkg/kubelet/dockershim/security_context.go @@ -170,6 +170,9 @@ func modifyCommonNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, hostConfig // modifyHostOptionsForSandbox applies NetworkMode/UTSMode to sandbox's dockercontainer.HostConfig. func modifyHostOptionsForSandbox(nsOpts *runtimeapi.NamespaceOption, network *knetwork.PluginManager, hc *dockercontainer.HostConfig) { + if nsOpts.GetUser() == runtimeapi.NamespaceMode_NODE { + hc.UsernsMode = namespaceModeHost + } if nsOpts.GetIpc() == runtimeapi.NamespaceMode_NODE { hc.IpcMode = namespaceModeHost } @@ -199,6 +202,9 @@ func modifyHostOptionsForContainer(nsOpts *runtimeapi.NamespaceOption, podSandbo hc.NetworkMode = dockercontainer.NetworkMode(sandboxNSMode) hc.IpcMode = dockercontainer.IpcMode(sandboxNSMode) hc.UTSMode = "" + if nsOpts.GetUser() == runtimeapi.NamespaceMode_NODE { + hc.UsernsMode = namespaceModeHost + } if nsOpts.GetNetwork() == runtimeapi.NamespaceMode_NODE { hc.UTSMode = namespaceModeHost diff --git a/pkg/kubelet/dockershim/security_context_test.go b/pkg/kubelet/dockershim/security_context_test.go index 3ce1366205d42..06d5ab9b11c25 100644 --- a/pkg/kubelet/dockershim/security_context_test.go +++ b/pkg/kubelet/dockershim/security_context_test.go @@ -346,6 +346,16 @@ func TestModifySandboxNamespaceOptions(t *testing.T) { NetworkMode: "default", }, }, + { + name: "Host User NamespaceOption", + nsOpt: &runtimeapi.NamespaceOption{ + User: runtimeapi.NamespaceMode_NODE, + }, + expected: &dockercontainer.HostConfig{ + NetworkMode: "default", + UsernsMode: namespaceModeHost, + }, + }, } for _, tc := range cases { dockerCfg := &dockercontainer.HostConfig{} @@ -396,6 +406,18 @@ func TestModifyContainerNamespaceOptions(t *testing.T) { PidMode: namespaceModeHost, }, }, + { + name: "Host User NamespaceOption", + nsOpt: &runtimeapi.NamespaceOption{ + User: runtimeapi.NamespaceMode_NODE, + }, + expected: &dockercontainer.HostConfig{ + NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), + IpcMode: dockercontainer.IpcMode(sandboxNSMode), + PidMode: dockercontainer.PidMode(sandboxNSMode), + UsernsMode: namespaceModeHost, + }, + }, } for _, tc := range cases { dockerCfg := &dockercontainer.HostConfig{} diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 307df7e97760c..e9694702753ff 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -492,57 +492,56 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, } klet := &Kubelet{ - hostname: hostname, - hostnameOverridden: len(hostnameOverride) > 0, - nodeName: nodeName, - kubeClient: kubeDeps.KubeClient, - heartbeatClient: kubeDeps.HeartbeatClient, - onRepeatedHeartbeatFailure: kubeDeps.OnHeartbeatFailure, - rootDirectory: rootDirectory, - resyncInterval: kubeCfg.SyncFrequency.Duration, - sourcesReady: config.NewSourcesReady(kubeDeps.PodConfig.SeenAllSources), - registerNode: registerNode, - registerWithTaints: registerWithTaints, - registerSchedulable: registerSchedulable, - dnsConfigurer: dns.NewConfigurer(kubeDeps.Recorder, nodeRef, parsedNodeIP, clusterDNS, kubeCfg.ClusterDomain, kubeCfg.ResolverConfig), - serviceLister: serviceLister, - nodeLister: nodeLister, - masterServiceNamespace: masterServiceNamespace, - streamingConnectionIdleTimeout: kubeCfg.StreamingConnectionIdleTimeout.Duration, - recorder: kubeDeps.Recorder, - cadvisor: kubeDeps.CAdvisorInterface, - cloud: kubeDeps.Cloud, - externalCloudProvider: cloudprovider.IsExternal(cloudProvider), - providerID: providerID, - nodeRef: nodeRef, - nodeLabels: nodeLabels, - nodeStatusUpdateFrequency: kubeCfg.NodeStatusUpdateFrequency.Duration, - nodeStatusReportFrequency: kubeCfg.NodeStatusReportFrequency.Duration, - os: kubeDeps.OSInterface, - oomWatcher: oomWatcher, - cgroupsPerQOS: kubeCfg.CgroupsPerQOS, - cgroupRoot: kubeCfg.CgroupRoot, - mounter: kubeDeps.Mounter, - hostutil: kubeDeps.HostUtil, - subpather: kubeDeps.Subpather, - maxPods: int(kubeCfg.MaxPods), - podsPerCore: int(kubeCfg.PodsPerCore), - syncLoopMonitor: atomic.Value{}, - daemonEndpoints: daemonEndpoints, - containerManager: kubeDeps.ContainerManager, - containerRuntimeName: containerRuntime, - redirectContainerStreaming: crOptions.RedirectContainerStreaming, - nodeIP: parsedNodeIP, - nodeIPValidator: validateNodeIP, - clock: clock.RealClock{}, - enableControllerAttachDetach: kubeCfg.EnableControllerAttachDetach, - iptClient: utilipt.New(utilexec.New(), protocol), - makeIPTablesUtilChains: kubeCfg.MakeIPTablesUtilChains, - iptablesMasqueradeBit: int(kubeCfg.IPTablesMasqueradeBit), - iptablesDropBit: int(kubeCfg.IPTablesDropBit), - experimentalHostUserNamespaceDefaulting: utilfeature.DefaultFeatureGate.Enabled(features.ExperimentalHostUserNamespaceDefaultingGate), - keepTerminatedPodVolumes: keepTerminatedPodVolumes, - nodeStatusMaxImages: nodeStatusMaxImages, + hostname: hostname, + hostnameOverridden: len(hostnameOverride) > 0, + nodeName: nodeName, + kubeClient: kubeDeps.KubeClient, + heartbeatClient: kubeDeps.HeartbeatClient, + onRepeatedHeartbeatFailure: kubeDeps.OnHeartbeatFailure, + rootDirectory: rootDirectory, + resyncInterval: kubeCfg.SyncFrequency.Duration, + sourcesReady: config.NewSourcesReady(kubeDeps.PodConfig.SeenAllSources), + registerNode: registerNode, + registerWithTaints: registerWithTaints, + registerSchedulable: registerSchedulable, + dnsConfigurer: dns.NewConfigurer(kubeDeps.Recorder, nodeRef, parsedNodeIP, clusterDNS, kubeCfg.ClusterDomain, kubeCfg.ResolverConfig), + serviceLister: serviceLister, + nodeLister: nodeLister, + masterServiceNamespace: masterServiceNamespace, + streamingConnectionIdleTimeout: kubeCfg.StreamingConnectionIdleTimeout.Duration, + recorder: kubeDeps.Recorder, + cadvisor: kubeDeps.CAdvisorInterface, + cloud: kubeDeps.Cloud, + externalCloudProvider: cloudprovider.IsExternal(cloudProvider), + providerID: providerID, + nodeRef: nodeRef, + nodeLabels: nodeLabels, + nodeStatusUpdateFrequency: kubeCfg.NodeStatusUpdateFrequency.Duration, + nodeStatusReportFrequency: kubeCfg.NodeStatusReportFrequency.Duration, + os: kubeDeps.OSInterface, + oomWatcher: oomWatcher, + cgroupsPerQOS: kubeCfg.CgroupsPerQOS, + cgroupRoot: kubeCfg.CgroupRoot, + mounter: kubeDeps.Mounter, + hostutil: kubeDeps.HostUtil, + subpather: kubeDeps.Subpather, + maxPods: int(kubeCfg.MaxPods), + podsPerCore: int(kubeCfg.PodsPerCore), + syncLoopMonitor: atomic.Value{}, + daemonEndpoints: daemonEndpoints, + containerManager: kubeDeps.ContainerManager, + containerRuntimeName: containerRuntime, + redirectContainerStreaming: crOptions.RedirectContainerStreaming, + nodeIP: parsedNodeIP, + nodeIPValidator: validateNodeIP, + clock: clock.RealClock{}, + enableControllerAttachDetach: kubeCfg.EnableControllerAttachDetach, + iptClient: utilipt.New(utilexec.New(), protocol), + makeIPTablesUtilChains: kubeCfg.MakeIPTablesUtilChains, + iptablesMasqueradeBit: int(kubeCfg.IPTablesMasqueradeBit), + iptablesDropBit: int(kubeCfg.IPTablesDropBit), + keepTerminatedPodVolumes: keepTerminatedPodVolumes, + nodeStatusMaxImages: nodeStatusMaxImages, } if klet.cloud != nil { @@ -570,10 +569,6 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, klet.secretManager = secretManager klet.configMapManager = configMapManager - if klet.experimentalHostUserNamespaceDefaulting { - klog.Infof("Experimental host user namespace defaulting is enabled.") - } - machineInfo, err := klet.cadvisor.MachineInfo() if err != nil { return nil, err @@ -1197,13 +1192,6 @@ type Kubelet struct { // The handler serving CRI streaming calls (exec/attach/port-forward). criHandler http.Handler - // experimentalHostUserNamespaceDefaulting sets userns=true when users request host namespaces (pid, ipc, net), - // are using non-namespaced capabilities (mknod, sys_time, sys_module), the pod contains a privileged container, - // or using host path volumes. - // This should only be enabled when the container runtime is performing user remapping AND if the - // experimental behavior is desired. - experimentalHostUserNamespaceDefaulting bool - // dockerLegacyService contains some legacy methods for backward compatibility. // It should be set only when docker is using non json-file logging driver. dockerLegacyService dockershim.DockerLegacyService @@ -1687,6 +1675,7 @@ func (kl *Kubelet) syncPod(o syncPodOptions) error { // Call the container runtime's SyncPod callback result := kl.containerRuntime.SyncPod(pod, podStatus, pullSecrets, kl.backOff) + kl.reasonCache.Update(pod.UID, result) if err := result.Error(); err != nil { // Do not return error if the only failures were pods in backoff @@ -1794,6 +1783,11 @@ func (kl *Kubelet) canAdmitPod(pods []*v1.Pod, pod *v1.Pod) (bool, string, strin } } + // TODO: Implement as an admit handler? + if _, err := kl.UserNamespaceForPod(pod); err != nil { + return false, "UsernsUnsupported", err.Error() + } + return true, "", "" } diff --git a/pkg/kubelet/kubelet_getters.go b/pkg/kubelet/kubelet_getters.go index 3dfed31904d4c..345072776c2b0 100644 --- a/pkg/kubelet/kubelet_getters.go +++ b/pkg/kubelet/kubelet_getters.go @@ -108,6 +108,13 @@ func (kl *Kubelet) getPodVolumeSubpathsDir(podUID types.UID) string { return filepath.Join(kl.getPodDir(podUID), config.DefaultKubeletVolumeSubpathsDirName) } +// getPodVolumesDir returns the full path to the per-pod data directory under +// which volumes are created for the specified pod. This directory may not +// exist if the pod does not exist. +func (kl *Kubelet) GetPodVolumesDir(podUID types.UID) string { + return kl.getPodVolumesDir(podUID) +} + // getPodVolumesDir returns the full path to the per-pod data directory under // which volumes are created for the specified pod. This directory may not // exist if the pod does not exist. diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index bb109753e167d..58ef3942a4ce7 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -70,6 +70,18 @@ import ( const ( managedHostsHeader = "# Kubernetes-managed hosts file.\n" managedHostsHeaderWithHostNetwork = "# Kubernetes-managed hosts file (host network).\n" + + // Kinvolk alpha annotation for user namespaces + kinvolkUsernsAnn = "alpha.kinvolk.io/userns" +) + +type UsernsAnn int + +const ( + UsernsInvalid UsernsAnn = iota + UsernsRuntimeDefault + UsernsPod + UsernsNode ) // Get a list of pods that have data directories. @@ -492,11 +504,6 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *v1.Pod, container *v1.Contai } } - // only do this check if the experimental behavior is enabled, otherwise allow it to default to false - if kl.experimentalHostUserNamespaceDefaulting { - opts.EnableHostUserNamespace = kl.enableHostUserNamespace(pod) - } - return opts, cleanupAction, nil } @@ -1735,6 +1742,9 @@ func (kl *Kubelet) cleanupOrphanedPodCgroups(cgroupPods map[types.UID]cm.CgroupN // or it will not have the correct capabilities in the namespace. This means that host user namespace // is enabled per pod, not per container. func (kl *Kubelet) enableHostUserNamespace(pod *v1.Pod) bool { + if pod == nil { + return false + } if kubecontainer.HasPrivilegedContainer(pod) || hasHostNamespace(pod) || hasHostVolume(pod) || hasNonNamespacedCapability(pod) || kl.hasHostMountPVC(pod) { return true @@ -1769,9 +1779,6 @@ func hasHostVolume(pod *v1.Pod) bool { // hasHostNamespace returns true if hostIPC, hostNetwork, or hostPID are set to true. func hasHostNamespace(pod *v1.Pod) bool { - if pod.Spec.SecurityContext == nil { - return false - } return pod.Spec.HostIPC || pod.Spec.HostNetwork || pod.Spec.HostPID } @@ -1798,3 +1805,55 @@ func (kl *Kubelet) hasHostMountPVC(pod *v1.Pod) bool { } return false } + +func (kl *Kubelet) UserNamespaceForPod(pod *v1.Pod) (runtimeapi.NamespaceMode, error) { + config, err := kl.containerRuntime.GetRuntimeConfigInfo() + if err != nil { + return runtimeapi.NamespaceMode_NODE, fmt.Errorf("user namespace can't be enabled: %v", err) + } + + runtimeEnabled := config != nil && config.IsUserNamespaceSupported() && config.IsUserNamespaceEnabled() + userns := getUserNsAnnotation(pod) + + switch userns { + case UsernsRuntimeDefault: + if runtimeEnabled && !kl.enableHostUserNamespace(pod) { + return runtimeapi.NamespaceMode_POD, nil + } + return runtimeapi.NamespaceMode_NODE, nil + case UsernsPod: + if hasHostNamespace(pod) { + kl.recorder.Eventf(pod, v1.EventTypeWarning, "UserNsWarning", "User namespace mode is 'Pod' and PodSpec shares a host namespace.") + } + if !runtimeEnabled { + return runtimeapi.NamespaceMode_NODE, fmt.Errorf("runtime doesn't support user namespaces") + } + return runtimeapi.NamespaceMode_POD, nil + case UsernsNode: + return runtimeapi.NamespaceMode_NODE, nil + default: + return runtimeapi.NamespaceMode_NODE, fmt.Errorf("invalid value for the %q annotation", kinvolkUsernsAnn) + } +} + +// getUserNsAnnotation returns the value of the user namespace annotation +func getUserNsAnnotation(pod *v1.Pod) UsernsAnn { + if pod == nil { + return UsernsRuntimeDefault + } + userns, ok := pod.Annotations[kinvolkUsernsAnn] + if !ok { + return UsernsRuntimeDefault + } + + switch userns { + case "pod": + return UsernsPod + case "node": + return UsernsNode + case "runtimeDefault": + return UsernsRuntimeDefault + default: + return UsernsInvalid + } +} diff --git a/pkg/kubelet/kubelet_pods_test.go b/pkg/kubelet/kubelet_pods_test.go index a542845c46e04..795c7ae6ee49a 100644 --- a/pkg/kubelet/kubelet_pods_test.go +++ b/pkg/kubelet/kubelet_pods_test.go @@ -37,6 +37,7 @@ import ( core "k8s.io/client-go/testing" "k8s.io/client-go/tools/record" featuregatetesting "k8s.io/component-base/featuregate/testing" + runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" // TODO: remove this import if // api.Registry.GroupOrDie(v1.GroupName).GroupVersions[0].String() is changed @@ -2385,3 +2386,216 @@ func TestTruncatePodHostname(t *testing.T) { assert.Equal(t, test.output, output) } } + +func TestUserNamespaceForPod(t *testing.T) { + testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) + defer testKubelet.Cleanup() + kubelet := testKubelet.kubelet + + // Runtime supports user namespaces + uidMappings := []*kubecontainer.UserNSMapping{ + &kubecontainer.UserNSMapping{ + ContainerID: 0, + HostID: 1000, + Size: 65536, + }, + } + userNSConfig := kubecontainer.UserNamespaceConfigInfo{ + UidMappings: uidMappings, + GidMappings: uidMappings, + } + // TODO: how to avoid creating a real class and mocking it instead? + testKubelet.fakeRuntime.RuntimeConfigInfo = &kubecontainer.RuntimeConfigInfo{UserNamespaceConfig: userNSConfig} + + for desc, test := range map[string]struct { + input *v1.Pod + expected runtimeapi.NamespaceMode + expectedError bool + }{ + "nil pod -> default v1 namespaces": { + nil, + runtimeapi.NamespaceMode_POD, + false, + }, + "v1.Pod default namespaces": { + &v1.Pod{}, + runtimeapi.NamespaceMode_POD, + false, + }, + "User ns node mode": { + &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + kinvolkUsernsAnn: "node", + }, + }, + }, + runtimeapi.NamespaceMode_NODE, + false, + }, + "Host Namespaces": { + &v1.Pod{ + Spec: v1.PodSpec{ + HostIPC: true, + HostNetwork: true, + HostPID: true, + }, + }, + runtimeapi.NamespaceMode_NODE, + false, + }, + "Host Namespaces and user ns pod mode": { + &v1.Pod{ + Spec: v1.PodSpec{ + HostIPC: true, + HostNetwork: true, + HostPID: true, + }, + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + kinvolkUsernsAnn: "pod", + }, + }, + }, + runtimeapi.NamespaceMode_NODE, + true, + }, + "Privileged container": { + &v1.Pod{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + v1.Container{ + SecurityContext: &v1.SecurityContext { + Privileged: &[]bool{true}[0], + }, + }, + }, + }, + }, + runtimeapi.NamespaceMode_NODE, + false, + }, + "Privileged container user ns pod mode": { + &v1.Pod{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + v1.Container{ + SecurityContext: &v1.SecurityContext { + Privileged: &[]bool{true}[0], + }, + }, + }, + }, + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + kinvolkUsernsAnn: "pod", + }, + }, + }, + runtimeapi.NamespaceMode_NODE, + true, + }, + "Non namespaced capability": { + &v1.Pod{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + v1.Container{ + SecurityContext: &v1.SecurityContext { + Capabilities: &v1.Capabilities { + Add: []v1.Capability { + "MKNOD", "SYS_TIME", "SYS_MODULE", + }, + }, + }, + }, + }, + }, + }, + runtimeapi.NamespaceMode_NODE, + false, + }, + "Non namespaced capability with userns pod": { + &v1.Pod{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + v1.Container{ + SecurityContext: &v1.SecurityContext { + Capabilities: &v1.Capabilities { + Add: []v1.Capability { + "MKNOD", "SYS_TIME", "SYS_MODULE", + }, + }, + }, + }, + }, + }, + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + kinvolkUsernsAnn: "pod", + }, + }, + }, + runtimeapi.NamespaceMode_NODE, + true, + }, + "Host path volume": { + &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume { + v1.Volume { + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{ + Path: "/tmp/anything", + }, + }, + }, + }, + }, + }, + runtimeapi.NamespaceMode_NODE, + false, + }, + "Host path volume with user ns pod": { + &v1.Pod{ + Spec: v1.PodSpec{ + Volumes: []v1.Volume { + v1.Volume { + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{ + Path: "/tmp/anything", + }, + }, + }, + }, + }, + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + kinvolkUsernsAnn: "pod", + }, + }, + }, + runtimeapi.NamespaceMode_NODE, + true, + }, + "Bad userns annotation": { + &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + kinvolkUsernsAnn: "itsbad", + }, + }, + }, + runtimeapi.NamespaceMode_NODE, + true, + }, + } { + t.Logf("TestCase: %s", desc) + actual, err := kubelet.UserNamespaceForPod(test.input) + if test.expectedError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, test.expected, actual) + } + } +} diff --git a/pkg/kubelet/kuberuntime/helpers.go b/pkg/kubelet/kuberuntime/helpers.go index 2d970333b3bd2..7b2b8fb2e003f 100644 --- a/pkg/kubelet/kuberuntime/helpers.go +++ b/pkg/kubelet/kuberuntime/helpers.go @@ -18,6 +18,7 @@ package kuberuntime import ( "fmt" + "os" "path/filepath" "strconv" "strings" @@ -202,6 +203,41 @@ func toKubeRuntimeStatus(status *runtimeapi.RuntimeStatus) *kubecontainer.Runtim return &kubecontainer.RuntimeStatus{Conditions: conditions} } +// toKubeRuntimeConfig converts the runtimeapi.ActiveRuntimeConfig to kubecontainer.RuntimeConfigInfo +func toKubeRuntimeConfig(config *runtimeapi.ActiveRuntimeConfig) *kubecontainer.RuntimeConfigInfo { + usernsConfig := config.GetUserNamespaceConfig() + if usernsConfig == nil { + return &kubecontainer.RuntimeConfigInfo{} + } + uidMappingsRuntime := usernsConfig.GetUidMappings() + if uidMappingsRuntime == nil || len(uidMappingsRuntime) == 0 { + return &kubecontainer.RuntimeConfigInfo{} + } + gidMappingsRuntime := usernsConfig.GetGidMappings() + if gidMappingsRuntime == nil || len(gidMappingsRuntime) == 0 { + return &kubecontainer.RuntimeConfigInfo{} + } + var uidMappings []*kubecontainer.UserNSMapping + var gidMappings []*kubecontainer.UserNSMapping + for _, runtimeMapping := range uidMappingsRuntime { + uidMappings = append(uidMappings, &kubecontainer.UserNSMapping{ + ContainerID: runtimeMapping.ContainerId, + HostID: runtimeMapping.HostId, + Size: runtimeMapping.Size_}) + } + for _, runtimeMapping := range gidMappingsRuntime { + gidMappings = append(gidMappings, &kubecontainer.UserNSMapping{ + ContainerID: runtimeMapping.ContainerId, + HostID: runtimeMapping.HostId, + Size: runtimeMapping.Size_}) + } + userNSConfig := kubecontainer.UserNamespaceConfigInfo{ + UidMappings: uidMappings, + GidMappings: gidMappings, + } + return &kubecontainer.RuntimeConfigInfo{UserNamespaceConfig: userNSConfig} +} + // getSeccompProfileFromAnnotations gets seccomp profile from annotations. // It gets pod's profile if containerName is empty. func (m *kubeGenericRuntimeManager) getSeccompProfileFromAnnotations(annotations map[string]string, containerName string) string { @@ -258,10 +294,58 @@ func pidNamespaceForPod(pod *v1.Pod) runtimeapi.NamespaceMode { // namespacesForPod returns the runtimeapi.NamespaceOption for a given pod. // An empty or nil pod can be used to get the namespace defaults for v1.Pod. -func namespacesForPod(pod *v1.Pod) *runtimeapi.NamespaceOption { +func (m *kubeGenericRuntimeManager) namespacesForPod(pod *v1.Pod) (*runtimeapi.NamespaceOption, error) { + user, err := m.runtimeHelper.UserNamespaceForPod(pod) + if err != nil { + return nil, err + } + return &runtimeapi.NamespaceOption{ Ipc: ipcNamespaceForPod(pod), Network: networkNamespaceForPod(pod), Pid: pidNamespaceForPod(pod), + User: user, + }, nil +} + +// getHostUID returns UID on host namespace which is mapped to given UID on container namespace +func (m *kubeGenericRuntimeManager) getHostUID(containerUID uint32) (uint32, error) { + return m.runtimeConfig.GetHostUIDFor(containerUID) +} + +// getHostUID returns GID on host namespace which is mapped to given GID on container namespace +func (m *kubeGenericRuntimeManager) getHostGID(containerGID uint32) (uint32, error) { + return m.runtimeConfig.GetHostGIDFor(containerGID) +} + +// chownAllFilesAt traverses the directory tree at the give path and chowns the paths to adjust for the remapped usernamespaces +func (m *kubeGenericRuntimeManager) chownAllFilesAt(dir string) error { + var files []string + + err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + files = append(files, path) + return nil + }) + if err != nil { + return err + } + klog.V(5).Infof("Chowned paths %v", files) + for _, file := range files { + containerUID := uint32(0) + containerGID := uint32(0) + uid, err := m.getHostUID(containerUID) + if err != nil { + return fmt.Errorf("Failed to get remapped host UID corresponding to UID 0 in container namespace: %v", err) + } + gid, err := m.getHostGID(containerGID) + if err != nil { + return fmt.Errorf("Failed to get remapped host GID corresponding to GID 0 in container namespace: %v", err) + } + klog.V(5).Infof("Remapped default uid %d, default gid %d path %s", uid, gid, file) + err = os.Lchown(file, int(uid), int(gid)) + if err != nil { + return err + } } + return nil } diff --git a/pkg/kubelet/kuberuntime/helpers_test.go b/pkg/kubelet/kuberuntime/helpers_test.go index e8f26d99bd78f..1061949a84fe1 100644 --- a/pkg/kubelet/kuberuntime/helpers_test.go +++ b/pkg/kubelet/kuberuntime/helpers_test.go @@ -282,6 +282,13 @@ func TestGetSeccompProfileFromAnnotations(t *testing.T) { } func TestNamespacesForPod(t *testing.T) { + _, _, m, err := createTestRuntimeManager() + assert.NoError(t, err) + + // Runtime doesn't support user namespaces + m.runtimeConfigCached = true + m.runtimeConfig = nil + for desc, test := range map[string]struct { input *v1.Pod expected *runtimeapi.NamespaceOption @@ -292,6 +299,7 @@ func TestNamespacesForPod(t *testing.T) { Ipc: runtimeapi.NamespaceMode_POD, Network: runtimeapi.NamespaceMode_POD, Pid: runtimeapi.NamespaceMode_CONTAINER, + User: runtimeapi.NamespaceMode_NODE, }, }, "v1.Pod default namespaces": { @@ -300,6 +308,7 @@ func TestNamespacesForPod(t *testing.T) { Ipc: runtimeapi.NamespaceMode_POD, Network: runtimeapi.NamespaceMode_POD, Pid: runtimeapi.NamespaceMode_CONTAINER, + User: runtimeapi.NamespaceMode_NODE, }, }, "Host Namespaces": { @@ -314,6 +323,7 @@ func TestNamespacesForPod(t *testing.T) { Ipc: runtimeapi.NamespaceMode_NODE, Network: runtimeapi.NamespaceMode_NODE, Pid: runtimeapi.NamespaceMode_NODE, + User: runtimeapi.NamespaceMode_NODE, }, }, "Shared Process Namespace (feature enabled)": { @@ -326,6 +336,7 @@ func TestNamespacesForPod(t *testing.T) { Ipc: runtimeapi.NamespaceMode_POD, Network: runtimeapi.NamespaceMode_POD, Pid: runtimeapi.NamespaceMode_POD, + User: runtimeapi.NamespaceMode_NODE, }, }, "Shared Process Namespace, redundant flag (feature enabled)": { @@ -338,11 +349,13 @@ func TestNamespacesForPod(t *testing.T) { Ipc: runtimeapi.NamespaceMode_POD, Network: runtimeapi.NamespaceMode_POD, Pid: runtimeapi.NamespaceMode_CONTAINER, + User: runtimeapi.NamespaceMode_NODE, }, }, } { t.Logf("TestCase: %s", desc) - actual := namespacesForPod(test.input) + actual, err := m.namespacesForPod(test.input) + assert.NoError(t, err) assert.Equal(t, test.expected, actual) } } diff --git a/pkg/kubelet/kuberuntime/instrumented_services.go b/pkg/kubelet/kuberuntime/instrumented_services.go index 48088346dcd3e..a4ea11d1466e9 100644 --- a/pkg/kubelet/kuberuntime/instrumented_services.go +++ b/pkg/kubelet/kuberuntime/instrumented_services.go @@ -265,6 +265,15 @@ func (in instrumentedRuntimeService) UpdateRuntimeConfig(runtimeConfig *runtimea return err } +func (in instrumentedRuntimeService) GetRuntimeConfigInfo() (*runtimeapi.ActiveRuntimeConfig, error) { + const operation = "get_runtime_config" + defer recordOperation(operation, time.Now()) + + out, err := in.service.GetRuntimeConfigInfo() + recordError(operation, err) + return out, err +} + func (in instrumentedImageManagerService) ListImages(filter *runtimeapi.ImageFilter) ([]*runtimeapi.Image, error) { const operation = "list_images" defer recordOperation(operation, time.Now()) diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager.go b/pkg/kubelet/kuberuntime/kuberuntime_manager.go index a6b301c769f6a..b7ed41963c6f6 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager.go @@ -24,6 +24,8 @@ import ( "time" cadvisorapi "github.com/google/cadvisor/info/v1" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "k8s.io/klog" v1 "k8s.io/api/core/v1" @@ -137,6 +139,10 @@ type kubeGenericRuntimeManager struct { // Cache last per-container error message to reduce log spam logReduction *logreduction.LogReduction + + // cache of runtime configuration eg, user-namespace configuration + runtimeConfig *kubecontainer.RuntimeConfigInfo + runtimeConfigCached bool } // KubeGenericRuntime is a interface contains interfaces for container runtime and command. @@ -312,6 +318,30 @@ func (m *kubeGenericRuntimeManager) Status() (*kubecontainer.RuntimeStatus, erro return toKubeRuntimeStatus(status), nil } +// GetRuntimeConfigInfo returns runtime configuration details cached at runtime manager +// nil is returned if the runtime doesn't support this method. +func (m *kubeGenericRuntimeManager) GetRuntimeConfigInfo() (*kubecontainer.RuntimeConfigInfo, error) { + if m.runtimeConfigCached { + return m.runtimeConfig, nil + } + runtimeConfig, err := m.runtimeService.GetRuntimeConfigInfo() + if err != nil { + // Do not try to call if again if this is not supported in the runtime. + if status, ok := status.FromError(err); ok && status.Code() == codes.Unimplemented { + klog.V(4).Infof("Container runtime doesn't support GetRuntimeConfigInfo()") + m.runtimeConfigCached = true + return toKubeRuntimeConfig(nil), nil + } + return toKubeRuntimeConfig(nil), fmt.Errorf("container runtime info get failed: %v", err) + } + ci := toKubeRuntimeConfig(runtimeConfig) + klog.V(4).Infof("Container runtime config info: %v", ci) + m.runtimeConfig = ci + m.runtimeConfigCached = true + + return ci, nil +} + // GetPods returns a list of containers grouped by pods. The boolean parameter // specifies whether the runtime returns all containers including those already // exited and dead containers (used for garbage collection). @@ -1061,6 +1091,10 @@ func (m *kubeGenericRuntimeManager) SyncPod(pod *v1.Pod, podStatus *kubecontaine return } + if userns, err := m.runtimeHelper.UserNamespaceForPod(pod); err == nil && userns == runtimeapi.NamespaceMode_POD { + m.chownAllFilesAt(m.runtimeHelper.GetPodVolumesDir(pod.UID)) + } + // Helper containing boilerplate common to starting all types of containers. // typeName is a label used to describe this type of container in log messages, // currently: "container", "init container" or "ephemeral container" diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go b/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go index 08d93b2ca4959..164b185afb183 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go @@ -17,6 +17,7 @@ limitations under the License. package kuberuntime import ( + "errors" "path/filepath" "reflect" "sort" @@ -26,6 +27,8 @@ import ( cadvisorapi "github.com/google/cadvisor/info/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -1356,3 +1359,121 @@ func makeBasePodAndStatusWithInitAndEphemeralContainers() (*v1.Pod, *kubecontain }) return pod, status } + +func TestGetRuntimeConfigInfo(t *testing.T) { + service, _, manager, err := createTestRuntimeManager() + assert.NoError(t, err) + + for desc, test := range map[string]struct { + input *runtimeapi.ActiveRuntimeConfig + expected *kubecontainer.RuntimeConfigInfo + expectedError bool + }{ + "nil -> empty RuntimeConfigInfo": { + nil, + &kubecontainer.RuntimeConfigInfo{}, + false, + }, + "Single mapping": { + &runtimeapi.ActiveRuntimeConfig{ + UserNamespaceConfig: &runtimeapi.LinuxUserNamespaceConfig{ + UidMappings: []*runtimeapi.LinuxIDMapping{ + &runtimeapi.LinuxIDMapping{ + ContainerId: 0, + HostId: 1000, + Size_: 65536, + }, + }, + GidMappings: []*runtimeapi.LinuxIDMapping{ + &runtimeapi.LinuxIDMapping{ + ContainerId: 0, + HostId: 1000, + Size_: 65536, + }, + }, + }, + }, + &kubecontainer.RuntimeConfigInfo{ + UserNamespaceConfig: kubecontainer.UserNamespaceConfigInfo{ + UidMappings: []*kubecontainer.UserNSMapping{ + &kubecontainer.UserNSMapping{ + ContainerID: 0, + HostID: 1000, + Size: 65536, + }, + }, + GidMappings: []*kubecontainer.UserNSMapping{ + &kubecontainer.UserNSMapping{ + ContainerID: 0, + HostID: 1000, + Size: 65536, + }, + }, + }, + }, + false, + }, + + } { + t.Logf("TestCase: %s", desc) + service.FakeRuntimeConfigInfo = test.input + // avoid caching + manager.runtimeConfigCached = false + + actual, err := manager.GetRuntimeConfigInfo() + if test.expectedError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, test.expected, actual) + } + } +} + +func TestGetRuntimeConfigInfoCache(t *testing.T) { + service, _, manager, err := createTestRuntimeManager() + assert.NoError(t, err) + + service.FakeRuntimeConfigInfo = &runtimeapi.ActiveRuntimeConfig{} + + _, err = manager.GetRuntimeConfigInfo() + assert.NoError(t, err) + + _, err = manager.GetRuntimeConfigInfo() + assert.NoError(t, err) + + count := 0 + for _, c := range service.Called { + if c == "GetRuntimeConfigInfo" { + count++ + } + } + + assert.Equal(t, count, 1) +} + +func TestGetRuntimeConfigInfoError(t *testing.T) { + service, _, manager, err := createTestRuntimeManager() + assert.NoError(t, err) + + service.FakeRuntimeConfigInfo = &runtimeapi.ActiveRuntimeConfig{} + + // Test any error + service.InjectError("GetRuntimeConfigInfo", errors.New("test error")) + + _, err = manager.GetRuntimeConfigInfo() + assert.Error(t, err) + + // A further call should not fail + _, err = manager.GetRuntimeConfigInfo() + assert.NoError(t, err) + + // Clean up cache + manager.runtimeConfigCached = false + + // Test not implemented grpc error + service.InjectError("GetRuntimeConfigInfo", status.Error(codes.Unimplemented, "non implemented")) + + _, err = manager.GetRuntimeConfigInfo() + assert.NoError(t, err) +} diff --git a/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go b/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go index 07824b3fbfd80..5abce616791d7 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go @@ -167,7 +167,11 @@ func (m *kubeGenericRuntimeManager) generatePodSandboxLinuxConfig(pod *v1.Pod) ( if sc.RunAsGroup != nil { lc.SecurityContext.RunAsGroup = &runtimeapi.Int64Value{Value: int64(*sc.RunAsGroup)} } - lc.SecurityContext.NamespaceOptions = namespacesForPod(pod) + namespaceOptions, err := m.namespacesForPod(pod) + if err != nil { + return nil, err + } + lc.SecurityContext.NamespaceOptions = namespaceOptions if sc.FSGroup != nil { lc.SecurityContext.SupplementalGroups = append(lc.SecurityContext.SupplementalGroups, int64(*sc.FSGroup)) diff --git a/pkg/kubelet/kuberuntime/security_context.go b/pkg/kubelet/kuberuntime/security_context.go index 47d524256da78..60813cc3ccb8e 100644 --- a/pkg/kubelet/kuberuntime/security_context.go +++ b/pkg/kubelet/kuberuntime/security_context.go @@ -51,7 +51,8 @@ func (m *kubeGenericRuntimeManager) determineEffectiveSecurityContext(pod *v1.Po } // set namespace options and supplemental groups. - synthesized.NamespaceOptions = namespacesForPod(pod) + synthesized.NamespaceOptions, _ = m.namespacesForPod(pod) + podSc := pod.Spec.SecurityContext if podSc != nil { if podSc.FSGroup != nil { diff --git a/pkg/kubelet/remote/fake/fake_runtime.go b/pkg/kubelet/remote/fake/fake_runtime.go index af77239ed11d1..30bcd65d51fe7 100644 --- a/pkg/kubelet/remote/fake/fake_runtime.go +++ b/pkg/kubelet/remote/fake/fake_runtime.go @@ -292,3 +292,13 @@ func (f *RemoteRuntime) ReopenContainerLog(ctx context.Context, req *kubeapi.Reo return &kubeapi.ReopenContainerLogResponse{}, nil } + +// GetRuntimeConfigInfo returns configuration details of the container runtime +func (f *RemoteRuntime) GetRuntimeConfigInfo(ctx context.Context, req *kubeapi.GetRuntimeConfigInfoRequest) (*kubeapi.GetRuntimeConfigInfoResponse, error) { + runtimeConfig, err := f.RuntimeService.GetRuntimeConfigInfo() + if err != nil { + return nil, err + } + + return &kubeapi.GetRuntimeConfigInfoResponse{RuntimeConfig: runtimeConfig}, nil +} diff --git a/pkg/kubelet/remote/remote_runtime.go b/pkg/kubelet/remote/remote_runtime.go index cf09dad4c1210..e4a927a450f04 100644 --- a/pkg/kubelet/remote/remote_runtime.go +++ b/pkg/kubelet/remote/remote_runtime.go @@ -443,6 +443,20 @@ func (r *RemoteRuntimeService) UpdateRuntimeConfig(runtimeConfig *runtimeapi.Run return nil } +// GetRuntimeConfigInfo returns the configuration information from the runtime +func (r *RemoteRuntimeService) GetRuntimeConfigInfo() (*runtimeapi.ActiveRuntimeConfig, error) { + ctx, cancel := getContextWithTimeout(r.timeout) + defer cancel() + + resp, err := r.runtimeClient.GetRuntimeConfigInfo(ctx, &runtimeapi.GetRuntimeConfigInfoRequest{}) + if err != nil { + klog.Errorf("GetRuntimeConfigInfo failed: %s", err) + return nil, err + } + + return resp.RuntimeConfig, nil +} + // Status returns the status of the runtime. func (r *RemoteRuntimeService) Status() (*runtimeapi.RuntimeStatus, error) { ctx, cancel := getContextWithTimeout(r.timeout) diff --git a/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.pb.go b/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.pb.go index 2d3e1f7b046c4..b6e46a72ee095 100644 --- a/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.pb.go +++ b/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.pb.go @@ -107,7 +107,7 @@ func (MountPropagation) EnumDescriptor() ([]byte, []int) { } // A NamespaceMode describes the intended namespace configuration for each -// of the namespaces (Network, PID, IPC) in NamespaceOption. Runtimes should +// of the namespaces (Network, PID, IPC, User) in NamespaceOption. Runtimes should // map these modes as appropriate for the technology underlying the runtime. type NamespaceMode int32 @@ -562,7 +562,12 @@ type NamespaceOption struct { // IPC namespace for this container/sandbox. // Note: There is currently no way to set CONTAINER scoped IPC in the Kubernetes API. // Namespaces currently set by the kubelet: POD, NODE - Ipc NamespaceMode `protobuf:"varint,3,opt,name=ipc,proto3,enum=runtime.v1alpha2.NamespaceMode" json:"ipc,omitempty"` + Ipc NamespaceMode `protobuf:"varint,3,opt,name=ipc,proto3,enum=runtime.v1alpha2.NamespaceMode" json:"ipc,omitempty"` + // User namespace for this container/sandbox. + // Note: There is currently no way to set CONTAINER scoped user namespace in the Kubernetes API. + // NODE is the default value. Kubelet will set it to POD if pod spec indicates to use user-namespace remapping + // Namespaces currently set by the kubelet: POD, NODE + User NamespaceMode `protobuf:"varint,4,opt,name=user,proto3,enum=runtime.v1alpha2.NamespaceMode" json:"user,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_sizecache int32 `json:"-"` } @@ -620,6 +625,13 @@ func (m *NamespaceOption) GetIpc() NamespaceMode { return NamespaceMode_POD } +func (m *NamespaceOption) GetUser() NamespaceMode { + if m != nil { + return m.User + } + return NamespaceMode_POD +} + // Int64Value is the wrapper of int64. type Int64Value struct { // The value. @@ -5854,6 +5866,259 @@ func (m *StatusResponse) GetInfo() map[string]string { return nil } +// LinuxIDMapping represents a single user namespace mapping in Linux. +type LinuxIDMapping struct { + // container_id is the starting id for the mapping inside the container. + ContainerId uint32 `protobuf:"varint,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // host_id is the starting id for the mapping on the host. + HostId uint32 `protobuf:"varint,2,opt,name=host_id,json=hostId,proto3" json:"host_id,omitempty"` + // size is the length of the mapping. + Size_ uint32 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LinuxIDMapping) Reset() { *m = LinuxIDMapping{} } +func (*LinuxIDMapping) ProtoMessage() {} +func (*LinuxIDMapping) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{87} +} +func (m *LinuxIDMapping) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LinuxIDMapping) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LinuxIDMapping.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *LinuxIDMapping) XXX_Merge(src proto.Message) { + xxx_messageInfo_LinuxIDMapping.Merge(m, src) +} +func (m *LinuxIDMapping) XXX_Size() int { + return m.Size() +} +func (m *LinuxIDMapping) XXX_DiscardUnknown() { + xxx_messageInfo_LinuxIDMapping.DiscardUnknown(m) +} + +var xxx_messageInfo_LinuxIDMapping proto.InternalMessageInfo + +func (m *LinuxIDMapping) GetContainerId() uint32 { + if m != nil { + return m.ContainerId + } + return 0 +} + +func (m *LinuxIDMapping) GetHostId() uint32 { + if m != nil { + return m.HostId + } + return 0 +} + +func (m *LinuxIDMapping) GetSize_() uint32 { + if m != nil { + return m.Size_ + } + return 0 +} + +// LinuxUserNamespaceConfig represents runtime's user-namespace configuration on a linux host. +type LinuxUserNamespaceConfig struct { + // uid_mappings is an array of user id mappings. + UidMappings []*LinuxIDMapping `protobuf:"bytes,1,rep,name=uid_mappings,json=uidMappings,proto3" json:"uid_mappings,omitempty"` + // gid_mappings is an array of group id mappings. + GidMappings []*LinuxIDMapping `protobuf:"bytes,2,rep,name=gid_mappings,json=gidMappings,proto3" json:"gid_mappings,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *LinuxUserNamespaceConfig) Reset() { *m = LinuxUserNamespaceConfig{} } +func (*LinuxUserNamespaceConfig) ProtoMessage() {} +func (*LinuxUserNamespaceConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{88} +} +func (m *LinuxUserNamespaceConfig) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LinuxUserNamespaceConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LinuxUserNamespaceConfig.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *LinuxUserNamespaceConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_LinuxUserNamespaceConfig.Merge(m, src) +} +func (m *LinuxUserNamespaceConfig) XXX_Size() int { + return m.Size() +} +func (m *LinuxUserNamespaceConfig) XXX_DiscardUnknown() { + xxx_messageInfo_LinuxUserNamespaceConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_LinuxUserNamespaceConfig proto.InternalMessageInfo + +func (m *LinuxUserNamespaceConfig) GetUidMappings() []*LinuxIDMapping { + if m != nil { + return m.UidMappings + } + return nil +} + +func (m *LinuxUserNamespaceConfig) GetGidMappings() []*LinuxIDMapping { + if m != nil { + return m.GidMappings + } + return nil +} + +// ActiveRuntimeConfig contains the configuration details from the runtime. +type ActiveRuntimeConfig struct { + // LinuxUserNamespaceConfig represents runtime's user-namespace configuration on a linux host. + UserNamespaceConfig *LinuxUserNamespaceConfig `protobuf:"bytes,1,opt,name=user_namespace_config,json=userNamespaceConfig,proto3" json:"user_namespace_config,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ActiveRuntimeConfig) Reset() { *m = ActiveRuntimeConfig{} } +func (*ActiveRuntimeConfig) ProtoMessage() {} +func (*ActiveRuntimeConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{89} +} +func (m *ActiveRuntimeConfig) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ActiveRuntimeConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ActiveRuntimeConfig.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ActiveRuntimeConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_ActiveRuntimeConfig.Merge(m, src) +} +func (m *ActiveRuntimeConfig) XXX_Size() int { + return m.Size() +} +func (m *ActiveRuntimeConfig) XXX_DiscardUnknown() { + xxx_messageInfo_ActiveRuntimeConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_ActiveRuntimeConfig proto.InternalMessageInfo + +func (m *ActiveRuntimeConfig) GetUserNamespaceConfig() *LinuxUserNamespaceConfig { + if m != nil { + return m.UserNamespaceConfig + } + return nil +} + +// GetRuntimeConfigInfoRequest is the message sent for requesting runtime configuration details. +type GetRuntimeConfigInfoRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetRuntimeConfigInfoRequest) Reset() { *m = GetRuntimeConfigInfoRequest{} } +func (*GetRuntimeConfigInfoRequest) ProtoMessage() {} +func (*GetRuntimeConfigInfoRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{90} +} +func (m *GetRuntimeConfigInfoRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetRuntimeConfigInfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetRuntimeConfigInfoRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetRuntimeConfigInfoRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetRuntimeConfigInfoRequest.Merge(m, src) +} +func (m *GetRuntimeConfigInfoRequest) XXX_Size() int { + return m.Size() +} +func (m *GetRuntimeConfigInfoRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetRuntimeConfigInfoRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetRuntimeConfigInfoRequest proto.InternalMessageInfo + +// GetRuntimeConfigInfoResponse is the response message from runtime that includes configuration details +type GetRuntimeConfigInfoResponse struct { + // GetRuntimeConfig are the configuration details from the runtime. + RuntimeConfig *ActiveRuntimeConfig `protobuf:"bytes,1,opt,name=runtime_config,json=runtimeConfig,proto3" json:"runtime_config,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetRuntimeConfigInfoResponse) Reset() { *m = GetRuntimeConfigInfoResponse{} } +func (*GetRuntimeConfigInfoResponse) ProtoMessage() {} +func (*GetRuntimeConfigInfoResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00212fb1f9d3bf1c, []int{91} +} +func (m *GetRuntimeConfigInfoResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetRuntimeConfigInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetRuntimeConfigInfoResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetRuntimeConfigInfoResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetRuntimeConfigInfoResponse.Merge(m, src) +} +func (m *GetRuntimeConfigInfoResponse) XXX_Size() int { + return m.Size() +} +func (m *GetRuntimeConfigInfoResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetRuntimeConfigInfoResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetRuntimeConfigInfoResponse proto.InternalMessageInfo + +func (m *GetRuntimeConfigInfoResponse) GetRuntimeConfig() *ActiveRuntimeConfig { + if m != nil { + return m.RuntimeConfig + } + return nil +} + type ImageFsInfoRequest struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_sizecache int32 `json:"-"` @@ -5862,7 +6127,7 @@ type ImageFsInfoRequest struct { func (m *ImageFsInfoRequest) Reset() { *m = ImageFsInfoRequest{} } func (*ImageFsInfoRequest) ProtoMessage() {} func (*ImageFsInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{87} + return fileDescriptor_00212fb1f9d3bf1c, []int{92} } func (m *ImageFsInfoRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5902,7 +6167,7 @@ type UInt64Value struct { func (m *UInt64Value) Reset() { *m = UInt64Value{} } func (*UInt64Value) ProtoMessage() {} func (*UInt64Value) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{88} + return fileDescriptor_00212fb1f9d3bf1c, []int{93} } func (m *UInt64Value) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5949,7 +6214,7 @@ type FilesystemIdentifier struct { func (m *FilesystemIdentifier) Reset() { *m = FilesystemIdentifier{} } func (*FilesystemIdentifier) ProtoMessage() {} func (*FilesystemIdentifier) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{89} + return fileDescriptor_00212fb1f9d3bf1c, []int{94} } func (m *FilesystemIdentifier) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6006,7 +6271,7 @@ type FilesystemUsage struct { func (m *FilesystemUsage) Reset() { *m = FilesystemUsage{} } func (*FilesystemUsage) ProtoMessage() {} func (*FilesystemUsage) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{90} + return fileDescriptor_00212fb1f9d3bf1c, []int{95} } func (m *FilesystemUsage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6073,7 +6338,7 @@ type ImageFsInfoResponse struct { func (m *ImageFsInfoResponse) Reset() { *m = ImageFsInfoResponse{} } func (*ImageFsInfoResponse) ProtoMessage() {} func (*ImageFsInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{91} + return fileDescriptor_00212fb1f9d3bf1c, []int{96} } func (m *ImageFsInfoResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6119,7 +6384,7 @@ type ContainerStatsRequest struct { func (m *ContainerStatsRequest) Reset() { *m = ContainerStatsRequest{} } func (*ContainerStatsRequest) ProtoMessage() {} func (*ContainerStatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{92} + return fileDescriptor_00212fb1f9d3bf1c, []int{97} } func (m *ContainerStatsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6165,7 +6430,7 @@ type ContainerStatsResponse struct { func (m *ContainerStatsResponse) Reset() { *m = ContainerStatsResponse{} } func (*ContainerStatsResponse) ProtoMessage() {} func (*ContainerStatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{93} + return fileDescriptor_00212fb1f9d3bf1c, []int{98} } func (m *ContainerStatsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6211,7 +6476,7 @@ type ListContainerStatsRequest struct { func (m *ListContainerStatsRequest) Reset() { *m = ListContainerStatsRequest{} } func (*ListContainerStatsRequest) ProtoMessage() {} func (*ListContainerStatsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{94} + return fileDescriptor_00212fb1f9d3bf1c, []int{99} } func (m *ListContainerStatsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6265,7 +6530,7 @@ type ContainerStatsFilter struct { func (m *ContainerStatsFilter) Reset() { *m = ContainerStatsFilter{} } func (*ContainerStatsFilter) ProtoMessage() {} func (*ContainerStatsFilter) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{95} + return fileDescriptor_00212fb1f9d3bf1c, []int{100} } func (m *ContainerStatsFilter) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6325,7 +6590,7 @@ type ListContainerStatsResponse struct { func (m *ListContainerStatsResponse) Reset() { *m = ListContainerStatsResponse{} } func (*ListContainerStatsResponse) ProtoMessage() {} func (*ListContainerStatsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{96} + return fileDescriptor_00212fb1f9d3bf1c, []int{101} } func (m *ListContainerStatsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6381,7 +6646,7 @@ type ContainerAttributes struct { func (m *ContainerAttributes) Reset() { *m = ContainerAttributes{} } func (*ContainerAttributes) ProtoMessage() {} func (*ContainerAttributes) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{97} + return fileDescriptor_00212fb1f9d3bf1c, []int{102} } func (m *ContainerAttributes) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6455,7 +6720,7 @@ type ContainerStats struct { func (m *ContainerStats) Reset() { *m = ContainerStats{} } func (*ContainerStats) ProtoMessage() {} func (*ContainerStats) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{98} + return fileDescriptor_00212fb1f9d3bf1c, []int{103} } func (m *ContainerStats) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6525,7 +6790,7 @@ type CpuUsage struct { func (m *CpuUsage) Reset() { *m = CpuUsage{} } func (*CpuUsage) ProtoMessage() {} func (*CpuUsage) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{99} + return fileDescriptor_00212fb1f9d3bf1c, []int{104} } func (m *CpuUsage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6581,7 +6846,7 @@ type MemoryUsage struct { func (m *MemoryUsage) Reset() { *m = MemoryUsage{} } func (*MemoryUsage) ProtoMessage() {} func (*MemoryUsage) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{100} + return fileDescriptor_00212fb1f9d3bf1c, []int{105} } func (m *MemoryUsage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6634,7 +6899,7 @@ type ReopenContainerLogRequest struct { func (m *ReopenContainerLogRequest) Reset() { *m = ReopenContainerLogRequest{} } func (*ReopenContainerLogRequest) ProtoMessage() {} func (*ReopenContainerLogRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{101} + return fileDescriptor_00212fb1f9d3bf1c, []int{106} } func (m *ReopenContainerLogRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6678,7 +6943,7 @@ type ReopenContainerLogResponse struct { func (m *ReopenContainerLogResponse) Reset() { *m = ReopenContainerLogResponse{} } func (*ReopenContainerLogResponse) ProtoMessage() {} func (*ReopenContainerLogResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_00212fb1f9d3bf1c, []int{102} + return fileDescriptor_00212fb1f9d3bf1c, []int{107} } func (m *ReopenContainerLogResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6819,6 +7084,11 @@ func init() { proto.RegisterType((*StatusRequest)(nil), "runtime.v1alpha2.StatusRequest") proto.RegisterType((*StatusResponse)(nil), "runtime.v1alpha2.StatusResponse") proto.RegisterMapType((map[string]string)(nil), "runtime.v1alpha2.StatusResponse.InfoEntry") + proto.RegisterType((*LinuxIDMapping)(nil), "runtime.v1alpha2.LinuxIDMapping") + proto.RegisterType((*LinuxUserNamespaceConfig)(nil), "runtime.v1alpha2.LinuxUserNamespaceConfig") + proto.RegisterType((*ActiveRuntimeConfig)(nil), "runtime.v1alpha2.ActiveRuntimeConfig") + proto.RegisterType((*GetRuntimeConfigInfoRequest)(nil), "runtime.v1alpha2.GetRuntimeConfigInfoRequest") + proto.RegisterType((*GetRuntimeConfigInfoResponse)(nil), "runtime.v1alpha2.GetRuntimeConfigInfoResponse") proto.RegisterType((*ImageFsInfoRequest)(nil), "runtime.v1alpha2.ImageFsInfoRequest") proto.RegisterType((*UInt64Value)(nil), "runtime.v1alpha2.UInt64Value") proto.RegisterType((*FilesystemIdentifier)(nil), "runtime.v1alpha2.FilesystemIdentifier") @@ -6843,306 +7113,316 @@ func init() { func init() { proto.RegisterFile("api.proto", fileDescriptor_00212fb1f9d3bf1c) } var fileDescriptor_00212fb1f9d3bf1c = []byte{ - // 4770 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5c, 0xcd, 0x6f, 0x1b, 0x49, - 0x76, 0x57, 0x93, 0xa2, 0x44, 0x3e, 0x8a, 0x14, 0x55, 0x96, 0x2d, 0x9a, 0x1e, 0x6b, 0xac, 0x9e, - 0xf1, 0xe7, 0xcc, 0xc8, 0x63, 0xcd, 0xac, 0x27, 0xb6, 0x67, 0x6d, 0xd3, 0x92, 0x6c, 0x33, 0x6b, - 0x53, 0x4c, 0x53, 0x9a, 0x8f, 0x9d, 0x01, 0x7a, 0x5b, 0xec, 0x12, 0xd5, 0x6b, 0xb2, 0xbb, 0xa7, - 0xbb, 0x69, 0x5b, 0x09, 0x10, 0x2c, 0xb0, 0xc8, 0x1e, 0x02, 0x04, 0xc8, 0x39, 0xc7, 0xcd, 0x21, - 0x87, 0xdc, 0x02, 0x04, 0x39, 0xe4, 0xb4, 0x41, 0x0e, 0x7b, 0x09, 0x90, 0xd3, 0x22, 0x41, 0x2e, - 0x99, 0x49, 0x72, 0x09, 0x90, 0x20, 0x7f, 0x40, 0x0e, 0x41, 0x7d, 0xf5, 0x77, 0xf3, 0xc3, 0xe3, - 0xdd, 0xd9, 0x9c, 0xd4, 0xf5, 0xfa, 0xbd, 0x57, 0xaf, 0x5f, 0xbd, 0x7a, 0xf5, 0xea, 0x57, 0x45, - 0x41, 0x49, 0xb3, 0x8d, 0x4d, 0xdb, 0xb1, 0x3c, 0x0b, 0xd5, 0x9c, 0x91, 0xe9, 0x19, 0x43, 0xbc, - 0xf9, 0xfc, 0x86, 0x36, 0xb0, 0x8f, 0xb5, 0xad, 0xc6, 0x7b, 0x7d, 0xc3, 0x3b, 0x1e, 0x1d, 0x6e, - 0xf6, 0xac, 0xe1, 0xf5, 0xbe, 0xd5, 0xb7, 0xae, 0x53, 0xc6, 0xc3, 0xd1, 0x11, 0x6d, 0xd1, 0x06, - 0x7d, 0x62, 0x0a, 0xe4, 0x6b, 0x50, 0xfd, 0x04, 0x3b, 0xae, 0x61, 0x99, 0x0a, 0xfe, 0x6a, 0x84, - 0x5d, 0x0f, 0xd5, 0x61, 0xf1, 0x39, 0xa3, 0xd4, 0xa5, 0x0b, 0xd2, 0x95, 0x92, 0x22, 0x9a, 0xf2, - 0x5f, 0x48, 0xb0, 0xec, 0x33, 0xbb, 0xb6, 0x65, 0xba, 0x38, 0x9b, 0x1b, 0x6d, 0xc0, 0x12, 0x37, - 0x4e, 0x35, 0xb5, 0x21, 0xae, 0xe7, 0xe8, 0xeb, 0x32, 0xa7, 0xb5, 0xb5, 0x21, 0x46, 0x97, 0x61, - 0x59, 0xb0, 0x08, 0x25, 0x79, 0xca, 0x55, 0xe5, 0x64, 0xde, 0x1b, 0xda, 0x84, 0x53, 0x82, 0x51, - 0xb3, 0x0d, 0x9f, 0x79, 0x9e, 0x32, 0xaf, 0xf0, 0x57, 0x4d, 0xdb, 0xe0, 0xfc, 0xf2, 0x17, 0x50, - 0xda, 0x69, 0x77, 0xb7, 0x2d, 0xf3, 0xc8, 0xe8, 0x13, 0x13, 0x5d, 0xec, 0x10, 0x99, 0xba, 0x74, - 0x21, 0x4f, 0x4c, 0xe4, 0x4d, 0xd4, 0x80, 0xa2, 0x8b, 0x35, 0xa7, 0x77, 0x8c, 0xdd, 0x7a, 0x8e, - 0xbe, 0xf2, 0xdb, 0x44, 0xca, 0xb2, 0x3d, 0xc3, 0x32, 0xdd, 0x7a, 0x9e, 0x49, 0xf1, 0xa6, 0xfc, - 0x73, 0x09, 0xca, 0x1d, 0xcb, 0xf1, 0x9e, 0x6a, 0xb6, 0x6d, 0x98, 0x7d, 0x74, 0x13, 0x8a, 0xd4, - 0x97, 0x3d, 0x6b, 0x40, 0x7d, 0x50, 0xdd, 0x6a, 0x6c, 0xc6, 0x87, 0x65, 0xb3, 0xc3, 0x39, 0x14, - 0x9f, 0x17, 0x5d, 0x84, 0x6a, 0xcf, 0x32, 0x3d, 0xcd, 0x30, 0xb1, 0xa3, 0xda, 0x96, 0xe3, 0x51, - 0x17, 0x15, 0x94, 0x8a, 0x4f, 0x25, 0xbd, 0xa0, 0x73, 0x50, 0x3a, 0xb6, 0x5c, 0x8f, 0x71, 0xe4, - 0x29, 0x47, 0x91, 0x10, 0xe8, 0xcb, 0x35, 0x58, 0xa4, 0x2f, 0x0d, 0x9b, 0x3b, 0x63, 0x81, 0x34, - 0x5b, 0xb6, 0xfc, 0x2b, 0x09, 0x0a, 0x4f, 0xad, 0x91, 0xe9, 0xc5, 0xba, 0xd1, 0xbc, 0x63, 0x3e, - 0x50, 0xa1, 0x6e, 0x34, 0xef, 0x38, 0xe8, 0x86, 0x70, 0xb0, 0xb1, 0x62, 0xdd, 0x90, 0x97, 0x0d, - 0x28, 0x3a, 0x58, 0xd3, 0x2d, 0x73, 0x70, 0x42, 0x4d, 0x28, 0x2a, 0x7e, 0x9b, 0x0c, 0xa2, 0x8b, - 0x07, 0x86, 0x39, 0x7a, 0xa9, 0x3a, 0x78, 0xa0, 0x1d, 0xe2, 0x01, 0x35, 0xa5, 0xa8, 0x54, 0x39, - 0x59, 0x61, 0x54, 0xb4, 0x03, 0x65, 0xdb, 0xb1, 0x6c, 0xad, 0xaf, 0x11, 0x3f, 0xd6, 0x0b, 0xd4, - 0x55, 0x72, 0xd2, 0x55, 0xd4, 0xec, 0x4e, 0xc0, 0xa9, 0x84, 0xc5, 0xe4, 0xbf, 0x92, 0x60, 0x99, - 0x04, 0x8f, 0x6b, 0x6b, 0x3d, 0xbc, 0x47, 0x87, 0x04, 0xdd, 0x82, 0x45, 0x13, 0x7b, 0x2f, 0x2c, - 0xe7, 0x19, 0x1f, 0x80, 0x37, 0x93, 0x5a, 0x7d, 0x99, 0xa7, 0x96, 0x8e, 0x15, 0xc1, 0x8f, 0x6e, - 0x40, 0xde, 0x36, 0x74, 0xfa, 0xc1, 0x53, 0x88, 0x11, 0x5e, 0x22, 0x62, 0xd8, 0x3d, 0xea, 0x87, - 0x69, 0x44, 0x0c, 0xbb, 0x27, 0xcb, 0x00, 0x2d, 0xd3, 0xbb, 0xf9, 0xe1, 0x27, 0xda, 0x60, 0x84, - 0xd1, 0x2a, 0x14, 0x9e, 0x93, 0x07, 0x6a, 0x6c, 0x5e, 0x61, 0x0d, 0xf9, 0xeb, 0x3c, 0x9c, 0x7b, - 0x42, 0xfc, 0xd5, 0xd5, 0x4c, 0xfd, 0xd0, 0x7a, 0xd9, 0xc5, 0xbd, 0x91, 0x63, 0x78, 0x27, 0xdb, - 0x96, 0xe9, 0xe1, 0x97, 0x1e, 0x6a, 0xc3, 0x8a, 0x29, 0x34, 0xab, 0x22, 0x34, 0x89, 0x86, 0xf2, - 0xd6, 0xc6, 0x18, 0x23, 0x98, 0x8b, 0x94, 0x9a, 0x19, 0x25, 0xb8, 0xe8, 0x71, 0x30, 0x6e, 0x42, - 0x5b, 0x8e, 0x6a, 0x4b, 0xf9, 0xa4, 0xee, 0x2e, 0xb5, 0x8c, 0xeb, 0x12, 0x03, 0x2b, 0x34, 0x7d, - 0x0c, 0x64, 0x56, 0xab, 0x9a, 0xab, 0x8e, 0x5c, 0xec, 0x50, 0xc7, 0x94, 0xb7, 0xde, 0x48, 0x6a, - 0x09, 0x5c, 0xa0, 0x94, 0x9c, 0x91, 0xd9, 0x74, 0x0f, 0x5c, 0xec, 0xa0, 0xbb, 0x34, 0x4f, 0x10, - 0xe9, 0xbe, 0x63, 0x8d, 0xec, 0x7a, 0x71, 0x0a, 0x71, 0xa0, 0xe2, 0x8f, 0x08, 0x3f, 0x4d, 0x22, - 0x3c, 0x16, 0x55, 0xc7, 0xb2, 0xbc, 0x23, 0x57, 0xc4, 0x9f, 0x20, 0x2b, 0x94, 0x8a, 0xae, 0xc3, - 0x29, 0x77, 0x64, 0xdb, 0x03, 0x3c, 0xc4, 0xa6, 0xa7, 0x0d, 0x58, 0x77, 0x6e, 0xbd, 0x70, 0x21, - 0x7f, 0x25, 0xaf, 0xa0, 0xf0, 0x2b, 0xaa, 0xd8, 0x45, 0xeb, 0x00, 0xb6, 0x63, 0x3c, 0x37, 0x06, - 0xb8, 0x8f, 0xf5, 0xfa, 0x02, 0x55, 0x1a, 0xa2, 0xa0, 0xf7, 0x61, 0xd5, 0xc5, 0xbd, 0x9e, 0x35, - 0xb4, 0x55, 0xdb, 0xb1, 0x8e, 0x8c, 0x01, 0x66, 0xb3, 0x67, 0x91, 0xce, 0x1e, 0xc4, 0xdf, 0x75, - 0xd8, 0x2b, 0x32, 0x8f, 0xe4, 0x9f, 0xe7, 0xe0, 0x34, 0xf5, 0x64, 0xc7, 0xd2, 0xf9, 0x30, 0xf3, - 0x24, 0xf5, 0x16, 0x54, 0x7a, 0xd4, 0x20, 0xd5, 0xd6, 0x1c, 0x6c, 0x7a, 0x7c, 0x92, 0x2e, 0x31, - 0x62, 0x87, 0xd2, 0xd0, 0x67, 0x50, 0x73, 0x79, 0x54, 0xa8, 0x3d, 0x16, 0x16, 0x7c, 0xcc, 0xde, - 0x4b, 0xba, 0x6b, 0x4c, 0x2c, 0x29, 0xcb, 0x6e, 0x22, 0xb8, 0x16, 0xdd, 0x13, 0xb7, 0xe7, 0x0d, - 0x58, 0xb6, 0x2b, 0x6f, 0x7d, 0x98, 0xa1, 0x30, 0x6e, 0xf8, 0x66, 0x97, 0x89, 0xed, 0x9a, 0x9e, - 0x73, 0xa2, 0x08, 0x25, 0x8d, 0xdb, 0xb0, 0x14, 0x7e, 0x81, 0x6a, 0x90, 0x7f, 0x86, 0x4f, 0xf8, - 0x47, 0x91, 0xc7, 0x60, 0x12, 0xb0, 0x5c, 0xc3, 0x1a, 0xb7, 0x73, 0xbf, 0x23, 0xc9, 0x0e, 0xa0, - 0xa0, 0x97, 0xa7, 0xd8, 0xd3, 0x74, 0xcd, 0xd3, 0x10, 0x82, 0x79, 0xba, 0x8c, 0x30, 0x15, 0xf4, - 0x99, 0x68, 0x1d, 0xf1, 0xc9, 0x5b, 0x52, 0xc8, 0x23, 0x7a, 0x03, 0x4a, 0x7e, 0xa0, 0xf3, 0xb5, - 0x24, 0x20, 0x90, 0x9c, 0xae, 0x79, 0x1e, 0x1e, 0xda, 0x1e, 0x0d, 0x91, 0x8a, 0x22, 0x9a, 0xf2, - 0x7f, 0xcf, 0x43, 0x2d, 0x31, 0x26, 0xf7, 0xa1, 0x38, 0xe4, 0xdd, 0xf3, 0x89, 0xf6, 0x76, 0x4a, - 0x62, 0x4f, 0x98, 0xaa, 0xf8, 0x52, 0x24, 0x6f, 0x92, 0x1c, 0x1a, 0x5a, 0xff, 0xfc, 0x36, 0x19, - 0xf1, 0x81, 0xd5, 0x57, 0x75, 0xc3, 0xc1, 0x3d, 0xcf, 0x72, 0x4e, 0xb8, 0xb9, 0x4b, 0x03, 0xab, - 0xbf, 0x23, 0x68, 0xe8, 0x36, 0x80, 0x6e, 0xba, 0x64, 0xb0, 0x8f, 0x8c, 0x3e, 0x35, 0xba, 0xbc, - 0x75, 0x2e, 0x69, 0x84, 0xbf, 0xd8, 0x29, 0x25, 0xdd, 0x74, 0xb9, 0xf9, 0x0f, 0xa0, 0x42, 0xd6, - 0x0c, 0x75, 0xc8, 0xd6, 0x29, 0x16, 0xe9, 0xe5, 0xad, 0xf3, 0x69, 0xdf, 0xe0, 0xaf, 0x66, 0xca, - 0x92, 0x1d, 0x34, 0x5c, 0xf4, 0x10, 0x16, 0x68, 0xf2, 0x76, 0xeb, 0x0b, 0x54, 0x78, 0x73, 0x9c, - 0x03, 0x78, 0x44, 0x3c, 0xa1, 0x02, 0x2c, 0x20, 0xb8, 0x34, 0x3a, 0x80, 0xb2, 0x66, 0x9a, 0x96, - 0xa7, 0xb1, 0x44, 0xb3, 0x48, 0x95, 0x7d, 0x30, 0x85, 0xb2, 0x66, 0x20, 0xc5, 0x34, 0x86, 0xf5, - 0xa0, 0xef, 0x43, 0x81, 0x66, 0x22, 0x9e, 0x34, 0x2e, 0x4f, 0x19, 0xb4, 0x0a, 0x93, 0x6a, 0xdc, - 0x82, 0x72, 0xc8, 0xd8, 0x59, 0x82, 0xb4, 0x71, 0x17, 0x6a, 0x71, 0xd3, 0x66, 0x0a, 0xf2, 0x3f, - 0x80, 0x55, 0x65, 0x64, 0x06, 0x86, 0x89, 0xea, 0xeb, 0x36, 0x2c, 0xf0, 0xc1, 0x66, 0x11, 0x27, - 0x4f, 0xf6, 0x91, 0xc2, 0x25, 0xc2, 0xe5, 0xd4, 0xb1, 0x66, 0xea, 0x03, 0xec, 0xf0, 0x7e, 0x45, - 0x39, 0xf5, 0x98, 0x51, 0xe5, 0xef, 0xc3, 0xe9, 0x58, 0xe7, 0xbc, 0x9a, 0x7b, 0x1b, 0xaa, 0xb6, - 0xa5, 0xab, 0x2e, 0x23, 0xab, 0x86, 0x2e, 0xd2, 0x90, 0xed, 0xf3, 0xb6, 0x74, 0x22, 0xde, 0xf5, - 0x2c, 0x3b, 0x69, 0xfc, 0x74, 0xe2, 0x75, 0x38, 0x13, 0x17, 0x67, 0xdd, 0xcb, 0xf7, 0x60, 0x4d, - 0xc1, 0x43, 0xeb, 0x39, 0x7e, 0x55, 0xd5, 0x0d, 0xa8, 0x27, 0x15, 0x70, 0xe5, 0x9f, 0xc3, 0x5a, - 0x40, 0xed, 0x7a, 0x9a, 0x37, 0x72, 0x67, 0x52, 0xce, 0x4b, 0xdd, 0x43, 0xcb, 0x65, 0xc3, 0x59, - 0x54, 0x44, 0x53, 0x5e, 0x83, 0x42, 0xc7, 0xd2, 0x5b, 0x1d, 0x54, 0x85, 0x9c, 0x61, 0x73, 0xe1, - 0x9c, 0x61, 0xcb, 0x46, 0xb8, 0xcf, 0x36, 0x2b, 0x39, 0x58, 0xd7, 0x71, 0x56, 0x74, 0x17, 0xaa, - 0x9a, 0xae, 0x1b, 0x24, 0x9c, 0xb4, 0x81, 0x6a, 0xd8, 0xac, 0x22, 0x2d, 0x6f, 0xad, 0xa5, 0x06, - 0x40, 0xab, 0xa3, 0x54, 0x02, 0xf6, 0x96, 0xed, 0xca, 0x8f, 0xa1, 0xe4, 0xaf, 0xf9, 0xe8, 0x4e, - 0x50, 0xbc, 0xe6, 0xa6, 0xad, 0x10, 0xfc, 0xfa, 0x76, 0x3f, 0xb1, 0x46, 0x71, 0x93, 0xef, 0x00, - 0xf8, 0xb9, 0x54, 0x94, 0x1e, 0xe7, 0xc6, 0x28, 0x56, 0x42, 0xec, 0xf2, 0x4f, 0x0b, 0xe1, 0x0c, - 0x1b, 0x72, 0x82, 0xee, 0x3b, 0x41, 0x8f, 0x64, 0xdc, 0xdc, 0x2b, 0x65, 0xdc, 0x8f, 0xa0, 0xe0, - 0x7a, 0x9a, 0x87, 0x79, 0x79, 0xb6, 0x31, 0x4e, 0x9c, 0x18, 0x81, 0x15, 0xc6, 0x8f, 0xce, 0x03, - 0xf4, 0x1c, 0xac, 0x79, 0x58, 0x57, 0x35, 0xb6, 0x3c, 0xe4, 0x95, 0x12, 0xa7, 0x34, 0x3d, 0xb4, - 0x1d, 0x94, 0x98, 0x05, 0x6a, 0xd8, 0xd5, 0x71, 0x9a, 0x23, 0x43, 0x1d, 0x14, 0x9b, 0x7e, 0xba, - 0x5a, 0x98, 0x32, 0x5d, 0x71, 0x05, 0x4c, 0x2a, 0x94, 0x8c, 0x17, 0x27, 0x27, 0x63, 0x26, 0x3a, - 0x4d, 0x32, 0x2e, 0x4e, 0x4e, 0xc6, 0x5c, 0xd9, 0xf8, 0x64, 0x9c, 0x92, 0x7e, 0x4a, 0x69, 0xe9, - 0xe7, 0xbb, 0x4c, 0xbb, 0xff, 0x2c, 0x41, 0x3d, 0x99, 0x05, 0x78, 0xf6, 0xbb, 0x0d, 0x0b, 0x2e, - 0xa5, 0x4c, 0x93, 0x7b, 0xb9, 0x2c, 0x97, 0x40, 0x8f, 0x61, 0xde, 0x30, 0x8f, 0x2c, 0x3e, 0x69, - 0x3f, 0x9c, 0x42, 0x92, 0xf7, 0xba, 0xd9, 0x32, 0x8f, 0x2c, 0xe6, 0x4d, 0xaa, 0xa1, 0xf1, 0x11, - 0x94, 0x7c, 0xd2, 0x4c, 0xdf, 0xb6, 0x07, 0xab, 0xb1, 0xd8, 0x66, 0xdb, 0x0d, 0x7f, 0x4a, 0x48, - 0xb3, 0x4d, 0x09, 0xf9, 0x27, 0xb9, 0xf0, 0x94, 0x7d, 0x68, 0x0c, 0x3c, 0xec, 0x24, 0xa6, 0xec, - 0xc7, 0x42, 0x3b, 0x9b, 0xaf, 0x97, 0x26, 0x6a, 0x67, 0x15, 0x3c, 0x9f, 0x75, 0x5f, 0x42, 0x95, - 0x06, 0xa5, 0xea, 0xe2, 0x01, 0x2d, 0x79, 0x78, 0xf9, 0xf9, 0xbd, 0x71, 0x6a, 0x98, 0x25, 0x2c, - 0xb4, 0xbb, 0x5c, 0x8e, 0x79, 0xb0, 0x32, 0x08, 0xd3, 0x1a, 0xf7, 0x01, 0x25, 0x99, 0x66, 0xf2, - 0x69, 0x97, 0xe4, 0x42, 0xb2, 0xd7, 0x4e, 0x59, 0xa7, 0x8f, 0xa8, 0x19, 0xd3, 0xc4, 0x0a, 0x33, - 0x58, 0xe1, 0x12, 0xf2, 0x7f, 0xe5, 0x01, 0x82, 0x97, 0xff, 0x8f, 0x92, 0xe0, 0x7d, 0x3f, 0x01, - 0xb1, 0x52, 0xf2, 0xca, 0x38, 0xc5, 0xa9, 0xa9, 0x67, 0x2f, 0x9a, 0x7a, 0x58, 0x51, 0xf9, 0xde, - 0x58, 0x35, 0x33, 0x27, 0x9d, 0xc5, 0xdf, 0xb6, 0xa4, 0xf3, 0x04, 0xce, 0xc4, 0x83, 0x88, 0x67, - 0x9c, 0x2d, 0x28, 0x18, 0x1e, 0x1e, 0x32, 0x60, 0x2a, 0x75, 0xd3, 0x1b, 0x12, 0x62, 0xac, 0xf2, - 0x06, 0x94, 0x5a, 0x43, 0xad, 0x8f, 0xbb, 0x36, 0xee, 0x91, 0x4e, 0x0d, 0xd2, 0xe0, 0x86, 0xb0, - 0x86, 0xbc, 0x05, 0xc5, 0x1f, 0xe0, 0x13, 0x36, 0xfb, 0xa7, 0x34, 0x54, 0xfe, 0x93, 0x1c, 0xac, - 0xd1, 0xd5, 0x67, 0x5b, 0xc0, 0x42, 0x0a, 0x76, 0xad, 0x91, 0xd3, 0xc3, 0x2e, 0x0d, 0x0b, 0x7b, - 0xa4, 0xda, 0xd8, 0x31, 0x2c, 0x9d, 0xa3, 0x16, 0xa5, 0x9e, 0x3d, 0xea, 0x50, 0x02, 0x3a, 0x07, - 0xa4, 0xa1, 0x7e, 0x35, 0xb2, 0x78, 0xc4, 0xe6, 0x95, 0x62, 0xcf, 0x1e, 0xfd, 0x1e, 0x69, 0x0b, - 0x59, 0xf7, 0x58, 0x73, 0xb0, 0x4b, 0x03, 0x92, 0xc9, 0x76, 0x29, 0x01, 0xdd, 0x80, 0xd3, 0x43, - 0x3c, 0xb4, 0x9c, 0x13, 0x75, 0x60, 0x0c, 0x0d, 0x4f, 0x35, 0x4c, 0xf5, 0xf0, 0xc4, 0xc3, 0x2e, - 0x0f, 0x3e, 0xc4, 0x5e, 0x3e, 0x21, 0xef, 0x5a, 0xe6, 0x03, 0xf2, 0x06, 0xc9, 0x50, 0xb1, 0xac, - 0xa1, 0xea, 0xf6, 0x2c, 0x07, 0xab, 0x9a, 0xfe, 0x63, 0xba, 0x20, 0xe7, 0x95, 0xb2, 0x65, 0x0d, - 0xbb, 0x84, 0xd6, 0xd4, 0x7f, 0x8c, 0xde, 0x84, 0x72, 0xcf, 0x1e, 0xb9, 0xd8, 0x53, 0xc9, 0x1f, - 0xba, 0xde, 0x96, 0x14, 0x60, 0xa4, 0x6d, 0x7b, 0xe4, 0x86, 0x18, 0x86, 0xc4, 0xff, 0x8b, 0x61, - 0x86, 0xa7, 0xc4, 0xcd, 0x1a, 0x54, 0x22, 0xa8, 0x07, 0xd9, 0x80, 0x52, 0x78, 0x83, 0x6f, 0x40, - 0xc9, 0x33, 0xa1, 0x39, 0xd6, 0x40, 0x78, 0x92, 0x3e, 0x13, 0x9a, 0x77, 0x62, 0x8b, 0xdd, 0x27, - 0x7d, 0x26, 0x2e, 0x1f, 0xe0, 0xe7, 0x1c, 0x19, 0x2b, 0x29, 0xac, 0x21, 0xeb, 0x00, 0xdb, 0x9a, - 0xad, 0x1d, 0x1a, 0x03, 0xc3, 0x3b, 0x41, 0x57, 0xa1, 0xa6, 0xe9, 0xba, 0xda, 0x13, 0x14, 0x03, - 0x0b, 0xbc, 0x72, 0x59, 0xd3, 0xf5, 0xed, 0x10, 0x19, 0xbd, 0x03, 0x2b, 0xba, 0x63, 0xd9, 0x51, - 0x5e, 0x06, 0x60, 0xd6, 0xc8, 0x8b, 0x30, 0xb3, 0xfc, 0xef, 0x05, 0x38, 0x1f, 0x1d, 0xd8, 0x38, - 0xb2, 0x74, 0x1f, 0x96, 0x62, 0xbd, 0x66, 0x20, 0x30, 0x81, 0xb5, 0x4a, 0x44, 0x22, 0x86, 0x94, - 0xe4, 0x12, 0x48, 0x49, 0x2a, 0x76, 0x95, 0x7f, 0xad, 0xd8, 0xd5, 0xfc, 0x6b, 0xc1, 0xae, 0x0a, - 0xdf, 0x0e, 0xbb, 0x5a, 0x9a, 0x11, 0xbb, 0xba, 0x44, 0xb3, 0x97, 0xe8, 0x9d, 0xc2, 0x04, 0x2c, - 0x54, 0x2b, 0x7e, 0x1f, 0xa6, 0x00, 0xca, 0x63, 0x18, 0xd7, 0xe2, 0x2c, 0x18, 0x57, 0x31, 0x13, - 0xe3, 0x22, 0x51, 0x67, 0xdb, 0x9a, 0x33, 0xb4, 0x1c, 0x01, 0x62, 0xf1, 0xaa, 0x6d, 0x59, 0xd0, - 0x39, 0x80, 0x95, 0x09, 0x77, 0x41, 0x16, 0xdc, 0x85, 0x2e, 0xc0, 0x92, 0x69, 0xa9, 0x26, 0x7e, - 0xa1, 0x92, 0x58, 0x70, 0xeb, 0x65, 0x16, 0x18, 0xa6, 0xd5, 0xc6, 0x2f, 0x3a, 0x84, 0x82, 0x36, - 0x60, 0x69, 0xa8, 0xb9, 0xcf, 0xb0, 0x4e, 0x55, 0xb9, 0xf5, 0x0a, 0x0d, 0xe2, 0x32, 0xa3, 0x11, - 0x1d, 0x2e, 0xba, 0x08, 0xfe, 0x47, 0x72, 0xa6, 0x2a, 0x65, 0xaa, 0x08, 0x2a, 0x65, 0x93, 0xff, - 0x56, 0x82, 0xd5, 0x68, 0x98, 0x73, 0x18, 0xe4, 0x11, 0x94, 0x1c, 0x91, 0xc9, 0x78, 0x68, 0x5f, - 0xcd, 0x28, 0xbc, 0x93, 0xa9, 0x4f, 0x09, 0x64, 0xd1, 0x0f, 0x33, 0xd1, 0xb7, 0xeb, 0x93, 0xf4, - 0x4d, 0xc2, 0xdf, 0x64, 0x07, 0xde, 0xfc, 0xd4, 0x30, 0x75, 0xeb, 0x85, 0x9b, 0x39, 0x4b, 0x53, - 0x62, 0x45, 0xca, 0x88, 0x95, 0x9e, 0x83, 0x75, 0x6c, 0x7a, 0x86, 0x36, 0x50, 0x5d, 0x1b, 0xf7, - 0x04, 0x0a, 0x10, 0x90, 0xc9, 0xda, 0x21, 0xff, 0x42, 0x82, 0x33, 0xf1, 0x4e, 0xb9, 0xcf, 0x5a, - 0x49, 0x9f, 0xbd, 0x93, 0xfc, 0xc6, 0xb8, 0x70, 0xaa, 0xd7, 0xbe, 0xcc, 0xf4, 0xda, 0x8d, 0xc9, - 0x1a, 0x27, 0xfa, 0xed, 0x2f, 0x25, 0x38, 0x9b, 0x69, 0x46, 0x6c, 0xed, 0x91, 0xe2, 0x6b, 0x0f, - 0x5f, 0xb7, 0x7a, 0xd6, 0xc8, 0xf4, 0x42, 0xeb, 0xd6, 0x36, 0x3d, 0x36, 0x61, 0x0b, 0x84, 0x3a, - 0xd4, 0x5e, 0x1a, 0xc3, 0xd1, 0x90, 0x2f, 0x5c, 0x44, 0xdd, 0x53, 0x46, 0x79, 0x85, 0x95, 0x4b, - 0x6e, 0xc2, 0x8a, 0x6f, 0xe5, 0x58, 0x60, 0x33, 0x04, 0x54, 0xe6, 0xa2, 0x40, 0xa5, 0x09, 0x0b, - 0x3b, 0xf8, 0xb9, 0xd1, 0xc3, 0xaf, 0xe5, 0x5c, 0xe7, 0x02, 0x94, 0x6d, 0xec, 0x0c, 0x0d, 0xd7, - 0xf5, 0x33, 0x72, 0x49, 0x09, 0x93, 0xe4, 0xff, 0x58, 0x80, 0xe5, 0x78, 0x74, 0xdc, 0x4b, 0xe0, - 0xa2, 0x6f, 0xa5, 0xac, 0x15, 0xf1, 0x0f, 0x0d, 0xd5, 0xa7, 0x37, 0x44, 0xd5, 0x92, 0xcb, 0xc2, - 0x10, 0xfc, 0x0a, 0x87, 0x97, 0x34, 0xc4, 0x23, 0x3d, 0x6b, 0x38, 0xd4, 0x4c, 0x5d, 0x1c, 0xc7, - 0xf1, 0x26, 0xf1, 0x9f, 0xe6, 0xf4, 0x89, 0xdb, 0x09, 0x99, 0x3e, 0x93, 0xc1, 0x23, 0x1b, 0x6e, - 0xc3, 0xa4, 0xf8, 0x2a, 0xcd, 0xea, 0x25, 0x05, 0x38, 0x69, 0xc7, 0x70, 0xd0, 0x26, 0xcc, 0x63, - 0xf3, 0xb9, 0x28, 0x40, 0x53, 0xce, 0xeb, 0x44, 0xfd, 0xa4, 0x50, 0x3e, 0x74, 0x1d, 0x16, 0x86, - 0x24, 0x2c, 0xc4, 0xd6, 0x7b, 0x2d, 0xe3, 0xd8, 0x4a, 0xe1, 0x6c, 0x68, 0x0b, 0x16, 0x75, 0x3a, - 0x4e, 0x62, 0x7f, 0x5d, 0x4f, 0x41, 0x6d, 0x29, 0x83, 0x22, 0x18, 0xd1, 0xae, 0x5f, 0x5e, 0x97, - 0xb2, 0xea, 0xe2, 0xd8, 0x50, 0xa4, 0xd6, 0xd8, 0xfb, 0xd1, 0x1a, 0x1b, 0xa8, 0xae, 0xad, 0xc9, - 0xba, 0xc6, 0x17, 0xda, 0x67, 0xa1, 0x38, 0xb0, 0xfa, 0x2c, 0x8c, 0xca, 0xec, 0xa4, 0x77, 0x60, - 0xf5, 0x69, 0x14, 0xad, 0x92, 0xed, 0x86, 0x6e, 0x98, 0x74, 0xf9, 0x2b, 0x2a, 0xac, 0x41, 0x26, - 0x1f, 0x7d, 0x50, 0x2d, 0xb3, 0x87, 0xeb, 0x15, 0xfa, 0xaa, 0x44, 0x29, 0x7b, 0x66, 0x8f, 0xd6, - 0xa5, 0x9e, 0x77, 0x52, 0xaf, 0x52, 0x3a, 0x79, 0x24, 0x3b, 0x49, 0x86, 0x8e, 0x2c, 0x67, 0xed, - 0x24, 0xd3, 0xf2, 0xbb, 0x00, 0x47, 0x1e, 0xc0, 0xe2, 0x0b, 0x96, 0x08, 0xea, 0x35, 0x2a, 0x7f, - 0x65, 0x72, 0x7a, 0xe1, 0x1a, 0x84, 0xe0, 0x77, 0xb9, 0x47, 0xf8, 0x7b, 0x09, 0xce, 0x6c, 0xd3, - 0x8d, 0x56, 0x28, 0x8f, 0xcd, 0x82, 0x4e, 0xde, 0xf2, 0x81, 0xe3, 0x4c, 0xc4, 0x2f, 0xfe, 0xdd, - 0x02, 0x37, 0x6e, 0x41, 0x55, 0x28, 0xe7, 0x2a, 0xf2, 0x53, 0x63, 0xcf, 0x15, 0x37, 0xdc, 0x94, - 0x3f, 0x86, 0xb5, 0xc4, 0x57, 0xf0, 0xbd, 0xce, 0x06, 0x2c, 0x05, 0xf9, 0xca, 0xff, 0x88, 0xb2, - 0x4f, 0x6b, 0xe9, 0xf2, 0x6d, 0x38, 0xdd, 0xf5, 0x34, 0xc7, 0x4b, 0xb8, 0x60, 0x0a, 0x59, 0x8a, - 0x2a, 0x47, 0x65, 0x39, 0xf0, 0xdb, 0x85, 0xd5, 0xae, 0x67, 0xd9, 0xaf, 0xa0, 0x94, 0x64, 0x1d, - 0xf2, 0xfd, 0xd6, 0x48, 0xac, 0x0f, 0xa2, 0x29, 0xaf, 0x31, 0x0c, 0x3c, 0xd9, 0xdb, 0x1d, 0x38, - 0xc3, 0x20, 0xe8, 0x57, 0xf9, 0x88, 0xb3, 0x02, 0x00, 0x4f, 0xea, 0x7d, 0x0a, 0xa7, 0x82, 0x65, - 0x31, 0x00, 0x77, 0x6e, 0x46, 0xc1, 0x9d, 0x0b, 0x63, 0x46, 0x3d, 0x82, 0xed, 0xfc, 0x79, 0x2e, - 0x94, 0xd7, 0x33, 0xa0, 0x9d, 0x3b, 0x51, 0x68, 0xe7, 0xe2, 0x24, 0xdd, 0x11, 0x64, 0x27, 0x19, - 0xb5, 0xf9, 0x94, 0xa8, 0xfd, 0x22, 0x81, 0xff, 0xcc, 0x67, 0x01, 0x68, 0x31, 0x6b, 0x7f, 0x23, - 0xf0, 0x8f, 0xc2, 0xe0, 0x1f, 0xbf, 0x6b, 0xff, 0xc4, 0xe0, 0x56, 0x0c, 0xfe, 0xd9, 0x98, 0x68, - 0xaf, 0x8f, 0xfe, 0xfc, 0xf5, 0x3c, 0x94, 0xfc, 0x77, 0x09, 0x9f, 0x27, 0xdd, 0x96, 0x4b, 0x71, - 0x5b, 0x78, 0x05, 0xce, 0x7f, 0xab, 0x15, 0x78, 0x7e, 0xea, 0x15, 0xf8, 0x1c, 0x94, 0xe8, 0x83, - 0xea, 0xe0, 0x23, 0xbe, 0xa2, 0x16, 0x29, 0x41, 0xc1, 0x47, 0x41, 0x18, 0x2e, 0xcc, 0x14, 0x86, - 0x31, 0xc0, 0x69, 0x31, 0x0e, 0x38, 0xdd, 0xf3, 0x57, 0x44, 0xb6, 0x88, 0x5e, 0x1e, 0xa3, 0x37, - 0x75, 0x2d, 0x6c, 0x47, 0xd7, 0x42, 0xb6, 0xae, 0xbe, 0x3b, 0x4e, 0xcb, 0xd8, 0x55, 0xf0, 0xbb, - 0x5c, 0x21, 0x0e, 0x18, 0x8a, 0x14, 0x8e, 0x45, 0x9e, 0x59, 0xef, 0x00, 0xf8, 0x49, 0x44, 0x40, - 0x49, 0xe7, 0xc6, 0x7c, 0xa3, 0x12, 0x62, 0x27, 0x6a, 0x23, 0x43, 0x13, 0x9c, 0x8a, 0x4d, 0x97, - 0x1f, 0x33, 0x8e, 0xc4, 0xfe, 0xb7, 0x10, 0xca, 0x2f, 0x19, 0xa7, 0x3d, 0xf7, 0x12, 0x40, 0xe7, - 0x8c, 0x51, 0x7c, 0x33, 0x8a, 0x73, 0xbe, 0x62, 0xd4, 0x25, 0x60, 0x4e, 0x5a, 0xb9, 0x68, 0x0e, - 0x7f, 0xcd, 0xd0, 0xa5, 0x12, 0xa7, 0x34, 0xe9, 0xce, 0xe0, 0xc8, 0x30, 0x0d, 0xf7, 0x98, 0xbd, - 0x5f, 0x60, 0x3b, 0x03, 0x41, 0x6a, 0xd2, 0x1b, 0x5b, 0xf8, 0xa5, 0xe1, 0xa9, 0x3d, 0x4b, 0xc7, - 0x34, 0xa6, 0x0b, 0x4a, 0x91, 0x10, 0xb6, 0x2d, 0x1d, 0x07, 0x33, 0xaf, 0xf8, 0x6a, 0x33, 0xaf, - 0x14, 0x9b, 0x79, 0x67, 0x60, 0xc1, 0xc1, 0x9a, 0x6b, 0x99, 0x7c, 0x1f, 0xce, 0x5b, 0x64, 0x68, - 0x86, 0xd8, 0x75, 0x49, 0x4f, 0xbc, 0x5c, 0xe3, 0xcd, 0x50, 0x99, 0xb9, 0x34, 0xb1, 0xcc, 0x1c, - 0x73, 0x8a, 0x14, 0x2b, 0x33, 0x2b, 0x13, 0xcb, 0xcc, 0xa9, 0x0e, 0x91, 0x82, 0x42, 0xbb, 0x3a, - 0x5d, 0xa1, 0x1d, 0xae, 0x4b, 0x97, 0x23, 0x75, 0xe9, 0x77, 0x39, 0x59, 0x7f, 0x25, 0xc1, 0x5a, - 0x62, 0x5a, 0xf1, 0xe9, 0x7a, 0x2b, 0x76, 0xcc, 0xb4, 0x31, 0xd1, 0x67, 0xfe, 0x29, 0xd3, 0xa3, - 0xc8, 0x29, 0xd3, 0x07, 0x93, 0x05, 0x5f, 0xfb, 0x21, 0xd3, 0x1f, 0x49, 0xf0, 0xe6, 0x81, 0xad, - 0xc7, 0x2a, 0x3c, 0xbe, 0xed, 0x9f, 0x3e, 0x71, 0xdc, 0x13, 0xb5, 0x7e, 0x6e, 0x56, 0x40, 0x86, - 0xc9, 0xc9, 0x32, 0x5c, 0xc8, 0x36, 0x83, 0x97, 0x4c, 0x3f, 0x82, 0xe5, 0xdd, 0x97, 0xb8, 0xd7, - 0x3d, 0x31, 0x7b, 0x33, 0x98, 0x56, 0x83, 0x7c, 0x6f, 0xa8, 0x73, 0x38, 0x95, 0x3c, 0x86, 0xab, - 0xc0, 0x7c, 0xb4, 0x0a, 0x54, 0xa1, 0x16, 0xf4, 0xc0, 0x87, 0xf7, 0x0c, 0x19, 0x5e, 0x9d, 0x30, - 0x13, 0xe5, 0x4b, 0x0a, 0x6f, 0x71, 0x3a, 0x76, 0xd8, 0xa5, 0x0c, 0x46, 0xc7, 0x8e, 0x13, 0xcd, - 0x16, 0xf9, 0x68, 0xb6, 0x90, 0xff, 0x4c, 0x82, 0x32, 0xe9, 0xe1, 0x5b, 0xd9, 0xcf, 0xb7, 0x5a, - 0xf9, 0x60, 0xab, 0xe5, 0xef, 0xd8, 0xe6, 0xc3, 0x3b, 0xb6, 0xc0, 0xf2, 0x02, 0x25, 0x27, 0x2d, - 0x5f, 0xf0, 0xe9, 0xd8, 0x71, 0xe4, 0x0b, 0xb0, 0xc4, 0x6c, 0xe3, 0x5f, 0x5e, 0x83, 0xfc, 0xc8, - 0x19, 0x88, 0x38, 0x1a, 0x39, 0x03, 0xf9, 0x8f, 0x25, 0xa8, 0x34, 0x3d, 0x4f, 0xeb, 0x1d, 0xcf, - 0xf0, 0x01, 0xbe, 0x71, 0xb9, 0xb0, 0x71, 0xc9, 0x8f, 0x08, 0xcc, 0x9d, 0xcf, 0x30, 0xb7, 0x10, - 0x31, 0x57, 0x86, 0xaa, 0xb0, 0x25, 0xd3, 0xe0, 0x36, 0xa0, 0x8e, 0xe5, 0x78, 0x0f, 0x2d, 0xe7, - 0x85, 0xe6, 0xe8, 0xb3, 0xed, 0xc0, 0x10, 0xcc, 0xf3, 0x5b, 0xbc, 0xf9, 0x2b, 0x05, 0x85, 0x3e, - 0xcb, 0x97, 0xe1, 0x54, 0x44, 0x5f, 0x66, 0xc7, 0xf7, 0xa1, 0x4c, 0xf3, 0x3e, 0x2f, 0xc5, 0x6f, - 0x84, 0xcf, 0x75, 0xa6, 0x5a, 0x25, 0xe4, 0xdf, 0x85, 0x15, 0x52, 0x1f, 0x50, 0xba, 0x3f, 0x15, - 0xbf, 0x17, 0xab, 0x53, 0xcf, 0x67, 0x28, 0x8a, 0xd5, 0xa8, 0x7f, 0x23, 0x41, 0x81, 0xd2, 0x13, - 0x6b, 0xf6, 0x39, 0x28, 0x39, 0xd8, 0xb6, 0x54, 0x4f, 0xeb, 0xfb, 0x77, 0xa6, 0x09, 0x61, 0x5f, - 0xeb, 0x53, 0x34, 0x97, 0xbe, 0xd4, 0x8d, 0x3e, 0x76, 0x3d, 0x71, 0x71, 0xba, 0x4c, 0x68, 0x3b, - 0x8c, 0x44, 0x9c, 0xe4, 0x1a, 0xbf, 0xcf, 0xea, 0xce, 0x79, 0x85, 0x3e, 0xa3, 0x4d, 0x76, 0x8d, - 0x6f, 0x1a, 0xec, 0x9d, 0x5e, 0xf2, 0x6b, 0x40, 0x31, 0x06, 0x97, 0xfb, 0x6d, 0x79, 0x17, 0x50, - 0xd8, 0x0b, 0xdc, 0xdf, 0xd7, 0x61, 0x81, 0x3a, 0x49, 0x54, 0x47, 0x6b, 0x19, 0x6e, 0x50, 0x38, - 0x9b, 0xac, 0x01, 0x62, 0x0e, 0x8e, 0x54, 0x44, 0xb3, 0x8f, 0xca, 0x98, 0x0a, 0xe9, 0xef, 0x24, - 0x38, 0x15, 0xe9, 0x83, 0xdb, 0xfa, 0x5e, 0xb4, 0x93, 0x4c, 0x53, 0x79, 0x07, 0xdb, 0x91, 0x25, - 0xe1, 0x7a, 0x96, 0x49, 0xbf, 0xa6, 0xe5, 0xe0, 0x1f, 0x24, 0x80, 0xe6, 0xc8, 0x3b, 0xe6, 0xc8, - 0x60, 0x78, 0x64, 0xa4, 0xe8, 0xc8, 0x90, 0x77, 0xb6, 0xe6, 0xba, 0x2f, 0x2c, 0x47, 0xec, 0x69, - 0xfc, 0x36, 0xc5, 0xf0, 0x46, 0xde, 0xb1, 0x38, 0x33, 0x23, 0xcf, 0xe8, 0x22, 0x54, 0xd9, 0x3d, - 0x7d, 0x55, 0xd3, 0x75, 0x07, 0xbb, 0x2e, 0x3f, 0x3c, 0xab, 0x30, 0x6a, 0x93, 0x11, 0x09, 0x9b, - 0x41, 0x51, 0x6d, 0xef, 0x44, 0xf5, 0xac, 0x67, 0xd8, 0xe4, 0x7b, 0x93, 0x8a, 0xa0, 0xee, 0x13, - 0x22, 0x3b, 0x45, 0xe8, 0x1b, 0xae, 0xe7, 0x08, 0x36, 0x71, 0xd0, 0xc2, 0xa9, 0x94, 0x8d, 0x0c, - 0x4a, 0xad, 0x33, 0x1a, 0x0c, 0x98, 0x8b, 0x5f, 0x7d, 0xd8, 0xdf, 0xe7, 0x1f, 0x94, 0xcb, 0x8a, - 0xe9, 0xc0, 0x69, 0xfc, 0x73, 0x5f, 0x23, 0x08, 0xf3, 0x3e, 0xac, 0x84, 0xbe, 0x81, 0x87, 0x55, - 0xa4, 0x88, 0x94, 0xa2, 0x45, 0xa4, 0xfc, 0x08, 0x10, 0xc3, 0x1d, 0xbe, 0xe5, 0x77, 0xcb, 0xa7, - 0xe1, 0x54, 0x44, 0x11, 0x5f, 0x89, 0xaf, 0x41, 0x85, 0x5f, 0x89, 0xe2, 0x81, 0x72, 0x16, 0x8a, - 0x24, 0xa3, 0xf6, 0x0c, 0x5d, 0x1c, 0xa8, 0x2e, 0xda, 0x96, 0xbe, 0x6d, 0xe8, 0x8e, 0xfc, 0x29, - 0x54, 0x14, 0xd6, 0x0f, 0xe7, 0x7d, 0x08, 0x55, 0x7e, 0x81, 0x4a, 0x8d, 0x5c, 0x8d, 0x4c, 0xbb, - 0x7a, 0x1f, 0xee, 0x44, 0xa9, 0x98, 0xe1, 0xa6, 0xac, 0x43, 0x83, 0x95, 0x0c, 0x11, 0xf5, 0xe2, - 0x63, 0x1f, 0x82, 0xb8, 0x31, 0x30, 0xb1, 0x97, 0xa8, 0x7c, 0xc5, 0x09, 0x37, 0xe5, 0xf3, 0x70, - 0x2e, 0xb5, 0x17, 0xee, 0x09, 0x1b, 0x6a, 0xc1, 0x0b, 0x76, 0x7f, 0xcf, 0x3f, 0x31, 0x96, 0x42, - 0x27, 0xc6, 0x67, 0xfc, 0x22, 0x31, 0x27, 0x16, 0x31, 0x5a, 0x01, 0x06, 0xe5, 0x7e, 0x3e, 0xab, - 0xdc, 0x9f, 0x8f, 0x94, 0xfb, 0x72, 0xd7, 0xf7, 0x27, 0xdf, 0x86, 0x3d, 0xa0, 0xdb, 0x45, 0xd6, - 0xb7, 0x48, 0x88, 0xf2, 0xb8, 0xaf, 0x64, 0xac, 0x4a, 0x48, 0x4a, 0xbe, 0x0a, 0x95, 0x68, 0x6a, - 0x0c, 0xe5, 0x39, 0x29, 0x91, 0xe7, 0xaa, 0xb1, 0x14, 0xf7, 0x51, 0xac, 0x02, 0xce, 0xf6, 0x71, - 0xac, 0xfe, 0xbd, 0x1b, 0x49, 0x76, 0xd7, 0x52, 0x0e, 0x7b, 0x7f, 0x4d, 0x79, 0x6e, 0x95, 0xaf, - 0x07, 0x0f, 0x5d, 0x22, 0xcf, 0x3f, 0x5a, 0x7e, 0x0b, 0xca, 0x07, 0x59, 0xbf, 0xeb, 0x98, 0x17, - 0x17, 0x2b, 0x6e, 0xc2, 0xea, 0x43, 0x63, 0x80, 0xdd, 0x13, 0xd7, 0xc3, 0xc3, 0x16, 0x4d, 0x4a, - 0x47, 0x06, 0x76, 0xd0, 0x3a, 0x00, 0xdd, 0xc2, 0xd8, 0x96, 0xe1, 0x5f, 0xf7, 0x0f, 0x51, 0xe4, - 0xff, 0x94, 0x60, 0x39, 0x10, 0x3c, 0xa0, 0x5b, 0xb7, 0x37, 0xa0, 0x44, 0xbe, 0xd7, 0xf5, 0xb4, - 0xa1, 0x2d, 0xce, 0xb3, 0x7c, 0x02, 0xba, 0x03, 0x85, 0x23, 0x57, 0x40, 0x46, 0xa9, 0x00, 0x7a, - 0x9a, 0x21, 0xca, 0xfc, 0x91, 0xdb, 0xd2, 0xd1, 0xc7, 0x00, 0x23, 0x17, 0xeb, 0xfc, 0x0c, 0x2b, - 0x9f, 0x55, 0x2d, 0x1c, 0x84, 0x0f, 0xc2, 0x89, 0x00, 0xbb, 0x93, 0x71, 0x17, 0xca, 0x86, 0x69, - 0xe9, 0x98, 0x1e, 0x4e, 0xea, 0x1c, 0x55, 0x9a, 0x20, 0x0e, 0x4c, 0xe2, 0xc0, 0xc5, 0xba, 0x8c, - 0xf9, 0x5a, 0x28, 0xfc, 0xcb, 0x03, 0xa5, 0x0d, 0x2b, 0x2c, 0x69, 0x1d, 0xf9, 0x86, 0x8b, 0x88, - 0xdd, 0x18, 0xf7, 0x75, 0xd4, 0x5b, 0x4a, 0xcd, 0xe0, 0xa5, 0x8d, 0x10, 0x95, 0x6f, 0xc3, 0xe9, - 0xc8, 0x0e, 0x69, 0x86, 0x2d, 0x8b, 0xdc, 0x89, 0x01, 0x25, 0x41, 0x38, 0x73, 0x18, 0x42, 0x44, - 0xf3, 0x24, 0x18, 0xc2, 0x65, 0x30, 0x84, 0x2b, 0x7f, 0x01, 0x67, 0x23, 0x88, 0x4e, 0xc4, 0xa2, - 0xbb, 0xb1, 0xca, 0xed, 0xd2, 0x24, 0xad, 0xb1, 0x12, 0xee, 0x7f, 0x24, 0x58, 0x4d, 0x63, 0x78, - 0x45, 0xc4, 0xf1, 0x47, 0x19, 0x17, 0xf5, 0x6e, 0x4d, 0x67, 0xd6, 0x6f, 0x04, 0xad, 0xdd, 0x87, - 0x46, 0x9a, 0x3f, 0x93, 0xa3, 0x94, 0x9f, 0x65, 0x94, 0x7e, 0x96, 0x0f, 0x21, 0xef, 0x4d, 0xcf, - 0x73, 0x8c, 0xc3, 0x11, 0x09, 0xf9, 0xd7, 0x8e, 0x66, 0xb5, 0x7c, 0x5c, 0x86, 0xb9, 0xf6, 0xc6, - 0x18, 0xf1, 0xc0, 0x8e, 0x54, 0x6c, 0xe6, 0xb3, 0x28, 0x36, 0xc3, 0x30, 0xf5, 0x9b, 0xd3, 0xe9, - 0xfb, 0xad, 0x05, 0x40, 0x7f, 0x96, 0x83, 0x6a, 0x74, 0x88, 0xd0, 0x2e, 0x80, 0xe6, 0x5b, 0xce, - 0x27, 0xca, 0xc5, 0xa9, 0x3e, 0x53, 0x09, 0x09, 0xa2, 0x77, 0x21, 0xdf, 0xb3, 0x47, 0x7c, 0xd4, - 0x52, 0x0e, 0x83, 0xb7, 0xed, 0x11, 0xcb, 0x28, 0x84, 0x8d, 0xec, 0xa9, 0xd8, 0xd9, 0x7e, 0x76, - 0x96, 0x7c, 0x4a, 0xdf, 0x33, 0x19, 0xce, 0x8c, 0x1e, 0x43, 0xf5, 0x85, 0x63, 0x78, 0xda, 0xe1, - 0x00, 0xab, 0x03, 0xed, 0x04, 0x3b, 0x3c, 0x4b, 0x4e, 0x91, 0xc8, 0x2a, 0x42, 0xf0, 0x09, 0x91, - 0x93, 0xff, 0x10, 0x8a, 0xc2, 0xa2, 0x09, 0x2b, 0xc2, 0x3e, 0xac, 0x8d, 0x08, 0x9b, 0x4a, 0xef, - 0xca, 0x99, 0x9a, 0x69, 0xa9, 0x2e, 0x26, 0xcb, 0xb8, 0xf8, 0x5d, 0xc0, 0x84, 0x14, 0xbd, 0x4a, - 0xa5, 0xb7, 0x2d, 0x07, 0xb7, 0x35, 0xd3, 0xea, 0x32, 0x51, 0xf9, 0x39, 0x94, 0x43, 0x1f, 0x38, - 0xc1, 0x84, 0x16, 0xac, 0x88, 0xa3, 0x78, 0x17, 0x7b, 0x7c, 0x79, 0x99, 0xaa, 0xf3, 0x65, 0x2e, - 0xd7, 0xc5, 0x1e, 0xbb, 0x3e, 0x71, 0x17, 0xce, 0x2a, 0xd8, 0xb2, 0xb1, 0xe9, 0x8f, 0xe7, 0x13, - 0xab, 0x3f, 0x43, 0x06, 0x7f, 0x03, 0x1a, 0x69, 0xf2, 0x2c, 0x3f, 0x5c, 0xbb, 0x04, 0x45, 0xf1, - 0x23, 0x5d, 0xb4, 0x08, 0xf9, 0xfd, 0xed, 0x4e, 0x6d, 0x8e, 0x3c, 0x1c, 0xec, 0x74, 0x6a, 0x12, - 0x2a, 0xc2, 0x7c, 0x77, 0x7b, 0xbf, 0x53, 0xcb, 0x5d, 0x1b, 0x42, 0x2d, 0xfe, 0x0b, 0x55, 0xb4, - 0x06, 0xa7, 0x3a, 0xca, 0x5e, 0xa7, 0xf9, 0xa8, 0xb9, 0xdf, 0xda, 0x6b, 0xab, 0x1d, 0xa5, 0xf5, - 0x49, 0x73, 0x7f, 0xb7, 0x36, 0x87, 0x36, 0xe0, 0x7c, 0xf8, 0xc5, 0xe3, 0xbd, 0xee, 0xbe, 0xba, - 0xbf, 0xa7, 0x6e, 0xef, 0xb5, 0xf7, 0x9b, 0xad, 0xf6, 0xae, 0x52, 0x93, 0xd0, 0x79, 0x38, 0x1b, - 0x66, 0x79, 0xd0, 0xda, 0x69, 0x29, 0xbb, 0xdb, 0xe4, 0xb9, 0xf9, 0xa4, 0x96, 0xbb, 0x76, 0x03, - 0x2a, 0x91, 0x1f, 0x94, 0x12, 0x93, 0x3a, 0x7b, 0x3b, 0xb5, 0x39, 0x54, 0x81, 0x52, 0x58, 0x4f, - 0x11, 0xe6, 0xdb, 0x7b, 0x3b, 0xbb, 0xb5, 0xdc, 0xb5, 0xdb, 0xb0, 0x1c, 0xbb, 0xdf, 0x8b, 0x56, - 0xa0, 0xd2, 0x6d, 0xb6, 0x77, 0x1e, 0xec, 0x7d, 0xa6, 0x2a, 0xbb, 0xcd, 0x9d, 0xcf, 0x6b, 0x73, - 0x68, 0x15, 0x6a, 0x82, 0xd4, 0xde, 0xdb, 0x67, 0x54, 0xe9, 0xda, 0xb3, 0xd8, 0x1c, 0xc3, 0xe8, - 0x34, 0xac, 0xf8, 0xdd, 0xa8, 0xdb, 0xca, 0x6e, 0x73, 0x7f, 0x97, 0xf4, 0x1e, 0x21, 0x2b, 0x07, - 0xed, 0x76, 0xab, 0xfd, 0xa8, 0x26, 0x11, 0xad, 0x01, 0x79, 0xf7, 0xb3, 0x16, 0x61, 0xce, 0x45, - 0x99, 0x0f, 0xda, 0x3f, 0x68, 0xef, 0x7d, 0xda, 0xae, 0xe5, 0xb7, 0x7e, 0xb1, 0x02, 0x55, 0x51, - 0xe8, 0x61, 0x87, 0xde, 0x6a, 0xe9, 0xc0, 0xa2, 0xf8, 0xd1, 0x77, 0x4a, 0x86, 0x8e, 0xfe, 0x54, - 0xbd, 0xb1, 0x31, 0x86, 0x83, 0xd7, 0xdb, 0x73, 0xe8, 0x90, 0xd6, 0xbf, 0xa1, 0xfb, 0xd6, 0x97, - 0x52, 0xab, 0xcd, 0xc4, 0x15, 0xef, 0xc6, 0xe5, 0x89, 0x7c, 0x7e, 0x1f, 0x98, 0x94, 0xb8, 0xe1, - 0x9f, 0x34, 0xa1, 0xcb, 0x69, 0xb5, 0x69, 0xca, 0x6f, 0xa6, 0x1a, 0x57, 0x26, 0x33, 0xfa, 0xdd, - 0x3c, 0x83, 0x5a, 0xfc, 0xe7, 0x4d, 0x28, 0x05, 0x3a, 0xcd, 0xf8, 0x0d, 0x55, 0xe3, 0xda, 0x34, - 0xac, 0xe1, 0xce, 0x12, 0xbf, 0xd7, 0xb9, 0x3a, 0xcd, 0xef, 0x1a, 0x32, 0x3b, 0xcb, 0xfa, 0x09, - 0x04, 0x73, 0x60, 0xf4, 0x8a, 0x34, 0x4a, 0xfd, 0x71, 0x4c, 0xca, 0x4d, 0xfc, 0x34, 0x07, 0xa6, - 0xdf, 0xb6, 0x96, 0xe7, 0xd0, 0x31, 0x2c, 0xc7, 0xae, 0x27, 0xa0, 0x14, 0xf1, 0xf4, 0x7b, 0x18, - 0x8d, 0xab, 0x53, 0x70, 0x46, 0x23, 0x22, 0x7c, 0x1d, 0x21, 0x3d, 0x22, 0x52, 0x2e, 0x3b, 0xa4, - 0x47, 0x44, 0xea, 0xcd, 0x06, 0x1a, 0xdc, 0x91, 0x6b, 0x08, 0x69, 0xc1, 0x9d, 0x76, 0xf9, 0xa1, - 0x71, 0x79, 0x22, 0x5f, 0xd8, 0x69, 0xb1, 0x4b, 0x09, 0x69, 0x4e, 0x4b, 0xbf, 0xf4, 0xd0, 0xb8, - 0x3a, 0x05, 0x67, 0x3c, 0x0a, 0x82, 0x23, 0xce, 0xac, 0x28, 0x48, 0x1c, 0xc8, 0x67, 0x45, 0x41, - 0xf2, 0xb4, 0x94, 0x47, 0x41, 0xec, 0x68, 0xf2, 0xca, 0x14, 0x47, 0x29, 0xd9, 0x51, 0x90, 0x7e, - 0xe8, 0x22, 0xcf, 0xa1, 0x9f, 0x4a, 0x50, 0xcf, 0x3a, 0xa6, 0x40, 0x29, 0xf5, 0xdd, 0x84, 0x93, - 0x95, 0xc6, 0xd6, 0x2c, 0x22, 0xbe, 0x15, 0x5f, 0x01, 0x4a, 0xae, 0x7b, 0xe8, 0x9d, 0xb4, 0x91, - 0xc9, 0x58, 0x5d, 0x1b, 0xef, 0x4e, 0xc7, 0xec, 0x77, 0xd9, 0x85, 0xa2, 0x38, 0x18, 0x41, 0x29, - 0x59, 0x3a, 0x76, 0x2c, 0xd3, 0x90, 0xc7, 0xb1, 0xf8, 0x4a, 0x1f, 0xc1, 0x3c, 0xa1, 0xa2, 0xf3, - 0xe9, 0xdc, 0x42, 0xd9, 0x7a, 0xd6, 0x6b, 0x5f, 0xd1, 0x53, 0x58, 0x60, 0x27, 0x01, 0x28, 0x05, - 0x79, 0x88, 0x9c, 0x57, 0x34, 0x2e, 0x64, 0x33, 0xf8, 0xea, 0xbe, 0x64, 0xff, 0x0f, 0x84, 0x83, - 0xfc, 0xe8, 0xed, 0xf4, 0x1f, 0x58, 0x47, 0xcf, 0x14, 0x1a, 0x17, 0x27, 0x70, 0x85, 0x27, 0x45, - 0xac, 0xea, 0xbd, 0x3c, 0x71, 0xeb, 0x92, 0x3d, 0x29, 0xd2, 0x37, 0x47, 0x2c, 0x48, 0x92, 0x9b, - 0xa7, 0xb4, 0x20, 0xc9, 0xdc, 0xb2, 0xa6, 0x05, 0x49, 0xf6, 0x7e, 0x4c, 0x9e, 0x43, 0x1e, 0x9c, - 0x4a, 0x81, 0xca, 0xd0, 0xbb, 0x59, 0x41, 0x9e, 0x86, 0xdb, 0x35, 0xde, 0x9b, 0x92, 0x3b, 0x3c, - 0xf8, 0x7c, 0xd2, 0xbf, 0x99, 0x8d, 0x1f, 0x65, 0x0e, 0x7e, 0x7c, 0x8a, 0x6f, 0xfd, 0x4b, 0x1e, - 0x96, 0x18, 0x0c, 0xca, 0x2b, 0x98, 0xcf, 0x01, 0x82, 0x13, 0x08, 0xf4, 0x56, 0xba, 0x4f, 0x22, - 0xa7, 0x34, 0x8d, 0xb7, 0xc7, 0x33, 0x85, 0x03, 0x2d, 0x84, 0xe6, 0xa7, 0x05, 0x5a, 0xf2, 0xd0, - 0x22, 0x2d, 0xd0, 0x52, 0x8e, 0x04, 0xe4, 0x39, 0xf4, 0x09, 0x94, 0x7c, 0xd8, 0x18, 0xa5, 0xc1, - 0xce, 0x31, 0x5c, 0xbc, 0xf1, 0xd6, 0x58, 0x9e, 0xb0, 0xd5, 0x21, 0x4c, 0x38, 0xcd, 0xea, 0x24, - 0xf6, 0x9c, 0x66, 0x75, 0x1a, 0xb0, 0x1c, 0xf8, 0x84, 0x21, 0x47, 0x99, 0x3e, 0x89, 0x00, 0x77, - 0x99, 0x3e, 0x89, 0xc2, 0x4f, 0xf2, 0xdc, 0x83, 0x4b, 0xbf, 0xfc, 0x7a, 0x5d, 0xfa, 0xa7, 0xaf, - 0xd7, 0xe7, 0x7e, 0xf2, 0xcd, 0xba, 0xf4, 0xcb, 0x6f, 0xd6, 0xa5, 0x7f, 0xfc, 0x66, 0x5d, 0xfa, - 0xd7, 0x6f, 0xd6, 0xa5, 0x3f, 0xfd, 0xb7, 0xf5, 0xb9, 0x1f, 0x16, 0x85, 0xf4, 0xe1, 0x02, 0xfd, - 0xaf, 0x3e, 0x1f, 0xfc, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1a, 0xde, 0xe7, 0x02, 0x9b, 0x49, - 0x00, 0x00, + // 4941 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x3c, 0x4d, 0x8f, 0x1b, 0x47, + 0x76, 0xd3, 0xe4, 0x70, 0x86, 0x7c, 0x1c, 0x72, 0xa8, 0xd2, 0x48, 0x43, 0x51, 0x96, 0xac, 0x69, + 0xdb, 0xfa, 0xb2, 0x3d, 0xb2, 0xc6, 0x5e, 0x39, 0x92, 0xbc, 0xb2, 0x29, 0xce, 0x48, 0x62, 0x56, + 0xe2, 0x30, 0xcd, 0x19, 0x7f, 0xac, 0x8d, 0xb4, 0x7b, 0xd8, 0x35, 0x9c, 0x5e, 0x91, 0xdd, 0xed, + 0xee, 0xe6, 0x48, 0x93, 0x00, 0xc1, 0x02, 0x8b, 0xec, 0x21, 0x40, 0x80, 0x9c, 0x73, 0xdc, 0x04, + 0xc8, 0x21, 0xe7, 0x20, 0x40, 0x72, 0x4a, 0x90, 0xc3, 0x5e, 0x02, 0xe4, 0xb4, 0x48, 0x90, 0x4b, + 0xec, 0x24, 0x08, 0x10, 0x20, 0x41, 0x7e, 0x40, 0x0e, 0x41, 0x7d, 0xf5, 0x77, 0xf3, 0x43, 0xd6, + 0xae, 0x37, 0xa7, 0x61, 0xbd, 0x7a, 0xef, 0xd5, 0xab, 0x57, 0xaf, 0x5e, 0xbd, 0x7a, 0xaf, 0x7a, + 0xa0, 0xa4, 0xd9, 0xc6, 0xa6, 0xed, 0x58, 0x9e, 0x85, 0x6a, 0xce, 0xd8, 0xf4, 0x8c, 0x11, 0xde, + 0x3c, 0xbe, 0xa9, 0x0d, 0xed, 0x23, 0x6d, 0xab, 0xf1, 0xf6, 0xc0, 0xf0, 0x8e, 0xc6, 0x07, 0x9b, + 0x7d, 0x6b, 0x74, 0x63, 0x60, 0x0d, 0xac, 0x1b, 0x14, 0xf1, 0x60, 0x7c, 0x48, 0x5b, 0xb4, 0x41, + 0x7f, 0x31, 0x06, 0xf2, 0x75, 0xa8, 0x7e, 0x8c, 0x1d, 0xd7, 0xb0, 0x4c, 0x05, 0x7f, 0x35, 0xc6, + 0xae, 0x87, 0xea, 0xb0, 0x7c, 0xcc, 0x20, 0x75, 0xe9, 0x92, 0x74, 0xb5, 0xa4, 0x88, 0xa6, 0xfc, + 0x67, 0x12, 0xac, 0xfa, 0xc8, 0xae, 0x6d, 0x99, 0x2e, 0xce, 0xc6, 0x46, 0x1b, 0xb0, 0xc2, 0x85, + 0x53, 0x4d, 0x6d, 0x84, 0xeb, 0x39, 0xda, 0x5d, 0xe6, 0xb0, 0x8e, 0x36, 0xc2, 0xe8, 0x0a, 0xac, + 0x0a, 0x14, 0xc1, 0x24, 0x4f, 0xb1, 0xaa, 0x1c, 0xcc, 0x47, 0x43, 0x9b, 0x70, 0x5a, 0x20, 0x6a, + 0xb6, 0xe1, 0x23, 0x2f, 0x52, 0xe4, 0x53, 0xbc, 0xab, 0x69, 0x1b, 0x1c, 0x5f, 0xfe, 0x1c, 0x4a, + 0xdb, 0x9d, 0x5e, 0xcb, 0x32, 0x0f, 0x8d, 0x01, 0x11, 0xd1, 0xc5, 0x0e, 0xa1, 0xa9, 0x4b, 0x97, + 0xf2, 0x44, 0x44, 0xde, 0x44, 0x0d, 0x28, 0xba, 0x58, 0x73, 0xfa, 0x47, 0xd8, 0xad, 0xe7, 0x68, + 0x97, 0xdf, 0x26, 0x54, 0x96, 0xed, 0x19, 0x96, 0xe9, 0xd6, 0xf3, 0x8c, 0x8a, 0x37, 0xe5, 0x9f, + 0x49, 0x50, 0xee, 0x5a, 0x8e, 0xf7, 0x44, 0xb3, 0x6d, 0xc3, 0x1c, 0xa0, 0x5b, 0x50, 0xa4, 0xba, + 0xec, 0x5b, 0x43, 0xaa, 0x83, 0xea, 0x56, 0x63, 0x33, 0xbe, 0x2c, 0x9b, 0x5d, 0x8e, 0xa1, 0xf8, + 0xb8, 0xe8, 0x0d, 0xa8, 0xf6, 0x2d, 0xd3, 0xd3, 0x0c, 0x13, 0x3b, 0xaa, 0x6d, 0x39, 0x1e, 0x55, + 0x51, 0x41, 0xa9, 0xf8, 0x50, 0x32, 0x0a, 0x3a, 0x0f, 0xa5, 0x23, 0xcb, 0xf5, 0x18, 0x46, 0x9e, + 0x62, 0x14, 0x09, 0x80, 0x76, 0xae, 0xc3, 0x32, 0xed, 0x34, 0x6c, 0xae, 0x8c, 0x25, 0xd2, 0x6c, + 0xdb, 0xf2, 0x2f, 0x24, 0x28, 0x3c, 0xb1, 0xc6, 0xa6, 0x17, 0x1b, 0x46, 0xf3, 0x8e, 0xf8, 0x42, + 0x85, 0x86, 0xd1, 0xbc, 0xa3, 0x60, 0x18, 0x82, 0xc1, 0xd6, 0x8a, 0x0d, 0x43, 0x3a, 0x1b, 0x50, + 0x74, 0xb0, 0xa6, 0x5b, 0xe6, 0xf0, 0x84, 0x8a, 0x50, 0x54, 0xfc, 0x36, 0x59, 0x44, 0x17, 0x0f, + 0x0d, 0x73, 0xfc, 0x5c, 0x75, 0xf0, 0x50, 0x3b, 0xc0, 0x43, 0x2a, 0x4a, 0x51, 0xa9, 0x72, 0xb0, + 0xc2, 0xa0, 0x68, 0x1b, 0xca, 0xb6, 0x63, 0xd9, 0xda, 0x40, 0x23, 0x7a, 0xac, 0x17, 0xa8, 0xaa, + 0xe4, 0xa4, 0xaa, 0xa8, 0xd8, 0xdd, 0x00, 0x53, 0x09, 0x93, 0xc9, 0xff, 0x21, 0xc1, 0x2a, 0x31, + 0x1e, 0xd7, 0xd6, 0xfa, 0x78, 0x97, 0x2e, 0x09, 0xba, 0x0d, 0xcb, 0x26, 0xf6, 0x9e, 0x59, 0xce, + 0x53, 0xbe, 0x00, 0xaf, 0x26, 0xb9, 0xfa, 0x34, 0x4f, 0x2c, 0x1d, 0x2b, 0x02, 0x1f, 0xdd, 0x84, + 0xbc, 0x6d, 0xe8, 0x74, 0xc2, 0x33, 0x90, 0x11, 0x5c, 0x42, 0x62, 0xd8, 0x7d, 0xaa, 0x87, 0x59, + 0x48, 0x0c, 0xbb, 0x8f, 0xde, 0x85, 0xc5, 0xb1, 0x8b, 0x1d, 0xaa, 0x98, 0x19, 0x68, 0x28, 0xb2, + 0x2c, 0x03, 0xb4, 0x4d, 0xef, 0xd6, 0x7b, 0x1f, 0x6b, 0xc3, 0x31, 0x46, 0x6b, 0x50, 0x38, 0x26, + 0x3f, 0xe8, 0x0c, 0xf3, 0x0a, 0x6b, 0xc8, 0x5f, 0xe7, 0xe1, 0xfc, 0x63, 0xa2, 0xe4, 0x9e, 0x66, + 0xea, 0x07, 0xd6, 0xf3, 0x1e, 0xee, 0x8f, 0x1d, 0xc3, 0x3b, 0x69, 0x59, 0xa6, 0x87, 0x9f, 0x7b, + 0xa8, 0x03, 0xa7, 0x4c, 0xc1, 0x5a, 0x15, 0xf6, 0x4c, 0x38, 0x94, 0xb7, 0x36, 0x26, 0x48, 0xc1, + 0xf4, 0xaa, 0xd4, 0xcc, 0x28, 0xc0, 0x45, 0x8f, 0x82, 0xc5, 0x16, 0xdc, 0x72, 0x94, 0x5b, 0xca, + 0x9c, 0x7a, 0x3b, 0x54, 0x32, 0xce, 0x4b, 0x58, 0x83, 0xe0, 0xf4, 0x01, 0x10, 0x57, 0xa0, 0x6a, + 0xae, 0x4a, 0x35, 0x93, 0xa7, 0x5c, 0x5e, 0x49, 0x72, 0x09, 0x54, 0xa0, 0x94, 0x9c, 0xb1, 0xd9, + 0x74, 0xf7, 0x5d, 0xec, 0xa0, 0x7b, 0xd4, 0xb9, 0x10, 0xea, 0x81, 0x63, 0x8d, 0xed, 0x7a, 0x71, + 0x06, 0x72, 0xa0, 0xe4, 0x0f, 0x09, 0x3e, 0xf5, 0x3c, 0xdc, 0x80, 0x55, 0xc7, 0xb2, 0xbc, 0x43, + 0x57, 0x18, 0xad, 0x00, 0x2b, 0x14, 0x8a, 0x6e, 0xc0, 0x69, 0x77, 0x6c, 0xdb, 0x43, 0x3c, 0xc2, + 0xa6, 0xa7, 0x0d, 0xd9, 0x70, 0x6e, 0xbd, 0x70, 0x29, 0x7f, 0x35, 0xaf, 0xa0, 0x70, 0x17, 0x65, + 0xec, 0xa2, 0x8b, 0x00, 0xb6, 0x63, 0x1c, 0x1b, 0x43, 0x3c, 0xc0, 0x7a, 0x7d, 0x89, 0x32, 0x0d, + 0x41, 0xd0, 0x3b, 0xb0, 0xe6, 0xe2, 0x7e, 0xdf, 0x1a, 0xd9, 0xaa, 0xed, 0x58, 0x87, 0xc6, 0x10, + 0xb3, 0x2d, 0xb7, 0x4c, 0xb7, 0x1c, 0xe2, 0x7d, 0x5d, 0xd6, 0x45, 0x36, 0x9f, 0xfc, 0xb3, 0x1c, + 0x9c, 0xa1, 0x9a, 0xec, 0x5a, 0x3a, 0x5f, 0x66, 0xee, 0xd9, 0x5e, 0x83, 0x4a, 0x9f, 0x0a, 0xa4, + 0xda, 0x9a, 0x83, 0x4d, 0x8f, 0xef, 0xec, 0x15, 0x06, 0xec, 0x52, 0x18, 0xfa, 0x14, 0x6a, 0x2e, + 0xb7, 0x0a, 0xb5, 0xcf, 0xcc, 0x82, 0xaf, 0xd9, 0xdb, 0x49, 0x75, 0x4d, 0xb0, 0x25, 0x65, 0xd5, + 0x4d, 0x18, 0xd7, 0xb2, 0x7b, 0xe2, 0xf6, 0xbd, 0x21, 0x73, 0x91, 0xe5, 0xad, 0xf7, 0x32, 0x18, + 0xc6, 0x05, 0xdf, 0xec, 0x31, 0xb2, 0x1d, 0xd3, 0x73, 0x4e, 0x14, 0xc1, 0xa4, 0x71, 0x07, 0x56, + 0xc2, 0x1d, 0xa8, 0x06, 0xf9, 0xa7, 0xf8, 0x84, 0x4f, 0x8a, 0xfc, 0x0c, 0x36, 0x01, 0x73, 0x50, + 0xac, 0x71, 0x27, 0xf7, 0x1b, 0x92, 0xec, 0x00, 0x0a, 0x46, 0x79, 0x82, 0x3d, 0x4d, 0xd7, 0x3c, + 0x0d, 0x21, 0x58, 0xa4, 0x67, 0x0f, 0x63, 0x41, 0x7f, 0x13, 0xae, 0x63, 0xbe, 0xe3, 0x4b, 0x0a, + 0xf9, 0x89, 0x5e, 0x81, 0x92, 0x6f, 0xe8, 0xfc, 0x00, 0x0a, 0x00, 0xe4, 0x20, 0xd0, 0x3c, 0x0f, + 0x8f, 0x6c, 0x8f, 0x9a, 0x48, 0x45, 0x11, 0x4d, 0xf9, 0xbf, 0x17, 0xa1, 0x96, 0x58, 0x93, 0x8f, + 0xa0, 0x38, 0xe2, 0xc3, 0xf3, 0x8d, 0xf6, 0x7a, 0xca, 0x69, 0x90, 0x10, 0x55, 0xf1, 0xa9, 0x88, + 0xb3, 0x25, 0x8e, 0x37, 0x74, 0x68, 0xfa, 0x6d, 0xb2, 0xe2, 0x43, 0x6b, 0xa0, 0xea, 0x86, 0x83, + 0xfb, 0x9e, 0xe5, 0x9c, 0x70, 0x71, 0x57, 0x86, 0xd6, 0x60, 0x5b, 0xc0, 0xd0, 0x1d, 0x00, 0xdd, + 0x74, 0xc9, 0x62, 0x1f, 0x1a, 0x03, 0x2a, 0x74, 0x79, 0xeb, 0x7c, 0x52, 0x08, 0xff, 0x84, 0x54, + 0x4a, 0xba, 0xe9, 0x72, 0xf1, 0xef, 0x43, 0x85, 0x1c, 0x34, 0xea, 0x88, 0x1d, 0x6e, 0xcc, 0xd2, + 0xcb, 0x5b, 0x17, 0xd2, 0xe6, 0xe0, 0x1f, 0x81, 0xca, 0x8a, 0x1d, 0x34, 0x5c, 0xf4, 0x00, 0x96, + 0xa8, 0xc7, 0x77, 0xeb, 0x4b, 0x94, 0x78, 0x73, 0x92, 0x02, 0xb8, 0x45, 0x3c, 0xa6, 0x04, 0xcc, + 0x20, 0x38, 0x35, 0xda, 0x87, 0xb2, 0x66, 0x9a, 0x96, 0xa7, 0x31, 0x47, 0xb3, 0x4c, 0x99, 0xbd, + 0x3b, 0x03, 0xb3, 0x66, 0x40, 0xc5, 0x38, 0x86, 0xf9, 0xa0, 0xef, 0x43, 0x81, 0x7a, 0x22, 0xee, + 0x34, 0xae, 0xcc, 0x68, 0xb4, 0x0a, 0xa3, 0x6a, 0xdc, 0x86, 0x72, 0x48, 0xd8, 0x79, 0x8c, 0xb4, + 0x71, 0x0f, 0x6a, 0x71, 0xd1, 0xe6, 0x32, 0xf2, 0xdf, 0x85, 0x35, 0x65, 0x6c, 0x06, 0x82, 0x89, + 0x90, 0xed, 0x0e, 0x2c, 0xf1, 0xc5, 0x66, 0x16, 0x27, 0x4f, 0xd7, 0x91, 0xc2, 0x29, 0xc2, 0x31, + 0xd8, 0x91, 0x66, 0xea, 0x43, 0xec, 0xf0, 0x71, 0x45, 0x0c, 0xf6, 0x88, 0x41, 0xe5, 0xef, 0xc3, + 0x99, 0xd8, 0xe0, 0x3c, 0x04, 0x7c, 0x1d, 0xaa, 0xb6, 0xa5, 0xab, 0x2e, 0x03, 0xab, 0x86, 0x2e, + 0xdc, 0x90, 0xed, 0xe3, 0xb6, 0x75, 0x42, 0xde, 0xf3, 0x2c, 0x3b, 0x29, 0xfc, 0x6c, 0xe4, 0x75, + 0x38, 0x1b, 0x27, 0x67, 0xc3, 0xcb, 0x1f, 0xc2, 0xba, 0x82, 0x47, 0xd6, 0x31, 0x7e, 0x51, 0xd6, + 0x0d, 0xa8, 0x27, 0x19, 0x70, 0xe6, 0x9f, 0xc1, 0x7a, 0x00, 0xed, 0x79, 0x9a, 0x37, 0x76, 0xe7, + 0x62, 0xce, 0xe3, 0xe3, 0x03, 0xcb, 0x65, 0xcb, 0x59, 0x54, 0x44, 0x53, 0x5e, 0x87, 0x42, 0xd7, + 0xd2, 0xdb, 0x5d, 0x54, 0x85, 0x9c, 0x61, 0x73, 0xe2, 0x9c, 0x61, 0xcb, 0x46, 0x78, 0xcc, 0x0e, + 0x8b, 0x53, 0xd8, 0xd0, 0x71, 0x54, 0x74, 0x0f, 0xaa, 0x9a, 0xae, 0x1b, 0xc4, 0x9c, 0xb4, 0xa1, + 0x6a, 0xd8, 0x2c, 0x8c, 0x2d, 0x6f, 0xad, 0xa7, 0x1a, 0x40, 0xbb, 0xab, 0x54, 0x02, 0xf4, 0xb6, + 0xed, 0xca, 0x8f, 0xa0, 0xe4, 0x9f, 0xf9, 0xe8, 0x6e, 0x10, 0xf1, 0xe6, 0x66, 0x8d, 0x10, 0xfc, + 0xa0, 0x78, 0x2f, 0x71, 0x46, 0x71, 0x91, 0xef, 0x02, 0xf8, 0xbe, 0x54, 0x84, 0x1e, 0xe7, 0x27, + 0x30, 0x56, 0x42, 0xe8, 0xf2, 0x4f, 0x0a, 0x61, 0x0f, 0x1b, 0x52, 0x82, 0xee, 0x2b, 0x41, 0x8f, + 0x78, 0xdc, 0xdc, 0x0b, 0x79, 0xdc, 0xf7, 0xa1, 0xe0, 0x7a, 0x9a, 0x87, 0x79, 0x4c, 0xb7, 0x31, + 0x89, 0x9c, 0x08, 0x81, 0x15, 0x86, 0x8f, 0x2e, 0x00, 0xf4, 0x1d, 0xac, 0x79, 0x58, 0x57, 0x35, + 0x76, 0x3c, 0xe4, 0x95, 0x12, 0x87, 0x34, 0x3d, 0xd4, 0x0a, 0xe2, 0xd2, 0x02, 0x15, 0xec, 0xda, + 0x24, 0xce, 0x91, 0xa5, 0x0e, 0x22, 0x54, 0xdf, 0x5d, 0x2d, 0xcd, 0xe8, 0xae, 0x38, 0x03, 0x46, + 0x15, 0x72, 0xc6, 0xcb, 0xd3, 0x9d, 0x31, 0x23, 0x9d, 0xc5, 0x19, 0x17, 0xa7, 0x3b, 0x63, 0xce, + 0x6c, 0xb2, 0x33, 0x4e, 0x71, 0x3f, 0xa5, 0x34, 0xf7, 0xf3, 0x5d, 0xba, 0xdd, 0x7f, 0x92, 0xa0, + 0x9e, 0xf4, 0x02, 0xdc, 0xfb, 0xdd, 0x81, 0x25, 0x97, 0x42, 0x66, 0xf1, 0xbd, 0x9c, 0x96, 0x53, + 0xa0, 0x47, 0xb0, 0x68, 0x98, 0x87, 0x16, 0xdf, 0xb4, 0xef, 0xcd, 0x40, 0xc9, 0x47, 0xdd, 0x6c, + 0x9b, 0x87, 0x16, 0xd3, 0x26, 0xe5, 0xd0, 0x78, 0x1f, 0x4a, 0x3e, 0x68, 0xae, 0xb9, 0xed, 0xc2, + 0x5a, 0xcc, 0xb6, 0xd9, 0x75, 0xc3, 0xdf, 0x12, 0xd2, 0x7c, 0x5b, 0x42, 0xfe, 0x71, 0x2e, 0xbc, + 0x65, 0x1f, 0x18, 0x43, 0x0f, 0x3b, 0x89, 0x2d, 0xfb, 0x81, 0xe0, 0xce, 0xf6, 0xeb, 0xe5, 0xa9, + 0xdc, 0x59, 0x04, 0xcf, 0x77, 0xdd, 0x17, 0x50, 0xa5, 0x46, 0xa9, 0xba, 0x78, 0x48, 0x43, 0x1e, + 0x1e, 0x7e, 0x7e, 0x6f, 0x12, 0x1b, 0x26, 0x09, 0x33, 0xed, 0x1e, 0xa7, 0x63, 0x1a, 0xac, 0x0c, + 0xc3, 0xb0, 0xc6, 0x47, 0x80, 0x92, 0x48, 0x73, 0xe9, 0xb4, 0x47, 0x7c, 0x21, 0xb9, 0xa0, 0xa7, + 0x9c, 0xd3, 0x87, 0x54, 0x8c, 0x59, 0x6c, 0x85, 0x09, 0xac, 0x70, 0x0a, 0xf9, 0xbf, 0xf2, 0x00, + 0x41, 0xe7, 0xff, 0x23, 0x27, 0xf8, 0x91, 0xef, 0x80, 0x58, 0x28, 0x79, 0x75, 0x12, 0xe3, 0x54, + 0xd7, 0xb3, 0x1b, 0x75, 0x3d, 0x2c, 0xa8, 0x7c, 0x7b, 0x22, 0x9b, 0xb9, 0x9d, 0xce, 0xf2, 0xaf, + 0x9b, 0xd3, 0x79, 0x0c, 0x67, 0xe3, 0x46, 0xc4, 0x3d, 0xce, 0x16, 0x14, 0x0c, 0x0f, 0x8f, 0x58, + 0x36, 0x2b, 0xf5, 0xd2, 0x1b, 0x22, 0x62, 0xa8, 0xf2, 0x06, 0x94, 0xda, 0x23, 0x6d, 0x80, 0x7b, + 0x36, 0xee, 0x93, 0x41, 0x0d, 0xd2, 0xe0, 0x82, 0xb0, 0x86, 0xbc, 0x05, 0xc5, 0x1f, 0xe0, 0x13, + 0xb6, 0xfb, 0x67, 0x14, 0x54, 0xfe, 0xc3, 0x1c, 0xac, 0xd3, 0xd3, 0xa7, 0x25, 0x72, 0x49, 0x0a, + 0x76, 0xad, 0xb1, 0xd3, 0xc7, 0x2e, 0x35, 0x0b, 0x7b, 0xac, 0xda, 0xd8, 0x31, 0x2c, 0x9d, 0x67, + 0x2d, 0x4a, 0x7d, 0x7b, 0xdc, 0xa5, 0x00, 0x74, 0x1e, 0x48, 0x43, 0xfd, 0x6a, 0x6c, 0x71, 0x8b, + 0xcd, 0x2b, 0xc5, 0xbe, 0x3d, 0xfe, 0x2d, 0xd2, 0x16, 0xb4, 0xee, 0x91, 0xe6, 0x60, 0x97, 0x1a, + 0x24, 0xa3, 0xed, 0x51, 0x00, 0xba, 0x09, 0x67, 0x46, 0x78, 0x64, 0x39, 0x27, 0xea, 0xd0, 0x18, + 0x19, 0x9e, 0x6a, 0x98, 0xea, 0xc1, 0x89, 0x87, 0x5d, 0x6e, 0x7c, 0x88, 0x75, 0x3e, 0x26, 0x7d, + 0x6d, 0xf3, 0x3e, 0xe9, 0x41, 0x32, 0x54, 0x2c, 0x6b, 0xa4, 0xba, 0x7d, 0xcb, 0xc1, 0xaa, 0xa6, + 0xff, 0x88, 0x1e, 0xc8, 0x79, 0xa5, 0x6c, 0x59, 0xa3, 0x1e, 0x81, 0x35, 0xf5, 0x1f, 0xa1, 0x57, + 0xa1, 0xdc, 0xb7, 0xc7, 0x2e, 0xf6, 0x54, 0xf2, 0x87, 0x9e, 0xb7, 0x25, 0x05, 0x18, 0xa8, 0x65, + 0x8f, 0xdd, 0x10, 0xc2, 0x88, 0xe8, 0x7f, 0x39, 0x8c, 0xf0, 0x84, 0xa8, 0x59, 0x83, 0x4a, 0x24, + 0xeb, 0x41, 0x2e, 0xa0, 0x34, 0xbd, 0xc1, 0x2f, 0xa0, 0xe4, 0x37, 0x81, 0x39, 0xd6, 0x50, 0x68, + 0x92, 0xfe, 0x26, 0x30, 0xef, 0xc4, 0x16, 0xb7, 0x4f, 0xfa, 0x9b, 0xa8, 0x7c, 0x88, 0x8f, 0x79, + 0x3a, 0xad, 0xa4, 0xb0, 0x86, 0xac, 0x03, 0xb4, 0x34, 0x5b, 0x3b, 0x30, 0x86, 0x86, 0x77, 0x82, + 0xae, 0x41, 0x4d, 0xd3, 0x75, 0xb5, 0x2f, 0x20, 0x06, 0x16, 0x49, 0xce, 0x55, 0x4d, 0xd7, 0x5b, + 0x21, 0x30, 0x7a, 0x13, 0x4e, 0xe9, 0x8e, 0x65, 0x47, 0x71, 0x59, 0xd6, 0xb3, 0x46, 0x3a, 0xc2, + 0xc8, 0xf2, 0xbf, 0x15, 0xe0, 0x42, 0x74, 0x61, 0xe3, 0x99, 0xa5, 0x8f, 0x60, 0x25, 0x36, 0x6a, + 0x46, 0x06, 0x26, 0x90, 0x56, 0x89, 0x50, 0xc4, 0x32, 0x25, 0xb9, 0x44, 0xa6, 0x24, 0x35, 0x77, + 0x95, 0x7f, 0xa9, 0xb9, 0xab, 0xc5, 0x97, 0x92, 0xbb, 0x2a, 0x7c, 0xbb, 0xdc, 0xd5, 0xca, 0x9c, + 0xb9, 0xab, 0xcb, 0xd4, 0x7b, 0x89, 0xd1, 0x69, 0x9a, 0x80, 0x99, 0x6a, 0xc5, 0x1f, 0xc3, 0x14, + 0xd9, 0xf5, 0x58, 0x8e, 0x6b, 0x79, 0x9e, 0x1c, 0x57, 0x31, 0x33, 0xc7, 0x45, 0xac, 0xce, 0xb6, + 0x35, 0x67, 0x64, 0x39, 0x22, 0x89, 0xc5, 0xa3, 0xb6, 0x55, 0x01, 0xe7, 0x09, 0xac, 0xcc, 0x74, + 0x17, 0x64, 0xa5, 0xbb, 0xd0, 0x25, 0x58, 0x31, 0x2d, 0xd5, 0xc4, 0xcf, 0x54, 0x62, 0x0b, 0x6e, + 0xbd, 0xcc, 0x0c, 0xc3, 0xb4, 0x3a, 0xf8, 0x59, 0x97, 0x40, 0xd0, 0x06, 0xac, 0x8c, 0x34, 0xf7, + 0x29, 0xd6, 0x29, 0x2b, 0xb7, 0x5e, 0xa1, 0x46, 0x5c, 0x66, 0x30, 0xc2, 0xc3, 0x45, 0x6f, 0x80, + 0x3f, 0x49, 0x8e, 0x54, 0xa5, 0x48, 0x15, 0x01, 0xa5, 0x68, 0xf2, 0x5f, 0x4b, 0xb0, 0x16, 0x35, + 0x73, 0x9e, 0x06, 0x79, 0x08, 0x25, 0x47, 0x78, 0x32, 0x6e, 0xda, 0xd7, 0x32, 0x02, 0xef, 0xa4, + 0xeb, 0x53, 0x02, 0x5a, 0xf4, 0xc3, 0xcc, 0xec, 0xdb, 0x8d, 0x69, 0xfc, 0xa6, 0xe5, 0xdf, 0x64, + 0x07, 0x5e, 0xfd, 0xc4, 0x30, 0x75, 0xeb, 0x99, 0x9b, 0xb9, 0x4b, 0x53, 0x6c, 0x45, 0xca, 0xb0, + 0x95, 0xbe, 0x83, 0x75, 0x6c, 0x7a, 0x86, 0x36, 0x54, 0x5d, 0x1b, 0xf7, 0x45, 0x16, 0x20, 0x00, + 0x93, 0xb3, 0x43, 0xfe, 0x1b, 0x09, 0xce, 0xc6, 0x07, 0xe5, 0x3a, 0x6b, 0x27, 0x75, 0xf6, 0x66, + 0x72, 0x8e, 0x71, 0xe2, 0x54, 0xad, 0x7d, 0x91, 0xa9, 0xb5, 0x9b, 0xd3, 0x39, 0x4e, 0xd5, 0xdb, + 0x9f, 0x4b, 0x70, 0x2e, 0x53, 0x8c, 0xd8, 0xd9, 0x23, 0xc5, 0xcf, 0x1e, 0x7e, 0x6e, 0xf5, 0xad, + 0xb1, 0xe9, 0x85, 0xce, 0xad, 0x16, 0xad, 0xb5, 0xb0, 0x03, 0x42, 0x1d, 0x69, 0xcf, 0x8d, 0xd1, + 0x78, 0xc4, 0x0f, 0x2e, 0xc2, 0xee, 0x09, 0x83, 0xbc, 0xc0, 0xc9, 0x25, 0x37, 0xe1, 0x94, 0x2f, + 0xe5, 0xc4, 0xc4, 0x66, 0x28, 0x51, 0x99, 0x8b, 0x26, 0x2a, 0x4d, 0x58, 0xda, 0xc6, 0xc7, 0x46, + 0x1f, 0xbf, 0x94, 0x62, 0xd0, 0x25, 0x28, 0xdb, 0xd8, 0x19, 0x19, 0xae, 0xeb, 0x7b, 0xe4, 0x92, + 0x12, 0x06, 0xc9, 0xff, 0xbe, 0x04, 0xab, 0x71, 0xeb, 0xf8, 0x30, 0x91, 0x17, 0x7d, 0x2d, 0xe5, + 0xac, 0x88, 0x4f, 0x34, 0x14, 0x9f, 0xde, 0x14, 0x51, 0x4b, 0x2e, 0x2b, 0x87, 0xe0, 0x47, 0x38, + 0x3c, 0xa4, 0x21, 0x1a, 0xe9, 0x5b, 0xa3, 0x91, 0x66, 0xea, 0xa2, 0x86, 0xc7, 0x9b, 0x44, 0x7f, + 0x9a, 0x33, 0x20, 0x6a, 0x27, 0x60, 0xfa, 0x9b, 0x2c, 0x1e, 0xb9, 0x70, 0x1b, 0x26, 0xcd, 0xaf, + 0x52, 0xaf, 0x5e, 0x52, 0x80, 0x83, 0xb6, 0x0d, 0x07, 0x6d, 0xc2, 0x22, 0x36, 0x8f, 0x45, 0x00, + 0x9a, 0x52, 0xe4, 0x13, 0xf1, 0x93, 0x42, 0xf1, 0xd0, 0x0d, 0x58, 0x1a, 0x11, 0xb3, 0x10, 0x57, + 0xef, 0xf5, 0x8c, 0x5a, 0x97, 0xc2, 0xd1, 0xd0, 0x16, 0x2c, 0xeb, 0x74, 0x9d, 0xc4, 0xfd, 0xba, + 0x9e, 0x92, 0xb5, 0xa5, 0x08, 0x8a, 0x40, 0x44, 0x3b, 0x7e, 0x78, 0x5d, 0xca, 0x8a, 0x8b, 0x63, + 0x4b, 0x91, 0x1a, 0x63, 0xef, 0x45, 0x63, 0x6c, 0xa0, 0xbc, 0xb6, 0xa6, 0xf3, 0x9a, 0x1c, 0x68, + 0x9f, 0x83, 0xe2, 0xd0, 0x1a, 0x30, 0x33, 0x2a, 0xb3, 0xf2, 0xf0, 0xd0, 0x1a, 0x50, 0x2b, 0x5a, + 0x23, 0xd7, 0x0d, 0xdd, 0x30, 0xe9, 0xf1, 0x57, 0x54, 0x58, 0x83, 0x6c, 0x3e, 0xfa, 0x43, 0xb5, + 0xcc, 0x3e, 0xae, 0x57, 0x68, 0x57, 0x89, 0x42, 0x76, 0xcd, 0x3e, 0x8d, 0x4b, 0x3d, 0xef, 0xa4, + 0x5e, 0xa5, 0x70, 0xf2, 0x93, 0xdc, 0x24, 0x59, 0x76, 0x64, 0x35, 0xeb, 0x26, 0x99, 0xe6, 0xdf, + 0x45, 0x72, 0xe4, 0x3e, 0x2c, 0x3f, 0x63, 0x8e, 0xa0, 0x5e, 0xa3, 0xf4, 0x57, 0xa7, 0xbb, 0x17, + 0xce, 0x41, 0x10, 0x7e, 0x97, 0x77, 0x84, 0xbf, 0x93, 0xe0, 0x6c, 0x8b, 0x5e, 0xb4, 0x42, 0x7e, + 0x6c, 0x9e, 0xec, 0xe4, 0x6d, 0x3f, 0x71, 0x9c, 0x99, 0xf1, 0x8b, 0xcf, 0x5b, 0xe4, 0x8d, 0xdb, + 0x50, 0x15, 0xcc, 0x39, 0x8b, 0xfc, 0xcc, 0xb9, 0xe7, 0x8a, 0x1b, 0x6e, 0xca, 0x1f, 0xc0, 0x7a, + 0x62, 0x16, 0xfc, 0xae, 0xb3, 0x01, 0x2b, 0x81, 0xbf, 0xf2, 0x27, 0x51, 0xf6, 0x61, 0x6d, 0x5d, + 0xbe, 0x03, 0x67, 0x7a, 0x9e, 0xe6, 0x78, 0x09, 0x15, 0xcc, 0x40, 0x4b, 0xb3, 0xca, 0x51, 0x5a, + 0x9e, 0xf8, 0xed, 0xc1, 0x5a, 0xcf, 0xb3, 0xec, 0x17, 0x60, 0x4a, 0xbc, 0x0e, 0x99, 0xbf, 0x35, + 0x16, 0xe7, 0x83, 0x68, 0xca, 0xeb, 0x2c, 0x07, 0x9e, 0x1c, 0xed, 0x2e, 0x9c, 0x65, 0x29, 0xe8, + 0x17, 0x99, 0xc4, 0x39, 0x91, 0x00, 0x4f, 0xf2, 0x7d, 0x02, 0xa7, 0x83, 0x63, 0x31, 0x48, 0xee, + 0xdc, 0x8a, 0x26, 0x77, 0x2e, 0x4d, 0x58, 0xf5, 0x48, 0x6e, 0xe7, 0x4f, 0x72, 0x21, 0xbf, 0x9e, + 0x91, 0xda, 0xb9, 0x1b, 0x4d, 0xed, 0xbc, 0x31, 0x8d, 0x77, 0x24, 0xb3, 0x93, 0xb4, 0xda, 0x7c, + 0x8a, 0xd5, 0x7e, 0x9e, 0xc8, 0xff, 0x2c, 0x66, 0x25, 0xd0, 0x62, 0xd2, 0xfe, 0x4a, 0xd2, 0x3f, + 0x0a, 0x4b, 0xff, 0xf8, 0x43, 0xfb, 0x15, 0x83, 0xdb, 0xb1, 0xf4, 0xcf, 0xc6, 0x54, 0x79, 0xfd, + 0xec, 0xcf, 0x5f, 0x2c, 0x42, 0xc9, 0xef, 0x4b, 0xe8, 0x3c, 0xa9, 0xb6, 0x5c, 0x8a, 0xda, 0xc2, + 0x27, 0x70, 0xfe, 0x5b, 0x9d, 0xc0, 0x8b, 0x33, 0x9f, 0xc0, 0xe7, 0xa1, 0x44, 0x7f, 0xa8, 0x0e, + 0x3e, 0xe4, 0x27, 0x6a, 0x91, 0x02, 0x14, 0x7c, 0x18, 0x98, 0xe1, 0xd2, 0x5c, 0x66, 0x18, 0x4b, + 0x38, 0x2d, 0xc7, 0x13, 0x4e, 0x1f, 0xfa, 0x27, 0x22, 0x3b, 0x44, 0xaf, 0x4c, 0xe0, 0x9b, 0x7a, + 0x16, 0x76, 0xa2, 0x67, 0x21, 0x3b, 0x57, 0xdf, 0x9a, 0xc4, 0x65, 0xe2, 0x29, 0xf8, 0x5d, 0x9e, + 0x10, 0xfb, 0x2c, 0x8b, 0x14, 0xb6, 0x45, 0xee, 0x59, 0xef, 0x02, 0xf8, 0x4e, 0x44, 0xa4, 0x92, + 0xce, 0x4f, 0x98, 0xa3, 0x12, 0x42, 0x27, 0x6c, 0x23, 0x4b, 0x13, 0x54, 0xc5, 0x66, 0xf3, 0x8f, + 0x19, 0x25, 0xb1, 0xff, 0x2d, 0x84, 0xfc, 0x4b, 0x46, 0xb5, 0xe7, 0xc3, 0x44, 0xa2, 0x73, 0x4e, + 0x2b, 0xbe, 0x15, 0xcd, 0x73, 0xbe, 0xa0, 0xd5, 0x25, 0xd2, 0x9c, 0x34, 0x72, 0xd1, 0x1c, 0xde, + 0xcd, 0xb2, 0x4b, 0x25, 0x0e, 0x69, 0xd2, 0x9b, 0xc1, 0xa1, 0x61, 0x1a, 0xee, 0x11, 0xeb, 0x5f, + 0x62, 0x37, 0x03, 0x01, 0x6a, 0xd2, 0x67, 0x5e, 0xf8, 0xb9, 0xe1, 0xa9, 0x7d, 0x4b, 0xc7, 0xd4, + 0xa6, 0x0b, 0x4a, 0x91, 0x00, 0x5a, 0x96, 0x8e, 0x83, 0x9d, 0x57, 0x7c, 0xb1, 0x9d, 0x57, 0x8a, + 0xed, 0xbc, 0xb3, 0xb0, 0xe4, 0x60, 0xcd, 0xb5, 0x4c, 0x7e, 0x0f, 0xe7, 0x2d, 0xb2, 0x34, 0x23, + 0xec, 0xba, 0x64, 0x24, 0x1e, 0xae, 0xf1, 0x66, 0x28, 0xcc, 0x5c, 0x99, 0x1a, 0x66, 0x4e, 0xa8, + 0x22, 0xc5, 0xc2, 0xcc, 0xca, 0xd4, 0x30, 0x73, 0xa6, 0x22, 0x52, 0x10, 0x68, 0x57, 0x67, 0x0b, + 0xb4, 0xc3, 0x71, 0xe9, 0x6a, 0x24, 0x2e, 0xfd, 0x2e, 0x37, 0xeb, 0x2f, 0x24, 0x58, 0x4f, 0x6c, + 0x2b, 0xbe, 0x5d, 0x6f, 0xc7, 0xca, 0x4c, 0x1b, 0x53, 0x75, 0xe6, 0x57, 0x99, 0x1e, 0x46, 0xaa, + 0x4c, 0xef, 0x4e, 0x27, 0x7c, 0xe9, 0x45, 0xa6, 0xdf, 0x97, 0xe0, 0xd5, 0x7d, 0x5b, 0x8f, 0x45, + 0x78, 0xfc, 0xda, 0x3f, 0xbb, 0xe3, 0xf8, 0x50, 0xc4, 0xfa, 0xb9, 0x79, 0x13, 0x32, 0x8c, 0x4e, + 0x96, 0xe1, 0x52, 0xb6, 0x18, 0x3c, 0x64, 0xfa, 0x12, 0x56, 0x77, 0x9e, 0xe3, 0x7e, 0xef, 0xc4, + 0xec, 0xcf, 0x21, 0x5a, 0x0d, 0xf2, 0xfd, 0x91, 0xce, 0xd3, 0xa9, 0xe4, 0x67, 0x38, 0x0a, 0xcc, + 0x47, 0xa3, 0x40, 0x15, 0x6a, 0xc1, 0x08, 0x7c, 0x79, 0xcf, 0x92, 0xe5, 0xd5, 0x09, 0x32, 0x61, + 0xbe, 0xa2, 0xf0, 0x16, 0x87, 0x63, 0x87, 0x3d, 0xca, 0x60, 0x70, 0xec, 0x38, 0x51, 0x6f, 0x91, + 0x8f, 0x7a, 0x0b, 0xf9, 0x8f, 0x25, 0x28, 0x93, 0x11, 0xbe, 0x95, 0xfc, 0xfc, 0xaa, 0x95, 0x0f, + 0xae, 0x5a, 0xfe, 0x8d, 0x6d, 0x31, 0x7c, 0x63, 0x0b, 0x24, 0x2f, 0x50, 0x70, 0x52, 0xf2, 0x25, + 0x1f, 0x8e, 0x1d, 0x47, 0xbe, 0x04, 0x2b, 0x4c, 0x36, 0x3e, 0xf3, 0x1a, 0xe4, 0xc7, 0xce, 0x50, + 0xd8, 0xd1, 0xd8, 0x19, 0xca, 0x7f, 0x20, 0x41, 0xa5, 0xe9, 0x79, 0x5a, 0xff, 0x68, 0x8e, 0x09, + 0xf8, 0xc2, 0xe5, 0xc2, 0xc2, 0x25, 0x27, 0x11, 0x88, 0xbb, 0x98, 0x21, 0x6e, 0x21, 0x22, 0xae, + 0x0c, 0x55, 0x21, 0x4b, 0xa6, 0xc0, 0x1d, 0x40, 0x5d, 0xcb, 0xf1, 0x1e, 0x58, 0xce, 0x33, 0xcd, + 0xd1, 0xe7, 0xbb, 0x81, 0x21, 0x58, 0xe4, 0x4f, 0x7f, 0xf3, 0x57, 0x0b, 0x0a, 0xfd, 0x2d, 0x5f, + 0x81, 0xd3, 0x11, 0x7e, 0x99, 0x03, 0x7f, 0x04, 0x65, 0xea, 0xf7, 0x79, 0x28, 0x7e, 0x33, 0x5c, + 0xd7, 0x99, 0xe9, 0x94, 0x90, 0x7f, 0x13, 0x4e, 0x91, 0xf8, 0x80, 0xc2, 0xfd, 0xad, 0xf8, 0xbd, + 0x58, 0x9c, 0x7a, 0x21, 0x83, 0x51, 0x2c, 0x46, 0xfd, 0x4b, 0x09, 0x0a, 0x14, 0x9e, 0x38, 0xb3, + 0xcf, 0x43, 0xc9, 0xc1, 0xb6, 0xa5, 0x7a, 0xda, 0xc0, 0x7f, 0x68, 0x4d, 0x00, 0x7b, 0xda, 0x80, + 0x66, 0x73, 0x69, 0xa7, 0x6e, 0x0c, 0xb0, 0xeb, 0x89, 0xd7, 0xd6, 0x65, 0x02, 0xdb, 0x66, 0x20, + 0xa2, 0x24, 0xd7, 0xf8, 0x1d, 0x16, 0x77, 0x2e, 0x2a, 0xf4, 0x37, 0xda, 0x64, 0xcf, 0xf8, 0x66, + 0xc9, 0xbd, 0xd3, 0x47, 0x7e, 0x0d, 0x28, 0xc6, 0xd2, 0xe5, 0x7e, 0x5b, 0xde, 0x01, 0x14, 0xd6, + 0x02, 0xd7, 0xf7, 0x0d, 0x58, 0xa2, 0x4a, 0x12, 0xd1, 0xd1, 0x7a, 0x86, 0x1a, 0x14, 0x8e, 0x26, + 0x6b, 0x80, 0x98, 0x82, 0x23, 0x11, 0xd1, 0xfc, 0xab, 0x32, 0x21, 0x42, 0xfa, 0x5b, 0x09, 0x4e, + 0x47, 0xc6, 0xe0, 0xb2, 0xbe, 0x1d, 0x1d, 0x24, 0x53, 0x54, 0x3e, 0x40, 0x2b, 0x72, 0x24, 0xdc, + 0xc8, 0x12, 0xe9, 0x97, 0x74, 0x1c, 0xfc, 0xbd, 0x04, 0xd0, 0x1c, 0x7b, 0x47, 0x3c, 0x33, 0x18, + 0x5e, 0x19, 0x29, 0xba, 0x32, 0xa4, 0xcf, 0xd6, 0x5c, 0xf7, 0x99, 0xe5, 0x88, 0x3b, 0x8d, 0xdf, + 0xa6, 0x39, 0xbc, 0xb1, 0x77, 0x24, 0x6a, 0x66, 0xe4, 0x37, 0x7a, 0x03, 0xaa, 0xec, 0x71, 0xbf, + 0xaa, 0xe9, 0xba, 0x83, 0x5d, 0x97, 0x17, 0xcf, 0x2a, 0x0c, 0xda, 0x64, 0x40, 0x82, 0x66, 0xd0, + 0xac, 0xb6, 0x77, 0xa2, 0x7a, 0xd6, 0x53, 0x6c, 0xf2, 0xbb, 0x49, 0x45, 0x40, 0xf7, 0x08, 0x90, + 0x55, 0x11, 0x06, 0x86, 0xeb, 0x39, 0x02, 0x4d, 0x14, 0x5a, 0x38, 0x94, 0xa2, 0x91, 0x45, 0xa9, + 0x75, 0xc7, 0xc3, 0x21, 0x53, 0xf1, 0x8b, 0x2f, 0xfb, 0x3b, 0x7c, 0x42, 0xb9, 0x2c, 0x9b, 0x0e, + 0x94, 0xc6, 0xa7, 0xfb, 0x12, 0x93, 0x30, 0xef, 0xc0, 0xa9, 0xd0, 0x1c, 0xb8, 0x59, 0x45, 0x82, + 0x48, 0x29, 0x1a, 0x44, 0xca, 0x0f, 0x01, 0xb1, 0xbc, 0xc3, 0xb7, 0x9c, 0xb7, 0x7c, 0x06, 0x4e, + 0x47, 0x18, 0xf1, 0x93, 0xf8, 0x3a, 0x54, 0xf8, 0x93, 0x28, 0x6e, 0x28, 0xe7, 0xa0, 0x48, 0x3c, + 0x6a, 0xdf, 0xd0, 0x45, 0x41, 0x75, 0xd9, 0xb6, 0xf4, 0x96, 0xa1, 0x3b, 0xf2, 0x27, 0x50, 0x51, + 0xd8, 0x38, 0x1c, 0xf7, 0x01, 0x54, 0xf9, 0x03, 0x2a, 0x35, 0xf2, 0x34, 0x32, 0xed, 0xed, 0x7d, + 0x78, 0x10, 0xa5, 0x62, 0x86, 0x9b, 0xb2, 0x0e, 0x0d, 0x16, 0x32, 0x44, 0xd8, 0x8b, 0xc9, 0x3e, + 0x00, 0xf1, 0x62, 0x60, 0xea, 0x28, 0x51, 0xfa, 0x8a, 0x13, 0x6e, 0xca, 0x17, 0xe0, 0x7c, 0xea, + 0x28, 0x5c, 0x13, 0x36, 0xd4, 0x82, 0x0e, 0xf6, 0x7e, 0xcf, 0xaf, 0x18, 0x4b, 0xa1, 0x8a, 0xf1, + 0x59, 0x3f, 0x48, 0xcc, 0x89, 0x43, 0x8c, 0x46, 0x80, 0x41, 0xb8, 0x9f, 0xcf, 0x0a, 0xf7, 0x17, + 0x23, 0xe1, 0xbe, 0xdc, 0xf3, 0xf5, 0xc9, 0xaf, 0x61, 0xf7, 0xe9, 0x75, 0x91, 0x8d, 0x2d, 0x1c, + 0xa2, 0x3c, 0x69, 0x96, 0x0c, 0x55, 0x09, 0x51, 0xc9, 0xd7, 0xa0, 0x12, 0x75, 0x8d, 0x21, 0x3f, + 0x27, 0x25, 0xfc, 0x5c, 0x35, 0xe6, 0xe2, 0xde, 0x8f, 0x45, 0xc0, 0xd9, 0x3a, 0x8e, 0xc5, 0xbf, + 0xf7, 0x22, 0xce, 0xee, 0x7a, 0x4a, 0xb1, 0xf7, 0x97, 0xe4, 0xe7, 0xbe, 0x84, 0x2a, 0x0d, 0x48, + 0xdb, 0xdb, 0xe2, 0x53, 0xa1, 0xb4, 0x40, 0xa6, 0x12, 0x0d, 0x64, 0xfc, 0x2f, 0x7a, 0x74, 0x5e, + 0xc5, 0x61, 0x5f, 0xf4, 0xe8, 0xfe, 0x21, 0x98, 0xa7, 0x50, 0xfa, 0x5b, 0xfe, 0x53, 0x09, 0xea, + 0x74, 0x88, 0x7d, 0x17, 0x3b, 0x7e, 0x05, 0x9c, 0x6f, 0x81, 0x16, 0xac, 0x8c, 0x0d, 0x3d, 0x78, + 0xc9, 0xcd, 0x16, 0xed, 0x52, 0x46, 0xd4, 0xec, 0x0b, 0xa9, 0x94, 0xc7, 0x86, 0xee, 0xbf, 0xe5, + 0x6e, 0xc1, 0xca, 0x20, 0xcc, 0x24, 0x37, 0x2b, 0x93, 0x41, 0xc0, 0x44, 0x1e, 0xc3, 0xe9, 0x66, + 0xdf, 0x33, 0x8e, 0xa3, 0xe6, 0x8d, 0x7e, 0x1b, 0xce, 0x10, 0x47, 0xaf, 0x06, 0x55, 0xfe, 0xc8, + 0x26, 0xba, 0x9e, 0x31, 0x48, 0xca, 0x5c, 0x95, 0xd3, 0xe3, 0x24, 0x90, 0xec, 0xaa, 0x87, 0xd8, + 0x8b, 0x8c, 0x49, 0x16, 0x92, 0x5b, 0x9f, 0x3c, 0x84, 0x57, 0xd2, 0xbb, 0xb9, 0xc1, 0x3d, 0xce, + 0xd8, 0xdc, 0x29, 0x29, 0xcd, 0x94, 0xd9, 0xc5, 0xb7, 0xf8, 0x1a, 0x0f, 0x0e, 0x1e, 0xb8, 0x61, + 0x19, 0x5e, 0x83, 0xf2, 0x7e, 0xd6, 0x47, 0x3e, 0x8b, 0xe2, 0x95, 0xcd, 0x2d, 0x58, 0x7b, 0x60, + 0x0c, 0xb1, 0x7b, 0xe2, 0x7a, 0x78, 0xd4, 0xa6, 0x27, 0xd4, 0xa1, 0x81, 0x1d, 0x74, 0x11, 0x80, + 0xde, 0x67, 0x6d, 0xcb, 0xf0, 0xbf, 0xfd, 0x08, 0x41, 0xe4, 0xff, 0x94, 0x60, 0x35, 0x20, 0xdc, + 0xa7, 0xf7, 0xf8, 0x57, 0xa0, 0x44, 0x84, 0x72, 0x3d, 0x6d, 0x64, 0x8b, 0xe2, 0xa6, 0x0f, 0x40, + 0x77, 0xa1, 0x70, 0xe8, 0x0a, 0xd3, 0x4b, 0xad, 0xa6, 0xa4, 0x09, 0xa2, 0x2c, 0x1e, 0xba, 0x6d, + 0x1d, 0x7d, 0x00, 0x30, 0x76, 0xb1, 0xce, 0x0b, 0x9a, 0xf9, 0xac, 0xd0, 0x71, 0x3f, 0xfc, 0x2a, + 0x82, 0x10, 0xb0, 0x07, 0x3a, 0xf7, 0xa0, 0x6c, 0x98, 0x96, 0x8e, 0x69, 0xa5, 0x5a, 0xe7, 0x29, + 0xc6, 0x29, 0xe4, 0xc0, 0x28, 0xf6, 0x5d, 0xac, 0xcb, 0x98, 0x07, 0x46, 0x42, 0xbf, 0x7c, 0x11, + 0x3b, 0x70, 0x8a, 0x9d, 0x60, 0x87, 0xbe, 0xe0, 0x62, 0x27, 0x6c, 0x4c, 0x9a, 0x1d, 0xd5, 0x96, + 0x52, 0x33, 0x78, 0x9c, 0x2b, 0x48, 0xe5, 0x3b, 0x70, 0x26, 0x72, 0x5d, 0x9e, 0xe3, 0xfe, 0x2a, + 0x77, 0x63, 0x59, 0xb3, 0xc0, 0xb7, 0xf1, 0x9c, 0x94, 0x70, 0x6d, 0xd3, 0x72, 0x52, 0x2e, 0xcb, + 0x49, 0xb9, 0xf2, 0xe7, 0x70, 0x2e, 0x92, 0xde, 0x8b, 0x48, 0x74, 0x2f, 0x16, 0xc6, 0x5f, 0x9e, + 0xc6, 0x35, 0x16, 0xcf, 0xff, 0x8f, 0x04, 0x6b, 0x69, 0x08, 0x2f, 0x98, 0x7e, 0xfe, 0x32, 0xe3, + 0xd5, 0xe6, 0xed, 0xd9, 0xc4, 0xfa, 0x95, 0xa4, 0xee, 0xf7, 0xa0, 0x91, 0xa6, 0xcf, 0xe4, 0x2a, + 0xe5, 0xe7, 0x59, 0xa5, 0x9f, 0xe6, 0x43, 0x65, 0x98, 0xa6, 0xe7, 0x39, 0xc6, 0xc1, 0x98, 0x98, + 0xfc, 0x4b, 0x4f, 0x6d, 0xb6, 0xfd, 0x24, 0x1d, 0x53, 0xed, 0xcd, 0x09, 0xe4, 0x81, 0x1c, 0xa9, + 0x89, 0xba, 0x4f, 0xa3, 0x89, 0x3a, 0x56, 0x60, 0xb9, 0x35, 0x1b, 0xbf, 0x5f, 0xdb, 0x6c, 0xf8, + 0x4f, 0x73, 0x50, 0x8d, 0x2e, 0x11, 0xda, 0x01, 0xd0, 0x7c, 0xc9, 0xb3, 0x1d, 0x7c, 0xca, 0x34, + 0x95, 0x10, 0x21, 0x7a, 0x0b, 0xf2, 0x7d, 0x7b, 0xcc, 0x57, 0x2d, 0xe5, 0x65, 0x40, 0xcb, 0x1e, + 0x33, 0x8f, 0x42, 0xd0, 0xc8, 0x05, 0x9b, 0x3d, 0xf4, 0xc8, 0xf6, 0x92, 0x4f, 0x68, 0x3f, 0xa3, + 0xe1, 0xc8, 0xe8, 0x11, 0x54, 0x9f, 0x39, 0x86, 0xa7, 0x1d, 0x0c, 0xb1, 0x3a, 0xd4, 0x4e, 0xf8, + 0xf7, 0xa4, 0x33, 0x39, 0xb2, 0x8a, 0x20, 0x7c, 0x4c, 0xe8, 0xe4, 0xdf, 0x83, 0xa2, 0x90, 0x68, + 0xca, 0x89, 0xb0, 0x07, 0xeb, 0x63, 0x82, 0xa6, 0xd2, 0x87, 0x93, 0xa6, 0x66, 0x5a, 0xaa, 0x8b, + 0x49, 0x4c, 0x27, 0x3e, 0x12, 0x99, 0xe2, 0xa2, 0xd7, 0x28, 0x75, 0xcb, 0x72, 0x70, 0x47, 0x33, + 0xad, 0x1e, 0x23, 0x95, 0x8f, 0xa1, 0x1c, 0x9a, 0xe0, 0x14, 0x11, 0xda, 0x70, 0x4a, 0xbc, 0xcb, + 0x70, 0xb1, 0xc7, 0x8f, 0x97, 0x99, 0x06, 0x5f, 0xe5, 0x74, 0x3d, 0xec, 0xb1, 0xb7, 0x34, 0xf7, + 0xe0, 0x9c, 0x82, 0x2d, 0x1b, 0x9b, 0xfe, 0x7a, 0x3e, 0xb6, 0x06, 0x73, 0x78, 0xf0, 0x57, 0xa0, + 0x91, 0x46, 0xcf, 0xfc, 0xc3, 0xf5, 0xcb, 0x50, 0x14, 0x9f, 0x79, 0xa3, 0x65, 0xc8, 0xef, 0xb5, + 0xba, 0xb5, 0x05, 0xf2, 0x63, 0x7f, 0xbb, 0x5b, 0x93, 0x50, 0x11, 0x16, 0x7b, 0xad, 0xbd, 0x6e, + 0x2d, 0x77, 0x7d, 0x04, 0xb5, 0xf8, 0x37, 0xce, 0x68, 0x1d, 0x4e, 0x77, 0x95, 0xdd, 0x6e, 0xf3, + 0x61, 0x73, 0xaf, 0xbd, 0xdb, 0x51, 0xbb, 0x4a, 0xfb, 0xe3, 0xe6, 0xde, 0x4e, 0x6d, 0x01, 0x6d, + 0xc0, 0x85, 0x70, 0xc7, 0xa3, 0xdd, 0xde, 0x9e, 0xba, 0xb7, 0xab, 0xb6, 0x76, 0x3b, 0x7b, 0xcd, + 0x76, 0x67, 0x47, 0xa9, 0x49, 0xe8, 0x02, 0x9c, 0x0b, 0xa3, 0xdc, 0x6f, 0x6f, 0xb7, 0x95, 0x9d, + 0x16, 0xf9, 0xdd, 0x7c, 0x5c, 0xcb, 0x5d, 0xbf, 0x09, 0x95, 0xc8, 0xe7, 0xc5, 0x44, 0xa4, 0xee, + 0xee, 0x76, 0x6d, 0x01, 0x55, 0xa0, 0x14, 0xe6, 0x53, 0x84, 0xc5, 0xce, 0xee, 0xf6, 0x4e, 0x2d, + 0x77, 0xfd, 0x0e, 0xac, 0xc6, 0x1e, 0x7b, 0xa3, 0x53, 0x50, 0xe9, 0x35, 0x3b, 0xdb, 0xf7, 0x77, + 0x3f, 0x55, 0x95, 0x9d, 0xe6, 0xf6, 0x67, 0xb5, 0x05, 0xb4, 0x06, 0x35, 0x01, 0xea, 0xec, 0xee, + 0x31, 0xa8, 0x74, 0xfd, 0x69, 0x6c, 0x8f, 0x61, 0x74, 0x06, 0x4e, 0xf9, 0xc3, 0xa8, 0x2d, 0x65, + 0xa7, 0xb9, 0xb7, 0x43, 0x46, 0x8f, 0x80, 0x95, 0xfd, 0x4e, 0xa7, 0xdd, 0x79, 0x58, 0x93, 0x08, + 0xd7, 0x00, 0xbc, 0xf3, 0x69, 0x9b, 0x20, 0xe7, 0xa2, 0xc8, 0xfb, 0x9d, 0x1f, 0x74, 0x76, 0x3f, + 0xe9, 0xd4, 0xf2, 0x5b, 0x7f, 0x85, 0xa0, 0x2a, 0xa2, 0x7e, 0xec, 0xd0, 0x27, 0x4e, 0x5d, 0x58, + 0x16, 0xff, 0x36, 0x20, 0xc5, 0x43, 0x47, 0xff, 0xd9, 0x41, 0x63, 0x63, 0x02, 0x06, 0xbf, 0x7c, + 0x2d, 0xa0, 0x03, 0x7a, 0x19, 0x0a, 0x3d, 0xbe, 0xbf, 0x9c, 0x7a, 0xf5, 0x48, 0xbc, 0xf7, 0x6f, + 0x5c, 0x99, 0x8a, 0xe7, 0x8f, 0x81, 0xc9, 0x7d, 0x27, 0xfc, 0x7d, 0x1b, 0xba, 0x92, 0x76, 0x51, + 0x49, 0xf9, 0x80, 0xae, 0x71, 0x75, 0x3a, 0xa2, 0x3f, 0xcc, 0x53, 0xa8, 0xc5, 0xbf, 0x75, 0x43, + 0x29, 0x79, 0xf4, 0x8c, 0x0f, 0xea, 0x1a, 0xd7, 0x67, 0x41, 0x0d, 0x0f, 0x96, 0xf8, 0x78, 0xeb, + 0xda, 0x2c, 0x1f, 0xb9, 0x64, 0x0e, 0x96, 0xf5, 0x3d, 0x0c, 0x53, 0x60, 0xf4, 0xbd, 0x3c, 0x4a, + 0xfd, 0x52, 0x2a, 0xe5, 0xb3, 0x8c, 0x34, 0x05, 0xa6, 0x3f, 0xbd, 0x97, 0x17, 0xd0, 0x11, 0xac, + 0xc6, 0xde, 0xaa, 0xa0, 0x14, 0xf2, 0xf4, 0x47, 0x39, 0x8d, 0x6b, 0x33, 0x60, 0x46, 0x2d, 0x22, + 0xfc, 0x36, 0x25, 0xdd, 0x22, 0x52, 0x5e, 0xbe, 0xa4, 0x5b, 0x44, 0xea, 0x33, 0x17, 0x6a, 0xdc, + 0x91, 0x37, 0x29, 0x69, 0xc6, 0x9d, 0xf6, 0x12, 0xa6, 0x71, 0x65, 0x2a, 0x5e, 0x58, 0x69, 0xb1, + 0x17, 0x2a, 0x69, 0x4a, 0x4b, 0x7f, 0x01, 0xd3, 0xb8, 0x36, 0x03, 0x66, 0xdc, 0x0a, 0x82, 0x7a, + 0x77, 0x96, 0x15, 0x24, 0x5e, 0x67, 0x64, 0x59, 0x41, 0xb2, 0x74, 0xce, 0xad, 0x20, 0x56, 0xa7, + 0xbe, 0x3a, 0x43, 0x5d, 0x2d, 0xdb, 0x0a, 0xd2, 0x2b, 0x70, 0xf2, 0x02, 0xfa, 0x89, 0x04, 0xf5, + 0xac, 0x9a, 0x15, 0x4a, 0x89, 0xef, 0xa6, 0x94, 0xd9, 0x1a, 0x5b, 0xf3, 0x90, 0xf8, 0x52, 0x7c, + 0x05, 0x28, 0x79, 0xee, 0xa1, 0x37, 0xd3, 0x56, 0x26, 0xe3, 0x74, 0x6d, 0xbc, 0x35, 0x1b, 0xb2, + 0x3f, 0x64, 0x0f, 0x8a, 0xa2, 0x4a, 0x86, 0x52, 0xbc, 0x74, 0xac, 0x46, 0xd7, 0x90, 0x27, 0xa1, + 0xf8, 0x4c, 0x1f, 0xc2, 0x22, 0x81, 0xa2, 0x0b, 0xe9, 0xd8, 0x82, 0xd9, 0xc5, 0xac, 0x6e, 0x9f, + 0xd1, 0x13, 0x58, 0x62, 0x65, 0x21, 0x94, 0x92, 0x86, 0x8a, 0x14, 0xaf, 0x1a, 0x97, 0xb2, 0x11, + 0x7c, 0x76, 0x5f, 0xb0, 0xff, 0x28, 0xc3, 0x2b, 0x3e, 0xe8, 0xf5, 0xf4, 0xaf, 0xed, 0xa3, 0x05, + 0xa6, 0xc6, 0x1b, 0x53, 0xb0, 0xc2, 0x9b, 0x22, 0x16, 0xf5, 0x5e, 0x99, 0x7a, 0x75, 0xc9, 0xde, + 0x14, 0xe9, 0x97, 0x23, 0x66, 0x24, 0xc9, 0xcb, 0x53, 0x9a, 0x91, 0x64, 0x5e, 0x59, 0xd3, 0x8c, + 0x24, 0xfb, 0x3e, 0x26, 0x2f, 0x20, 0x0f, 0x4e, 0xa7, 0xe4, 0x4d, 0xd1, 0x5b, 0x59, 0x46, 0x9e, + 0x96, 0xc4, 0x6d, 0xbc, 0x3d, 0x23, 0x76, 0x78, 0xf1, 0xf9, 0xa6, 0x7f, 0x35, 0x3b, 0x99, 0x98, + 0xb9, 0xf8, 0x89, 0x2d, 0xfe, 0x0c, 0xd6, 0xd2, 0xf2, 0x50, 0x28, 0x45, 0xae, 0x09, 0xe9, 0xac, + 0xc6, 0xe6, 0xac, 0xe8, 0x62, 0xe0, 0xad, 0x7f, 0xce, 0xc3, 0x0a, 0x4b, 0xc6, 0xf3, 0xd0, 0xe9, + 0x33, 0x80, 0xa0, 0x0e, 0x86, 0x5e, 0x4b, 0x5f, 0x8c, 0x48, 0xad, 0xb0, 0xf1, 0xfa, 0x64, 0xa4, + 0xb0, 0x85, 0x87, 0x6a, 0x4a, 0x69, 0x16, 0x9e, 0x2c, 0x9d, 0xa5, 0x59, 0x78, 0x4a, 0x61, 0x4a, + 0x5e, 0x40, 0x1f, 0x43, 0xc9, 0x2f, 0x5e, 0xa0, 0xb4, 0xe2, 0x47, 0xac, 0x3a, 0xd3, 0x78, 0x6d, + 0x22, 0x4e, 0x58, 0xea, 0x50, 0x65, 0x22, 0x4d, 0xea, 0x64, 0x05, 0x24, 0x4d, 0xea, 0xb4, 0xf2, + 0x46, 0xa0, 0x13, 0x96, 0xb2, 0xca, 0xd4, 0x49, 0x24, 0x63, 0x98, 0xa9, 0x93, 0x68, 0xde, 0x4b, + 0x5e, 0xb8, 0x7f, 0xf9, 0xe7, 0x5f, 0x5f, 0x94, 0xfe, 0xf1, 0xeb, 0x8b, 0x0b, 0x3f, 0xfe, 0xe6, + 0xa2, 0xf4, 0xf3, 0x6f, 0x2e, 0x4a, 0xff, 0xf0, 0xcd, 0x45, 0xe9, 0x5f, 0xbe, 0xb9, 0x28, 0xfd, + 0xd1, 0xbf, 0x5e, 0x5c, 0xf8, 0x61, 0x51, 0x50, 0x1f, 0x2c, 0xd1, 0x7f, 0x48, 0xf5, 0xee, 0xff, + 0x05, 0x00, 0x00, 0xff, 0xff, 0x3a, 0x25, 0x26, 0xdf, 0x56, 0x4c, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -7226,6 +7506,8 @@ type RuntimeServiceClient interface { UpdateRuntimeConfig(ctx context.Context, in *UpdateRuntimeConfigRequest, opts ...grpc.CallOption) (*UpdateRuntimeConfigResponse, error) // Status returns the status of the runtime. Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) + // GetRuntimeConfigInfo returns the configuration details of the runtime. + GetRuntimeConfigInfo(ctx context.Context, in *GetRuntimeConfigInfoRequest, opts ...grpc.CallOption) (*GetRuntimeConfigInfoResponse, error) } type runtimeServiceClient struct { @@ -7434,6 +7716,15 @@ func (c *runtimeServiceClient) Status(ctx context.Context, in *StatusRequest, op return out, nil } +func (c *runtimeServiceClient) GetRuntimeConfigInfo(ctx context.Context, in *GetRuntimeConfigInfoRequest, opts ...grpc.CallOption) (*GetRuntimeConfigInfoResponse, error) { + out := new(GetRuntimeConfigInfoResponse) + err := c.cc.Invoke(ctx, "/runtime.v1alpha2.RuntimeService/GetRuntimeConfigInfo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // RuntimeServiceServer is the server API for RuntimeService service. type RuntimeServiceServer interface { // Version returns the runtime name, runtime version, and runtime API version. @@ -7505,6 +7796,8 @@ type RuntimeServiceServer interface { UpdateRuntimeConfig(context.Context, *UpdateRuntimeConfigRequest) (*UpdateRuntimeConfigResponse, error) // Status returns the status of the runtime. Status(context.Context, *StatusRequest) (*StatusResponse, error) + // GetRuntimeConfigInfo returns the configuration details of the runtime. + GetRuntimeConfigInfo(context.Context, *GetRuntimeConfigInfoRequest) (*GetRuntimeConfigInfoResponse, error) } // UnimplementedRuntimeServiceServer can be embedded to have forward compatible implementations. @@ -7577,6 +7870,9 @@ func (*UnimplementedRuntimeServiceServer) UpdateRuntimeConfig(ctx context.Contex func (*UnimplementedRuntimeServiceServer) Status(ctx context.Context, req *StatusRequest) (*StatusResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Status not implemented") } +func (*UnimplementedRuntimeServiceServer) GetRuntimeConfigInfo(ctx context.Context, req *GetRuntimeConfigInfoRequest) (*GetRuntimeConfigInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetRuntimeConfigInfo not implemented") +} func RegisterRuntimeServiceServer(s *grpc.Server, srv RuntimeServiceServer) { s.RegisterService(&_RuntimeService_serviceDesc, srv) @@ -7978,6 +8274,24 @@ func _RuntimeService_Status_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _RuntimeService_GetRuntimeConfigInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetRuntimeConfigInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RuntimeServiceServer).GetRuntimeConfigInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/runtime.v1alpha2.RuntimeService/GetRuntimeConfigInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RuntimeServiceServer).GetRuntimeConfigInfo(ctx, req.(*GetRuntimeConfigInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _RuntimeService_serviceDesc = grpc.ServiceDesc{ ServiceName: "runtime.v1alpha2.RuntimeService", HandlerType: (*RuntimeServiceServer)(nil), @@ -8070,6 +8384,10 @@ var _RuntimeService_serviceDesc = grpc.ServiceDesc{ MethodName: "Status", Handler: _RuntimeService_Status_Handler, }, + { + MethodName: "GetRuntimeConfigInfo", + Handler: _RuntimeService_GetRuntimeConfigInfo_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "api.proto", @@ -8567,6 +8885,11 @@ func (m *NamespaceOption) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.User != 0 { + i = encodeVarintApi(dAtA, i, uint64(m.User)) + i-- + dAtA[i] = 0x20 + } if m.Ipc != 0 { i = encodeVarintApi(dAtA, i, uint64(m.Ipc)) i-- @@ -12635,7 +12958,7 @@ func (m *StatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ImageFsInfoRequest) Marshal() (dAtA []byte, err error) { +func (m *LinuxIDMapping) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -12645,20 +12968,35 @@ func (m *ImageFsInfoRequest) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ImageFsInfoRequest) MarshalTo(dAtA []byte) (int, error) { +func (m *LinuxIDMapping) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ImageFsInfoRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *LinuxIDMapping) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l + if m.Size_ != 0 { + i = encodeVarintApi(dAtA, i, uint64(m.Size_)) + i-- + dAtA[i] = 0x18 + } + if m.HostId != 0 { + i = encodeVarintApi(dAtA, i, uint64(m.HostId)) + i-- + dAtA[i] = 0x10 + } + if m.ContainerId != 0 { + i = encodeVarintApi(dAtA, i, uint64(m.ContainerId)) + i-- + dAtA[i] = 0x8 + } return len(dAtA) - i, nil } -func (m *UInt64Value) Marshal() (dAtA []byte, err error) { +func (m *LinuxUserNamespaceConfig) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -12668,25 +13006,192 @@ func (m *UInt64Value) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *UInt64Value) MarshalTo(dAtA []byte) (int, error) { +func (m *LinuxUserNamespaceConfig) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *UInt64Value) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *LinuxUserNamespaceConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if m.Value != 0 { - i = encodeVarintApi(dAtA, i, uint64(m.Value)) - i-- - dAtA[i] = 0x8 + if len(m.GidMappings) > 0 { + for iNdEx := len(m.GidMappings) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.GidMappings[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.UidMappings) > 0 { + for iNdEx := len(m.UidMappings) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.UidMappings[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } } return len(dAtA) - i, nil } -func (m *FilesystemIdentifier) Marshal() (dAtA []byte, err error) { +func (m *ActiveRuntimeConfig) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ActiveRuntimeConfig) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ActiveRuntimeConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.UserNamespaceConfig != nil { + { + size, err := m.UserNamespaceConfig.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GetRuntimeConfigInfoRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetRuntimeConfigInfoRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetRuntimeConfigInfoRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetRuntimeConfigInfoResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetRuntimeConfigInfoResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetRuntimeConfigInfoResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.RuntimeConfig != nil { + { + size, err := m.RuntimeConfig.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintApi(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ImageFsInfoRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ImageFsInfoRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ImageFsInfoRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *UInt64Value) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *UInt64Value) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UInt64Value) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != 0 { + i = encodeVarintApi(dAtA, i, uint64(m.Value)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *FilesystemIdentifier) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -13433,6 +13938,9 @@ func (m *NamespaceOption) Size() (n int) { if m.Ipc != 0 { n += 1 + sovApi(uint64(m.Ipc)) } + if m.User != 0 { + n += 1 + sovApi(uint64(m.User)) + } return n } @@ -15132,6 +15640,80 @@ func (m *StatusResponse) Size() (n int) { return n } +func (m *LinuxIDMapping) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ContainerId != 0 { + n += 1 + sovApi(uint64(m.ContainerId)) + } + if m.HostId != 0 { + n += 1 + sovApi(uint64(m.HostId)) + } + if m.Size_ != 0 { + n += 1 + sovApi(uint64(m.Size_)) + } + return n +} + +func (m *LinuxUserNamespaceConfig) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.UidMappings) > 0 { + for _, e := range m.UidMappings { + l = e.Size() + n += 1 + l + sovApi(uint64(l)) + } + } + if len(m.GidMappings) > 0 { + for _, e := range m.GidMappings { + l = e.Size() + n += 1 + l + sovApi(uint64(l)) + } + } + return n +} + +func (m *ActiveRuntimeConfig) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.UserNamespaceConfig != nil { + l = m.UserNamespaceConfig.Size() + n += 1 + l + sovApi(uint64(l)) + } + return n +} + +func (m *GetRuntimeConfigInfoRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GetRuntimeConfigInfoResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.RuntimeConfig != nil { + l = m.RuntimeConfig.Size() + n += 1 + l + sovApi(uint64(l)) + } + return n +} + func (m *ImageFsInfoRequest) Size() (n int) { if m == nil { return 0 @@ -15472,6 +16054,7 @@ func (this *NamespaceOption) String() string { `Network:` + fmt.Sprintf("%v", this.Network) + `,`, `Pid:` + fmt.Sprintf("%v", this.Pid) + `,`, `Ipc:` + fmt.Sprintf("%v", this.Ipc) + `,`, + `User:` + fmt.Sprintf("%v", this.User) + `,`, `}`, }, "") return s @@ -16668,6 +17251,68 @@ func (this *StatusResponse) String() string { }, "") return s } +func (this *LinuxIDMapping) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&LinuxIDMapping{`, + `ContainerId:` + fmt.Sprintf("%v", this.ContainerId) + `,`, + `HostId:` + fmt.Sprintf("%v", this.HostId) + `,`, + `Size_:` + fmt.Sprintf("%v", this.Size_) + `,`, + `}`, + }, "") + return s +} +func (this *LinuxUserNamespaceConfig) String() string { + if this == nil { + return "nil" + } + repeatedStringForUidMappings := "[]*LinuxIDMapping{" + for _, f := range this.UidMappings { + repeatedStringForUidMappings += strings.Replace(f.String(), "LinuxIDMapping", "LinuxIDMapping", 1) + "," + } + repeatedStringForUidMappings += "}" + repeatedStringForGidMappings := "[]*LinuxIDMapping{" + for _, f := range this.GidMappings { + repeatedStringForGidMappings += strings.Replace(f.String(), "LinuxIDMapping", "LinuxIDMapping", 1) + "," + } + repeatedStringForGidMappings += "}" + s := strings.Join([]string{`&LinuxUserNamespaceConfig{`, + `UidMappings:` + repeatedStringForUidMappings + `,`, + `GidMappings:` + repeatedStringForGidMappings + `,`, + `}`, + }, "") + return s +} +func (this *ActiveRuntimeConfig) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ActiveRuntimeConfig{`, + `UserNamespaceConfig:` + strings.Replace(this.UserNamespaceConfig.String(), "LinuxUserNamespaceConfig", "LinuxUserNamespaceConfig", 1) + `,`, + `}`, + }, "") + return s +} +func (this *GetRuntimeConfigInfoRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&GetRuntimeConfigInfoRequest{`, + `}`, + }, "") + return s +} +func (this *GetRuntimeConfigInfoResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&GetRuntimeConfigInfoResponse{`, + `RuntimeConfig:` + strings.Replace(this.RuntimeConfig.String(), "ActiveRuntimeConfig", "ActiveRuntimeConfig", 1) + `,`, + `}`, + }, "") + return s +} func (this *ImageFsInfoRequest) String() string { if this == nil { return "nil" @@ -17706,6 +18351,25 @@ func (m *NamespaceOption) Unmarshal(dAtA []byte) error { break } } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field User", wireType) + } + m.User = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.User |= NamespaceMode(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipApi(dAtA[iNdEx:]) @@ -30703,6 +31367,468 @@ func (m *StatusResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *LinuxIDMapping) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LinuxIDMapping: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LinuxIDMapping: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ContainerId", wireType) + } + m.ContainerId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ContainerId |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HostId", wireType) + } + m.HostId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HostId |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Size_", wireType) + } + m.Size_ = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Size_ |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LinuxUserNamespaceConfig) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LinuxUserNamespaceConfig: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LinuxUserNamespaceConfig: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UidMappings", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UidMappings = append(m.UidMappings, &LinuxIDMapping{}) + if err := m.UidMappings[len(m.UidMappings)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GidMappings", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GidMappings = append(m.GidMappings, &LinuxIDMapping{}) + if err := m.GidMappings[len(m.GidMappings)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ActiveRuntimeConfig) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ActiveRuntimeConfig: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ActiveRuntimeConfig: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UserNamespaceConfig", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.UserNamespaceConfig == nil { + m.UserNamespaceConfig = &LinuxUserNamespaceConfig{} + } + if err := m.UserNamespaceConfig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetRuntimeConfigInfoRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetRuntimeConfigInfoRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetRuntimeConfigInfoRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetRuntimeConfigInfoResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetRuntimeConfigInfoResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetRuntimeConfigInfoResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RuntimeConfig", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowApi + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthApi + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthApi + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RuntimeConfig == nil { + m.RuntimeConfig = &ActiveRuntimeConfig{} + } + if err := m.RuntimeConfig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipApi(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthApi + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *ImageFsInfoRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.proto b/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.proto index 0290d0f240f98..97642174e188c 100644 --- a/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.proto +++ b/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.proto @@ -107,6 +107,9 @@ service RuntimeService { // Status returns the status of the runtime. rpc Status(StatusRequest) returns (StatusResponse) {} + + // GetRuntimeConfigInfo returns the configuration details of the runtime. + rpc GetRuntimeConfigInfo(GetRuntimeConfigInfoRequest) returns (GetRuntimeConfigInfoResponse) {} } // ImageService defines the public APIs for managing images. @@ -201,7 +204,7 @@ message Mount { } // A NamespaceMode describes the intended namespace configuration for each -// of the namespaces (Network, PID, IPC) in NamespaceOption. Runtimes should +// of the namespaces (Network, PID, IPC, User) in NamespaceOption. Runtimes should // map these modes as appropriate for the technology underlying the runtime. enum NamespaceMode { // A POD namespace is common to all containers in a pod. @@ -233,6 +236,11 @@ message NamespaceOption { // Note: There is currently no way to set CONTAINER scoped IPC in the Kubernetes API. // Namespaces currently set by the kubelet: POD, NODE NamespaceMode ipc = 3; + // User namespace for this container/sandbox. + // Note: There is currently no way to set CONTAINER scoped user namespace in the Kubernetes API. + // NODE is the default value. Kubelet will set it to POD if pod spec indicates to use user-namespace remapping + // Namespaces currently set by the kubelet: POD, NODE + NamespaceMode user = 4; } // Int64Value is the wrapper of int64. @@ -1161,6 +1169,39 @@ message StatusResponse { map info = 2; } +// LinuxIDMapping represents a single user namespace mapping in Linux. +message LinuxIDMapping { + // container_id is the starting id for the mapping inside the container. + uint32 container_id = 1; + // host_id is the starting id for the mapping on the host. + uint32 host_id = 2; + // size is the length of the mapping. + uint32 size = 3; +} + +// LinuxUserNamespaceConfig represents runtime's user-namespace configuration on a linux host. +message LinuxUserNamespaceConfig { + // uid_mappings is an array of user id mappings. + repeated LinuxIDMapping uid_mappings = 1; + // gid_mappings is an array of group id mappings. + repeated LinuxIDMapping gid_mappings = 2; +} + +// ActiveRuntimeConfig contains the configuration details from the runtime. +message ActiveRuntimeConfig { + // LinuxUserNamespaceConfig represents runtime's user-namespace configuration on a linux host. + LinuxUserNamespaceConfig user_namespace_config = 1; +} + +// GetRuntimeConfigInfoRequest is the message sent for requesting runtime configuration details. +message GetRuntimeConfigInfoRequest {} + +// GetRuntimeConfigInfoResponse is the response message from runtime that includes configuration details +message GetRuntimeConfigInfoResponse { + // GetRuntimeConfig are the configuration details from the runtime. + ActiveRuntimeConfig runtime_config = 1; +} + message ImageFsInfoRequest {} // UInt64Value is the wrapper of uint64. diff --git a/staging/src/k8s.io/cri-api/pkg/apis/services.go b/staging/src/k8s.io/cri-api/pkg/apis/services.go index 9a22ecbf031dd..1742738b4811d 100644 --- a/staging/src/k8s.io/cri-api/pkg/apis/services.go +++ b/staging/src/k8s.io/cri-api/pkg/apis/services.go @@ -100,6 +100,8 @@ type RuntimeService interface { UpdateRuntimeConfig(runtimeConfig *runtimeapi.RuntimeConfig) error // Status returns the status of the runtime. Status() (*runtimeapi.RuntimeStatus, error) + // GetRuntimeConfigInfo returns runtime's configuration details, eg: if user-namespaces are enabled or not + GetRuntimeConfigInfo() (*runtimeapi.ActiveRuntimeConfig, error) } // ImageManagerService interface should be implemented by a container image diff --git a/staging/src/k8s.io/cri-api/pkg/apis/testing/fake_runtime_service.go b/staging/src/k8s.io/cri-api/pkg/apis/testing/fake_runtime_service.go index b475ad95d3b50..c486bb190e60b 100644 --- a/staging/src/k8s.io/cri-api/pkg/apis/testing/fake_runtime_service.go +++ b/staging/src/k8s.io/cri-api/pkg/apis/testing/fake_runtime_service.go @@ -57,10 +57,11 @@ type FakeRuntimeService struct { Errors map[string][]error ContainersKilled []string - FakeStatus *runtimeapi.RuntimeStatus - Containers map[string]*FakeContainer - Sandboxes map[string]*FakePodSandbox - FakeContainerStats map[string]*runtimeapi.ContainerStats + FakeStatus *runtimeapi.RuntimeStatus + FakeRuntimeConfigInfo *runtimeapi.ActiveRuntimeConfig + Containers map[string]*FakeContainer + Sandboxes map[string]*FakePodSandbox + FakeContainerStats map[string]*runtimeapi.ContainerStats } func (r *FakeRuntimeService) GetContainerID(sandboxID, name string, attempt uint32) (string, error) { @@ -173,6 +174,18 @@ func (r *FakeRuntimeService) Status() (*runtimeapi.RuntimeStatus, error) { return r.FakeStatus, nil } +func (r *FakeRuntimeService) GetRuntimeConfigInfo() (*runtimeapi.ActiveRuntimeConfig, error) { + r.Lock() + defer r.Unlock() + + r.Called = append(r.Called, "GetRuntimeConfigInfo") + if err := r.popError("GetRuntimeConfigInfo"); err != nil { + return nil, err + } + + return r.FakeRuntimeConfigInfo, nil +} + func (r *FakeRuntimeService) RunPodSandbox(config *runtimeapi.PodSandboxConfig, runtimeHandler string) (string, error) { r.Lock() defer r.Unlock() diff --git a/userns-tests/capabilities/net_admin.yaml b/userns-tests/capabilities/net_admin.yaml new file mode 100644 index 0000000000000..dff79eb0fb9fa --- /dev/null +++ b/userns-tests/capabilities/net_admin.yaml @@ -0,0 +1,19 @@ +# Pod that runs on a different user namespace and has the NET_ADMIN capability +# to add an address to the eth0 interface. +apiVersion: v1 +kind: Pod +metadata: + name: pod-net-admin + namespace: default + annotations: + alpha.kinvolk.io/userns: "pod" +spec: + restartPolicy: Never + containers: + - name: container1 + image: gaiadocker/iproute2 + command: ["sh"] + args: ["-c", "ip addr add 10.10.10.1/24 dev eth0"] + securityContext: + capabilities: + add: ["NET_ADMIN"] diff --git a/userns-tests/capabilities/sys_admin.yaml b/userns-tests/capabilities/sys_admin.yaml new file mode 100644 index 0000000000000..637f56311e27b --- /dev/null +++ b/userns-tests/capabilities/sys_admin.yaml @@ -0,0 +1,20 @@ +# Pod that runs on a different user namespace and has the SYS_ADMIN capability +# to create a tmpfs mount. +apiVersion: v1 +kind: Pod +metadata: + name: pod-sys-admin + namespace: default + annotations: + alpha.kinvolk.io/userns: "pod" + container.apparmor.security.beta.kubernetes.io/container1: "unconfined" +spec: + restartPolicy: Never + containers: + - name: container1 + image: busybox + command: ["sh"] + args: ["-c", "mkdir temp && mount -t tmpfs -o size=10M tmpfs temp"] + securityContext: + capabilities: + add: ["SYS_ADMIN"] diff --git a/userns-tests/default-standard.yaml b/userns-tests/default-standard.yaml new file mode 100644 index 0000000000000..92a590c0b2618 --- /dev/null +++ b/userns-tests/default-standard.yaml @@ -0,0 +1,15 @@ +# Pod without the userns annotation and without any feature that would cause +# the user namespace support to be disable if available in the runtime. +# User namespace should be used if available in the runtime. +apiVersion: v1 +kind: Pod +metadata: + name: default-standard + namespace: default +spec: + restartPolicy: Never + containers: + - name: container1 + image: busybox + command: ["sh"] + args: ["-c", "sleep infinity"] diff --git a/userns-tests/detault-special.yaml b/userns-tests/detault-special.yaml new file mode 100644 index 0000000000000..9cc73f87b631d --- /dev/null +++ b/userns-tests/detault-special.yaml @@ -0,0 +1,15 @@ +# Pod without the userns annotation and with special features that would cause +# the user namespace support to be disabled. +apiVersion: v1 +kind: Pod +metadata: + name: default-special + namespace: default +spec: + restartPolicy: Never + containers: + - name: container1 + image: busybox + command: ["sh"] + args: ["-c", "sleep infinity"] + hostNetwork: true diff --git a/userns-tests/ipc/test-dev-shm.yaml b/userns-tests/ipc/test-dev-shm.yaml new file mode 100644 index 0000000000000..b86825702483f --- /dev/null +++ b/userns-tests/ipc/test-dev-shm.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-dev-shm + namespace: default + annotations: + alpha.kinvolk.io/userns: "pod" +spec: + restartPolicy: Never + containers: + - name: reader + image: busybox + command: ["sh"] + args: ["-c", 'content=$(cat /dev/shm//foo.txt); if [[ "$content" != "bar" ]]; then exit 1; else exit 0; fi'] + initContainers: + - name: writer + image: busybox + command: ["sh"] + args: ["-c", "echo 'bar' > /dev/shm/foo.txt"] diff --git a/userns-tests/ipc/test-empty-volume.yaml b/userns-tests/ipc/test-empty-volume.yaml new file mode 100644 index 0000000000000..6faf4e0922f49 --- /dev/null +++ b/userns-tests/ipc/test-empty-volume.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-empty-volume + namespace: default + annotations: + alpha.kinvolk.io/userns: "pod" +spec: + restartPolicy: Never + containers: + - name: reader + image: busybox + command: ["sh"] + args: ["-c", 'content=$(cat /cache2/foo.txt); if [[ "$content" != "bar" ]]; then exit 1; else exit 0; fi'] + volumeMounts: + - mountPath: /cache2 + name: cache-volume + initContainers: + - name: writer + image: busybox + command: ["sh"] + args: ["-c", "echo 'bar' > /cache1/foo.txt"] + volumeMounts: + - mountPath: /cache1 + name: cache-volume + volumes: + - name: cache-volume + emptyDir: {} diff --git a/userns-tests/ipc/test-shm.yaml b/userns-tests/ipc/test-shm.yaml new file mode 100644 index 0000000000000..ea5c1214d7711 --- /dev/null +++ b/userns-tests/ipc/test-shm.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-shm + namespace: default + annotations: + alpha.kinvolk.io/userns: "pod" +spec: + restartPolicy: Never + containers: + - name: reader + image: mauriciovasquezbernal/sharedmemoryexample + command: ["bash"] + args: ["-c", 'content=$(/reader); if [[ "$content" != "bar" ]]; then exit 1; else exit 0; fi'] + initContainers: + - name: writer + image: mauriciovasquezbernal/sharedmemoryexample + command: ["/writer"] + args: ["bar"] diff --git a/userns-tests/node-special.yaml b/userns-tests/node-special.yaml new file mode 100644 index 0000000000000..3a2a8282a211d --- /dev/null +++ b/userns-tests/node-special.yaml @@ -0,0 +1,16 @@ +# Pod user with userns set to "node" mode and special features. +apiVersion: v1 +kind: Pod +metadata: + name: node-special + namespace: default + annotations: + alpha.kinvolk.io/userns: "node" +spec: + restartPolicy: Never + containers: + - name: container1 + image: busybox + command: ["sh"] + args: ["-c", "sleep infinity"] + hostNetwork: true diff --git a/userns-tests/node-standard.yaml b/userns-tests/node-standard.yaml new file mode 100644 index 0000000000000..475e7fa2353e1 --- /dev/null +++ b/userns-tests/node-standard.yaml @@ -0,0 +1,15 @@ +# Pod user with userns set to "node" mode. +apiVersion: v1 +kind: Pod +metadata: + name: node-standard + namespace: default + annotations: + alpha.kinvolk.io/userns: "node" +spec: + restartPolicy: Never + containers: + - name: container1 + image: busybox + command: ["sh"] + args: ["-c", "sleep infinity"] diff --git a/userns-tests/pod-special.yaml b/userns-tests/pod-special.yaml new file mode 100644 index 0000000000000..b524276b16743 --- /dev/null +++ b/userns-tests/pod-special.yaml @@ -0,0 +1,17 @@ +# Pod user with userns set to "pod" mode and special features. +# The pod creation will fail. +apiVersion: v1 +kind: Pod +metadata: + name: pod-special + namespace: default + annotations: + alpha.kinvolk.io/userns: "pod" +spec: + restartPolicy: Never + containers: + - name: container1 + image: busybox + command: ["sh"] + args: ["-c", "sleep infinity"] + hostNetwork: true diff --git a/userns-tests/pod-standard.yaml b/userns-tests/pod-standard.yaml new file mode 100644 index 0000000000000..5534ae0557c26 --- /dev/null +++ b/userns-tests/pod-standard.yaml @@ -0,0 +1,16 @@ +# Pod user with userns set to "pod" mode. Pod creation would fail if userns +# not supported by runtime. +apiVersion: v1 +kind: Pod +metadata: + name: pod-standard + namespace: default + annotations: + alpha.kinvolk.io/userns: "pod" +spec: + restartPolicy: Never + containers: + - name: container1 + image: busybox + command: ["sh"] + args: ["-c", "sleep infinity"] diff --git a/userns-tests/volumes/pod-with-config-map.yaml b/userns-tests/volumes/pod-with-config-map.yaml new file mode 100644 index 0000000000000..2c886d2dc6abf --- /dev/null +++ b/userns-tests/volumes/pod-with-config-map.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: test-config-map + namespace: default +data: + content: '"This is a ConfigMap"' +--- +apiVersion: v1 +kind: Pod +metadata: + name: pod-with-configmap + namespace: default +spec: + securityContext: + # Uncomment the following lines to get different behaviours + #runAsUser: 1000 + #runAsGroup: 3000 + #fsGroup: 2000 + restartPolicy: Never + containers: + - name: pod-with-configmap + image: busybox + command: ["sh"] + args: ["-c", "sleep infinity"] + volumeMounts: + - name: config-volume + mountPath: /etc/userns-cm/content + volumes: + - name: config-volume + configMap: + name: test-config-map + defaultMode: 0400