Skip to content

Commit

Permalink
Fix use of active_deadline_seconds and concurrency_policy
Browse files Browse the repository at this point in the history
  • Loading branch information
wpjunior committed Mar 22, 2024
1 parent 96ec7d1 commit 3b481b9
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 47 deletions.
14 changes: 2 additions & 12 deletions docs/resources/job.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ resource "tsuru_job" "my-job" {

### Optional

- `active_deadline_seconds` (Number) Time a Job can run before its terminated. Defaults is 3600
- `concurrency_policy` (String) Concurrency policy
- `description` (String) Job description
- `metadata` (Block List, Max: 1) (see [below for nested schema](#nestedblock--metadata))
- `schedule` (String) Cron-like schedule for when the job should be triggered
- `spec` (Block List, Max: 1) Check Kubernetes official Job specs docs for more details (see [below for nested schema](#nestedblock--spec))
- `tags` (List of String) Tags
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))

Expand Down Expand Up @@ -73,17 +74,6 @@ Optional:
- `labels` (Map of String)


<a id="nestedblock--spec"></a>
### Nested Schema for `spec`

Optional:

- `active_deadline_seconds` (Number) Time a Job can run before its terminated. Has precedence over backoff_limit. Defaults to no deadline
- `backoff_limit` (Number) Number of retries before considering a Job as failed. Default=6
- `completions` (Number) Successful executions for the job to be consider done. Default=1
- `parallelism` (Number) Number of concurrent instances (Pods) of the job. Default=1


<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/labstack/echo/v4 v4.9.1
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.8.4
github.com/tsuru/go-tsuruclient v0.0.0-20231130165047-4fa4c756fc6d
github.com/tsuru/go-tsuruclient v0.0.0-20240322174439-2a0eecb27288
github.com/tsuru/tsuru v0.0.0-20230721211340-f41fb455f8c3
k8s.io/apimachinery v0.22.5
)
Expand Down
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,8 @@ github.com/tsuru/config v0.0.0-20201023175036-375aaee8b560 h1:fniQ/BmYAHdnNmY333
github.com/tsuru/config v0.0.0-20201023175036-375aaee8b560/go.mod h1:mj6t8JKWU51GScTT50XRmDj65T5XhTyNvO5FUNV5zS4=
github.com/tsuru/gnuflag v0.0.0-20151217162021-86b8c1b864aa h1:JlLQP1xa13a994p/Aau2e3K9xXYaHNoNvTDVIMHSUa4=
github.com/tsuru/gnuflag v0.0.0-20151217162021-86b8c1b864aa/go.mod h1:UibOSvkMFKRe/eiwktAPAvQG8L+p8nYsECJvu3Dgw7I=
github.com/tsuru/go-tsuruclient v0.0.0-20231108180105-5735487e6f98 h1:bjSRngH503mFLCj/1EyVxR62OF6huYMkR903VIa23BM=
github.com/tsuru/go-tsuruclient v0.0.0-20231108180105-5735487e6f98/go.mod h1:BmePxHey9hxrxk0kzTMHFFr7aJWXSxtlrUx6FIeV0Ic=
github.com/tsuru/go-tsuruclient v0.0.0-20231130165047-4fa4c756fc6d h1:oP+/hghDjbLlfka1U/IDBi9sKWdrHcb/QOYLuvxkU14=
github.com/tsuru/go-tsuruclient v0.0.0-20231130165047-4fa4c756fc6d/go.mod h1:BmePxHey9hxrxk0kzTMHFFr7aJWXSxtlrUx6FIeV0Ic=
github.com/tsuru/go-tsuruclient v0.0.0-20240322174439-2a0eecb27288 h1:v8yGiRYcPL+85UwXpHlmCZ9Nz/Z2utxoAtBYtrnCzY8=
github.com/tsuru/go-tsuruclient v0.0.0-20240322174439-2a0eecb27288/go.mod h1:BmePxHey9hxrxk0kzTMHFFr7aJWXSxtlrUx6FIeV0Ic=
github.com/tsuru/tablecli v0.0.0-20190131152944-7ded8a3383c6 h1:1XDdWFAjIbCSG1OjN9v9KdWhuM8UtYlFcfHe/Ldkchk=
github.com/tsuru/tablecli v0.0.0-20190131152944-7ded8a3383c6/go.mod h1:ztYpOhW+u1k21FEqp7nZNgpWbr0dUKok5lgGCZi+1AQ=
github.com/tsuru/tsuru v0.0.0-20230721211340-f41fb455f8c3 h1:Fi5mEiJiHlTCaSYpfP19kbiOzJD26yqwVojUKdLsVHA=
Expand Down
65 changes: 35 additions & 30 deletions internal/provider/resource_tsuru_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,38 +113,16 @@ func resourceTsuruJob() *schema.Resource {
},
},

"spec": {
Type: schema.TypeList,
Description: "Check Kubernetes official Job specs docs for more details",
MaxItems: 1,
"active_deadline_seconds": {
Type: schema.TypeInt,
Description: "Time a Job can run before its terminated. Defaults is 3600",
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"completions": {
Type: schema.TypeInt,
Description: "Successful executions for the job to be consider done. Default=1",
Optional: true,
},

"parallelism": {
Type: schema.TypeInt,
Description: "Number of concurrent instances (Pods) of the job. Default=1",
Optional: true,
},

"active_deadline_seconds": {
Type: schema.TypeInt,
Description: "Time a Job can run before its terminated. Has precedence over backoff_limit. Defaults to no deadline",
Optional: true,
},
},

"backoff_limit": {
Type: schema.TypeInt,
Description: "Number of retries before considering a Job as failed. Default=6",
Optional: true,
},
},
},
"concurrency_policy": {
Type: schema.TypeString,
Description: "Concurrency policy",
Optional: true,
},
},
}
Expand Down Expand Up @@ -238,6 +216,10 @@ func resourceTsuruJobRead(ctx context.Context, d *schema.ResourceData, meta inte
d.Set("description", job.Job.Description)
}

