diff --git a/argocd/resource_argocd_account_token_test.go b/argocd/resource_argocd_account_token_test.go index b94f5a75..51b7b6e9 100644 --- a/argocd/resource_argocd_account_token_test.go +++ b/argocd/resource_argocd_account_token_test.go @@ -138,8 +138,7 @@ func TestAccArgoCDAccountToken_RenewBefore(t *testing.T) { func TestAccArgoCDAccountToken_RenewAfter(t *testing.T) { resourceName := "argocd_account_token.renew_after" - - renewAfterSeconds := 2 + renewAfterSeconds := 30 resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, diff --git a/argocd/resource_argocd_cluster_test.go b/argocd/resource_argocd_cluster_test.go index 72b00571..8c82fa4f 100644 --- a/argocd/resource_argocd_cluster_test.go +++ b/argocd/resource_argocd_cluster_test.go @@ -52,7 +52,7 @@ func TestAccArgoCDCluster(t *testing.T) { ResourceName: "argocd_cluster.simple", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"config.0.bearer_token"}, + ImportStateVerifyIgnore: []string{"config.0.bearer_token", "info"}, }, { Config: testAccArgoCDClusterTLSCertificate(t, acctest.RandString(10)), @@ -107,7 +107,7 @@ func TestAccArgoCDCluster_projectScope(t *testing.T) { ResourceName: "argocd_cluster.project_scope", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"config.0.bearer_token"}, + ImportStateVerifyIgnore: []string{"config.0.bearer_token", "info"}, }, }, }) diff --git a/argocd/resource_argocd_project_test.go b/argocd/resource_argocd_project_test.go index 331f30c1..bcd1aa9c 100644 --- a/argocd/resource_argocd_project_test.go +++ b/argocd/resource_argocd_project_test.go @@ -47,6 +47,12 @@ func TestAccArgoCDProject(t *testing.T) { ), ExpectError: regexp.MustCompile("cannot parse schedule"), }, + { + Config: testAccArgoCDProjectSyncWindowTimezoneError( + "test-acc-" + acctest.RandString(10), + ), + ExpectError: regexp.MustCompile("cannot parse timezone"), + }, { Config: testAccArgoCDProjectSimple(name), Check: resource.TestCheckResourceAttrSet( @@ -332,6 +338,7 @@ resource "argocd_project" "simple" { duration = "12h" schedule = "22 1 5 * *" manual_sync = false + timezone = "Europe/London" } signature_keys = [ "4AEE18F83AFDEB23", @@ -791,3 +798,39 @@ resource "argocd_project" "simple" { } `, name) } + +func testAccArgoCDProjectSyncWindowTimezoneError(name string) string { + return fmt.Sprintf(` +resource "argocd_project" "failure" { + metadata { + name = "%s" + namespace = "argocd" + } + + spec { + description = "expected timezone failure" + destination { + server = "https://kubernetes.default.svc" + namespace = "*" + } + source_repos = ["*"] + role { + name = "incorrect-syncwindow" + policies = [ + "p, proj:%s:testrole, applications, override, %s/foo, allow", + ] + } + sync_window { + kind = "allow" + applications = ["api-*"] + clusters = ["*"] + namespaces = ["*"] + duration = "1h" + schedule = "10 1 * * *" + manual_sync = true + timezone = "invalid" + } + } +} + `, name, name, name) +} diff --git a/argocd/resource_argocd_project_token_test.go b/argocd/resource_argocd_project_token_test.go index fafac352..9b9dc755 100644 --- a/argocd/resource_argocd_project_token_test.go +++ b/argocd/resource_argocd_project_token_test.go @@ -109,8 +109,7 @@ func TestAccArgoCDProjectToken_RenewBefore(t *testing.T) { func TestAccArgoCDProjectToken_RenewAfter(t *testing.T) { resourceName := "argocd_project_token.renew_after" - - renewAfterSeconds := 2 + renewAfterSeconds := 30 // Note: not running in parallel as this is a time sensitive test case resource.Test(t, resource.TestCase{ diff --git a/argocd/schema_project.go b/argocd/schema_project.go index 8ea22621..037a2114 100644 --- a/argocd/schema_project.go +++ b/argocd/schema_project.go @@ -665,6 +665,13 @@ func projectSpecSchemaV2() *schema.Schema { ValidateFunc: validateSyncWindowSchedule, Optional: true, }, + "timezone": { + Type: schema.TypeString, + Description: "Timezone that the schedule will be evaluated in.", + ValidateFunc: validateSyncWindowTimezone, + Optional: true, + Default: "UTC", + }, }, }, }, diff --git a/argocd/structure_application.go b/argocd/structure_application.go index 89fe68b8..0da48b85 100644 --- a/argocd/structure_application.go +++ b/argocd/structure_application.go @@ -516,6 +516,7 @@ func expandSyncWindows(sws []interface{}) (result []*application.SyncWindow) { ManualSync: sw["manual_sync"].(bool), Namespaces: expandStringList(sw["namespaces"].([]interface{})), Schedule: sw["schedule"].(string), + TimeZone: sw["timezone"].(string), }) } diff --git a/argocd/structures.go b/argocd/structures.go index 9a08a6bb..36ad943d 100644 --- a/argocd/structures.go +++ b/argocd/structures.go @@ -97,6 +97,7 @@ func flattenSyncWindows(sws application.SyncWindows) (result []map[string]interf "manual_sync": sw.ManualSync, "namespaces": sw.Namespaces, "schedule": sw.Schedule, + "timezone": sw.TimeZone, }) } diff --git a/argocd/validators.go b/argocd/validators.go index 489e900a..ff725cf2 100644 --- a/argocd/validators.go +++ b/argocd/validators.go @@ -4,8 +4,10 @@ import ( "fmt" "regexp" "strings" + "time" + _ "time/tzdata" - "github.com/argoproj/pkg/time" + argocdtime "github.com/argoproj/pkg/time" "github.com/robfig/cron" "golang.org/x/crypto/ssh" apiValidation "k8s.io/apimachinery/pkg/api/validation" @@ -105,13 +107,22 @@ func validateSyncWindowSchedule(value interface{}, key string) (ws []string, es func validateSyncWindowDuration(value interface{}, key string) (ws []string, es []error) { v := value.(string) - if _, err := time.ParseDuration(v); err != nil { + if _, err := argocdtime.ParseDuration(v); err != nil { es = append(es, fmt.Errorf("%s: cannot parse duration '%s': %s", key, v, err)) } return } +func validateSyncWindowTimezone(value interface{}, key string) (ws []string, es []error) { + v := value.(string) + if _, err := time.LoadLocation(v); err != nil { + es = append(es, fmt.Errorf("%s: cannot parse timezone '%s': %s", key, v, err)) + } + + return +} + func validateDuration(value interface{}, key string) (ws []string, es []error) { v := value.(string) diff --git a/docs/resources/project.md b/docs/resources/project.md index ea23d125..3ea8e8ae 100644 --- a/docs/resources/project.md +++ b/docs/resources/project.md @@ -120,6 +120,7 @@ resource "argocd_project" "myproject" { duration = "12h" schedule = "22 1 5 * *" manual_sync = false + timezone = "Europe/London" } signature_keys = [ @@ -274,6 +275,7 @@ Optional: - `manual_sync` (Boolean) Enables manual syncs when they would otherwise be blocked. - `namespaces` (List of String) List of namespaces that the window will apply to. - `schedule` (String) Time the window will begin, specified in cron format. +- `timezone` (String) Timezone that the schedule will be evaluated in. ## Import diff --git a/examples/resources/argocd_project/resource.tf b/examples/resources/argocd_project/resource.tf index 60ace0ea..180e25f7 100644 --- a/examples/resources/argocd_project/resource.tf +++ b/examples/resources/argocd_project/resource.tf @@ -105,6 +105,7 @@ resource "argocd_project" "myproject" { duration = "12h" schedule = "22 1 5 * *" manual_sync = false + timezone = "Europe/London" } signature_keys = [ diff --git a/manifests/local-dev/project.tf b/manifests/local-dev/project.tf index 800892ec..15ed9590 100644 --- a/manifests/local-dev/project.tf +++ b/manifests/local-dev/project.tf @@ -79,6 +79,7 @@ resource "argocd_project" "foo" { duration = "12h" schedule = "22 1 5 * *" manual_sync = false + timezone = "Europe/London" } } }