@@ -99,6 +99,7 @@ func resourceCloudSchedulerJob() *schema.Resource {
9999 return & schema.Resource {
100100 Create : resourceCloudSchedulerJobCreate ,
101101 Read : resourceCloudSchedulerJobRead ,
102+ Update : resourceCloudSchedulerJobUpdate ,
102103 Delete : resourceCloudSchedulerJobDelete ,
103104
104105 Importer : & schema.ResourceImporter {
@@ -107,6 +108,7 @@ func resourceCloudSchedulerJob() *schema.Resource {
107108
108109 Timeouts : & schema.ResourceTimeout {
109110 Create : schema .DefaultTimeout (4 * time .Minute ),
111+ Update : schema .DefaultTimeout (4 * time .Minute ),
110112 Delete : schema .DefaultTimeout (4 * time .Minute ),
111113 },
112114
@@ -122,7 +124,6 @@ func resourceCloudSchedulerJob() *schema.Resource {
122124 "app_engine_http_target" : {
123125 Type : schema .TypeList ,
124126 Optional : true ,
125- ForceNew : true ,
126127 Description : `App Engine HTTP target.
127128If the job providers a App Engine HTTP target the cron will
128129send a request to the service instance` ,
@@ -132,7 +133,6 @@ send a request to the service instance`,
132133 "relative_uri" : {
133134 Type : schema .TypeString ,
134135 Required : true ,
135- ForceNew : true ,
136136 Description : `The relative URI.
137137The relative URL must begin with "/" and must be a valid HTTP relative URL.
138138It can contain a path, query string arguments, and \# fragments.
@@ -142,31 +142,27 @@ No spaces are allowed, and the maximum length allowed is 2083 characters`,
142142 "app_engine_routing" : {
143143 Type : schema .TypeList ,
144144 Optional : true ,
145- ForceNew : true ,
146145 Description : `App Engine Routing setting for the job.` ,
147146 MaxItems : 1 ,
148147 Elem : & schema.Resource {
149148 Schema : map [string ]* schema.Schema {
150149 "instance" : {
151150 Type : schema .TypeString ,
152151 Optional : true ,
153- ForceNew : true ,
154152 Description : `App instance.
155153By default, the job is sent to an instance which is available when the job is attempted.` ,
156154 AtLeastOneOf : []string {"app_engine_http_target.0.app_engine_routing.0.service" , "app_engine_http_target.0.app_engine_routing.0.version" , "app_engine_http_target.0.app_engine_routing.0.instance" },
157155 },
158156 "service" : {
159157 Type : schema .TypeString ,
160158 Optional : true ,
161- ForceNew : true ,
162159 Description : `App service.
163160By default, the job is sent to the service which is the default service when the job is attempted.` ,
164161 AtLeastOneOf : []string {"app_engine_http_target.0.app_engine_routing.0.service" , "app_engine_http_target.0.app_engine_routing.0.version" , "app_engine_http_target.0.app_engine_routing.0.instance" },
165162 },
166163 "version" : {
167164 Type : schema .TypeString ,
168165 Optional : true ,
169- ForceNew : true ,
170166 Description : `App version.
171167By default, the job is sent to the version which is the default version when the job is attempted.` ,
172168 AtLeastOneOf : []string {"app_engine_http_target.0.app_engine_routing.0.service" , "app_engine_http_target.0.app_engine_routing.0.version" , "app_engine_http_target.0.app_engine_routing.0.instance" },
@@ -177,7 +173,6 @@ By default, the job is sent to the version which is the default version when the
177173 "body" : {
178174 Type : schema .TypeString ,
179175 Optional : true ,
180- ForceNew : true ,
181176 Description : `HTTP request body.
182177A request body is allowed only if the HTTP method is POST or PUT.
183178It will result in invalid argument error to set a body on a job with an incompatible HttpMethod.
@@ -187,7 +182,6 @@ A base64-encoded string.`,
187182 "headers" : {
188183 Type : schema .TypeMap ,
189184 Optional : true ,
190- ForceNew : true ,
191185 ValidateFunc : validateHttpHeaders (),
192186 Description : `HTTP request headers.
193187This map contains the header field names and values.
@@ -197,7 +191,6 @@ Headers can be set when the job is created.`,
197191 "http_method" : {
198192 Type : schema .TypeString ,
199193 Optional : true ,
200- ForceNew : true ,
201194 Description : `Which HTTP method to use for the request.` ,
202195 },
203196 },
@@ -207,7 +200,6 @@ Headers can be set when the job is created.`,
207200 "attempt_deadline" : {
208201 Type : schema .TypeString ,
209202 Optional : true ,
210- ForceNew : true ,
211203 DiffSuppressFunc : emptyOrDefaultStringSuppress ("180s" ),
212204 Description : `The deadline for job attempts. If the request handler does not respond by this deadline then the request is
213205cancelled and the attempt is marked as a DEADLINE_EXCEEDED failure. The failed attempt can be viewed in
@@ -222,14 +214,12 @@ A duration in seconds with up to nine fractional digits, terminated by 's'. Exam
222214 "description" : {
223215 Type : schema .TypeString ,
224216 Optional : true ,
225- ForceNew : true ,
226217 Description : `A human-readable description for the job.
227218This string must not contain more than 500 characters.` ,
228219 },
229220 "http_target" : {
230221 Type : schema .TypeList ,
231222 Optional : true ,
232- ForceNew : true ,
233223 Description : `HTTP target.
234224If the job providers a http_target the cron will
235225send a request to the targeted url` ,
@@ -239,13 +229,11 @@ send a request to the targeted url`,
239229 "uri" : {
240230 Type : schema .TypeString ,
241231 Required : true ,
242- ForceNew : true ,
243232 Description : `The full URI path that the request will be sent to.` ,
244233 },
245234 "body" : {
246235 Type : schema .TypeString ,
247236 Optional : true ,
248- ForceNew : true ,
249237 Description : `HTTP request body.
250238A request body is allowed only if the HTTP method is POST, PUT, or PATCH.
251239It is an error to set body on a job with an incompatible HttpMethod.
@@ -255,7 +243,6 @@ A base64-encoded string.`,
255243 "headers" : {
256244 Type : schema .TypeMap ,
257245 Optional : true ,
258- ForceNew : true ,
259246 ValidateFunc : validateHttpHeaders (),
260247 Description : `This map contains the header field names and values.
261248Repeated headers are not supported, but a header value can contain commas.` ,
@@ -264,13 +251,11 @@ Repeated headers are not supported, but a header value can contain commas.`,
264251 "http_method" : {
265252 Type : schema .TypeString ,
266253 Optional : true ,
267- ForceNew : true ,
268254 Description : `Which HTTP method to use for the request.` ,
269255 },
270256 "oauth_token" : {
271257 Type : schema .TypeList ,
272258 Optional : true ,
273- ForceNew : true ,
274259 DiffSuppressFunc : authHeaderDiffSuppress ,
275260 Description : `Contains information needed for generating an OAuth token.
276261This type of authorization should be used when sending requests to a GCP endpoint.` ,
@@ -280,14 +265,12 @@ This type of authorization should be used when sending requests to a GCP endpoin
280265 "service_account_email" : {
281266 Type : schema .TypeString ,
282267 Required : true ,
283- ForceNew : true ,
284268 Description : `Service account email to be used for generating OAuth token.
285269The service account must be within the same project as the job.` ,
286270 },
287271 "scope" : {
288272 Type : schema .TypeString ,
289273 Optional : true ,
290- ForceNew : true ,
291274 Description : `OAuth scope to be used for generating OAuth access token. If not specified,
292275"https://www.googleapis.com/auth/cloud-platform" will be used.` ,
293276 },
@@ -297,7 +280,6 @@ The service account must be within the same project as the job.`,
297280 "oidc_token" : {
298281 Type : schema .TypeList ,
299282 Optional : true ,
300- ForceNew : true ,
301283 DiffSuppressFunc : authHeaderDiffSuppress ,
302284 Description : `Contains information needed for generating an OpenID Connect token.
303285This type of authorization should be used when sending requests to third party endpoints or Cloud Run.` ,
@@ -307,14 +289,12 @@ This type of authorization should be used when sending requests to third party e
307289 "service_account_email" : {
308290 Type : schema .TypeString ,
309291 Required : true ,
310- ForceNew : true ,
311292 Description : `Service account email to be used for generating OAuth token.
312293The service account must be within the same project as the job.` ,
313294 },
314295 "audience" : {
315296 Type : schema .TypeString ,
316297 Optional : true ,
317- ForceNew : true ,
318298 Description : `Audience to be used when generating OIDC token. If not specified,
319299the URI specified in target will be used.` ,
320300 },
@@ -328,7 +308,6 @@ the URI specified in target will be used.`,
328308 "pubsub_target" : {
329309 Type : schema .TypeList ,
330310 Optional : true ,
331- ForceNew : true ,
332311 Description : `Pub/Sub target
333312If the job providers a Pub/Sub target the cron will publish
334313a message to the provided topic` ,
@@ -338,7 +317,6 @@ a message to the provided topic`,
338317 "topic_name" : {
339318 Type : schema .TypeString ,
340319 Required : true ,
341- ForceNew : true ,
342320 Description : `The full resource name for the Cloud Pub/Sub topic to which
343321messages will be published when a job is delivered. ~>**NOTE:**
344322The topic name must be in the same format as required by PubSub's
@@ -347,15 +325,13 @@ PublishRequest.name, e.g. 'projects/my-project/topics/my-topic'.`,
347325 "attributes" : {
348326 Type : schema .TypeMap ,
349327 Optional : true ,
350- ForceNew : true ,
351328 Description : `Attributes for PubsubMessage.
352329Pubsub message must contain either non-empty data, or at least one attribute.` ,
353330 Elem : & schema.Schema {Type : schema .TypeString },
354331 },
355332 "data" : {
356333 Type : schema .TypeString ,
357334 Optional : true ,
358- ForceNew : true ,
359335 Description : `The message payload for PubsubMessage.
360336Pubsub message must contain either non-empty data, or at least one attribute.` ,
361337 },
@@ -373,7 +349,6 @@ Pubsub message must contain either non-empty data, or at least one attribute.`,
373349 "retry_config" : {
374350 Type : schema .TypeList ,
375351 Optional : true ,
376- ForceNew : true ,
377352 Description : `By default, if a job does not complete successfully,
378353meaning that an acknowledgement is not received from the handler,
379354then it will be retried with exponential backoff according to the settings` ,
@@ -384,7 +359,6 @@ then it will be retried with exponential backoff according to the settings`,
384359 Type : schema .TypeString ,
385360 Computed : true ,
386361 Optional : true ,
387- ForceNew : true ,
388362 Description : `The maximum amount of time to wait before retrying a job after it fails.
389363A duration in seconds with up to nine fractional digits, terminated by 's'.` ,
390364 AtLeastOneOf : []string {"retry_config.0.retry_count" , "retry_config.0.max_retry_duration" , "retry_config.0.min_backoff_duration" , "retry_config.0.max_backoff_duration" , "retry_config.0.max_doublings" },
@@ -393,7 +367,6 @@ A duration in seconds with up to nine fractional digits, terminated by 's'.`,
393367 Type : schema .TypeInt ,
394368 Computed : true ,
395369 Optional : true ,
396- ForceNew : true ,
397370 Description : `The time between retries will double maxDoublings times.
398371A job's retry interval starts at minBackoffDuration,
399372then doubles maxDoublings times, then increases linearly,
@@ -404,7 +377,6 @@ and finally retries retries at intervals of maxBackoffDuration up to retryCount
404377 Type : schema .TypeString ,
405378 Computed : true ,
406379 Optional : true ,
407- ForceNew : true ,
408380 Description : `The time limit for retrying a failed job, measured from time when an execution was first attempted.
409381If specified with retryCount, the job will be retried until both limits are reached.
410382A duration in seconds with up to nine fractional digits, terminated by 's'.` ,
@@ -414,7 +386,6 @@ A duration in seconds with up to nine fractional digits, terminated by 's'.`,
414386 Type : schema .TypeString ,
415387 Computed : true ,
416388 Optional : true ,
417- ForceNew : true ,
418389 Description : `The minimum amount of time to wait before retrying a job after it fails.
419390A duration in seconds with up to nine fractional digits, terminated by 's'.` ,
420391 AtLeastOneOf : []string {"retry_config.0.retry_count" , "retry_config.0.max_retry_duration" , "retry_config.0.min_backoff_duration" , "retry_config.0.max_backoff_duration" , "retry_config.0.max_doublings" },
@@ -423,7 +394,6 @@ A duration in seconds with up to nine fractional digits, terminated by 's'.`,
423394 Type : schema .TypeInt ,
424395 Computed : true ,
425396 Optional : true ,
426- ForceNew : true ,
427397 Description : `The number of attempts that the system will make to run a
428398job using the exponential backoff procedure described by maxDoublings.
429399Values greater than 5 and negative values are not allowed.` ,
@@ -435,13 +405,11 @@ Values greater than 5 and negative values are not allowed.`,
435405 "schedule" : {
436406 Type : schema .TypeString ,
437407 Optional : true ,
438- ForceNew : true ,
439408 Description : `Describes the schedule on which the job will be executed.` ,
440409 },
441410 "time_zone" : {
442411 Type : schema .TypeString ,
443412 Optional : true ,
444- ForceNew : true ,
445413 Description : `Specifies the time zone to be used in interpreting schedule.
446414The value of this field must be a time zone name from the tz database.` ,
447415 Default : "Etc/UTC" ,
@@ -629,6 +597,94 @@ func resourceCloudSchedulerJobRead(d *schema.ResourceData, meta interface{}) err
629597 return nil
630598}
631599
600+ func resourceCloudSchedulerJobUpdate (d * schema.ResourceData , meta interface {}) error {
601+ config := meta .(* Config )
602+ userAgent , err := generateUserAgentString (d , config .userAgent )
603+ if err != nil {
604+ return err
605+ }
606+
607+ billingProject := ""
608+
609+ project , err := getProject (d , config )
610+ if err != nil {
611+ return fmt .Errorf ("Error fetching project for Job: %s" , err )
612+ }
613+ billingProject = project
614+
615+ obj := make (map [string ]interface {})
616+ descriptionProp , err := expandCloudSchedulerJobDescription (d .Get ("description" ), d , config )
617+ if err != nil {
618+ return err
619+ } else if v , ok := d .GetOkExists ("description" ); ! isEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , descriptionProp )) {
620+ obj ["description" ] = descriptionProp
621+ }
622+ scheduleProp , err := expandCloudSchedulerJobSchedule (d .Get ("schedule" ), d , config )
623+ if err != nil {
624+ return err
625+ } else if v , ok := d .GetOkExists ("schedule" ); ! isEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , scheduleProp )) {
626+ obj ["schedule" ] = scheduleProp
627+ }
628+ timeZoneProp , err := expandCloudSchedulerJobTimeZone (d .Get ("time_zone" ), d , config )
629+ if err != nil {
630+ return err
631+ } else if v , ok := d .GetOkExists ("time_zone" ); ! isEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , timeZoneProp )) {
632+ obj ["timeZone" ] = timeZoneProp
633+ }
634+ attemptDeadlineProp , err := expandCloudSchedulerJobAttemptDeadline (d .Get ("attempt_deadline" ), d , config )
635+ if err != nil {
636+ return err
637+ } else if v , ok := d .GetOkExists ("attempt_deadline" ); ! isEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , attemptDeadlineProp )) {
638+ obj ["attemptDeadline" ] = attemptDeadlineProp
639+ }
640+ retryConfigProp , err := expandCloudSchedulerJobRetryConfig (d .Get ("retry_config" ), d , config )
641+ if err != nil {
642+ return err
643+ } else if v , ok := d .GetOkExists ("retry_config" ); ! isEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , retryConfigProp )) {
644+ obj ["retryConfig" ] = retryConfigProp
645+ }
646+ pubsubTargetProp , err := expandCloudSchedulerJobPubsubTarget (d .Get ("pubsub_target" ), d , config )
647+ if err != nil {
648+ return err
649+ } else if v , ok := d .GetOkExists ("pubsub_target" ); ! isEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , pubsubTargetProp )) {
650+ obj ["pubsubTarget" ] = pubsubTargetProp
651+ }
652+ appEngineHttpTargetProp , err := expandCloudSchedulerJobAppEngineHttpTarget (d .Get ("app_engine_http_target" ), d , config )
653+ if err != nil {
654+ return err
655+ } else if v , ok := d .GetOkExists ("app_engine_http_target" ); ! isEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , appEngineHttpTargetProp )) {
656+ obj ["appEngineHttpTarget" ] = appEngineHttpTargetProp
657+ }
658+ httpTargetProp , err := expandCloudSchedulerJobHttpTarget (d .Get ("http_target" ), d , config )
659+ if err != nil {
660+ return err
661+ } else if v , ok := d .GetOkExists ("http_target" ); ! isEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , httpTargetProp )) {
662+ obj ["httpTarget" ] = httpTargetProp
663+ }
664+
665+ url , err := replaceVars (d , config , "{{CloudSchedulerBasePath}}projects/{{project}}/locations/{{region}}/jobs/{{name}}" )
666+ if err != nil {
667+ return err
668+ }
669+
670+ log .Printf ("[DEBUG] Updating Job %q: %#v" , d .Id (), obj )
671+
672+ // err == nil indicates that the billing_project value was found
673+ if bp , err := getBillingProject (d , config ); err == nil {
674+ billingProject = bp
675+ }
676+
677+ res , err := sendRequestWithTimeout (config , "PATCH" , billingProject , url , userAgent , obj , d .Timeout (schema .TimeoutUpdate ))
678+
679+ if err != nil {
680+ return fmt .Errorf ("Error updating Job %q: %s" , d .Id (), err )
681+ } else {
682+ log .Printf ("[DEBUG] Finished updating Job %q: %#v" , d .Id (), res )
683+ }
684+
685+ return resourceCloudSchedulerJobRead (d , meta )
686+ }
687+
632688func resourceCloudSchedulerJobDelete (d * schema.ResourceData , meta interface {}) error {
633689 config := meta .(* Config )
634690 userAgent , err := generateUserAgentString (d , config .userAgent )
0 commit comments