mirror of
https://github.com/outbackdingo/kubernetes.git
synced 2026-01-27 18:19:28 +00:00
SSA: add integration tests
test/integration/apiserver/apply covers the behavior of server-side-apply (SSA) for official APIs. But there seem to be no integration tests which cover the semantic of SSA like adding/removing/updating entries in a list map. This adds such a test. It needs an API which is under control of the test and uses k8s.io/apimachinery/pkg/apis/testapigroup for that purpose, with some issues fixed (OpenAPI code generation complained) and a new list map added. Registering that API group in the apiserver needs a REST storage and strategy. The API group only gets added in the test. However, the production code has to know about it. In particular, pkg/generated/openapi/zz_generated.openapi.go has to describe it.
This commit is contained in:
@@ -120,6 +120,12 @@ const (
|
||||
repairLoopInterval = 3 * time.Minute
|
||||
)
|
||||
|
||||
var (
|
||||
// AdditionalStorageProvidersForTests allows tests to inject additional test-only API groups.
|
||||
// Only meant for use in integration tests.
|
||||
AdditionalStorageProvidersForTests func(client *kubernetes.Clientset) []controlplaneapiserver.RESTStorageProvider
|
||||
)
|
||||
|
||||
// Extra defines extra configuration for kube-apiserver
|
||||
type Extra struct {
|
||||
EndpointReconcilerConfig EndpointReconcilerConfig
|
||||
@@ -401,7 +407,7 @@ func (c CompletedConfig) StorageProviders(client *kubernetes.Clientset) ([]contr
|
||||
// with specific priorities.
|
||||
// TODO: describe the priority all the way down in the RESTStorageProviders and plumb it back through the various discovery
|
||||
// handlers that we have.
|
||||
return []controlplaneapiserver.RESTStorageProvider{
|
||||
providers := []controlplaneapiserver.RESTStorageProvider{
|
||||
legacyRESTStorageProvider,
|
||||
apiserverinternalrest.StorageProvider{},
|
||||
authenticationrest.RESTStorageProvider{Authenticator: c.ControlPlane.Generic.Authentication.Authenticator, APIAudiences: c.ControlPlane.Generic.Authentication.APIAudiences},
|
||||
@@ -425,7 +431,13 @@ func (c CompletedConfig) StorageProviders(client *kubernetes.Clientset) ([]contr
|
||||
admissionregistrationrest.RESTStorageProvider{Authorizer: c.ControlPlane.Generic.Authorization.Authorizer, DiscoveryClient: client.Discovery()},
|
||||
eventsrest.RESTStorageProvider{TTL: c.ControlPlane.EventTTL},
|
||||
resourcerest.RESTStorageProvider{NamespaceClient: client.CoreV1().Namespaces()},
|
||||
}, nil
|
||||
}
|
||||
|
||||
if AdditionalStorageProvidersForTests != nil {
|
||||
providers = append(providers, AdditionalStorageProvidersForTests(client)...)
|
||||
}
|
||||
|
||||
return providers, nil
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
417
pkg/generated/openapi/zz_generated.openapi.go
generated
417
pkg/generated/openapi/zz_generated.openapi.go
generated
@@ -1163,6 +1163,12 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1.UpdateOptions": schema_pkg_apis_meta_v1_UpdateOptions(ref),
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1.WatchEvent": schema_pkg_apis_meta_v1_WatchEvent(ref),
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1beta1.PartialObjectMetadataList": schema_pkg_apis_meta_v1beta1_PartialObjectMetadataList(ref),
|
||||
"k8s.io/apimachinery/pkg/apis/testapigroup/v1.Carp": schema_pkg_apis_testapigroup_v1_Carp(ref),
|
||||
"k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpCondition": schema_pkg_apis_testapigroup_v1_CarpCondition(ref),
|
||||
"k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpInfo": schema_pkg_apis_testapigroup_v1_CarpInfo(ref),
|
||||
"k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpList": schema_pkg_apis_testapigroup_v1_CarpList(ref),
|
||||
"k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpSpec": schema_pkg_apis_testapigroup_v1_CarpSpec(ref),
|
||||
"k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpStatus": schema_pkg_apis_testapigroup_v1_CarpStatus(ref),
|
||||
"k8s.io/apimachinery/pkg/runtime.RawExtension": schema_k8sio_apimachinery_pkg_runtime_RawExtension(ref),
|
||||
"k8s.io/apimachinery/pkg/runtime.TypeMeta": schema_k8sio_apimachinery_pkg_runtime_TypeMeta(ref),
|
||||
"k8s.io/apimachinery/pkg/runtime.Unknown": schema_k8sio_apimachinery_pkg_runtime_Unknown(ref),
|
||||
@@ -59659,6 +59665,417 @@ func schema_pkg_apis_meta_v1beta1_PartialObjectMetadataList(ref common.Reference
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_testapigroup_v1_Carp(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Carp is a collection of containers, used as either input (create, update) or as output (list, get).",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"kind": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"apiVersion": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"metadata": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata",
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
|
||||
},
|
||||
},
|
||||
"spec": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Specification of the desired behavior of the carp. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status",
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpSpec"),
|
||||
},
|
||||
},
|
||||
"status": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Most recently observed status of the carp. This data may not be up to date. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status",
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpStatus"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta", "k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpSpec", "k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpStatus"},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_testapigroup_v1_CarpCondition(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"type": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Type is the type of the condition. Currently only Ready. More info: http://kubernetes.io/docs/user-guide/carp-states#carp-conditions",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"status": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Status is the status of the condition. Can be True, False, Unknown. More info: http://kubernetes.io/docs/user-guide/carp-states#carp-conditions",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"lastProbeTime": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Last time we probed the condition.",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
|
||||
},
|
||||
},
|
||||
"lastTransitionTime": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Last time the condition transitioned from one status to another.",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
|
||||
},
|
||||
},
|
||||
"reason": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Unique, one-word, CamelCase reason for the condition's last transition.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"message": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Human-readable message indicating details about last transition.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"type", "status"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_testapigroup_v1_CarpInfo(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"a": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A is the first map key.",
|
||||
Default: 0,
|
||||
Type: []string{"integer"},
|
||||
Format: "int64",
|
||||
},
|
||||
},
|
||||
"b": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "B is the second map key.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"data": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Some data for each pair of A and B.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"a", "b", "data"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_testapigroup_v1_CarpList(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "CarpList is a list of Carps.",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"kind": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"apiVersion": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"metadata": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
|
||||
},
|
||||
},
|
||||
"items": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "List of carps. More info: http://kubernetes.io/docs/user-guide/carps",
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/testapigroup/v1.Carp"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"items"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta", "k8s.io/apimachinery/pkg/apis/testapigroup/v1.Carp"},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_testapigroup_v1_CarpSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "CarpSpec is a description of a carp",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"restartPolicy": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Restart policy for all containers within the carp. One of Always, OnFailure, Never. Default to Always. More info: http://kubernetes.io/docs/user-guide/carp-states#restartpolicy",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"terminationGracePeriodSeconds": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Optional duration in seconds the carp needs to terminate gracefully. May be decreased in delete request. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period will be used instead. The grace period is the duration in seconds after the processes running in the carp are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process. Defaults to 30 seconds.",
|
||||
Type: []string{"integer"},
|
||||
Format: "int64",
|
||||
},
|
||||
},
|
||||
"activeDeadlineSeconds": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Optional duration in seconds the carp may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer.",
|
||||
Type: []string{"integer"},
|
||||
Format: "int64",
|
||||
},
|
||||
},
|
||||
"nodeSelector": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "NodeSelector is a selector which must be true for the carp to fit on a node. Selector which must match a node's labels for the carp to be scheduled on that node. More info: http://kubernetes.io/docs/user-guide/node-selection/README",
|
||||
Type: []string{"object"},
|
||||
AdditionalProperties: &spec.SchemaOrBool{
|
||||
Allows: true,
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"serviceAccountName": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ServiceAccountName is the name of the ServiceAccount to use to run this carp. More info: https://kubernetes.io/docs/concepts/security/service-accounts/",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"deprecatedServiceAccount": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "DeprecatedServiceAccount is a deprecated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"nodeName": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "NodeName is a request to schedule this carp onto a specific node. If it is non-empty, the scheduler simply schedules this carp onto that node, assuming that it fits resource requirements.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"hostNetwork": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Host networking requested for this carp. Use the host's network namespace. Default to false.",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"hostPID": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Use the host's pid namespace. Optional: Default to false.",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"hostIPC": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Use the host's ipc namespace. Optional: Default to false.",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"hostname": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Specifies the hostname of the Carp If not specified, the carp's hostname will be set to a system-defined value.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"subdomain": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "If specified, the fully qualified Carp hostname will be \"<hostname>.<subdomain>.<carp namespace>.svc.<cluster domain>\". If not specified, the carp will not have a domainname at all.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"schedulerName": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "If specified, the carp will be dispatched by specified scheduler. If not specified, the carp will be dispatched by default scheduler.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_testapigroup_v1_CarpStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "CarpStatus represents information about the status of a carp. Status may trail the actual state of a system.",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"phase": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Current condition of the carp. More info: http://kubernetes.io/docs/user-guide/carp-states#carp-phase",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"conditions": {
|
||||
VendorExtensible: spec.VendorExtensible{
|
||||
Extensions: spec.Extensions{
|
||||
"x-kubernetes-list-map-keys": []interface{}{
|
||||
"type",
|
||||
},
|
||||
"x-kubernetes-list-type": "map",
|
||||
"x-kubernetes-patch-merge-key": "type",
|
||||
"x-kubernetes-patch-strategy": "merge",
|
||||
},
|
||||
},
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Current service state of carp. More info: http://kubernetes.io/docs/user-guide/carp-states#carp-conditions",
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpCondition"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"message": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A human readable message indicating details about why the carp is in this condition.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"reason": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A brief CamelCase message indicating details about why the carp is in this state. e.g. 'DiskPressure'",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"hostIP": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "IP address of the host to which the carp is assigned. Empty if not yet scheduled.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"carpIP": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "IP address allocated to the carp. Routable at least within the cluster. Empty if not yet allocated.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"startTime": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "RFC 3339 date and time at which the object was acknowledged by the Kubelet. This is before the Kubelet pulled the container image(s) for the carp.",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
|
||||
},
|
||||
},
|
||||
"infos": {
|
||||
VendorExtensible: spec.VendorExtensible{
|
||||
Extensions: spec.Extensions{
|
||||
"x-kubernetes-list-map-keys": []interface{}{
|
||||
"a",
|
||||
"b",
|
||||
},
|
||||
"x-kubernetes-list-type": "map",
|
||||
},
|
||||
},
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Carp infos are provided by different clients, hence the map type.",
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpInfo"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1.Time", "k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpCondition", "k8s.io/apimachinery/pkg/apis/testapigroup/v1.CarpInfo"},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_apimachinery_pkg_runtime_RawExtension(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
|
||||
108
pkg/registry/testapigroup/carp/storage/storage.go
Normal file
108
pkg/registry/testapigroup/carp/storage/storage.go
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/testapigroup"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
|
||||
printerstorage "k8s.io/kubernetes/pkg/printers/storage"
|
||||
"k8s.io/kubernetes/pkg/registry/testapigroup/carp"
|
||||
"sigs.k8s.io/structured-merge-diff/v6/fieldpath"
|
||||
)
|
||||
|
||||
// REST implements a RESTStorage for Carps.
|
||||
type REST struct {
|
||||
*genericregistry.Store
|
||||
}
|
||||
|
||||
// NewREST returns a RESTStorage object that will work against Carps.
|
||||
func NewREST(optsGetter generic.RESTOptionsGetter, nsClient v1.NamespaceInterface) (*REST, *StatusREST, error) {
|
||||
if nsClient == nil {
|
||||
return nil, nil, fmt.Errorf("namespace client is required")
|
||||
}
|
||||
strategy := carp.NewStrategy(nsClient)
|
||||
store := &genericregistry.Store{
|
||||
NewFunc: func() runtime.Object { return &testapigroup.Carp{} },
|
||||
NewListFunc: func() runtime.Object { return &testapigroup.CarpList{} },
|
||||
PredicateFunc: carp.Match,
|
||||
DefaultQualifiedResource: testapigroup.Resource("carps"),
|
||||
SingularQualifiedResource: testapigroup.Resource("carp"),
|
||||
|
||||
CreateStrategy: strategy,
|
||||
UpdateStrategy: strategy,
|
||||
DeleteStrategy: strategy,
|
||||
ReturnDeletedObject: true,
|
||||
ResetFieldsStrategy: strategy,
|
||||
|
||||
TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
|
||||
}
|
||||
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: carp.GetAttrs}
|
||||
if err := store.CompleteWithOptions(options); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
statusStore := *store
|
||||
statusStrategy := carp.NewStatusStrategy(strategy)
|
||||
statusStore.UpdateStrategy = statusStrategy
|
||||
statusStore.ResetFieldsStrategy = statusStrategy
|
||||
|
||||
rest := &REST{store}
|
||||
|
||||
return rest, &StatusREST{store: &statusStore}, nil
|
||||
}
|
||||
|
||||
// StatusREST implements the REST endpoint for changing the status of a Carp.
|
||||
type StatusREST struct {
|
||||
store *genericregistry.Store
|
||||
}
|
||||
|
||||
// New creates a new Carp object.
|
||||
func (r *StatusREST) New() runtime.Object {
|
||||
return &testapigroup.Carp{}
|
||||
}
|
||||
|
||||
func (r *StatusREST) Destroy() {
|
||||
// Given that underlying store is shared with REST,
|
||||
// we don't destroy it here explicitly.
|
||||
}
|
||||
|
||||
// Get retrieves the object from the storage. It is required to support Patch.
|
||||
func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
|
||||
return r.store.Get(ctx, name, options)
|
||||
}
|
||||
|
||||
// Update alters the status subset of an object.
|
||||
func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
|
||||
// We are explicitly setting forceAllowCreate to false in the call to the underlying storage because
|
||||
// subresources should never allow create on update.
|
||||
return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options)
|
||||
}
|
||||
|
||||
// GetResetFields implements rest.ResetFieldsStrategy
|
||||
func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
|
||||
return r.store.GetResetFields()
|
||||
}
|
||||
168
pkg/registry/testapigroup/carp/strategy.go
Normal file
168
pkg/registry/testapigroup/carp/strategy.go
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package carp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/testapigroup"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
"k8s.io/apiserver/pkg/storage"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"sigs.k8s.io/structured-merge-diff/v6/fieldpath"
|
||||
)
|
||||
|
||||
// carpStrategy implements behavior for Carp objects
|
||||
type carpStrategy struct {
|
||||
runtime.ObjectTyper
|
||||
names.NameGenerator
|
||||
nsClient v1.NamespaceInterface
|
||||
}
|
||||
|
||||
// NewStrategy is the default logic that applies when creating and updating Carp objects.
|
||||
func NewStrategy(nsClient v1.NamespaceInterface) *carpStrategy {
|
||||
return &carpStrategy{
|
||||
legacyscheme.Scheme,
|
||||
names.SimpleNameGenerator,
|
||||
nsClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (*carpStrategy) NamespaceScoped() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// GetResetFields returns the set of fields that get reset by the strategy and
|
||||
// should not be modified by the user. For a new Carp that is the
|
||||
// status.
|
||||
func (*carpStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
|
||||
fields := map[fieldpath.APIVersion]*fieldpath.Set{
|
||||
"testapigroup.apimachinery.k8s.io/v1": fieldpath.NewSet(
|
||||
fieldpath.MakePathOrDie("status"),
|
||||
),
|
||||
}
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
func (*carpStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
||||
claim := obj.(*testapigroup.Carp)
|
||||
// Status must not be set by user on create.
|
||||
claim.Status = testapigroup.CarpStatus{}
|
||||
}
|
||||
|
||||
func (s *carpStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*carpStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*carpStrategy) Canonicalize(obj runtime.Object) {
|
||||
}
|
||||
|
||||
func (*carpStrategy) AllowCreateOnUpdate() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (*carpStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
|
||||
newClaim := obj.(*testapigroup.Carp)
|
||||
oldClaim := old.(*testapigroup.Carp)
|
||||
newClaim.Status = oldClaim.Status
|
||||
}
|
||||
|
||||
func (s *carpStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*carpStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*carpStrategy) AllowUnconditionalUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type carpStatusStrategy struct {
|
||||
*carpStrategy
|
||||
}
|
||||
|
||||
// NewStatusStrategy creates a strategy for operating the status object.
|
||||
func NewStatusStrategy(carpStrategy *carpStrategy) *carpStatusStrategy {
|
||||
return &carpStatusStrategy{carpStrategy}
|
||||
}
|
||||
|
||||
// GetResetFields returns the set of fields that get reset by the strategy and
|
||||
// should not be modified by the user. For a status update that is the spec.
|
||||
func (*carpStatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
|
||||
fields := map[fieldpath.APIVersion]*fieldpath.Set{
|
||||
"testapigroup.apimachinery.k8s.io/v1": fieldpath.NewSet(
|
||||
fieldpath.MakePathOrDie("spec"),
|
||||
),
|
||||
}
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
func (*carpStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
|
||||
newClaim := obj.(*testapigroup.Carp)
|
||||
oldClaim := old.(*testapigroup.Carp)
|
||||
newClaim.Spec = oldClaim.Spec
|
||||
metav1.ResetObjectMetaForStatus(&newClaim.ObjectMeta, &oldClaim.ObjectMeta)
|
||||
}
|
||||
|
||||
func (r *carpStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WarningsOnUpdate returns warnings for the given update.
|
||||
func (*carpStatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Match returns a generic matcher for a given label and field selector.
|
||||
func Match(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||
return storage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
claim, ok := obj.(*testapigroup.Carp)
|
||||
if !ok {
|
||||
return nil, nil, errors.New("not a carp")
|
||||
}
|
||||
return labels.Set(claim.Labels), toSelectableFields(claim), nil
|
||||
}
|
||||
|
||||
// toSelectableFields returns a field set that represents the object
|
||||
func toSelectableFields(claim *testapigroup.Carp) fields.Set {
|
||||
fields := generic.ObjectMetaFieldsSet(&claim.ObjectMeta, true)
|
||||
return fields
|
||||
}
|
||||
66
pkg/registry/testapigroup/rest/storage_resource.go
Normal file
66
pkg/registry/testapigroup/rest/storage_resource.go
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package rest
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/apis/testapigroup"
|
||||
testapigroupv1 "k8s.io/apimachinery/pkg/apis/testapigroup/v1"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
carpstore "k8s.io/kubernetes/pkg/registry/testapigroup/carp/storage"
|
||||
)
|
||||
|
||||
type RESTStorageProvider struct {
|
||||
NamespaceClient v1.NamespaceInterface
|
||||
}
|
||||
|
||||
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) {
|
||||
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(testapigroup.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs)
|
||||
// If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities.
|
||||
// TODO refactor the plumbing to provide the information in the APIGroupInfo
|
||||
|
||||
if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter, p.NamespaceClient); err != nil {
|
||||
return genericapiserver.APIGroupInfo{}, err
|
||||
} else if len(storageMap) > 0 {
|
||||
apiGroupInfo.VersionedResourcesStorageMap[testapigroupv1.SchemeGroupVersion.Version] = storageMap
|
||||
}
|
||||
|
||||
return apiGroupInfo, nil
|
||||
}
|
||||
|
||||
func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter, nsClient v1.NamespaceInterface) (map[string]rest.Storage, error) {
|
||||
storage := map[string]rest.Storage{}
|
||||
|
||||
if resource := "carps"; apiResourceConfigSource.ResourceEnabled(testapigroupv1.SchemeGroupVersion.WithResource(resource)) {
|
||||
resourceClaimStorage, resourceClaimStatusStorage, err := carpstore.NewREST(restOptionsGetter, nsClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storage[resource] = resourceClaimStorage
|
||||
storage[resource+"/status"] = resourceClaimStatusStorage
|
||||
}
|
||||
|
||||
return storage, nil
|
||||
}
|
||||
|
||||
func (p RESTStorageProvider) GroupName() string {
|
||||
return testapigroup.GroupName
|
||||
}
|
||||
@@ -46,6 +46,7 @@ func Resource(resource string) schema.GroupResource {
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Carp{},
|
||||
&CarpList{},
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -68,6 +68,13 @@ type CarpStatus struct {
|
||||
// This is before the Kubelet pulled the container image(s) for the carp.
|
||||
// +optional
|
||||
StartTime *metav1.Time
|
||||
|
||||
// Carp infos are provided by different clients, hence the map type.
|
||||
//
|
||||
// +listType=map
|
||||
// +listKey=a
|
||||
// +listKey=b
|
||||
Infos []CarpInfo
|
||||
}
|
||||
|
||||
type CarpCondition struct {
|
||||
@@ -83,6 +90,18 @@ type CarpCondition struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
type CarpInfo struct {
|
||||
// A is the first map key.
|
||||
// +required
|
||||
A int64
|
||||
// B is the second map key.
|
||||
// +required
|
||||
B string
|
||||
|
||||
// Some data for each pair of A and B.
|
||||
Data string
|
||||
}
|
||||
|
||||
// CarpSpec is a description of a carp
|
||||
type CarpSpec struct {
|
||||
// +optional
|
||||
|
||||
@@ -14,11 +14,13 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/apimachinery/pkg/apis/testapigroup
|
||||
// +k8s:openapi-gen=false
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
|
||||
// +k8s:prerelease-lifecycle-gen=true
|
||||
// +groupName=testapigroup.apimachinery.k8s.io
|
||||
|
||||
package v1
|
||||
|
||||
@@ -101,10 +101,38 @@ func (m *CarpCondition) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_CarpCondition proto.InternalMessageInfo
|
||||
|
||||
func (m *CarpInfo) Reset() { *m = CarpInfo{} }
|
||||
func (*CarpInfo) ProtoMessage() {}
|
||||
func (*CarpInfo) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_83e19b543dd132db, []int{2}
|
||||
}
|
||||
func (m *CarpInfo) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *CarpInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
func (m *CarpInfo) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_CarpInfo.Merge(m, src)
|
||||
}
|
||||
func (m *CarpInfo) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *CarpInfo) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_CarpInfo.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_CarpInfo proto.InternalMessageInfo
|
||||
|
||||
func (m *CarpList) Reset() { *m = CarpList{} }
|
||||
func (*CarpList) ProtoMessage() {}
|
||||
func (*CarpList) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_83e19b543dd132db, []int{2}
|
||||
return fileDescriptor_83e19b543dd132db, []int{3}
|
||||
}
|
||||
func (m *CarpList) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -132,7 +160,7 @@ var xxx_messageInfo_CarpList proto.InternalMessageInfo
|
||||
func (m *CarpSpec) Reset() { *m = CarpSpec{} }
|
||||
func (*CarpSpec) ProtoMessage() {}
|
||||
func (*CarpSpec) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_83e19b543dd132db, []int{3}
|
||||
return fileDescriptor_83e19b543dd132db, []int{4}
|
||||
}
|
||||
func (m *CarpSpec) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -160,7 +188,7 @@ var xxx_messageInfo_CarpSpec proto.InternalMessageInfo
|
||||
func (m *CarpStatus) Reset() { *m = CarpStatus{} }
|
||||
func (*CarpStatus) ProtoMessage() {}
|
||||
func (*CarpStatus) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_83e19b543dd132db, []int{4}
|
||||
return fileDescriptor_83e19b543dd132db, []int{5}
|
||||
}
|
||||
func (m *CarpStatus) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@@ -188,6 +216,7 @@ var xxx_messageInfo_CarpStatus proto.InternalMessageInfo
|
||||
func init() {
|
||||
proto.RegisterType((*Carp)(nil), "k8s.io.apimachinery.pkg.apis.testapigroup.v1.Carp")
|
||||
proto.RegisterType((*CarpCondition)(nil), "k8s.io.apimachinery.pkg.apis.testapigroup.v1.CarpCondition")
|
||||
proto.RegisterType((*CarpInfo)(nil), "k8s.io.apimachinery.pkg.apis.testapigroup.v1.CarpInfo")
|
||||
proto.RegisterType((*CarpList)(nil), "k8s.io.apimachinery.pkg.apis.testapigroup.v1.CarpList")
|
||||
proto.RegisterType((*CarpSpec)(nil), "k8s.io.apimachinery.pkg.apis.testapigroup.v1.CarpSpec")
|
||||
proto.RegisterMapType((map[string]string)(nil), "k8s.io.apimachinery.pkg.apis.testapigroup.v1.CarpSpec.NodeSelectorEntry")
|
||||
@@ -199,72 +228,76 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_83e19b543dd132db = []byte{
|
||||
// 1037 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xc1, 0x6e, 0xdb, 0x46,
|
||||
0x13, 0x36, 0x2d, 0xc9, 0x96, 0xd6, 0x56, 0x62, 0x6f, 0x62, 0x80, 0xbf, 0x81, 0x48, 0x8e, 0x0f,
|
||||
0x86, 0xff, 0xc2, 0xa5, 0x62, 0xa3, 0x09, 0xdc, 0xa6, 0x40, 0x11, 0xda, 0x45, 0xa5, 0xc2, 0x71,
|
||||
0x84, 0x95, 0x81, 0x14, 0x45, 0x0f, 0x59, 0x51, 0x5b, 0x8a, 0x95, 0xc8, 0x25, 0x76, 0x57, 0x2a,
|
||||
0x74, 0x2b, 0xfa, 0x04, 0x7d, 0x88, 0xde, 0x7a, 0xee, 0x03, 0xf4, 0x50, 0xc0, 0xc7, 0x1c, 0x73,
|
||||
0x12, 0x6a, 0xf5, 0x2d, 0x7c, 0x2a, 0x76, 0xb9, 0xa4, 0x48, 0x4b, 0x55, 0xa3, 0xdc, 0xb8, 0x33,
|
||||
0xdf, 0xf7, 0xcd, 0xec, 0xce, 0x68, 0x46, 0xe0, 0xf3, 0xde, 0x29, 0xb7, 0x3c, 0x5a, 0xc3, 0xa1,
|
||||
0xe7, 0x63, 0xa7, 0xeb, 0x05, 0x84, 0x8d, 0x6a, 0x61, 0xcf, 0x95, 0x06, 0x5e, 0x13, 0x84, 0x0b,
|
||||
0x1c, 0x7a, 0x2e, 0xa3, 0x83, 0xb0, 0x36, 0x3c, 0xae, 0xb9, 0x24, 0x20, 0x0c, 0x0b, 0xd2, 0xb1,
|
||||
0x42, 0x46, 0x05, 0x85, 0x47, 0x11, 0xdb, 0x4a, 0xb3, 0xad, 0xb0, 0xe7, 0x4a, 0x03, 0xb7, 0xd2,
|
||||
0x6c, 0x6b, 0x78, 0xbc, 0xfb, 0xb1, 0xeb, 0x89, 0xee, 0xa0, 0x6d, 0x39, 0xd4, 0xaf, 0xb9, 0xd4,
|
||||
0xa5, 0x35, 0x25, 0xd2, 0x1e, 0x7c, 0xaf, 0x4e, 0xea, 0xa0, 0xbe, 0x22, 0xf1, 0xdd, 0x4f, 0x16,
|
||||
0xa6, 0xe6, 0x13, 0x81, 0xe7, 0xa4, 0xb4, 0x5b, 0xfb, 0x37, 0x16, 0x1b, 0x04, 0xc2, 0xf3, 0xc9,
|
||||
0x0c, 0xe1, 0xd9, 0x7f, 0x11, 0xb8, 0xd3, 0x25, 0x3e, 0xbe, 0xcb, 0xdb, 0xff, 0x75, 0x15, 0xe4,
|
||||
0xcf, 0x30, 0x0b, 0xe1, 0x1b, 0x50, 0x94, 0xc9, 0x74, 0xb0, 0xc0, 0xa6, 0xb1, 0x67, 0x1c, 0x6e,
|
||||
0x9c, 0x3c, 0xb1, 0x16, 0xbe, 0x8b, 0x44, 0x5b, 0xc3, 0x63, 0xeb, 0x55, 0xfb, 0x07, 0xe2, 0x88,
|
||||
0x97, 0x44, 0x60, 0x1b, 0x5e, 0x8f, 0xab, 0x2b, 0x93, 0x71, 0x15, 0x4c, 0x6d, 0x28, 0x51, 0x85,
|
||||
0xdf, 0x80, 0x3c, 0x0f, 0x89, 0x63, 0xae, 0x2a, 0xf5, 0x67, 0xd6, 0x32, 0xaf, 0x6e, 0xc9, 0x1c,
|
||||
0x5b, 0x21, 0x71, 0xec, 0x4d, 0x1d, 0x23, 0x2f, 0x4f, 0x48, 0x29, 0xc2, 0x37, 0x60, 0x8d, 0x0b,
|
||||
0x2c, 0x06, 0xdc, 0xcc, 0x29, 0xed, 0xd3, 0x0f, 0xd0, 0x56, 0x7c, 0xfb, 0x9e, 0x56, 0x5f, 0x8b,
|
||||
0xce, 0x48, 0xeb, 0xee, 0xff, 0x9e, 0x03, 0x65, 0x09, 0x3b, 0xa3, 0x41, 0xc7, 0x13, 0x1e, 0x0d,
|
||||
0xe0, 0x53, 0x90, 0x17, 0xa3, 0x90, 0xa8, 0xb7, 0x2a, 0xd9, 0x8f, 0xe3, 0xac, 0xae, 0x46, 0x21,
|
||||
0xb9, 0x1d, 0x57, 0xb7, 0x33, 0x60, 0x69, 0x44, 0x0a, 0x0e, 0x3f, 0x4d, 0x52, 0x5d, 0xcd, 0x10,
|
||||
0x75, 0xc0, 0xdb, 0x71, 0xf5, 0x7e, 0x42, 0xcb, 0xe6, 0x00, 0x5d, 0x50, 0xee, 0x63, 0x2e, 0x9a,
|
||||
0x8c, 0xb6, 0xc9, 0x95, 0xe7, 0x13, 0x7d, 0xd9, 0x8f, 0xde, 0xaf, 0x4c, 0x92, 0x61, 0xef, 0xe8,
|
||||
0x68, 0xe5, 0x8b, 0xb4, 0x10, 0xca, 0xea, 0xc2, 0x21, 0x80, 0xd2, 0x70, 0xc5, 0x70, 0xc0, 0xa3,
|
||||
0xfc, 0x65, 0xb4, 0xfc, 0xd2, 0xd1, 0x76, 0x75, 0x34, 0x78, 0x31, 0xa3, 0x86, 0xe6, 0x44, 0x80,
|
||||
0x07, 0x60, 0x8d, 0x11, 0xcc, 0x69, 0x60, 0x16, 0xd4, 0xdb, 0x24, 0xc5, 0x40, 0xca, 0x8a, 0xb4,
|
||||
0x17, 0xfe, 0x1f, 0xac, 0xfb, 0x84, 0x73, 0xec, 0x12, 0x73, 0x4d, 0x01, 0xef, 0x6b, 0xe0, 0xfa,
|
||||
0xcb, 0xc8, 0x8c, 0x62, 0xff, 0xfe, 0x1f, 0x06, 0x28, 0xca, 0x52, 0x5c, 0x78, 0x5c, 0xc0, 0xef,
|
||||
0x66, 0x5a, 0xdc, 0x7a, 0xbf, 0xdb, 0x48, 0xb6, 0x6a, 0xf0, 0x2d, 0x1d, 0xa8, 0x18, 0x5b, 0x52,
|
||||
0xed, 0xfd, 0x1a, 0x14, 0x3c, 0x41, 0x7c, 0x59, 0xd8, 0xdc, 0xe1, 0xc6, 0xc9, 0xc9, 0xf2, 0x3d,
|
||||
0x68, 0x97, 0xb5, 0x7c, 0xa1, 0x21, 0x85, 0x50, 0xa4, 0xb7, 0xff, 0xe7, 0x7a, 0x74, 0x07, 0xd9,
|
||||
0xf0, 0xf0, 0x02, 0x94, 0x99, 0xa4, 0x32, 0xd1, 0xa4, 0x7d, 0xcf, 0x19, 0xa9, 0x26, 0x28, 0xd9,
|
||||
0x07, 0x71, 0x61, 0x51, 0xda, 0x79, 0x7b, 0xd7, 0x80, 0xb2, 0x64, 0xe8, 0x82, 0x47, 0x82, 0x30,
|
||||
0xdf, 0x0b, 0xb0, 0x2c, 0xc2, 0x57, 0x0c, 0x3b, 0xa4, 0x49, 0x98, 0x47, 0x3b, 0x2d, 0xe2, 0xd0,
|
||||
0xa0, 0xc3, 0x55, 0xd1, 0x73, 0xf6, 0xe3, 0xc9, 0xb8, 0xfa, 0xe8, 0x6a, 0x11, 0x10, 0x2d, 0xd6,
|
||||
0x81, 0xaf, 0xc0, 0x0e, 0x76, 0x84, 0x37, 0x24, 0xe7, 0x04, 0x77, 0xfa, 0x5e, 0x40, 0xe2, 0x00,
|
||||
0x05, 0x15, 0xe0, 0x7f, 0x93, 0x71, 0x75, 0xe7, 0xc5, 0x3c, 0x00, 0x9a, 0xcf, 0x83, 0x3f, 0x1b,
|
||||
0x60, 0x33, 0xa0, 0x1d, 0xd2, 0x22, 0x7d, 0xe2, 0x08, 0xca, 0xcc, 0x75, 0xf5, 0xea, 0xf5, 0x0f,
|
||||
0x9b, 0x2a, 0xd6, 0x65, 0x4a, 0xea, 0xcb, 0x40, 0xb0, 0x91, 0xfd, 0x50, 0xbf, 0xe8, 0x66, 0xda,
|
||||
0x85, 0x32, 0x31, 0xe1, 0xd7, 0x00, 0x72, 0xc2, 0x86, 0x9e, 0x43, 0x5e, 0x38, 0x0e, 0x1d, 0x04,
|
||||
0xe2, 0x12, 0xfb, 0xc4, 0x2c, 0xaa, 0x8a, 0x24, 0xcd, 0xdf, 0x9a, 0x41, 0xa0, 0x39, 0x2c, 0x58,
|
||||
0x07, 0xf7, 0xb2, 0x56, 0xb3, 0xa4, 0x74, 0xf6, 0xb4, 0x8e, 0x79, 0x4e, 0x42, 0x46, 0x1c, 0x39,
|
||||
0xba, 0xb3, 0x8a, 0xe8, 0x0e, 0x0f, 0x1e, 0x81, 0xa2, 0xcc, 0x52, 0xe5, 0x02, 0x94, 0x46, 0xd2,
|
||||
0xb6, 0x97, 0xda, 0x8e, 0x12, 0x04, 0x7c, 0x0a, 0x36, 0xba, 0x94, 0x8b, 0x4b, 0x22, 0x7e, 0xa4,
|
||||
0xac, 0x67, 0x6e, 0xec, 0x19, 0x87, 0x45, 0xfb, 0x81, 0x26, 0x6c, 0xd4, 0xa7, 0x2e, 0x94, 0xc6,
|
||||
0xc9, 0xdf, 0xa0, 0x3c, 0x36, 0x1b, 0xe7, 0xe6, 0xa6, 0xa2, 0x24, 0xbf, 0xc1, 0x7a, 0x64, 0x46,
|
||||
0xb1, 0x3f, 0x86, 0x36, 0x9a, 0x67, 0x66, 0x79, 0x16, 0xda, 0x68, 0x9e, 0xa1, 0xd8, 0x2f, 0x53,
|
||||
0x97, 0x9f, 0x81, 0x4c, 0x7d, 0x2b, 0x9b, 0x7a, 0x5d, 0xdb, 0x51, 0x82, 0x80, 0x35, 0x50, 0xe2,
|
||||
0x83, 0x76, 0x87, 0xfa, 0xd8, 0x0b, 0xcc, 0x6d, 0x05, 0xdf, 0xd6, 0xf0, 0x52, 0x2b, 0x76, 0xa0,
|
||||
0x29, 0x06, 0x3e, 0x07, 0x65, 0xb9, 0x06, 0x3b, 0x83, 0x3e, 0x61, 0x2a, 0xc6, 0x03, 0x45, 0x4a,
|
||||
0xa6, 0x62, 0x2b, 0x76, 0xaa, 0x37, 0xca, 0x62, 0x77, 0xbf, 0x00, 0xdb, 0x33, 0x5d, 0x02, 0xb7,
|
||||
0x40, 0xae, 0x47, 0x46, 0xd1, 0x12, 0x40, 0xf2, 0x13, 0x3e, 0x04, 0x85, 0x21, 0xee, 0x0f, 0x48,
|
||||
0x34, 0xdf, 0x51, 0x74, 0xf8, 0x6c, 0xf5, 0xd4, 0xd8, 0xff, 0x2d, 0x07, 0xc0, 0x74, 0xd5, 0xc0,
|
||||
0x27, 0xa0, 0x10, 0x76, 0x31, 0x8f, 0x37, 0x48, 0xdc, 0x2f, 0x85, 0xa6, 0x34, 0xde, 0x8e, 0xab,
|
||||
0x25, 0x89, 0x55, 0x07, 0x14, 0x01, 0x21, 0x05, 0xc0, 0x89, 0x77, 0x43, 0x3c, 0x66, 0x9e, 0x2f,
|
||||
0xdf, 0xf0, 0xc9, 0x7e, 0x99, 0xee, 0xeb, 0xc4, 0xc4, 0x51, 0x2a, 0x44, 0x7a, 0xd0, 0xe6, 0x16,
|
||||
0x0f, 0xda, 0xd4, 0xec, 0xce, 0x2f, 0x9c, 0xdd, 0x07, 0x60, 0x2d, 0x2a, 0xf6, 0xdd, 0x19, 0x1f,
|
||||
0xf5, 0x02, 0xd2, 0x5e, 0x89, 0x73, 0x30, 0x0b, 0x1b, 0x4d, 0x3d, 0xe2, 0x13, 0xdc, 0x99, 0xb2,
|
||||
0x22, 0xed, 0x85, 0xaf, 0x41, 0x49, 0x0d, 0x34, 0xb5, 0xa2, 0xd6, 0x97, 0x5e, 0x51, 0x65, 0xd5,
|
||||
0x2b, 0xb1, 0x00, 0x9a, 0x6a, 0xd9, 0xe8, 0xfa, 0xa6, 0xb2, 0xf2, 0xf6, 0xa6, 0xb2, 0xf2, 0xee,
|
||||
0xa6, 0xb2, 0xf2, 0xd3, 0xa4, 0x62, 0x5c, 0x4f, 0x2a, 0xc6, 0xdb, 0x49, 0xc5, 0x78, 0x37, 0xa9,
|
||||
0x18, 0x7f, 0x4d, 0x2a, 0xc6, 0x2f, 0x7f, 0x57, 0x56, 0xbe, 0x3d, 0x5a, 0xe6, 0x8f, 0xe7, 0x3f,
|
||||
0x01, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xd1, 0x13, 0x90, 0xa7, 0x0a, 0x00, 0x00,
|
||||
// 1103 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0x4f, 0x4f, 0x1b, 0x47,
|
||||
0x14, 0x67, 0xb1, 0x0d, 0xf6, 0x80, 0x9b, 0x30, 0x09, 0xea, 0x16, 0x29, 0x36, 0xf1, 0x01, 0xd1,
|
||||
0x8a, 0xae, 0x03, 0x6a, 0x22, 0xda, 0x54, 0xaa, 0x58, 0xa8, 0x0a, 0x15, 0x21, 0xd6, 0x18, 0x29,
|
||||
0x55, 0x1b, 0x55, 0x19, 0xef, 0x0e, 0xcb, 0x16, 0xef, 0xce, 0x6a, 0x66, 0xec, 0xca, 0xb7, 0xaa,
|
||||
0xa7, 0x1e, 0xfb, 0x21, 0xfa, 0x15, 0xfa, 0x01, 0x7a, 0xe3, 0x98, 0x63, 0x7a, 0xb1, 0x8a, 0xfb,
|
||||
0x2d, 0x38, 0x55, 0x33, 0x3b, 0xbb, 0x5e, 0x63, 0xe3, 0xc6, 0xdc, 0x3c, 0xef, 0xfd, 0x7e, 0xbf,
|
||||
0xf7, 0x3c, 0xf3, 0xfe, 0x2c, 0xf8, 0xf2, 0x62, 0x97, 0x5b, 0x3e, 0xad, 0xe3, 0xc8, 0x0f, 0xb0,
|
||||
0x73, 0xee, 0x87, 0x84, 0xf5, 0xea, 0xd1, 0x85, 0x27, 0x0d, 0xbc, 0x2e, 0x08, 0x17, 0x38, 0xf2,
|
||||
0x3d, 0x46, 0x3b, 0x51, 0xbd, 0xbb, 0x5d, 0xf7, 0x48, 0x48, 0x18, 0x16, 0xc4, 0xb5, 0x22, 0x46,
|
||||
0x05, 0x85, 0x5b, 0x31, 0xdb, 0xca, 0xb2, 0xad, 0xe8, 0xc2, 0x93, 0x06, 0x6e, 0x65, 0xd9, 0x56,
|
||||
0x77, 0x7b, 0xed, 0x53, 0xcf, 0x17, 0xe7, 0x9d, 0x96, 0xe5, 0xd0, 0xa0, 0xee, 0x51, 0x8f, 0xd6,
|
||||
0x95, 0x48, 0xab, 0x73, 0xa6, 0x4e, 0xea, 0xa0, 0x7e, 0xc5, 0xe2, 0x6b, 0x9f, 0x4d, 0x4d, 0x2d,
|
||||
0x20, 0x02, 0x4f, 0x48, 0x69, 0xad, 0x7e, 0x1b, 0x8b, 0x75, 0x42, 0xe1, 0x07, 0x64, 0x8c, 0xf0,
|
||||
0xec, 0xff, 0x08, 0xdc, 0x39, 0x27, 0x01, 0xbe, 0xc9, 0xab, 0xfd, 0x31, 0x0f, 0xf2, 0xfb, 0x98,
|
||||
0x45, 0xf0, 0x0d, 0x28, 0xca, 0x64, 0x5c, 0x2c, 0xb0, 0x69, 0xac, 0x1b, 0x9b, 0x4b, 0x3b, 0x4f,
|
||||
0xac, 0xa9, 0xf7, 0x22, 0xd1, 0x56, 0x77, 0xdb, 0x7a, 0xd9, 0xfa, 0x89, 0x38, 0xe2, 0x05, 0x11,
|
||||
0xd8, 0x86, 0x97, 0xfd, 0xea, 0xdc, 0xa0, 0x5f, 0x05, 0x43, 0x1b, 0x4a, 0x55, 0xe1, 0x77, 0x20,
|
||||
0xcf, 0x23, 0xe2, 0x98, 0xf3, 0x4a, 0xfd, 0x99, 0x35, 0xcb, 0xad, 0x5b, 0x32, 0xc7, 0x66, 0x44,
|
||||
0x1c, 0x7b, 0x59, 0xc7, 0xc8, 0xcb, 0x13, 0x52, 0x8a, 0xf0, 0x0d, 0x58, 0xe0, 0x02, 0x8b, 0x0e,
|
||||
0x37, 0x73, 0x4a, 0x7b, 0xf7, 0x0e, 0xda, 0x8a, 0x6f, 0x7f, 0xa0, 0xd5, 0x17, 0xe2, 0x33, 0xd2,
|
||||
0xba, 0xb5, 0x3f, 0x73, 0xa0, 0x2c, 0x61, 0xfb, 0x34, 0x74, 0x7d, 0xe1, 0xd3, 0x10, 0x3e, 0x05,
|
||||
0x79, 0xd1, 0x8b, 0x88, 0xba, 0xab, 0x92, 0xfd, 0x38, 0xc9, 0xea, 0xb4, 0x17, 0x91, 0xeb, 0x7e,
|
||||
0x75, 0x65, 0x04, 0x2c, 0x8d, 0x48, 0xc1, 0xe1, 0xe7, 0x69, 0xaa, 0xf3, 0x23, 0x44, 0x1d, 0xf0,
|
||||
0xba, 0x5f, 0xbd, 0x97, 0xd2, 0x46, 0x73, 0x80, 0x1e, 0x28, 0xb7, 0x31, 0x17, 0x0d, 0x46, 0x5b,
|
||||
0xe4, 0xd4, 0x0f, 0x88, 0xfe, 0xb3, 0x9f, 0xbc, 0xdf, 0x33, 0x49, 0x86, 0xbd, 0xaa, 0xa3, 0x95,
|
||||
0x8f, 0xb3, 0x42, 0x68, 0x54, 0x17, 0x76, 0x01, 0x94, 0x86, 0x53, 0x86, 0x43, 0x1e, 0xe7, 0x2f,
|
||||
0xa3, 0xe5, 0x67, 0x8e, 0xb6, 0xa6, 0xa3, 0xc1, 0xe3, 0x31, 0x35, 0x34, 0x21, 0x02, 0xdc, 0x00,
|
||||
0x0b, 0x8c, 0x60, 0x4e, 0x43, 0xb3, 0xa0, 0xee, 0x26, 0x7d, 0x0c, 0xa4, 0xac, 0x48, 0x7b, 0xe1,
|
||||
0xc7, 0x60, 0x31, 0x20, 0x9c, 0x63, 0x8f, 0x98, 0x0b, 0x0a, 0x78, 0x4f, 0x03, 0x17, 0x5f, 0xc4,
|
||||
0x66, 0x94, 0xf8, 0x6b, 0x3f, 0x82, 0xa2, 0x7c, 0x89, 0xa3, 0xf0, 0x8c, 0xc2, 0x0f, 0x81, 0x11,
|
||||
0x97, 0x76, 0xce, 0x2e, 0x69, 0x82, 0xb1, 0x87, 0x0c, 0x2c, 0x1d, 0x2d, 0xfd, 0x1c, 0xa9, 0xc3,
|
||||
0x46, 0x46, 0x0b, 0xae, 0x83, 0xbc, 0xea, 0x87, 0x9c, 0xf2, 0xa5, 0x95, 0x77, 0x80, 0x05, 0x46,
|
||||
0xca, 0x53, 0xfb, 0xcb, 0x88, 0x03, 0x1c, 0xfb, 0x5c, 0xc0, 0xd7, 0x63, 0x2d, 0x64, 0xbd, 0xdf,
|
||||
0x6d, 0x49, 0xb6, 0x6a, 0xa0, 0xfb, 0x3a, 0x44, 0x31, 0xb1, 0x64, 0xda, 0xe7, 0x15, 0x28, 0xf8,
|
||||
0x82, 0x04, 0xb2, 0x70, 0x72, 0x9b, 0x4b, 0x3b, 0x3b, 0xb3, 0xd7, 0xb8, 0x5d, 0xd6, 0xf2, 0x85,
|
||||
0x23, 0x29, 0x84, 0x62, 0xbd, 0xda, 0xdf, 0x8b, 0xf1, 0x7f, 0x90, 0x0d, 0x05, 0x8f, 0x41, 0x99,
|
||||
0x49, 0x2a, 0x13, 0x0d, 0xda, 0xf6, 0x9d, 0x9e, 0xfe, 0xef, 0x1b, 0x49, 0xe1, 0xa0, 0xac, 0xf3,
|
||||
0xfa, 0xa6, 0x01, 0x8d, 0x92, 0xa1, 0x07, 0x1e, 0x09, 0xc2, 0x02, 0x3f, 0xc4, 0xf2, 0x91, 0xbf,
|
||||
0x61, 0xd8, 0x21, 0x0d, 0xc2, 0x7c, 0xea, 0x36, 0x89, 0x43, 0x43, 0x97, 0xab, 0xa2, 0xca, 0xd9,
|
||||
0x8f, 0x07, 0xfd, 0xea, 0xa3, 0xd3, 0x69, 0x40, 0x34, 0x5d, 0x07, 0xbe, 0x04, 0xab, 0xd8, 0x11,
|
||||
0x7e, 0x97, 0x1c, 0x10, 0xec, 0xb6, 0xfd, 0x90, 0x24, 0x01, 0x0a, 0x2a, 0xc0, 0x47, 0x83, 0x7e,
|
||||
0x75, 0x75, 0x6f, 0x12, 0x00, 0x4d, 0xe6, 0xc1, 0x5f, 0x0d, 0xb0, 0x1c, 0x52, 0x97, 0x34, 0x49,
|
||||
0x9b, 0x38, 0x82, 0x32, 0x73, 0x51, 0xdd, 0xfa, 0xe1, 0xdd, 0xa6, 0x96, 0x75, 0x92, 0x91, 0xfa,
|
||||
0x3a, 0x14, 0xac, 0x67, 0x3f, 0xd4, 0x37, 0xba, 0x9c, 0x75, 0xa1, 0x91, 0x98, 0xf0, 0x5b, 0x00,
|
||||
0x39, 0x61, 0x5d, 0xdf, 0x21, 0x7b, 0x8e, 0x43, 0x3b, 0xa1, 0x38, 0xc1, 0x01, 0x31, 0x8b, 0xea,
|
||||
0x45, 0xd2, 0xe6, 0x6a, 0x8e, 0x21, 0xd0, 0x04, 0x16, 0x7c, 0x0d, 0x4c, 0x97, 0x44, 0x8c, 0x38,
|
||||
0x72, 0xf8, 0x8f, 0x72, 0xcc, 0x92, 0x52, 0x5c, 0xd7, 0x8a, 0xe6, 0xc1, 0x2d, 0x38, 0x74, 0xab,
|
||||
0x02, 0xdc, 0x02, 0x45, 0x99, 0xb9, 0xca, 0x0f, 0x28, 0xb5, 0xb4, 0x94, 0x4f, 0xb4, 0x1d, 0xa5,
|
||||
0x08, 0xf8, 0x14, 0x2c, 0x9d, 0x53, 0x2e, 0x4e, 0x88, 0xf8, 0x99, 0xb2, 0x0b, 0x73, 0x69, 0xdd,
|
||||
0xd8, 0x2c, 0xda, 0x0f, 0x34, 0x61, 0xe9, 0x70, 0xe8, 0x42, 0x59, 0x9c, 0xec, 0x7b, 0x79, 0x6c,
|
||||
0x1c, 0x1d, 0x98, 0xcb, 0x8a, 0x92, 0xf6, 0xfd, 0x61, 0x6c, 0x46, 0x89, 0x3f, 0x81, 0x1e, 0x35,
|
||||
0xf6, 0xcd, 0xf2, 0x38, 0xf4, 0xa8, 0xb1, 0x8f, 0x12, 0xbf, 0x4c, 0x5d, 0xfe, 0x0c, 0x65, 0xea,
|
||||
0xf7, 0x47, 0x53, 0x3f, 0xd4, 0x76, 0x94, 0x22, 0x60, 0x1d, 0x94, 0x78, 0xa7, 0xe5, 0xd2, 0x00,
|
||||
0xfb, 0xa1, 0xb9, 0xa2, 0xe0, 0x2b, 0x1a, 0x5e, 0x6a, 0x26, 0x0e, 0x34, 0xc4, 0xc0, 0xe7, 0xa0,
|
||||
0x2c, 0x57, 0xaf, 0xdb, 0x69, 0x13, 0xa6, 0xae, 0xe7, 0x81, 0x22, 0xa5, 0x93, 0xb8, 0x99, 0x75,
|
||||
0xa2, 0x51, 0xec, 0xda, 0x57, 0x60, 0x65, 0xac, 0x72, 0xe0, 0x7d, 0x90, 0xbb, 0x20, 0xbd, 0x78,
|
||||
0xf1, 0x20, 0xf9, 0x13, 0x3e, 0x04, 0x85, 0x2e, 0x6e, 0x77, 0x48, 0x3c, 0xc4, 0x50, 0x7c, 0xf8,
|
||||
0x62, 0x7e, 0xd7, 0xa8, 0xfd, 0x96, 0x07, 0x60, 0xb8, 0xde, 0xe0, 0x13, 0x50, 0x88, 0xce, 0x31,
|
||||
0x4f, 0xb6, 0x56, 0x52, 0x43, 0x85, 0x86, 0x34, 0x5e, 0xf7, 0xab, 0x25, 0x89, 0x55, 0x07, 0x14,
|
||||
0x03, 0x21, 0x05, 0xc0, 0x49, 0xf6, 0x51, 0x32, 0x7a, 0x9e, 0xcf, 0xde, 0x04, 0xe9, 0x4e, 0x1b,
|
||||
0x7e, 0x23, 0xa4, 0x26, 0x8e, 0x32, 0x21, 0xb2, 0xc3, 0x3d, 0x37, 0x7d, 0xb8, 0x67, 0xf6, 0x45,
|
||||
0x7e, 0xea, 0xbe, 0xd8, 0x00, 0x0b, 0xf1, 0x63, 0xdf, 0xdc, 0x2b, 0x71, 0x2d, 0x20, 0xed, 0x95,
|
||||
0x38, 0x47, 0x2e, 0x8b, 0x86, 0x5e, 0x2b, 0x29, 0x4e, 0xad, 0x90, 0x06, 0xd2, 0x5e, 0xf8, 0x0a,
|
||||
0x94, 0xd4, 0x90, 0x53, 0x6b, 0x71, 0x71, 0xe6, 0xb5, 0x58, 0x56, 0xb5, 0x92, 0x08, 0xa0, 0xa1,
|
||||
0x16, 0xfc, 0x01, 0x14, 0xfc, 0xf0, 0x8c, 0x72, 0xb3, 0xa8, 0xee, 0xf9, 0x0e, 0x9f, 0x48, 0x72,
|
||||
0xd1, 0x65, 0xc6, 0xbc, 0x14, 0x43, 0xb1, 0xa6, 0x8d, 0x2e, 0xaf, 0x2a, 0x73, 0x6f, 0xaf, 0x2a,
|
||||
0x73, 0xef, 0xae, 0x2a, 0x73, 0xbf, 0x0c, 0x2a, 0xc6, 0xe5, 0xa0, 0x62, 0xbc, 0x1d, 0x54, 0x8c,
|
||||
0x77, 0x83, 0x8a, 0xf1, 0xcf, 0xa0, 0x62, 0xfc, 0xfe, 0x6f, 0x65, 0xee, 0xfb, 0xad, 0x59, 0xbe,
|
||||
0xa4, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xce, 0x5e, 0x7f, 0xf0, 0x78, 0x0b, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *Carp) Marshal() (dAtA []byte, err error) {
|
||||
@@ -383,6 +416,42 @@ func (m *CarpCondition) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *CarpInfo) 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 *CarpInfo) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *CarpInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
i -= len(m.Data)
|
||||
copy(dAtA[i:], m.Data)
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Data)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
i -= len(m.B)
|
||||
copy(dAtA[i:], m.B)
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(m.B)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(m.A))
|
||||
i--
|
||||
dAtA[i] = 0x8
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *CarpList) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
@@ -572,6 +641,20 @@ func (m *CarpStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Infos) > 0 {
|
||||
for iNdEx := len(m.Infos) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.Infos[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x42
|
||||
}
|
||||
}
|
||||
if m.StartTime != nil {
|
||||
{
|
||||
size, err := m.StartTime.MarshalToSizedBuffer(dAtA[:i])
|
||||
@@ -673,6 +756,20 @@ func (m *CarpCondition) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *CarpInfo) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
n += 1 + sovGenerated(uint64(m.A))
|
||||
l = len(m.B)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
l = len(m.Data)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *CarpList) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
@@ -756,6 +853,12 @@ func (m *CarpStatus) Size() (n int) {
|
||||
l = m.StartTime.Size()
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if len(m.Infos) > 0 {
|
||||
for _, e := range m.Infos {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@@ -792,6 +895,18 @@ func (this *CarpCondition) String() string {
|
||||
}, "")
|
||||
return s
|
||||
}
|
||||
func (this *CarpInfo) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
}
|
||||
s := strings.Join([]string{`&CarpInfo{`,
|
||||
`A:` + fmt.Sprintf("%v", this.A) + `,`,
|
||||
`B:` + fmt.Sprintf("%v", this.B) + `,`,
|
||||
`Data:` + fmt.Sprintf("%v", this.Data) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
}
|
||||
func (this *CarpList) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
@@ -849,6 +964,11 @@ func (this *CarpStatus) String() string {
|
||||
repeatedStringForConditions += strings.Replace(strings.Replace(f.String(), "CarpCondition", "CarpCondition", 1), `&`, ``, 1) + ","
|
||||
}
|
||||
repeatedStringForConditions += "}"
|
||||
repeatedStringForInfos := "[]CarpInfo{"
|
||||
for _, f := range this.Infos {
|
||||
repeatedStringForInfos += strings.Replace(strings.Replace(f.String(), "CarpInfo", "CarpInfo", 1), `&`, ``, 1) + ","
|
||||
}
|
||||
repeatedStringForInfos += "}"
|
||||
s := strings.Join([]string{`&CarpStatus{`,
|
||||
`Phase:` + fmt.Sprintf("%v", this.Phase) + `,`,
|
||||
`Conditions:` + repeatedStringForConditions + `,`,
|
||||
@@ -857,6 +977,7 @@ func (this *CarpStatus) String() string {
|
||||
`HostIP:` + fmt.Sprintf("%v", this.HostIP) + `,`,
|
||||
`CarpIP:` + fmt.Sprintf("%v", this.CarpIP) + `,`,
|
||||
`StartTime:` + strings.Replace(fmt.Sprintf("%v", this.StartTime), "Time", "v1.Time", 1) + `,`,
|
||||
`Infos:` + repeatedStringForInfos + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
@@ -1262,6 +1383,139 @@ func (m *CarpCondition) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *CarpInfo) 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 ErrIntOverflowGenerated
|
||||
}
|
||||
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: CarpInfo: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: CarpInfo: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field A", wireType)
|
||||
}
|
||||
m.A = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.A |= int64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field B", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.B = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Data = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *CarpList) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
@@ -2139,6 +2393,40 @@ func (m *CarpStatus) Unmarshal(dAtA []byte) error {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 8:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Infos", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Infos = append(m.Infos, CarpInfo{})
|
||||
if err := m.Infos[len(m.Infos)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
|
||||
@@ -77,6 +77,19 @@ message CarpCondition {
|
||||
optional string message = 6;
|
||||
}
|
||||
|
||||
message CarpInfo {
|
||||
// A is the first map key.
|
||||
// +required
|
||||
optional int64 a = 1;
|
||||
|
||||
// B is the second map key.
|
||||
// +required
|
||||
optional string b = 2;
|
||||
|
||||
// Some data for each pair of A and B.
|
||||
optional string data = 3;
|
||||
}
|
||||
|
||||
// CarpList is a list of Carps.
|
||||
message CarpList {
|
||||
// Standard list metadata.
|
||||
@@ -129,7 +142,7 @@ message CarpSpec {
|
||||
// Deprecated: Use serviceAccountName instead.
|
||||
// +k8s:conversion-gen=false
|
||||
// +optional
|
||||
optional string serviceAccount = 9;
|
||||
optional string deprecatedServiceAccount = 9;
|
||||
|
||||
// NodeName is a request to schedule this carp onto a specific node. If it is non-empty,
|
||||
// the scheduler simply schedules this carp onto that node, assuming that it fits resource
|
||||
@@ -168,7 +181,7 @@ message CarpSpec {
|
||||
// If specified, the carp will be dispatched by specified scheduler.
|
||||
// If not specified, the carp will be dispatched by default scheduler.
|
||||
// +optional
|
||||
optional string schedulername = 19;
|
||||
optional string schedulerName = 19;
|
||||
}
|
||||
|
||||
// CarpStatus represents information about the status of a carp. Status may trail the actual
|
||||
@@ -181,6 +194,10 @@ message CarpStatus {
|
||||
|
||||
// Current service state of carp.
|
||||
// More info: http://kubernetes.io/docs/user-guide/carp-states#carp-conditions
|
||||
// +patchStrategy=merge
|
||||
// +patchMergeKey=type
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
// +optional
|
||||
repeated CarpCondition conditions = 2;
|
||||
|
||||
@@ -206,5 +223,12 @@ message CarpStatus {
|
||||
// This is before the Kubelet pulled the container image(s) for the carp.
|
||||
// +optional
|
||||
optional .k8s.io.apimachinery.pkg.apis.meta.v1.Time startTime = 7;
|
||||
|
||||
// Carp infos are provided by different clients, hence the map type.
|
||||
//
|
||||
// +listType=map
|
||||
// +listMapKey=a
|
||||
// +listMapKey=b
|
||||
repeated CarpInfo infos = 8;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ func init() {
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Carp{},
|
||||
&CarpList{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
|
||||
@@ -28,6 +28,7 @@ type (
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +k8s:prerelease-lifecycle-gen:introduced=1.1
|
||||
|
||||
// Carp is a collection of containers, used as either input (create, update) or as output (list, get).
|
||||
type Carp struct {
|
||||
@@ -60,8 +61,12 @@ type CarpStatus struct {
|
||||
Phase CarpPhase `json:"phase,omitempty" protobuf:"bytes,1,opt,name=phase,casttype=CarpPhase"`
|
||||
// Current service state of carp.
|
||||
// More info: http://kubernetes.io/docs/user-guide/carp-states#carp-conditions
|
||||
// +patchStrategy=merge
|
||||
// +patchMergeKey=type
|
||||
// +listType=map
|
||||
// +listMapKey=type
|
||||
// +optional
|
||||
Conditions []CarpCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,2,rep,name=conditions"`
|
||||
Conditions []CarpCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,2,opt,name=conditions"`
|
||||
// A human readable message indicating details about why the carp is in this condition.
|
||||
// +optional
|
||||
Message string `json:"message,omitempty" protobuf:"bytes,3,opt,name=message"`
|
||||
@@ -82,6 +87,13 @@ type CarpStatus struct {
|
||||
// This is before the Kubelet pulled the container image(s) for the carp.
|
||||
// +optional
|
||||
StartTime *metav1.Time `json:"startTime,omitempty" protobuf:"bytes,7,opt,name=startTime"`
|
||||
|
||||
// Carp infos are provided by different clients, hence the map type.
|
||||
//
|
||||
// +listType=map
|
||||
// +listMapKey=a
|
||||
// +listMapKey=b
|
||||
Infos []CarpInfo `json:"infos,omitempty" protobuf:"bytes,8,rep,name=infos"`
|
||||
}
|
||||
|
||||
type CarpCondition struct {
|
||||
@@ -107,6 +119,18 @@ type CarpCondition struct {
|
||||
Message string `json:"message,omitempty" protobuf:"bytes,6,opt,name=message"`
|
||||
}
|
||||
|
||||
type CarpInfo struct {
|
||||
// A is the first map key.
|
||||
// +required
|
||||
A int64 `json:"a" protobuf:"bytes,1,name=a"`
|
||||
// B is the second map key.
|
||||
// +required
|
||||
B string `json:"b" protobuf:"bytes,2,name=b"`
|
||||
|
||||
// Some data for each pair of A and B.
|
||||
Data string `json:"data" protobuf:"bytes,3,name=data"`
|
||||
}
|
||||
|
||||
// CarpSpec is a description of a carp
|
||||
type CarpSpec struct {
|
||||
// Restart policy for all containers within the carp.
|
||||
@@ -143,7 +167,7 @@ type CarpSpec struct {
|
||||
// Deprecated: Use serviceAccountName instead.
|
||||
// +k8s:conversion-gen=false
|
||||
// +optional
|
||||
DeprecatedServiceAccount string `json:"serviceAccount,omitempty" protobuf:"bytes,9,opt,name=serviceAccount"`
|
||||
DeprecatedServiceAccount string `json:"deprecatedServiceAccount,omitempty" protobuf:"bytes,9,opt,name=deprecatedServiceAccount"`
|
||||
|
||||
// NodeName is a request to schedule this carp onto a specific node. If it is non-empty,
|
||||
// the scheduler simply schedules this carp onto that node, assuming that it fits resource
|
||||
@@ -176,10 +200,11 @@ type CarpSpec struct {
|
||||
// If specified, the carp will be dispatched by specified scheduler.
|
||||
// If not specified, the carp will be dispatched by default scheduler.
|
||||
// +optional
|
||||
SchedulerName string `json:"schedulername,omitempty" protobuf:"bytes,19,opt,name=schedulername"`
|
||||
SchedulerName string `json:"schedulerName,omitempty" protobuf:"bytes,19,opt,name=schedulerName"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +k8s:prerelease-lifecycle-gen:introduced=1.1
|
||||
|
||||
// CarpList is a list of Carps.
|
||||
type CarpList struct {
|
||||
|
||||
@@ -57,6 +57,16 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*CarpInfo)(nil), (*testapigroup.CarpInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_CarpInfo_To_testapigroup_CarpInfo(a.(*CarpInfo), b.(*testapigroup.CarpInfo), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*testapigroup.CarpInfo)(nil), (*CarpInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_testapigroup_CarpInfo_To_v1_CarpInfo(a.(*testapigroup.CarpInfo), b.(*CarpInfo), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*CarpList)(nil), (*testapigroup.CarpList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_CarpList_To_testapigroup_CarpList(a.(*CarpList), b.(*testapigroup.CarpList), scope)
|
||||
}); err != nil {
|
||||
@@ -152,6 +162,30 @@ func Convert_testapigroup_CarpCondition_To_v1_CarpCondition(in *testapigroup.Car
|
||||
return autoConvert_testapigroup_CarpCondition_To_v1_CarpCondition(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_CarpInfo_To_testapigroup_CarpInfo(in *CarpInfo, out *testapigroup.CarpInfo, s conversion.Scope) error {
|
||||
out.A = in.A
|
||||
out.B = in.B
|
||||
out.Data = in.Data
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_CarpInfo_To_testapigroup_CarpInfo is an autogenerated conversion function.
|
||||
func Convert_v1_CarpInfo_To_testapigroup_CarpInfo(in *CarpInfo, out *testapigroup.CarpInfo, s conversion.Scope) error {
|
||||
return autoConvert_v1_CarpInfo_To_testapigroup_CarpInfo(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_testapigroup_CarpInfo_To_v1_CarpInfo(in *testapigroup.CarpInfo, out *CarpInfo, s conversion.Scope) error {
|
||||
out.A = in.A
|
||||
out.B = in.B
|
||||
out.Data = in.Data
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_testapigroup_CarpInfo_To_v1_CarpInfo is an autogenerated conversion function.
|
||||
func Convert_testapigroup_CarpInfo_To_v1_CarpInfo(in *testapigroup.CarpInfo, out *CarpInfo, s conversion.Scope) error {
|
||||
return autoConvert_testapigroup_CarpInfo_To_v1_CarpInfo(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_CarpList_To_testapigroup_CarpList(in *CarpList, out *testapigroup.CarpList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
@@ -242,6 +276,7 @@ func autoConvert_v1_CarpStatus_To_testapigroup_CarpStatus(in *CarpStatus, out *t
|
||||
out.HostIP = in.HostIP
|
||||
out.CarpIP = in.CarpIP
|
||||
out.StartTime = (*metav1.Time)(unsafe.Pointer(in.StartTime))
|
||||
out.Infos = *(*[]testapigroup.CarpInfo)(unsafe.Pointer(&in.Infos))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -258,6 +293,7 @@ func autoConvert_testapigroup_CarpStatus_To_v1_CarpStatus(in *testapigroup.CarpS
|
||||
out.HostIP = in.HostIP
|
||||
out.CarpIP = in.CarpIP
|
||||
out.StartTime = (*metav1.Time)(unsafe.Pointer(in.StartTime))
|
||||
out.Infos = *(*[]CarpInfo)(unsafe.Pointer(&in.Infos))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,22 @@ func (in *CarpCondition) DeepCopy() *CarpCondition {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CarpInfo) DeepCopyInto(out *CarpInfo) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CarpInfo.
|
||||
func (in *CarpInfo) DeepCopy() *CarpInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CarpInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CarpList) DeepCopyInto(out *CarpList) {
|
||||
*out = *in
|
||||
@@ -151,6 +167,11 @@ func (in *CarpStatus) DeepCopyInto(out *CarpStatus) {
|
||||
in, out := &in.StartTime, &out.StartTime
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.Infos != nil {
|
||||
in, out := &in.Infos, &out.Infos
|
||||
*out = make([]CarpInfo, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
34
staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.prerelease-lifecycle.go
generated
Normal file
34
staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1/zz_generated.prerelease-lifecycle.go
generated
Normal file
@@ -0,0 +1,34 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by prerelease-lifecycle-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
// APILifecycleIntroduced is an autogenerated function, returning the release in which the API struct was introduced as int versions of major and minor for comparison.
|
||||
// It is controlled by "k8s:prerelease-lifecycle-gen:introduced" tags in types.go.
|
||||
func (in *Carp) APILifecycleIntroduced() (major, minor int) {
|
||||
return 1, 1
|
||||
}
|
||||
|
||||
// APILifecycleIntroduced is an autogenerated function, returning the release in which the API struct was introduced as int versions of major and minor for comparison.
|
||||
// It is controlled by "k8s:prerelease-lifecycle-gen:introduced" tags in types.go.
|
||||
func (in *CarpList) APILifecycleIntroduced() (major, minor int) {
|
||||
return 1, 1
|
||||
}
|
||||
@@ -71,6 +71,22 @@ func (in *CarpCondition) DeepCopy() *CarpCondition {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CarpInfo) DeepCopyInto(out *CarpInfo) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CarpInfo.
|
||||
func (in *CarpInfo) DeepCopy() *CarpInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CarpInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CarpList) DeepCopyInto(out *CarpList) {
|
||||
*out = *in
|
||||
@@ -151,6 +167,11 @@ func (in *CarpStatus) DeepCopyInto(out *CarpStatus) {
|
||||
in, out := &in.StartTime, &out.StartTime
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.Infos != nil {
|
||||
in, out := &in.Infos, &out.Infos
|
||||
*out = make([]CarpInfo, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
364
test/integration/apimachinery/apply/apply_test.go
Normal file
364
test/integration/apimachinery/apply/apply_test.go
Normal file
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
Copyright 2025 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package dra
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/apis/testapigroup/install"
|
||||
testapigroupv1 "k8s.io/apimachinery/pkg/apis/testapigroup/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/controlplane"
|
||||
controlplaneapiserver "k8s.io/kubernetes/pkg/controlplane/apiserver"
|
||||
testapigrouprest "k8s.io/kubernetes/pkg/registry/testapigroup/rest"
|
||||
"k8s.io/kubernetes/test/integration/framework"
|
||||
"k8s.io/kubernetes/test/utils/ktesting"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
func init() {
|
||||
install.Install(legacyscheme.Scheme)
|
||||
}
|
||||
|
||||
func TestApply(t *testing.T) {
|
||||
tCtx := ktesting.Init(t)
|
||||
etcdOptions := framework.SharedEtcd()
|
||||
apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
|
||||
apiServerFlags := framework.DefaultTestServerFlags()
|
||||
runtimeConfigs := []string{"testapigroup.apimachinery.k8s.io/v1=true"}
|
||||
apiServerFlags = append(apiServerFlags, "--runtime-config="+strings.Join(runtimeConfigs, ","))
|
||||
|
||||
// Sanity check. Not protected against concurrent access, but that's
|
||||
// okay: integration tests are also run with race detection, so that
|
||||
// would catch it.
|
||||
if controlplane.AdditionalStorageProvidersForTests != nil {
|
||||
t.Fatal("cannot set AdditionalStorageProvidersForTests, already set")
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
controlplane.AdditionalStorageProvidersForTests = nil
|
||||
})
|
||||
controlplane.AdditionalStorageProvidersForTests = func(client *kubernetes.Clientset) []controlplaneapiserver.RESTStorageProvider {
|
||||
return []controlplaneapiserver.RESTStorageProvider{
|
||||
testapigrouprest.RESTStorageProvider{NamespaceClient: client.CoreV1().Namespaces()},
|
||||
}
|
||||
}
|
||||
|
||||
server := kubeapiservertesting.StartTestServerOrDie(t, apiServerOptions, apiServerFlags, etcdOptions)
|
||||
tCtx.CleanupCtx(func(tCtx ktesting.TContext) {
|
||||
tCtx.Log("Stopping the apiserver...")
|
||||
server.TearDownFn()
|
||||
})
|
||||
tCtx = ktesting.WithRESTConfig(tCtx, server.ClientConfig)
|
||||
|
||||
// More sub-tests could be added here. Currently there's only one.
|
||||
tCtx.Run("optional-list-map-key", testOptionalListMapKey)
|
||||
}
|
||||
|
||||
func testOptionalListMapKey(tCtx ktesting.TContext) {
|
||||
requireManagedFields := func(what string, obj *unstructured.Unstructured, expectedManagedFields any) {
|
||||
tCtx.Helper()
|
||||
actualManagedFields, _, _ := unstructured.NestedFieldCopy(obj.Object, "metadata", "managedFields")
|
||||
// Strip non-deterministic time.
|
||||
if actualManagedFields != nil {
|
||||
managers := actualManagedFields.([]any)
|
||||
for i := range managers {
|
||||
unstructured.RemoveNestedField(managers[i].(map[string]any), "time")
|
||||
}
|
||||
}
|
||||
require.Equal(tCtx, dump(expectedManagedFields), dump(actualManagedFields), fmt.Sprintf("%s:\n%s", what, dump(obj)))
|
||||
}
|
||||
|
||||
requireInfos := func(what string, obj *unstructured.Unstructured, expectedInfos []testapigroupv1.CarpInfo) {
|
||||
tCtx.Helper()
|
||||
actualInfos, _, _ := unstructured.NestedFieldCopy(obj.Object, "status", "infos")
|
||||
require.Equal(tCtx, dump(expectedInfos), dump(actualInfos), fmt.Sprintf("%s:\n%s", what, dump(obj)))
|
||||
}
|
||||
|
||||
carp := &unstructured.Unstructured{}
|
||||
name := "test-carp"
|
||||
namespace := createTestNamespace(tCtx, nil)
|
||||
carp.SetName(name)
|
||||
carp.SetNamespace(namespace)
|
||||
client := tCtx.Dynamic().Resource(testapigroupv1.SchemeGroupVersion.WithResource("carps")).Namespace(namespace)
|
||||
|
||||
// Create with no fields in spec -> managed fields still empty.
|
||||
carp, err := client.Create(tCtx, carp, metav1.CreateOptions{FieldManager: "creator"})
|
||||
tCtx.ExpectNoError(err, "create carp")
|
||||
requireManagedFields("after creation", carp, nil)
|
||||
|
||||
// Set infos with "A: 1, B: x" and "A: 2, B: x".
|
||||
carp, err = client.ApplyStatus(tCtx, name, parseObj(tCtx, `
|
||||
kind: Carp
|
||||
apiVersion: testapigroup.apimachinery.k8s.io/v1
|
||||
status:
|
||||
infos:
|
||||
- a: 1
|
||||
b: "x"
|
||||
data: status1_a1_bx
|
||||
- a: 2
|
||||
b: "x"
|
||||
data: status1_a2_bx
|
||||
`),
|
||||
metav1.ApplyOptions{FieldManager: "status1"})
|
||||
tCtx.ExpectNoError(err, "add status #1")
|
||||
requireManagedFields("add status #1", carp, parseAny(tCtx, `
|
||||
- apiVersion: testapigroup.apimachinery.k8s.io/v1
|
||||
fieldsType: FieldsV1
|
||||
fieldsV1:
|
||||
f:status:
|
||||
f:infos:
|
||||
k:{"a":1,"b":"x"}:
|
||||
.: {}
|
||||
f:a: {}
|
||||
f:b: {}
|
||||
f:data: {}
|
||||
k:{"a":2,"b":"x"}:
|
||||
.: {}
|
||||
f:a: {}
|
||||
f:b: {}
|
||||
f:data: {}
|
||||
manager: status1
|
||||
operation: Apply
|
||||
subresource: status
|
||||
`))
|
||||
requireInfos("add status #1", carp, []testapigroupv1.CarpInfo{{A: 1, B: "x", Data: "status1_a1_bx"}, {A: 2, B: "x", Data: "status1_a2_bx"}})
|
||||
|
||||
// Second status infos with "A: 1, B: y" and "A: 2, B: y".
|
||||
carp, err = client.ApplyStatus(tCtx, name, parseObj(tCtx, `
|
||||
kind: Carp
|
||||
apiVersion: testapigroup.apimachinery.k8s.io/v1
|
||||
status:
|
||||
infos:
|
||||
- a: 1
|
||||
b: "y"
|
||||
data: status2_a1_by
|
||||
- a: 2
|
||||
b: "y"
|
||||
data: status2_a2_by
|
||||
`),
|
||||
metav1.ApplyOptions{FieldManager: "status2"})
|
||||
tCtx.ExpectNoError(err, "add status #2")
|
||||
requireManagedFields("add status #2", carp, parseAny(tCtx, `
|
||||
- apiVersion: testapigroup.apimachinery.k8s.io/v1
|
||||
fieldsType: FieldsV1
|
||||
fieldsV1:
|
||||
f:status:
|
||||
f:infos:
|
||||
k:{"a":1,"b":"x"}:
|
||||
.: {}
|
||||
f:a: {}
|
||||
f:b: {}
|
||||
f:data: {}
|
||||
k:{"a":2,"b":"x"}:
|
||||
.: {}
|
||||
f:a: {}
|
||||
f:b: {}
|
||||
f:data: {}
|
||||
manager: status1
|
||||
operation: Apply
|
||||
subresource: status
|
||||
- apiVersion: testapigroup.apimachinery.k8s.io/v1
|
||||
fieldsType: FieldsV1
|
||||
fieldsV1:
|
||||
f:status:
|
||||
f:infos:
|
||||
k:{"a":1,"b":"y"}:
|
||||
.: {}
|
||||
f:a: {}
|
||||
f:b: {}
|
||||
f:data: {}
|
||||
k:{"a":2,"b":"y"}:
|
||||
.: {}
|
||||
f:a: {}
|
||||
f:b: {}
|
||||
f:data: {}
|
||||
manager: status2
|
||||
operation: Apply
|
||||
subresource: status
|
||||
`))
|
||||
requireInfos("add status #2", carp, []testapigroupv1.CarpInfo{{A: 1, B: "x", Data: "status1_a1_bx"}, {A: 2, B: "x", Data: "status1_a2_bx"}, {A: 1, B: "y", Data: "status2_a1_by"}, {A: 2, B: "y", Data: "status2_a2_by"}})
|
||||
|
||||
// Remove one entry of first field manager.
|
||||
carp, err = client.ApplyStatus(tCtx, name, parseObj(tCtx, `
|
||||
kind: Carp
|
||||
apiVersion: testapigroup.apimachinery.k8s.io/v1
|
||||
status:
|
||||
infos:
|
||||
- a: 1
|
||||
b: "x"
|
||||
data: status1_a1_bx
|
||||
`),
|
||||
metav1.ApplyOptions{FieldManager: "status1"})
|
||||
tCtx.ExpectNoError(err, "remove status #1")
|
||||
requireManagedFields("remove status #1", carp, parseAny(tCtx, `
|
||||
- apiVersion: testapigroup.apimachinery.k8s.io/v1
|
||||
fieldsType: FieldsV1
|
||||
fieldsV1:
|
||||
f:status:
|
||||
f:infos:
|
||||
k:{"a":1,"b":"x"}:
|
||||
.: {}
|
||||
f:a: {}
|
||||
f:b: {}
|
||||
f:data: {}
|
||||
manager: status1
|
||||
operation: Apply
|
||||
subresource: status
|
||||
- apiVersion: testapigroup.apimachinery.k8s.io/v1
|
||||
fieldsType: FieldsV1
|
||||
fieldsV1:
|
||||
f:status:
|
||||
f:infos:
|
||||
k:{"a":1,"b":"y"}:
|
||||
.: {}
|
||||
f:a: {}
|
||||
f:b: {}
|
||||
f:data: {}
|
||||
k:{"a":2,"b":"y"}:
|
||||
.: {}
|
||||
f:a: {}
|
||||
f:b: {}
|
||||
f:data: {}
|
||||
manager: status2
|
||||
operation: Apply
|
||||
subresource: status
|
||||
`))
|
||||
requireInfos("remove status #1", carp, []testapigroupv1.CarpInfo{{A: 1, B: "x", Data: "status1_a1_bx"}, {A: 1, B: "y", Data: "status2_a1_by"}, {A: 2, B: "y", Data: "status2_a2_by"}})
|
||||
|
||||
// Update one entry of second field manager.
|
||||
carp, err = client.ApplyStatus(tCtx, name, parseObj(tCtx, `
|
||||
kind: Carp
|
||||
apiVersion: testapigroup.apimachinery.k8s.io/v1
|
||||
status:
|
||||
infos:
|
||||
- a: 1
|
||||
b: "y"
|
||||
data: status2_a1_by
|
||||
- a: 2
|
||||
b: "y"
|
||||
data: status2_a2_by_updated
|
||||
`),
|
||||
metav1.ApplyOptions{FieldManager: "status2"})
|
||||
tCtx.ExpectNoError(err, "update status #2")
|
||||
requireManagedFields("update status #2", carp, parseAny(tCtx, `
|
||||
- apiVersion: testapigroup.apimachinery.k8s.io/v1
|
||||
fieldsType: FieldsV1
|
||||
fieldsV1:
|
||||
f:status:
|
||||
f:infos:
|
||||
k:{"a":1,"b":"x"}:
|
||||
.: {}
|
||||
f:a: {}
|
||||
f:b: {}
|
||||
f:data: {}
|
||||
manager: status1
|
||||
operation: Apply
|
||||
subresource: status
|
||||
- apiVersion: testapigroup.apimachinery.k8s.io/v1
|
||||
fieldsType: FieldsV1
|
||||
fieldsV1:
|
||||
f:status:
|
||||
f:infos:
|
||||
k:{"a":1,"b":"y"}:
|
||||
.: {}
|
||||
f:a: {}
|
||||
f:b: {}
|
||||
f:data: {}
|
||||
k:{"a":2,"b":"y"}:
|
||||
.: {}
|
||||
f:a: {}
|
||||
f:b: {}
|
||||
f:data: {}
|
||||
manager: status2
|
||||
operation: Apply
|
||||
subresource: status
|
||||
`))
|
||||
requireInfos("update status #2", carp, []testapigroupv1.CarpInfo{{A: 1, B: "x", Data: "status1_a1_bx"}, {A: 1, B: "y", Data: "status2_a1_by"}, {A: 2, B: "y", Data: "status2_a2_by_updated"}})
|
||||
}
|
||||
|
||||
func nestedFieldNoCopy(obj *unstructured.Unstructured, fields ...string) fieldLookupResult {
|
||||
field, found, err := unstructured.NestedFieldNoCopy(obj.Object, fields...)
|
||||
return fieldLookupResult{
|
||||
field: field,
|
||||
found: found,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
type fieldLookupResult struct {
|
||||
field any
|
||||
found bool
|
||||
err error
|
||||
}
|
||||
|
||||
// createTestNamespace creates a namespace with a name that is derived from the
|
||||
// current test name:
|
||||
// - Non-alpha-numeric characters replaced by hyphen.
|
||||
// - Truncated in the middle to make it short enough for GenerateName.
|
||||
// - Hyphen plus random suffix added by the apiserver.
|
||||
func createTestNamespace(tCtx ktesting.TContext, labels map[string]string) string {
|
||||
tCtx.Helper()
|
||||
name := regexp.MustCompile(`[^[:alnum:]_-]`).ReplaceAllString(tCtx.Name(), "-")
|
||||
name = strings.ToLower(name)
|
||||
if len(name) > 63 {
|
||||
name = name[:30] + "--" + name[len(name)-30:]
|
||||
}
|
||||
ns := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{GenerateName: name + "-"}}
|
||||
ns.Labels = labels
|
||||
ns, err := tCtx.Client().CoreV1().Namespaces().Create(tCtx, ns, metav1.CreateOptions{})
|
||||
tCtx.ExpectNoError(err, "create test namespace")
|
||||
tCtx.CleanupCtx(func(tCtx ktesting.TContext) {
|
||||
tCtx.ExpectNoError(tCtx.Client().CoreV1().Namespaces().Delete(tCtx, ns.Name, metav1.DeleteOptions{}), "delete test namespace")
|
||||
})
|
||||
return ns.Name
|
||||
}
|
||||
|
||||
func dump(in any) string {
|
||||
out, err := yaml.Marshal(in)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return string(out)
|
||||
}
|
||||
|
||||
func parseObj(tCtx ktesting.TContext, data string) *unstructured.Unstructured {
|
||||
tCtx.Helper()
|
||||
|
||||
var obj unstructured.Unstructured
|
||||
err := yaml.Unmarshal([]byte(data), &obj)
|
||||
tCtx.ExpectNoError(err, data)
|
||||
return &obj
|
||||
}
|
||||
|
||||
func parseAny(tCtx ktesting.TContext, data string) any {
|
||||
tCtx.Helper()
|
||||
|
||||
var result any
|
||||
err := yaml.Unmarshal([]byte(data), &result)
|
||||
tCtx.ExpectNoError(err, data)
|
||||
return result
|
||||
}
|
||||
27
test/integration/apimachinery/apply/main_test.go
Normal file
27
test/integration/apimachinery/apply/main_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright 2025 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package dra
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/test/integration/framework"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
framework.EtcdMain(m.Run)
|
||||
}
|
||||
Reference in New Issue
Block a user