mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 12:15:52 +00:00
Merge pull request #21434 from erictune/job-ga
Auto commit by PR queue bot
This commit is contained in:
commit
aee2eb3977
30
api/swagger-spec/batch.json
Normal file
30
api/swagger-spec/batch.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"swaggerVersion": "1.2",
|
||||
"apiVersion": "",
|
||||
"basePath": "https://10.10.10.10:443",
|
||||
"resourcePath": "/apis/batch",
|
||||
"apis": [
|
||||
{
|
||||
"path": "/apis/batch",
|
||||
"description": "get information of a group",
|
||||
"operations": [
|
||||
{
|
||||
"type": "void",
|
||||
"method": "GET",
|
||||
"summary": "get information of a group",
|
||||
"nickname": "getAPIGroup",
|
||||
"parameters": [],
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/yaml"
|
||||
],
|
||||
"consumes": [
|
||||
"application/json",
|
||||
"application/yaml"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"models": {}
|
||||
}
|
2429
api/swagger-spec/batch_v1.json
Normal file
2429
api/swagger-spec/batch_v1.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -32,6 +32,14 @@
|
||||
{
|
||||
"path": "/apis/autoscaling",
|
||||
"description": "get information of a group"
|
||||
},
|
||||
{
|
||||
"path": "/apis/batch/v1",
|
||||
"description": "API at /apis/batch/v1"
|
||||
},
|
||||
{
|
||||
"path": "/apis/batch",
|
||||
"description": "get information of a group"
|
||||
}
|
||||
],
|
||||
"apiVersion": "",
|
||||
|
@ -28,6 +28,7 @@ import (
|
||||
_ "k8s.io/kubernetes/pkg/api/install"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/batch/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/metrics/install"
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
_ "k8s.io/kubernetes/pkg/api/install"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/batch/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/metrics/install"
|
||||
|
@ -38,6 +38,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apiserver"
|
||||
"k8s.io/kubernetes/pkg/apiserver/authenticator"
|
||||
@ -305,6 +306,11 @@ func Run(s *options.APIServer) error {
|
||||
// sure autoscaling has a storage destination. If the autoscaling group
|
||||
// itself is on, it will overwrite this decision below.
|
||||
storageDestinations.AddAPIGroup(autoscaling.GroupName, expEtcdStorage)
|
||||
|
||||
// Since Job has been moved to the batch group, we need to make
|
||||
// sure batch has a storage destination. If the batch group
|
||||
// itself is on, it will overwrite this decision below.
|
||||
storageDestinations.AddAPIGroup(batch.GroupName, expEtcdStorage)
|
||||
}
|
||||
|
||||
// autoscaling/v1/horizontalpodautoscalers is a move from extensions/v1beta1/horizontalpodautoscalers.
|
||||
@ -333,6 +339,33 @@ func Run(s *options.APIServer) error {
|
||||
storageDestinations.AddAPIGroup(autoscaling.GroupName, autoscalingEtcdStorage)
|
||||
}
|
||||
|
||||
// batch/v1/job is a move from extensions/v1beta1/job. The storage
|
||||
// version needs to be either extensions/v1beta1 or batch/v1. Users
|
||||
// must roll forward while using 1.2, because we will require the
|
||||
// latter for 1.3.
|
||||
if !apiGroupVersionOverrides["batch/v1"].Disable {
|
||||
glog.Infof("Configuring batch/v1 storage destination")
|
||||
batchGroup, err := registered.Group(batch.GroupName)
|
||||
if err != nil {
|
||||
glog.Fatalf("Batch API is enabled in runtime config, but not enabled in the environment variable KUBE_API_VERSIONS. Error: %v", err)
|
||||
}
|
||||
// Figure out what storage group/version we should use.
|
||||
storageGroupVersion, found := storageVersions[batchGroup.GroupVersion.Group]
|
||||
if !found {
|
||||
glog.Fatalf("Couldn't find the storage version for group: %q in storageVersions: %v", batchGroup.GroupVersion.Group, storageVersions)
|
||||
}
|
||||
|
||||
if storageGroupVersion != "batch/v1" && storageGroupVersion != "extensions/v1beta1" {
|
||||
glog.Fatalf("The storage version for batch must be either 'batch/v1' or 'extensions/v1beta1'")
|
||||
}
|
||||
glog.Infof("Using %v for batch group storage version", storageGroupVersion)
|
||||
batchEtcdStorage, err := newEtcd(s.EtcdServerList, api.Codecs, storageGroupVersion, "extensions/__internal", s.EtcdPathPrefix, s.EtcdQuorumRead)
|
||||
if err != nil {
|
||||
glog.Fatalf("Invalid extensions storage version or misconfigured etcd: %v", err)
|
||||
}
|
||||
storageDestinations.AddAPIGroup(batch.GroupName, batchEtcdStorage)
|
||||
}
|
||||
|
||||
updateEtcdOverrides(s.EtcdServersOverrides, storageVersions, s.EtcdPathPrefix, s.EtcdQuorumRead, &storageDestinations, newEtcd)
|
||||
|
||||
n := s.ServiceClusterIPRange
|
||||
@ -520,6 +553,14 @@ func parseRuntimeConfig(s *options.APIServer) (map[string]genericapiserver.APIGr
|
||||
Disable: true,
|
||||
}
|
||||
}
|
||||
disableBatch := disableAllAPIs
|
||||
batchGroupVersion := "batch/v1"
|
||||
disableBatch = !getRuntimeConfigValue(s, batchGroupVersion, !disableBatch)
|
||||
if disableBatch {
|
||||
apiGroupVersionOverrides[batchGroupVersion] = genericapiserver.APIGroupVersionOverride{
|
||||
Disable: true,
|
||||
}
|
||||
}
|
||||
|
||||
for key := range s.RuntimeConfig {
|
||||
if strings.HasPrefix(key, v1GroupVersion+"/") {
|
||||
|
@ -394,6 +394,7 @@ _kubectl_describe()
|
||||
must_have_one_noun+=("horizontalpodautoscaler")
|
||||
must_have_one_noun+=("ingress")
|
||||
must_have_one_noun+=("job")
|
||||
must_have_one_noun+=("job")
|
||||
must_have_one_noun+=("limitrange")
|
||||
must_have_one_noun+=("namespace")
|
||||
must_have_one_noun+=("node")
|
||||
|
@ -102,7 +102,7 @@ kube-apiserver
|
||||
--service-node-port-range=: A port range to reserve for services with NodePort visibility. Example: '30000-32767'. Inclusive at both ends of the range.
|
||||
--ssh-keyfile="": If non-empty, use secure SSH proxy to the nodes, using this user keyfile
|
||||
--ssh-user="": If non-empty, use secure SSH proxy to the nodes, using this user name
|
||||
--storage-versions="authorization.k8s.io/v1beta1,autoscaling/v1,componentconfig/v1alpha1,extensions/v1beta1,metrics/v1alpha1,v1": The per-group version to store resources in. Specified in the format "group1/version1,group2/version2,...". In the case where objects are moved from one group to the other, you may specify the format "group1=group2/v1beta1,group3/v1beta1,...". You only need to pass the groups you wish to change from the defaults. It defaults to a list of preferred versions of all registered groups, which is derived from the KUBE_API_VERSIONS environment variable.
|
||||
--storage-versions="authorization.k8s.io/v1beta1,autoscaling/v1,batch/v1,componentconfig/v1alpha1,extensions/v1beta1,metrics/v1alpha1,v1": The per-group version to store resources in. Specified in the format "group1/version1,group2/version2,...". In the case where objects are moved from one group to the other, you may specify the format "group1=group2/v1beta1,group3/v1beta1,...". You only need to pass the groups you wish to change from the defaults. It defaults to a list of preferred versions of all registered groups, which is derived from the KUBE_API_VERSIONS environment variable.
|
||||
--tls-cert-file="": File containing x509 Certificate for HTTPS. (CA cert, if any, concatenated after server cert). If HTTPS serving is enabled, and --tls-cert-file and --tls-private-key-file are not provided, a self-signed certificate and key are generated for the public address and saved to /var/run/kubernetes.
|
||||
--tls-private-key-file="": File containing x509 private key matching --tls-cert-file.
|
||||
--token-auth-file="": If set, the file that will be used to secure the secure port of the API server via token authentication.
|
||||
@ -110,7 +110,7 @@ kube-apiserver
|
||||
--watch-cache-sizes=[]: List of watch cache sizes for every resource (pods, nodes, etc.), comma separated. The individual override format: resource#size, where size is a number. It takes effect when watch-cache is enabled.
|
||||
```
|
||||
|
||||
###### Auto generated by spf13/cobra on 15-Feb-2016
|
||||
###### Auto generated by spf13/cobra on 18-Feb-2016
|
||||
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
|
@ -43,7 +43,7 @@ EOF
|
||||
}
|
||||
|
||||
# TODO(lavalamp): get this list by listing the pkg/apis/ directory?
|
||||
DEFAULT_GROUP_VERSIONS="v1 authorization/v1beta1 autoscaling/v1 extensions/v1beta1 componentconfig/v1alpha1 metrics/v1alpha1"
|
||||
DEFAULT_GROUP_VERSIONS="v1 authorization/v1beta1 autoscaling/v1 batch/v1 extensions/v1beta1 componentconfig/v1alpha1 metrics/v1alpha1"
|
||||
VERSIONS=${VERSIONS:-$DEFAULT_GROUP_VERSIONS}
|
||||
for ver in $VERSIONS; do
|
||||
# Ensure that the version being processed is registered by setting
|
||||
|
@ -62,6 +62,6 @@ function generate_deep_copies() {
|
||||
# Currently pkg/api/deep_copy_generated.go is generated by the new go2idl generator.
|
||||
# All others (mentioned above) are still generated by the old reflection-based generator.
|
||||
# TODO: Migrate these to the new generator.
|
||||
DEFAULT_VERSIONS="v1 authorization/__internal authorization/v1beta1 autoscaling/__internal autoscaling/v1 extensions/__internal extensions/v1beta1 componentconfig/__internal componentconfig/v1alpha1 metrics/__internal metrics/v1alpha1"
|
||||
DEFAULT_VERSIONS="v1 authorization/__internal authorization/v1beta1 autoscaling/__internal autoscaling/v1 batch/__internal batch/v1 extensions/__internal extensions/v1beta1 componentconfig/__internal componentconfig/v1alpha1 metrics/__internal metrics/v1alpha1"
|
||||
VERSIONS=${VERSIONS:-$DEFAULT_VERSIONS}
|
||||
generate_deep_copies "$VERSIONS"
|
||||
|
@ -50,7 +50,7 @@ kube::etcd::start
|
||||
|
||||
# Start kube-apiserver
|
||||
kube::log::status "Starting kube-apiserver"
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,batch/v1,extensions/v1beta1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \
|
||||
--address="127.0.0.1" \
|
||||
--public-address-override="127.0.0.1" \
|
||||
--port="${API_PORT}" \
|
||||
@ -64,7 +64,7 @@ APISERVER_PID=$!
|
||||
kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/healthz" "apiserver: "
|
||||
|
||||
SWAGGER_API_PATH="http://127.0.0.1:${API_PORT}/swaggerapi/"
|
||||
DEFAULT_GROUP_VERSIONS="v1 autoscaling/v1 extensions/v1beta1"
|
||||
DEFAULT_GROUP_VERSIONS="v1 autoscaling/v1 batch/v1 extensions/v1beta1"
|
||||
VERSIONS=${VERSIONS:-$DEFAULT_GROUP_VERSIONS}
|
||||
|
||||
kube::log::status "Updating " ${SWAGGER_ROOT_DIR}
|
||||
|
@ -23,7 +23,7 @@ source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||
|
||||
kube::golang::setup_env
|
||||
|
||||
APIROOTS=${APIROOTS:-pkg/api pkg/apis/authorization pkg/apis/autoscaling pkg/apis/extensions pkg/apis/metrics}
|
||||
APIROOTS=${APIROOTS:-pkg/api pkg/apis/authorization pkg/apis/autoscaling pkg/apis/batch pkg/apis/extensions pkg/apis/metrics}
|
||||
_tmp="${KUBE_ROOT}/_tmp"
|
||||
|
||||
cleanup() {
|
||||
|
@ -25,7 +25,7 @@ kube::golang::setup_env
|
||||
|
||||
gendeepcopy=$(kube::util::find-binary "gendeepcopy")
|
||||
|
||||
APIROOTS=${APIROOTS:-pkg/api pkg/apis/authorization pkg/apis/autoscaling pkg/apis/extensions pkg/apis/metrics}
|
||||
APIROOTS=${APIROOTS:-pkg/api pkg/apis/authorization pkg/apis/autoscaling pkg/apis/batch pkg/apis/extensions pkg/apis/metrics}
|
||||
_tmp="${KUBE_ROOT}/_tmp"
|
||||
|
||||
cleanup() {
|
||||
|
@ -178,7 +178,7 @@ kube::log::status "Starting kube-apiserver"
|
||||
# Admission Controllers to invoke prior to persisting objects in cluster
|
||||
ADMISSION_CONTROL="NamespaceLifecycle,LimitRanger,ResourceQuota"
|
||||
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,batch/v1,extensions/v1beta1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \
|
||||
--address="127.0.0.1" \
|
||||
--public-address-override="127.0.0.1" \
|
||||
--port="${API_PORT}" \
|
||||
@ -727,6 +727,8 @@ __EOF__
|
||||
kube::test::get_object_assert jobs "{{range.items}}{{$id_field}}:{{end}}" 'pi:'
|
||||
# Clean up
|
||||
kubectl delete jobs pi "${kube_flags[@]}"
|
||||
# Post-condition: no pods exist.
|
||||
kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
# Pre-Condition: no Deployment exists
|
||||
kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
# Command
|
||||
@ -1604,7 +1606,7 @@ kube_api_versions=(
|
||||
v1
|
||||
)
|
||||
for version in "${kube_api_versions[@]}"; do
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" runTests "${version}"
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,batch/v1,extensions/v1beta1" runTests "${version}"
|
||||
done
|
||||
|
||||
kube::log::status "TEST PASSED"
|
||||
|
@ -58,7 +58,7 @@ KUBE_GOVERALLS_BIN=${KUBE_GOVERALLS_BIN:-}
|
||||
# Lists of API Versions of each groups that should be tested, groups are
|
||||
# separated by comma, lists are separated by semicolon. e.g.,
|
||||
# "v1,compute/v1alpha1,experimental/v1alpha2;v1,compute/v2,experimental/v1alpha3"
|
||||
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1,metrics/v1alpha1;v1,autoscaling/v1,extensions/v1beta1,metrics/v1alpha1"}
|
||||
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1,metrics/v1alpha1;v1,autoscaling/v1,batch/v1,extensions/v1beta1,metrics/v1alpha1"}
|
||||
# once we have multiple group supports
|
||||
# Run tests with the standard (registry) and a custom etcd prefix
|
||||
# (kubernetes.io/registry).
|
||||
@ -315,7 +315,7 @@ for (( i=0, j=0; ; )); do
|
||||
# KUBE_TEST_API sets the version of each group to be tested. KUBE_API_VERSIONS
|
||||
# register the groups/versions as supported by k8s. So KUBE_API_VERSIONS
|
||||
# needs to be the superset of KUBE_TEST_API.
|
||||
KUBE_TEST_API="${apiVersion}" KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1,componentconfig/v1alpha1,metrics/v1alpha1" ETCD_PREFIX=${etcdPrefix} runTests "$@"
|
||||
KUBE_TEST_API="${apiVersion}" KUBE_API_VERSIONS="v1,autoscaling/v1,batch/v1,extensions/v1beta1,componentconfig/v1alpha1,metrics/v1alpha1" ETCD_PREFIX=${etcdPrefix} runTests "$@"
|
||||
i=${i}+1
|
||||
j=${j}+1
|
||||
if [[ i -eq ${apiVersionsCount} ]] && [[ j -eq ${etcdPrefixesCount} ]]; then
|
||||
|
@ -29,7 +29,7 @@ source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||
# "v1,compute/v1alpha1,experimental/v1alpha2;v1,compute/v2,experimental/v1alpha3"
|
||||
# TODO: It's going to be:
|
||||
# KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1"}
|
||||
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1;v1,autoscaling/v1,extensions/v1beta1"}
|
||||
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1;v1,autoscaling/v1,batch/v1,extensions/v1beta1"}
|
||||
|
||||
# Give integration tests longer to run
|
||||
KUBE_TIMEOUT=${KUBE_TIMEOUT:--timeout 240s}
|
||||
@ -52,21 +52,21 @@ runTests() {
|
||||
KUBE_RACE="" \
|
||||
KUBE_TIMEOUT="${KUBE_TIMEOUT}" \
|
||||
KUBE_TEST_API_VERSIONS="$1" \
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" \
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,batch/v1,extensions/v1beta1" \
|
||||
"${KUBE_ROOT}/hack/test-go.sh" test/integration
|
||||
|
||||
kube::log::status "Running integration test scenario with watch cache on"
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" KUBE_TEST_API_VERSIONS="$1" "${KUBE_OUTPUT_HOSTBIN}/integration" --v=${LOG_LEVEL} \
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,batch/v1,extensions/v1beta1" KUBE_TEST_API_VERSIONS="$1" "${KUBE_OUTPUT_HOSTBIN}/integration" --v=${LOG_LEVEL} \
|
||||
--max-concurrency="${KUBE_INTEGRATION_TEST_MAX_CONCURRENCY}" --watch-cache=true
|
||||
|
||||
kube::log::status "Running integration test scenario with watch cache off"
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" KUBE_TEST_API_VERSIONS="$1" "${KUBE_OUTPUT_HOSTBIN}/integration" --v=${LOG_LEVEL} \
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,batch/v1,extensions/v1beta1" KUBE_TEST_API_VERSIONS="$1" "${KUBE_OUTPUT_HOSTBIN}/integration" --v=${LOG_LEVEL} \
|
||||
--max-concurrency="${KUBE_INTEGRATION_TEST_MAX_CONCURRENCY}" --watch-cache=false
|
||||
|
||||
cleanup
|
||||
}
|
||||
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" "${KUBE_ROOT}/hack/build-go.sh" "$@" cmd/integration
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,batch/v1,extensions/v1beta1" "${KUBE_ROOT}/hack/build-go.sh" "$@" cmd/integration
|
||||
|
||||
# Run cleanup to stop etcd on interrupt or other kill signal.
|
||||
trap cleanup EXIT
|
||||
|
@ -33,7 +33,7 @@ function generate_version() {
|
||||
echo "package ${group_version##*/}" >> "$TMPFILE"
|
||||
cat >> "$TMPFILE" <<EOF
|
||||
|
||||
// This file contains a collection of methods that can be used from go-resful to
|
||||
// This file contains a collection of methods that can be used from go-restful to
|
||||
// generate Swagger API documentation for its models. Please read this PR for more
|
||||
// information on the implementation: https://github.com/emicklei/go-restful/pull/215
|
||||
//
|
||||
@ -56,7 +56,7 @@ EOF
|
||||
mv "$TMPFILE" "pkg/$(kube::util::group-version-to-pkg-path "${group_version}")/types_swagger_doc_generated.go"
|
||||
}
|
||||
|
||||
GROUP_VERSIONS=(unversioned v1 authorization/v1beta1 autoscaling/v1 extensions/v1beta1)
|
||||
GROUP_VERSIONS=(unversioned v1 authorization/v1beta1 autoscaling/v1 batch/v1 extensions/v1beta1)
|
||||
# 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"
|
||||
|
@ -27,11 +27,13 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
|
||||
_ "k8s.io/kubernetes/pkg/api/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/batch/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/metrics/install"
|
||||
@ -41,6 +43,7 @@ var (
|
||||
Groups = make(map[string]TestGroup)
|
||||
Default TestGroup
|
||||
Autoscaling TestGroup
|
||||
Batch TestGroup
|
||||
Extensions TestGroup
|
||||
)
|
||||
|
||||
@ -72,21 +75,28 @@ func init() {
|
||||
internalGroupVersion: api.SchemeGroupVersion,
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[autoscaling.GroupName]; !ok {
|
||||
Groups[autoscaling.GroupName] = TestGroup{
|
||||
externalGroupVersion: unversioned.GroupVersion{Group: autoscaling.GroupName, Version: registered.GroupOrDie(autoscaling.GroupName).GroupVersion.Version},
|
||||
internalGroupVersion: extensions.SchemeGroupVersion,
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[extensions.GroupName]; !ok {
|
||||
Groups[extensions.GroupName] = TestGroup{
|
||||
externalGroupVersion: unversioned.GroupVersion{Group: extensions.GroupName, Version: registered.GroupOrDie(extensions.GroupName).GroupVersion.Version},
|
||||
internalGroupVersion: extensions.SchemeGroupVersion,
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[autoscaling.GroupName]; !ok {
|
||||
Groups[autoscaling.GroupName] = TestGroup{
|
||||
externalGroupVersion: unversioned.GroupVersion{Group: autoscaling.GroupName, Version: registered.GroupOrDie(autoscaling.GroupName).GroupVersion.Version},
|
||||
internalGroupVersion: extensions.SchemeGroupVersion,
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[batch.GroupName]; !ok {
|
||||
Groups[batch.GroupName] = TestGroup{
|
||||
externalGroupVersion: unversioned.GroupVersion{Group: batch.GroupName, Version: registered.GroupOrDie(batch.GroupName).GroupVersion.Version},
|
||||
internalGroupVersion: extensions.SchemeGroupVersion,
|
||||
}
|
||||
}
|
||||
|
||||
Default = Groups[api.GroupName]
|
||||
Autoscaling = Groups[autoscaling.GroupName]
|
||||
Batch = Groups[batch.GroupName]
|
||||
Extensions = Groups[extensions.GroupName]
|
||||
}
|
||||
|
||||
|
@ -128,6 +128,10 @@ func TestAutoscalingEncodeDecodeStatus(t *testing.T) {
|
||||
testEncodeDecodeStatus(t, Autoscaling.Codec())
|
||||
}
|
||||
|
||||
func TestBatchEncodeDecodeStatus(t *testing.T) {
|
||||
testEncodeDecodeStatus(t, Batch.Codec())
|
||||
}
|
||||
|
||||
func TestExperimentalEncodeDecodeStatus(t *testing.T) {
|
||||
testEncodeDecodeStatus(t, Extensions.Codec())
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
package unversioned
|
||||
|
||||
// This file contains a collection of methods that can be used from go-resful to
|
||||
// This file contains a collection of methods that can be used from go-restful to
|
||||
// generate Swagger API documentation for its models. Please read this PR for more
|
||||
// information on the implementation: https://github.com/emicklei/go-restful/pull/215
|
||||
//
|
||||
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
package v1
|
||||
|
||||
// This file contains a collection of methods that can be used from go-resful to
|
||||
// This file contains a collection of methods that can be used from go-restful to
|
||||
// generate Swagger API documentation for its models. Please read this PR for more
|
||||
// information on the implementation: https://github.com/emicklei/go-restful/pull/215
|
||||
//
|
||||
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
package v1beta1
|
||||
|
||||
// This file contains a collection of methods that can be used from go-resful to
|
||||
// This file contains a collection of methods that can be used from go-restful to
|
||||
// generate Swagger API documentation for its models. Please read this PR for more
|
||||
// information on the implementation: https://github.com/emicklei/go-restful/pull/215
|
||||
//
|
||||
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
package v1
|
||||
|
||||
// This file contains a collection of methods that can be used from go-resful to
|
||||
// This file contains a collection of methods that can be used from go-restful to
|
||||
// generate Swagger API documentation for its models. Please read this PR for more
|
||||
// information on the implementation: https://github.com/emicklei/go-restful/pull/215
|
||||
//
|
||||
|
29
pkg/apis/batch/deep_copy_generated.go
Normal file
29
pkg/apis/batch/deep_copy_generated.go
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS AUTO-GENERATED BY $KUBEROOT/hack/update-generated-deep-copies.sh.
|
||||
|
||||
package batch
|
||||
|
||||
import api "k8s.io/kubernetes/pkg/api"
|
||||
|
||||
func init() {
|
||||
err := api.Scheme.AddGeneratedDeepCopyFuncs()
|
||||
if err != nil {
|
||||
// if one of the deep copy functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
129
pkg/apis/batch/install/install.go
Normal file
129
pkg/apis/batch/install/install.go
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 batch 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/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/batch/v1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
|
||||
const importPrefix = "k8s.io/kubernetes/pkg/apis/batch"
|
||||
|
||||
var accessor = meta.NewAccessor()
|
||||
|
||||
// availableVersions lists all known external versions for this group from most preferred to least preferred
|
||||
var availableVersions = []unversioned.GroupVersion{v1.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", batch.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()
|
||||
|
||||
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 v1.SchemeGroupVersion:
|
||||
return &meta.VersionInterfaces{
|
||||
ObjectConvertor: api.Scheme,
|
||||
MetadataAccessor: accessor,
|
||||
}, nil
|
||||
default:
|
||||
g, _ := registered.Group(batch.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
|
||||
batch.AddToScheme(api.Scheme)
|
||||
// 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 v1.SchemeGroupVersion:
|
||||
v1.AddToScheme(api.Scheme)
|
||||
}
|
||||
}
|
||||
}
|
54
pkg/apis/batch/register.go
Normal file
54
pkg/apis/batch/register.go
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 batch
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "batch"
|
||||
|
||||
// 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 back a Group qualified GroupKind
|
||||
func Kind(kind string) unversioned.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns back a Group qualified GroupResource
|
||||
func Resource(resource string) unversioned.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
// Add the API to Scheme.
|
||||
addKnownTypes(scheme)
|
||||
}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&extensions.Job{},
|
||||
&extensions.JobList{},
|
||||
&api.ListOptions{},
|
||||
)
|
||||
}
|
63
pkg/apis/batch/v1/conversion.go
Normal file
63
pkg/apis/batch/v1/conversion.go
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func addConversionFuncs(scheme *runtime.Scheme) {
|
||||
// Add non-generated conversion functions
|
||||
err := scheme.AddConversionFuncs(
|
||||
Convert_api_PodSpec_To_v1_PodSpec,
|
||||
Convert_v1_PodSpec_To_api_PodSpec,
|
||||
)
|
||||
if err != nil {
|
||||
// If one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = api.Scheme.AddFieldLabelConversionFunc("batch/v1", "Job",
|
||||
func(label, value string) (string, string, error) {
|
||||
switch label {
|
||||
case "metadata.name", "metadata.namespace", "status.successful":
|
||||
return label, value, nil
|
||||
default:
|
||||
return "", "", fmt.Errorf("field label not supported: %s", label)
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
// If one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// The following two PodSpec conversions functions where copied from pkg/api/conversion.go
|
||||
// for the generated functions to work properly.
|
||||
// This should be fixed: https://github.com/kubernetes/kubernetes/issues/12977
|
||||
func Convert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *v1.PodSpec, s conversion.Scope) error {
|
||||
return v1.Convert_api_PodSpec_To_v1_PodSpec(in, out, s)
|
||||
}
|
||||
|
||||
func Convert_v1_PodSpec_To_api_PodSpec(in *v1.PodSpec, out *api.PodSpec, s conversion.Scope) error {
|
||||
return v1.Convert_v1_PodSpec_To_api_PodSpec(in, out, s)
|
||||
}
|
3053
pkg/apis/batch/v1/conversion_generated.go
Normal file
3053
pkg/apis/batch/v1/conversion_generated.go
Normal file
File diff suppressed because it is too large
Load Diff
1227
pkg/apis/batch/v1/deep_copy_generated.go
Normal file
1227
pkg/apis/batch/v1/deep_copy_generated.go
Normal file
File diff suppressed because it is too large
Load Diff
52
pkg/apis/batch/v1/defaults.go
Normal file
52
pkg/apis/batch/v1/defaults.go
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) {
|
||||
scheme.AddDefaultingFuncs(
|
||||
func(obj *Job) {
|
||||
labels := obj.Spec.Template.Labels
|
||||
// TODO: support templates defined elsewhere when we support them in the API
|
||||
if labels != nil {
|
||||
if obj.Spec.Selector == nil {
|
||||
obj.Spec.Selector = &LabelSelector{
|
||||
MatchLabels: labels,
|
||||
}
|
||||
}
|
||||
if len(obj.Labels) == 0 {
|
||||
obj.Labels = labels
|
||||
}
|
||||
}
|
||||
// For a non-parallel job, you can leave both `.spec.completions` and
|
||||
// `.spec.parallelism` unset. When both are unset, both are defaulted to 1.
|
||||
if obj.Spec.Completions == nil && obj.Spec.Parallelism == nil {
|
||||
obj.Spec.Completions = new(int32)
|
||||
*obj.Spec.Completions = 1
|
||||
obj.Spec.Parallelism = new(int32)
|
||||
*obj.Spec.Parallelism = 1
|
||||
}
|
||||
if obj.Spec.Parallelism == nil {
|
||||
obj.Spec.Parallelism = new(int32)
|
||||
*obj.Spec.Parallelism = 1
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
47
pkg/apis/batch/v1/register.go
Normal file
47
pkg/apis/batch/v1/register.go
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "batch"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: "v1"}
|
||||
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
addKnownTypes(scheme)
|
||||
addDefaultingFuncs(scheme)
|
||||
addConversionFuncs(scheme)
|
||||
}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Job{},
|
||||
&JobList{},
|
||||
&v1.ListOptions{},
|
||||
)
|
||||
}
|
||||
|
||||
func (obj *Job) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *JobList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
3108
pkg/apis/batch/v1/types.generated.go
Normal file
3108
pkg/apis/batch/v1/types.generated.go
Normal file
File diff suppressed because it is too large
Load Diff
170
pkg/apis/batch/v1/types.go
Normal file
170
pkg/apis/batch/v1/types.go
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
// Job represents the configuration of a single job.
|
||||
type Job 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"`
|
||||
|
||||
// Spec is a structure defining the expected behavior of a job.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status
|
||||
Spec JobSpec `json:"spec,omitempty"`
|
||||
|
||||
// Status is a structure describing current status of a job.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status
|
||||
Status JobStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// JobList is a collection of jobs.
|
||||
type JobList 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 Job.
|
||||
Items []Job `json:"items"`
|
||||
}
|
||||
|
||||
// JobSpec describes how the job execution will look like.
|
||||
type JobSpec struct {
|
||||
|
||||
// Parallelism specifies the maximum desired number of pods the job should
|
||||
// run at any given time. The actual number of pods running in steady state will
|
||||
// be less than this number when ((.spec.completions - .status.successful) < .spec.parallelism),
|
||||
// i.e. when the work left to do is less than max parallelism.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/user-guide/jobs.md
|
||||
Parallelism *int32 `json:"parallelism,omitempty"`
|
||||
|
||||
// Completions specifies the desired number of successfully finished pods the
|
||||
// job should be run with. Setting to nil means that the success of any
|
||||
// pod signals the success of all pods, and allows parallelism to have any positive
|
||||
// value. Setting to 1 means that parallelism is limited to 1 and the success of that
|
||||
// pod signals the success of the job.
|
||||
Completions *int32 `json:"completions,omitempty"`
|
||||
|
||||
// Optional duration in seconds relative to the startTime that the job may be active
|
||||
// before the system tries to terminate it; value must be positive integer
|
||||
ActiveDeadlineSeconds *int64 `json:"activeDeadlineSeconds,omitempty"`
|
||||
|
||||
// Selector is a label query over pods that should match the pod count.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md#label-selectors
|
||||
Selector *LabelSelector `json:"selector,omitempty"`
|
||||
|
||||
// Template is the object that describes the pod that will be created when
|
||||
// executing a job.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/user-guide/jobs.md
|
||||
Template v1.PodTemplateSpec `json:"template"`
|
||||
}
|
||||
|
||||
// JobStatus represents the current state of a Job.
|
||||
type JobStatus struct {
|
||||
|
||||
// Conditions represent the latest available observations of an object's current state.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/user-guide/jobs.md
|
||||
Conditions []JobCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||
|
||||
// StartTime represents time when the job was acknowledged by the Job Manager.
|
||||
// It is not guaranteed to be set in happens-before order across separate operations.
|
||||
// It is represented in RFC3339 form and is in UTC.
|
||||
StartTime *unversioned.Time `json:"startTime,omitempty"`
|
||||
|
||||
// CompletionTime represents time when the job was completed. It is not guaranteed to
|
||||
// be set in happens-before order across separate operations.
|
||||
// It is represented in RFC3339 form and is in UTC.
|
||||
CompletionTime *unversioned.Time `json:"completionTime,omitempty"`
|
||||
|
||||
// Active is the number of actively running pods.
|
||||
Active int32 `json:"active,omitempty"`
|
||||
|
||||
// Succeeded is the number of pods which reached Phase Succeeded.
|
||||
Succeeded int32 `json:"succeeded,omitempty"`
|
||||
|
||||
// Failed is the number of pods which reached Phase Failed.
|
||||
Failed int32 `json:"failed,omitempty"`
|
||||
}
|
||||
|
||||
type JobConditionType string
|
||||
|
||||
// These are valid conditions of a job.
|
||||
const (
|
||||
// JobComplete means the job has completed its execution.
|
||||
JobComplete JobConditionType = "Complete"
|
||||
// JobFailed means the job has failed its execution.
|
||||
JobFailed JobConditionType = "Failed"
|
||||
)
|
||||
|
||||
// JobCondition describes current state of a job.
|
||||
type JobCondition struct {
|
||||
// Type of job condition, Complete or Failed.
|
||||
Type JobConditionType `json:"type"`
|
||||
// Status of the condition, one of True, False, Unknown.
|
||||
Status v1.ConditionStatus `json:"status"`
|
||||
// Last time the condition was checked.
|
||||
LastProbeTime unversioned.Time `json:"lastProbeTime,omitempty"`
|
||||
// Last time the condition transit from one status to another.
|
||||
LastTransitionTime unversioned.Time `json:"lastTransitionTime,omitempty"`
|
||||
// (brief) reason for the condition's last transition.
|
||||
Reason string `json:"reason,omitempty"`
|
||||
// Human readable message indicating details about last transition.
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
// A label selector is a label query over a set of resources. The result of matchLabels and
|
||||
// matchExpressions are ANDed. An empty label selector matches all objects. A null
|
||||
// label selector matches no objects.
|
||||
type LabelSelector struct {
|
||||
// matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
|
||||
// map is equivalent to an element of matchExpressions, whose key field is "key", the
|
||||
// operator is "In", and the values array contains only "value". The requirements are ANDed.
|
||||
MatchLabels map[string]string `json:"matchLabels,omitempty"`
|
||||
// matchExpressions is a list of label selector requirements. The requirements are ANDed.
|
||||
MatchExpressions []LabelSelectorRequirement `json:"matchExpressions,omitempty"`
|
||||
}
|
||||
|
||||
// A label selector requirement is a selector that contains values, a key, and an operator that
|
||||
// relates the key and values.
|
||||
type LabelSelectorRequirement struct {
|
||||
// key is the label key that the selector applies to.
|
||||
Key string `json:"key" patchStrategy:"merge" patchMergeKey:"key"`
|
||||
// operator represents a key's relationship to a set of values.
|
||||
// Valid operators ard In, NotIn, Exists and DoesNotExist.
|
||||
Operator LabelSelectorOperator `json:"operator"`
|
||||
// values is an array of string values. If the operator is In or NotIn,
|
||||
// the values array must be non-empty. If the operator is Exists or DoesNotExist,
|
||||
// the values array must be empty. This array is replaced during a strategic
|
||||
// merge patch.
|
||||
Values []string `json:"values,omitempty"`
|
||||
}
|
||||
|
||||
// A label selector operator is the set of operators that can be used in a selector requirement.
|
||||
type LabelSelectorOperator string
|
||||
|
||||
const (
|
||||
LabelSelectorOpIn LabelSelectorOperator = "In"
|
||||
LabelSelectorOpNotIn LabelSelectorOperator = "NotIn"
|
||||
LabelSelectorOpExists LabelSelectorOperator = "Exists"
|
||||
LabelSelectorOpDoesNotExist LabelSelectorOperator = "DoesNotExist"
|
||||
)
|
113
pkg/apis/batch/v1/types_swagger_doc_generated.go
Normal file
113
pkg/apis/batch/v1/types_swagger_doc_generated.go
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1
|
||||
|
||||
// This file contains a collection of methods that can be used from go-restful to
|
||||
// generate Swagger API documentation for its models. Please read this PR for more
|
||||
// information on the implementation: https://github.com/emicklei/go-restful/pull/215
|
||||
//
|
||||
// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if
|
||||
// they are on one line! For multiple line or blocks that you want to ignore use ---.
|
||||
// Any context after a --- is ignored.
|
||||
//
|
||||
// Those methods can be generated by using hack/update-generated-swagger-docs.sh
|
||||
|
||||
// AUTO-GENERATED FUNCTIONS START HERE
|
||||
var map_Job = map[string]string{
|
||||
"": "Job represents the configuration of a single job.",
|
||||
"metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
|
||||
"spec": "Spec is a structure defining the expected behavior of a job. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status",
|
||||
"status": "Status is a structure describing current status of a job. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status",
|
||||
}
|
||||
|
||||
func (Job) SwaggerDoc() map[string]string {
|
||||
return map_Job
|
||||
}
|
||||
|
||||
var map_JobCondition = map[string]string{
|
||||
"": "JobCondition describes current state of a job.",
|
||||
"type": "Type of job condition, Complete or Failed.",
|
||||
"status": "Status of the condition, one of True, False, Unknown.",
|
||||
"lastProbeTime": "Last time the condition was checked.",
|
||||
"lastTransitionTime": "Last time the condition transit from one status to another.",
|
||||
"reason": "(brief) reason for the condition's last transition.",
|
||||
"message": "Human readable message indicating details about last transition.",
|
||||
}
|
||||
|
||||
func (JobCondition) SwaggerDoc() map[string]string {
|
||||
return map_JobCondition
|
||||
}
|
||||
|
||||
var map_JobList = map[string]string{
|
||||
"": "JobList is a collection of jobs.",
|
||||
"metadata": "Standard list metadata More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
|
||||
"items": "Items is the list of Job.",
|
||||
}
|
||||
|
||||
func (JobList) SwaggerDoc() map[string]string {
|
||||
return map_JobList
|
||||
}
|
||||
|
||||
var map_JobSpec = map[string]string{
|
||||
"": "JobSpec describes how the job execution will look like.",
|
||||
"parallelism": "Parallelism specifies the maximum desired number of pods the job should run at any given time. The actual number of pods running in steady state will be less than this number when ((.spec.completions - .status.successful) < .spec.parallelism), i.e. when the work left to do is less than max parallelism. More info: http://releases.k8s.io/HEAD/docs/user-guide/jobs.md",
|
||||
"completions": "Completions specifies the desired number of successfully finished pods the job should be run with. Setting to nil means that the success of any pod signals the success of all pods, and allows parallelism to have any positive value. Setting to 1 means that parallelism is limited to 1 and the success of that pod signals the success of the job.",
|
||||
"activeDeadlineSeconds": "Optional duration in seconds relative to the startTime that the job may be active before the system tries to terminate it; value must be positive integer",
|
||||
"selector": "Selector is a label query over pods that should match the pod count. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md#label-selectors",
|
||||
"template": "Template is the object that describes the pod that will be created when executing a job. More info: http://releases.k8s.io/HEAD/docs/user-guide/jobs.md",
|
||||
}
|
||||
|
||||
func (JobSpec) SwaggerDoc() map[string]string {
|
||||
return map_JobSpec
|
||||
}
|
||||
|
||||
var map_JobStatus = map[string]string{
|
||||
"": "JobStatus represents the current state of a Job.",
|
||||
"conditions": "Conditions represent the latest available observations of an object's current state. More info: http://releases.k8s.io/HEAD/docs/user-guide/jobs.md",
|
||||
"startTime": "StartTime represents time when the job was acknowledged by the Job Manager. It is not guaranteed to be set in happens-before order across separate operations. It is represented in RFC3339 form and is in UTC.",
|
||||
"completionTime": "CompletionTime represents time when the job was completed. It is not guaranteed to be set in happens-before order across separate operations. It is represented in RFC3339 form and is in UTC.",
|
||||
"active": "Active is the number of actively running pods.",
|
||||
"succeeded": "Succeeded is the number of pods which reached Phase Succeeded.",
|
||||
"failed": "Failed is the number of pods which reached Phase Failed.",
|
||||
}
|
||||
|
||||
func (JobStatus) SwaggerDoc() map[string]string {
|
||||
return map_JobStatus
|
||||
}
|
||||
|
||||
var map_LabelSelector = map[string]string{
|
||||
"": "A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects.",
|
||||
"matchLabels": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.",
|
||||
"matchExpressions": "matchExpressions is a list of label selector requirements. The requirements are ANDed.",
|
||||
}
|
||||
|
||||
func (LabelSelector) SwaggerDoc() map[string]string {
|
||||
return map_LabelSelector
|
||||
}
|
||||
|
||||
var map_LabelSelectorRequirement = map[string]string{
|
||||
"": "A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.",
|
||||
"key": "key is the label key that the selector applies to.",
|
||||
"operator": "operator represents a key's relationship to a set of values. Valid operators ard In, NotIn, Exists and DoesNotExist.",
|
||||
"values": "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.",
|
||||
}
|
||||
|
||||
func (LabelSelectorRequirement) SwaggerDoc() map[string]string {
|
||||
return map_LabelSelectorRequirement
|
||||
}
|
||||
|
||||
// AUTO-GENERATED FUNCTIONS END HERE
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
package v1beta1
|
||||
|
||||
// This file contains a collection of methods that can be used from go-resful to
|
||||
// This file contains a collection of methods that can be used from go-restful to
|
||||
// generate Swagger API documentation for its models. Please read this PR for more
|
||||
// information on the implementation: https://github.com/emicklei/go-restful/pull/215
|
||||
//
|
||||
|
82
pkg/client/unversioned/batch.go
Normal file
82
pkg/client/unversioned/batch.go
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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/batch"
|
||||
)
|
||||
|
||||
type BatchInterface interface {
|
||||
JobsNamespacer
|
||||
}
|
||||
|
||||
// BatchClient is used to interact with Kubernetes batch features.
|
||||
type BatchClient struct {
|
||||
*RESTClient
|
||||
}
|
||||
|
||||
func (c *BatchClient) Jobs(namespace string) JobInterface {
|
||||
return newJobsV1(c, namespace)
|
||||
}
|
||||
|
||||
func NewBatch(c *Config) (*BatchClient, error) {
|
||||
config := *c
|
||||
if err := setBatchDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &BatchClient{client}, nil
|
||||
}
|
||||
|
||||
func NewBatchOrDie(c *Config) *BatchClient {
|
||||
client, err := NewBatch(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func setBatchDefaults(config *Config) error {
|
||||
// if batch group is not registered, return an error
|
||||
g, err := registered.Group(batch.GroupName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.APIPath = defaultAPIPath
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = DefaultKubernetesUserAgent()
|
||||
}
|
||||
// TODO: Unconditionally set the config.Version, until we fix the config.
|
||||
//if config.Version == "" {
|
||||
copyGroupVersion := g.GroupVersion
|
||||
config.GroupVersion = ©GroupVersion
|
||||
//}
|
||||
|
||||
config.Codec = api.Codecs.LegacyCodec(*config.GroupVersion)
|
||||
if config.QPS == 0 {
|
||||
config.QPS = 5
|
||||
}
|
||||
if config.Burst == 0 {
|
||||
config.Burst = 10
|
||||
}
|
||||
return nil
|
||||
}
|
@ -42,6 +42,7 @@ type Interface interface {
|
||||
ComponentStatusesInterface
|
||||
ConfigMapsNamespacer
|
||||
Autoscaling() AutoscalingInterface
|
||||
Batch() BatchInterface
|
||||
Extensions() ExtensionsInterface
|
||||
Discovery() DiscoveryInterface
|
||||
}
|
||||
@ -113,6 +114,7 @@ func (c *Client) ConfigMaps(namespace string) ConfigMapsInterface {
|
||||
type Client struct {
|
||||
*RESTClient
|
||||
*AutoscalingClient
|
||||
*BatchClient
|
||||
*ExtensionsClient
|
||||
*DiscoveryClient
|
||||
}
|
||||
@ -152,6 +154,10 @@ func (c *Client) Autoscaling() AutoscalingInterface {
|
||||
return c.AutoscalingClient
|
||||
}
|
||||
|
||||
func (c *Client) Batch() BatchInterface {
|
||||
return c.BatchClient
|
||||
}
|
||||
|
||||
func (c *Client) Extensions() ExtensionsInterface {
|
||||
return c.ExtensionsClient
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util"
|
||||
@ -165,6 +166,15 @@ func New(c *Config) (*Client, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var batchClient *BatchClient
|
||||
if registered.IsRegistered(batch.GroupName) {
|
||||
batchConfig := *c
|
||||
batchClient, err = NewBatch(&batchConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var extensionsClient *ExtensionsClient
|
||||
if registered.IsRegistered(extensions.GroupName) {
|
||||
extensionsConfig := *c
|
||||
@ -174,7 +184,7 @@ func New(c *Config) (*Client, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return &Client{RESTClient: client, AutoscalingClient: autoscalingClient, ExtensionsClient: extensionsClient, DiscoveryClient: discoveryClient}, nil
|
||||
return &Client{RESTClient: client, AutoscalingClient: autoscalingClient, BatchClient: batchClient, ExtensionsClient: extensionsClient, DiscoveryClient: discoveryClient}, nil
|
||||
}
|
||||
|
||||
// MatchesServerVersion queries the server to compares the build version
|
||||
|
@ -35,7 +35,7 @@ func getHorizontalPodAutoscalersResoureName() string {
|
||||
return "horizontalpodautoscalers"
|
||||
}
|
||||
|
||||
func getClient(t *testing.T, c *simple.Client, ns, resourceGroup string) HorizontalPodAutoscalerInterface {
|
||||
func getHPAClient(t *testing.T, c *simple.Client, ns, resourceGroup string) HorizontalPodAutoscalerInterface {
|
||||
switch resourceGroup {
|
||||
case autoscaling.GroupName:
|
||||
return c.Setup(t).Autoscaling().HorizontalPodAutoscalers(ns)
|
||||
@ -66,7 +66,7 @@ func testHorizontalPodAutoscalerCreate(t *testing.T, group testapi.TestGroup, re
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
|
||||
response, err := getClient(t, c, ns, resourceGroup).Create(&horizontalPodAutoscaler)
|
||||
response, err := getHPAClient(t, c, ns, resourceGroup).Create(&horizontalPodAutoscaler)
|
||||
defer c.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@ -98,7 +98,7 @@ func testHorizontalPodAutoscalerGet(t *testing.T, group testapi.TestGroup, resou
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
|
||||
response, err := getClient(t, c, ns, resourceGroup).Get("abc")
|
||||
response, err := getHPAClient(t, c, ns, resourceGroup).Get("abc")
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
@ -130,7 +130,7 @@ func testHorizontalPodAutoscalerList(t *testing.T, group testapi.TestGroup, reso
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscalerList},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
response, err := getClient(t, c, ns, resourceGroup).List(api.ListOptions{})
|
||||
response, err := getHPAClient(t, c, ns, resourceGroup).List(api.ListOptions{})
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
@ -154,7 +154,7 @@ func testHorizontalPodAutoscalerUpdate(t *testing.T, group testapi.TestGroup, re
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
response, err := getClient(t, c, ns, resourceGroup).Update(horizontalPodAutoscaler)
|
||||
response, err := getHPAClient(t, c, ns, resourceGroup).Update(horizontalPodAutoscaler)
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
@ -178,7 +178,7 @@ func testHorizontalPodAutoscalerUpdateStatus(t *testing.T, group testapi.TestGro
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
response, err := getClient(t, c, ns, resourceGroup).UpdateStatus(horizontalPodAutoscaler)
|
||||
response, err := getHPAClient(t, c, ns, resourceGroup).UpdateStatus(horizontalPodAutoscaler)
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
@ -195,7 +195,7 @@ func testHorizontalPodAutoscalerDelete(t *testing.T, group testapi.TestGroup, re
|
||||
Response: simple.Response{StatusCode: 200},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
err := getClient(t, c, ns, resourceGroup).Delete("foo", nil)
|
||||
err := getHPAClient(t, c, ns, resourceGroup).Delete("foo", nil)
|
||||
defer c.Close()
|
||||
c.Validate(t, nil, err)
|
||||
}
|
||||
@ -214,7 +214,7 @@ func testHorizontalPodAutoscalerWatch(t *testing.T, group testapi.TestGroup, res
|
||||
Response: simple.Response{StatusCode: 200},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
_, err := getClient(t, c, api.NamespaceAll, resourceGroup).Watch(api.ListOptions{})
|
||||
_, err := getHPAClient(t, c, api.NamespaceAll, resourceGroup).Watch(api.ListOptions{})
|
||||
defer c.Close()
|
||||
c.Validate(t, nil, err)
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
_ "k8s.io/kubernetes/pkg/apis/authorization/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/batch/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/metrics/install"
|
||||
|
@ -101,3 +101,67 @@ func (c *jobs) UpdateStatus(job *extensions.Job) (result *extensions.Job, err er
|
||||
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).SubResource("status").Body(job).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// jobsV1 implements JobsNamespacer interface using BatchClient internally
|
||||
type jobsV1 struct {
|
||||
r *BatchClient
|
||||
ns string
|
||||
}
|
||||
|
||||
// newJobsV1 returns a jobsV1
|
||||
func newJobsV1(c *BatchClient, namespace string) *jobsV1 {
|
||||
return &jobsV1{c, namespace}
|
||||
}
|
||||
|
||||
// Ensure statically that jobsV1 implements JobInterface.
|
||||
var _ JobInterface = &jobsV1{}
|
||||
|
||||
// List returns a list of jobs that match the label and field selectors.
|
||||
func (c *jobsV1) List(opts api.ListOptions) (result *extensions.JobList, err error) {
|
||||
result = &extensions.JobList{}
|
||||
err = c.r.Get().Namespace(c.ns).Resource("jobs").VersionedParams(&opts, api.ParameterCodec).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Get returns information about a particular job.
|
||||
func (c *jobsV1) Get(name string) (result *extensions.Job, err error) {
|
||||
result = &extensions.Job{}
|
||||
err = c.r.Get().Namespace(c.ns).Resource("jobs").Name(name).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Create creates a new job.
|
||||
func (c *jobsV1) Create(job *extensions.Job) (result *extensions.Job, err error) {
|
||||
result = &extensions.Job{}
|
||||
err = c.r.Post().Namespace(c.ns).Resource("jobs").Body(job).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update updates an existing job.
|
||||
func (c *jobsV1) Update(job *extensions.Job) (result *extensions.Job, err error) {
|
||||
result = &extensions.Job{}
|
||||
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).Body(job).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete deletes a job, returns error if one occurs.
|
||||
func (c *jobsV1) Delete(name string, options *api.DeleteOptions) (err error) {
|
||||
return c.r.Delete().Namespace(c.ns).Resource("jobs").Name(name).Body(options).Do().Error()
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested jobs.
|
||||
func (c *jobsV1) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||
return c.r.Get().
|
||||
Prefix("watch").
|
||||
Namespace(c.ns).
|
||||
Resource("jobs").
|
||||
VersionedParams(&opts, api.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// UpdateStatus takes the name of the job and the new status. Returns the server's representation of the job, and an error, if it occurs.
|
||||
func (c *jobsV1) UpdateStatus(job *extensions.Job) (result *extensions.Job, err error) {
|
||||
result = &extensions.Job{}
|
||||
err = c.r.Put().Namespace(c.ns).Resource("jobs").Name(job.Name).SubResource("status").Body(job).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
@ -26,19 +26,32 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
)
|
||||
|
||||
func getJobResourceName() string {
|
||||
func getJobsResourceName() string {
|
||||
return "jobs"
|
||||
}
|
||||
|
||||
func TestListJobs(t *testing.T) {
|
||||
func getJobClient(t *testing.T, c *simple.Client, ns, resourceGroup string) JobInterface {
|
||||
switch resourceGroup {
|
||||
case batch.GroupName:
|
||||
return c.Setup(t).Batch().Jobs(ns)
|
||||
case extensions.GroupName:
|
||||
return c.Setup(t).Extensions().Jobs(ns)
|
||||
default:
|
||||
t.Fatalf("Unknown group %v", resourceGroup)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func testListJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceAll
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "GET",
|
||||
Path: testapi.Extensions.ResourcePath(getJobResourceName(), ns, ""),
|
||||
Path: group.ResourcePath(getJobsResourceName(), ns, ""),
|
||||
},
|
||||
Response: simple.Response{StatusCode: 200,
|
||||
Body: &extensions.JobList{
|
||||
@ -58,18 +71,24 @@ func TestListJobs(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
receivedJobList, err := c.Setup(t).Extensions().Jobs(ns).List(api.ListOptions{})
|
||||
receivedJobList, err := getJobClient(t, c, ns, resourceGroup).List(api.ListOptions{})
|
||||
defer c.Close()
|
||||
c.Validate(t, receivedJobList, err)
|
||||
}
|
||||
|
||||
func TestGetJob(t *testing.T) {
|
||||
func TestListJob(t *testing.T) {
|
||||
testListJob(t, testapi.Extensions, extensions.GroupName)
|
||||
testListJob(t, testapi.Batch, batch.GroupName)
|
||||
}
|
||||
|
||||
func testGetJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "GET",
|
||||
Path: testapi.Extensions.ResourcePath(getJobResourceName(), ns, "foo"),
|
||||
Path: group.ResourcePath(getJobsResourceName(), ns, "foo"),
|
||||
Query: simple.BuildQueryValues(nil),
|
||||
},
|
||||
Response: simple.Response{
|
||||
@ -87,61 +106,61 @@ func TestGetJob(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
receivedJob, err := c.Setup(t).Extensions().Jobs(ns).Get("foo")
|
||||
receivedJob, err := getJobClient(t, c, ns, resourceGroup).Get("foo")
|
||||
defer c.Close()
|
||||
c.Validate(t, receivedJob, err)
|
||||
}
|
||||
|
||||
func TestGetJobWithNoName(t *testing.T) {
|
||||
ns := api.NamespaceDefault
|
||||
c := &simple.Client{Error: true}
|
||||
receivedJob, err := c.Setup(t).Extensions().Jobs(ns).Get("")
|
||||
defer c.Close()
|
||||
if (err != nil) && (err.Error() != simple.NameRequiredError) {
|
||||
t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err)
|
||||
}
|
||||
func TestGetJob(t *testing.T) {
|
||||
testGetJob(t, testapi.Extensions, extensions.GroupName)
|
||||
testGetJob(t, testapi.Batch, batch.GroupName)
|
||||
}
|
||||
|
||||
func testUpdateJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
requestJob := &extensions.Job{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
Namespace: ns,
|
||||
ResourceVersion: "1",
|
||||
},
|
||||
}
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "PUT",
|
||||
Path: group.ResourcePath(getJobsResourceName(), ns, "foo"),
|
||||
Query: simple.BuildQueryValues(nil),
|
||||
},
|
||||
Response: simple.Response{
|
||||
StatusCode: 200,
|
||||
Body: &extensions.Job{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
"name": "baz",
|
||||
},
|
||||
},
|
||||
Spec: extensions.JobSpec{
|
||||
Template: api.PodTemplateSpec{},
|
||||
},
|
||||
},
|
||||
},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
receivedJob, err := getJobClient(t, c, ns, resourceGroup).Update(requestJob)
|
||||
defer c.Close()
|
||||
c.Validate(t, receivedJob, err)
|
||||
}
|
||||
|
||||
func TestUpdateJob(t *testing.T) {
|
||||
ns := api.NamespaceDefault
|
||||
requestJob := &extensions.Job{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
Namespace: ns,
|
||||
ResourceVersion: "1",
|
||||
},
|
||||
}
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "PUT",
|
||||
Path: testapi.Extensions.ResourcePath(getJobResourceName(), ns, "foo"),
|
||||
Query: simple.BuildQueryValues(nil),
|
||||
},
|
||||
Response: simple.Response{
|
||||
StatusCode: 200,
|
||||
Body: &extensions.Job{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
"name": "baz",
|
||||
},
|
||||
},
|
||||
Spec: extensions.JobSpec{
|
||||
Template: api.PodTemplateSpec{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
receivedJob, err := c.Setup(t).Extensions().Jobs(ns).Update(requestJob)
|
||||
defer c.Close()
|
||||
c.Validate(t, receivedJob, err)
|
||||
testUpdateJob(t, testapi.Extensions, extensions.GroupName)
|
||||
testUpdateJob(t, testapi.Batch, batch.GroupName)
|
||||
}
|
||||
|
||||
func TestUpdateJobStatus(t *testing.T) {
|
||||
func testUpdateJobStatus(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
requestJob := &extensions.Job{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
@ -153,7 +172,7 @@ func TestUpdateJobStatus(t *testing.T) {
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "PUT",
|
||||
Path: testapi.Extensions.ResourcePath(getJobResourceName(), ns, "foo") + "/status",
|
||||
Path: group.ResourcePath(getJobsResourceName(), ns, "foo") + "/status",
|
||||
Query: simple.BuildQueryValues(nil),
|
||||
},
|
||||
Response: simple.Response{
|
||||
@ -174,28 +193,40 @@ func TestUpdateJobStatus(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
receivedJob, err := c.Setup(t).Extensions().Jobs(ns).UpdateStatus(requestJob)
|
||||
receivedJob, err := getJobClient(t, c, ns, resourceGroup).UpdateStatus(requestJob)
|
||||
defer c.Close()
|
||||
c.Validate(t, receivedJob, err)
|
||||
}
|
||||
|
||||
func TestDeleteJob(t *testing.T) {
|
||||
func TestUpdateJobStatus(t *testing.T) {
|
||||
testUpdateJobStatus(t, testapi.Extensions, extensions.GroupName)
|
||||
testUpdateJobStatus(t, testapi.Batch, batch.GroupName)
|
||||
}
|
||||
|
||||
func testDeleteJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "DELETE",
|
||||
Path: testapi.Extensions.ResourcePath(getJobResourceName(), ns, "foo"),
|
||||
Path: group.ResourcePath(getJobsResourceName(), ns, "foo"),
|
||||
Query: simple.BuildQueryValues(nil),
|
||||
},
|
||||
Response: simple.Response{StatusCode: 200},
|
||||
Response: simple.Response{StatusCode: 200},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
err := c.Setup(t).Extensions().Jobs(ns).Delete("foo", nil)
|
||||
err := getJobClient(t, c, ns, resourceGroup).Delete("foo", nil)
|
||||
defer c.Close()
|
||||
c.Validate(t, nil, err)
|
||||
}
|
||||
|
||||
func TestCreateJob(t *testing.T) {
|
||||
func TestDeleteJob(t *testing.T) {
|
||||
testDeleteJob(t, testapi.Extensions, extensions.GroupName)
|
||||
testDeleteJob(t, testapi.Batch, batch.GroupName)
|
||||
}
|
||||
|
||||
func testCreateJob(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
requestJob := &extensions.Job{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
@ -206,7 +237,7 @@ func TestCreateJob(t *testing.T) {
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "POST",
|
||||
Path: testapi.Extensions.ResourcePath(getJobResourceName(), ns, ""),
|
||||
Path: group.ResourcePath(getJobsResourceName(), ns, ""),
|
||||
Body: requestJob,
|
||||
Query: simple.BuildQueryValues(nil),
|
||||
},
|
||||
@ -225,8 +256,17 @@ func TestCreateJob(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
receivedJob, err := c.Setup(t).Extensions().Jobs(ns).Create(requestJob)
|
||||
receivedJob, err := getJobClient(t, c, ns, resourceGroup).Create(requestJob)
|
||||
defer c.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
c.Validate(t, receivedJob, err)
|
||||
}
|
||||
|
||||
func TestCreateJob(t *testing.T) {
|
||||
testCreateJob(t, testapi.Extensions, extensions.GroupName)
|
||||
testCreateJob(t, testapi.Batch, batch.GroupName)
|
||||
}
|
||||
|
@ -82,3 +82,66 @@ func (c *FakeJobs) UpdateStatus(job *extensions.Job) (result *extensions.Job, er
|
||||
|
||||
return obj.(*extensions.Job), err
|
||||
}
|
||||
|
||||
// FakeJobs implements JobInterface. Meant to be embedded into a struct to get a default
|
||||
// implementation. This makes faking out just the methods you want to test easier.
|
||||
// This is a test implementation of JobsV1
|
||||
// TODO(piosz): get back to one client implementation once HPA will be graduated to GA completely
|
||||
type FakeJobsV1 struct {
|
||||
Fake *FakeBatch
|
||||
Namespace string
|
||||
}
|
||||
|
||||
func (c *FakeJobsV1) Get(name string) (*extensions.Job, error) {
|
||||
obj, err := c.Fake.Invokes(NewGetAction("jobs", c.Namespace, name), &extensions.Job{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.Job), err
|
||||
}
|
||||
|
||||
func (c *FakeJobsV1) List(opts api.ListOptions) (*extensions.JobList, error) {
|
||||
obj, err := c.Fake.Invokes(NewListAction("jobs", c.Namespace, opts), &extensions.JobList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.JobList), err
|
||||
}
|
||||
|
||||
func (c *FakeJobsV1) Create(job *extensions.Job) (*extensions.Job, error) {
|
||||
obj, err := c.Fake.Invokes(NewCreateAction("jobs", c.Namespace, job), job)
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.Job), err
|
||||
}
|
||||
|
||||
func (c *FakeJobsV1) Update(job *extensions.Job) (*extensions.Job, error) {
|
||||
obj, err := c.Fake.Invokes(NewUpdateAction("jobs", c.Namespace, job), job)
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.Job), err
|
||||
}
|
||||
|
||||
func (c *FakeJobsV1) Delete(name string, options *api.DeleteOptions) error {
|
||||
_, err := c.Fake.Invokes(NewDeleteAction("jobs", c.Namespace, name), &extensions.Job{})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *FakeJobsV1) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.InvokesWatch(NewWatchAction("jobs", c.Namespace, opts))
|
||||
}
|
||||
|
||||
func (c *FakeJobsV1) UpdateStatus(job *extensions.Job) (result *extensions.Job, err error) {
|
||||
obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("jobs", "status", c.Namespace, job), job)
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.Job), err
|
||||
}
|
||||
|
@ -92,6 +92,10 @@ func (c *Client) Setup(t *testing.T) *Client {
|
||||
Host: c.server.URL,
|
||||
ContentConfig: client.ContentConfig{GroupVersion: testapi.Autoscaling.GroupVersion()},
|
||||
})
|
||||
c.BatchClient = client.NewBatchOrDie(&client.Config{
|
||||
Host: c.server.URL,
|
||||
ContentConfig: client.ContentConfig{GroupVersion: testapi.Batch.GroupVersion()},
|
||||
})
|
||||
c.ExtensionsClient = client.NewExtensionsOrDie(&client.Config{
|
||||
Host: c.server.URL,
|
||||
ContentConfig: client.ContentConfig{GroupVersion: testapi.Extensions.GroupVersion()},
|
||||
|
@ -278,6 +278,10 @@ func (c *Fake) Autoscaling() client.AutoscalingInterface {
|
||||
return &FakeAutoscaling{c}
|
||||
}
|
||||
|
||||
func (c *Fake) Batch() client.BatchInterface {
|
||||
return &FakeBatch{c}
|
||||
}
|
||||
|
||||
func (c *Fake) Extensions() client.ExtensionsInterface {
|
||||
return &FakeExperimental{c}
|
||||
}
|
||||
@ -321,6 +325,19 @@ func (c *FakeAutoscaling) HorizontalPodAutoscalers(namespace string) client.Hori
|
||||
return &FakeHorizontalPodAutoscalersV1{Fake: c, Namespace: namespace}
|
||||
}
|
||||
|
||||
// NewSimpleFakeBatch returns a client that will respond with the provided objects
|
||||
func NewSimpleFakeBatch(objects ...runtime.Object) *FakeBatch {
|
||||
return &FakeBatch{Fake: NewSimpleFake(objects...)}
|
||||
}
|
||||
|
||||
type FakeBatch struct {
|
||||
*Fake
|
||||
}
|
||||
|
||||
func (c *FakeBatch) Jobs(namespace string) client.JobInterface {
|
||||
return &FakeJobsV1{Fake: c, Namespace: namespace}
|
||||
}
|
||||
|
||||
// NewSimpleFakeExp returns a client that will respond with the provided objects
|
||||
func NewSimpleFakeExp(objects ...runtime.Object) *FakeExperimental {
|
||||
return &FakeExperimental{Fake: NewSimpleFake(objects...)}
|
||||
|
@ -242,7 +242,7 @@ func (o *DrainOptions) getPodsForDeletion() ([]api.Pod, error) {
|
||||
daemonset_pod = true
|
||||
}
|
||||
} else if sr.Reference.Kind == "Job" {
|
||||
job, err := o.client.Jobs(sr.Reference.Namespace).Get(sr.Reference.Name)
|
||||
job, err := o.client.ExtensionsClient.Jobs(sr.Reference.Namespace).Get(sr.Reference.Name)
|
||||
|
||||
// Assume the only reason for an error is because the Job is
|
||||
// gone/missing, not for any other cause. TODO(mml): something more
|
||||
|
@ -40,6 +40,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
@ -221,6 +222,8 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
||||
return client.RESTClient, nil
|
||||
case autoscaling.GroupName:
|
||||
return client.AutoscalingClient.RESTClient, nil
|
||||
case batch.GroupName:
|
||||
return client.BatchClient.RESTClient, nil
|
||||
case extensions.GroupName:
|
||||
return client.ExtensionsClient.RESTClient, nil
|
||||
}
|
||||
@ -710,6 +713,12 @@ func (c *clientSwaggerSchema) ValidateBytes(data []byte) error {
|
||||
}
|
||||
return getSchemaAndValidate(c.c.AutoscalingClient.RESTClient, data, "apis/", gvk.GroupVersion().String(), c.cacheDir)
|
||||
}
|
||||
if gvk.Group == batch.GroupName {
|
||||
if c.c.BatchClient == nil {
|
||||
return errors.New("unable to validate: no batch client")
|
||||
}
|
||||
return getSchemaAndValidate(c.c.BatchClient.RESTClient, data, "apis/", gvk.GroupVersion().String(), c.cacheDir)
|
||||
}
|
||||
if gvk.Group == extensions.GroupName {
|
||||
if c.c.ExtensionsClient == nil {
|
||||
return errors.New("unable to validate: no experimental client")
|
||||
|
@ -33,6 +33,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
@ -94,6 +95,7 @@ func describerMap(c *client.Client) map[unversioned.GroupKind]Describer {
|
||||
extensions.Kind("DaemonSet"): &DaemonSetDescriber{c},
|
||||
extensions.Kind("Deployment"): &DeploymentDescriber{clientset.FromUnversionedClient(c)},
|
||||
extensions.Kind("Job"): &JobDescriber{c},
|
||||
batch.Kind("Job"): &JobDescriber{c},
|
||||
extensions.Kind("Ingress"): &IngressDescriber{c},
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
@ -46,8 +47,8 @@ func ScalerFor(kind unversioned.GroupKind, c client.Interface) (Scaler, error) {
|
||||
return &ReplicationControllerScaler{c}, nil
|
||||
case extensions.Kind("ReplicaSet"):
|
||||
return &ReplicaSetScaler{c.Extensions()}, nil
|
||||
case extensions.Kind("Job"):
|
||||
return &JobScaler{c.Extensions()}, nil
|
||||
case extensions.Kind("Job"), batch.Kind("Job"):
|
||||
return &JobScaler{c.Extensions()}, nil // Either kind of job can be scaled with Extensions interface.
|
||||
case extensions.Kind("Deployment"):
|
||||
return &DeploymentScaler{c.Extensions()}, nil
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
@ -75,7 +76,7 @@ func ReaperFor(kind unversioned.GroupKind, c client.Interface) (Reaper, error) {
|
||||
case api.Kind("Service"):
|
||||
return &ServiceReaper{c}, nil
|
||||
|
||||
case extensions.Kind("Job"):
|
||||
case extensions.Kind("Job"), batch.Kind("Job"):
|
||||
return &JobReaper{c, Interval, Timeout}, nil
|
||||
|
||||
case extensions.Kind("Deployment"):
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
_ "k8s.io/kubernetes/pkg/apis/authorization/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/batch/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
)
|
||||
|
@ -32,6 +32,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apiserver"
|
||||
apiservermetrics "k8s.io/kubernetes/pkg/apiserver/metrics"
|
||||
@ -285,6 +286,38 @@ func (m *Master) InstallAPIs(c *Config) {
|
||||
allGroups = append(allGroups, group)
|
||||
}
|
||||
|
||||
// Install batch unless disabled.
|
||||
if !m.ApiGroupVersionOverrides["batch/v1"].Disable {
|
||||
batchResources := m.getBatchResources(c)
|
||||
batchGroupMeta := registered.GroupOrDie(batch.GroupName)
|
||||
|
||||
// Hard code preferred group version to batch/v1
|
||||
batchGroupMeta.GroupVersion = unversioned.GroupVersion{Group: "batch", Version: "v1"}
|
||||
|
||||
apiGroupInfo := genericapiserver.APIGroupInfo{
|
||||
GroupMeta: *batchGroupMeta,
|
||||
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
|
||||
"v1": batchResources,
|
||||
},
|
||||
OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion,
|
||||
Scheme: api.Scheme,
|
||||
ParameterCodec: api.ParameterCodec,
|
||||
NegotiatedSerializer: api.Codecs,
|
||||
}
|
||||
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
|
||||
|
||||
batchGVForDiscovery := unversioned.GroupVersionForDiscovery{
|
||||
GroupVersion: batchGroupMeta.GroupVersion.String(),
|
||||
Version: batchGroupMeta.GroupVersion.Version,
|
||||
}
|
||||
group := unversioned.APIGroup{
|
||||
Name: batchGroupMeta.GroupVersion.Group,
|
||||
Versions: []unversioned.GroupVersionForDiscovery{batchGVForDiscovery},
|
||||
PreferredVersion: batchGVForDiscovery,
|
||||
}
|
||||
allGroups = append(allGroups, group)
|
||||
}
|
||||
|
||||
if err := m.InstallAPIGroups(apiGroupsInfo); err != nil {
|
||||
glog.Fatalf("Error in registering group versions: %v", err)
|
||||
}
|
||||
@ -666,9 +699,7 @@ func (m *Master) getExtensionResources(c *Config) map[string]rest.Storage {
|
||||
storage["deployments/rollback"] = deploymentStorage.Rollback
|
||||
}
|
||||
if isEnabled("jobs") {
|
||||
jobStorage, jobStatusStorage := jobetcd.NewREST(dbClient("jobs"), storageDecorator)
|
||||
storage["jobs"] = jobStorage
|
||||
storage["jobs/status"] = jobStatusStorage
|
||||
m.constructJobResources(c, storage)
|
||||
}
|
||||
if isEnabled("ingresses") {
|
||||
ingressStorage, ingressStatusStorage := ingressetcd.NewREST(dbClient("ingresses"), storageDecorator)
|
||||
@ -722,6 +753,40 @@ func (m *Master) getAutoscalingResources(c *Config) map[string]rest.Storage {
|
||||
return storage
|
||||
}
|
||||
|
||||
// constructJobResources makes Job resources and adds them to the storage map.
|
||||
// They're installed in both batch and extensions. It's assumed that you've
|
||||
// already done the check that they should be on.
|
||||
func (m *Master) constructJobResources(c *Config, restStorage map[string]rest.Storage) {
|
||||
// Note that job's storage settings are changed by changing the batch
|
||||
// group. Clearly we want all jobs to be stored in the same place no
|
||||
// matter where they're accessed from.
|
||||
storageDecorator := m.StorageDecorator()
|
||||
dbClient := func(resource string) storage.Interface {
|
||||
return c.StorageDestinations.Search([]string{batch.GroupName, extensions.GroupName}, resource)
|
||||
}
|
||||
jobStorage, jobStatusStorage := jobetcd.NewREST(dbClient("jobs"), storageDecorator)
|
||||
restStorage["jobs"] = jobStorage
|
||||
restStorage["jobs/status"] = jobStatusStorage
|
||||
}
|
||||
|
||||
// getBatchResources returns the resources for batch api
|
||||
func (m *Master) getBatchResources(c *Config) map[string]rest.Storage {
|
||||
resourceOverrides := m.ApiGroupVersionOverrides["batch/v1"].ResourceOverrides
|
||||
isEnabled := func(resource string) bool {
|
||||
// Check if the resource has been overriden.
|
||||
if enabled, ok := resourceOverrides[resource]; ok {
|
||||
return enabled
|
||||
}
|
||||
return !m.ApiGroupVersionOverrides["batch/v1"].Disable
|
||||
}
|
||||
|
||||
storage := map[string]rest.Storage{}
|
||||
if isEnabled("jobs") {
|
||||
m.constructJobResources(c, storage)
|
||||
}
|
||||
return storage
|
||||
}
|
||||
|
||||
// findExternalAddress returns ExternalIP of provided node with fallback to LegacyHostIP.
|
||||
func findExternalAddress(node *api.Node) (string, error) {
|
||||
var fallback string
|
||||
|
@ -32,10 +32,10 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
apiutil "k8s.io/kubernetes/pkg/api/util"
|
||||
utilnet "k8s.io/kubernetes/pkg/util/net"
|
||||
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||
"k8s.io/kubernetes/pkg/kubelet/client"
|
||||
@ -69,12 +69,15 @@ func setUp(t *testing.T) (Master, *etcdtesting.EtcdTestServer, Config, *assert.A
|
||||
api.GroupName, etcdstorage.NewEtcdStorage(server.Client, testapi.Default.Codec(), etcdtest.PathPrefix(), false))
|
||||
storageDestinations.AddAPIGroup(
|
||||
autoscaling.GroupName, etcdstorage.NewEtcdStorage(server.Client, testapi.Autoscaling.Codec(), etcdtest.PathPrefix(), false))
|
||||
storageDestinations.AddAPIGroup(
|
||||
batch.GroupName, etcdstorage.NewEtcdStorage(server.Client, testapi.Batch.Codec(), etcdtest.PathPrefix(), false))
|
||||
storageDestinations.AddAPIGroup(
|
||||
extensions.GroupName, etcdstorage.NewEtcdStorage(server.Client, testapi.Extensions.Codec(), etcdtest.PathPrefix(), false))
|
||||
|
||||
config.StorageDestinations = storageDestinations
|
||||
storageVersions[api.GroupName] = testapi.Default.GroupVersion().String()
|
||||
storageVersions[autoscaling.GroupName] = testapi.Autoscaling.GroupVersion().String()
|
||||
storageVersions[batch.GroupName] = testapi.Batch.GroupVersion().String()
|
||||
storageVersions[extensions.GroupName] = testapi.Extensions.GroupVersion().String()
|
||||
config.StorageVersions = storageVersions
|
||||
config.PublicAddress = net.ParseIP("192.168.10.4")
|
||||
@ -337,95 +340,114 @@ func TestAPIVersionOfDiscoveryEndpoints(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDiscoveryAtAPIS(t *testing.T) {
|
||||
master, etcdserver, config, assert := newMaster(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
// TODO(caesarxuchao): make this pass now that batch is added,
|
||||
// and rewrite it so that the indexes do not need to change each time a new api group is added.
|
||||
/*
|
||||
master, etcdserver, config, assert := newMaster(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
server := httptest.NewServer(master.HandlerContainer.ServeMux)
|
||||
resp, err := http.Get(server.URL + "/apis")
|
||||
if !assert.NoError(err) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
server := httptest.NewServer(master.HandlerContainer.ServeMux)
|
||||
resp, err := http.Get(server.URL + "/apis")
|
||||
if !assert.NoError(err) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
assert.Equal(http.StatusOK, resp.StatusCode)
|
||||
assert.Equal(http.StatusOK, resp.StatusCode)
|
||||
|
||||
groupList := unversioned.APIGroupList{}
|
||||
assert.NoError(decodeResponse(resp, &groupList))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
groupList := unversioned.APIGroupList{}
|
||||
assert.NoError(decodeResponse(resp, &groupList))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
expectGroupNames := []string{autoscaling.GroupName, extensions.GroupName}
|
||||
expectVersions := [][]unversioned.GroupVersionForDiscovery{
|
||||
{
|
||||
expectGroupNames := []string{autoscaling.GroupName, batch.GroupName, extensions.GroupName}
|
||||
expectVersions := [][]unversioned.GroupVersionForDiscovery{
|
||||
{
|
||||
GroupVersion: testapi.Autoscaling.GroupVersion().String(),
|
||||
Version: testapi.Autoscaling.GroupVersion().Version,
|
||||
{
|
||||
GroupVersion: testapi.Autoscaling.GroupVersion().String(),
|
||||
Version: testapi.Autoscaling.GroupVersion().Version,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
GroupVersion: testapi.Extensions.GroupVersion().String(),
|
||||
Version: testapi.Extensions.GroupVersion().Version,
|
||||
{
|
||||
GroupVersion: testapi.Batch.GroupVersion().String(),
|
||||
Version: testapi.Batch.GroupVersion().Version,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
expectPreferredVersion := []unversioned.GroupVersionForDiscovery{
|
||||
{
|
||||
GroupVersion: config.StorageVersions[autoscaling.GroupName],
|
||||
Version: apiutil.GetVersion(config.StorageVersions[autoscaling.GroupName]),
|
||||
},
|
||||
{
|
||||
GroupVersion: config.StorageVersions[extensions.GroupName],
|
||||
Version: apiutil.GetVersion(config.StorageVersions[extensions.GroupName]),
|
||||
},
|
||||
}
|
||||
{
|
||||
{
|
||||
GroupVersion: testapi.Extensions.GroupVersion().String(),
|
||||
Version: testapi.Extensions.GroupVersion().Version,
|
||||
},
|
||||
},
|
||||
}
|
||||
expectPreferredVersion := []unversioned.GroupVersionForDiscovery{
|
||||
{
|
||||
GroupVersion: config.StorageVersions[autoscaling.GroupName],
|
||||
Version: apiutil.GetVersion(config.StorageVersions[autoscaling.GroupName]),
|
||||
},
|
||||
{
|
||||
GroupVersion: config.StorageVersions[batch.GroupName],
|
||||
Version: apiutil.GetVersion(config.StorageVersions[batch.GroupName]),
|
||||
},
|
||||
{
|
||||
GroupVersion: config.StorageVersions[extensions.GroupName],
|
||||
Version: apiutil.GetVersion(config.StorageVersions[extensions.GroupName]),
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(2, len(groupList.Groups))
|
||||
assert.Equal(expectGroupNames[0], groupList.Groups[0].Name)
|
||||
assert.Equal(expectGroupNames[1], groupList.Groups[1].Name)
|
||||
|
||||
assert.Equal(expectVersions[0], groupList.Groups[0].Versions)
|
||||
assert.Equal(expectVersions[1], groupList.Groups[1].Versions)
|
||||
assert.Equal(2, len(groupList.Groups))
|
||||
assert.Equal(expectGroupNames[0], groupList.Groups[0].Name)
|
||||
assert.Equal(expectGroupNames[1], groupList.Groups[1].Name)
|
||||
|
||||
assert.Equal(expectPreferredVersion[0], groupList.Groups[0].PreferredVersion)
|
||||
assert.Equal(expectPreferredVersion[1], groupList.Groups[1].PreferredVersion)
|
||||
assert.Equal(expectVersions[0], groupList.Groups[0].Versions)
|
||||
assert.Equal(expectVersions[1], groupList.Groups[1].Versions)
|
||||
|
||||
thirdPartyGV := unversioned.GroupVersionForDiscovery{GroupVersion: "company.com/v1", Version: "v1"}
|
||||
master.addThirdPartyResourceStorage("/apis/company.com/v1", nil,
|
||||
unversioned.APIGroup{
|
||||
Name: "company.com",
|
||||
Versions: []unversioned.GroupVersionForDiscovery{thirdPartyGV},
|
||||
PreferredVersion: thirdPartyGV,
|
||||
})
|
||||
assert.Equal(expectPreferredVersion[0], groupList.Groups[0].PreferredVersion)
|
||||
assert.Equal(expectPreferredVersion[1], groupList.Groups[1].PreferredVersion)
|
||||
|
||||
resp, err = http.Get(server.URL + "/apis")
|
||||
if !assert.NoError(err) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
thirdPartyGV := unversioned.GroupVersionForDiscovery{GroupVersion: "company.com/v1", Version: "v1"}
|
||||
master.addThirdPartyResourceStorage("/apis/company.com/v1", nil,
|
||||
unversioned.APIGroup{
|
||||
Name: "company.com",
|
||||
Versions: []unversioned.GroupVersionForDiscovery{thirdPartyGV},
|
||||
PreferredVersion: thirdPartyGV,
|
||||
})
|
||||
|
||||
assert.Equal(http.StatusOK, resp.StatusCode)
|
||||
resp, err = http.Get(server.URL + "/apis")
|
||||
if !assert.NoError(err) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
assert.NoError(decodeResponse(resp, &groupList))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
assert.Equal(http.StatusOK, resp.StatusCode)
|
||||
|
||||
thirdPartyGroupName := "company.com"
|
||||
thirdPartyExpectVersions := []unversioned.GroupVersionForDiscovery{thirdPartyGV}
|
||||
assert.NoError(decodeResponse(resp, &groupList))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
assert.Equal(3, len(groupList.Groups))
|
||||
// autoscaling group
|
||||
assert.Equal(expectGroupNames[0], groupList.Groups[0].Name)
|
||||
assert.Equal(expectVersions[0], groupList.Groups[0].Versions)
|
||||
assert.Equal(expectPreferredVersion[0], groupList.Groups[0].PreferredVersion)
|
||||
// third party
|
||||
assert.Equal(thirdPartyGroupName, groupList.Groups[1].Name)
|
||||
assert.Equal(thirdPartyExpectVersions, groupList.Groups[1].Versions)
|
||||
assert.Equal(thirdPartyGV, groupList.Groups[1].PreferredVersion)
|
||||
// extensions group
|
||||
assert.Equal(expectGroupNames[1], groupList.Groups[2].Name)
|
||||
assert.Equal(expectVersions[1], groupList.Groups[2].Versions)
|
||||
assert.Equal(expectPreferredVersion[1], groupList.Groups[2].PreferredVersion)
|
||||
thirdPartyGroupName := "company.com"
|
||||
thirdPartyExpectVersions := []unversioned.GroupVersionForDiscovery{thirdPartyGV}
|
||||
|
||||
assert.Equal(4, len(groupList.Groups))
|
||||
// autoscaling group
|
||||
assert.Equal(expectGroupNames[0], groupList.Groups[0].Name)
|
||||
assert.Equal(expectVersions[0], groupList.Groups[0].Versions)
|
||||
assert.Equal(expectPreferredVersion[0], groupList.Groups[0].PreferredVersion)
|
||||
// batch group
|
||||
assert.Equal(expectGroupNames[1], groupList.Groups[1].Name)
|
||||
assert.Equal(expectVersions[1], groupList.Groups[1].Versions)
|
||||
assert.Equal(expectPreferredVersion[1], groupList.Groups[1].PreferredVersion)
|
||||
// third party
|
||||
assert.Equal(thirdPartyGroupName, groupList.Groups[2].Name)
|
||||
assert.Equal(thirdPartyExpectVersions, groupList.Groups[2].Versions)
|
||||
assert.Equal(thirdPartyGV, groupList.Groups[2].PreferredVersion)
|
||||
// extensions group
|
||||
assert.Equal(expectGroupNames[2], groupList.Groups[3].Name)
|
||||
assert.Equal(expectVersions[2], groupList.Groups[3].Versions)
|
||||
assert.Equal(expectPreferredVersion[2], groupList.Groups[3].PreferredVersion)
|
||||
*/
|
||||
}
|
||||
|
||||
var versionsToTest = []string{"v1", "v3"}
|
||||
|
@ -59,6 +59,13 @@ func NewAutoscalingEtcdStorage(client etcd.Client) storage.Interface {
|
||||
return etcdstorage.NewEtcdStorage(client, testapi.Autoscaling.Codec(), etcdtest.PathPrefix(), false)
|
||||
}
|
||||
|
||||
func NewBatchEtcdStorage(client etcd.Client) storage.Interface {
|
||||
if client == nil {
|
||||
client = NewEtcdClient()
|
||||
}
|
||||
return etcdstorage.NewEtcdStorage(client, testapi.Batch.Codec(), etcdtest.PathPrefix(), false)
|
||||
}
|
||||
|
||||
func NewExtensionsEtcdStorage(client etcd.Client) storage.Interface {
|
||||
if client == nil {
|
||||
client = NewEtcdClient()
|
||||
|
@ -30,6 +30,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apiserver"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
@ -153,12 +154,15 @@ func NewMasterConfig() *master.Config {
|
||||
storageVersions[api.GroupName] = testapi.Default.GroupVersion().String()
|
||||
autoscalingEtcdStorage := NewAutoscalingEtcdStorage(etcdClient)
|
||||
storageVersions[autoscaling.GroupName] = testapi.Autoscaling.GroupVersion().String()
|
||||
batchEtcdStorage := NewBatchEtcdStorage(etcdClient)
|
||||
storageVersions[batch.GroupName] = testapi.Batch.GroupVersion().String()
|
||||
expEtcdStorage := NewExtensionsEtcdStorage(etcdClient)
|
||||
storageVersions[extensions.GroupName] = testapi.Extensions.GroupVersion().String()
|
||||
|
||||
storageDestinations := genericapiserver.NewStorageDestinations()
|
||||
storageDestinations.AddAPIGroup(api.GroupName, etcdStorage)
|
||||
storageDestinations.AddAPIGroup(autoscaling.GroupName, autoscalingEtcdStorage)
|
||||
storageDestinations.AddAPIGroup(batch.GroupName, batchEtcdStorage)
|
||||
storageDestinations.AddAPIGroup(extensions.GroupName, expEtcdStorage)
|
||||
|
||||
return &master.Config{
|
||||
|
@ -51,6 +51,10 @@ func TestAutoscalingPrefix(t *testing.T) {
|
||||
testPrefix(t, "/apis/autoscaling/")
|
||||
}
|
||||
|
||||
func TestBatchPrefix(t *testing.T) {
|
||||
testPrefix(t, "/apis/batch/")
|
||||
}
|
||||
|
||||
func TestExtensionsPrefix(t *testing.T) {
|
||||
testPrefix(t, "/apis/extensions/")
|
||||
}
|
||||
@ -95,6 +99,10 @@ func autoscalingPath(resource, namespace, name string) string {
|
||||
return testapi.Autoscaling.ResourcePath(resource, namespace, name)
|
||||
}
|
||||
|
||||
func batchPath(resource, namespace, name string) string {
|
||||
return testapi.Batch.ResourcePath(resource, namespace, name)
|
||||
}
|
||||
|
||||
func extensionsPath(resource, namespace, name string) string {
|
||||
return testapi.Extensions.ResourcePath(resource, namespace, name)
|
||||
}
|
||||
@ -145,6 +153,164 @@ func TestAutoscalingGroupBackwardCompatibility(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
var jobV1beta1 string = `
|
||||
{
|
||||
"kind": "Job",
|
||||
"apiVersion": "extensions/v1beta1",
|
||||
"metadata": {
|
||||
"name": "pi",
|
||||
"labels": {
|
||||
"app": "pi"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"parallelism": 1,
|
||||
"completions": 1,
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"app": "pi"
|
||||
}
|
||||
},
|
||||
"template": {
|
||||
"metadata": {
|
||||
"name": "pi",
|
||||
"creationTimestamp": null,
|
||||
"labels": {
|
||||
"app": "pi"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "pi",
|
||||
"image": "perl",
|
||||
"command": [
|
||||
"perl",
|
||||
"-Mbignum=bpi",
|
||||
"-wle",
|
||||
"print bpi(2000)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Never"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var jobV1 string = `
|
||||
{
|
||||
"kind": "Job",
|
||||
"apiVersion": "batch/v1",
|
||||
"metadata": {
|
||||
"name": "pi",
|
||||
"labels": {
|
||||
"app": "pi"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"parallelism": 1,
|
||||
"completions": 1,
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"app": "pi"
|
||||
}
|
||||
},
|
||||
"template": {
|
||||
"metadata": {
|
||||
"name": "pi",
|
||||
"creationTimestamp": null,
|
||||
"labels": {
|
||||
"app": "pi"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "pi",
|
||||
"image": "perl",
|
||||
"command": [
|
||||
"perl",
|
||||
"-Mbignum=bpi",
|
||||
"-wle",
|
||||
"print bpi(2000)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Never"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var deleteResp string = `
|
||||
{
|
||||
"kind": "Status",
|
||||
"apiVersion": "v1",
|
||||
"metadata":{},
|
||||
"status":"Success",
|
||||
"code":200
|
||||
}
|
||||
`
|
||||
|
||||
// TestBatchGroupBackwardCompatibility is testing that batch/v1 and ext/v1beta1
|
||||
// Job share storage. This test can be deleted when Jobs is removed from ext/v1beta1,
|
||||
// (expected to happen in 1.4).
|
||||
func TestBatchGroupBackwardCompatibility(t *testing.T) {
|
||||
_, s := framework.RunAMaster(t)
|
||||
defer s.Close()
|
||||
transport := http.DefaultTransport
|
||||
|
||||
requests := []struct {
|
||||
verb string
|
||||
URL string
|
||||
body string
|
||||
expectedStatusCodes map[int]bool
|
||||
expectedVersion string
|
||||
}{
|
||||
// Post a v1 and get back both as v1beta1 and as v1.
|
||||
{"POST", batchPath("jobs", api.NamespaceDefault, ""), jobV1, code201, ""},
|
||||
{"GET", batchPath("jobs", api.NamespaceDefault, "pi"), "", code200, testapi.Batch.GroupVersion().String()},
|
||||
{"GET", extensionsPath("jobs", api.NamespaceDefault, "pi"), "", code200, testapi.Extensions.GroupVersion().String()},
|
||||
{"DELETE", batchPath("jobs", api.NamespaceDefault, "pi"), "", code200, testapi.Default.GroupVersion().String()}, // status response
|
||||
// Post a v1beta1 and get back both as v1beta1 and as v1.
|
||||
{"POST", extensionsPath("jobs", api.NamespaceDefault, ""), jobV1beta1, code201, ""},
|
||||
{"GET", batchPath("jobs", api.NamespaceDefault, "pi"), "", code200, testapi.Batch.GroupVersion().String()},
|
||||
{"GET", extensionsPath("jobs", api.NamespaceDefault, "pi"), "", code200, testapi.Extensions.GroupVersion().String()},
|
||||
{"DELETE", extensionsPath("jobs", api.NamespaceDefault, "pi"), "", code200, testapi.Default.GroupVersion().String()}, //status response
|
||||
}
|
||||
|
||||
for _, r := range requests {
|
||||
bodyBytes := bytes.NewReader([]byte(r.body))
|
||||
req, err := http.NewRequest(r.verb, s.URL+r.URL, bodyBytes)
|
||||
if err != nil {
|
||||
t.Logf("case %v", r)
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
func() {
|
||||
resp, err := transport.RoundTrip(req)
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
t.Logf("case %v", r)
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
body := string(b)
|
||||
if _, ok := r.expectedStatusCodes[resp.StatusCode]; !ok {
|
||||
t.Logf("case %v", r)
|
||||
t.Errorf("Expected status one of %v, but got %v", r.expectedStatusCodes, resp.StatusCode)
|
||||
t.Errorf("Body: %v", body)
|
||||
}
|
||||
if !strings.Contains(body, "\"apiVersion\":\""+r.expectedVersion) {
|
||||
t.Logf("case %v", r)
|
||||
t.Errorf("Expected version %v, got body %v", r.expectedVersion, body)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccept(t *testing.T) {
|
||||
_, s := framework.RunAMaster(t)
|
||||
// TODO: Uncomment when fix #19254
|
||||
|
Loading…
Reference in New Issue
Block a user