Skip to content

Commit

Permalink
Merge pull request #159 from rundeck/add_logging_limits
Browse files Browse the repository at this point in the history
Add logging limits
  • Loading branch information
fdevans authored Jan 22, 2025
2 parents a662859 + f5feb3e commit c9788ed
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 10 deletions.
8 changes: 8 additions & 0 deletions rundeck/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type JobDetail struct {
Description string `xml:"description"`
ExecutionEnabled bool `xml:"executionEnabled"`
LogLevel string `xml:"loglevel,omitempty"`
LoggingLimit *JobLoggingLimit `xml:"logging,omitempty"`
AllowConcurrentExecutions bool `xml:"multipleExecutions,omitempty"`
Dispatch *JobDispatch `xml:"dispatch,omitempty"`
CommandSequence *JobCommandSequence `xml:"sequence,omitempty"`
Expand All @@ -85,6 +86,13 @@ type Boolean struct {
Value bool `xml:",chardata"`
}

// JobLoggingLimit represents the logging limit options for a job.
type JobLoggingLimit struct {
Output string `xml:"limit,attr"`
Action string `xml:"limitAction,attr"`
Status string `xml:"status,attr"`
}

type Retry struct {
Delay string `xml:"delay,attr"`
Value string `xml:",chardata"`
Expand Down
63 changes: 63 additions & 0 deletions rundeck/resource_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,30 @@ func resourceRundeckJob() *schema.Resource {
Default: "INFO",
},

"log_limit": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"output": {
Type: schema.TypeString,
Required: true,
Description: "Enter either maximum total line-count (e.g. \"100\"), maximum per-node line-count (\"100/node\"), or maximum log file size (\"100MB\", \"100KB\", etc.), using \"GB\",\"MB\",\"KB\",\"B\" as Giga- Mega- Kilo- and bytes.",
},
"action": {
Type: schema.TypeString,
Optional: true,
Description: "Enter either \"halt\" or \"truncate\" to specify the action to take when the log limit is reached.",
},
"status": {
Type: schema.TypeString,
Optional: true,
Description: "Enter either \"failed\" or \"canceled\" or any custom status.",
},
},
},
},

"allow_concurrent_executions": {
Type: schema.TypeBool,
Optional: true,
Expand Down Expand Up @@ -722,6 +746,35 @@ func jobFromResourceData(d *schema.ResourceData) (*JobDetail, error) {
job.Dispatch.SuccessOnEmptyNodeFilter = successOnEmpty.(bool)
}

if v, ok := d.GetOk("log_limit"); ok {
logLimitList := v.([]interface{})

if len(logLimitList) > 0 {
logLimit := logLimitList[0].(map[string]interface{})

output, outputOk := logLimit["output"].(string)
if !outputOk || output == "" {
return nil, fmt.Errorf("log_limit.output is required and can't be empty")
}

action, actionOk := logLimit["action"].(string)
if actionOk && action != "" && action != "halt" && action != "truncate" {
return nil, fmt.Errorf("log_limit.action must be either 'halt' or 'truncate'")
}

status, statusOk := logLimit["status"].(string)
if !statusOk {
return nil, fmt.Errorf("log_limit.status could be either \"failed\" or \"canceled\" or any custom status)")
}

job.LoggingLimit = &JobLoggingLimit{
Output: output,
Action: action,
Status: status,
}
}
}

orchList := d.Get("orchestrator").([]interface{})
if len(orchList) > 1 {
return nil, fmt.Errorf("rundeck command may have no more than one orchestrator")
Expand Down Expand Up @@ -985,6 +1038,16 @@ func jobToResourceData(job *JobDetail, d *schema.ResourceData) error {
if err := d.Set("log_level", job.LogLevel); err != nil {
return err
}
if job.LoggingLimit != nil {
logLimit := map[string]interface{}{
"output": job.LoggingLimit.Output,
"action": job.LoggingLimit.Action,
"status": job.LoggingLimit.Status,
}
if err := d.Set("log_limit", logLimit); err != nil {
return err
}
}
if err := d.Set("allow_concurrent_executions", job.AllowConcurrentExecutions); err != nil {
return err
}
Expand Down
77 changes: 69 additions & 8 deletions rundeck/resource_job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,36 @@ func TestAccJob_basic(t *testing.T) {
})
}

func TestAccJob_withLogLimit(t *testing.T) {
var job JobDetail

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccJobCheckDestroy(&job),
Steps: []resource.TestStep{
{
Config: testAccJobConfig_withLogLimit,
Check: resource.ComposeTestCheckFunc(
testAccJobCheckExists("rundeck_job.testWithAllLimitsSpecified", &job),
func(s *terraform.State) error {
if expected := "100MB"; job.LoggingLimit.Output != expected {
return fmt.Errorf("wrong value for log limit output; expected %v, got %v", expected, job.LoggingLimit.Output)
}
if expected := "truncate"; job.LoggingLimit.Action != expected {
return fmt.Errorf("wrong value for log limit action; expected %v, got %v", expected, job.LoggingLimit.Action)
}
if expected := "failed"; job.LoggingLimit.Status != expected {
return fmt.Errorf("wrong value for log limit status; expected %v, got %v", expected, job.LoggingLimit.Status)
}
return nil
},
),
},
},
})
}