for key, value := range flattenJobSpec(job.Job.Spec) {
d.Set(key, value)
}

d.Set("metadata", flattenMetadata(job.Job.Metadata))

return nil
Expand Down Expand Up @@ -327,6 +309,15 @@ func inputJobFromResourceData(ctx context.Context, d *schema.ResourceData, provi
if schedule, ok := d.GetOk("schedule"); ok {
job.Schedule = schedule.(string)
}
if concurrencyPolicyInterface, ok := d.GetOk("concurrency_policy"); ok {
concurrencyPolicy := concurrencyPolicyInterface.(string)
job.ConcurrencyPolicy = &concurrencyPolicy
}

if activeDeadLineSecondsInterface, ok := d.GetOk("active_deadline_seconds"); ok {
activeDeadLineSeconds := int64(activeDeadLineSecondsInterface.(int))
job.ActiveDeadlineSeconds = &activeDeadLineSeconds
}

return job, nil
}
Expand Down Expand Up @@ -363,3 +354,17 @@ func flattenJobContainer(container tsuru.InputJobContainer) []interface{} {

return []interface{}{m}
}

func flattenJobSpec(spec tsuru.JobSpec) map[string]any {
m := map[string]any{}

if spec.ConcurrencyPolicy != nil {
m["concurrency_policy"] = spec.ConcurrencyPolicy
}

if spec.ActiveDeadlineSeconds != nil {
m["active_deadline_seconds"] = *spec.ActiveDeadlineSeconds
}

return m
}
129 changes: 129 additions & 0 deletions internal/provider/resource_tsuru_job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
echo "github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tsuru/go-tsuruclient/pkg/tsuru"
)

Expand Down Expand Up @@ -113,6 +114,113 @@ func TestAccResourceTsuruJob(t *testing.T) {
})
}

