Merge pull request #4653 from thockin/secret_fixups

Secrets fixups
This commit is contained in:
Tim Hockin 2015-02-23 13:49:19 -08:00
commit eed36455a7
21 changed files with 162 additions and 160 deletions

View File

@ -273,7 +273,8 @@ type Secret struct {
ObjectMeta ObjectMeta
// Data contains the secret data. Each key must be a valid DNS_SUBDOMAIN. // Data contains the secret data. Each key must be a valid DNS_SUBDOMAIN.
// The serialized form of the secret data is a base64 encoded string. // The serialized form of the secret data is a base64 encoded string,
// representing the arbitrary (possibly non-string) data value here.
Data map[string][]byte `json:"data,omitempty"` Data map[string][]byte `json:"data,omitempty"`
// Used to facilitate programatic handling of secret data. // Used to facilitate programatic handling of secret data.
@ -283,9 +284,9 @@ type Secret struct {
type SecretType string type SecretType string
const ( const (
SecretTypeOpaque SecretType = "opaque" // Opaque (arbitrary data; default) SecretTypeOpaque SecretType = "Opaque" // Opaque (arbitrary data; default)
SecretTypeKubernetesAuthToken SecretType = "kubernetes-auth" // Kubernetes auth token SecretTypeKubernetesAuthToken SecretType = "KubernetesAuth" // Kubernetes auth token
SecretTypeDockerRegistryAuth SecretType = "docker-reg-auth" // Docker registry auth SecretTypeDockerRegistryAuth SecretType = "DockerRegistryAuth" // Docker registry auth
// FUTURE: other type values // FUTURE: other type values
) )
@ -398,8 +399,9 @@ To create a pod that uses an ssh key stored as a secret, we first need to create
} }
``` ```
**Note:** The values of secret data are encoded as base64-encoded strings. Newlines are not **Note:** The serialized JSON and YAML values of secret data are encoded as
valid within these strings and must be omitted. base64 strings. Newlines are not valid within these strings and must be
omitted.
Now we can create a pod which references the secret with the ssh key and consumes it in a volume: Now we can create a pod which references the secret with the ssh key and consumes it in a volume:

View File

