Skip to content

Commit f0c7d62

Browse files
committed
Update struct types and functions in terraform provider
Multiple struct types are renamed and added to translate structs in the `terraform_provider` package. The changes affect the `struct.go`, `terraform_provider_file.go` and `template.go` files. Also added instructions in `README.md` file for using the provider locally. Changes also include debugging information in `terraform_provider_file.go` and function renaming/updates in several places in the code.
1 parent a967aaa commit f0c7d62

File tree

4 files changed

+196
-23
lines changed

4 files changed

+196
-23
lines changed

assets/provider/README.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
### How to use it locally
2+
3+
Firstly you need to create `.terraformrc` file in your home directory:
4+
5+
```shell
6+
touch ~/.terraformrc
7+
```
8+
9+
The content of the file should look like that:
10+
11+
```
12+
provider_installation {
13+
14+
dev_overrides {
15+
"github.com/PaloAltoNetworks/panos" = "/home/USERNAME/go/bin"
16+
}
17+
18+
# For all other providers, install them directly from their origin provider
19+
# registries as normal. If you omit this, Terraform will _only_ use
20+
# the dev_overrides block, and so no other providers will be available.
21+
direct {}
22+
}
23+
```
24+
25+
Now when you generate the terraform-provider go to `terraform-provider-panos` folder and follow steps:
26+
27+
Install dependencies:
28+
```shell
29+
go mod tidy
30+
```
31+
32+
Install provider:
33+
34+
```shell
35+
go install .
36+
```
37+
38+
Now you can use Terraform with locally built provider.
39+
40+
Example Terraform file:
41+
42+
`provider.tf`
43+
```terraform
44+
# Traditional provider example.
45+
provider "panos" {
46+
hostname = ""
47+
username = ""
48+
password = ""
49+
skip_verify_certificate = true
50+
}
51+
52+
# Local inspection mode provider example.
53+
# provider "panos" {
54+
# #config_file = file("/tmp/candidate-config.xml")
55+
#
56+
# # This is only used if a "detail-version" attribute is not present in
57+
# # the exported XML schema. If it's there, this can be omitted.
58+
# panos_version = "10.2.0"
59+
# }
60+
61+
terraform {
62+
required_providers {
63+
panos = {
64+
source = "github.com/PaloAltoNetworks/panos"
65+
version = "2.0.0"
66+
}
67+
}
68+
}
69+
```
70+
71+
`main.tf`
72+
73+
```terraform
74+
resource "panos_address_group" "test1" {
75+
location = {
76+
device_group = {
77+
name = "test123"
78+
}
79+
}
80+
81+
name = "test123123"
82+
}
83+
84+
resource "panos_address_object" "test1" {
85+
location = {
86+
device_group = {
87+
name = "test123"
88+
}
89+
}
90+
91+
name = "test123123"
92+
fqdn = "10.0.0.0"
93+
ip_netmask = "8"
94+
}
95+
```
96+
97+
### Known issue:
98+
In early stages of Terraform Provider development helps a lot manually removing the resources and the statefile, after that some errors not occurred again.

pkg/translate/terraform_provider/struct.go

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,43 @@ type deviceGroupLocation struct {
3131
PanoramaDevice string
3232
}
3333

