Skip to content

Commit e6eff84

Browse files
Add support for timezone in sync window (#314)
Co-authored-by: OneMatchFox <[email protected]>
1 parent aaf4a18 commit e6eff84

File tree

11 files changed

+73
-8
lines changed

11 files changed

+73
-8
lines changed

argocd/resource_argocd_account_token_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,7 @@ func TestAccArgoCDAccountToken_RenewBefore(t *testing.T) {
138138

139139
func TestAccArgoCDAccountToken_RenewAfter(t *testing.T) {
140140
resourceName := "argocd_account_token.renew_after"
141-
142-
renewAfterSeconds := 2
141+
renewAfterSeconds := 30
143142

144143
resource.Test(t, resource.TestCase{
145144
PreCheck: func() { testAccPreCheck(t) },

argocd/resource_argocd_cluster_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func TestAccArgoCDCluster(t *testing.T) {
5252
ResourceName: "argocd_cluster.simple",
5353
ImportState: true,
5454
ImportStateVerify: true,
55-
ImportStateVerifyIgnore: []string{"config.0.bearer_token"},
55+
ImportStateVerifyIgnore: []string{"config.0.bearer_token", "info"},
5656
},
5757
{
5858
Config: testAccArgoCDClusterTLSCertificate(t, acctest.RandString(10)),
@@ -107,7 +107,7 @@ func TestAccArgoCDCluster_projectScope(t *testing.T) {
107107
ResourceName: "argocd_cluster.project_scope",
108108
ImportState: true,
109109
ImportStateVerify: true,
110-
ImportStateVerifyIgnore: []string{"config.0.bearer_token"},
110+
ImportStateVerifyIgnore: []string{"config.0.bearer_token", "info"},
111111
},
112112
},
113113
})

argocd/resource_argocd_project_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ func TestAccArgoCDProject(t *testing.T) {
4747
),
4848
ExpectError: regexp.MustCompile("cannot parse schedule"),
4949
},
50+
{
51+
Config: testAccArgoCDProjectSyncWindowTimezoneError(
52+
"test-acc-" + acctest.RandString(10),
53+
),
54+
ExpectError: regexp.MustCompile("cannot parse timezone"),
55+
},
5056
{
5157
Config: testAccArgoCDProjectSimple(name),
5258
Check: resource.TestCheckResourceAttrSet(
@@ -332,6 +338,7 @@ resource "argocd_project" "simple" {
332338
duration = "12h"
333339
schedule = "22 1 5 * *"
334340
manual_sync = false
341+
timezone = "Europe/London"
335342
}
336343
signature_keys = [
337344
"4AEE18F83AFDEB23",
@@ -791,3 +798,39 @@ resource "argocd_project" "simple" {
791798
}
792799
`, name)
793800
}
801+
802+
func testAccArgoCDProjectSyncWindowTimezoneError(name string) string {
803+
return fmt.Sprintf(`
804+
resource "argocd_project" "failure" {
805+
metadata {
806+
name = "%s"
807+
namespace = "argocd"
808+
}
809+
810+
spec {
811+
description = "expected timezone failure"
812+
destination {
813+
server = "https://kubernetes.default.svc"
814+
namespace = "*"
815+
}
816+
source_repos = ["*"]
817+
role {
818+
name = "incorrect-syncwindow"
819+
policies = [
820+
"p, proj:%s:testrole, applications, override, %s/foo, allow",
821+
]
822+
}
823+
sync_window {
824+
kind = "allow"
825+
applications = ["api-*"]
826+
clusters = ["*"]
827+
namespaces = ["*"]
828+
duration = "1h"
829+
schedule = "10 1 * * *"
830+
manual_sync = true
831+
timezone = "invalid"
832+
}
833+
}
834+
}
835+
`, name, name, name)
836+
}

argocd/resource_argocd_project_token_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,7 @@ func TestAccArgoCDProjectToken_RenewBefore(t *testing.T) {
109109

110110
func TestAccArgoCDProjectToken_RenewAfter(t *testing.T) {
111111
resourceName := "argocd_project_token.renew_after"
112-
113-
renewAfterSeconds := 2
112+
renewAfterSeconds := 30
114113

115114
// Note: not running in parallel as this is a time sensitive test case
116115
resource.Test(t, resource.TestCase{

argocd/schema_project.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,13 @@ func projectSpecSchemaV2() *schema.Schema {
665665
ValidateFunc: validateSyncWindowSchedule,
666666
Optional: true,
667667
},
668+
"timezone": {
669+
Type: schema.TypeString,
670+
Description: "Timezone that the schedule will be evaluated in.",
671+
ValidateFunc: validateSyncWindowTimezone,
672+
Optional: true,
673+
Default: "UTC",
674+
},
668675
},
669676
},
670677
},

argocd/structure_application.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ func expandSyncWindows(sws []interface{}) (result []*application.SyncWindow) {
516516
ManualSync: sw["manual_sync"].(bool),
517517
Namespaces: expandStringList(sw["namespaces"].([]interface{})),
518518
Schedule: sw["schedule"].(string),
519+
TimeZone: sw["timezone"].(string),
519520
})
520521
}
521522

argocd/structures.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ func flattenSyncWindows(sws application.SyncWindows) (result []map[string]interf
9797
"manual_sync": sw.ManualSync,
9898
"namespaces": sw.Namespaces,
9999
"schedule": sw.Schedule,
100+
"timezone": sw.TimeZone,
100101
})
101102
}
102103

argocd/validators.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import (
44
"fmt"
55
"regexp"
66
"strings"
7+
"time"
8+
_ "time/tzdata"
79

8-
"github.com/argoproj/pkg/time"
10+
argocdtime "github.com/argoproj/pkg/time"
911
"github.com/robfig/cron"
1012
"golang.org/x/crypto/ssh"
1113
apiValidation "k8s.io/apimachinery/pkg/api/validation"
@@ -105,13 +107,22 @@ func validateSyncWindowSchedule(value interface{}, key string) (ws []string, es
105107
func validateSyncWindowDuration(value interface{}, key string) (ws []string, es []error) {
106108
v := value.(string)
107109

108-
if _, err := time.ParseDuration(v); err != nil {
110+
if _, err := argocdtime.ParseDuration(v); err != nil {
109111
es = append(es, fmt.Errorf("%s: cannot parse duration '%s': %s", key, v, err))
110112
}
111113

112114
return
113115
}
114116

117+
func validateSyncWindowTimezone(value interface{}, key string) (ws []string, es []error) {
118+
v := value.(string)
119+
if _, err := time.LoadLocation(v); err != nil {
120+
es = append(es, fmt.Errorf("%s: cannot parse timezone '%s': %s", key, v, err))
121+
}
122+
123+
return
124+
}
125+
115126
func validateDuration(value interface{}, key string) (ws []string, es []error) {
116127
v := value.(string)
117128

docs/resources/project.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ resource "argocd_project" "myproject" {
120120
duration = "12h"
121121
schedule = "22 1 5 * *"
122122
manual_sync = false
123+
timezone = "Europe/London"
123124
}
124125
125126
signature_keys = [
@@ -274,6 +275,7 @@ Optional:
274275
- `manual_sync` (Boolean) Enables manual syncs when they would otherwise be blocked.
275276
- `namespaces` (List of String) List of namespaces that the window will apply to.
276277
- `schedule` (String) Time the window will begin, specified in cron format.
278+
- `timezone` (String) Timezone that the schedule will be evaluated in.
277279

278280
## Import
279281

examples/resources/argocd_project/resource.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ resource "argocd_project" "myproject" {
105105
duration = "12h"
106106
schedule = "22 1 5 * *"
107107
manual_sync = false
108+
timezone = "Europe/London"
108109
}
109110

110111
signature_keys = [

0 commit comments

Comments
 (0)