Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
8bf4cfcf
Unverified
Commit
8bf4cfcf
authored
Feb 21, 2018
by
Maciej Szulik
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add kubectl create job --from=cronjob/<name>
parent
5b57c2db
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
78 additions
and
107 deletions
+78
-107
BUILD
pkg/kubectl/cmd/BUILD
+0
-2
create_job.go
pkg/kubectl/cmd/create_job.go
+52
-53
create_job_test.go
pkg/kubectl/cmd/create_job_test.go
+26
-52
No files found.
pkg/kubectl/cmd/BUILD
View file @
8bf4cfcf
...
...
@@ -133,7 +133,6 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/util/jsonmergepatch:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/mergepatch:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/rand:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
...
...
@@ -145,7 +144,6 @@ go_library(
"//vendor/k8s.io/client-go/discovery:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/typed/batch/v1:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/typed/batch/v1beta1:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library",
...
...
pkg/kubectl/cmd/create_job.go
View file @
8bf4cfcf
...
...
@@ -23,37 +23,34 @@ import (
"github.com/spf13/cobra"
batchv1
"k8s.io/api/batch/v1"
"k8s.io/apimachinery/pkg/api/meta
"
batchv1beta1
"k8s.io/api/batch/v1beta1
"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/rand"
clientbatchv1
"k8s.io/client-go/kubernetes/typed/batch/v1"
clientbatchv1beta1
"k8s.io/client-go/kubernetes/typed/batch/v1beta1"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil
"k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
)
var
(
jobLong
=
templates
.
LongDesc
(
i18n
.
T
(
`
Create a
Job to execute immediately from a specified CronJob
.`
))
Create a
job with the specified name
.`
))
jobExample
=
templates
.
Examples
(
i18n
.
T
(
`
# Create a
J
ob from a CronJob named "a-cronjob"
kubectl create job --from
-cronjob=
a-cronjob`
))
# Create a
j
ob from a CronJob named "a-cronjob"
kubectl create job --from
=cronjob/
a-cronjob`
))
)
type
CreateJobOptions
struct
{
FromCronJob
string
OutputFormat
string
Namespace
string
V1Beta1Client
clientbatchv1beta1
.
BatchV1beta1Interface
V1Client
clientbatchv1
.
BatchV1Interface
Mapper
meta
.
RESTMapper
Out
io
.
Writer
PrintObject
func
(
obj
runtime
.
Object
)
error
PrintSuccess
func
(
mapper
meta
.
RESTMapper
,
shortOutput
bool
,
out
io
.
Writer
,
resource
,
name
string
,
dryRun
bool
,
operation
string
)
Name
string
From
string
Namespace
string
Client
clientbatchv1
.
BatchV1Interface
Out
io
.
Writer
DryRun
bool
Builder
*
resource
.
Builder
Cmd
*
cobra
.
Command
}
// NewCmdCreateJob is a command to ease creating Jobs from CronJobs.
...
...
@@ -62,7 +59,7 @@ func NewCmdCreateJob(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
Out
:
cmdOut
,
}
cmd
:=
&
cobra
.
Command
{
Use
:
"job
--from-cronjob=CRONJOB
"
,
Use
:
"job
NAME [--from-cronjob=CRONJOB]
"
,
Short
:
jobLong
,
Long
:
jobLong
,
Example
:
jobExample
,
...
...
@@ -74,74 +71,76 @@ func NewCmdCreateJob(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
cmdutil
.
AddApplyAnnotationFlags
(
cmd
)
cmdutil
.
AddValidateFlags
(
cmd
)
cmdutil
.
AddPrinterFlags
(
cmd
)
cmd
.
Flags
()
.
String
(
"from
-cronjob"
,
""
,
"Specify the name of the CronJob to create a Job from
."
)
cmd
.
Flags
()
.
String
(
"from
"
,
""
,
"The name of the resource to create a Job from (only cronjob is supported)
."
)
return
cmd
}
func
(
c
*
CreateJobOptions
)
Complete
(
f
cmdutil
.
Factory
,
cmd
*
cobra
.
Command
,
args
[]
string
)
(
err
error
)
{
c
.
FromCronJob
=
cmdutil
.
GetFlagString
(
cmd
,
"from-cronjob"
)
// Complete other options for Run.
c
.
Mapper
,
_
=
f
.
Object
()
c
.
OutputFormat
=
cmdutil
.
GetFlagString
(
cmd
,
"output"
)
if
len
(
args
)
==
0
{
return
cmdutil
.
UsageErrorf
(
cmd
,
"NAME is required"
)
}
c
.
Name
=
args
[
0
]
c
.
From
=
cmdutil
.
GetFlagString
(
cmd
,
"from"
)
c
.
Namespace
,
_
,
err
=
f
.
DefaultNamespace
()
if
err
!=
nil
{
return
err
}
c
.
PrintObject
=
func
(
obj
runtime
.
Object
)
error
{
return
f
.
PrintObject
(
cmd
,
obj
,
c
.
Out
)
}
// need two client sets to deal with the differing versions of CronJobs and Jobs
clientset
,
err
:=
f
.
KubernetesClientSet
()
if
err
!=
nil
{
return
err
}
if
c
.
V1Client
==
nil
{
c
.
V1Client
=
clientset
.
BatchV1
()
}
if
c
.
V1Beta1Client
==
nil
{
c
.
V1Beta1Client
=
clientset
.
BatchV1beta1
()
}
c
.
Client
=
clientset
.
BatchV1
()
c
.
Builder
=
f
.
NewBuilder
()
c
.
Cmd
=
cmd
return
nil
}
func
(
c
*
CreateJobOptions
)
RunCreateJob
()
(
err
error
)
{
cronjob
,
err
:=
c
.
V1Beta1Client
.
CronJobs
(
c
.
Namespace
)
.
Get
(
c
.
FromCronJob
,
metav1
.
GetOptions
{})
func
(
c
*
CreateJobOptions
)
RunCreateJob
()
error
{
infos
,
err
:=
c
.
Builder
.
Unstructured
()
.
NamespaceParam
(
c
.
Namespace
)
.
DefaultNamespace
()
.
ResourceTypeOrNameArgs
(
false
,
c
.
From
)
.
Flatten
()
.
Latest
()
.
Do
()
.
Infos
()
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to fetch job: %v"
,
err
)
return
err
}
if
len
(
infos
)
!=
1
{
return
fmt
.
Errorf
(
"from must be an existing cronjob"
)
}
cronJob
,
ok
:=
infos
[
0
]
.
AsVersioned
()
.
(
*
batchv1beta1
.
CronJob
)
if
!
ok
{
return
fmt
.
Errorf
(
"from must be an existing cronjob"
)
}
return
c
.
createJob
(
cronJob
)
}
func
(
c
*
CreateJobOptions
)
createJob
(
cronJob
*
batchv1beta1
.
CronJob
)
error
{
annotations
:=
make
(
map
[
string
]
string
)
annotations
[
"cronjob.kubernetes.io/instantiate"
]
=
"manual"
labels
:=
make
(
map
[
string
]
string
)
for
k
,
v
:=
range
cronjob
.
Spec
.
JobTemplate
.
Labels
{
labels
[
k
]
=
v
for
k
,
v
:=
range
cronJob
.
Spec
.
JobTemplate
.
Annotations
{
annotations
[
k
]
=
v
}
jobToCreate
:=
&
batchv1
.
Job
{
ObjectMeta
:
metav1
.
ObjectMeta
{
// job name cannot exceed DNS1053LabelMaxLength (52 characters)
Name
:
cronjob
.
Name
+
"-manual-"
+
rand
.
String
(
3
),
Name
:
c
.
Name
,
Namespace
:
c
.
Namespace
,
Annotations
:
annotations
,
Labels
:
l
abels
,
Labels
:
cronJob
.
Spec
.
JobTemplate
.
L
abels
,
},
Spec
:
cron
j
ob
.
Spec
.
JobTemplate
.
Spec
,
Spec
:
cron
J
ob
.
Spec
.
JobTemplate
.
Spec
,
}
result
,
err
:=
c
.
V1Client
.
Jobs
(
c
.
Namespace
)
.
Create
(
jobToCreate
)
job
,
err
:=
c
.
Client
.
Jobs
(
c
.
Namespace
)
.
Create
(
jobToCreate
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to create job: %v"
,
err
)
}
return
c
.
PrintObject
(
result
)
return
cmdutil
.
PrintObject
(
c
.
Cmd
,
job
,
c
.
Out
)
}
pkg/kubectl/cmd/create_job_test.go
View file @
8bf4cfcf
...
...
@@ -18,32 +18,28 @@ package cmd
import
(
"bytes"
"fmt"
"strings"
"testing"
"k8s.io/apimachinery/pkg/runtime"
batchv1
"k8s.io/api/batch/v1"
batchv1beta1
"k8s.io/api/batch/v1beta1"
corev1
"k8s.io/api/core/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
fake
"k8s.io/client-go/kubernetes/fake"
clienttesting
"k8s.io/client-go/testing"
cmdtesting
"k8s.io/kubernetes/pkg/kubectl/cmd/testing"
)
var
submittedJob
*
batchv1
.
Job
func
TestCreateJobFromCronJob
(
t
*
testing
.
T
)
{
var
submittedJob
*
batchv1
.
Job
testNamespaceName
:=
"test"
testCronJobName
:=
"test-cronjob"
testJobName
:=
"test-job"
testImageName
:=
"fake"
expectedLabels
:=
make
(
map
[
string
]
string
)
expectedAnnotations
:=
make
(
map
[
string
]
string
)
expectedLabels
[
"test-label"
]
=
"test-value"
expectedAnnotations
[
"cronjob.kubernetes.io/instantiate"
]
=
"manual"
expectJob
:=
&
batchv1
.
Job
{
ObjectMeta
:
metav1
.
ObjectMeta
{
...
...
@@ -62,7 +58,7 @@ func TestCreateJobFromCronJob(t *testing.T) {
},
}
cronJob
ToCreate
:=
&
batchv1beta1
.
CronJob
{
cronJob
:=
&
batchv1beta1
.
CronJob
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
testCronJobName
,
Namespace
:
testNamespaceName
,
...
...
@@ -80,69 +76,47 @@ func TestCreateJobFromCronJob(t *testing.T) {
}
clientset
:=
fake
.
Clientset
{}
clientset
.
PrependReactor
(
"get"
,
"cronjobs"
,
func
(
action
clienttesting
.
Action
)
(
handled
bool
,
ret
runtime
.
Object
,
err
error
)
{
return
true
,
cronJobToCreate
,
nil
})
clientset
.
PrependReactor
(
"create"
,
"jobs"
,
func
(
action
clienttesting
.
Action
)
(
handled
bool
,
ret
runtime
.
Object
,
err
error
)
{
ca
:=
action
.
(
clienttesting
.
CreateAction
)
submittedJob
=
ca
.
GetObject
()
.
(
*
batchv1
.
Job
)
return
true
,
expectJob
,
nil
})
f
,
_
,
_
,
_
:=
cmdtesting
.
NewAPIFactory
()
f
,
_
:=
cmdtesting
.
NewAPIFactory
()
buf
:=
bytes
.
NewBuffer
([]
byte
{})
mapper
,
_
:=
f
.
Object
()
cmdOptions
:=
&
CreateJobOptions
{
Out
:
buf
,
OutputFormat
:
"na"
,
Namespace
:
testNamespaceName
,
FromCronJob
:
testCronJobName
,
V1Client
:
clientset
.
BatchV1
(),
V1Beta1Client
:
clientset
.
BatchV1beta1
(),
Mapper
:
mapper
,
PrintObject
:
func
(
obj
runtime
.
Object
)
error
{
return
nil
},
Name
:
testJobName
,
Namespace
:
testNamespaceName
,
Client
:
clientset
.
BatchV1
(),
Out
:
buf
,
Cmd
:
NewCmdCreateJob
(
f
,
buf
),
}
cmdOptions
.
RunCreateJob
()
composedJobName
:=
fmt
.
Sprintf
(
"%s-manual-"
,
testCronJobName
)
if
!
strings
.
HasPrefix
(
submittedJob
.
ObjectMeta
.
Name
,
composedJobName
)
{
t
.
Errorf
(
"
expected '%s', got '%s'"
,
composedJobName
,
submittedJob
.
ObjectMeta
.
Name
)
err
:=
cmdOptions
.
createJob
(
cronJob
)
if
err
!=
nil
{
t
.
Errorf
(
"
unexpected error: %v"
,
err
)
}
annotationsArrayLength
:=
len
(
submittedJob
.
Annotations
)
if
annotationsArrayLength
!=
1
{
t
.
Errorf
(
"expected length of annotations array to be 1, got %d"
,
annotationsArrayLength
)
if
submittedJob
.
ObjectMeta
.
Name
!=
testJobName
{
t
.
Errorf
(
"expected '%s', got '%s'"
,
testJobName
,
submittedJob
.
ObjectMeta
.
Name
)
}
if
v
,
ok
:=
submittedJob
.
Annotations
[
"cronjob.kubernetes.io/instantiate"
];
ok
{
if
v
!=
"manual"
{
t
.
Errorf
(
"expected annotation cronjob.kubernetes.io/instantiate to be 'manual', got '%s'"
,
v
)
}
}
else
{
t
.
Errorf
(
"expected annotation cronjob.kubernetes.io/instantiate to exist"
)
if
l
:=
len
(
submittedJob
.
Annotations
);
l
!=
1
{
t
.
Errorf
(
"expected length of annotations array to be 1, got %d"
,
l
)
}
labelsArrayLength
:=
len
(
submittedJob
.
Labels
)
if
labelsArrayLength
!=
1
{
t
.
Errorf
(
"expected length of labels array to be 1, got %d"
,
labelsArrayLength
)
if
v
,
ok
:=
submittedJob
.
Annotations
[
"cronjob.kubernetes.io/instantiate"
];
!
ok
||
v
!=
"manual"
{
t
.
Errorf
(
"expected annotation cronjob.kubernetes.io/instantiate=manual to exist, got '%s'"
,
v
)
}
if
v
,
ok
:=
submittedJob
.
Labels
[
"test-label"
];
ok
{
if
v
!=
"test-value"
{
t
.
Errorf
(
"expected label test-label to be 'test-value', got '%s'"
,
v
)
}
}
else
{
t
.
Errorf
(
"expected label test-label to exist"
)
if
l
:=
len
(
submittedJob
.
Labels
);
l
!=
1
{
t
.
Errorf
(
"expected length of labels array to be 1, got %d"
,
l
)
}
containerArrayLength
:=
len
(
submittedJob
.
Spec
.
Template
.
Spec
.
Containers
)
if
containerArrayLength
!=
1
{
t
.
Errorf
(
"expected length of container array to be 1, got %d"
,
containerArrayLength
)
if
v
,
ok
:=
submittedJob
.
Labels
[
"test-label"
];
!
ok
||
v
!=
"test-value"
{
t
.
Errorf
(
"expected label test-label=test-value to to exist, got '%s'"
,
v
)
}
if
l
:=
len
(
submittedJob
.
Spec
.
Template
.
Spec
.
Containers
);
l
!=
1
{
t
.
Errorf
(
"expected length of container array to be 1, got %d"
,
l
)
}
if
submittedJob
.
Spec
.
Template
.
Spec
.
Containers
[
0
]
.
Image
!=
testImageName
{
t
.
Errorf
(
"expected '%s', got '%s'"
,
testImageName
,
submittedJob
.
Spec
.
Template
.
Spec
.
Containers
[
0
]
.
Image
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment