move StorageClass to its own group
This commit is contained in:
parent
008fc22d31
commit
cd5b6cc491
@ -42,6 +42,7 @@ var (
|
||||
"certificates/",
|
||||
"extensions/",
|
||||
"rbac/",
|
||||
"storage/",
|
||||
}, "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\". Default to \"api/,extensions/,autoscaling/,batch/,rbac/\"")
|
||||
includedTypesOverrides = flag.StringSlice("included-types-overrides", []string{}, "list of group/version/type for which client should be generated. By default, client is generated for all types which have genclient=true in types.go. This overrides that. For each groupVersion in this list, only the types mentioned here will be included. The default check of genclient=true will be used for other group versions.")
|
||||
basePath = flag.String("input-base", "k8s.io/kubernetes/pkg/apis", "base path to look for the api group. Default to \"k8s.io/kubernetes/pkg/apis\"")
|
||||
|
@ -78,6 +78,7 @@ func New() *Generator {
|
||||
`k8s.io/kubernetes/federation/apis/federation/v1beta1`,
|
||||
`k8s.io/kubernetes/pkg/apis/certificates/v1alpha1`,
|
||||
`k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1`,
|
||||
`k8s.io/kubernetes/pkg/apis/storage/v1beta1`,
|
||||
}, ","),
|
||||
DropEmbeddedFields: "k8s.io/kubernetes/pkg/api/unversioned.TypeMeta",
|
||||
}
|
||||
|
@ -2388,7 +2388,7 @@ __EOF__
|
||||
kubectl create -f - "${kube_flags[@]}" << __EOF__
|
||||
{
|
||||
"kind": "StorageClass",
|
||||
"apiVersion": "extensions/v1beta1",
|
||||
"apiVersion": "storage.k8s.io/v1beta1",
|
||||
"metadata": {
|
||||
"name": "storage-class-name"
|
||||
},
|
||||
|
@ -27,7 +27,7 @@ source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||
# KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1"}
|
||||
# FIXME: due to current implementation of a test client (see: pkg/api/testapi/testapi.go)
|
||||
# ONLY the last version is tested in each group.
|
||||
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,authorization.k8s.io/v1beta1,autoscaling/v1,batch/v1,apps/v1alpha1,policy/v1alpha1,extensions/v1beta1,rbac.authorization.k8s.io/v1alpha1,certificates.k8s.io/v1alpha1"}
|
||||
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,authorization.k8s.io/v1beta1,autoscaling/v1,batch/v1,apps/v1alpha1,policy/v1alpha1,extensions/v1beta1,rbac.authorization.k8s.io/v1alpha1,certificates.k8s.io/v1alpha1,storage.k8s.io/v1beta1"}
|
||||
|
||||
# Give integration tests longer to run
|
||||
# TODO: allow a larger value to be passed in
|
||||
|
@ -66,7 +66,7 @@ KUBE_GOVERALLS_BIN=${KUBE_GOVERALLS_BIN:-}
|
||||
# "v1,compute/v1alpha1,experimental/v1alpha2;v1,compute/v2,experimental/v1alpha3"
|
||||
# FIXME: due to current implementation of a test client (see: pkg/api/testapi/testapi.go)
|
||||
# ONLY the last version is tested in each group.
|
||||
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,apps/v1alpha1,authentication.k8s.io/v1beta1,authorization.k8s.io/v1beta1,autoscaling/v1,batch/v1,batch/v2alpha1,certificates.k8s.io/v1alpha1,extensions/v1beta1,federation/v1beta1,policy/v1alpha1,rbac.authorization.k8s.io/v1alpha1,imagepolicy.k8s.io/v1alpha1"}
|
||||
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,apps/v1alpha1,authentication.k8s.io/v1beta1,authorization.k8s.io/v1beta1,autoscaling/v1,batch/v1,batch/v2alpha1,certificates.k8s.io/v1alpha1,extensions/v1beta1,federation/v1beta1,policy/v1alpha1,rbac.authorization.k8s.io/v1alpha1,imagepolicy.k8s.io/v1alpha1,storage.k8s.io/v1beta1"}
|
||||
# once we have multiple group supports
|
||||
# Create a junit-style XML test report in this directory if set.
|
||||
KUBE_JUNIT_REPORT_DIR=${KUBE_JUNIT_REPORT_DIR:-}
|
||||
|
@ -28,7 +28,7 @@ source "${KUBE_ROOT}/hack/lib/swagger.sh"
|
||||
|
||||
kube::golang::setup_env
|
||||
|
||||
GROUP_VERSIONS=(unversioned v1 authentication/v1beta1 authorization/v1beta1 autoscaling/v1 batch/v1 batch/v2alpha1 extensions/v1beta1 apps/v1alpha1 policy/v1alpha1 rbac/v1alpha1 certificates/v1alpha1)
|
||||
GROUP_VERSIONS=(unversioned v1 authentication/v1beta1 authorization/v1beta1 autoscaling/v1 batch/v1 batch/v2alpha1 extensions/v1beta1 apps/v1alpha1 policy/v1alpha1 rbac/v1alpha1 storage/v1beta1 certificates/v1alpha1)
|
||||
# To avoid compile errors, remove the currently existing files.
|
||||
for group_version in "${GROUP_VERSIONS[@]}"; do
|
||||
rm -f "pkg/$(kube::util::group-version-to-pkg-path "${group_version}")/types_swagger_doc_generated.go"
|
||||
|
@ -73,7 +73,7 @@ APISERVER_PID=$!
|
||||
kube::util::wait_for_url "${API_HOST}:${API_PORT}/healthz" "apiserver: "
|
||||
|
||||
SWAGGER_API_PATH="${API_HOST}:${API_PORT}/swaggerapi/"
|
||||
DEFAULT_GROUP_VERSIONS="v1 apps/v1alpha1 authentication.k8s.io/v1beta1 authorization.k8s.io/v1beta1 autoscaling/v1 batch/v1 batch/v2alpha1 extensions/v1beta1 certificates.k8s.io/v1alpha1 policy/v1alpha1 rbac.authorization.k8s.io/v1alpha1"
|
||||
DEFAULT_GROUP_VERSIONS="v1 apps/v1alpha1 authentication.k8s.io/v1beta1 authorization.k8s.io/v1beta1 autoscaling/v1 batch/v1 batch/v2alpha1 extensions/v1beta1 certificates.k8s.io/v1alpha1 policy/v1alpha1 rbac.authorization.k8s.io/v1alpha1 storage.k8s.io/v1beta1"
|
||||
VERSIONS=${VERSIONS:-$DEFAULT_GROUP_VERSIONS}
|
||||
|
||||
kube::log::status "Updating " ${SWAGGER_ROOT_DIR}
|
||||
|
@ -37,6 +37,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/apis/imagepolicy"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/runtime/serializer/recognizer"
|
||||
|
||||
@ -53,6 +54,7 @@ import (
|
||||
_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/policy/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/rbac/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/storage/install"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -66,6 +68,7 @@ var (
|
||||
Federation TestGroup
|
||||
Rbac TestGroup
|
||||
Certificates TestGroup
|
||||
Storage TestGroup
|
||||
ImagePolicy TestGroup
|
||||
|
||||
serializer runtime.SerializerInfo
|
||||
@ -218,6 +221,15 @@ func init() {
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[storage.GroupName]; !ok {
|
||||
externalGroupVersion := unversioned.GroupVersion{Group: storage.GroupName, Version: registered.GroupOrDie(storage.GroupName).GroupVersion.Version}
|
||||
Groups[storage.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: storage.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(storage.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[certificates.GroupName]; !ok {
|
||||
externalGroupVersion := unversioned.GroupVersion{Group: certificates.GroupName, Version: registered.GroupOrDie(certificates.GroupName).GroupVersion.Version}
|
||||
Groups[certificates.GroupName] = TestGroup{
|
||||
@ -247,6 +259,7 @@ func init() {
|
||||
Extensions = Groups[extensions.GroupName]
|
||||
Federation = Groups[federation.GroupName]
|
||||
Rbac = Groups[rbac.GroupName]
|
||||
Storage = Groups[storage.GroupName]
|
||||
ImagePolicy = Groups[imagepolicy.GroupName]
|
||||
}
|
||||
|
||||
|
@ -76,8 +76,6 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
&PodSecurityPolicyList{},
|
||||
&NetworkPolicy{},
|
||||
&NetworkPolicyList{},
|
||||
&StorageClass{},
|
||||
&StorageClassList{},
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
@ -911,41 +911,3 @@ type NetworkPolicyList struct {
|
||||
|
||||
Items []NetworkPolicy `json:"items"`
|
||||
}
|
||||
|
||||
// +genclient=true
|
||||
// +nonNamespaced=true
|
||||
|
||||
// StorageClass describes a named "class" of storage offered in a cluster.
|
||||
// Different classes might map to quality-of-service levels, or to backup policies,
|
||||
// or to arbitrary policies determined by the cluster administrators. Kubernetes
|
||||
// itself is unopinionated about what classes represent. This concept is sometimes
|
||||
// called "profiles" in other storage systems.
|
||||
// The name of a StorageClass object is significant, and is how users can request a particular class.
|
||||
type StorageClass struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
api.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// provisioner is the driver expected to handle this StorageClass.
|
||||
// This is an optionally-prefixed name, like a label key.
|
||||
// For example: "kubernetes.io/gce-pd" or "kubernetes.io/aws-ebs".
|
||||
// This value may not be empty.
|
||||
Provisioner string `json:"provisioner"`
|
||||
|
||||
// parameters holds parameters for the provisioner.
|
||||
// These values are opaque to the system and are passed directly
|
||||
// to the provisioner. The only validation done on keys is that they are
|
||||
// not empty. The maximum number of parameters is
|
||||
// 512, with a cumulative max size of 256K
|
||||
Parameters map[string]string `json:"parameters,omitempty"`
|
||||
}
|
||||
|
||||
// StorageClassList is a collection of storage classes.
|
||||
type StorageClassList struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
// Standard list metadata
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
unversioned.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Items is the list of StorageClasses
|
||||
Items []StorageClass `json:"items"`
|
||||
}
|
||||
|
@ -62,8 +62,6 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
&PodSecurityPolicyList{},
|
||||
&NetworkPolicy{},
|
||||
&NetworkPolicyList{},
|
||||
&StorageClass{},
|
||||
&StorageClassList{},
|
||||
)
|
||||
// Add the watch version that applies
|
||||
versionedwatch.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
|
@ -1199,36 +1199,3 @@ type NetworkPolicyList struct {
|
||||
// Items is a list of schema objects.
|
||||
Items []NetworkPolicy `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// +genclient=true
|
||||
// +nonNamespaced=true
|
||||
|
||||
// StorageClass describes the parameters for a class of storage for
|
||||
// which PersistentVolumes can be dynamically provisioned.
|
||||
//
|
||||
// StorageClasses are non-namespaced; the name of the storage class
|
||||
// according to etcd is in ObjectMeta.Name.
|
||||
type StorageClass struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
v1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// Provisioner indicates the type of the provisioner.
|
||||
Provisioner string `json:"provisioner" protobuf:"bytes,2,opt,name=provisioner"`
|
||||
|
||||
// Parameters holds the parameters for the provisioner that should
|
||||
// create volumes of this storage class.
|
||||
Parameters map[string]string `json:"parameters,omitempty" protobuf:"bytes,3,rep,name=parameters"`
|
||||
}
|
||||
|
||||
// StorageClassList is a collection of storage classes.
|
||||
type StorageClassList struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
// Standard list metadata
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
unversioned.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// Items is the list of StorageClasses
|
||||
Items []StorageClass `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
@ -822,65 +822,3 @@ func ValidateNetworkPolicyUpdate(update, old *extensions.NetworkPolicy) field.Er
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateStorageClass validates a StorageClass.
|
||||
func ValidateStorageClass(storageClass *extensions.StorageClass) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMeta(&storageClass.ObjectMeta, false, apivalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, validateProvisioner(storageClass.Provisioner, field.NewPath("provisioner"))...)
|
||||
allErrs = append(allErrs, validateParameters(storageClass.Parameters, field.NewPath("parameters"))...)
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateStorageClassUpdate tests if an update to StorageClass is valid.
|
||||
func ValidateStorageClassUpdate(storageClass, oldStorageClass *extensions.StorageClass) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&storageClass.ObjectMeta, &oldStorageClass.ObjectMeta, field.NewPath("metadata"))
|
||||
if !reflect.DeepEqual(oldStorageClass.Parameters, storageClass.Parameters) {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("parameters"), "updates to parameters are forbidden."))
|
||||
}
|
||||
|
||||
if strings.Compare(storageClass.Provisioner, oldStorageClass.Provisioner) != 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("provisioner"), "updates to provisioner are forbidden."))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// validateProvisioner tests if provisioner is a valid qualified name.
|
||||
func validateProvisioner(provisioner string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(provisioner) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath, provisioner))
|
||||
}
|
||||
if len(provisioner) > 0 {
|
||||
for _, msg := range validation.IsQualifiedName(strings.ToLower(provisioner)) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, provisioner, msg))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
const maxProvisionerParameterSize = 256 * (1 << 10) // 256 kB
|
||||
const maxProvisionerParameterLen = 512
|
||||
|
||||
// validateParameters tests that keys are qualified names and that provisionerParameter are < 256kB.
|
||||
func validateParameters(params map[string]string, fldPath *field.Path) field.ErrorList {
|
||||
var totalSize int64
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if len(params) > maxProvisionerParameterLen {
|
||||
allErrs = append(allErrs, field.TooLong(fldPath, "Provisioner Parameters exceeded max allowed", maxProvisionerParameterLen))
|
||||
return allErrs
|
||||
}
|
||||
|
||||
for k, v := range params {
|
||||
if len(k) < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, k, "field can not be empty."))
|
||||
}
|
||||
totalSize += (int64)(len(k)) + (int64)(len(v))
|
||||
}
|
||||
|
||||
if totalSize > maxProvisionerParameterSize {
|
||||
allErrs = append(allErrs, field.TooLong(fldPath, "", maxProvisionerParameterSize))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
@ -2133,80 +2133,3 @@ func newBool(val bool) *bool {
|
||||
*p = val
|
||||
return p
|
||||
}
|
||||
|
||||
func TestValidateStorageClass(t *testing.T) {
|
||||
successCases := []extensions.StorageClass{
|
||||
{
|
||||
// empty parameters
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
Parameters: map[string]string{},
|
||||
},
|
||||
{
|
||||
// nil parameters
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
},
|
||||
{
|
||||
// some parameters
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
Parameters: map[string]string{
|
||||
"kubernetes.io/foo-parameter": "free/form/string",
|
||||
"foo-parameter": "free-form-string",
|
||||
"foo-parameter2": "{\"embedded\": \"json\", \"with\": {\"structures\":\"inside\"}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Success cases are expected to pass validation.
|
||||
for k, v := range successCases {
|
||||
if errs := ValidateStorageClass(&v); len(errs) != 0 {
|
||||
t.Errorf("Expected success for %d, got %v", k, errs)
|
||||
}
|
||||
}
|
||||
|
||||
// generate a map longer than maxProvisionerParameterSize
|
||||
longParameters := make(map[string]string)
|
||||
totalSize := 0
|
||||
for totalSize < maxProvisionerParameterSize {
|
||||
k := fmt.Sprintf("param/%d", totalSize)
|
||||
v := fmt.Sprintf("value-%d", totalSize)
|
||||
longParameters[k] = v
|
||||
totalSize = totalSize + len(k) + len(v)
|
||||
}
|
||||
|
||||
errorCases := map[string]extensions.StorageClass{
|
||||
"namespace is present": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
},
|
||||
"invalid provisioner": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/invalid/provisioner",
|
||||
},
|
||||
"invalid empty parameter name": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo",
|
||||
Parameters: map[string]string{
|
||||
"": "value",
|
||||
},
|
||||
},
|
||||
"provisioner: Required value": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "",
|
||||
},
|
||||
"too long parameters": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo",
|
||||
Parameters: longParameters,
|
||||
},
|
||||
}
|
||||
|
||||
// Error cases are not expected to pass validation.
|
||||
for testName, storageClass := range errorCases {
|
||||
if errs := ValidateStorageClass(&storageClass); len(errs) == 0 {
|
||||
t.Errorf("Expected failure for test: %s", testName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
19
pkg/apis/storage/doc.go
Normal file
19
pkg/apis/storage/doc.go
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package,register
|
||||
// +groupName=storage.k8s.io
|
||||
package storage // import "k8s.io/kubernetes/pkg/apis/storage"
|
137
pkg/apis/storage/install/install.go
Normal file
137
pkg/apis/storage/install/install.go
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package install installs the experimental API group, making it available as
|
||||
// an option to all of the API encoding/decoding machinery.
|
||||
package install
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apimachinery"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/apis/storage/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
|
||||
const importPrefix = "k8s.io/kubernetes/pkg/apis/storage"
|
||||
|
||||
var accessor = meta.NewAccessor()
|
||||
|
||||
// availableVersions lists all known external versions for this group from most preferred to least preferred
|
||||
var availableVersions = []unversioned.GroupVersion{v1beta1.SchemeGroupVersion}
|
||||
|
||||
func init() {
|
||||
registered.RegisterVersions(availableVersions)
|
||||
externalVersions := []unversioned.GroupVersion{}
|
||||
for _, v := range availableVersions {
|
||||
if registered.IsAllowedVersion(v) {
|
||||
externalVersions = append(externalVersions, v)
|
||||
}
|
||||
}
|
||||
if len(externalVersions) == 0 {
|
||||
glog.V(4).Infof("No version is registered for group %v", storage.GroupName)
|
||||
return
|
||||
}
|
||||
|
||||
if err := registered.EnableVersions(externalVersions...); err != nil {
|
||||
glog.V(4).Infof("%v", err)
|
||||
return
|
||||
}
|
||||
if err := enableVersions(externalVersions); err != nil {
|
||||
glog.V(4).Infof("%v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: enableVersions should be centralized rather than spread in each API
|
||||
// group.
|
||||
// We can combine registered.RegisterVersions, registered.EnableVersions and
|
||||
// registered.RegisterGroup once we have moved enableVersions there.
|
||||
func enableVersions(externalVersions []unversioned.GroupVersion) error {
|
||||
addVersionsToScheme(externalVersions...)
|
||||
preferredExternalVersion := externalVersions[0]
|
||||
|
||||
groupMeta := apimachinery.GroupMeta{
|
||||
GroupVersion: preferredExternalVersion,
|
||||
GroupVersions: externalVersions,
|
||||
RESTMapper: newRESTMapper(externalVersions),
|
||||
SelfLinker: runtime.SelfLinker(accessor),
|
||||
InterfacesFor: interfacesFor,
|
||||
}
|
||||
|
||||
if err := registered.RegisterGroup(groupMeta); err != nil {
|
||||
return err
|
||||
}
|
||||
api.RegisterRESTMapper(groupMeta.RESTMapper)
|
||||
return nil
|
||||
}
|
||||
|
||||
func newRESTMapper(externalVersions []unversioned.GroupVersion) meta.RESTMapper {
|
||||
// the list of kinds that are scoped at the root of the api hierarchy
|
||||
// if a kind is not enumerated here, it is assumed to have a namespace scope
|
||||
rootScoped := sets.NewString(
|
||||
"StorageClass",
|
||||
)
|
||||
|
||||
ignoredKinds := sets.NewString()
|
||||
|
||||
return api.NewDefaultRESTMapper(externalVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped)
|
||||
}
|
||||
|
||||
// interfacesFor returns the default Codec and ResourceVersioner for a given version
|
||||
// string, or an error if the version is not known.
|
||||
func interfacesFor(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
|
||||
switch version {
|
||||
case v1beta1.SchemeGroupVersion:
|
||||
return &meta.VersionInterfaces{
|
||||
ObjectConvertor: api.Scheme,
|
||||
MetadataAccessor: accessor,
|
||||
}, nil
|
||||
default:
|
||||
g, _ := registered.Group(storage.GroupName)
|
||||
return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, g.GroupVersions)
|
||||
}
|
||||
}
|
||||
|
||||
func addVersionsToScheme(externalVersions ...unversioned.GroupVersion) {
|
||||
// add the internal version to Scheme
|
||||
if err := storage.AddToScheme(api.Scheme); err != nil {
|
||||
// Programmer error, detect immediately
|
||||
panic(err)
|
||||
}
|
||||
// add the enabled external versions to Scheme
|
||||
for _, v := range externalVersions {
|
||||
if !registered.IsEnabledVersion(v) {
|
||||
glog.Errorf("Version %s is not enabled, so it will not be added to the Scheme.", v)
|
||||
continue
|
||||
}
|
||||
switch v {
|
||||
case v1beta1.SchemeGroupVersion:
|
||||
if err := v1beta1.AddToScheme(api.Scheme); err != nil {
|
||||
// Programmer error, detect immediately
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
56
pkg/apis/storage/register.go
Normal file
56
pkg/apis/storage/register.go
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package storage
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "storage.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
|
||||
|
||||
// Kind takes an unqualified kind and returns a Group qualified GroupKind
|
||||
func Kind(kind string) unversioned.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func Resource(resource string) unversioned.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
var (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&api.ListOptions{},
|
||||
&api.DeleteOptions{},
|
||||
&api.ExportOptions{},
|
||||
|
||||
&StorageClass{},
|
||||
&StorageClassList{},
|
||||
)
|
||||
return nil
|
||||
}
|
60
pkg/apis/storage/types.go
Normal file
60
pkg/apis/storage/types.go
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package storage
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
)
|
||||
|
||||
// +genclient=true
|
||||
// +nonNamespaced=true
|
||||
|
||||
// StorageClass describes a named "class" of storage offered in a cluster.
|
||||
// Different classes might map to quality-of-service levels, or to backup policies,
|
||||
// or to arbitrary policies determined by the cluster administrators. Kubernetes
|
||||
// itself is unopinionated about what classes represent. This concept is sometimes
|
||||
// called "profiles" in other storage systems.
|
||||
// The name of a StorageClass object is significant, and is how users can request a particular class.
|
||||
type StorageClass struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
api.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// provisioner is the driver expected to handle this StorageClass.
|
||||
// This is an optionally-prefixed name, like a label key.
|
||||
// For example: "kubernetes.io/gce-pd" or "kubernetes.io/aws-ebs".
|
||||
// This value may not be empty.
|
||||
Provisioner string `json:"provisioner"`
|
||||
|
||||
// parameters holds parameters for the provisioner.
|
||||
// These values are opaque to the system and are passed directly
|
||||
// to the provisioner. The only validation done on keys is that they are
|
||||
// not empty. The maximum number of parameters is
|
||||
// 512, with a cumulative max size of 256K
|
||||
Parameters map[string]string `json:"parameters,omitempty"`
|
||||
}
|
||||
|
||||
// StorageClassList is a collection of storage classes.
|
||||
type StorageClassList struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
// Standard list metadata
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
unversioned.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Items is the list of StorageClasses
|
||||
Items []StorageClass `json:"items"`
|
||||
}
|
20
pkg/apis/storage/v1beta1/doc.go
Normal file
20
pkg/apis/storage/v1beta1/doc.go
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package,register
|
||||
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/storage
|
||||
// +groupName=storage.k8s.io
|
||||
package v1beta1 // import "k8s.io/kubernetes/pkg/apis/storage/v1beta1"
|
50
pkg/apis/storage/v1beta1/register.go
Normal file
50
pkg/apis/storage/v1beta1/register.go
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
versionedwatch "k8s.io/kubernetes/pkg/watch/versioned"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "storage.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: "v1beta1"}
|
||||
|
||||
var (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&v1.ListOptions{},
|
||||
&v1.DeleteOptions{},
|
||||
&v1.ExportOptions{},
|
||||
|
||||
&StorageClass{},
|
||||
&StorageClassList{},
|
||||
)
|
||||
|
||||
versionedwatch.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
55
pkg/apis/storage/v1beta1/types.go
Normal file
55
pkg/apis/storage/v1beta1/types.go
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
// +genclient=true
|
||||
// +nonNamespaced=true
|
||||
|
||||
// StorageClass describes the parameters for a class of storage for
|
||||
// which PersistentVolumes can be dynamically provisioned.
|
||||
//
|
||||
// StorageClasses are non-namespaced; the name of the storage class
|
||||
// according to etcd is in ObjectMeta.Name.
|
||||
type StorageClass struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
v1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// Provisioner indicates the type of the provisioner.
|
||||
Provisioner string `json:"provisioner" protobuf:"bytes,2,opt,name=provisioner"`
|
||||
|
||||
// Parameters holds the parameters for the provisioner that should
|
||||
// create volumes of this storage class.
|
||||
Parameters map[string]string `json:"parameters,omitempty" protobuf:"bytes,3,rep,name=parameters"`
|
||||
}
|
||||
|
||||
// StorageClassList is a collection of storage classes.
|
||||
type StorageClassList struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
// Standard list metadata
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
unversioned.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// Items is the list of StorageClasses
|
||||
Items []StorageClass `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
89
pkg/apis/storage/validation/validation.go
Normal file
89
pkg/apis/storage/validation/validation.go
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validation
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
apivalidation "k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/util/validation"
|
||||
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
// ValidateStorageClass validates a StorageClass.
|
||||
func ValidateStorageClass(storageClass *storage.StorageClass) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMeta(&storageClass.ObjectMeta, false, apivalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, validateProvisioner(storageClass.Provisioner, field.NewPath("provisioner"))...)
|
||||
allErrs = append(allErrs, validateParameters(storageClass.Parameters, field.NewPath("parameters"))...)
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateStorageClassUpdate tests if an update to StorageClass is valid.
|
||||
func ValidateStorageClassUpdate(storageClass, oldStorageClass *storage.StorageClass) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&storageClass.ObjectMeta, &oldStorageClass.ObjectMeta, field.NewPath("metadata"))
|
||||
if !reflect.DeepEqual(oldStorageClass.Parameters, storageClass.Parameters) {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("parameters"), "updates to parameters are forbidden."))
|
||||
}
|
||||
|
||||
if strings.Compare(storageClass.Provisioner, oldStorageClass.Provisioner) != 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("provisioner"), "updates to provisioner are forbidden."))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// validateProvisioner tests if provisioner is a valid qualified name.
|
||||
func validateProvisioner(provisioner string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(provisioner) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath, provisioner))
|
||||
}
|
||||
if len(provisioner) > 0 {
|
||||
for _, msg := range validation.IsQualifiedName(strings.ToLower(provisioner)) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, provisioner, msg))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
const maxProvisionerParameterSize = 256 * (1 << 10) // 256 kB
|
||||
const maxProvisionerParameterLen = 512
|
||||
|
||||
// validateParameters tests that keys are qualified names and that provisionerParameter are < 256kB.
|
||||
func validateParameters(params map[string]string, fldPath *field.Path) field.ErrorList {
|
||||
var totalSize int64
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if len(params) > maxProvisionerParameterLen {
|
||||
allErrs = append(allErrs, field.TooLong(fldPath, "Provisioner Parameters exceeded max allowed", maxProvisionerParameterLen))
|
||||
return allErrs
|
||||
}
|
||||
|
||||
for k, v := range params {
|
||||
if len(k) < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, k, "field can not be empty."))
|
||||
}
|
||||
totalSize += (int64)(len(k)) + (int64)(len(v))
|
||||
}
|
||||
|
||||
if totalSize > maxProvisionerParameterSize {
|
||||
allErrs = append(allErrs, field.TooLong(fldPath, "", maxProvisionerParameterSize))
|
||||
}
|
||||
return allErrs
|
||||
}
|
102
pkg/apis/storage/validation/validation_test.go
Normal file
102
pkg/apis/storage/validation/validation_test.go
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
)
|
||||
|
||||
func TestValidateStorageClass(t *testing.T) {
|
||||
successCases := []storage.StorageClass{
|
||||
{
|
||||
// empty parameters
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
Parameters: map[string]string{},
|
||||
},
|
||||
{
|
||||
// nil parameters
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
},
|
||||
{
|
||||
// some parameters
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
Parameters: map[string]string{
|
||||
"kubernetes.io/foo-parameter": "free/form/string",
|
||||
"foo-parameter": "free-form-string",
|
||||
"foo-parameter2": "{\"embedded\": \"json\", \"with\": {\"structures\":\"inside\"}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Success cases are expected to pass validation.
|
||||
for k, v := range successCases {
|
||||
if errs := ValidateStorageClass(&v); len(errs) != 0 {
|
||||
t.Errorf("Expected success for %d, got %v", k, errs)
|
||||
}
|
||||
}
|
||||
|
||||
// generate a map longer than maxProvisionerParameterSize
|
||||
longParameters := make(map[string]string)
|
||||
totalSize := 0
|
||||
for totalSize < maxProvisionerParameterSize {
|
||||
k := fmt.Sprintf("param/%d", totalSize)
|
||||
v := fmt.Sprintf("value-%d", totalSize)
|
||||
longParameters[k] = v
|
||||
totalSize = totalSize + len(k) + len(v)
|
||||
}
|
||||
|
||||
errorCases := map[string]storage.StorageClass{
|
||||
"namespace is present": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
},
|
||||
"invalid provisioner": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/invalid/provisioner",
|
||||
},
|
||||
"invalid empty parameter name": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo",
|
||||
Parameters: map[string]string{
|
||||
"": "value",
|
||||
},
|
||||
},
|
||||
"provisioner: Required value": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "",
|
||||
},
|
||||
"too long parameters": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo",
|
||||
Parameters: longParameters,
|
||||
},
|
||||
}
|
||||
|
||||
// Error cases are not expected to pass validation.
|
||||
for testName, storageClass := range errorCases {
|
||||
if errs := ValidateStorageClass(&storageClass); len(errs) == 0 {
|
||||
t.Errorf("Expected failure for test: %s", testName)
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ import (
|
||||
unversionedbatch "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned"
|
||||
unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned"
|
||||
unversionedextensions "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned"
|
||||
unversionedstorage "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/unversioned"
|
||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned"
|
||||
)
|
||||
@ -68,6 +69,11 @@ func FromUnversionedClient(c *unversioned.Client) *internalclientset.Clientset {
|
||||
} else {
|
||||
clientset.DiscoveryClient = discovery.NewDiscoveryClient(nil)
|
||||
}
|
||||
if c != nil && c.StorageClient != nil {
|
||||
clientset.StorageClient = unversionedstorage.New(c.StorageClient.RESTClient)
|
||||
} else {
|
||||
clientset.StorageClient = unversionedstorage.New(nil)
|
||||
}
|
||||
|
||||
return &clientset
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ type Interface interface {
|
||||
Rbac() RbacInterface
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
Certificates() CertificatesInterface
|
||||
Storage() StorageInterface
|
||||
}
|
||||
|
||||
func (c *Client) ReplicationControllers(namespace string) ReplicationControllerInterface {
|
||||
@ -131,6 +132,7 @@ type Client struct {
|
||||
*RbacClient
|
||||
*discovery.DiscoveryClient
|
||||
*CertificatesClient
|
||||
*StorageClient
|
||||
}
|
||||
|
||||
// IsTimeout tests if this is a timeout error in the underlying transport.
|
||||
@ -194,3 +196,7 @@ func (c *Client) Discovery() discovery.DiscoveryInterface {
|
||||
func (c *Client) Certificates() CertificatesInterface {
|
||||
return c.CertificatesClient
|
||||
}
|
||||
|
||||
func (c *Client) Storage() StorageInterface {
|
||||
return c.StorageClient
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ type ExtensionsInterface interface {
|
||||
ThirdPartyResourceNamespacer
|
||||
ReplicaSetsNamespacer
|
||||
PodSecurityPoliciesInterface
|
||||
StorageClassesInterface
|
||||
}
|
||||
|
||||
// ExtensionsClient is used to interact with experimental Kubernetes features.
|
||||
@ -81,10 +80,6 @@ func (c *ExtensionsClient) ReplicaSets(namespace string) ReplicaSetInterface {
|
||||
return newReplicaSets(c, namespace)
|
||||
}
|
||||
|
||||
func (c *ExtensionsClient) StorageClasses() StorageClassInterface {
|
||||
return newStorageClasses(c)
|
||||
}
|
||||
|
||||
// NewExtensions creates a new ExtensionsClient for the given config. This client
|
||||
// provides access to experimental Kubernetes features.
|
||||
// Features of Extensions group are not supported and may be changed or removed in
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
@ -143,6 +144,15 @@ func New(c *restclient.Config) (*Client, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var storageClient *StorageClient
|
||||
if registered.IsRegistered(storage.GroupName) {
|
||||
storageConfig := *c
|
||||
storageClient, err = NewStorage(&storageConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &Client{
|
||||
RESTClient: client,
|
||||
AppsClient: appsClient,
|
||||
@ -155,6 +165,7 @@ func New(c *restclient.Config) (*Client, error) {
|
||||
ExtensionsClient: extensionsClient,
|
||||
PolicyClient: policyClient,
|
||||
RbacClient: rbacClient,
|
||||
StorageClient: storageClient,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ import (
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/policy/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/rbac/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/storage/install"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
77
pkg/client/unversioned/storage.go
Normal file
77
pkg/client/unversioned/storage.go
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package unversioned
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
)
|
||||
|
||||
type StorageInterface interface {
|
||||
StorageClassesInterface
|
||||
}
|
||||
|
||||
// StorageClient is used to interact with Kubernetes storage features.
|
||||
type StorageClient struct {
|
||||
*restclient.RESTClient
|
||||
}
|
||||
|
||||
func (c *StorageClient) StorageClasses() StorageClassInterface {
|
||||
return newStorageClasses(c)
|
||||
}
|
||||
|
||||
func NewStorage(c *restclient.Config) (*StorageClient, error) {
|
||||
config := *c
|
||||
if err := setStorageDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := restclient.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &StorageClient{client}, nil
|
||||
}
|
||||
|
||||
func NewStorageOrDie(c *restclient.Config) *StorageClient {
|
||||
client, err := NewStorage(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func setStorageDefaults(config *restclient.Config) error {
|
||||
// if storage group is not registered, return an error
|
||||
g, err := registered.Group(storage.GroupName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.APIPath = defaultAPIPath
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = restclient.DefaultKubernetesUserAgent()
|
||||
}
|
||||
// TODO: Unconditionally set the config.Version, until we fix the config.
|
||||
//if config.Version == "" {
|
||||
copyGroupVersion := g.GroupVersion
|
||||
config.GroupVersion = ©GroupVersion
|
||||
//}
|
||||
|
||||
config.NegotiatedSerializer = api.Codecs
|
||||
return nil
|
||||
}
|
@ -18,7 +18,7 @@ package unversioned
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
@ -28,25 +28,25 @@ type StorageClassesInterface interface {
|
||||
|
||||
// StorageClassInterface has methods to work with StorageClass resources.
|
||||
type StorageClassInterface interface {
|
||||
List(opts api.ListOptions) (*extensions.StorageClassList, error)
|
||||
Get(name string) (*extensions.StorageClass, error)
|
||||
Create(storageClass *extensions.StorageClass) (*extensions.StorageClass, error)
|
||||
Update(storageClass *extensions.StorageClass) (*extensions.StorageClass, error)
|
||||
List(opts api.ListOptions) (*storage.StorageClassList, error)
|
||||
Get(name string) (*storage.StorageClass, error)
|
||||
Create(storageClass *storage.StorageClass) (*storage.StorageClass, error)
|
||||
Update(storageClass *storage.StorageClass) (*storage.StorageClass, error)
|
||||
Delete(name string) error
|
||||
Watch(opts api.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// storageClasses implements StorageClassInterface
|
||||
type storageClasses struct {
|
||||
client *ExtensionsClient
|
||||
client *StorageClient
|
||||
}
|
||||
|
||||
func newStorageClasses(c *ExtensionsClient) *storageClasses {
|
||||
func newStorageClasses(c *StorageClient) *storageClasses {
|
||||
return &storageClasses{c}
|
||||
}
|
||||
|
||||
func (c *storageClasses) List(opts api.ListOptions) (result *extensions.StorageClassList, err error) {
|
||||
result = &extensions.StorageClassList{}
|
||||
func (c *storageClasses) List(opts api.ListOptions) (result *storage.StorageClassList, err error) {
|
||||
result = &storage.StorageClassList{}
|
||||
err = c.client.Get().
|
||||
Resource("storageclasses").
|
||||
VersionedParams(&opts, api.ParameterCodec).
|
||||
@ -56,20 +56,20 @@ func (c *storageClasses) List(opts api.ListOptions) (result *extensions.StorageC
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (c *storageClasses) Get(name string) (result *extensions.StorageClass, err error) {
|
||||
result = &extensions.StorageClass{}
|
||||
func (c *storageClasses) Get(name string) (result *storage.StorageClass, err error) {
|
||||
result = &storage.StorageClass{}
|
||||
err = c.client.Get().Resource("storageClasses").Name(name).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *storageClasses) Create(storageClass *extensions.StorageClass) (result *extensions.StorageClass, err error) {
|
||||
result = &extensions.StorageClass{}
|
||||
func (c *storageClasses) Create(storageClass *storage.StorageClass) (result *storage.StorageClass, err error) {
|
||||
result = &storage.StorageClass{}
|
||||
err = c.client.Post().Resource("storageClasses").Body(storageClass).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *storageClasses) Update(storageClass *extensions.StorageClass) (result *extensions.StorageClass, err error) {
|
||||
result = &extensions.StorageClass{}
|
||||
func (c *storageClasses) Update(storageClass *storage.StorageClass) (result *storage.StorageClass, err error) {
|
||||
result = &storage.StorageClass{}
|
||||
err = c.client.Put().Resource("storageClasses").Name(storageClass.Name).Body(storageClass).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/testclient/simple"
|
||||
)
|
||||
|
||||
@ -33,11 +33,11 @@ func TestListStorageClasses(t *testing.T) {
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "GET",
|
||||
Path: testapi.Extensions.ResourcePath(getStorageClassResourceName(), "", ""),
|
||||
Path: testapi.Storage.ResourcePath(getStorageClassResourceName(), "", ""),
|
||||
},
|
||||
Response: simple.Response{StatusCode: 200,
|
||||
Body: &extensions.StorageClassList{
|
||||
Items: []extensions.StorageClass{
|
||||
Body: &storage.StorageClassList{
|
||||
Items: []storage.StorageClass{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
@ -52,16 +52,16 @@ func TestListStorageClasses(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
receivedSCList, err := c.Setup(t).Extensions().StorageClasses().List(api.ListOptions{})
|
||||
receivedSCList, err := c.Setup(t).Storage().StorageClasses().List(api.ListOptions{})
|
||||
c.Validate(t, receivedSCList, err)
|
||||
}
|
||||
|
||||
func TestGetStorageClass(t *testing.T) {
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{Method: "GET", Path: testapi.Extensions.ResourcePath(getStorageClassResourceName(), "", "foo"), Query: simple.BuildQueryValues(nil)},
|
||||
Request: simple.Request{Method: "GET", Path: testapi.Storage.ResourcePath(getStorageClassResourceName(), "", "foo"), Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{
|
||||
StatusCode: 200,
|
||||
Body: &extensions.StorageClass{
|
||||
Body: &storage.StorageClass{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
Labels: map[string]string{
|
||||
@ -73,13 +73,13 @@ func TestGetStorageClass(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
receivedSC, err := c.Setup(t).Extensions().StorageClasses().Get("foo")
|
||||
receivedSC, err := c.Setup(t).Storage().StorageClasses().Get("foo")
|
||||
c.Validate(t, receivedSC, err)
|
||||
}
|
||||
|
||||
func TestGetStorageClassWithNoName(t *testing.T) {
|
||||
c := &simple.Client{Error: true}
|
||||
receivedSC, err := c.Setup(t).Extensions().StorageClasses().Get("")
|
||||
receivedSC, err := c.Setup(t).Storage().StorageClasses().Get("")
|
||||
if (err != nil) && (err.Error() != simple.NameRequiredError) {
|
||||
t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err)
|
||||
}
|
||||
@ -88,15 +88,15 @@ func TestGetStorageClassWithNoName(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateStorageClass(t *testing.T) {
|
||||
requestSC := &extensions.StorageClass{
|
||||
requestSC := &storage.StorageClass{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"},
|
||||
Provisioner: "aaa",
|
||||
}
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{Method: "PUT", Path: testapi.Extensions.ResourcePath(getStorageClassResourceName(), "", "foo"), Query: simple.BuildQueryValues(nil)},
|
||||
Request: simple.Request{Method: "PUT", Path: testapi.Storage.ResourcePath(getStorageClassResourceName(), "", "foo"), Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{
|
||||
StatusCode: 200,
|
||||
Body: &extensions.StorageClass{
|
||||
Body: &storage.StorageClass{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
Labels: map[string]string{
|
||||
@ -108,29 +108,29 @@ func TestUpdateStorageClass(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
receivedSC, err := c.Setup(t).Extensions().StorageClasses().Update(requestSC)
|
||||
receivedSC, err := c.Setup(t).Storage().StorageClasses().Update(requestSC)
|
||||
c.Validate(t, receivedSC, err)
|
||||
}
|
||||
|
||||
func TestDeleteStorageClass(t *testing.T) {
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{Method: "DELETE", Path: testapi.Extensions.ResourcePath(getStorageClassResourceName(), "", "foo"), Query: simple.BuildQueryValues(nil)},
|
||||
Request: simple.Request{Method: "DELETE", Path: testapi.Storage.ResourcePath(getStorageClassResourceName(), "", "foo"), Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{StatusCode: 200},
|
||||
}
|
||||
err := c.Setup(t).Extensions().StorageClasses().Delete("foo")
|
||||
err := c.Setup(t).Storage().StorageClasses().Delete("foo")
|
||||
c.Validate(t, nil, err)
|
||||
}
|
||||
|
||||
func TestCreateStorageClass(t *testing.T) {
|
||||
requestSC := &extensions.StorageClass{
|
||||
requestSC := &storage.StorageClass{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "aaa",
|
||||
}
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{Method: "POST", Path: testapi.Extensions.ResourcePath(getStorageClassResourceName(), "", ""), Body: requestSC, Query: simple.BuildQueryValues(nil)},
|
||||
Request: simple.Request{Method: "POST", Path: testapi.Storage.ResourcePath(getStorageClassResourceName(), "", ""), Body: requestSC, Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{
|
||||
StatusCode: 200,
|
||||
Body: &extensions.StorageClass{
|
||||
Body: &storage.StorageClass{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
Labels: map[string]string{
|
||||
@ -142,6 +142,6 @@ func TestCreateStorageClass(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
receivedSC, err := c.Setup(t).Extensions().StorageClasses().Create(requestSC)
|
||||
receivedSC, err := c.Setup(t).Storage().StorageClasses().Create(requestSC)
|
||||
c.Validate(t, receivedSC, err)
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ package testclient
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
kclientlib "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/pkg/watch"
|
||||
)
|
||||
@ -26,46 +26,46 @@ import (
|
||||
// FakeStorageClasses implements StorageClassInterface. Meant to be embedded into a struct to get a default
|
||||
// implementation. This makes faking out just the method you want to test easier.
|
||||
type FakeStorageClasses struct {
|
||||
Fake *FakeExperimental
|
||||
Fake *FakeStorage
|
||||
}
|
||||
|
||||
// Ensure statically that FakeStorageClasses implements StorageClassInterface.
|
||||
var _ kclientlib.StorageClassInterface = &FakeStorageClasses{}
|
||||
|
||||
func (c *FakeStorageClasses) Get(name string) (*extensions.StorageClass, error) {
|
||||
obj, err := c.Fake.Invokes(NewGetAction("storageclasses", "", name), &extensions.StorageClass{})
|
||||
func (c *FakeStorageClasses) Get(name string) (*storage.StorageClass, error) {
|
||||
obj, err := c.Fake.Invokes(NewGetAction("storageclasses", "", name), &storage.StorageClass{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*extensions.StorageClass), err
|
||||
return obj.(*storage.StorageClass), err
|
||||
}
|
||||
|
||||
func (c *FakeStorageClasses) List(opts api.ListOptions) (*extensions.StorageClassList, error) {
|
||||
obj, err := c.Fake.Invokes(NewListAction("storageclasses", "", opts), &extensions.StorageClassList{})
|
||||
func (c *FakeStorageClasses) List(opts api.ListOptions) (*storage.StorageClassList, error) {
|
||||
obj, err := c.Fake.Invokes(NewListAction("storageclasses", "", opts), &storage.StorageClassList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*extensions.StorageClassList), err
|
||||
return obj.(*storage.StorageClassList), err
|
||||
}
|
||||
|
||||
func (c *FakeStorageClasses) Create(np *extensions.StorageClass) (*extensions.StorageClass, error) {
|
||||
obj, err := c.Fake.Invokes(NewCreateAction("storageclasses", "", np), &extensions.StorageClass{})
|
||||
func (c *FakeStorageClasses) Create(np *storage.StorageClass) (*storage.StorageClass, error) {
|
||||
obj, err := c.Fake.Invokes(NewCreateAction("storageclasses", "", np), &storage.StorageClass{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*extensions.StorageClass), err
|
||||
return obj.(*storage.StorageClass), err
|
||||
}
|
||||
|
||||
func (c *FakeStorageClasses) Update(np *extensions.StorageClass) (*extensions.StorageClass, error) {
|
||||
obj, err := c.Fake.Invokes(NewUpdateAction("storageclasses", "", np), &extensions.StorageClass{})
|
||||
func (c *FakeStorageClasses) Update(np *storage.StorageClass) (*storage.StorageClass, error) {
|
||||
obj, err := c.Fake.Invokes(NewUpdateAction("storageclasses", "", np), &storage.StorageClass{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*extensions.StorageClass), err
|
||||
return obj.(*storage.StorageClass), err
|
||||
}
|
||||
|
||||
func (c *FakeStorageClasses) Delete(name string) error {
|
||||
_, err := c.Fake.Invokes(NewDeleteAction("storageclasses", "", name), &extensions.StorageClass{})
|
||||
_, err := c.Fake.Invokes(NewDeleteAction("storageclasses", "", name), &storage.StorageClass{})
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,10 @@ func (c *Client) Setup(t *testing.T) *Client {
|
||||
Host: c.server.URL,
|
||||
ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Rbac.GroupVersion()},
|
||||
})
|
||||
c.StorageClient = client.NewStorageOrDie(&restclient.Config{
|
||||
Host: c.server.URL,
|
||||
ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Storage.GroupVersion()},
|
||||
})
|
||||
|
||||
c.Clientset = clientset.NewForConfigOrDie(&restclient.Config{Host: c.server.URL})
|
||||
}
|
||||
|
@ -317,6 +317,10 @@ func (c *Fake) Rbac() client.RbacInterface {
|
||||
return &FakeRbac{Fake: c}
|
||||
}
|
||||
|
||||
func (c *Fake) Storage() client.StorageInterface {
|
||||
return &FakeStorage{Fake: c}
|
||||
}
|
||||
|
||||
func (c *Fake) Authentication() client.AuthenticationInterface {
|
||||
return &FakeAuthentication{Fake: c}
|
||||
}
|
||||
@ -444,10 +448,6 @@ func (c *FakeExperimental) NetworkPolicies(namespace string) client.NetworkPolic
|
||||
return &FakeNetworkPolicies{Fake: c, Namespace: namespace}
|
||||
}
|
||||
|
||||
func (c *FakeExperimental) StorageClasses() client.StorageClassInterface {
|
||||
return &FakeStorageClasses{Fake: c}
|
||||
}
|
||||
|
||||
func NewSimpleFakeRbac(objects ...runtime.Object) *FakeRbac {
|
||||
return &FakeRbac{Fake: NewSimpleFake(objects...)}
|
||||
}
|
||||
@ -472,6 +472,18 @@ func (c *FakeRbac) ClusterRoleBindings() client.ClusterRoleBindingInterface {
|
||||
return &FakeClusterRoleBindings{Fake: c}
|
||||
}
|
||||
|
||||
func NewSimpleFakeStorage(objects ...runtime.Object) *FakeStorage {
|
||||
return &FakeStorage{Fake: NewSimpleFake(objects...)}
|
||||
}
|
||||
|
||||
type FakeStorage struct {
|
||||
*Fake
|
||||
}
|
||||
|
||||
func (c *FakeStorage) StorageClasses() client.StorageClassInterface {
|
||||
return &FakeStorageClasses{Fake: c}
|
||||
}
|
||||
|
||||
type FakeDiscovery struct {
|
||||
*Fake
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
)
|
||||
|
||||
// Test single call to syncClaim and syncVolume methods.
|
||||
@ -503,7 +503,7 @@ func TestSync(t *testing.T) {
|
||||
noevents, noerrors, testSyncClaim,
|
||||
},
|
||||
}
|
||||
runSyncTests(t, tests, []*extensions.StorageClass{})
|
||||
runSyncTests(t, tests, []*storage.StorageClass{})
|
||||
}
|
||||
|
||||
// Test multiple calls to syncClaim/syncVolume and periodic sync of all
|
||||
@ -550,5 +550,5 @@ func TestMultiSync(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
runMultisyncTests(t, tests, []*extensions.StorageClass{}, "")
|
||||
runMultisyncTests(t, tests, []*storage.StorageClass{}, "")
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/client/cache"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/client/record"
|
||||
@ -1366,7 +1366,7 @@ func (ctrl *PersistentVolumeController) scheduleOperation(operationName string,
|
||||
}
|
||||
}
|
||||
|
||||
func (ctrl *PersistentVolumeController) findProvisionablePlugin(claim *api.PersistentVolumeClaim) (vol.ProvisionableVolumePlugin, *extensions.StorageClass, error) {
|
||||
func (ctrl *PersistentVolumeController) findProvisionablePlugin(claim *api.PersistentVolumeClaim) (vol.ProvisionableVolumePlugin, *storage.StorageClass, error) {
|
||||
// TODO: remove this alpha behavior in 1.5
|
||||
alpha := hasAnnotation(claim.ObjectMeta, annAlphaClass)
|
||||
beta := hasAnnotation(claim.ObjectMeta, annClass)
|
||||
@ -1391,7 +1391,7 @@ func (ctrl *PersistentVolumeController) findProvisionablePlugin(claim *api.Persi
|
||||
if !found {
|
||||
return nil, nil, fmt.Errorf("StorageClass %q not found", claimClass)
|
||||
}
|
||||
class, ok := classObj.(*extensions.StorageClass)
|
||||
class, ok := classObj.(*storage.StorageClass)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("Cannot convert object to StorageClass: %+v", classObj)
|
||||
}
|
||||
@ -1407,13 +1407,13 @@ func (ctrl *PersistentVolumeController) findProvisionablePlugin(claim *api.Persi
|
||||
// findAlphaProvisionablePlugin returns a volume plugin compatible with
|
||||
// Kubernetes 1.3.
|
||||
// TODO: remove in Kubernetes 1.5
|
||||
func (ctrl *PersistentVolumeController) findAlphaProvisionablePlugin() (vol.ProvisionableVolumePlugin, *extensions.StorageClass, error) {
|
||||
func (ctrl *PersistentVolumeController) findAlphaProvisionablePlugin() (vol.ProvisionableVolumePlugin, *storage.StorageClass, error) {
|
||||
if ctrl.alphaProvisioner == nil {
|
||||
return nil, nil, fmt.Errorf("cannot find volume plugin for alpha provisioning")
|
||||
}
|
||||
|
||||
// Return a dummy StorageClass instance with no parameters
|
||||
storageClass := &extensions.StorageClass{
|
||||
storageClass := &storage.StorageClass{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/client/cache"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
unversioned_core "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned"
|
||||
@ -111,10 +111,10 @@ func NewPersistentVolumeController(
|
||||
if classSource == nil {
|
||||
classSource = &cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
return kubeClient.Extensions().StorageClasses().List(options)
|
||||
return kubeClient.Storage().StorageClasses().List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
return kubeClient.Extensions().StorageClasses().Watch(options)
|
||||
return kubeClient.Storage().StorageClasses().Watch(options)
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -147,7 +147,7 @@ func NewPersistentVolumeController(
|
||||
controller.classes = cache.NewStore(framework.DeletionHandlingMetaNamespaceKeyFunc)
|
||||
controller.classReflector = cache.NewReflector(
|
||||
classSource,
|
||||
&extensions.StorageClass{},
|
||||
&storage.StorageClass{},
|
||||
controller.classes,
|
||||
syncPeriod,
|
||||
)
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
)
|
||||
|
||||
// Test single call to syncVolume, expecting recycling to happen.
|
||||
@ -134,7 +134,7 @@ func TestDeleteSync(t *testing.T) {
|
||||
wrapTestWithReclaimCalls(operationDelete, []error{nil}, testSyncVolume),
|
||||
},
|
||||
}
|
||||
runSyncTests(t, tests, []*extensions.StorageClass{})
|
||||
runSyncTests(t, tests, []*storage.StorageClass{})
|
||||
}
|
||||
|
||||
// Test multiple calls to syncClaim/syncVolume and periodic sync of all
|
||||
@ -166,5 +166,5 @@ func TestDeleteMultiSync(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
runMultisyncTests(t, tests, []*extensions.StorageClass{}, "")
|
||||
runMultisyncTests(t, tests, []*storage.StorageClass{}, "")
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/client/cache"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
@ -905,7 +905,7 @@ func evaluateTestResults(ctrl *PersistentVolumeController, reactor *volumeReacto
|
||||
// 2. Call the tested function (syncClaim/syncVolume) via
|
||||
// controllerTest.testCall *once*.
|
||||
// 3. Compare resulting volumes and claims with expected volumes and claims.
|
||||
func runSyncTests(t *testing.T, tests []controllerTest, storageClasses []*extensions.StorageClass) {
|
||||
func runSyncTests(t *testing.T, tests []controllerTest, storageClasses []*storage.StorageClass) {
|
||||
for _, test := range tests {
|
||||
glog.V(4).Infof("starting test %q", test.name)
|
||||
|
||||
@ -961,7 +961,7 @@ func runSyncTests(t *testing.T, tests []controllerTest, storageClasses []*extens
|
||||
// 5. When 3. does not do any changes, finish the tests and compare final set
|
||||
// of volumes/claims with expected claims/volumes and report differences.
|
||||
// Some limit of calls in enforced to prevent endless loops.
|
||||
func runMultisyncTests(t *testing.T, tests []controllerTest, storageClasses []*extensions.StorageClass, defaultStorageClass string) {
|
||||
func runMultisyncTests(t *testing.T, tests []controllerTest, storageClasses []*storage.StorageClass, defaultStorageClass string) {
|
||||
for _, test := range tests {
|
||||
glog.V(4).Infof("starting multisync test %q", test.name)
|
||||
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
)
|
||||
|
||||
var class1Parameters = map[string]string{
|
||||
@ -31,7 +31,7 @@ var class1Parameters = map[string]string{
|
||||
var class2Parameters = map[string]string{
|
||||
"param2": "value2",
|
||||
}
|
||||
var storageClasses = []*extensions.StorageClass{
|
||||
var storageClasses = []*storage.StorageClass{
|
||||
{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
@ -345,7 +345,7 @@ func TestAlphaProvisionSync(t *testing.T) {
|
||||
noevents, noerrors, wrapTestWithProvisionCalls([]provisionCall{provisionAlphaSuccess}, testSyncClaim),
|
||||
},
|
||||
}
|
||||
runSyncTests(t, tests, []*extensions.StorageClass{})
|
||||
runSyncTests(t, tests, []*storage.StorageClass{})
|
||||
}
|
||||
|
||||
// Test multiple calls to syncClaim/syncVolume and periodic sync of all
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
)
|
||||
|
||||
// Test single call to syncVolume, expecting recycling to happen.
|
||||
@ -161,7 +161,7 @@ func TestRecycleSync(t *testing.T) {
|
||||
[]string{"Warning VolumeUnknownReclaimPolicy"}, noerrors, testSyncVolume,
|
||||
},
|
||||
}
|
||||
runSyncTests(t, tests, []*extensions.StorageClass{})
|
||||
runSyncTests(t, tests, []*storage.StorageClass{})
|
||||
}
|
||||
|
||||
// Test multiple calls to syncClaim/syncVolume and periodic sync of all
|
||||
@ -193,5 +193,5 @@ func TestRecycleMultiSync(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
runMultisyncTests(t, tests, []*extensions.StorageClass{}, "")
|
||||
runMultisyncTests(t, tests, []*storage.StorageClass{}, "")
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
||||
@ -1151,6 +1152,11 @@ func (c *clientSwaggerSchema) ValidateBytes(data []byte) error {
|
||||
return errors.New("unable to validate: no rbac client")
|
||||
}
|
||||
return getSchemaAndValidate(c.c.RbacClient.RESTClient, data, "apis/", gvk.GroupVersion().String(), c.cacheDir, c)
|
||||
case storage.GroupName:
|
||||
if c.c.StorageClient == nil {
|
||||
return errors.New("unable to validate: no storage client")
|
||||
}
|
||||
return getSchemaAndValidate(c.c.StorageClient.RESTClient, data, "apis/", gvk.GroupVersion().String(), c.cacheDir, c)
|
||||
}
|
||||
if registered.IsThirdPartyAPIGroupVersion(gvk.GroupVersion()) {
|
||||
// Don't attempt to validate third party objects
|
||||
|
@ -42,6 +42,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/apis/certificates"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
utilerrors "k8s.io/kubernetes/pkg/util/errors"
|
||||
@ -2068,7 +2069,7 @@ func printNetworkPolicyList(list *extensions.NetworkPolicyList, w io.Writer, opt
|
||||
return nil
|
||||
}
|
||||
|
||||
func printStorageClass(sc *extensions.StorageClass, w io.Writer, options PrintOptions) error {
|
||||
func printStorageClass(sc *storage.StorageClass, w io.Writer, options PrintOptions) error {
|
||||
name := sc.Name
|
||||
provtype := sc.Provisioner
|
||||
|
||||
@ -2085,7 +2086,7 @@ func printStorageClass(sc *extensions.StorageClass, w io.Writer, options PrintOp
|
||||
return nil
|
||||
}
|
||||
|
||||
func printStorageClassList(scList *extensions.StorageClassList, w io.Writer, options PrintOptions) error {
|
||||
func printStorageClassList(scList *storage.StorageClassList, w io.Writer, options PrintOptions) error {
|
||||
for _, sc := range scList.Items {
|
||||
if err := printStorageClass(&sc, w, options); err != nil {
|
||||
return err
|
||||
|
@ -33,6 +33,7 @@ import (
|
||||
_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/policy/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/rbac/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/storage/install"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -49,6 +49,8 @@ import (
|
||||
policyapiv1alpha1 "k8s.io/kubernetes/pkg/apis/policy/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
rbacapi "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
storageapiv1beta1 "k8s.io/kubernetes/pkg/apis/storage/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/apiserver"
|
||||
apiservermetrics "k8s.io/kubernetes/pkg/apiserver/metrics"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||
@ -205,6 +207,7 @@ func New(c *Config) (*Master, error) {
|
||||
}
|
||||
c.RESTStorageProviders[policy.GroupName] = PolicyRESTStorageProvider{}
|
||||
c.RESTStorageProviders[rbac.GroupName] = RBACRESTStorageProvider{AuthorizerRBACSuperUser: c.AuthorizerRBACSuperUser}
|
||||
c.RESTStorageProviders[storage.GroupName] = StorageRESTStorageProvider{}
|
||||
c.RESTStorageProviders[authenticationv1beta1.GroupName] = AuthenticationRESTStorageProvider{Authenticator: c.Authenticator}
|
||||
c.RESTStorageProviders[authorization.GroupName] = AuthorizationRESTStorageProvider{Authorizer: c.Authorizer}
|
||||
m.InstallAPIs(c)
|
||||
@ -840,6 +843,7 @@ func DefaultAPIResourceConfigSource() *genericapiserver.ResourceConfig {
|
||||
appsapi.SchemeGroupVersion,
|
||||
policyapiv1alpha1.SchemeGroupVersion,
|
||||
rbacapi.SchemeGroupVersion,
|
||||
storageapiv1beta1.SchemeGroupVersion,
|
||||
certificatesapiv1alpha1.SchemeGroupVersion,
|
||||
authorizationapiv1beta1.SchemeGroupVersion,
|
||||
)
|
||||
@ -854,7 +858,6 @@ func DefaultAPIResourceConfigSource() *genericapiserver.ResourceConfig {
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("networkpolicies"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("thirdpartyresources"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("storageclasses"),
|
||||
)
|
||||
|
||||
return ret
|
||||
|
@ -35,7 +35,6 @@ import (
|
||||
networkpolicyetcd "k8s.io/kubernetes/pkg/registry/networkpolicy/etcd"
|
||||
pspetcd "k8s.io/kubernetes/pkg/registry/podsecuritypolicy/etcd"
|
||||
replicasetetcd "k8s.io/kubernetes/pkg/registry/replicaset/etcd"
|
||||
storageclassetcd "k8s.io/kubernetes/pkg/registry/storageclass/etcd"
|
||||
thirdpartyresourceetcd "k8s.io/kubernetes/pkg/registry/thirdpartyresource/etcd"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
)
|
||||
@ -124,10 +123,6 @@ func (p ExtensionsRESTStorageProvider) v1beta1Storage(apiResourceConfigSource ge
|
||||
networkExtensionsStorage := networkpolicyetcd.NewREST(restOptionsGetter(extensions.Resource("networkpolicies")))
|
||||
storage["networkpolicies"] = networkExtensionsStorage
|
||||
}
|
||||
if apiResourceConfigSource.ResourceEnabled(version.WithResource("storageclasses")) {
|
||||
storageClassStorage := storageclassetcd.NewREST(restOptionsGetter(extensions.Resource("storageclasses")))
|
||||
storage["storageclasses"] = storageClassStorage
|
||||
}
|
||||
|
||||
return storage
|
||||
}
|
||||
|
54
pkg/master/storage_storage.go
Normal file
54
pkg/master/storage_storage.go
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package master
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/rest"
|
||||
storageapi "k8s.io/kubernetes/pkg/apis/storage"
|
||||
storageapiv1beta1 "k8s.io/kubernetes/pkg/apis/storage/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||
storageclassetcd "k8s.io/kubernetes/pkg/registry/storageclass/etcd"
|
||||
)
|
||||
|
||||
type StorageRESTStorageProvider struct {
|
||||
}
|
||||
|
||||
var _ RESTStorageProvider = &StorageRESTStorageProvider{}
|
||||
|
||||
func (p StorageRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
|
||||
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(storageapi.GroupName)
|
||||
|
||||
if apiResourceConfigSource.AnyResourcesForVersionEnabled(storageapiv1beta1.SchemeGroupVersion) {
|
||||
apiGroupInfo.VersionedResourcesStorageMap[storageapiv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter)
|
||||
apiGroupInfo.GroupMeta.GroupVersion = storageapiv1beta1.SchemeGroupVersion
|
||||
}
|
||||
|
||||
return apiGroupInfo, true
|
||||
}
|
||||
|
||||
func (p StorageRESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage {
|
||||
version := storageapiv1beta1.SchemeGroupVersion
|
||||
|
||||
storage := map[string]rest.Storage{}
|
||||
|
||||
if apiResourceConfigSource.ResourceEnabled(version.WithResource("storageclasses")) {
|
||||
storageClassStorage := storageclassetcd.NewREST(restOptionsGetter(storageapi.Resource("storageclasses")))
|
||||
storage["storageclasses"] = storageClassStorage
|
||||
}
|
||||
|
||||
return storage
|
||||
}
|
@ -18,7 +18,7 @@ package etcd
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
storageapi "k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/registry/cachesize"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
"k8s.io/kubernetes/pkg/registry/generic/registry"
|
||||
@ -35,11 +35,11 @@ type REST struct {
|
||||
func NewREST(opts generic.RESTOptions) *REST {
|
||||
prefix := "/" + opts.ResourcePrefix
|
||||
|
||||
newListFunc := func() runtime.Object { return &extensions.StorageClassList{} }
|
||||
newListFunc := func() runtime.Object { return &storageapi.StorageClassList{} }
|
||||
storageInterface, _ := opts.Decorator(
|
||||
opts.StorageConfig,
|
||||
cachesize.GetWatchCacheSizeByResource(cachesize.StorageClasses),
|
||||
&extensions.StorageClass{},
|
||||
&storageapi.StorageClass{},
|
||||
prefix,
|
||||
storageclass.Strategy,
|
||||
newListFunc,
|
||||
@ -47,7 +47,7 @@ func NewREST(opts generic.RESTOptions) *REST {
|
||||
)
|
||||
|
||||
store := ®istry.Store{
|
||||
NewFunc: func() runtime.Object { return &extensions.StorageClass{} },
|
||||
NewFunc: func() runtime.Object { return &storageapi.StorageClass{} },
|
||||
NewListFunc: newListFunc,
|
||||
KeyRootFunc: func(ctx api.Context) string {
|
||||
return prefix
|
||||
@ -56,10 +56,10 @@ func NewREST(opts generic.RESTOptions) *REST {
|
||||
return registry.NoNamespaceKeyFunc(ctx, prefix, name)
|
||||
},
|
||||
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
||||
return obj.(*extensions.StorageClass).Name, nil
|
||||
return obj.(*storageapi.StorageClass).Name, nil
|
||||
},
|
||||
PredicateFunc: storageclass.MatchStorageClasses,
|
||||
QualifiedResource: api.Resource("storageclasses"),
|
||||
QualifiedResource: storageapi.Resource("storageclasses"),
|
||||
DeleteCollectionWorkers: opts.DeleteCollectionWorkers,
|
||||
|
||||
CreateStrategy: storageclass.Strategy,
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
storageapi "k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
@ -30,14 +30,14 @@ import (
|
||||
)
|
||||
|
||||
func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) {
|
||||
etcdStorage, server := registrytest.NewEtcdStorage(t, extensions.GroupName)
|
||||
etcdStorage, server := registrytest.NewEtcdStorage(t, storageapi.GroupName)
|
||||
restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1}
|
||||
storageClassStorage := NewREST(restOptions)
|
||||
return storageClassStorage, server
|
||||
}
|
||||
|
||||
func validNewStorageClass(name string) *extensions.StorageClass {
|
||||
return &extensions.StorageClass{
|
||||
func validNewStorageClass(name string) *storageapi.StorageClass {
|
||||
return &storageapi.StorageClass{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
@ -48,7 +48,7 @@ func validNewStorageClass(name string) *extensions.StorageClass {
|
||||
}
|
||||
}
|
||||
|
||||
func validChangedStorageClass() *extensions.StorageClass {
|
||||
func validChangedStorageClass() *storageapi.StorageClass {
|
||||
return validNewStorageClass("foo")
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ func TestCreate(t *testing.T) {
|
||||
// valid
|
||||
storageClass,
|
||||
// invalid
|
||||
&extensions.StorageClass{
|
||||
&storageapi.StorageClass{
|
||||
ObjectMeta: api.ObjectMeta{Name: "*BadName!"},
|
||||
},
|
||||
)
|
||||
@ -77,13 +77,13 @@ func TestUpdate(t *testing.T) {
|
||||
validNewStorageClass("foo"),
|
||||
// updateFunc
|
||||
func(obj runtime.Object) runtime.Object {
|
||||
object := obj.(*extensions.StorageClass)
|
||||
object := obj.(*storageapi.StorageClass)
|
||||
object.Parameters = map[string]string{"foo": "bar"}
|
||||
return object
|
||||
},
|
||||
//invalid update
|
||||
func(obj runtime.Object) runtime.Object {
|
||||
object := obj.(*extensions.StorageClass)
|
||||
object := obj.(*storageapi.StorageClass)
|
||||
object.Parameters = map[string]string{"faz": "bar"}
|
||||
return object
|
||||
},
|
||||
|
@ -20,8 +20,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions/validation"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/apis/storage/validation"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
@ -45,11 +45,11 @@ func (storageClassStrategy) NamespaceScoped() bool {
|
||||
|
||||
// ResetBeforeCreate clears the Status field which is not allowed to be set by end users on creation.
|
||||
func (storageClassStrategy) PrepareForCreate(ctx api.Context, obj runtime.Object) {
|
||||
_ = obj.(*extensions.StorageClass)
|
||||
_ = obj.(*storage.StorageClass)
|
||||
}
|
||||
|
||||
func (storageClassStrategy) Validate(ctx api.Context, obj runtime.Object) field.ErrorList {
|
||||
storageClass := obj.(*extensions.StorageClass)
|
||||
storageClass := obj.(*storage.StorageClass)
|
||||
return validation.ValidateStorageClass(storageClass)
|
||||
}
|
||||
|
||||
@ -63,13 +63,13 @@ func (storageClassStrategy) AllowCreateOnUpdate() bool {
|
||||
|
||||
// PrepareForUpdate sets the Status fields which is not allowed to be set by an end user updating a PV
|
||||
func (storageClassStrategy) PrepareForUpdate(ctx api.Context, obj, old runtime.Object) {
|
||||
_ = obj.(*extensions.StorageClass)
|
||||
_ = old.(*extensions.StorageClass)
|
||||
_ = obj.(*storage.StorageClass)
|
||||
_ = old.(*storage.StorageClass)
|
||||
}
|
||||
|
||||
func (storageClassStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList {
|
||||
errorList := validation.ValidateStorageClass(obj.(*extensions.StorageClass))
|
||||
return append(errorList, validation.ValidateStorageClassUpdate(obj.(*extensions.StorageClass), old.(*extensions.StorageClass))...)
|
||||
errorList := validation.ValidateStorageClass(obj.(*storage.StorageClass))
|
||||
return append(errorList, validation.ValidateStorageClassUpdate(obj.(*storage.StorageClass), old.(*storage.StorageClass))...)
|
||||
}
|
||||
|
||||
func (storageClassStrategy) AllowUnconditionalUpdate() bool {
|
||||
@ -82,7 +82,7 @@ func MatchStorageClasses(label labels.Selector, field fields.Selector) *generic.
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
cls, ok := obj.(*extensions.StorageClass)
|
||||
cls, ok := obj.(*storage.StorageClass)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("given object is not of type StorageClass")
|
||||
}
|
||||
@ -93,6 +93,6 @@ func MatchStorageClasses(label labels.Selector, field fields.Selector) *generic.
|
||||
}
|
||||
|
||||
// StorageClassToSelectableFields returns a label set that represents the object
|
||||
func StorageClassToSelectableFields(storageClass *extensions.StorageClass) fields.Set {
|
||||
func StorageClassToSelectableFields(storageClass *storage.StorageClass) fields.Set {
|
||||
return generic.ObjectMetaFieldsSet(&storageClass.ObjectMeta, false)
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
)
|
||||
|
||||
func TestStorageClassStrategy(t *testing.T) {
|
||||
@ -32,7 +32,7 @@ func TestStorageClassStrategy(t *testing.T) {
|
||||
t.Errorf("StorageClass should not allow create on update")
|
||||
}
|
||||
|
||||
storageClass := &extensions.StorageClass{
|
||||
storageClass := &storage.StorageClass{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "valid-class",
|
||||
},
|
||||
@ -49,7 +49,7 @@ func TestStorageClassStrategy(t *testing.T) {
|
||||
t.Errorf("unexpected error validating %v", errs)
|
||||
}
|
||||
|
||||
newStorageClass := &extensions.StorageClass{
|
||||
newStorageClass := &storage.StorageClass{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "valid-class-2",
|
||||
ResourceVersion: "4",
|
||||
|
@ -25,7 +25,7 @@ import (
|
||||
admission "k8s.io/kubernetes/pkg/admission"
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/client/cache"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
@ -62,13 +62,13 @@ func newPlugin(kclient clientset.Interface) *claimDefaulterPlugin {
|
||||
reflector := cache.NewReflector(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||
return kclient.Extensions().StorageClasses().List(options)
|
||||
return kclient.Storage().StorageClasses().List(options)
|
||||
},
|
||||
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||
return kclient.Extensions().StorageClasses().Watch(options)
|
||||
return kclient.Storage().StorageClasses().Watch(options)
|
||||
},
|
||||
},
|
||||
&extensions.StorageClass{},
|
||||
&storage.StorageClass{},
|
||||
store,
|
||||
0,
|
||||
)
|
||||
@ -147,10 +147,10 @@ func (c *claimDefaulterPlugin) Admit(a admission.Attributes) error {
|
||||
}
|
||||
|
||||
// getDefaultClass returns the default StorageClass from the store, or nil.
|
||||
func getDefaultClass(store cache.Store) (*extensions.StorageClass, error) {
|
||||
defaultClasses := []*extensions.StorageClass{}
|
||||
func getDefaultClass(store cache.Store) (*storage.StorageClass, error) {
|
||||
defaultClasses := []*storage.StorageClass{}
|
||||
for _, c := range store.List() {
|
||||
class, ok := c.(*extensions.StorageClass)
|
||||
class, ok := c.(*storage.StorageClass)
|
||||
if !ok {
|
||||
return nil, errors.NewInternalError(fmt.Errorf("error converting stored object to StorageClass: %v", c))
|
||||
}
|
||||
|
@ -24,12 +24,12 @@ import (
|
||||
"k8s.io/kubernetes/pkg/admission"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
)
|
||||
|
||||
func TestAdmission(t *testing.T) {
|
||||
defaultClass1 := &extensions.StorageClass{
|
||||
defaultClass1 := &storage.StorageClass{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
@ -41,7 +41,7 @@ func TestAdmission(t *testing.T) {
|
||||
},
|
||||
Provisioner: "default1",
|
||||
}
|
||||
defaultClass2 := &extensions.StorageClass{
|
||||
defaultClass2 := &storage.StorageClass{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
@ -54,7 +54,7 @@ func TestAdmission(t *testing.T) {
|
||||
Provisioner: "default2",
|
||||
}
|
||||
// Class that has explicit default = false
|
||||
classWithFalseDefault := &extensions.StorageClass{
|
||||
classWithFalseDefault := &storage.StorageClass{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
@ -67,7 +67,7 @@ func TestAdmission(t *testing.T) {
|
||||
Provisioner: "nondefault1",
|
||||
}
|
||||
// Class with missing default annotation (=non-default)
|
||||
classWithNoDefault := &extensions.StorageClass{
|
||||
classWithNoDefault := &storage.StorageClass{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
@ -77,7 +77,7 @@ func TestAdmission(t *testing.T) {
|
||||
Provisioner: "nondefault1",
|
||||
}
|
||||
// Class with empty default annotation (=non-default)
|
||||
classWithEmptyDefault := &extensions.StorageClass{
|
||||
classWithEmptyDefault := &storage.StorageClass{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
@ -126,56 +126,56 @@ func TestAdmission(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
classes []*extensions.StorageClass
|
||||
classes []*storage.StorageClass
|
||||
claim *api.PersistentVolumeClaim
|
||||
expectError bool
|
||||
expectedClassName string
|
||||
}{
|
||||
{
|
||||
"no default, no modification of PVCs",
|
||||
[]*extensions.StorageClass{classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
[]*storage.StorageClass{classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
claimWithNoClass,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"one default, modify PVC with class=nil",
|
||||
[]*extensions.StorageClass{defaultClass1, classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
[]*storage.StorageClass{defaultClass1, classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
claimWithNoClass,
|
||||
false,
|
||||
"default1",
|
||||
},
|
||||
{
|
||||
"one default, no modification of PVC with class=''",
|
||||
[]*extensions.StorageClass{defaultClass1, classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
[]*storage.StorageClass{defaultClass1, classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
claimWithEmptyClass,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"one default, no modification of PVC with class='foo'",
|
||||
[]*extensions.StorageClass{defaultClass1, classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
[]*storage.StorageClass{defaultClass1, classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
claimWithClass,
|
||||
false,
|
||||
"foo",
|
||||
},
|
||||
{
|
||||
"two defaults, error with PVC with class=nil",
|
||||
[]*extensions.StorageClass{defaultClass1, defaultClass2, classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
[]*storage.StorageClass{defaultClass1, defaultClass2, classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
claimWithNoClass,
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"two defaults, no modification of PVC with class=''",
|
||||
[]*extensions.StorageClass{defaultClass1, defaultClass2, classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
[]*storage.StorageClass{defaultClass1, defaultClass2, classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
claimWithEmptyClass,
|
||||
false,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"two defaults, no modification of PVC with class='foo'",
|
||||
[]*extensions.StorageClass{defaultClass1, defaultClass2, classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
[]*storage.StorageClass{defaultClass1, defaultClass2, classWithFalseDefault, classWithNoDefault, classWithEmptyDefault},
|
||||
claimWithClass,
|
||||
false,
|
||||
"foo",
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
|
||||
@ -119,8 +119,8 @@ var _ = framework.KubeDescribe("Dynamic provisioning", func() {
|
||||
|
||||
By("creating a StorageClass")
|
||||
class := newStorageClass()
|
||||
_, err := c.Extensions().StorageClasses().Create(class)
|
||||
defer c.Extensions().StorageClasses().Delete(class.Name)
|
||||
_, err := c.Storage().StorageClasses().Create(class)
|
||||
defer c.Storage().StorageClasses().Delete(class.Name)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("creating a claim with a dynamic provisioning annotation")
|
||||
@ -231,7 +231,7 @@ func runInPodWithVolume(c *client.Client, ns, claimName, command string) {
|
||||
framework.ExpectNoError(framework.WaitForPodSuccessInNamespaceSlow(c, pod.Name, pod.Spec.Containers[0].Name, pod.Namespace))
|
||||
}
|
||||
|
||||
func newStorageClass() *extensions.StorageClass {
|
||||
func newStorageClass() *storage.StorageClass {
|
||||
var pluginName string
|
||||
|
||||
switch {
|
||||
@ -243,7 +243,7 @@ func newStorageClass() *extensions.StorageClass {
|
||||
pluginName = "kubernetes.io/cinder"
|
||||
}
|
||||
|
||||
return &extensions.StorageClass{
|
||||
return &storage.StorageClass{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
|
@ -37,6 +37,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/client/record"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
@ -209,6 +210,10 @@ func NewMasterConfig() *master.Config {
|
||||
unversioned.GroupResource{Group: certificates.GroupName, Resource: genericapiserver.AllResources},
|
||||
"",
|
||||
NewSingleContentTypeSerializer(api.Scheme, testapi.Certificates.Codec(), runtime.ContentTypeJSON))
|
||||
storageFactory.SetSerializer(
|
||||
unversioned.GroupResource{Group: storage.GroupName, Resource: genericapiserver.AllResources},
|
||||
"",
|
||||
NewSingleContentTypeSerializer(api.Scheme, testapi.Storage.Codec(), runtime.ContentTypeJSON))
|
||||
|
||||
return &master.Config{
|
||||
Config: &genericapiserver.Config{
|
||||
|
@ -31,7 +31,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
fake_cloud "k8s.io/kubernetes/pkg/cloudprovider/providers/fake"
|
||||
@ -862,9 +862,9 @@ func TestPersistentVolumeProvisionMultiPVCs(t *testing.T) {
|
||||
// NOTE: This test cannot run in parallel, because it is creating and deleting
|
||||
// non-namespaced objects (PersistenceVolumes and StorageClasses).
|
||||
defer testClient.Core().PersistentVolumes().DeleteCollection(nil, api.ListOptions{})
|
||||
defer testClient.Extensions().StorageClasses().DeleteCollection(nil, api.ListOptions{})
|
||||
defer testClient.Storage().StorageClasses().DeleteCollection(nil, api.ListOptions{})
|
||||
|
||||
storageClass := extensions.StorageClass{
|
||||
storageClass := storage.StorageClass{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
@ -873,7 +873,7 @@ func TestPersistentVolumeProvisionMultiPVCs(t *testing.T) {
|
||||
},
|
||||
Provisioner: provisionerPluginName,
|
||||
}
|
||||
testClient.Extensions().StorageClasses().Create(&storageClass)
|
||||
testClient.Storage().StorageClasses().Create(&storageClass)
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
binder.Run(stopCh)
|
||||
|
@ -27,7 +27,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/test/integration/framework"
|
||||
@ -51,7 +51,7 @@ func TestStorageClasses(t *testing.T) {
|
||||
// DoTestStorageClasses tests storage classes for one api version.
|
||||
func DoTestStorageClasses(t *testing.T, client *client.Client, ns *api.Namespace) {
|
||||
// Make a storage class object.
|
||||
s := extensions.StorageClass{
|
||||
s := storage.StorageClass{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
@ -61,7 +61,7 @@ func DoTestStorageClasses(t *testing.T, client *client.Client, ns *api.Namespace
|
||||
Provisioner: provisionerPluginName,
|
||||
}
|
||||
|
||||
if _, err := client.Extensions().StorageClasses().Create(&s); err != nil {
|
||||
if _, err := client.Storage().StorageClasses().Create(&s); err != nil {
|
||||
t.Errorf("unable to create test storage class: %v", err)
|
||||
}
|
||||
defer deleteStorageClassOrErrorf(t, client, s.Namespace, s.Name)
|
||||
@ -89,7 +89,7 @@ func DoTestStorageClasses(t *testing.T, client *client.Client, ns *api.Namespace
|
||||
}
|
||||
|
||||
func deleteStorageClassOrErrorf(t *testing.T, c *client.Client, ns, name string) {
|
||||
if err := c.Extensions().StorageClasses().Delete(name); err != nil {
|
||||
if err := c.Storage().StorageClasses().Delete(name); err != nil {
|
||||
t.Errorf("unable to delete storage class %v: %v", name, err)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user