Skip to content

Commit bb195d8

Browse files
committed
Update network group policy definition and enhance definition generator to update existing definitions
1 parent 71730d4 commit bb195d8

File tree

12 files changed

+2102
-1911
lines changed

12 files changed

+2102
-1911
lines changed

docs/data-sources/network_group_policy.md

Lines changed: 65 additions & 65 deletions
Large diffs are not rendered by default.

docs/resources/network_group_policy.md

Lines changed: 136 additions & 119 deletions
Large diffs are not rendered by default.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
data "meraki_network_group_policy" "example" {
22
id = "12345678"
3-
network_id = ""
3+
network_id = "L_123456"
44
}
Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
resource "meraki_network_group_policy" "example" {
2+
network_id = "L_123456"
3+
name = "No video streaming"
24
splash_auth_settings = "bypass"
3-
vlan_tagging_settings = "custom"
4-
vlan_tagging_vlan_id = "1"
5+
bandwidth_settings = "custom"
6+
bandwidth_limit_down = 1000000
7+
bandwidth_limit_up = 1000000
58
bonjour_forwarding_settings = "custom"
69
bonjour_forwarding_rules = [
710
{
@@ -10,70 +13,67 @@ resource "meraki_network_group_policy" "example" {
1013
services = ["All Services"]
1114
}
1215
]
13-
name = "No video streaming"
14-
scheduling_monday_to = "17:00"
15-
scheduling_monday_active = true
16-
scheduling_monday_from = "09:00"
17-
scheduling_tuesday_active = true
18-
scheduling_tuesday_from = "09:00"
19-
scheduling_tuesday_to = "17:00"
20-
scheduling_wednesday_to = "17:00"
21-
scheduling_wednesday_active = true
22-
scheduling_wednesday_from = "09:00"
23-
scheduling_thursday_active = true
24-
scheduling_thursday_from = "09:00"
25-
scheduling_thursday_to = "17:00"
26-
scheduling_friday_active = true
27-
scheduling_friday_from = "09:00"
28-
scheduling_friday_to = "17:00"
29-
scheduling_saturday_to = "17:00"
30-
scheduling_saturday_active = true
31-
scheduling_saturday_from = "09:00"
32-
scheduling_sunday_from = "09:00"
33-
scheduling_sunday_to = "17:00"
34-
scheduling_sunday_active = true
35-
scheduling_enabled = true
36-
bandwidth_settings = "custom"
37-
bandwidth_bandwidth_limits_limit_up = 1000000
38-
bandwidth_bandwidth_limits_limit_down = 1000000
39-
firewall_and_traffic_shaping_l7_firewall_rules = [
16+
content_filtering_allowed_url_patterns_settings = "network default"
17+
content_filtering_allowed_url_patterns = [""]
18+
content_filtering_blocked_url_categories_settings = "override"
19+
content_filtering_blocked_url_categories = ["meraki:contentFiltering/category/1"]
20+
content_filtering_blocked_url_patterns_settings = "append"
21+
content_filtering_blocked_url_patterns = ["http://www.example.com"]
22+
firewall_and_traffic_shaping_settings = "custom"
23+
l3_firewall_rules = [
24+
{
25+
comment = "Allow TCP traffic to subnet with HTTP servers."
26+
dest_cidr = "192.168.1.0/24"
27+
dest_port = "443"
28+
policy = "allow"
29+
protocol = "tcp"
30+
}
31+
]
32+
l7_firewall_rules = [
4033
{
4134
policy = "deny"
4235
type = "host"
4336
value = "google.com"
4437
}
4538
]
46-
firewall_and_traffic_shaping_settings = "custom"
47-
firewall_and_traffic_shaping_traffic_shaping_rules = [
39+
traffic_shaping_rules = [
4840
{
41+
dscp_tag_value = 0
42+
pcp_tag_value = 0
43+
priority = "normal"
44+
per_client_bandwidth_limits_settings = "custom"
45+
per_client_bandwidth_limits_bandwidth_limits_limit_down = 1000000
46+
per_client_bandwidth_limits_bandwidth_limits_limit_up = 1000000
4947
definitions = [
5048
{
5149
type = "host"
5250
value = "google.com"
5351
}
5452
]
55-
per_client_bandwidth_limits_settings = "custom"
56-
per_client_bandwidth_limits_bandwidth_limits_limit_up = 1000000
57-
per_client_bandwidth_limits_bandwidth_limits_limit_down = 1000000
58-
dscp_tag_value = 0
59-
pcp_tag_value = 0
60-
priority = "normal"
61-
}
62-
]
63-
firewall_and_traffic_shaping_l3_firewall_rules = [
64-
{
65-
protocol = "tcp"
66-
dest_port = "443"
67-
dest_cidr = "192.168.1.0/24"
68-
comment = "Allow TCP traffic to subnet with HTTP servers."
69-
policy = "allow"
7053
}
7154
]
72-
content_filtering_allowed_url_patterns_settings = "network default"
73-
content_filtering_allowed_url_patterns_patterns = ["http://www.example.com"]
74-
content_filtering_blocked_url_patterns_settings = "append"
75-
content_filtering_blocked_url_patterns_patterns = ["http://www.example.com"]
76-
content_filtering_blocked_url_categories_settings = "override"
77-
content_filtering_blocked_url_categories_categories = ["meraki:contentFiltering/category/1"]
78-
network_id = ""
55+
scheduling_enabled = true
56+
scheduling_friday_active = true
57+
scheduling_friday_from = "09:00"
58+
scheduling_friday_to = "17:00"
59+
scheduling_monday_active = true
60+
scheduling_monday_from = "09:00"
61+
scheduling_monday_to = "17:00"
62+
scheduling_saturday_active = true
63+
scheduling_saturday_from = "09:00"
64+
scheduling_saturday_to = "17:00"
65+
scheduling_sunday_active = true
66+
scheduling_sunday_from = "09:00"
67+
scheduling_sunday_to = "17:00"
68+
scheduling_thursday_active = true
69+
scheduling_thursday_from = "09:00"
70+
scheduling_thursday_to = "17:00"
71+
scheduling_tuesday_active = true
72+
scheduling_tuesday_from = "09:00"
73+
scheduling_tuesday_to = "17:00"
74+
scheduling_wednesday_active = true
75+
scheduling_wednesday_from = "09:00"
76+
scheduling_wednesday_to = "17:00"
77+
vlan_tagging_settings = "custom"
78+
vlan_tagging_vlan_id = "1"
7979
}

gen/definition.go

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ package main
2222
import (
2323
"bytes"
2424
"encoding/json"
25-
"errors"
2625
"fmt"
2726
"os"
2827
"regexp"
28+
"slices"
2929
"sort"
3030
"strings"
3131

@@ -76,8 +76,19 @@ func main() {
7676
os.Exit(1)
7777
}
7878

79-
endpoint := spec.(map[string]interface{})["paths"].(map[string]interface{})[endpointPath].(map[string]interface{})
80-
schema := endpoint["put"].(map[string]interface{})["requestBody"].(map[string]interface{})["content"].(map[string]interface{})["application/json"].(map[string]interface{})
79+
parts := strings.Split(endpointPath, "/")
80+
if len(parts) > 0 {
81+
parts = parts[:len(parts)-1]
82+
}
83+
shortEndpointPath := strings.Join(parts, "/")
84+
var schema map[string]interface{}
85+
paths := spec.(map[string]interface{})["paths"].(map[string]interface{})
86+
// use POST schema if it exists, otherwise fall back to PUT schema
87+
if endpoint, ok := paths[shortEndpointPath].(map[string]interface{})["post"]; ok {
88+
schema = endpoint.(map[string]interface{})["requestBody"].(map[string]interface{})["content"].(map[string]interface{})["application/json"].(map[string]interface{})
89+
} else {
90+
schema = paths[endpointPath].(map[string]interface{})["put"].(map[string]interface{})["requestBody"].(map[string]interface{})["content"].(map[string]interface{})["application/json"].(map[string]interface{})
91+
}
8192
example := schema["schema"].(map[string]interface{})["example"].(map[string]interface{})
8293
exampleStr, err := json.Marshal(&example)
8394
if err != nil {
@@ -95,14 +106,6 @@ func main() {
95106
config.IdName = urlResult.idName[1 : len(urlResult.idName)-1]
96107
}
97108
config.DocCategory = urlResult.category
98-
dataSourceNameQuery := false
99-
for _, a := range config.Attributes {
100-
if a.ModelName == "name" {
101-
dataSourceNameQuery = true
102-
break
103-
}
104-
}
105-
config.DataSourceNameQuery = dataSourceNameQuery
106109
config.Name = resourceName
107110
if urlResult.oneToOne {
108111
config.PutCreate = true
@@ -123,21 +126,52 @@ func main() {
123126
attr.Example = "<<Example>>"
124127
attributes = append(attributes, attr)
125128
}
126-
attributes = append(attributes, traverseProperties(schema["schema"].(map[string]interface{})["properties"].(map[string]interface{}), []string{}, "", string(exampleStr))...)
129+
required := []string{}
130+
if r, ok := schema["schema"].(map[string]interface{})["required"]; ok {
131+
required = toStringSlice(r.([]interface{}))
132+
}
133+
attributes = append(attributes, traverseProperties(schema["schema"].(map[string]interface{})["properties"].(map[string]interface{}), []string{}, "", string(exampleStr), required)...)
127134
config.Attributes = attributes
128135

136+
dataSourceNameQuery := false
137+
for _, a := range config.Attributes {
138+
if a.ModelName == "name" {
139+
dataSourceNameQuery = true
140+
break
141+
}
142+
}
143+
config.DataSourceNameQuery = dataSourceNameQuery
144+
145+
outputPath := definitionsPath + yamlconfig.SnakeCase(resourceName) + ".yaml"
146+
147+
existingConfig := yamlconfig.YamlConfig{}
148+
if yamlFile, err := os.ReadFile(outputPath); err == nil {
149+
existingConfig = yamlconfig.YamlConfig{}
150+
err = yaml.Unmarshal(yamlFile, &existingConfig)
151+
if err != nil {
152+
panic(err)
153+
}
154+
}
155+
156+
newConfig := yamlconfig.MergeYamlConfig(config, existingConfig)
157+
129158
var yamlBytes bytes.Buffer
130159
yamlEncoder := yaml.NewEncoder(&yamlBytes)
131160
yamlEncoder.SetIndent(2)
132-
err = yamlEncoder.Encode(&config)
161+
err = yamlEncoder.Encode(&newConfig)
133162
if err != nil {
134163
panic(err)
135164
}
136-
outputPath := definitionsPath + yamlconfig.SnakeCase(resourceName) + ".yaml"
137-
// Only write the file if it doesn't exist
138-
if _, err := os.Stat(outputPath); errors.Is(err, os.ErrNotExist) {
139-
os.WriteFile(outputPath, []byte("---\n"+string(yamlBytes.Bytes())), 0644)
165+
166+
os.WriteFile(outputPath, yamlBytes.Bytes(), 0644)
167+
}
168+
169+
func toStringSlice(i []interface{}) []string {
170+
ret := []string{}
171+
for _, v := range i {
172+
ret = append(ret, v.(string))
140173
}
174+
return ret
141175
}
142176

143177
var jsonTypes = map[string]string{
@@ -176,7 +210,7 @@ func parseUrl(url string) parseUrlResult {
176210
return ret
177211
}
178212

179-
func traverseProperties(m map[string]interface{}, path []string, gjsonPath string, exampleStr string) []yamlconfig.YamlConfigAttribute {
213+
func traverseProperties(m map[string]interface{}, path []string, gjsonPath string, exampleStr string, requiredProperties []string) []yamlconfig.YamlConfigAttribute {
180214
ret := []yamlconfig.YamlConfigAttribute{}
181215

182216
keys := maps.Keys(m)
@@ -215,6 +249,9 @@ func traverseProperties(m map[string]interface{}, path []string, gjsonPath strin
215249
attr.MaxFloat = max.(float64)
216250
}
217251
}
252+
if slices.Contains(requiredProperties, propName) {
253+
attr.Mandatory = true
254+
}
218255
ret = append(ret, attr)
219256
}
220257
}
@@ -223,7 +260,11 @@ func traverseProperties(m map[string]interface{}, path []string, gjsonPath strin
223260
if propMap["type"] == "object" {
224261
childPath := append(path, propName)
225262
childGjsonPath := gjsonPath + "." + propName
226-
children := traverseProperties(propMap["properties"].(map[string]interface{}), childPath, childGjsonPath, exampleStr)
263+
childRequired := []string{}
264+
if rp, ok := propMap["required"]; ok {
265+
childRequired = toStringSlice(rp.([]interface{}))
266+
}
267+
children := traverseProperties(propMap["properties"].(map[string]interface{}), childPath, childGjsonPath, exampleStr, childRequired)
227268
ret = append(ret, children...)
228269
}
229270
}
@@ -245,7 +286,11 @@ func traverseProperties(m map[string]interface{}, path []string, gjsonPath strin
245286
attr.Example = res.String()
246287
} else if items["type"].(string) == "object" {
247288
childGjsonPath := gjsonPath + "." + propName + ".0"
248-
children := traverseProperties(items["properties"].(map[string]interface{}), []string{}, childGjsonPath, exampleStr)
289+
childRequired := []string{}
290+
if rp, ok := items["required"]; ok {
291+
childRequired = toStringSlice(rp.([]interface{}))
292+
}
293+
children := traverseProperties(items["properties"].(map[string]interface{}), []string{}, childGjsonPath, exampleStr, childRequired)
249294
attr.Attributes = children
250295
}
251296
ret = append(ret, attr)

0 commit comments

Comments
 (0)