-
Notifications
You must be signed in to change notification settings - Fork 985
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
Changes from all commits
321edb6
51ca9ae
ac5f5d7
8ef706c
4dd3ba4
b6a9819
b57cf57
93f8a8d
90f15ec
a8207ee
b5dcd47
2a45f60
38d2829
438debc
1f5a782
f79374d
22f458f
af3b4f0
60eb0ea
a0b433b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
package kubernetes | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
"k8s.io/api/batch/v1beta1" | ||
"k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
kubernetes "k8s.io/client-go/kubernetes" | ||
) | ||
|
||
func resourceKubernetesCronJob() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceKubernetesCronJobCreate, | ||
Read: resourceKubernetesCronJobRead, | ||
Update: resourceKubernetesCronJobUpdate, | ||
Delete: resourceKubernetesCronJobDelete, | ||
Exists: resourceKubernetesCronJobExists, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
Schema: map[string]*schema.Schema{ | ||
"metadata": namespacedMetadataSchema("cronjob", true), | ||
"spec": { | ||
Type: schema.TypeList, | ||
Description: "Spec of the cron job owned by the cluster", | ||
Required: true, | ||
MaxItems: 1, | ||
Elem: &schema.Resource{ | ||
Schema: cronJobSpecFields(), | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceKubernetesCronJobCreate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*kubernetes.Clientset) | ||
|
||
metadata := expandMetadata(d.Get("metadata").([]interface{})) | ||
spec, err := expandCronJobSpec(d.Get("spec").([]interface{})) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
job := v1beta1.CronJob{ | ||
ObjectMeta: metadata, | ||
Spec: spec, | ||
} | ||
|
||
log.Printf("[INFO] Creating new cron job: %#v", job) | ||
|
||
out, err := conn.BatchV1beta1().CronJobs(metadata.Namespace).Create(&job) | ||
if err != nil { | ||
return err | ||
} | ||
log.Printf("[INFO] Submitted new cron job: %#v", out) | ||
|
||
d.SetId(buildId(out.ObjectMeta)) | ||
|
||
return resourceKubernetesCronJobRead(d, meta) | ||
} | ||
|
||
func resourceKubernetesCronJobUpdate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*kubernetes.Clientset) | ||
|
||
namespace, _, err := idParts(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
metadata := expandMetadata(d.Get("metadata").([]interface{})) | ||
spec, err := expandCronJobSpec(d.Get("spec").([]interface{})) | ||
if err != nil { | ||
return err | ||
} | ||
spec.JobTemplate.ObjectMeta.Annotations = metadata.Annotations | ||
|
||
cronjob := &v1beta1.CronJob{ | ||
ObjectMeta: metadata, | ||
Spec: spec, | ||
} | ||
|
||
log.Printf("[INFO] Updating cron job %s: %s", d.Id(), cronjob) | ||
|
||
out, err := conn.BatchV1beta1().CronJobs(namespace).Update(cronjob) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The 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 Alternatively, if the resource doesn't support in-place update, then the I notice the |
||
if err != nil { | ||
return err | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Error wrapping. |
||
} | ||
log.Printf("[INFO] Submitted updated cron job: %#v", out) | ||
|
||
d.SetId(buildId(out.ObjectMeta)) | ||
return resourceKubernetesCronJobRead(d, meta) | ||
} | ||
|
||
func resourceKubernetesCronJobRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*kubernetes.Clientset) | ||
|
||
namespace, name, err := idParts(d.Id()) | ||
if err != nil { | ||
return err | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Error wrapping. |
||
} | ||
|
||
log.Printf("[INFO] Reading cron job %s", name) | ||
job, err := conn.BatchV1beta1().CronJobs(namespace).Get(name, metav1.GetOptions{}) | ||
if err != nil { | ||
log.Printf("[DEBUG] Received error: %#v", err) | ||
return err | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Error wrapping. |
||
} | ||
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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This dot-syntax type of attribute referencing in |
||
labels := job.ObjectMeta.Labels | ||
|
||
if _, ok := labels["controller-uid"]; ok { | ||
delete(labels, "controller-uid") | ||
} | ||
|
||
if _, ok := labels["cron-job-name"]; ok { | ||
delete(labels, "cron-job-name") | ||
} | ||
|
||
if job.Spec.JobTemplate.Spec.Selector != nil && | ||
job.Spec.JobTemplate.Spec.Selector.MatchLabels != nil { | ||
labels = job.Spec.JobTemplate.Spec.Selector.MatchLabels | ||
} | ||
|
||
if _, ok := labels["controller-uid"]; ok { | ||
delete(labels, "controller-uid") | ||
} | ||
} | ||
|
||
err = d.Set("metadata", flattenMetadata(job.ObjectMeta, d)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
jobSpec, err := flattenCronJobSpec(job.Spec, d) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = d.Set("spec", jobSpec) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceKubernetesCronJobDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*kubernetes.Clientset) | ||
|
||
namespace, name, err := idParts(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
log.Printf("[INFO] Deleting cron job: %#v", name) | ||
err = conn.BatchV1beta1().CronJobs(namespace).Delete(name, nil) | ||
if err != nil { | ||
return err | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Error wrapping. |
||
} | ||
|
||
err = resource.Retry(1*time.Minute, func() *resource.RetryError { | ||
_, err := conn.BatchV1beta1().CronJobs(namespace).Get(name, metav1.GetOptions{}) | ||
if err != nil { | ||
if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { | ||
return nil | ||
} | ||
return resource.NonRetryableError(err) | ||
} | ||
|
||
e := fmt.Errorf("Cron Job %s still exists", name) | ||
return resource.RetryableError(e) | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
log.Printf("[INFO] Cron Job %s deleted", name) | ||
|
||
d.SetId("") | ||
return nil | ||
} | ||
|
||
func resourceKubernetesCronJobExists(d *schema.ResourceData, meta interface{}) (bool, error) { | ||
conn := meta.(*kubernetes.Clientset) | ||
|
||
namespace, name, err := idParts(d.Id()) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
log.Printf("[INFO] Checking cron job %s", name) | ||
_, err = conn.BatchV1beta1().CronJobs(namespace).Get(name, metav1.GetOptions{}) | ||
if err != nil { | ||
if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { | ||
return false, nil | ||
} | ||
log.Printf("[DEBUG] Received error: %#v", err) | ||
} | ||
return true, err | ||
} |
There was a problem hiding this comment.
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?