@@ -51,6 +51,8 @@ func init() {
|
||||
&ResourceQuotaList{},
|
||||
&Namespace{},
|
||||
&NamespaceList{},
|
||||
&ServiceAccount{},
|
||||
&ServiceAccountList{},
|
||||
&Secret{},
|
||||
&SecretList{},
|
||||
&PersistentVolume{},
|
||||
@@ -98,6 +100,8 @@ func (*ResourceQuota) IsAnAPIObject() {}
|
||||
func (*ResourceQuotaList) IsAnAPIObject() {}
|
||||
func (*Namespace) IsAnAPIObject() {}
|
||||
func (*NamespaceList) IsAnAPIObject() {}
|
||||
func (*ServiceAccount) IsAnAPIObject() {}
|
||||
func (*ServiceAccountList) IsAnAPIObject() {}
|
||||
func (*Secret) IsAnAPIObject() {}
|
||||
func (*SecretList) IsAnAPIObject() {}
|
||||
func (*PersistentVolume) IsAnAPIObject() {}
|
||||
|
@@ -814,6 +814,10 @@ type PodSpec struct {
|
||||
// NodeSelector is a selector which must be true for the pod to fit on a node
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
||||
|
||||
// ServiceAccount is the name of the ServiceAccount to use to run this pod
|
||||
// The pod will be allowed to use secrets referenced by the ServiceAccount
|
||||
ServiceAccount string `json:"serviceAccount"`
|
||||
|
||||
// Host is a request to schedule this pod onto a specific host. If it is non-empty,
|
||||
// the the scheduler simply schedules this pod onto that host, assuming that it fits
|
||||
// resource requirements.
|
||||
@@ -1035,6 +1039,26 @@ type Service struct {
|
||||
Status ServiceStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// ServiceAccount binds together:
|
||||
// * a name, understood by users, and perhaps by peripheral systems, for an identity
|
||||
// * a principal that can be authenticated and authorized
|
||||
// * a set of secrets
|
||||
type ServiceAccount struct {
|
||||
TypeMeta `json:",inline"`
|
||||
ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount
|
||||
Secrets []ObjectReference `json:"secrets"`
|
||||
}
|
||||
|
||||
// ServiceAccountList is a list of ServiceAccount objects
|
||||
type ServiceAccountList struct {
|
||||
TypeMeta `json:",inline"`
|
||||
ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
Items []ServiceAccount `json:"items"`
|
||||
}
|
||||
|
||||
// Endpoints is a collection of endpoints that implement the actual service. Example:
|
||||
// Name: "mysvc",
|
||||
// Subsets: [
|
||||
@@ -1805,7 +1829,25 @@ const MaxSecretSize = 1 * 1024 * 1024
|
||||
type SecretType string
|
||||
|
||||
const (
|
||||
SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
|
||||
// SecretTypeOpaque is the default; arbitrary user-defined data
|
||||
SecretTypeOpaque SecretType = "Opaque"
|
||||
|
||||
// SecretTypeServiceAccountToken contains a token that identifies a service account to the API
|
||||
//
|
||||
// Required fields:
|
||||
// - Secret.Annotations["kubernetes.io/service-account.name"] - the name of the ServiceAccount the token identifies
|
||||
// - Secret.Annotations["kubernetes.io/service-account.uid"] - the UID of the ServiceAccount the token identifies
|
||||
// - Secret.Data["token"] - a token that identifies the service account to the API
|
||||
SecretTypeServiceAccountToken SecretType = "kubernetes.io/service-account-token"
|
||||
|
||||
// ServiceAccountNameKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountNameKey = "kubernetes.io/service-account.name"
|
||||
// ServiceAccountUIDKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountUIDKey = "kubernetes.io/service-account.uid"
|
||||
// ServiceAccountTokenKey is the key of the required data for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountTokenKey = "token"
|
||||
// ServiceAccountKubeconfigKey is the key of the optional kubeconfig data for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountKubeconfigKey = "kubernetes.kubeconfig"
|
||||
)
|
||||
|
||||
type SecretList struct {
|
||||
|
@@ -1880,6 +1880,7 @@ func init() {
|
||||
out.NodeSelector[key] = val
|
||||
}
|
||||
}
|
||||
out.ServiceAccount = in.ServiceAccount
|
||||
out.Host = in.Host
|
||||
out.HostNetwork = in.HostNetwork
|
||||
return nil
|
||||
@@ -1913,6 +1914,7 @@ func init() {
|
||||
out.NodeSelector[key] = val
|
||||
}
|
||||
}
|
||||
out.ServiceAccount = in.ServiceAccount
|
||||
out.Host = in.Host
|
||||
out.HostNetwork = in.HostNetwork
|
||||
return nil
|
||||
@@ -2477,6 +2479,74 @@ func init() {
|
||||
}
|
||||
return nil
|
||||
},
|
||||
func(in *ServiceAccount, out *newer.ServiceAccount, s conversion.Scope) error {
|
||||
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Secrets != nil {
|
||||
out.Secrets = make([]newer.ObjectReference, len(in.Secrets))
|
||||
for i := range in.Secrets {
|
||||
if err := s.Convert(&in.Secrets[i], &out.Secrets[i], 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
func(in *newer.ServiceAccount, out *ServiceAccount, s conversion.Scope) error {
|
||||
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Secrets != nil {
|
||||
out.Secrets = make([]ObjectReference, len(in.Secrets))
|
||||
for i := range in.Secrets {
|
||||
if err := s.Convert(&in.Secrets[i], &out.Secrets[i], 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
func(in *ServiceAccountList, out *newer.ServiceAccountList, s conversion.Scope) error {
|
||||
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.Convert(&in.ListMeta, &out.ListMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Items != nil {
|
||||
out.Items = make([]newer.ServiceAccount, len(in.Items))
|
||||
for i := range in.Items {
|
||||
if err := s.Convert(&in.Items[i], &out.Items[i], 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
func(in *newer.ServiceAccountList, out *ServiceAccountList, s conversion.Scope) error {
|
||||
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.Convert(&in.ListMeta, &out.ListMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Items != nil {
|
||||
out.Items = make([]ServiceAccount, len(in.Items))
|
||||
for i := range in.Items {
|
||||
if err := s.Convert(&in.Items[i], &out.Items[i], 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
func(in *ServiceList, out *newer.ServiceList, s conversion.Scope) error {
|
||||
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
|
||||
return err
|
||||
|
@@ -52,6 +52,8 @@ func init() {
|
||||
&NamespaceList{},
|
||||
&Secret{},
|
||||
&SecretList{},
|
||||
&ServiceAccount{},
|
||||
&ServiceAccountList{},
|
||||
&PersistentVolume{},
|
||||
&PersistentVolumeList{},
|
||||
&PersistentVolumeClaim{},
|
||||
@@ -97,6 +99,8 @@ func (*Namespace) IsAnAPIObject() {}
|
||||
func (*NamespaceList) IsAnAPIObject() {}
|
||||
func (*Secret) IsAnAPIObject() {}
|
||||
func (*SecretList) IsAnAPIObject() {}
|
||||
func (*ServiceAccount) IsAnAPIObject() {}
|
||||
func (*ServiceAccountList) IsAnAPIObject() {}
|
||||
func (*PersistentVolume) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeList) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeClaim) IsAnAPIObject() {}
|
||||
|
@@ -816,6 +816,9 @@ type PodSpec struct {
|
||||
// NodeSelector is a selector which must be true for the pod to fit on a node
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty" description:"selector which must match a node's labels for the pod to be scheduled on that node"`
|
||||
|
||||
// ServiceAccount is the name of the ServiceAccount to use to run this pod
|
||||
ServiceAccount string `json:"serviceAccount" description:"name of the ServiceAccount to use to run this pod"`
|
||||
|
||||
// Host is a request to schedule this pod onto a specific host. If it is non-empty,
|
||||
// the the scheduler simply schedules this pod onto that host, assuming that it fits
|
||||
// resource requirements.
|
||||
@@ -1036,6 +1039,26 @@ type ServiceList struct {
|
||||
Items []Service `json:"items" description:"list of services"`
|
||||
}
|
||||
|
||||
// ServiceAccount binds together:
|
||||
// * a name, understood by users, and perhaps by peripheral systems, for an identity
|
||||
// * a principal that can be authenticated and authorized
|
||||
// * a set of secrets
|
||||
type ServiceAccount struct {
|
||||
TypeMeta `json:",inline"`
|
||||
ObjectMeta `json:"metadata,omitempty" description:"standard object metadata; see http://docs.k8s.io/api-conventions.md#metadata"`
|
||||
|
||||
// Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount
|
||||
Secrets []ObjectReference `json:"secrets" description:"list of secrets that can be used by pods running as this service account" patchStrategy:"merge" patchMergeKey:"name"`
|
||||
}
|
||||
|
||||
// ServiceAccountList is a list of ServiceAccount objects
|
||||
type ServiceAccountList struct {
|
||||
TypeMeta `json:",inline"`
|
||||
ListMeta `json:"metadata,omitempty" description:"standard list metadata; see http://docs.k8s.io/api-conventions.md#metadata"`
|
||||
|
||||
Items []ServiceAccount `json:"items" description:"list of ServiceAccounts"`
|
||||
}
|
||||
|
||||
// Endpoints is a collection of endpoints that implement the actual service. Example:
|
||||
// Name: "mysvc",
|
||||
// Subsets: [
|
||||
@@ -1708,7 +1731,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
||||
type SecretType string
|
||||
|
||||
const (
|
||||
SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
|
||||
// SecretTypeOpaque is the default; arbitrary user-defined data
|
||||
SecretTypeOpaque SecretType = "Opaque"
|
||||
|
||||
// SecretTypeServiceAccountToken contains a token that identifies a service account to the API
|
||||
//
|
||||
// Required fields:
|
||||
// - Secret.Annotations["kubernetes.io/service-account.name"] - the name of the ServiceAccount the token identifies
|
||||
// - Secret.Annotations["kubernetes.io/service-account.uid"] - the UID of the ServiceAccount the token identifies
|
||||
// - Secret.Data["token"] - a token that identifies the service account to the API
|
||||
SecretTypeServiceAccountToken SecretType = "kubernetes.io/service-account-token"
|
||||
|
||||
// ServiceAccountNameKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountNameKey = "kubernetes.io/service-account.name"
|
||||
// ServiceAccountUIDKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountUIDKey = "kubernetes.io/service-account.uid"
|
||||
// ServiceAccountTokenKey is the key of the required data for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountTokenKey = "token"
|
||||
)
|
||||
|
||||
type SecretList struct {
|
||||
|
@@ -377,6 +377,7 @@ func init() {
|
||||
}
|
||||
out.DesiredState.Host = in.Spec.Host
|
||||
out.CurrentState.Host = in.Spec.Host
|
||||
out.ServiceAccount = in.Spec.ServiceAccount
|
||||
if err := s.Convert(&in.Status, &out.CurrentState, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -399,6 +400,7 @@ func init() {
|
||||
return err
|
||||
}
|
||||
out.Spec.Host = in.DesiredState.Host
|
||||
out.Spec.ServiceAccount = in.ServiceAccount
|
||||
if err := s.Convert(&in.CurrentState, &out.Status, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -503,6 +505,7 @@ func init() {
|
||||
return err
|
||||
}
|
||||
out.DesiredState.Host = in.Spec.Host
|
||||
out.ServiceAccount = in.Spec.ServiceAccount
|
||||
if err := s.Convert(&in.Spec.NodeSelector, &out.NodeSelector, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -519,6 +522,7 @@ func init() {
|
||||
return err
|
||||
}
|
||||
out.Spec.Host = in.DesiredState.Host
|
||||
out.Spec.ServiceAccount = in.ServiceAccount
|
||||
if err := s.Convert(&in.NodeSelector, &out.Spec.NodeSelector, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1685,4 +1689,17 @@ func init() {
|
||||
// If one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
err = newer.Scheme.AddFieldLabelConversionFunc("v1beta1", "ServiceAccount",
|
||||
func(label, value string) (string, string, error) {
|
||||
switch label {
|
||||
case "name":
|
||||
return "metadata.name", value, nil
|
||||
default:
|
||||
return "", "", fmt.Errorf("field label not supported: %s", label)
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
// If one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
@@ -59,6 +59,8 @@ func init() {
|
||||
&NamespaceList{},
|
||||
&Secret{},
|
||||
&SecretList{},
|
||||
&ServiceAccount{},
|
||||
&ServiceAccountList{},
|
||||
&PersistentVolume{},
|
||||
&PersistentVolumeList{},
|
||||
&PersistentVolumeClaim{},
|
||||
@@ -105,6 +107,8 @@ func (*Namespace) IsAnAPIObject() {}
|
||||
func (*NamespaceList) IsAnAPIObject() {}
|
||||
func (*Secret) IsAnAPIObject() {}
|
||||
func (*SecretList) IsAnAPIObject() {}
|
||||
func (*ServiceAccount) IsAnAPIObject() {}
|
||||
func (*ServiceAccountList) IsAnAPIObject() {}
|
||||
func (*PersistentVolume) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeList) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeClaim) IsAnAPIObject() {}
|
||||
|
@@ -755,6 +755,8 @@ type Pod struct {
|
||||
Labels map[string]string `json:"labels,omitempty" description:"map of string keys and values that can be used to organize and categorize pods; may match selectors of replication controllers and services"`
|
||||
DesiredState PodState `json:"desiredState,omitempty" description:"specification of the desired state of the pod"`
|
||||
CurrentState PodState `json:"currentState,omitempty" description:"current state of the pod; populated by the system, read-only"`
|
||||
// ServiceAccount is the name of the ServiceAccount to use to run this pod
|
||||
ServiceAccount string `json:"serviceAccount,omitempty" description:"the name of the ServiceAccount to use to run this pod"`
|
||||
// NodeSelector is a selector which must be true for the pod to fit on a node
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty" description:"selector which must match a node's labels for the pod to be scheduled on that node"`
|
||||
}
|
||||
@@ -782,10 +784,11 @@ type ReplicationController struct {
|
||||
|
||||
// PodTemplate holds the information used for creating pods.
|
||||
type PodTemplate struct {
|
||||
DesiredState PodState `json:"desiredState,omitempty" description:"specification of the desired state of pods created from this template"`
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty" description:"a selector which must be true for the pod to fit on a node"`
|
||||
Labels map[string]string `json:"labels,omitempty" description:"map of string keys and values that can be used to organize and categorize the pods created from the template; must match the selector of the replication controller to which the template belongs; may match selectors of services"`
|
||||
Annotations map[string]string `json:"annotations,omitempty" description:"map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about pods created from the template"`
|
||||
DesiredState PodState `json:"desiredState,omitempty" description:"specification of the desired state of pods created from this template"`
|
||||
ServiceAccount string `json:"serviceAccount,omitempty" description:"the name of the ServiceAccount to use to run this pod"`
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty" description:"a selector which must be true for the pod to fit on a node"`
|
||||
Labels map[string]string `json:"labels,omitempty" description:"map of string keys and values that can be used to organize and categorize the pods created from the template; must match the selector of the replication controller to which the template belongs; may match selectors of services"`
|
||||
Annotations map[string]string `json:"annotations,omitempty" description:"map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about pods created from the template"`
|
||||
}
|
||||
|
||||
// Session Affinity Type string
|
||||
@@ -884,6 +887,24 @@ type ServicePort struct {
|
||||
ContainerPort util.IntOrString `json:"containerPort" description:"the port to access on the containers belonging to pods targeted by the service; defaults to the service port"`
|
||||
}
|
||||
|
||||
// ServiceAccount binds together:
|
||||
// * a name, understood by users, and perhaps by peripheral systems, for an identity
|
||||
// * a principal that can be authenticated and authorized
|
||||
// * a set of secrets
|
||||
type ServiceAccount struct {
|
||||
TypeMeta `json:",inline"`
|
||||
|
||||
// Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount
|
||||
Secrets []ObjectReference `json:"secrets" description:"list of secrets that can be used by pods running as this service account" patchStrategy:"merge" patchMergeKey:"name"`
|
||||
}
|
||||
|
||||
// ServiceAccountList is a list of ServiceAccount objects
|
||||
type ServiceAccountList struct {
|
||||
TypeMeta `json:",inline"`
|
||||
|
||||
Items []ServiceAccount `json:"items" description:"list of ServiceAccounts"`
|
||||
}
|
||||
|
||||
// EndpointObjectReference is a reference to an object exposing the endpoint
|
||||
type EndpointObjectReference struct {
|
||||
Endpoint string `json:"endpoint" description:"endpoint exposed by the referenced object"`
|
||||
@@ -1617,7 +1638,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
||||
type SecretType string
|
||||
|
||||
const (
|
||||
SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
|
||||
// SecretTypeOpaque is the default; arbitrary user-defined data
|
||||
SecretTypeOpaque SecretType = "Opaque"
|
||||
|
||||
// SecretTypeServiceAccountToken contains a token that identifies a service account to the API
|
||||
//
|
||||
// Required fields:
|
||||
// - Secret.Annotations["kubernetes.io/service-account.name"] - the name of the ServiceAccount the token identifies
|
||||
// - Secret.Annotations["kubernetes.io/service-account.uid"] - the UID of the ServiceAccount the token identifies
|
||||
// - Secret.Data["token"] - a token that identifies the service account to the API
|
||||
SecretTypeServiceAccountToken SecretType = "kubernetes.io/service-account-token"
|
||||
|
||||
// ServiceAccountNameKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountNameKey = "kubernetes.io/service-account.name"
|
||||
// ServiceAccountUIDKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountUIDKey = "kubernetes.io/service-account.uid"
|
||||
// ServiceAccountTokenKey is the key of the required data for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountTokenKey = "token"
|
||||
)
|
||||
|
||||
type SecretList struct {
|
||||
|
@@ -180,6 +180,7 @@ func init() {
|
||||
}
|
||||
out.DesiredState.Host = in.Spec.Host
|
||||
out.CurrentState.Host = in.Spec.Host
|
||||
out.ServiceAccount = in.Spec.ServiceAccount
|
||||
if err := s.Convert(&in.Status, &out.CurrentState, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -201,6 +202,7 @@ func init() {
|
||||
if err := s.Convert(&in.DesiredState.Manifest, &out.Spec, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Spec.ServiceAccount = in.ServiceAccount
|
||||
out.Spec.Host = in.DesiredState.Host
|
||||
if err := s.Convert(&in.CurrentState, &out.Status, 0); err != nil {
|
||||
return err
|
||||
@@ -282,6 +284,7 @@ func init() {
|
||||
return err
|
||||
}
|
||||
out.DesiredState.Host = in.Spec.Host
|
||||
out.ServiceAccount = in.Spec.ServiceAccount
|
||||
if err := s.Convert(&in.Spec.NodeSelector, &out.NodeSelector, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -298,6 +301,7 @@ func init() {
|
||||
return err
|
||||
}
|
||||
out.Spec.Host = in.DesiredState.Host
|
||||
out.Spec.ServiceAccount = in.ServiceAccount
|
||||
if err := s.Convert(&in.NodeSelector, &out.Spec.NodeSelector, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1601,4 +1605,17 @@ func init() {
|
||||
// If one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
err = newer.Scheme.AddFieldLabelConversionFunc("v1beta2", "ServiceAccount",
|
||||
func(label, value string) (string, string, error) {
|
||||
switch label {
|
||||
case "name":
|
||||
return "metadata.name", value, nil
|
||||
default:
|
||||
return "", "", fmt.Errorf("field label not supported: %s", label)
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
// If one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
@@ -59,6 +59,8 @@ func init() {
|
||||
&NamespaceList{},
|
||||
&Secret{},
|
||||
&SecretList{},
|
||||
&ServiceAccount{},
|
||||
&ServiceAccountList{},
|
||||
&PersistentVolume{},
|
||||
&PersistentVolumeList{},
|
||||
&PersistentVolumeClaim{},
|
||||
@@ -105,6 +107,8 @@ func (*Namespace) IsAnAPIObject() {}
|
||||
func (*NamespaceList) IsAnAPIObject() {}
|
||||
func (*Secret) IsAnAPIObject() {}
|
||||
func (*SecretList) IsAnAPIObject() {}
|
||||
func (*ServiceAccount) IsAnAPIObject() {}
|
||||
func (*ServiceAccountList) IsAnAPIObject() {}
|
||||
func (*PersistentVolume) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeList) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeClaim) IsAnAPIObject() {}
|
||||
|
@@ -756,6 +756,8 @@ type Pod struct {
|
||||
Labels map[string]string `json:"labels,omitempty" description:"map of string keys and values that can be used to organize and categorize pods; may match selectors of replication controllers and services"`
|
||||
DesiredState PodState `json:"desiredState,omitempty" description:"specification of the desired state of the pod"`
|
||||
CurrentState PodState `json:"currentState,omitempty" description:"current state of the pod; populated by the system, read-only"`
|
||||
// ServiceAccount is the name of the ServiceAccount to use to run this pod
|
||||
ServiceAccount string `json:"serviceAccount,omitempty" description:"the name of the ServiceAccount to use to run this pod"`
|
||||
// NodeSelector is a selector which must be true for the pod to fit on a node
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty" description:"selector which must match a node's labels for the pod to be scheduled on that node"`
|
||||
}
|
||||
@@ -787,10 +789,11 @@ type ReplicationController struct {
|
||||
//
|
||||
// http://docs.k8s.io/replication-controller.md#pod-template
|
||||
type PodTemplate struct {
|
||||
DesiredState PodState `json:"desiredState,omitempty" description:"specification of the desired state of pods created from this template"`
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty" description:"a selector which must be true for the pod to fit on a node"`
|
||||
Labels map[string]string `json:"labels,omitempty" description:"map of string keys and values that can be used to organize and categorize the pods created from the template; must match the selector of the replication controller to which the template belongs; may match selectors of services"`
|
||||
Annotations map[string]string `json:"annotations,omitempty" description:"map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about pods created from the template"`
|
||||
DesiredState PodState `json:"desiredState,omitempty" description:"specification of the desired state of pods created from this template"`
|
||||
ServiceAccount string `json:"serviceAccount,omitempty" description:"the name of the ServiceAccount to use to run this pod"`
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty" description:"a selector which must be true for the pod to fit on a node"`
|
||||
Labels map[string]string `json:"labels,omitempty" description:"map of string keys and values that can be used to organize and categorize the pods created from the template; must match the selector of the replication controller to which the template belongs; may match selectors of services"`
|
||||
Annotations map[string]string `json:"annotations,omitempty" description:"map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about pods created from the template"`
|
||||
}
|
||||
|
||||
// Session Affinity Type string
|
||||
@@ -891,6 +894,24 @@ type ServicePort struct {
|
||||
ContainerPort util.IntOrString `json:"containerPort" description:"the port to access on the containers belonging to pods targeted by the service; defaults to the service port"`
|
||||
}
|
||||
|
||||
// ServiceAccount binds together:
|
||||
// * a name, understood by users, and perhaps by peripheral systems, for an identity
|
||||
// * a principal that can be authenticated and authorized
|
||||
// * a set of secrets
|
||||
type ServiceAccount struct {
|
||||
TypeMeta `json:",inline"`
|
||||
|
||||
// Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount
|
||||
Secrets []ObjectReference `json:"secrets" description:"list of secrets that can be used by pods running as this service account" patchStrategy:"merge" patchMergeKey:"name"`
|
||||
}
|
||||
|
||||
// ServiceAccountList is a list of ServiceAccount objects
|
||||
type ServiceAccountList struct {
|
||||
TypeMeta `json:",inline"`
|
||||
|
||||
Items []ServiceAccount `json:"items" description:"list of ServiceAccounts"`
|
||||
}
|
||||
|
||||
// EndpointObjectReference is a reference to an object exposing the endpoint
|
||||
type EndpointObjectReference struct {
|
||||
Endpoint string `json:"endpoint" description:"endpoint exposed by the referenced object"`
|
||||
@@ -1692,7 +1713,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
||||
type SecretType string
|
||||
|
||||
const (
|
||||
SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
|
||||
// SecretTypeOpaque is the default; arbitrary user-defined data
|
||||
SecretTypeOpaque SecretType = "Opaque"
|
||||
|
||||
// SecretTypeServiceAccountToken contains a token that identifies a service account to the API
|
||||
//
|
||||
// Required fields:
|
||||
// - Secret.Annotations["kubernetes.io/service-account.name"] - the name of the ServiceAccount the token identifies
|
||||
// - Secret.Annotations["kubernetes.io/service-account.uid"] - the UID of the ServiceAccount the token identifies
|
||||
// - Secret.Data["token"] - a token that identifies the service account to the API
|
||||
SecretTypeServiceAccountToken SecretType = "kubernetes.io/service-account-token"
|
||||
|
||||
// ServiceAccountNameKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountNameKey = "kubernetes.io/service-account.name"
|
||||
// ServiceAccountUIDKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountUIDKey = "kubernetes.io/service-account.uid"
|
||||
// ServiceAccountTokenKey is the key of the required data for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountTokenKey = "token"
|
||||
)
|
||||
|
||||
type SecretList struct {
|
||||
|
@@ -128,6 +128,19 @@ func init() {
|
||||
// If one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
err = newer.Scheme.AddFieldLabelConversionFunc("v1beta3", "ServiceAccount",
|
||||
func(label, value string) (string, string, error) {
|
||||
switch label {
|
||||
case "metadata.name":
|
||||
return label, value, nil
|
||||
default:
|
||||
return "", "", fmt.Errorf("field label not supported: %s", label)
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
// If one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func convert_v1beta3_Container_To_api_Container(in *Container, out *newer.Container, s conversion.Scope) error {
|
||||
|
@@ -2639,6 +2639,7 @@ func convert_v1beta3_PodSpec_To_api_PodSpec(in *PodSpec, out *newer.PodSpec, s c
|
||||
} else {
|
||||
out.NodeSelector = nil
|
||||
}
|
||||
out.ServiceAccount = in.ServiceAccount
|
||||
out.Host = in.Host
|
||||
out.HostNetwork = in.HostNetwork
|
||||
return nil
|
||||
@@ -2684,6 +2685,7 @@ func convert_api_PodSpec_To_v1beta3_PodSpec(in *newer.PodSpec, out *PodSpec, s c
|
||||
} else {
|
||||
out.NodeSelector = nil
|
||||
}
|
||||
out.ServiceAccount = in.ServiceAccount
|
||||
out.Host = in.Host
|
||||
out.HostNetwork = in.HostNetwork
|
||||
return nil
|
||||
@@ -3625,6 +3627,98 @@ func convert_api_Service_To_v1beta3_Service(in *newer.Service, out *Service, s c
|
||||
return nil
|
||||
}
|
||||
|
||||
func convert_v1beta3_ServiceAccount_To_api_ServiceAccount(in *ServiceAccount, out *newer.ServiceAccount, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*ServiceAccount))(in)
|
||||
}
|
||||
if err := convert_v1beta3_TypeMeta_To_api_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := convert_v1beta3_ObjectMeta_To_api_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Secrets != nil {
|
||||
out.Secrets = make([]newer.ObjectReference, len(in.Secrets))
|
||||
for i := range in.Secrets {
|
||||
if err := convert_v1beta3_ObjectReference_To_api_ObjectReference(&in.Secrets[i], &out.Secrets[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Secrets = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func convert_api_ServiceAccount_To_v1beta3_ServiceAccount(in *newer.ServiceAccount, out *ServiceAccount, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*newer.ServiceAccount))(in)
|
||||
}
|
||||
if err := convert_api_TypeMeta_To_v1beta3_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := convert_api_ObjectMeta_To_v1beta3_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Secrets != nil {
|
||||
out.Secrets = make([]ObjectReference, len(in.Secrets))
|
||||
for i := range in.Secrets {
|
||||
if err := convert_api_ObjectReference_To_v1beta3_ObjectReference(&in.Secrets[i], &out.Secrets[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Secrets = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func convert_v1beta3_ServiceAccountList_To_api_ServiceAccountList(in *ServiceAccountList, out *newer.ServiceAccountList, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*ServiceAccountList))(in)
|
||||
}
|
||||
if err := convert_v1beta3_TypeMeta_To_api_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := convert_v1beta3_ListMeta_To_api_ListMeta(&in.ListMeta, &out.ListMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Items != nil {
|
||||
out.Items = make([]newer.ServiceAccount, len(in.Items))
|
||||
for i := range in.Items {
|
||||
if err := convert_v1beta3_ServiceAccount_To_api_ServiceAccount(&in.Items[i], &out.Items[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func convert_api_ServiceAccountList_To_v1beta3_ServiceAccountList(in *newer.ServiceAccountList, out *ServiceAccountList, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*newer.ServiceAccountList))(in)
|
||||
}
|
||||
if err := convert_api_TypeMeta_To_v1beta3_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := convert_api_ListMeta_To_v1beta3_ListMeta(&in.ListMeta, &out.ListMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Items != nil {
|
||||
out.Items = make([]ServiceAccount, len(in.Items))
|
||||
for i := range in.Items {
|
||||
if err := convert_api_ServiceAccount_To_v1beta3_ServiceAccount(&in.Items[i], &out.Items[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func convert_v1beta3_ServiceList_To_api_ServiceList(in *ServiceList, out *newer.ServiceList, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*ServiceList))(in)
|
||||
@@ -4244,6 +4338,8 @@ func init() {
|
||||
convert_api_Secret_To_v1beta3_Secret,
|
||||
convert_api_SecurityContext_To_v1beta3_SecurityContext,
|
||||
convert_api_SerializedReference_To_v1beta3_SerializedReference,
|
||||
convert_api_ServiceAccountList_To_v1beta3_ServiceAccountList,
|
||||
convert_api_ServiceAccount_To_v1beta3_ServiceAccount,
|
||||
convert_api_ServiceList_To_v1beta3_ServiceList,
|
||||
convert_api_ServicePort_To_v1beta3_ServicePort,
|
||||
convert_api_ServiceSpec_To_v1beta3_ServiceSpec,
|
||||
@@ -4350,6 +4446,8 @@ func init() {
|
||||
convert_v1beta3_Secret_To_api_Secret,
|
||||
convert_v1beta3_SecurityContext_To_api_SecurityContext,
|
||||
convert_v1beta3_SerializedReference_To_api_SerializedReference,
|
||||
convert_v1beta3_ServiceAccountList_To_api_ServiceAccountList,
|
||||
convert_v1beta3_ServiceAccount_To_api_ServiceAccount,
|
||||
convert_v1beta3_ServiceList_To_api_ServiceList,
|
||||
convert_v1beta3_ServicePort_To_api_ServicePort,
|
||||
convert_v1beta3_ServiceSpec_To_api_ServiceSpec,
|
||||
|
@@ -52,6 +52,8 @@ func init() {
|
||||
&NamespaceList{},
|
||||
&Secret{},
|
||||
&SecretList{},
|
||||
&ServiceAccount{},
|
||||
&ServiceAccountList{},
|
||||
&PersistentVolume{},
|
||||
&PersistentVolumeList{},
|
||||
&PersistentVolumeClaim{},
|
||||
@@ -97,6 +99,8 @@ func (*Namespace) IsAnAPIObject() {}
|
||||
func (*NamespaceList) IsAnAPIObject() {}
|
||||
func (*Secret) IsAnAPIObject() {}
|
||||
func (*SecretList) IsAnAPIObject() {}
|
||||
func (*ServiceAccount) IsAnAPIObject() {}
|
||||
func (*ServiceAccountList) IsAnAPIObject() {}
|
||||
func (*PersistentVolume) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeList) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeClaim) IsAnAPIObject() {}
|
||||
|
@@ -816,6 +816,9 @@ type PodSpec struct {
|
||||
// NodeSelector is a selector which must be true for the pod to fit on a node
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty" description:"selector which must match a node's labels for the pod to be scheduled on that node"`
|
||||
|
||||
// ServiceAccount is the name of the ServiceAccount to use to run this pod
|
||||
ServiceAccount string `json:"serviceAccount" description:"name of the ServiceAccount to use to run this pod"`
|
||||
|
||||
// Host is a request to schedule this pod onto a specific host. If it is non-empty,
|
||||
// the the scheduler simply schedules this pod onto that host, assuming that it fits
|
||||
// resource requirements.
|
||||
@@ -1036,6 +1039,26 @@ type ServiceList struct {
|
||||
Items []Service `json:"items" description:"list of services"`
|
||||
}
|
||||
|
||||
// ServiceAccount binds together:
|
||||
// * a name, understood by users, and perhaps by peripheral systems, for an identity
|
||||
// * a principal that can be authenticated and authorized
|
||||
// * a set of secrets
|
||||
type ServiceAccount struct {
|
||||
TypeMeta `json:",inline"`
|
||||
ObjectMeta `json:"metadata,omitempty" description:"standard object metadata; see http://docs.k8s.io/api-conventions.md#metadata"`
|
||||
|
||||
// Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount
|
||||
Secrets []ObjectReference `json:"secrets" description:"list of secrets that can be used by pods running as this service account" patchStrategy:"merge" patchMergeKey:"name"`
|
||||
}
|
||||
|
||||
// ServiceAccountList is a list of ServiceAccount objects
|
||||
type ServiceAccountList struct {
|
||||
TypeMeta `json:",inline"`
|
||||
ListMeta `json:"metadata,omitempty" description:"standard list metadata; see http://docs.k8s.io/api-conventions.md#metadata"`
|
||||
|
||||
Items []ServiceAccount `json:"items" description:"list of ServiceAccounts"`
|
||||
}
|
||||
|
||||
// Endpoints is a collection of endpoints that implement the actual service. Example:
|
||||
// Name: "mysvc",
|
||||
// Subsets: [
|
||||
@@ -1708,7 +1731,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
||||
type SecretType string
|
||||
|
||||
const (
|
||||
SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
|
||||
// SecretTypeOpaque is the default; arbitrary user-defined data
|
||||
SecretTypeOpaque SecretType = "Opaque"
|
||||
|
||||
// SecretTypeServiceAccountToken contains a token that identifies a service account to the API
|
||||
//
|
||||
// Required fields:
|
||||
// - Secret.Annotations["kubernetes.io/service-account.name"] - the name of the ServiceAccount the token identifies
|
||||
// - Secret.Annotations["kubernetes.io/service-account.uid"] - the UID of the ServiceAccount the token identifies
|
||||
// - Secret.Data["token"] - a token that identifies the service account to the API
|
||||
SecretTypeServiceAccountToken SecretType = "kubernetes.io/service-account-token"
|
||||
|
||||
// ServiceAccountNameKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountNameKey = "kubernetes.io/service-account.name"
|
||||
// ServiceAccountUIDKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountUIDKey = "kubernetes.io/service-account.uid"
|
||||
// ServiceAccountTokenKey is the key of the required data for SecretTypeServiceAccountToken secrets
|
||||
ServiceAccountTokenKey = "token"
|
||||
)
|
||||
|
||||
type SecretList struct {
|
||||
|
@@ -153,6 +153,13 @@ func ValidateSecretName(name string, prefix bool) (bool, string) {
|
||||
return nameIsDNSSubdomain(name, prefix)
|
||||
}
|
||||
|
||||
// ValidateServiceAccountName can be used to check whether the given service account name is valid.
|
||||
// Prefix indicates this name will be used as part of generation, in which case
|
||||
// trailing dashes are allowed.
|
||||
func ValidateServiceAccountName(name string, prefix bool) (bool, string) {
|
||||
return nameIsDNSSubdomain(name, prefix)
|
||||
}
|
||||
|
||||
// ValidateEndpointsName can be used to check whether the given endpoints name is valid.
|
||||
// Prefix indicates this name will be used as part of generation, in which case
|
||||
// trailing dashes are allowed.
|
||||
@@ -1227,6 +1234,21 @@ func ValidateLimitRange(limitRange *api.LimitRange) errs.ValidationErrorList {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateServiceAccount tests if required fields in the ServiceAccount are set.
|
||||
func ValidateServiceAccount(serviceAccount *api.ServiceAccount) errs.ValidationErrorList {
|
||||
allErrs := errs.ValidationErrorList{}
|
||||
allErrs = append(allErrs, ValidateObjectMeta(&serviceAccount.ObjectMeta, true, ValidateServiceAccountName).Prefix("metadata")...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateServiceAccountUpdate tests if required fields in the ServiceAccount are set.
|
||||
func ValidateServiceAccountUpdate(oldServiceAccount, newServiceAccount *api.ServiceAccount) errs.ValidationErrorList {
|
||||
allErrs := errs.ValidationErrorList{}
|
||||
allErrs = append(allErrs, ValidateObjectMetaUpdate(&oldServiceAccount.ObjectMeta, &newServiceAccount.ObjectMeta).Prefix("metadata")...)
|
||||
allErrs = append(allErrs, ValidateServiceAccount(newServiceAccount)...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateSecret tests if required fields in the Secret are set.
|
||||
func ValidateSecret(secret *api.Secret) errs.ValidationErrorList {
|
||||
allErrs := errs.ValidationErrorList{}
|
||||
@@ -1246,6 +1268,12 @@ func ValidateSecret(secret *api.Secret) errs.ValidationErrorList {
|
||||
}
|
||||
|
||||
switch secret.Type {
|
||||
case api.SecretTypeServiceAccountToken:
|
||||
// Only require Annotations[kubernetes.io/service-account.name]
|
||||
// Additional fields (like Annotations[kubernetes.io/service-account.uid] and Data[token]) might be contributed later by a controller loop
|
||||
if value := secret.Annotations[api.ServiceAccountNameKey]; len(value) == 0 {
|
||||
allErrs = append(allErrs, errs.NewFieldRequired(fmt.Sprintf("metadata.annotations[%s]", api.ServiceAccountNameKey)))
|
||||
}
|
||||
case api.SecretTypeOpaque, "":
|
||||
// no-op
|
||||
default:
|
||||
|
@@ -2961,6 +2961,7 @@ func TestValidateNamespaceUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestValidateSecret(t *testing.T) {
|
||||
// Opaque secret validation
|
||||
validSecret := func() api.Secret {
|
||||
return api.Secret{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||
@@ -2988,6 +2989,32 @@ func TestValidateSecret(t *testing.T) {
|
||||
}
|
||||
invalidKey.Data["a..b"] = []byte("whoops")
|
||||
|
||||
// kubernetes.io/service-account-token secret validation
|
||||
validServiceAccountTokenSecret := func() api.Secret {
|
||||
return api.Secret{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
Namespace: "bar",
|
||||
Annotations: map[string]string{
|
||||
api.ServiceAccountNameKey: "foo",
|
||||
},
|
||||
},
|
||||
Type: api.SecretTypeServiceAccountToken,
|
||||
Data: map[string][]byte{
|
||||
"data-1": []byte("bar"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
emptyTokenAnnotation = validServiceAccountTokenSecret()
|
||||
missingTokenAnnotation = validServiceAccountTokenSecret()
|
||||
missingTokenAnnotations = validServiceAccountTokenSecret()
|
||||
)
|
||||
emptyTokenAnnotation.Annotations[api.ServiceAccountNameKey] = ""
|
||||
delete(missingTokenAnnotation.Annotations, api.ServiceAccountNameKey)
|
||||
missingTokenAnnotations.Annotations = nil
|
||||
|
||||
tests := map[string]struct {
|
||||
secret api.Secret
|
||||
valid bool
|
||||
@@ -2999,6 +3026,11 @@ func TestValidateSecret(t *testing.T) {
|
||||
"invalid namespace": {invalidNs, false},
|
||||
"over max size": {overMaxSize, false},
|
||||
"invalid key": {invalidKey, false},
|
||||
|
||||
"valid service-account-token secret": {validServiceAccountTokenSecret(), true},
|
||||
"empty service-account-token annotation": {emptyTokenAnnotation, false},
|
||||
"missing service-account-token annotation": {missingTokenAnnotation, false},
|
||||
"missing service-account-token annotations": {missingTokenAnnotations, false},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
|
Reference in New Issue
Block a user