Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Job and CronJob (closes #86 and #212) #411

Merged
merged 20 commits into from
Jun 24, 2019

Conversation

mbarrien
Copy link
Contributor

@mbarrien mbarrien commented Apr 23, 2019

This PR adds Terraform resources for Kubernetes Job and CronJob objects, and closes #86 and #212. It is mostly cherry picks from the sl1pm4t fork, using contributions from @srhaber, @sl1pm4t and @bassrock, and rebased against the head of master (currently just past 1.6.2). The licensing on the other branch should be compatible for cherry-picking here.

Although the commits are ostensibly cherry-picks, I've had to modify some of them for compatibility with the original branch. For followers of the sl1pm4t fork, these changes are:

  • Does not copy the top level metadata to the pod spec's metadata
  • Uses expandPodTemplate from the main branch rather than expandPodTemplateSpec from the fork
  • Does not hard code job spec restart policy to OnFailure
  • Forces job to use BatchV1beta1 api, removing support for BatchV2alpha1 api
  • Restore ability to patch kubernetes_job resources

.travis.yml Outdated
@@ -5,6 +5,7 @@ services:
language: go
go:
- "1.11.x"
go_import_path: github.com/terraform-providers/terraform-provider-kubernetes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any particular reason why this was needed?


out, err := conn.BatchV1beta1().CronJobs(metadata.Namespace).Create(&job)
if err != nil {
return err
Copy link
Member

@alexsomesan alexsomesan Apr 24, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mind wrapping this error with a message mentioning the Create operation failed?

Suggested change
return err
return fmt.Errorf("Failed to create CronJob: %s", err)


out, err := conn.BatchV1beta1().CronJobs(namespace).Update(cronjob)
if err != nil {
return err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error wrapping.


namespace, name, err := idParts(d.Id())
if err != nil {
return err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error wrapping.

job, err := conn.BatchV1beta1().CronJobs(namespace).Get(name, metav1.GetOptions{})
if err != nil {
log.Printf("[DEBUG] Received error: %#v", err)
return err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error wrapping.

"schedule": {
Type: schema.TypeString,
Required: true,
//ValidateFunc: validate, TODO: validate cron syntax..
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the plan here?
One option would be validation.ValidateRegexp(...) paired with something like http://regexlib.com/REDetails.aspx?regexp_id=2580&AspxAutoDetectCookieSupport=1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about reusing cron.ParseStandard() that the kubernetes API server uses for validation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even better idea! :)

"failed_jobs_history_limit": {
Type: schema.TypeInt,
Optional: true,
Default: "1",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This attribute is TypeInt. I presume the Default value should be an int literal.

"failed_jobs_history_limit": {
Type: schema.TypeInt,
Optional: true,
Default: "1",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This attribute is TypeInt. I presume the Default value should be an int literal.

Copy link
Member

@alexsomesan alexsomesan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for porting these resources over.

I've left some comments around the code. As usual, I can help and make those changes and push on top of the PR if that's ok with you.


log.Printf("[INFO] Updating cron job %s: %s", d.Id(), cronjob)

out, err := conn.BatchV1beta1().CronJobs(namespace).Update(cronjob)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Update() client-go operation is doing a complete replacing of the resource, rather then mutating only the fields present in the Terraform diff.

This is generally not the behaviour Terraform users expect when they see a diff with updates, since this wholesale-replace behaviour is modeled in Terraform via a Delete/Create sequence.

To achieve the expected behaviour of in-place updating specific attributes as per Terraform diff, one has to model this operation using d.HasChange(..) to extract changes for the Terraform diff and build a set of JSON-Patch actions to be passed to the Patch(..) operation of the client-go.

Alternatively, if the resource doesn't support in-place update, then the Update operation on the provider resource should just not be implemented.

I notice the Job resource also introduced in this PR does make proper use of patching, so it'd be great to have them both aligned.

log.Printf("[INFO] Received cron job: %#v", job)

// Remove server-generated labels unless using manual selector
if _, ok := d.GetOk("spec.0.manual_selector"); !ok {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This dot-syntax type of attribute referencing in d.Get(..) is on a deprecation path and not guaranteed to be supported in TF 0.12 and beyond. It'd be better to move this operation to its appropriate flatten func.

log.Printf("[INFO] Deleting cron job: %#v", name)
err = conn.BatchV1beta1().CronJobs(namespace).Delete(name, nil)
if err != nil {
return err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error wrapping.

})
}

func TestAccKubernetesCronJob_extra(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to expand extra to a more descriptive term.


func testAccKubernetesCronJobConfig_basic(name string) string {
return fmt.Sprintf(`
resource "kubernetes_cron_job" "test" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This inline HCL should be formatted similarly to what terraform fmt would produce.
Also, it needs to be Terraform 0.12 compatible (can be obtained by passing it to terraform 0.12upgrade).

log.Printf("[INFO] Updating job %s: %#v", d.Id(), ops)

out, err := conn.BatchV1().Jobs(namespace).Patch(name, pkgApi.JSONPatchType, data)
// out, err := conn.BatchV1().Jobs(namespace).Update(&job)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code!

log.Printf("[INFO] Deleting job: %#v", name)
err = conn.BatchV1().Jobs(namespace).Delete(name, nil)
if err != nil {
return err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error wrapping.

if in.StartingDeadlineSeconds != nil {
att["starting_deadline_seconds"] = int64(*in.StartingDeadlineSeconds)
} else {
att["starting_deadline_seconds"] = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The else block is not necessary. Zero is the default value for unset TypeInt. Also, there is a Default attribute on it's schema already.

if in.SuccessfulJobsHistoryLimit != nil {
att["successful_jobs_history_limit"] = int32(*in.SuccessfulJobsHistoryLimit)
} else {
att["successful_jobs_history_limit"] = 3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed. This attribute already has a Default in its schema.

if in.FailedJobsHistoryLimit != nil {
att["failed_jobs_history_limit"] = int(*in.FailedJobsHistoryLimit)
} else {
att["failed_jobs_history_limit"] = 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed. This attribute already has a Default in its schema.

@ghost ghost added the dependencies label Jun 21, 2019
@ghost ghost added the documentation label Jun 24, 2019
@alexsomesan
Copy link
Member

I completed the remaining items to get this change in mergeable shape.
Added docs and extended the test cases to reflect all attributes.
Fix issues with immutable attribute errors on updates.

Copy link
Member

@alexsomesan alexsomesan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI is green.

@alexsomesan alexsomesan merged commit 71bd6b0 into hashicorp:master Jun 24, 2019
@mbarrien mbarrien deleted the job branch October 21, 2019 06:26
@ghost ghost locked and limited conversation to collaborators Apr 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

kubernetes_job
6 participants