@@ -99,39 +99,49 @@ func (parser Parser) WriteYaml(filePath string) {
9999 log .Printf ("Generated product %+v/product.yaml" , productPath )
100100 for name , resource := range resources {
101101 if resource .create == nil {
102- continue
103- }
104- resource := buildResource (filePath , name , resource , doc )
102+ if resource .update == nil {
103+ continue
104+ }
105+ singleton := buildSingleton (name , resource , doc )
105106
106- // marshal method
107- var yamlContent bytes.Buffer
108- resourceOutPathMarshal := filepath .Join (productPath , fmt .Sprintf ("%s.yaml" , resource .Name ))
109- encoder := yaml .NewEncoder (& yamlContent )
110- encoder .SetIndent (2 )
107+ parser .writeResource (singleton , productPath )
108+ } else {
109+ resource := buildResource (name , resource , doc )
111110
112- err := encoder .Encode (& resource )
113- if err != nil {
114- log .Fatalf ("Failed to encode: %v" , err )
111+ parser .writeResource (resource , productPath )
115112 }
113+ }
114+ }
116115
117- f , err := os .Create (resourceOutPathMarshal )
118- if err != nil {
119- log .Fatalf ("error creating resource file %v" , err )
120- }
121- _ , err = f .Write (header )
122- if err != nil {
123- log .Fatalf ("error writing resource file header %v" , err )
124- }
125- _ , err = f .Write (yamlContent .Bytes ())
126- if err != nil {
127- log .Fatalf ("error writing resource file %v" , err )
128- }
129- err = f .Close ()
130- if err != nil {
131- log .Fatalf ("error closing resource file %v" , err )
132- }
133- log .Printf ("Generated resource %s" , resourceOutPathMarshal )
116+ func (parser Parser ) writeResource (resource api.Resource , productPath string ) {
117+ // marshal method
118+ var yamlContent bytes.Buffer
119+ resourceOutPathMarshal := filepath .Join (productPath , fmt .Sprintf ("%s.yaml" , resource .Name ))
120+ encoder := yaml .NewEncoder (& yamlContent )
121+ encoder .SetIndent (2 )
122+
123+ err := encoder .Encode (& resource )
124+ if err != nil {
125+ log .Fatalf ("Failed to encode: %v" , err )
126+ }
127+
128+ f , err := os .Create (resourceOutPathMarshal )
129+ if err != nil {
130+ log .Fatalf ("error creating resource file %v" , err )
131+ }
132+ _ , err = f .Write (header )
133+ if err != nil {
134+ log .Fatalf ("error writing resource file header %v" , err )
135+ }
136+ _ , err = f .Write (yamlContent .Bytes ())
137+ if err != nil {
138+ log .Fatalf ("error writing resource file %v" , err )
139+ }
140+ err = f .Close ()
141+ if err != nil {
142+ log .Fatalf ("error closing resource file %v" , err )
134143 }
144+ log .Printf ("Generated resource %s" , resourceOutPathMarshal )
135145}
136146
137147type resourceOp struct {
@@ -278,11 +288,54 @@ func stripVersion(path string) string {
278288 return re .ReplaceAllString (path , "" )
279289}
280290
281- func buildResource (filePath , resourceName string , in * resource , root * openapi3.T ) api.Resource {
291+ func buildSingleton (resourceName string , in * resource , root * openapi3.T ) api.Resource {
292+ resource := api.Resource {}
293+ resourcePath := in .update .path
294+
295+ op := root .Paths .Find (resourcePath ).Patch
296+ parsedObjects := parseOpenApi (resourcePath , resourceName , op )
297+
298+ parameters := parsedObjects [0 ].([]* api.Type )
299+ properties := parsedObjects [1 ].([]* api.Type )
300+
301+ baseUrl := baseUrl (resourcePath )
302+ selfLink := baseUrl
303+
304+ resource .Name = resourceName
305+ resource .BaseUrl = baseUrl
306+ resource .Parameters = parameters
307+ resource .Properties = properties
308+ resource .SelfLink = selfLink
309+ resource .CreateUrl = fmt .Sprintf ("%s=?updateMask=*" , baseUrl )
310+
311+ resource .CreateVerb = "PATCH"
312+
313+ resource .UpdateVerb = "PATCH"
314+ resource .UpdateMask = true
315+ if in .update .async {
316+ resource .AutogenAsync = true
317+ async := api .NewAsync ()
318+ async .Operation .BaseUrl = "{{op_id}}"
319+ async .Result .ResourceInsideResponse = true
320+ // Clear the default, we will attach the right values below
321+ async .Actions = nil
322+ resource .Async = async
323+ resource .Async .Actions = append (resource .Async .Actions , "update" )
324+ }
325+
326+ resource .ExcludeDelete = true
327+
328+ resource = attachStandardFunctionality (resource )
329+
330+ return resource
331+ }
332+
333+ func buildResource (resourceName string , in * resource , root * openapi3.T ) api.Resource {
282334 resource := api.Resource {}
283335 resourcePath := in .create .path
284336
285- parsedObjects := parseOpenApi (resourcePath , resourceName , root )
337+ op := root .Paths .Find (resourcePath ).Post
338+ parsedObjects := parseOpenApi (resourcePath , resourceName , op )
286339
287340 parameters := parsedObjects [0 ].([]* api.Type )
288341 properties := parsedObjects [1 ].([]* api.Type )
@@ -296,10 +349,7 @@ func buildResource(filePath, resourceName string, in *resource, root *openapi3.T
296349 resource .Parameters = parameters
297350 resource .Properties = properties
298351 resource .SelfLink = selfLink
299- resource .IdFormat = selfLink
300- resource .ImportFormat = []string {selfLink }
301352 resource .CreateUrl = fmt .Sprintf ("%s?%s={{%s}}" , baseUrl , queryParam , google .Underscore (queryParam ))
302- resource .Description = "Description"
303353
304354 resource .AutogenAsync = true
305355 async := api .NewAsync ()
@@ -325,28 +375,42 @@ func buildResource(filePath, resourceName string, in *resource, root *openapi3.T
325375 resource .Async .Actions = append (resource .Async .Actions , "delete" )
326376 }
327377
378+ resource = attachStandardFunctionality (resource )
379+
380+ return resource
381+ }
382+
383+ // Standard functionality between regular and singleton resources
384+ func attachStandardFunctionality (resource api.Resource ) api.Resource {
385+ resource .Description = "Description"
386+
387+ resource .IdFormat = resource .SelfLink
388+ resource .ImportFormat = []string {resource .SelfLink }
389+
328390 example := r.Examples {}
329391 example .Name = "name_of_example_file"
330392 example .PrimaryResourceId = "example"
331393 example .Vars = map [string ]string {"resource_name" : "test-resource" }
332394
333395 resource .Examples = []* r.Examples {& example }
334396
335- resourceNameBytes := []byte (resourceName )
397+ resourceNameBytes := []byte (resource . Name )
336398 // Write the status as an encoded string to flag when a YAML file has been
337399 // copy and pasted without actually using this tool
338400 resource .AutogenStatus = base64 .StdEncoding .EncodeToString (resourceNameBytes )
339401
340402 return resource
341403}
342404
343- func parseOpenApi (resourcePath , resourceName string , root * openapi3.T ) []any {
405+ func parseOpenApi (resourcePath , resourceName string , op * openapi3.Operation ) []any {
406+ if op == nil {
407+ log .Fatalf ("error parsing nil OpenAPI operation for resource: %v" , resourceName )
408+ }
344409 returnArray := []any {}
345- path := root .Paths .Find (resourcePath )
346410
347411 parameters := []* api.Type {}
348412 var idParam string
349- for _ , param := range path . Post .Parameters {
413+ for _ , param := range op .Parameters {
350414 if strings .Contains (strings .ToLower (param .Value .Name ), strings .ToLower (resourceName )) {
351415 idParam = param .Value .Name
352416 }
@@ -357,7 +421,7 @@ func parseOpenApi(resourcePath, resourceName string, root *openapi3.T) []any {
357421 }
358422 paramObj .Description = trimDescription (description )
359423
360- if param .Value .Name == "requestId" || param .Value .Name == "validateOnly" || paramObj .Name == "" {
424+ if param .Value .Name == "requestId" || param .Value .Name == "validateOnly" || paramObj .Name == "" || paramObj . Name == "updateMask" {
361425 continue
362426 }
363427
@@ -366,7 +430,7 @@ func parseOpenApi(resourcePath, resourceName string, root *openapi3.T) []any {
366430 parameters = append (parameters , & paramObj )
367431 }
368432
369- properties := buildProperties (path . Post . RequestBody .Value .Content ["application/json" ].Schema .Value .Properties , path . Post .RequestBody .Value .Content ["application/json" ].Schema .Value .Required )
433+ properties := buildProperties (op . RequestBody .Value .Content ["application/json" ].Schema .Value .Properties , op .RequestBody .Value .Content ["application/json" ].Schema .Value .Required )
370434
371435 returnArray = append (returnArray , parameters )
372436 returnArray = append (returnArray , properties )
0 commit comments