Add serviceaccount & resources config to cronjob source (#665)

Co-authored-by: Roland Huß <rhuss@redhat.com>
This commit is contained in:
Ying Chun Guo 2020-03-04 16:51:53 +08:00 committed by GitHub
parent 136de19775
commit e6c7d2859d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 160 additions and 20 deletions

View File

@ -18,6 +18,10 @@
|===
| | Description | PR
| ✨
| Add serviceaccount and resources config to cronjob source handling
| https://github.com/knative/client/issues/564[#564]
| ✨
| Allow configuration sink prefixes
| https://github.com/knative/client/pull/571[#571]

View File

@ -16,16 +16,27 @@ kn source cronjob create NAME --schedule SCHEDULE --sink SINK --data DATA [flags
# Create a crontab scheduler 'my-cron-trigger' which fires every minute and sends 'ping' to service 'mysvc' as a cloudevent
kn source cronjob create my-cron-trigger --schedule "* * * * */1" --data "ping" --sink svc:mysvc
# Create a crontab scheduler 'my-cron-trigger' with ServiceAccount name
kn source cronjob create my-cron-trigger1 --schedule "* * * * */1" --data "ping" --sink svc:event-display --service-account myaccount
# Create a crontab scheduler 'my-cron-trigger' with requested resources
kn source cronjob create my-cron-trigger1 --schedule "* * * * */1" --data "ping" --sink svc:event-display --requests-cpu 100m --requests-memory 128Mi
```
### Options
```
-d, --data string String data to send
-h, --help help for create
-n, --namespace string Specify the namespace to operate in.
--schedule string Schedule specification in crontab format (e.g. '* * * * */2' for every two minutes
-s, --sink string Addressable sink for events
-d, --data string String data to send
-h, --help help for create
--limits-cpu string The limits on the requested CPU (e.g., 1000m).
--limits-memory string The limits on the requested memory (e.g., 1024Mi).
-n, --namespace string Specify the namespace to operate in.
--requests-cpu string The requested CPU (e.g., 250m).
--requests-memory string The requested memory (e.g., 64Mi).
--schedule string Schedule specification in crontab format (e.g. '* * * * */2' for every two minutes
--service-account string Name of the service account to use to run this source
-s, --sink string Addressable sink for events
```
### Options inherited from parent commands

View File

@ -21,11 +21,16 @@ kn source cronjob update NAME --schedule SCHEDULE --sink SERVICE --data DATA [fl
### Options
```
-d, --data string String data to send
-h, --help help for update
-n, --namespace string Specify the namespace to operate in.
--schedule string Schedule specification in crontab format (e.g. '* * * * */2' for every two minutes
-s, --sink string Addressable sink for events
-d, --data string String data to send
-h, --help help for update
--limits-cpu string The limits on the requested CPU (e.g., 1000m).
--limits-memory string The limits on the requested memory (e.g., 1024Mi).
-n, --namespace string Specify the namespace to operate in.
--requests-cpu string The requested CPU (e.g., 250m).
--requests-memory string The requested memory (e.g., 64Mi).
--schedule string Schedule specification in crontab format (e.g. '* * * * */2' for every two minutes
--service-account string Name of the service account to use to run this source
-s, --sink string Addressable sink for events
```
### Options inherited from parent commands

View File

@ -158,6 +158,31 @@ func (b *CronJobSourceBuilder) Sink(sink *duckv1beta1.Destination) *CronJobSourc
return b
}
func (b *CronJobSourceBuilder) ServiceAccount(sa string) *CronJobSourceBuilder {
b.cronjobSource.Spec.ServiceAccountName = sa
return b
}
func (b *CronJobSourceBuilder) ResourceRequestsCPU(cpu string) *CronJobSourceBuilder {
b.cronjobSource.Spec.Resources.Requests.ResourceCPU = cpu
return b
}
func (b *CronJobSourceBuilder) ResourceRequestsMemory(memory string) *CronJobSourceBuilder {
b.cronjobSource.Spec.Resources.Requests.ResourceMemory = memory
return b
}
func (b *CronJobSourceBuilder) ResourceLimitsCPU(cpu string) *CronJobSourceBuilder {
b.cronjobSource.Spec.Resources.Limits.ResourceCPU = cpu
return b
}
func (b *CronJobSourceBuilder) ResourceLimitsMemory(memory string) *CronJobSourceBuilder {
b.cronjobSource.Spec.Resources.Limits.ResourceMemory = memory
return b
}
func (b *CronJobSourceBuilder) Build() *v1alpha1.CronJobSource {
return b.cronjobSource
}

View File

@ -35,7 +35,13 @@ func NewCronJobCreateCommand(p *commands.KnParams) *cobra.Command {
Short: "Create a CronJob source.",
Example: `
# Create a crontab scheduler 'my-cron-trigger' which fires every minute and sends 'ping' to service 'mysvc' as a cloudevent
kn source cronjob create my-cron-trigger --schedule "* * * * */1" --data "ping" --sink svc:mysvc`,
kn source cronjob create my-cron-trigger --schedule "* * * * */1" --data "ping" --sink svc:mysvc
# Create a crontab scheduler 'my-cron-trigger' with ServiceAccount name
kn source cronjob create my-cron-trigger1 --schedule "* * * * */1" --data "ping" --sink svc:event-display --service-account myaccount
# Create a crontab scheduler 'my-cron-trigger' with requested resources
kn source cronjob create my-cron-trigger1 --schedule "* * * * */1" --data "ping" --sink svc:event-display --requests-cpu 100m --requests-memory 128Mi`,
RunE: func(cmd *cobra.Command, args []string) (err error) {
if len(args) != 1 {
@ -68,6 +74,11 @@ func NewCronJobCreateCommand(p *commands.KnParams) *cobra.Command {
Schedule(cronUpdateFlags.schedule).
Data(cronUpdateFlags.data).
Sink(toDuckV1Beta1(destination)).
ResourceRequestsCPU(cronUpdateFlags.resourceRequestsCPU).
ResourceRequestsMemory(cronUpdateFlags.resourceRequestsMemory).
ResourceLimitsCPU(cronUpdateFlags.resourceLimitsCPU).
ResourceLimitsMemory(cronUpdateFlags.resourceLimitsMemory).
ServiceAccount(cronUpdateFlags.serviceAccountName).
Build())
if err == nil {
fmt.Fprintf(cmd.OutOrStdout(), "CronJob source '%s' created in namespace '%s'.\n", args[0], cronSourceClient.Namespace())

View File

@ -37,9 +37,10 @@ func TestSimpleCreateCronJobSource(t *testing.T) {
cronjobClient := clientsourcesv1alpha1.NewMockKnCronJobSourceClient(t)
cronJobRecorder := cronjobClient.Recorder()
cronJobRecorder.CreateCronJobSource(createCronJobSource("testsource", "* * * * */2", "maxwell", "mysvc"), nil)
cronJobRecorder.CreateCronJobSource(createCronJobSource("testsource", "* * * * */2", "maxwell", "mysvc", "mysa", "100m", "128Mi", "200m", "256Mi"), nil)
out, err := executeCronJobSourceCommand(cronjobClient, dynamicClient, "create", "--sink", "svc:mysvc", "--schedule", "* * * * */2", "--data", "maxwell", "testsource")
out, err := executeCronJobSourceCommand(cronjobClient, dynamicClient, "create", "--sink", "svc:mysvc", "--schedule", "* * * * */2", "--data", "maxwell",
"--service-account", "mysa", "--requests-cpu", "100m", "--requests-memory", "128Mi", "--limits-cpu", "200m", "--limits-memory", "256Mi", "testsource")
assert.NilError(t, err, "Source should have been created")
util.ContainsAll(out, "created", "default", "testsource")

View File

@ -82,9 +82,18 @@ func cleanupCronJobMockClient() {
cronJobSourceClientFactory = nil
}
func createCronJobSource(name, schedule, data, service string) *v1alpha1.CronJobSource {
func createCronJobSource(name, schedule, data, service string, sa string, requestcpu string, requestmm string, limitcpu string, limitmm string) *v1alpha1.CronJobSource {
sink := &v1beta1.Destination{
Ref: &corev1.ObjectReference{Name: service, Kind: "Service", APIVersion: "serving.knative.dev/v1", Namespace: "default"},
}
return source_client_v1alpha1.NewCronJobSourceBuilder(name).Schedule(schedule).Data(data).Sink(sink).Build()
return source_client_v1alpha1.NewCronJobSourceBuilder(name).
Schedule(schedule).
Data(data).
Sink(sink).
ResourceRequestsCPU(requestcpu).
ResourceRequestsMemory(requestmm).
ResourceLimitsCPU(limitcpu).
ResourceLimitsMemory(limitmm).
ServiceAccount(sa).
Build()
}

View File

@ -106,4 +106,12 @@ func writeCronJobSource(dw printers.PrefixWriter, source *v1alpha1.CronJobSource
commands.WriteMetadata(dw, &source.ObjectMeta, printDetails)
dw.WriteAttribute("Schedule", source.Spec.Schedule)
dw.WriteAttribute("Data", source.Spec.Data)
dw.WriteAttribute("ServiceAccountName", source.Spec.ServiceAccountName)
subWriter1 := dw.WriteAttribute("Resources", "")
subWriter2 := subWriter1.WriteAttribute("Requests", "")
subWriter2.WriteAttribute("CPU", source.Spec.Resources.Requests.ResourceCPU)
subWriter2.WriteAttribute("Memory", source.Spec.Resources.Requests.ResourceMemory)
subWriter2 = subWriter1.WriteAttribute("Limits", "")
subWriter2.WriteAttribute("CPU", source.Spec.Resources.Limits.ResourceCPU)
subWriter2.WriteAttribute("Memory", source.Spec.Resources.Limits.ResourceMemory)
}

View File

@ -37,6 +37,7 @@ func TestSimpleDescribe(t *testing.T) {
out, err := executeCronJobSourceCommand(cronjobClient, nil, "describe", "testsource")
assert.NilError(t, err)
util.ContainsAll(out, "1 2 3 4 5", "honeymoon", "myservicenamespace", "mysvc", "Service", "testsource")
util.ContainsAll(out, "myaccount", "100m", "128Mi", "200m", "256Mi")
cronJobRecorder.Validate()
@ -72,6 +73,17 @@ func getCronJobSource() *v1alpha1.CronJobSource {
Name: "mysvc",
},
},
ServiceAccountName: "myaccount",
Resources: v1alpha1.CronJobResourceSpec{
Requests: v1alpha1.CronJobRequestsSpec{
ResourceCPU: "100m",
ResourceMemory: "128Mi",
},
Limits: v1alpha1.CronJobLimitsSpec{
ResourceCPU: "200m",
ResourceMemory: "256Mi",
},
},
},
Status: v1alpha1.CronJobSourceStatus{},
}

View File

@ -29,13 +29,24 @@ import (
)
type cronJobUpdateFlags struct {
schedule string
data string
schedule string
data string
resourceRequestsCPU string
resourceRequestsMemory string
resourceLimitsCPU string
resourceLimitsMemory string
serviceAccountName string
}
func (c *cronJobUpdateFlags) addCronJobFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&c.schedule, "schedule", "", "Schedule specification in crontab format (e.g. '* * * * */2' for every two minutes")
cmd.Flags().StringVarP(&c.data, "data", "d", "", "String data to send")
cmd.Flags().StringVar(&c.resourceRequestsCPU, "requests-cpu", "", "The requested CPU (e.g., 250m).")
cmd.Flags().StringVar(&c.resourceRequestsMemory, "requests-memory", "", "The requested memory (e.g., 64Mi).")
cmd.Flags().StringVar(&c.resourceLimitsCPU, "limits-cpu", "", "The limits on the requested CPU (e.g., 1000m).")
cmd.Flags().StringVar(&c.resourceLimitsMemory, "limits-memory", "",
"The limits on the requested memory (e.g., 1024Mi).")
cmd.Flags().StringVar(&c.serviceAccountName, "service-account", "", "Name of the service account to use to run this source")
}
// CronJobListHandlers handles printing human readable table for `kn source cronjob list` command's output

View File

@ -28,7 +28,7 @@ func TestListCronJobSource(t *testing.T) {
cronjobClient := knsource_v1alpha1.NewMockKnCronJobSourceClient(t)
cronJobRecorder := cronjobClient.Recorder()
cJSource := createCronJobSource("testsource", "* * * * */2", "maxwell", "mysvc")
cJSource := createCronJobSource("testsource", "* * * * */2", "maxwell", "mysvc", "mysa", "100m", "128Mi", "200m", "256Mi")
cJSourceList := v1alpha1.CronJobSourceList{}
cJSourceList.Items = []v1alpha1.CronJobSource{*cJSource}

View File

@ -76,6 +76,21 @@ func NewCronJobUpdateCommand(p *commands.KnParams) *cobra.Command {
}
b.Sink(toDuckV1Beta1(destination))
}
if cmd.Flags().Changed("requests-cpu") {
b.ResourceRequestsCPU(cronUpdateFlags.resourceRequestsCPU)
}
if cmd.Flags().Changed("requests-memory") {
b.ResourceRequestsMemory(cronUpdateFlags.resourceRequestsMemory)
}
if cmd.Flags().Changed("limits-cpu") {
b.ResourceLimitsCPU(cronUpdateFlags.resourceLimitsCPU)
}
if cmd.Flags().Changed("limits-memory") {
b.ResourceLimitsMemory(cronUpdateFlags.resourceLimitsMemory)
}
if cmd.Flags().Changed("service-account") {
b.ServiceAccount(cronUpdateFlags.serviceAccountName)
}
err = cronSourceClient.UpdateCronJobSource(b.Build())
if err == nil {
fmt.Fprintf(cmd.OutOrStdout(), "CronJob source '%s' updated in namespace '%s'.\n", name, cronSourceClient.Namespace())

View File

@ -52,9 +52,10 @@ func TestSimpleUpdate(t *testing.T) {
},
Status: v1alpha1.CronJobSourceStatus{},
}, nil)
cronJobRecorder.UpdateCronJobSource(createCronJobSource("testsource", "* * * * */3", "maxwell", "mysvc"), nil)
cronJobRecorder.UpdateCronJobSource(createCronJobSource("testsource", "* * * * */3", "maxwell", "mysvc", "mysa", "100m", "128Mi", "200m", "256Mi"), nil)
out, err := executeCronJobSourceCommand(cronjobClient, nil, "update", "--schedule", "* * * * */3", "testsource")
out, err := executeCronJobSourceCommand(cronjobClient, nil, "update", "--schedule", "* * * * */3", "--service-account",
"mysa", "--requests-cpu", "100m", "--requests-memory", "128Mi", "--limits-cpu", "200m", "--limits-memory", "256Mi", "testsource")
assert.NilError(t, err)
util.ContainsAll(out, "updated", "default", "testsource")

View File

@ -57,6 +57,12 @@ func TestSourceCronJob(t *testing.T) {
out, err := test.getResourceFieldsWithJSONPath("cronjobsource", "testcronjobsource2", jpSinkRefNameInSpec)
assert.NilError(t, err)
assert.Equal(t, out, "testsvc1")
t.Log("create cronJob source with service account and resources")
test.cronJobSourceCreateWithResources(t, r, "testcronjobsource3", "* * * * */1", "ping", "svc:testsvc0", "default", "100m", "128Mi", "200m", "256Mi")
test.verifyCronJobSourceDescribe(t, r, "testcronjobsource3", "* * * * */1", "ping", "testsvc0", "default", "100m", "128Mi", "200m", "256Mi")
test.cronJobSourceUpdateResources(t, r, "testcronjobsource3", "101m", "129Mi", "201m", "257Mi")
test.verifyCronJobSourceDescribe(t, r, "testcronjobsource3", "* * * * */1", "ping", "testsvc0", "default", "101m", "129Mi", "201m", "257Mi")
}
func (test *e2eTest) cronJobSourceCreate(t *testing.T, r *KnRunResultCollector, sourceName string, schedule string, data string, sink string) {
@ -85,3 +91,24 @@ func (test *e2eTest) cronJobSourceUpdateSink(t *testing.T, r *KnRunResultCollect
assert.Check(t, util.ContainsAll(out.Stdout, sourceName, "updated", "namespace", test.kn.namespace))
r.AssertNoError(out)
}
func (test *e2eTest) cronJobSourceCreateWithResources(t *testing.T, r *KnRunResultCollector, sourceName string, schedule string, data string, sink string, sa string, requestcpu string, requestmm string, limitcpu string, limitmm string) {
out := test.kn.Run("source", "cronjob", "create", sourceName,
"--schedule", schedule, "--data", data, "--sink", sink, "--service-account", sa,
"--requests-cpu", requestcpu, "--requests-memory", requestmm, "--limits-cpu", limitcpu, "--limits-memory", limitmm)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, "cronjob", "source", sourceName, "created", "namespace", test.kn.namespace))
r.AssertNoError(out)
}
func (test *e2eTest) cronJobSourceUpdateResources(t *testing.T, r *KnRunResultCollector, sourceName string, requestcpu string, requestmm string, limitcpu string, limitmm string) {
out := test.kn.Run("source", "cronjob", "update", sourceName,
"--requests-cpu", requestcpu, "--requests-memory", requestmm, "--limits-cpu", limitcpu, "--limits-memory", limitmm)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, sourceName, "updated", "namespace", test.kn.namespace))
r.AssertNoError(out)
}
func (test *e2eTest) verifyCronJobSourceDescribe(t *testing.T, r *KnRunResultCollector, sourceName string, schedule string, data string, sink string, sa string, requestcpu string, requestmm string, limitcpu string, limitmm string) {
out := test.kn.Run("source", "cronjob", "describe", sourceName)
assert.Check(t, util.ContainsAllIgnoreCase(out.Stdout, sourceName, schedule, data, sink, sa, requestcpu, requestmm, limitcpu, limitmm))
r.AssertNoError(out)
}