func TestAccJob_cmd_nodefilter(t *testing.T) {
var job JobDetail

Expand Down Expand Up @@ -437,6 +467,37 @@ resource "rundeck_job" "test" {
}
`

const testAccJobConfig_withLogLimit = `
resource "rundeck_project" "test" {
name = "terraform-acc-test-job"
description = "parent project for job acceptance tests"
resource_model_source {
type = "file"
config = {
format = "resourcexml"
file = "/tmp/terraform-acc-tests.xml"
}
}
}
resource "rundeck_job" "testWithAllLimitsSpecified" {
name = "Test Job with All Log Limits Specified"
project_name = "${rundeck_project.test.name}"
description = "This is a test job with log_limit"
log_limit {
output = "100MB"
action = "truncate"
status = "failed"
}
command {
description = "Test command"
shell_command = "echo Hello World"
}
}
`

const testAccJobConfig_cmd_nodefilter = `
resource "rundeck_project" "test" {
name = "terraform-acc-test-job"
Expand Down Expand Up @@ -465,7 +526,7 @@ resource "rundeck_job" "test" {
option {
name = "foo"
default_value = "bar"
}
}
orchestrator {
type = "subset"
count = 1
Expand Down Expand Up @@ -522,7 +583,7 @@ resource "rundeck_job" "source_test_job" {
option {
name = "foo"
default_value = "bar"
}
}
}
resource "rundeck_job" "target_test_job" {
project_name = "${rundeck_project.target_test.name}"
Expand Down Expand Up @@ -780,7 +841,7 @@ const testOchestration_maxperecent = `
resource "rundeck_project" "test" {
name = "terraform-acc-test-job"
description = "parent project for job acceptance tests"
resource_model_source {
type = "file"
config = {
Expand All @@ -804,7 +865,7 @@ resource "rundeck_project" "test" {
option {
name = "foo"
default_value = "bar"
}
}
orchestrator {
type = "maxPercentage"
percent = 10
Expand Down Expand Up @@ -832,7 +893,7 @@ const testOchestration_high_low = `
resource "rundeck_project" "test" {
name = "terraform-acc-test-job"
description = "parent project for job acceptance tests"
resource_model_source {
type = "file"
config = {
Expand All @@ -856,7 +917,7 @@ resource "rundeck_project" "test" {
option {
name = "foo"
default_value = "bar"
}
}
orchestrator {
type = "orchestrator-highest-lowest-attribute"
sort = "highest"
Expand Down Expand Up @@ -885,7 +946,7 @@ const testOchestration_rank_tiered = `
resource "rundeck_project" "test" {
name = "terraform-acc-test-job"
description = "parent project for job acceptance tests"
resource_model_source {
type = "file"
config = {
Expand All @@ -909,7 +970,7 @@ resource "rundeck_project" "test" {
option {
name = "foo"
default_value = "bar"
}
}
orchestrator {
type = "rankTiered"
}
Expand Down
31 changes: 29 additions & 2 deletions website/docs/r/job.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,25 @@ Each job belongs to a project. A project can be created with the `rundeck_projec
```

## Example Usage (Specify Log Limit)
```hcl
resource "rundeck_job" "example_with_log_limit" {
name = "Example Job with Log Limit"
project_name = rundeck_project.terraform.name
description = "An example job with log limit settings"
log_limit {
output = "100MB"
action = "halt"
status = "failed"
}
command {
shell_command = "echo 'Hello, World!'"
}
}
```

## Argument Reference

The following arguments are supported:
Expand All @@ -89,6 +108,14 @@ The following arguments are supported:

* `log_level` - (Optional) The log level that Rundeck should use for this job. Defaults to "INFO".

* `log_limit` - (Optional) A block defining the log limit settings for the job. The structure of this nested block is described below.

The `log_limit` block has the following structure:

* `output` - (Required) Enter either maximum total line-count (e.g. "100"), maximum per-node line-count ("100/node"), or maximum log file size ("100MB", "100KB", etc.), using "GB","MB","KB","B" as Giga- Mega- Kilo- and bytes.
* `action` - (Optional) Enter either "halt" or "truncate" to specify the action to take when the log limit is reached.
* `status` - (Optional) Enter either "failed" or "aborted" or any custom status.

* `timeout` - (Optional) The maximum time for an execution to run. Time in seconds, or specify time units: "120m", "2h", "3d". Use blank or 0 to indicate no timeout.

* `schedule` - (Optional) The job's schedule in Quartz schedule cron format. Similar to unix crontab, but with seven fields instead of five: Second Minute Hour Day-of-Month Month Day-of-Week Year
Expand Down Expand Up @@ -281,9 +308,9 @@ A command's `job` block has the following structure:

* `skip_notifications` (Optional) If the referenced job has notifications, they will be skipped.

* `fail_on_disable` (Optional) If the referenced job has disabled execution, it will be considered a failure
* `fail_on_disable` (Optional) If the referenced job has disabled execution, it will be considered a failure

* `child_nodes`: (Optional) If the referenced job is from another project, you can use referenced job node list instead of the parent's nodes.
* `child_nodes`: (Optional) If the referenced job is from another project, you can use referenced job node list instead of the parent's nodes.

* `node_filters`: (Optional) A map for overriding the referenced job's node filters.

Expand Down

0 comments on commit c9788ed

Please sign in to comment.