func TestAccResourceTsuruJobComplete(t *testing.T) {
fakeServer := echo.New()

iterationCount := 0

fakeServer.GET("/1.0/pools", func(c echo.Context) error {
return c.JSON(http.StatusOK, []tsuru.Pool{{Name: "prod"}})
})

fakeServer.GET("/1.0/plans", func(c echo.Context) error {
return c.JSON(http.StatusOK, []tsuru.Plan{{Name: "c1m1"}})
})

fakeServer.POST("/1.13/jobs", func(c echo.Context) error {
job := tsuru.InputJob{}
c.Bind(&job)
assert.Equal(t, "job01", job.Name)
assert.Equal(t, "my job description", job.Description)
assert.Equal(t, "c1m1", job.Plan)
assert.Equal(t, "my-team", job.TeamOwner)
assert.Equal(t, "prod", job.Pool)
assert.Equal(t, []string{"sleep", "600"}, job.Container.Command)
assert.Equal(t, "tsuru/scratch:latest", job.Container.Image)
require.NotNil(t, job.ConcurrencyPolicy)
assert.Equal(t, "Forbid", *job.ConcurrencyPolicy)

require.NotNil(t, job.ActiveDeadlineSeconds)
assert.Equal(t, int64(300), *job.ActiveDeadlineSeconds)

iterationCount++
return c.JSON(http.StatusOK, map[string]interface{}{
"status": "success",
"jobName": job.Name,
})
})

fakeServer.GET("/1.13/jobs/:name", func(c echo.Context) error {
name := c.Param("name")
if name != "job01" {
return nil
}

concurrencyPolicy := "Forbid"
activeDeadLineSeconds := int64(300)

if iterationCount == 1 {
job := &tsuru.Job{
Name: name,
Description: "my job description",
TeamOwner: "my-team",
Plan: tsuru.Plan{Name: "c1m1"},
Pool: "prod",
Spec: tsuru.JobSpec{
Container: tsuru.InputJobContainer{
Image: "tsuru/scratch:latest",
Command: []string{
"sleep",
"600",
},
},
ConcurrencyPolicy: &concurrencyPolicy,
ActiveDeadlineSeconds: &activeDeadLineSeconds,
},
}
return c.JSON(http.StatusOK, tsuru.JobInfo{Job: *job})
}

return c.JSON(http.StatusNotFound, nil)
})

fakeServer.PUT("/1.13/jobs/:name", func(c echo.Context) error {
return c.JSON(http.StatusOK, nil)
})

fakeServer.DELETE("/1.13/jobs/:name", func(c echo.Context) error {
name := c.Param("name")
assert.Equal(t, "job01", name)
return c.NoContent(http.StatusNoContent)
})

fakeServer.HTTPErrorHandler = func(err error, c echo.Context) {
t.Errorf("methods=%s, path=%s, err=%s", c.Request().Method, c.Path(), err.Error())
}
server := httptest.NewServer(fakeServer)
os.Setenv("TSURU_TARGET", server.URL)

resourceName := "tsuru_job.job"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactories,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: testAccResourceTsuruJob_complete(),
Check: resource.ComposeAggregateTestCheckFunc(
testAccResourceExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "name", "job01"),
resource.TestCheckResourceAttr(resourceName, "description", "my job description"),
resource.TestCheckResourceAttr(resourceName, "plan", "c1m1"),
resource.TestCheckResourceAttr(resourceName, "team_owner", "my-team"),
resource.TestCheckResourceAttr(resourceName, "pool", "prod"),
),
},
},
})
}

func testAccResourceTsuruJob_basic() string {
return `
resource "tsuru_job" "job" {
Expand All @@ -129,3 +237,24 @@ func testAccResourceTsuruJob_basic() string {
}
`
}

func testAccResourceTsuruJob_complete() string {
return `
resource "tsuru_job" "job" {
name = "job01"
description = "my job description"
plan = "c1m1"
team_owner = "my-team"
pool = "prod"
schedule = "* * * * *"
container {
image = "tsuru/scratch:latest"
command = ["sleep", 600]
}
active_deadline_seconds = 300
concurrency_policy = "Forbid"
}
`
}

0 comments on commit 3b481b9

Please sign in to comment.