@ -181,7 +181,7 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
func(vs *api.VolumeSource, c fuzz.Continue) { func(vs *api.VolumeSource, c fuzz.Continue) {
// Exactly one of the fields should be set. // Exactly one of the fields should be set.
//FIXME: the fuzz can still end up nil. What if fuzz allowed me to say that? //FIXME: the fuzz can still end up nil. What if fuzz allowed me to say that?
fuzzOneOf(c, &vs.HostPath, &vs.EmptyDir, &vs.GCEPersistentDisk, &vs.GitRepo) fuzzOneOf(c, &vs.HostPath, &vs.EmptyDir, &vs.GCEPersistentDisk, &vs.GitRepo, &vs.Secret)
}, },
func(d *api.DNSPolicy, c fuzz.Continue) { func(d *api.DNSPolicy, c fuzz.Continue) {
policies := []api.DNSPolicy{api.DNSClusterFirst, api.DNSDefault} policies := []api.DNSPolicy{api.DNSClusterFirst, api.DNSDefault}
@ -235,6 +235,7 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
c.Fuzz(&s.ObjectMeta) c.Fuzz(&s.ObjectMeta)
s.Type = api.SecretTypeOpaque s.Type = api.SecretTypeOpaque
c.Fuzz(&s.Data)
}, },
func(ep *api.Endpoint, c fuzz.Continue) { func(ep *api.Endpoint, c fuzz.Continue) {
// TODO: If our API used a particular type for IP fields we could just catch that here. // TODO: If our API used a particular type for IP fields we could just catch that here.

View File

@ -170,24 +170,24 @@ type VolumeSource struct {
// machine. Most containers will NOT need this. // machine. Most containers will NOT need this.
// TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not // TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not
// mount host directories as read/write. // mount host directories as read/write.
HostPath *HostPath `json:"hostPath"` HostPath *HostPathVolumeSource `json:"hostPath"`
// EmptyDir represents a temporary directory that shares a pod's lifetime. // EmptyDir represents a temporary directory that shares a pod's lifetime.
EmptyDir *EmptyDir `json:"emptyDir"` EmptyDir *EmptyDirVolumeSource `json:"emptyDir"`
// GCEPersistentDisk represents a GCE Disk resource that is attached to a // GCEPersistentDisk represents a GCE Disk resource that is attached to a
// kubelet's host machine and then exposed to the pod. // kubelet's host machine and then exposed to the pod.
GCEPersistentDisk *GCEPersistentDisk `json:"persistentDisk"` GCEPersistentDisk *GCEPersistentDiskVolumeSource `json:"persistentDisk"`
// GitRepo represents a git repository at a particular revision. // GitRepo represents a git repository at a particular revision.
GitRepo *GitRepo `json:"gitRepo"` GitRepo *GitRepoVolumeSource `json:"gitRepo"`
// Secret represents a secret that should populate this volume. // Secret represents a secret that should populate this volume.
Secret *SecretSource `json:"secret"` Secret *SecretVolumeSource `json:"secret"`
} }
// HostPath represents bare host directory volume. // HostPathVolumeSource represents bare host directory volume.
type HostPath struct { type HostPathVolumeSource struct {
Path string `json:"path"` Path string `json:"path"`
} }
type EmptyDir struct{} type EmptyDirVolumeSource struct{}
// Protocol defines network protocols supported for things like conatiner ports. // Protocol defines network protocols supported for things like conatiner ports.
type Protocol string type Protocol string
@ -199,12 +199,12 @@ const (
ProtocolUDP Protocol = "UDP" ProtocolUDP Protocol = "UDP"
) )
// GCEPersistentDisk represents a Persistent Disk resource in Google Compute Engine. // GCEPersistentDiskVolumeSource represents a Persistent Disk resource in Google Compute Engine.
// //
// A GCE PD must exist and be formatted before mounting to a container. // A GCE PD must exist and be formatted before mounting to a container.
// The disk must also be in the same GCE project and zone as the kubelet. // The disk must also be in the same GCE project and zone as the kubelet.
// A GCE PD can only be mounted as read/write once. // A GCE PD can only be mounted as read/write once.
type GCEPersistentDisk struct { type GCEPersistentDiskVolumeSource struct {
// Unique name of the PD resource. Used to identify the disk in GCE // Unique name of the PD resource. Used to identify the disk in GCE
PDName string `json:"pdName"` PDName string `json:"pdName"`
// Required: Filesystem type to mount. // Required: Filesystem type to mount.
@ -221,8 +221,8 @@ type GCEPersistentDisk struct {
ReadOnly bool `json:"readOnly,omitempty"` ReadOnly bool `json:"readOnly,omitempty"`
} }
// GitRepo represents a volume that is pulled from git when the pod is created. // GitRepoVolumeSource represents a volume that is pulled from git when the pod is created.
type GitRepo struct { type GitRepoVolumeSource struct {
// Repository URL // Repository URL
Repository string `json:"repository"` Repository string `json:"repository"`
// Commit hash, this is optional // Commit hash, this is optional
@ -230,11 +230,11 @@ type GitRepo struct {
// TODO: Consider credentials here. // TODO: Consider credentials here.
} }
// Adapts a Secret into a VolumeSource. // SecretVolumeSource adapts a Secret into a VolumeSource.
// //
// The contents of the target Secret's Data field will be presented in a volume // The contents of the target Secret's Data field will be presented in a volume
// as files using the keys in the Data field as the file names. // as files using the keys in the Data field as the file names.
type SecretSource struct { type SecretVolumeSource struct {
// Reference to a Secret // Reference to a Secret
Target ObjectReference `json:"target"` Target ObjectReference `json:"target"`
} }
@ -1343,7 +1343,8 @@ type Secret struct {
ObjectMeta `json:"metadata,omitempty"` ObjectMeta `json:"metadata,omitempty"`
// Data contains the secret data. Each key must be a valid DNS_SUBDOMAIN. // Data contains the secret data. Each key must be a valid DNS_SUBDOMAIN.
// The serialized form of the secret data is a base64 encoded string. // The serialized form of the secret data is a base64 encoded string,
// representing the arbitrary (possibly non-string) data value here.
Data map[string][]byte `json:"data,omitempty"` Data map[string][]byte `json:"data,omitempty"`
// Used to facilitate programatic handling of secret data. // Used to facilitate programatic handling of secret data.
@ -1355,7 +1356,7 @@ const MaxSecretSize = 1 * 1024 * 1024
type SecretType string type SecretType string
const ( const (
SecretTypeOpaque SecretType = "opaque" // Default; arbitrary user-defined data SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
) )
type SecretList struct { type SecretList struct {

View File

@ -28,7 +28,7 @@ func init() {
func(obj *Volume) { func(obj *Volume) {
if util.AllPtrFieldsNil(&obj.Source) { if util.AllPtrFieldsNil(&obj.Source) {
obj.Source = VolumeSource{ obj.Source = VolumeSource{
EmptyDir: &EmptyDir{}, EmptyDir: &EmptyDirVolumeSource{},
} }
} }
}, },

View File

@ -95,24 +95,24 @@ type VolumeSource struct {
// things that are allowed to see the host machine. Most containers will NOT need this. // things that are allowed to see the host machine. Most containers will NOT need this.
// TODO(jonesdl) We need to restrict who can use host directory mounts and // TODO(jonesdl) We need to restrict who can use host directory mounts and
// who can/can not mount host directories as read/write. // who can/can not mount host directories as read/write.
HostDir *HostPath `json:"hostDir" description:"pre-existing host file or directory; generally for privileged system daemons or other agents tied to the host"` HostDir *HostPathVolumeSource `json:"hostDir" description:"pre-existing host file or directory; generally for privileged system daemons or other agents tied to the host"`
// EmptyDir represents a temporary directory that shares a pod's lifetime. // EmptyDir represents a temporary directory that shares a pod's lifetime.
EmptyDir *EmptyDir `json:"emptyDir" description:"temporary directory that shares a pod's lifetime"` EmptyDir *EmptyDirVolumeSource `json:"emptyDir" description:"temporary directory that shares a pod's lifetime"`
// GCEPersistentDisk represents a GCE Disk resource that is attached to a // GCEPersistentDisk represents a GCE Disk resource that is attached to a
// kubelet's host machine and then exposed to the pod. // kubelet's host machine and then exposed to the pod.
GCEPersistentDisk *GCEPersistentDisk `json:"persistentDisk" description:"GCE disk resource attached to the host machine on demand"` GCEPersistentDisk *GCEPersistentDiskVolumeSource `json:"persistentDisk" description:"GCE disk resource attached to the host machine on demand"`
// GitRepo represents a git repository at a particular revision. // GitRepo represents a git repository at a particular revision.
GitRepo *GitRepo `json:"gitRepo" description:"git repository at a particular revision"` GitRepo *GitRepoVolumeSource `json:"gitRepo" description:"git repository at a particular revision"`
// Secret represents a secret to populate the volume with // Secret represents a secret to populate the volume with
Secret *SecretSource `json:"secret" description:"secret to populate volume with"` Secret *SecretVolumeSource `json:"secret" description:"secret to populate volume with"`
} }
// HostPath represents bare host directory volume. // HostPathVolumeSource represents bare host directory volume.
type HostPath struct { type HostPathVolumeSource struct {
Path string `json:"path" description:"path of the directory on the host"` Path string `json:"path" description:"path of the directory on the host"`
} }
type EmptyDir struct{} type EmptyDirVolumeSource struct{}
// Protocol defines network protocols supported for things like conatiner ports. // Protocol defines network protocols supported for things like conatiner ports.
type Protocol string type Protocol string
@ -124,12 +124,12 @@ const (
ProtocolUDP Protocol = "UDP" ProtocolUDP Protocol = "UDP"
) )
// GCEPersistentDisk represents a Persistent Disk resource in Google Compute Engine. // GCEPersistentDiskVolumeSource represents a Persistent Disk resource in Google Compute Engine.
// //
// A GCE PD must exist and be formatted before mounting to a container. // A GCE PD must exist and be formatted before mounting to a container.
// The disk must also be in the same GCE project and zone as the kubelet. // The disk must also be in the same GCE project and zone as the kubelet.
// A GCE PD can only be mounted as read/write once. // A GCE PD can only be mounted as read/write once.
type GCEPersistentDisk struct { type GCEPersistentDiskVolumeSource struct {
// Unique name of the PD resource. Used to identify the disk in GCE // Unique name of the PD resource. Used to identify the disk in GCE
PDName string `json:"pdName" description:"unique name of the PD resource in GCE"` PDName string `json:"pdName" description:"unique name of the PD resource in GCE"`
// Required: Filesystem type to mount. // Required: Filesystem type to mount.
@ -147,16 +147,16 @@ type GCEPersistentDisk struct {
ReadOnly bool `json:"readOnly,omitempty" description:"read-only if true, read-write otherwise (false or unspecified)"` ReadOnly bool `json:"readOnly,omitempty" description:"read-only if true, read-write otherwise (false or unspecified)"`
} }
// GitRepo represents a volume that is pulled from git when the pod is created. // GitRepoVolumeSource represents a volume that is pulled from git when the pod is created.
type GitRepo struct { type GitRepoVolumeSource struct {
// Repository URL // Repository URL
Repository string `json:"repository" description:"repository URL"` Repository string `json:"repository" description:"repository URL"`
// Commit hash, this is optional // Commit hash, this is optional
Revision string `json:"revision" description:"commit hash for the specified revision"` Revision string `json:"revision" description:"commit hash for the specified revision"`
} }
// Adapts a Secret into a VolumeSource // SecretVolumeSource adapts a Secret into a VolumeSource
type SecretSource struct { type SecretVolumeSource struct {
// Reference to a Secret // Reference to a Secret
Target ObjectReference `json:"target" description:"target is a reference to a secret"` Target ObjectReference `json:"target" description:"target is a reference to a secret"`
} }
@ -1115,7 +1115,8 @@ type Secret struct {
TypeMeta `json:",inline"` TypeMeta `json:",inline"`
// Data contains the secret data. Each key must be a valid DNS_SUBDOMAIN. // Data contains the secret data. Each key must be a valid DNS_SUBDOMAIN.
// The serialized form of the secret data is a base64 encoded string. // The serialized form of the secret data is a base64 encoded string,
// representing the arbitrary (possibly non-string) data value here.
Data map[string][]byte `json:"data,omitempty" description:"data contains the secret data. Each key must be a valid DNS_SUBDOMAIN. Each value must be a base64 encoded string"` Data map[string][]byte `json:"data,omitempty" description:"data contains the secret data. Each key must be a valid DNS_SUBDOMAIN. Each value must be a base64 encoded string"`
// Used to facilitate programatic handling of secret data. // Used to facilitate programatic handling of secret data.
@ -1127,7 +1128,7 @@ const MaxSecretSize = 1 * 1024 * 1024
type SecretType string type SecretType string
const ( const (
SecretTypeOpaque SecretType = "opaque" // Default; arbitrary user-defined data SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
) )
type SecretList struct { type SecretList struct {

View File

@ -30,7 +30,7 @@ func init() {
if util.AllPtrFieldsNil(&obj.Source) { if util.AllPtrFieldsNil(&obj.Source) {
glog.Errorf("Defaulting volume source for %v", obj) glog.Errorf("Defaulting volume source for %v", obj)
obj.Source = VolumeSource{ obj.Source = VolumeSource{
EmptyDir: &EmptyDir{}, EmptyDir: &EmptyDirVolumeSource{},
} }
} }
}, },

View File

@ -64,27 +64,27 @@ type VolumeSource struct {
// things that are allowed to see the host machine. Most containers will NOT need this. // things that are allowed to see the host machine. Most containers will NOT need this.
// TODO(jonesdl) We need to restrict who can use host directory mounts and // TODO(jonesdl) We need to restrict who can use host directory mounts and
// who can/can not mount host directories as read/write. // who can/can not mount host directories as read/write.
HostDir *HostPath `json:"hostDir" description:"pre-existing host file or directory; generally for privileged system daemons or other agents tied to the host"` HostDir *HostPathVolumeSource `json:"hostDir" description:"pre-existing host file or directory; generally for privileged system daemons or other agents tied to the host"`
// EmptyDir represents a temporary directory that shares a pod's lifetime. // EmptyDir represents a temporary directory that shares a pod's lifetime.
EmptyDir *EmptyDir `json:"emptyDir" description:"temporary directory that shares a pod's lifetime"` EmptyDir *EmptyDirVolumeSource `json:"emptyDir" description:"temporary directory that shares a pod's lifetime"`
// A persistent disk that is mounted to the // A persistent disk that is mounted to the
// kubelet's host machine and then exposed to the pod. // kubelet's host machine and then exposed to the pod.
GCEPersistentDisk *GCEPersistentDisk `json:"persistentDisk" description:"GCE disk resource attached to the host machine on demand"` GCEPersistentDisk *GCEPersistentDiskVolumeSource `json:"persistentDisk" description:"GCE disk resource attached to the host machine on demand"`
// GitRepo represents a git repository at a particular revision. // GitRepo represents a git repository at a particular revision.
GitRepo *GitRepo `json:"gitRepo" description:"git repository at a particular revision"` GitRepo *GitRepoVolumeSource `json:"gitRepo" description:"git repository at a particular revision"`
// Secret is a secret to populate the volume with // Secret is a secret to populate the volume with
Secret *SecretSource `json:"secret" description:"secret to populate volume"` Secret *SecretVolumeSource `json:"secret" description:"secret to populate volume"`
} }
// HostPath represents bare host directory volume. // HostPathVolumeSource represents bare host directory volume.
type HostPath struct { type HostPathVolumeSource struct {
Path string `json:"path" description:"path of the directory on the host"` Path string `json:"path" description:"path of the directory on the host"`
} }
type EmptyDir struct{} type EmptyDirVolumeSource struct{}
// Adapts a Secret into a VolumeSource // SecretVolumeSource adapts a Secret into a VolumeSource
type SecretSource struct { type SecretVolumeSource struct {
// Reference to a Secret // Reference to a Secret
Target ObjectReference `json:"target" description:"target is a reference to a secret"` Target ObjectReference `json:"target" description:"target is a reference to a secret"`
} }
@ -114,12 +114,12 @@ type ContainerPort struct {
HostIP string `json:"hostIP,omitempty" description:"host IP to bind the port to"` HostIP string `json:"hostIP,omitempty" description:"host IP to bind the port to"`
} }
// GCEPersistentDisk represents a Persistent Disk resource in Google Compute Engine. // GCEPersistentDiskVolumeSource represents a Persistent Disk resource in Google Compute Engine.
// //
// A GCE PD must exist and be formatted before mounting to a container. // A GCE PD must exist and be formatted before mounting to a container.
// The disk must also be in the same GCE project and zone as the kubelet. // The disk must also be in the same GCE project and zone as the kubelet.
// A GCE PD can only be mounted as read/write once. // A GCE PD can only be mounted as read/write once.
type GCEPersistentDisk struct { type GCEPersistentDiskVolumeSource struct {
// Unique name of the PD resource. Used to identify the disk in GCE // Unique name of the PD resource. Used to identify the disk in GCE
PDName string `json:"pdName" description:"unique name of the PD resource in GCE"` PDName string `json:"pdName" description:"unique name of the PD resource in GCE"`
// Required: Filesystem type to mount. // Required: Filesystem type to mount.
@ -137,8 +137,8 @@ type GCEPersistentDisk struct {
ReadOnly bool `json:"readOnly,omitempty" description:"read-only if true, read-write otherwise (false or unspecified)"` ReadOnly bool `json:"readOnly,omitempty" description:"read-only if true, read-write otherwise (false or unspecified)"`
} }
// GitRepo represents a volume that is pulled from git when the pod is created. // GitRepoVolumeSource represents a volume that is pulled from git when the pod is created.
type GitRepo struct { type GitRepoVolumeSource struct {
// Repository URL // Repository URL
Repository string `json:"repository" description:"repository URL"` Repository string `json:"repository" description:"repository URL"`
// Commit hash, this is optional // Commit hash, this is optional
@ -1118,7 +1118,8 @@ type Secret struct {
TypeMeta `json:",inline"` TypeMeta `json:",inline"`
// Data contains the secret data. Each key must be a valid DNS_SUBDOMAIN. // Data contains the secret data. Each key must be a valid DNS_SUBDOMAIN.
// The serialized form of the secret data is a base64 encoded string. // The serialized form of the secret data is a base64 encoded string,
// representing the arbitrary (possibly non-string) data value here.
Data map[string][]byte `json:"data,omitempty" description:"data contains the secret data. Each key must be a valid DNS_SUBDOMAIN. Each value must be a base64 encoded string"` Data map[string][]byte `json:"data,omitempty" description:"data contains the secret data. Each key must be a valid DNS_SUBDOMAIN. Each value must be a base64 encoded string"`
// Used to facilitate programatic handling of secret data. // Used to facilitate programatic handling of secret data.
@ -1130,7 +1131,7 @@ const MaxSecretSize = 1 * 1024 * 1024
type SecretType string type SecretType string
const ( const (
SecretTypeOpaque SecretType = "opaque" // Default; arbitrary user-defined data SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
) )
type SecretList struct { type SecretList struct {

View File

@ -28,7 +28,7 @@ func init() {
func(obj *Volume) { func(obj *Volume) {
if util.AllPtrFieldsNil(&obj.Source) { if util.AllPtrFieldsNil(&obj.Source) {
obj.Source = VolumeSource{ obj.Source = VolumeSource{
EmptyDir: &EmptyDir{}, EmptyDir: &EmptyDirVolumeSource{},
} }
} }
}, },

View File

@ -189,24 +189,24 @@ type VolumeSource struct {
// to see the host machine. Most containers will NOT need this. // to see the host machine. Most containers will NOT need this.
// TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not // TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not
// mount host directories as read/write. // mount host directories as read/write.
HostPath *HostPath `json:"hostPath"` HostPath *HostPathVolumeSource `json:"hostPath"`
// EmptyDir represents a temporary directory that shares a pod's lifetime. // EmptyDir represents a temporary directory that shares a pod's lifetime.
EmptyDir *EmptyDir `json:"emptyDir"` EmptyDir *EmptyDirVolumeSource `json:"emptyDir"`
// GCEPersistentDisk represents a GCE Disk resource that is attached to a // GCEPersistentDisk represents a GCE Disk resource that is attached to a
// kubelet's host machine and then exposed to the pod. // kubelet's host machine and then exposed to the pod.
GCEPersistentDisk *GCEPersistentDisk `json:"gcePersistentDisk"` GCEPersistentDisk *GCEPersistentDiskVolumeSource `json:"gcePersistentDisk"`
// GitRepo represents a git repository at a particular revision. // GitRepo represents a git repository at a particular revision.
GitRepo *GitRepo `json:"gitRepo"` GitRepo *GitRepoVolumeSource `json:"gitRepo"`
// Secret represents a secret that should populate this volume. // Secret represents a secret that should populate this volume.
Secret *SecretSource `json:"secret"` Secret *SecretVolumeSource `json:"secret"`
} }
// HostPath represents bare host directory volume. // HostPathVolumeSource represents bare host directory volume.
type HostPath struct { type HostPathVolumeSource struct {
Path string `json:"path"` Path string `json:"path"`
} }
type EmptyDir struct{} type EmptyDirVolumeSource struct{}
// Protocol defines network protocols supported for things like conatiner ports. // Protocol defines network protocols supported for things like conatiner ports.
type Protocol string type Protocol string
@ -218,12 +218,12 @@ const (
ProtocolUDP Protocol = "UDP" ProtocolUDP Protocol = "UDP"
) )
// GCEPersistentDisk represents a Persistent Disk resource in Google Compute Engine. // GCEPersistentDiskVolumeSource represents a Persistent Disk resource in Google Compute Engine.
// //
// A GCE PD must exist and be formatted before mounting to a container. // A GCE PD must exist and be formatted before mounting to a container.
// The disk must also be in the same GCE project and zone as the kubelet. // The disk must also be in the same GCE project and zone as the kubelet.
// A GCE PD can only be mounted as read/write once. // A GCE PD can only be mounted as read/write once.
type GCEPersistentDisk struct { type GCEPersistentDiskVolumeSource struct {
// Unique name of the PD resource. Used to identify the disk in GCE // Unique name of the PD resource. Used to identify the disk in GCE
PDName string `json:"pdName"` PDName string `json:"pdName"`
// Required: Filesystem type to mount. // Required: Filesystem type to mount.
@ -240,16 +240,16 @@ type GCEPersistentDisk struct {
ReadOnly bool `json:"readOnly,omitempty"` ReadOnly bool `json:"readOnly,omitempty"`
} }
// GitRepo represents a volume that is pulled from git when the pod is created. // GitRepoVolumeSource represents a volume that is pulled from git when the pod is created.
type GitRepo struct { type GitRepoVolumeSource struct {
// Repository URL // Repository URL
Repository string `json:"repository"` Repository string `json:"repository"`
// Commit hash, this is optional // Commit hash, this is optional
Revision string `json:"revision"` Revision string `json:"revision"`
} }
// Adapts a Secret into a VolumeSource // SecretVolumeSource adapts a Secret into a VolumeSource
type SecretSource struct { type SecretVolumeSource struct {
// Reference to a Secret // Reference to a Secret
Target ObjectReference `json:"target" description:"target is a reference to a secret"` Target ObjectReference `json:"target" description:"target is a reference to a secret"`
} }
@ -1279,7 +1279,8 @@ type Secret struct {
ObjectMeta `json:"metadata,omitempty"` ObjectMeta `json:"metadata,omitempty"`
// Data contains the secret data. Each key must be a valid DNS_SUBDOMAIN. // Data contains the secret data. Each key must be a valid DNS_SUBDOMAIN.
// The serialized form of the secret data is a base64 encoded string. // The serialized form of the secret data is a base64 encoded string,
// representing the arbitrary (possibly non-string) data value here.
Data map[string][]byte `json:"data,omitempty" description:"data contains the secret data. Each key must be a valid DNS_SUBDOMAIN. Each value must be a base64 encoded string"` Data map[string][]byte `json:"data,omitempty" description:"data contains the secret data. Each key must be a valid DNS_SUBDOMAIN. Each value must be a base64 encoded string"`
// Used to facilitate programatic handling of secret data. // Used to facilitate programatic handling of secret data.
@ -1291,7 +1292,7 @@ const MaxSecretSize = 1 * 1024 * 1024
type SecretType string type SecretType string
const ( const (
SecretTypeOpaque SecretType = "opaque" // Default; arbitrary user-defined data SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
) )
type SecretList struct { type SecretList struct {

View File

@ -116,6 +116,28 @@ func ValidateNamespaceName(name string, prefix bool) (bool, string) {
return nameIsDNSSubdomain(name, prefix) return nameIsDNSSubdomain(name, prefix)
} }
// ValidateLimitRangeName can be used to check whether the given limit range name is valid.
// Prefix indicates this name will be used as part of generation, in which case
// trailing dashes are allowed.
func ValidateLimitRangeName(name string, prefix bool) (bool, string) {
return nameIsDNSSubdomain(name, prefix)
}
// ValidateResourceQuotaName can be used to check whether the given
// resource quota name is valid.
// Prefix indicates this name will be used as part of generation, in which case
// trailing dashes are allowed.
func ValidateResourceQuotaName(name string, prefix bool) (bool, string) {
return nameIsDNSSubdomain(name, prefix)
}
// ValidateSecretName can be used to check whether the given secret name is valid.
// Prefix indicates this name will be used as part of generation, in which case
// trailing dashes are allowed.
func ValidateSecretName(name string, prefix bool) (bool, string) {
return nameIsDNSSubdomain(name, prefix)
}
// nameIsDNSSubdomain is a ValidateNameFunc for names that must be a DNS subdomain. // nameIsDNSSubdomain is a ValidateNameFunc for names that must be a DNS subdomain.
func nameIsDNSSubdomain(name string, prefix bool) (bool, string) { func nameIsDNSSubdomain(name string, prefix bool) (bool, string) {
if prefix { if prefix {
@ -233,7 +255,7 @@ func validateSource(source *api.VolumeSource) errs.ValidationErrorList {
allErrs := errs.ValidationErrorList{} allErrs := errs.ValidationErrorList{}
if source.HostPath != nil { if source.HostPath != nil {
numVolumes++ numVolumes++
allErrs = append(allErrs, validateHostPath(source.HostPath).Prefix("hostPath")...) allErrs = append(allErrs, validateHostPathVolumeSource(source.HostPath).Prefix("hostPath")...)
} }
if source.EmptyDir != nil { if source.EmptyDir != nil {
numVolumes++ numVolumes++
@ -241,15 +263,15 @@ func validateSource(source *api.VolumeSource) errs.ValidationErrorList {
} }
if source.GitRepo != nil { if source.GitRepo != nil {
numVolumes++ numVolumes++
allErrs = append(allErrs, validateGitRepo(source.GitRepo).Prefix("gitRepo")...) allErrs = append(allErrs, validateGitRepoVolumeSource(source.GitRepo).Prefix("gitRepo")...)
} }
if source.GCEPersistentDisk != nil { if source.GCEPersistentDisk != nil {
numVolumes++ numVolumes++
allErrs = append(allErrs, validateGCEPersistentDisk(source.GCEPersistentDisk).Prefix("persistentDisk")...) allErrs = append(allErrs, validateGCEPersistentDiskVolumeSource(source.GCEPersistentDisk).Prefix("persistentDisk")...)
} }
if source.Secret != nil { if source.Secret != nil {
numVolumes++ numVolumes++
allErrs = append(allErrs, validateSecretSource(source.Secret).Prefix("secret")...) allErrs = append(allErrs, validateSecretVolumeSource(source.Secret).Prefix("secret")...)
} }
if numVolumes != 1 { if numVolumes != 1 {
allErrs = append(allErrs, errs.NewFieldInvalid("", source, "exactly 1 volume type is required")) allErrs = append(allErrs, errs.NewFieldInvalid("", source, "exactly 1 volume type is required"))
@ -257,7 +279,7 @@ func validateSource(source *api.VolumeSource) errs.ValidationErrorList {
return allErrs return allErrs
} }
func validateHostPath(hostDir *api.HostPath) errs.ValidationErrorList { func validateHostPathVolumeSource(hostDir *api.HostPathVolumeSource) errs.ValidationErrorList {
allErrs := errs.ValidationErrorList{} allErrs := errs.ValidationErrorList{}
if hostDir.Path == "" { if hostDir.Path == "" {
allErrs = append(allErrs, errs.NewFieldRequired("path", hostDir.Path)) allErrs = append(allErrs, errs.NewFieldRequired("path", hostDir.Path))
@ -265,7 +287,7 @@ func validateHostPath(hostDir *api.HostPath) errs.ValidationErrorList {
return allErrs return allErrs
} }
func validateGitRepo(gitRepo *api.GitRepo) errs.ValidationErrorList { func validateGitRepoVolumeSource(gitRepo *api.GitRepoVolumeSource) errs.ValidationErrorList {
allErrs := errs.ValidationErrorList{} allErrs := errs.ValidationErrorList{}
if gitRepo.Repository == "" { if gitRepo.Repository == "" {
allErrs = append(allErrs, errs.NewFieldRequired("repository", gitRepo.Repository)) allErrs = append(allErrs, errs.NewFieldRequired("repository", gitRepo.Repository))
@ -273,7 +295,7 @@ func validateGitRepo(gitRepo *api.GitRepo) errs.ValidationErrorList {
return allErrs return allErrs
} }
func validateGCEPersistentDisk(PD *api.GCEPersistentDisk) errs.ValidationErrorList { func validateGCEPersistentDiskVolumeSource(PD *api.GCEPersistentDiskVolumeSource) errs.ValidationErrorList {
allErrs := errs.ValidationErrorList{} allErrs := errs.ValidationErrorList{}
if PD.PDName == "" { if PD.PDName == "" {
allErrs = append(allErrs, errs.NewFieldRequired("pdName", PD.PDName)) allErrs = append(allErrs, errs.NewFieldRequired("pdName", PD.PDName))
@ -287,7 +309,7 @@ func validateGCEPersistentDisk(PD *api.GCEPersistentDisk) errs.ValidationErrorLi
return allErrs return allErrs
} }
func validateSecretSource(secretSource *api.SecretSource) errs.ValidationErrorList { func validateSecretVolumeSource(secretSource *api.SecretVolumeSource) errs.ValidationErrorList {
allErrs := errs.ValidationErrorList{} allErrs := errs.ValidationErrorList{}
if secretSource.Target.Name == "" { if secretSource.Target.Name == "" {
allErrs = append(allErrs, errs.NewFieldRequired("target.name", "")) allErrs = append(allErrs, errs.NewFieldRequired("target.name", ""))
@ -815,16 +837,8 @@ func validateResourceName(value string, field string) errs.ValidationErrorList {
// ValidateLimitRange tests if required fields in the LimitRange are set. // ValidateLimitRange tests if required fields in the LimitRange are set.
func ValidateLimitRange(limitRange *api.LimitRange) errs.ValidationErrorList { func ValidateLimitRange(limitRange *api.LimitRange) errs.ValidationErrorList {
allErrs := errs.ValidationErrorList{} allErrs := errs.ValidationErrorList{}
if len(limitRange.Name) == 0 { allErrs = append(allErrs, ValidateObjectMeta(&limitRange.ObjectMeta, true, ValidateLimitRangeName).Prefix("metadata")...)
allErrs = append(allErrs, errs.NewFieldRequired("name", limitRange.Name))
} else if !util.IsDNSSubdomain(limitRange.Name) {
allErrs = append(allErrs, errs.NewFieldInvalid("name", limitRange.Name, dnsSubdomainErrorMsg))
}
if len(limitRange.Namespace) == 0 {
allErrs = append(allErrs, errs.NewFieldRequired("namespace", limitRange.Namespace))
} else if !util.IsDNSSubdomain(limitRange.Namespace) {
allErrs = append(allErrs, errs.NewFieldInvalid("namespace", limitRange.Namespace, dnsSubdomainErrorMsg))
}
// ensure resource names are properly qualified per docs/resources.md // ensure resource names are properly qualified per docs/resources.md
for i := range limitRange.Spec.Limits { for i := range limitRange.Spec.Limits {
limit := limitRange.Spec.Limits[i] limit := limitRange.Spec.Limits[i]
@ -841,21 +855,12 @@ func ValidateLimitRange(limitRange *api.LimitRange) errs.ValidationErrorList {
// ValidateSecret tests if required fields in the Secret are set. // ValidateSecret tests if required fields in the Secret are set.
func ValidateSecret(secret *api.Secret) errs.ValidationErrorList { func ValidateSecret(secret *api.Secret) errs.ValidationErrorList {
allErrs := errs.ValidationErrorList{} allErrs := errs.ValidationErrorList{}
if len(secret.Name) == 0 { allErrs = append(allErrs, ValidateObjectMeta(&secret.ObjectMeta, true, ValidateSecretName).Prefix("metadata")...)
allErrs = append(allErrs, errs.NewFieldRequired("name", secret.Name))
} else if !util.IsDNSSubdomain(secret.Name) {
allErrs = append(allErrs, errs.NewFieldInvalid("name", secret.Name, ""))
}
if len(secret.Namespace) == 0 {
allErrs = append(allErrs, errs.NewFieldRequired("namespace", secret.Namespace))
} else if !util.IsDNSSubdomain(secret.Namespace) {
allErrs = append(allErrs, errs.NewFieldInvalid("namespace", secret.Namespace, ""))
}
totalSize := 0 totalSize := 0
for key, value := range secret.Data { for key, value := range secret.Data {
if !util.IsDNSSubdomain(key) { if !util.IsDNSSubdomain(key) {
allErrs = append(allErrs, errs.NewFieldInvalid(fmt.Sprintf("data[%v]", key), key, cIdentifierErrorMsg)) allErrs = append(allErrs, errs.NewFieldInvalid(fmt.Sprintf("data[%s]", key), key, cIdentifierErrorMsg))
} }
totalSize += len(value) totalSize += len(value)
@ -893,16 +898,8 @@ func validateResourceRequirements(container *api.Container) errs.ValidationError
// ValidateResourceQuota tests if required fields in the ResourceQuota are set. // ValidateResourceQuota tests if required fields in the ResourceQuota are set.
func ValidateResourceQuota(resourceQuota *api.ResourceQuota) errs.ValidationErrorList { func ValidateResourceQuota(resourceQuota *api.ResourceQuota) errs.ValidationErrorList {
allErrs := errs.ValidationErrorList{} allErrs := errs.ValidationErrorList{}
if len(resourceQuota.Name) == 0 { allErrs = append(allErrs, ValidateObjectMeta(&resourceQuota.ObjectMeta, true, ValidateResourceQuotaName).Prefix("metadata")...)
allErrs = append(allErrs, errs.NewFieldRequired("name", resourceQuota.Name))
} else if !util.IsDNSSubdomain(resourceQuota.Name) {
allErrs = append(allErrs, errs.NewFieldInvalid("name", resourceQuota.Name, dnsSubdomainErrorMsg))
}
if len(resourceQuota.Namespace) == 0 {
allErrs = append(allErrs, errs.NewFieldRequired("namespace", resourceQuota.Namespace))
} else if !util.IsDNSSubdomain(resourceQuota.Namespace) {
allErrs = append(allErrs, errs.NewFieldInvalid("namespace", resourceQuota.Namespace, dnsSubdomainErrorMsg))
}
for k := range resourceQuota.Spec.Hard { for k := range resourceQuota.Spec.Hard {
allErrs = append(allErrs, validateResourceName(string(k), string(resourceQuota.TypeMeta.Kind))...) allErrs = append(allErrs, validateResourceName(string(k), string(resourceQuota.TypeMeta.Kind))...)
} }

View File

@ -147,13 +147,13 @@ func TestValidateAnnotations(t *testing.T) {
func TestValidateVolumes(t *testing.T) { func TestValidateVolumes(t *testing.T) {
successCase := []api.Volume{ successCase := []api.Volume{
{Name: "abc", Source: api.VolumeSource{HostPath: &api.HostPath{"/mnt/path1"}}}, {Name: "abc", Source: api.VolumeSource{HostPath: &api.HostPathVolumeSource{"/mnt/path1"}}},
{Name: "123", Source: api.VolumeSource{HostPath: &api.HostPath{"/mnt/path2"}}}, {Name: "123", Source: api.VolumeSource{HostPath: &api.HostPathVolumeSource{"/mnt/path2"}}},
{Name: "abc-123", Source: api.VolumeSource{HostPath: &api.HostPath{"/mnt/path3"}}}, {Name: "abc-123", Source: api.VolumeSource{HostPath: &api.HostPathVolumeSource{"/mnt/path3"}}},
{Name: "empty", Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}, {Name: "empty", Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
{Name: "gcepd", Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDisk{"my-PD", "ext4", 1, false}}}, {Name: "gcepd", Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{"my-PD", "ext4", 1, false}}},
{Name: "gitrepo", Source: api.VolumeSource{GitRepo: &api.GitRepo{"my-repo", "hashstring"}}}, {Name: "gitrepo", Source: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{"my-repo", "hashstring"}}},
{Name: "secret", Source: api.VolumeSource{Secret: &api.SecretSource{api.ObjectReference{Namespace: api.NamespaceDefault, Name: "my-secret", Kind: "Secret"}}}}, {Name: "secret", Source: api.VolumeSource{Secret: &api.SecretVolumeSource{api.ObjectReference{Namespace: api.NamespaceDefault, Name: "my-secret", Kind: "Secret"}}}},
} }
names, errs := validateVolumes(successCase) names, errs := validateVolumes(successCase)
if len(errs) != 0 { if len(errs) != 0 {
@ -162,7 +162,7 @@ func TestValidateVolumes(t *testing.T) {
if len(names) != len(successCase) || !names.HasAll("abc", "123", "abc-123", "empty", "gcepd", "gitrepo", "secret") { if len(names) != len(successCase) || !names.HasAll("abc", "123", "abc-123", "empty", "gcepd", "gitrepo", "secret") {
t.Errorf("wrong names result: %v", names) t.Errorf("wrong names result: %v", names)
} }
emptyVS := api.VolumeSource{EmptyDir: &api.EmptyDir{}} emptyVS := api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}
errorCases := map[string]struct { errorCases := map[string]struct {
V []api.Volume V []api.Volume
T errors.ValidationErrorType T errors.ValidationErrorType
@ -573,8 +573,8 @@ func TestValidateManifest(t *testing.T) {
{ {
Version: "v1beta1", Version: "v1beta1",
ID: "abc", ID: "abc",
Volumes: []api.Volume{{Name: "vol1", Source: api.VolumeSource{HostPath: &api.HostPath{"/mnt/vol1"}}}, Volumes: []api.Volume{{Name: "vol1", Source: api.VolumeSource{HostPath: &api.HostPathVolumeSource{"/mnt/vol1"}}},
{Name: "vol2", Source: api.VolumeSource{HostPath: &api.HostPath{"/mnt/vol2"}}}}, {Name: "vol2", Source: api.VolumeSource{HostPath: &api.HostPathVolumeSource{"/mnt/vol2"}}}},
Containers: []api.Container{ Containers: []api.Container{
{ {
Name: "abc", Name: "abc",
@ -624,7 +624,7 @@ func TestValidateManifest(t *testing.T) {
"invalid volume name": { "invalid volume name": {
Version: "v1beta1", Version: "v1beta1",
ID: "abc", ID: "abc",
Volumes: []api.Volume{{Name: "vol.1", Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}}, Volumes: []api.Volume{{Name: "vol.1", Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}},
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
DNSPolicy: api.DNSClusterFirst, DNSPolicy: api.DNSClusterFirst,
}, },
@ -647,14 +647,14 @@ func TestValidateManifest(t *testing.T) {
func TestValidatePodSpec(t *testing.T) { func TestValidatePodSpec(t *testing.T) {
successCases := []api.PodSpec{ successCases := []api.PodSpec{
{ // Populate basic fields, leave defaults for most. { // Populate basic fields, leave defaults for most.
Volumes: []api.Volume{{Name: "vol", Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}}, Volumes: []api.Volume{{Name: "vol", Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}},
Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
DNSPolicy: api.DNSClusterFirst, DNSPolicy: api.DNSClusterFirst,
}, },
{ // Populate all fields. { // Populate all fields.
Volumes: []api.Volume{ Volumes: []api.Volume{
{Name: "vol", Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}, {Name: "vol", Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
}, },
Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
@ -703,7 +703,7 @@ func TestValidatePod(t *testing.T) {
{ // Basic fields. { // Basic fields.
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"}, ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"},
Spec: api.PodSpec{ Spec: api.PodSpec{
Volumes: []api.Volume{{Name: "vol", Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}}, Volumes: []api.Volume{{Name: "vol", Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}},
Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
DNSPolicy: api.DNSClusterFirst, DNSPolicy: api.DNSClusterFirst,
@ -713,7 +713,7 @@ func TestValidatePod(t *testing.T) {
ObjectMeta: api.ObjectMeta{Name: "abc.123.do-re-mi", Namespace: "ns"}, ObjectMeta: api.ObjectMeta{Name: "abc.123.do-re-mi", Namespace: "ns"},
Spec: api.PodSpec{ Spec: api.PodSpec{
Volumes: []api.Volume{ Volumes: []api.Volume{
{Name: "vol", Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}, {Name: "vol", Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
}, },
Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
@ -1005,7 +1005,7 @@ func TestValidateBoundPods(t *testing.T) {
{ // Basic fields. { // Basic fields.
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"}, ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"},
Spec: api.PodSpec{ Spec: api.PodSpec{
Volumes: []api.Volume{{Name: "vol", Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}}, Volumes: []api.Volume{{Name: "vol", Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}},
Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
DNSPolicy: api.DNSClusterFirst, DNSPolicy: api.DNSClusterFirst,
@ -1015,7 +1015,7 @@ func TestValidateBoundPods(t *testing.T) {
ObjectMeta: api.ObjectMeta{Name: "abc.123.do-re-mi", Namespace: "ns"}, ObjectMeta: api.ObjectMeta{Name: "abc.123.do-re-mi", Namespace: "ns"},
Spec: api.PodSpec{ Spec: api.PodSpec{
Volumes: []api.Volume{ Volumes: []api.Volume{
{Name: "vol", Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}, {Name: "vol", Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
}, },
Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}},
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
@ -1477,7 +1477,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
Spec: api.PodSpec{ Spec: api.PodSpec{
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
DNSPolicy: api.DNSClusterFirst, DNSPolicy: api.DNSClusterFirst,
Volumes: []api.Volume{{Name: "gcepd", Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDisk{"my-PD", "ext4", 1, false}}}}, Volumes: []api.Volume{{Name: "gcepd", Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{"my-PD", "ext4", 1, false}}}},
}, },
}, },
} }
@ -1635,7 +1635,7 @@ func TestValidateReplicationController(t *testing.T) {
Labels: validSelector, Labels: validSelector,
}, },
Spec: api.PodSpec{ Spec: api.PodSpec{
Volumes: []api.Volume{{Name: "gcepd", Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDisk{"my-PD", "ext4", 1, false}}}}, Volumes: []api.Volume{{Name: "gcepd", Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{"my-PD", "ext4", 1, false}}}},
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
DNSPolicy: api.DNSClusterFirst, DNSPolicy: api.DNSClusterFirst,
}, },
@ -2302,8 +2302,7 @@ func TestValidateLimitRange(t *testing.T) {
for i := range errs { for i := range errs {
field := errs[i].(*errors.ValidationError).Field field := errs[i].(*errors.ValidationError).Field
detail := errs[i].(*errors.ValidationError).Detail detail := errs[i].(*errors.ValidationError).Detail
if field != "name" && if field != "metadata.name" && field != "metadata.namespace" {
field != "namespace" {
t.Errorf("%s: missing prefix for: %v", k, errs[i]) t.Errorf("%s: missing prefix for: %v", k, errs[i])
} }
if detail != v.D { if detail != v.D {
@ -2370,8 +2369,7 @@ func TestValidateResourceQuota(t *testing.T) {
for i := range errs { for i := range errs {
field := errs[i].(*errors.ValidationError).Field field := errs[i].(*errors.ValidationError).Field
detail := errs[i].(*errors.ValidationError).Detail detail := errs[i].(*errors.ValidationError).Detail
if field != "name" && if field != "metadata.name" && field != "metadata.namespace" {
field != "namespace" {
t.Errorf("%s: missing prefix for: %v", k, errs[i]) t.Errorf("%s: missing prefix for: %v", k, errs[i])
} }
if detail != v.D { if detail != v.D {

View File

@ -89,11 +89,11 @@ func TestMerge(t *testing.T) {
Volumes: []api.Volume{ Volumes: []api.Volume{
{ {
Name: "v1", Name: "v1",
Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}, Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}},
}, },
{ {
Name: "v2", Name: "v2",
Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}, Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}},
}, },
}, },
RestartPolicy: api.RestartPolicy{ RestartPolicy: api.RestartPolicy{

View File

@ -47,7 +47,7 @@ func ExampleManifestAndPod(id string) (v1beta1.ContainerManifest, api.BoundPod)
{ {
Name: "host-dir", Name: "host-dir",
Source: v1beta1.VolumeSource{ Source: v1beta1.VolumeSource{
HostDir: &v1beta1.HostPath{"/dir/path"}, HostDir: &v1beta1.HostPathVolumeSource{"/dir/path"},
}, },
}, },
}, },
@ -68,7 +68,7 @@ func ExampleManifestAndPod(id string) (v1beta1.ContainerManifest, api.BoundPod)
{ {
Name: "host-dir", Name: "host-dir",
Source: api.VolumeSource{ Source: api.VolumeSource{
HostPath: &api.HostPath{"/dir/path"}, HostPath: &api.HostPathVolumeSource{"/dir/path"},
}, },
}, },
}, },

View File

@ -36,7 +36,7 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/empty-dir" { if plug.Name() != "kubernetes.io/empty-dir" {
t.Errorf("Wrong name: %s", plug.Name()) t.Errorf("Wrong name: %s", plug.Name())
} }
if !plug.CanSupport(&api.Volume{Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}) { if !plug.CanSupport(&api.Volume{Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}) {
t.Errorf("Expected true") t.Errorf("Expected true")
} }
if !plug.CanSupport(&api.Volume{Source: api.VolumeSource{}}) { if !plug.CanSupport(&api.Volume{Source: api.VolumeSource{}}) {
@ -54,7 +54,7 @@ func TestPlugin(t *testing.T) {
} }
spec := &api.Volume{ spec := &api.Volume{
Name: "vol1", Name: "vol1",
Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}, Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}},
} }
builder, err := plug.NewBuilder(spec, types.UID("poduid")) builder, err := plug.NewBuilder(spec, types.UID("poduid"))
if err != nil { if err != nil {
@ -134,11 +134,11 @@ func TestPluginLegacy(t *testing.T) {
if plug.Name() != "empty" { if plug.Name() != "empty" {
t.Errorf("Wrong name: %s", plug.Name()) t.Errorf("Wrong name: %s", plug.Name())
} }
if plug.CanSupport(&api.Volume{Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}) { if plug.CanSupport(&api.Volume{Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}) {
t.Errorf("Expected false") t.Errorf("Expected false")
} }
if _, err := plug.NewBuilder(&api.Volume{Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}, types.UID("poduid")); err == nil { if _, err := plug.NewBuilder(&api.Volume{Source: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}, types.UID("poduid")); err == nil {
t.Errorf("Expected failiure") t.Errorf("Expected failiure")
} }

View File

@ -37,7 +37,7 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/gce-pd" { if plug.Name() != "kubernetes.io/gce-pd" {
t.Errorf("Wrong name: %s", plug.Name()) t.Errorf("Wrong name: %s", plug.Name())
} }
if !plug.CanSupport(&api.Volume{Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDisk{}}}) { if !plug.CanSupport(&api.Volume{Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}}) {
t.Errorf("Expected true") t.Errorf("Expected true")
} }
} }
@ -89,7 +89,7 @@ func TestPlugin(t *testing.T) {
spec := &api.Volume{ spec := &api.Volume{
Name: "vol1", Name: "vol1",
Source: api.VolumeSource{ Source: api.VolumeSource{
GCEPersistentDisk: &api.GCEPersistentDisk{ GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{
PDName: "pd", PDName: "pd",
FSType: "ext4", FSType: "ext4",
}, },
@ -155,11 +155,11 @@ func TestPluginLegacy(t *testing.T) {
if plug.Name() != "gce-pd" { if plug.Name() != "gce-pd" {
t.Errorf("Wrong name: %s", plug.Name()) t.Errorf("Wrong name: %s", plug.Name())
} }
if plug.CanSupport(&api.Volume{Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDisk{}}}) { if plug.CanSupport(&api.Volume{Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}}) {
t.Errorf("Expected false") t.Errorf("Expected false")
} }
if _, err := plug.NewBuilder(&api.Volume{Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDisk{}}}, types.UID("poduid")); err == nil { if _, err := plug.NewBuilder(&api.Volume{Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}}, types.UID("poduid")); err == nil {
t.Errorf("Expected failiure") t.Errorf("Expected failiure")
} }

View File

@ -49,7 +49,7 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/git-repo" { if plug.Name() != "kubernetes.io/git-repo" {
t.Errorf("Wrong name: %s", plug.Name()) t.Errorf("Wrong name: %s", plug.Name())
} }
if !plug.CanSupport(&api.Volume{Source: api.VolumeSource{GitRepo: &api.GitRepo{}}}) { if !plug.CanSupport(&api.Volume{Source: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}}) {
t.Errorf("Expected true") t.Errorf("Expected true")
} }
} }
@ -111,7 +111,7 @@ func TestPlugin(t *testing.T) {
spec := &api.Volume{ spec := &api.Volume{
Name: "vol1", Name: "vol1",
Source: api.VolumeSource{ Source: api.VolumeSource{
GitRepo: &api.GitRepo{ GitRepo: &api.GitRepoVolumeSource{
Repository: "https://github.com/GoogleCloudPlatform/kubernetes.git", Repository: "https://github.com/GoogleCloudPlatform/kubernetes.git",
Revision: "2a30ce65c5ab586b98916d83385c5983edd353a1", Revision: "2a30ce65c5ab586b98916d83385c5983edd353a1",
}, },
@ -168,11 +168,11 @@ func TestPluginLegacy(t *testing.T) {
if plug.Name() != "git" { if plug.Name() != "git" {
t.Errorf("Wrong name: %s", plug.Name()) t.Errorf("Wrong name: %s", plug.Name())
} }
if plug.CanSupport(&api.Volume{Source: api.VolumeSource{GitRepo: &api.GitRepo{}}}) { if plug.CanSupport(&api.Volume{Source: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}}) {
t.Errorf("Expected false") t.Errorf("Expected false")
} }
if _, err := plug.NewBuilder(&api.Volume{Source: api.VolumeSource{GitRepo: &api.GitRepo{}}}, types.UID("poduid")); err == nil { if _, err := plug.NewBuilder(&api.Volume{Source: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}}, types.UID("poduid")); err == nil {
t.Errorf("Expected failiure") t.Errorf("Expected failiure")
} }

View File

@ -35,7 +35,7 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/host-path" { if plug.Name() != "kubernetes.io/host-path" {
t.Errorf("Wrong name: %s", plug.Name()) t.Errorf("Wrong name: %s", plug.Name())
} }
if !plug.CanSupport(&api.Volume{Source: api.VolumeSource{HostPath: &api.HostPath{}}}) { if !plug.CanSupport(&api.Volume{Source: api.VolumeSource{HostPath: &api.HostPathVolumeSource{}}}) {
t.Errorf("Expected true") t.Errorf("Expected true")
} }
if plug.CanSupport(&api.Volume{Source: api.VolumeSource{}}) { if plug.CanSupport(&api.Volume{Source: api.VolumeSource{}}) {
@ -53,7 +53,7 @@ func TestPlugin(t *testing.T) {
} }
spec := &api.Volume{ spec := &api.Volume{
Name: "vol1", Name: "vol1",
Source: api.VolumeSource{HostPath: &api.HostPath{"/vol1"}}, Source: api.VolumeSource{HostPath: &api.HostPathVolumeSource{"/vol1"}},
} }
builder, err := plug.NewBuilder(spec, types.UID("poduid")) builder, err := plug.NewBuilder(spec, types.UID("poduid"))
if err != nil { if err != nil {

View File

@ -50,7 +50,7 @@ func TestCanSupport(t *testing.T) {
if plugin.Name() != secretPluginName { if plugin.Name() != secretPluginName {
t.Errorf("Wrong name: %s", plugin.Name()) t.Errorf("Wrong name: %s", plugin.Name())
} }
if !plugin.CanSupport(&api.Volume{Source: api.VolumeSource{Secret: &api.SecretSource{Target: api.ObjectReference{}}}}) { if !plugin.CanSupport(&api.Volume{Source: api.VolumeSource{Secret: &api.SecretVolumeSource{Target: api.ObjectReference{}}}}) {
t.Errorf("Expected true") t.Errorf("Expected true")
} }
} }
@ -66,7 +66,7 @@ func TestPlugin(t *testing.T) {
volumeSpec := &api.Volume{ volumeSpec := &api.Volume{
Name: testVolumeName, Name: testVolumeName,
Source: api.VolumeSource{ Source: api.VolumeSource{
Secret: &api.SecretSource{ Secret: &api.SecretVolumeSource{
Target: api.ObjectReference{ Target: api.ObjectReference{
Namespace: testNamespace, Namespace: testNamespace,
Name: testName, Name: testName,

View File

@ -277,7 +277,7 @@ func TestDiskConflicts(t *testing.T) {
Volumes: []api.Volume{ Volumes: []api.Volume{
{ {
Source: api.VolumeSource{ Source: api.VolumeSource{
GCEPersistentDisk: &api.GCEPersistentDisk{ GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{
PDName: "foo", PDName: "foo",
}, },
}, },
@ -288,7 +288,7 @@ func TestDiskConflicts(t *testing.T) {
Volumes: []api.Volume{ Volumes: []api.Volume{
{ {
Source: api.VolumeSource{ Source: api.VolumeSource{
GCEPersistentDisk: &api.GCEPersistentDisk{ GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{
PDName: "bar", PDName: "bar",
}, },
}, },

View File

@ -82,7 +82,7 @@ var _ = Describe("Secrets", func() {
{ {
Name: volumeName, Name: volumeName,
Source: api.VolumeSource{ Source: api.VolumeSource{
Secret: &api.SecretSource{ Secret: &api.SecretVolumeSource{
Target: api.ObjectReference{ Target: api.ObjectReference{
Kind: "Secret", Kind: "Secret",
Namespace: ns, Namespace: ns,

View File

@ -76,7 +76,7 @@ var _ = Describe("Services", func() {
{ {
Name: "results", Name: "results",
Source: api.VolumeSource{ Source: api.VolumeSource{
EmptyDir: &api.EmptyDir{}, EmptyDir: &api.EmptyDirVolumeSource{},
}, },
}, },
}, },