34-
type resourceLocation struct {
34+
type resourceObjectLocation struct {
3535
FromPanorama bool
3636
Shared bool
3737
Vsys vsysLocation
3838
DeviceGroup deviceGroupLocation
3939
}
4040

41+
type ngfwLocation struct {
42+
NgfwDevice string
43+
}
44+
45+
type templateLocation struct {
46+
NgfwDevice string
47+
PanoramaDevice string
48+
Template string
49+
}
50+
51+
type templateStackLocation struct {
52+
NgfwDevice string
53+
PanoramaDevice string
54+
TemplateStack string
55+
}
56+
57+
type resourceNGFWConfigLocation struct {
58+
Ngfw ngfwLocation
59+
Template templateLocation
60+
TemplateStack templateStackLocation
61+
}
62+
63+
type panoramaLocation struct {
64+
PanoramaDevice string
65+
}
66+
67+
type resourcePanoramaConfigLocation struct {
68+
Panorama panoramaLocation
69+
}
70+
4171
// ParamToModelBasic converts the given parameter name and properties to a model representation.
4272
func ParamToModelBasic(paramName string, paramProp interface{}) (string, error) {
4373
data := map[string]interface{}{
@@ -54,8 +84,8 @@ func ParamToModelBasic(paramName string, paramProp interface{}) (string, error)
5484
{{- /* Done */ -}}`, "param-to-model", data, nil)
5585
}
5686

57-
// ParamToSchema converts the given parameter name and properties to a schema representation.
58-
func ParamToSchema(paramName string, paramProp interface{}) (string, error) {
87+
// ParamToSchemaProvider converts the given parameter name and properties to a schema representation.
88+
func ParamToSchemaProvider(paramName string, paramProp interface{}) (string, error) {
5989
return processTemplate(`
6090
{{- /* Begin */ -}}
6191
"`+paramName+`": schema.{{ CamelCaseType .Type }}Attribute{
@@ -77,11 +107,13 @@ func ParamToSchema(paramName string, paramProp interface{}) (string, error) {
77107
}
78108

79109
func ParamToSchemaResource(paramName string, paramProp interface{}, terraformProvider *properties.TerraformProviderFile) (string, error) {
80-
if paramProp.(properties.SpecParam).Type == "bool" && paramProp.(properties.SpecParam).Default != "" {
81-
terraformProvider.ImportManager.AddHashicorpImport("github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault", "")
82-
}
110+
switch v := paramProp.(type) {
111+
case *properties.SpecParam:
112+
if v.Type == "bool" && v.Default != "" {
113+
terraformProvider.ImportManager.AddHashicorpImport("github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault", "")
114+
}
83115

84-
return processTemplate(`
116+
return processTemplate(`
85117
{{- /* Begin */ -}}
86118
{{- if .Type }}
87119
"`+strings.ReplaceAll(paramName, "-", "_")+`": rsschema.{{ CamelCaseType .Type }}Attribute{
@@ -102,11 +134,24 @@ func ParamToSchemaResource(paramName string, paramProp interface{}, terraformPro
102134
Computed: true ,
103135
{{- end }}
104136
},
105-
{{- /* Done */ -}}`, "describe-param", paramProp, nil)
106-
}
137+
{{- /* Done */ -}}`, "describe-param", v, nil)
138+
139+
case *properties.Location:
140+
return processTemplate(`
141+
{{- /* Begin */ -}}
142+
{{- if .Vars }}
143+
"`+strings.ReplaceAll(paramName, "-", "_")+`": rsschema.SingleNestedAttribute{
144+
{{- else }}
145+
"`+strings.ReplaceAll(paramName, "-", "_")+`": rsschema.StringAttribute{
146+
{{- end }}
147+
Description: "{{ .Description }}",
148+
Required: true,
149+
},
150+
{{- /* Done */ -}}`, "describe-location", v, nil)
107151

108-
func checkForObjectValidation(paramProp interface{}) bool {
109-
return true
152+
default:
153+
return "", fmt.Errorf("unsupported type: %T", paramProp)
154+
}
110155
}
111156

112157
func CreateResourceSchemaLocationAttribute() (string, error) {
@@ -218,6 +263,7 @@ func CreateNestedStruct(paramName string, paramProp *properties.SpecParam, struc
218263
return nestedStructString.String(), nil
219264
}
220265

266+
// CreateLocationStruct generates a corresponding Terraform location struct if the provided value is a struct, otherwise, it returns an error.
221267
func CreateLocationStruct(v interface{}, structName string) (string, error) {
222268
val := reflect.ValueOf(v)
223269
t := val.Type()

pkg/translate/terraform_provider/template.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ type {{ structName }} struct {
130130
}
131131
132132
type {{ structName }}Tfid struct {
133-
//TODO: Generate tfid struct via function
134133
{{ CreateTfIdStruct }}
135134
}
136135
@@ -158,7 +157,6 @@ type {{ structName }}DeviceGroupLocation struct {
158157
}
159158
160159
type {{ structName }}Model struct {
161-
// TODO: Entry model struct via function
162160
{{ CreateTfIdResourceModel }}
163161
Name types.String` + "`" + `tfsdk:"name"` + "`" + `
164162
{{- range $pName, $pParam := $.Spec.Params}}
@@ -190,11 +188,20 @@ func (r *{{ structName }}) Schema(ctx context.Context, req resource.SchemaReques
190188
Description: "The name of the resource.",
191189
Required: true,
192190
},
193-
{{- range $pName, $pParam := $.Spec.Params }}
194-
{{ ResourceParamToSchema $pName $pParam }}
191+
"location": rsschema.SingleNestedAttribute{
192+
Description: "The location of this object.",
193+
Required: true,
194+
Attributes: map[string]rsschema.Attribute{
195+
{{- range $pName, $pParam := $.Locations -}}
196+
{{ ResourceParamToSchema $pName $pParam }}
197+
{{- end }}
198+
}
199+
},
200+
{{- range $pName, $pParam := $.Spec.Params -}}
201+
{{ ResourceParamToSchema $pName $pParam }}
195202
{{- end }}
196-
{{- range $pName, $pParam := $.Spec.OneOf }}
197-
{{ ResourceParamToSchema $pName $pParam }}
203+
{{- range $pName, $pParam := $.Spec.OneOf -}}
204+
{{ ResourceParamToSchema $pName $pParam }}
198205
{{- end }}
199206
},
200207
}
@@ -644,7 +651,7 @@ func (p *PanosProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp
644651
Description: "Terraform provider to interact with Palo Alto Networks PAN-OS.",
645652
Attributes: map[string]schema.Attribute{
646653
{{- range $pName, $pParam := ProviderParams }}
647-
{{ ParamToSchema $pName $pParam }}
654+
{{ ParamToSchemaProvider $pName $pParam }}
648655
{{- end }}
649656
},
650657
}

pkg/translate/terraform_provider/terraform_provider_file.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,14 @@ func (g *GenerateTerraformProvider) GenerateTerraformResource(spec *properties.N
114114
},
115115
"ParamToModelResource": ParamToModelResource,
116116
"ModelNestedStruct": ModelNestedStruct,
117-
"ResourceParamToSchema": func(paramName string, paramParameters properties.SpecParam) (string, error) {
117+
"ResourceParamToSchema": func(paramName string, paramParameters interface{}) (string, error) {
118118
return ParamToSchemaResource(paramName, paramParameters, terraformProvider)
119119
},
120120
"ResourceSchemaLocationAttribute": CreateResourceSchemaLocationAttribute,
121-
"CreateLocationStruct": func(structName string) (string, error) { return CreateLocationStruct(resourceLocation{}, structName) },
122-
"CreateLocationVsysStruct": func(structName string) (string, error) { return CreateLocationStruct(vsysLocation{}, structName) },
121+
"CreateLocationStruct": func(structName string) (string, error) {
122+
return CreateLocationStruct(resourceObjectLocation{}, structName)
123+
},
124+
"CreateLocationVsysStruct": func(structName string) (string, error) { return CreateLocationStruct(vsysLocation{}, structName) },
123125
"CreateLocationDeviceGroupStruct": func(structName string) (string, error) {
124126
return CreateLocationStruct(deviceGroupLocation{}, structName)
125127
},
@@ -165,6 +167,26 @@ func (g *GenerateTerraformProvider) GenerateTerraformResource(spec *properties.N
165167
}
166168
}
167169
}
170+
171+
// START DEBUG
172+
173+
log.Printf("Whole properties: %s \n", spec)
174+
log.Printf("Whole Location: %s \n", spec.Locations)
175+
log.Printf("Location formatted: %v \n", spec.Locations)
176+
177+
for i := range spec.Locations {
178+
log.Printf("Location: %v \n", i)
179+
log.Printf("Location spec: %v \n", spec.Locations[i])
180+
}
181+
for n := range spec.Spec.Params {
182+
log.Printf("Spec param: %v \n", n)
183+
log.Printf("Spec param spec: %v \n", spec.Spec.Params[n])
184+
}
185+
for k := range spec.Spec.OneOf {
186+
log.Printf("Spec oneof: %v \n", k)
187+
log.Printf("Spec oneof spec: %v \n", spec.Spec.OneOf[k])
188+
}
189+
// END OF DEBUG
168190
return nil
169191
}
170192

@@ -235,8 +257,8 @@ func (g *GenerateTerraformProvider) GenerateTerraformProvider(terraformProvider
235257
"ParamToModelBasic": func(paramName string, paramProp properties.TerraformProviderParams) (string, error) {
236258
return ParamToModelBasic(paramName, paramProp)
237259
},
238-
"ParamToSchema": func(paramName string, paramProp properties.TerraformProviderParams) (string, error) {
239-
return ParamToSchema(paramName, paramProp)
260+
"ParamToSchemaProvider": func(paramName string, paramProp properties.TerraformProviderParams) (string, error) {
261+
return ParamToSchemaProvider(paramName, paramProp)
240262
},
241263
}
242264
return g.generateTerraformEntityTemplate("ProviderFile", &NameProvider{}, spec, terraformProvider, providerTemplateStr, funcMap)

0 commit comments

Comments
 (0)