diff --git a/go.mod b/go.mod index 4e301715..fc4c4514 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,24 @@ module github.com/paloaltonetworks/pan-os-codegen require ( + github.com/onsi/ginkgo/v2 v2.20.0 + github.com/onsi/gomega v1.34.1 github.com/stretchr/testify v1.9.0 - golang.org/x/text v0.16.0 + golang.org/x/text v0.17.0 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/tools v0.24.0 // indirect ) go 1.22.5 diff --git a/go.sum b/go.sum index 5474e7a4..34f9c99b 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,33 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/onsi/ginkgo/v2 v2.20.0 h1:PE84V2mHqoT1sglvHc8ZdQtPcwmvvt29WLEEO3xmdZw= +github.com/onsi/ginkgo/v2 v2.20.0/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= +github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= +github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/pkg/errors/errors.go b/pkg/errors/errors.go new file mode 100644 index 00000000..5351c797 --- /dev/null +++ b/pkg/errors/errors.go @@ -0,0 +1,46 @@ +package errors + +import "fmt" + +type SchemaError struct { + Message string + Err error +} + +func NewSchemaError(msg string) *SchemaError { + return &SchemaError{Message: msg} +} + +func (o *SchemaError) Error() string { + return o.Message +} + +func (o *SchemaError) Unwrap() error { + return o.Err +} + +type MarshallerError struct { + Err error + Message string +} + +func NewMarshallerError(msg string) *MarshallerError { + return &MarshallerError{Message: msg} +} + +func NewWrappedMarshallerError(err error) *MarshallerError { + return &MarshallerError{ + Err: err, + } +} + +func (o *MarshallerError) Error() string { + if o.Err != nil { + return fmt.Sprintf("error while marshalling specs: %s", o.Err) + } + return o.Message +} + +func (o *MarshallerError) Unwrap() error { + return o.Err +} diff --git a/pkg/properties/normalized.go b/pkg/properties/normalized.go index 1d21b824..237973dc 100644 --- a/pkg/properties/normalized.go +++ b/pkg/properties/normalized.go @@ -9,6 +9,10 @@ import ( "github.com/paloaltonetworks/pan-os-codegen/pkg/content" "github.com/paloaltonetworks/pan-os-codegen/pkg/naming" + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/object" + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/parameter" + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/validator" + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/xpath" ) type Normalization struct { @@ -238,11 +242,369 @@ func GetNormalizations() ([]string, error) { return files, nil } +func schemaParameterToSpecParameter(schemaSpec *parameter.Parameter) (*SpecParam, error) { + var specType string + if schemaSpec.Type == "object" { + specType = "" + } else if schemaSpec.Type == "enum" { + specType = "string" + } else { + specType = schemaSpec.Type + } + + var defaultVal string + + var innerSpec *Spec + var itemsSpec SpecParamItems + + generateInnerSpec := func(spec *parameter.StructSpec) (*Spec, error) { + params := make(map[string]*SpecParam) + oneofs := make(map[string]*SpecParam) + + for _, elt := range spec.Parameters { + param, err := schemaParameterToSpecParameter(elt) + if err != nil { + return nil, err + } + params[elt.Name] = param + } + + for _, elt := range spec.Variants { + param, err := schemaParameterToSpecParameter(elt) + if err != nil { + return nil, err + } + oneofs[elt.Name] = param + } + + return &Spec{ + Params: params, + OneOf: oneofs, + }, nil + } + + switch spec := schemaSpec.Spec.(type) { + case *parameter.StructSpec: + var err error + innerSpec, err = generateInnerSpec(spec) + if err != nil { + return nil, err + } + + case *parameter.ListSpec: + if spec.Items.Type == "object" { + itemsSpec.Type = "entry" + var err error + innerSpec, err = generateInnerSpec(&spec.Items.Spec) + if err != nil { + return nil, err + } + } else { + itemsSpec.Type = spec.Items.Type + } + for _, v := range schemaSpec.Validators { + switch spec := v.Spec.(type) { + case *validator.CountSpec: + min := int64(spec.Min) + max := int64(spec.Max) + itemsSpec.Length = &SpecParamItemsLength{ + Min: &min, + Max: &max, + } + } + } + case *parameter.EnumSpec: + defaultVal = spec.Default + case *parameter.NilSpec: + specType = "string" + case *parameter.SimpleSpec: + if typed, ok := spec.Default.(string); ok { + defaultVal = typed + } + } + + var profiles []*SpecParamProfile + for _, profile := range schemaSpec.Profiles { + var notPresent bool + var version string + if profile.MaximumVersion != nil { + notPresent = true + version = profile.MaximumVersion.String() + } else if profile.MinimumVersion != nil { + version = profile.MinimumVersion.String() + } + profiles = append(profiles, &SpecParamProfile{ + Xpath: profile.Xpath, + Type: profile.Type, + NotPresent: notPresent, + FromVersion: version, + }) + } + + specParameter := &SpecParam{ + Description: schemaSpec.Description, + Type: specType, + Default: defaultVal, + Required: schemaSpec.Required, + Profiles: profiles, + Spec: innerSpec, + } + + for _, v := range schemaSpec.Validators { + switch spec := v.Spec.(type) { + case *validator.RegexpSpec: + specParameter.Regex = spec.Expr + case *validator.StringLengthSpec: + min := int64(spec.Min) + max := int64(spec.Max) + specParameter.Length = &SpecParamLength{ + Min: &min, + Max: &max, + } + case *validator.CountSpec: + min := int64(spec.Min) + max := int64(spec.Max) + specParameter.Count = &SpecParamCount{ + Min: &min, + Max: &max, + } + } + } + + if schemaSpec.Type == "list" { + specParameter.Items = &itemsSpec + } + + return specParameter, nil +} + +func generateXpathVariables(variables []xpathschema.Variable) map[string]*LocationVar { + xpathVars := make(map[string]*LocationVar) + for _, variable := range variables { + entry := &LocationVar{ + Description: variable.Description, + Default: variable.Default, + Required: variable.Required, + Validation: nil, + } + + for _, v := range variable.Validators { + switch spec := v.Spec.(type) { + case *validator.NotValuesSpec: + notValues := make(map[string]string) + for _, value := range spec.Values { + notValues[value.Value] = value.Error + + } + entry.Validation = &LocationVarValidation{ + NotValues: notValues, + } + + } + } + + xpathVars[variable.Name] = entry + } + + return xpathVars +} + +func generateImportVariables(variables []xpathschema.Variable) map[string]*ImportVar { + importVars := make(map[string]*ImportVar) + for _, variable := range variables { + entry := &ImportVar{ + Description: variable.Description, + Default: variable.Default, + } + importVars[variable.Name] = entry + } + + return importVars +} + +func schemaToSpec(object object.Object) (*Normalization, error) { + spec := &Normalization{ + Name: object.DisplayName, + TerraformProviderConfig: TerraformProviderConfig{ + SkipResource: object.TerraformConfig.SkipResource, + SkipDatasource: object.TerraformConfig.SkipDatasource, + SkipDatasourceListing: object.TerraformConfig.SkipdatasourceListing, + Suffix: object.TerraformConfig.Suffix, + }, + Locations: make(map[string]*Location), + Imports: make(map[string]*Import), + GoSdkPath: object.GoSdkConfig.Package, + XpathSuffix: object.XpathSuffix, + Version: object.Version, + Spec: &Spec{ + Params: make(map[string]*SpecParam), + OneOf: make(map[string]*SpecParam), + }, + } + + for _, location := range object.Locations { + var xpath []string + + schemaXpathVars := make(map[string]xpathschema.Variable) + for _, elt := range location.Xpath.Variables { + schemaXpathVars[elt.Name] = elt + } + for _, elt := range location.Xpath.Elements { + var eltEntry string + if xpathVar, ok := schemaXpathVars[elt[1:]]; ok { + if xpathVar.Type == "entry" { + eltEntry = fmt.Sprintf("{{ Entry %s }}", elt) + } else if xpathVar.Type == "object" { + eltEntry = fmt.Sprintf("{{ Object %s }}", elt) + } + } else { + if strings.HasPrefix(elt, "$") { + panic(fmt.Sprintf("elt: %s", elt)) + } + eltEntry = elt + } + xpath = append(xpath, eltEntry) + } + + locationDevice := &LocationDevice{} + + for _, device := range location.Devices { + if device == "panorama" { + locationDevice.Panorama = true + } else if device == "ngfw" { + locationDevice.Ngfw = true + } + } + + xpathVars := generateXpathVariables(location.Xpath.Variables) + if len(xpathVars) == 0 { + xpathVars = nil + } + + entry := &Location{ + Description: location.Description, + Device: locationDevice, + Xpath: xpath, + Vars: xpathVars, + } + spec.Locations[location.Name] = entry + } + + for _, entry := range object.Entries { + if entry.Name == "name" { + specEntry := &Entry{ + Name: &EntryName{ + Description: entry.Description, + }, + } + + for _, v := range entry.Validators { + switch spec := v.Spec.(type) { + case *validator.StringLengthSpec: + min := int64(spec.Min) + max := int64(spec.Max) + specEntry.Name.Length = &EntryNameLength{ + Min: &min, + Max: &max, + } + } + } + spec.Entry = specEntry + } + + } + + imports := make(map[string]*Import, len(object.Imports)) + for _, elt := range object.Imports { + var xpath []string + + schemaXpathVars := make(map[string]xpathschema.Variable) + for _, xpathVariable := range elt.Xpath.Variables { + schemaXpathVars[xpathVariable.Name] = xpathVariable + } + + for _, element := range elt.Xpath.Elements { + var eltEntry string + if xpathVar, ok := schemaXpathVars[element[1:]]; ok { + if xpathVar.Type == "entry" { + eltEntry = fmt.Sprintf("{{ Entry %s }}", elt.Name) + } else if xpathVar.Type == "object" { + eltEntry = fmt.Sprintf("{{ Object %s }}", elt.Name) + } + } else { + eltEntry = element + } + xpath = append(xpath, eltEntry) + } + + importVariables := generateImportVariables(elt.Xpath.Variables) + if len(importVariables) == 0 { + importVariables = nil + } + + imports[elt.Name] = &Import{ + Xpath: xpath, + Vars: importVariables, + OnlyForParams: elt.OnlyForParams, + } + } + + if len(imports) > 0 { + spec.Imports = imports + } + + consts := make(map[string]*Const) + for _, param := range object.Spec.Parameters { + specParam, err := schemaParameterToSpecParameter(param) + if err != nil { + return nil, err + } + + switch spec := param.Spec.(type) { + case *parameter.EnumSpec: + constValues := make(map[string]*ConstValue) + for _, elt := range spec.Values { + if elt.Const == "" { + continue + } + constValues[elt.Const] = &ConstValue{ + Value: elt.Value, + } + } + if len(constValues) > 0 { + consts[param.Name] = &Const{ + Values: constValues, + } + } + + } + spec.Spec.Params[param.Name] = specParam + } + + if len(consts) > 0 { + spec.Const = consts + } + + for _, param := range object.Spec.Variants { + specParam, err := schemaParameterToSpecParameter(param) + if err != nil { + return nil, err + } + spec.Spec.OneOf[param.Name] = specParam + } + + return spec, nil +} + // ParseSpec parse single spec (unmarshal file), add name variants for locations and params, add default types for params. func ParseSpec(input []byte) (*Normalization, error) { - var spec Normalization + var object object.Object + err := content.Unmarshal(input, &object) + if err != nil { + return nil, err + } - err := content.Unmarshal(input, &spec) + spec, err := schemaToSpec(object) if err != nil { return nil, err } @@ -272,7 +634,7 @@ func ParseSpec(input []byte) (*Normalization, error) { return nil, err } - return &spec, err + return spec, err } // AddNameVariantsForLocation add name variants for location (under_score and CamelCase). diff --git a/pkg/properties/normalized_test.go b/pkg/properties/normalized_test.go index b375c436..b256f1dd 100644 --- a/pkg/properties/normalized_test.go +++ b/pkg/properties/normalized_test.go @@ -1,168 +1,22 @@ package properties import ( + "os" "testing" "github.com/stretchr/testify/assert" "gopkg.in/yaml.v3" ) -const sampleSpec = `name: 'Address' -terraform_provider_config: - suffix: 'address' -go_sdk_path: - - 'objects' - - 'address' -xpath_suffix: - - 'address' -locations: - 'shared': - description: 'Located in shared.' - device: - panorama: true - ngfw: true - xpath: ['config', 'shared'] - 'from_panorama': - description: 'Located in the config pushed from Panorama.' - read_only: true - device: - ngfw: true - xpath: ['config', 'panorama'] - 'vsys': - description: 'Located in a specific vsys.' - device: - panorama: true - ngfw: true - xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'device_group': - description: 'Located in a specific device group.' - device: - panorama: true - xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'device-group' - - '{{ Entry $device_group }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'device_group': - description: 'The device group.' - required: true - validation: - not_values: - 'shared': 'The device group cannot be "shared". Use the "shared" path instead.' -entry: - name: - description: 'The name of the address object.' - length: - min: 1 - max: 63 -imports: - 'template': - xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'vsys' - - '{{ Entry $vsys }}' - - 'import' - - 'network' - - 'interface' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'vsys': - description: 'The vsys.' - default: 'vsys1' - only_for_params: - - layer3 -version: '10.1.0' -spec: - params: - description: - description: 'The description.' - type: 'string' - length: - min: 0 - max: 1023 - profiles: - - - xpath: ["description"] - from_version: "10.1.1" - tags: - description: 'The administrative tags.' - type: 'list' - count: - max: 64 - items: - type: 'string' - length: - max: 127 - profiles: - - - type: 'member' - xpath: ["tag"] - one_of: - 'ip_netmask': - description: 'The IP netmask value.' - profiles: - - - xpath: ["ip-netmask"] - 'ip_range': - description: 'The IP range value.' - profiles: - - - xpath: ["ip-range"] - 'fqdn': - description: 'The FQDN value.' - regex: '^[a-zA-Z0-9_]([a-zA-Z0-9:_-])+[a-zA-Z0-9]$' - length: - min: 1 - max: 255 - profiles: - - - xpath: ["fqdn"] - 'ip_wildcard': - description: 'The IP wildcard value.' - profiles: - - - xpath: ["ip-wildcard"] - from_version: "11.1.2" -const: - color: - values: - red: - value: color1 - light green: - value: color9 - blue: - value: color3 -` +const addressSpecPath = "../../specs/objects/address.yaml" func TestUnmarshallAddressSpecFile(t *testing.T) { // given - + sampleSpec, err := os.ReadFile(addressSpecPath) + assert.Nil(t, err, "failed to read address spec") // when - yamlParsedData, _ := ParseSpec([]byte(sampleSpec)) + yamlParsedData, err := ParseSpec([]byte(sampleSpec)) + assert.Nil(t, err) // then assert.NotNilf(t, yamlParsedData, "Unmarshalled data cannot be nil") @@ -176,313 +30,6 @@ func TestUnmarshallAddressSpecFile(t *testing.T) { assert.NotNilf(t, yamlParsedData.Spec, "Unmarshalled data should contain `spec`") } -func TestMarshallAddressSpecFile(t *testing.T) { - // given - var expectedMarshalledData = `name: Address -terraform_provider_config: - skip_resource: false - skip_datasource: false - skip_datasource_listing: false - suffix: address -go_sdk_path: - - objects - - address -xpath_suffix: - - address -locations: - device_group: - name: - underscore: device_group - camelcase: DeviceGroup - lowercamelcase: deviceGroup - description: Located in a specific device group. - device: - panorama: true - ngfw: false - xpath: - - config - - devices - - '{{ Entry $panorama_device }}' - - device-group - - '{{ Entry $device_group }}' - read_only: false - vars: - device_group: - name: - underscore: device_group - camelcase: DeviceGroup - lowercamelcase: deviceGroup - description: The device group. - default: "" - required: true - validation: - not_values: - shared: The device group cannot be "shared". Use the "shared" path instead. - panorama_device: - name: - underscore: panorama_device - camelcase: PanoramaDevice - lowercamelcase: panoramaDevice - description: The panorama device. - default: localhost.localdomain - required: false - validation: null - from_panorama: - name: - underscore: from_panorama - camelcase: FromPanorama - lowercamelcase: fromPanorama - description: Located in the config pushed from Panorama. - device: - panorama: false - ngfw: true - xpath: - - config - - panorama - read_only: true - vars: {} - shared: - name: - underscore: shared - camelcase: Shared - lowercamelcase: shared - description: Located in shared. - device: - panorama: true - ngfw: true - xpath: - - config - - shared - read_only: false - vars: {} - vsys: - name: - underscore: vsys - camelcase: Vsys - lowercamelcase: vsys - description: Located in a specific vsys. - device: - panorama: true - ngfw: true - xpath: - - config - - devices - - '{{ Entry $ngfw_device }}' - - vsys - - '{{ Entry $vsys }}' - read_only: false - vars: - ngfw_device: - name: - underscore: ngfw_device - camelcase: NgfwDevice - lowercamelcase: ngfwDevice - description: The NGFW device. - default: localhost.localdomain - required: false - validation: null - vsys: - name: - underscore: vsys - camelcase: Vsys - lowercamelcase: vsys - description: The vsys. - default: vsys1 - required: false - validation: - not_values: - shared: The vsys cannot be "shared". Use the "shared" path instead. -entry: - name: - description: The name of the address object. - length: - min: 1 - max: 63 -imports: - template: - name: - underscore: template - camelcase: Template - lowercamelcase: template - xpath: - - config - - devices - - '{{ Entry $ngfw_device }}' - - vsys - - '{{ Entry $vsys }}' - - import - - network - - interface - vars: - ngfw_device: - name: - underscore: ngfw_device - camelcase: NgfwDevice - lowercamelcase: ngfwDevice - description: The NGFW device. - default: localhost.localdomain - vsys: - name: - underscore: vsys - camelcase: Vsys - lowercamelcase: vsys - description: The vsys. - default: vsys1 - only_for_params: - - layer3 -version: 10.1.0 -spec: - params: - description: - name: - underscore: description - camelcase: Description - lowercamelcase: description - description: The description. - type: string - default: "" - required: false - sensitive: false - length: - min: 0 - max: 1023 - profiles: - - xpath: - - description - not_present: false - from_version: 10.1.1 - spec: null - tags: - name: - underscore: tags - camelcase: Tags - lowercamelcase: tags - description: The administrative tags. - type: list - default: "" - required: false - sensitive: false - count: - min: null - max: 64 - items: - type: string - length: - min: null - max: 127 - ref: [] - profiles: - - xpath: - - tag - type: member - not_present: false - from_version: "" - spec: null - one_of: - fqdn: - name: - underscore: fqdn - camelcase: Fqdn - lowercamelcase: fqdn - description: The FQDN value. - type: string - default: "" - required: false - sensitive: false - length: - min: 1 - max: 255 - regex: ^[a-zA-Z0-9_]([a-zA-Z0-9:_-])+[a-zA-Z0-9]$ - profiles: - - xpath: - - fqdn - not_present: false - from_version: "" - spec: null - ip_netmask: - name: - underscore: ip_netmask - camelcase: IpNetmask - lowercamelcase: ipNetmask - description: The IP netmask value. - type: string - default: "" - required: false - sensitive: false - profiles: - - xpath: - - ip-netmask - not_present: false - from_version: "" - spec: null - ip_range: - name: - underscore: ip_range - camelcase: IpRange - lowercamelcase: ipRange - description: The IP range value. - type: string - default: "" - required: false - sensitive: false - profiles: - - xpath: - - ip-range - not_present: false - from_version: "" - spec: null - ip_wildcard: - name: - underscore: ip_wildcard - camelcase: IpWildcard - lowercamelcase: ipWildcard - description: The IP wildcard value. - type: string - default: "" - required: false - sensitive: false - profiles: - - xpath: - - ip-wildcard - not_present: false - from_version: 11.1.2 - spec: null -const: - color: - name: - underscore: color - camelcase: Color - lowercamelcase: color - values: - blue: - name: - underscore: blue - camelcase: Blue - lowercamelcase: blue - value: color3 - light green: - name: - underscore: light_green - camelcase: LightGreen - lowercamelcase: lightGreen - value: color9 - red: - name: - underscore: red - camelcase: Red - lowercamelcase: red - value: color1 -` - - // when - yamlParsedData, _ := ParseSpec([]byte(sampleSpec)) - yamlDump, _ := yaml.Marshal(&yamlParsedData) - - // then - assert.NotNilf(t, yamlDump, "Marshalled data cannot be nil") - assert.Equal(t, expectedMarshalledData, string(yamlDump), "Marshalled data differs from expected") -} - func TestGetNormalizations(t *testing.T) { // given @@ -541,27 +88,3 @@ xpath_suffix: // then assert.Len(t, problems, 2, "Not all expected validation checks failed") } - -func TestGettingListOfSupportedVersions(t *testing.T) { - // given - yamlParsedData, _ := ParseSpec([]byte(sampleSpec)) - - // when - versions := yamlParsedData.SupportedVersions() - - // then - assert.NotNilf(t, yamlParsedData, "Unmarshalled data cannot be nil") - assert.Contains(t, versions, "10.1.1") -} - -func TestCustomType(t *testing.T) { - // given - - // when - yamlParsedData, _ := ParseSpec([]byte(sampleSpec)) - - // then - assert.NotNil(t, yamlParsedData.Const) - assert.Equal(t, "Red", yamlParsedData.Const["color"].Values["red"].Name.CamelCase) - assert.Equal(t, "color1", yamlParsedData.Const["color"].Values["red"].Value) -} diff --git a/pkg/schema/imports/import.go b/pkg/schema/imports/import.go new file mode 100644 index 00000000..d188536e --- /dev/null +++ b/pkg/schema/imports/import.go @@ -0,0 +1,9 @@ +package imports + +import "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/xpath" + +type Import struct { + Name string `yaml:"name"` + Xpath xpathschema.Xpath `yaml:"xpath"` + OnlyForParams []string `yaml:"only_for_params"` +} diff --git a/pkg/schema/location/location.go b/pkg/schema/location/location.go new file mode 100644 index 00000000..e060b397 --- /dev/null +++ b/pkg/schema/location/location.go @@ -0,0 +1,21 @@ +package location + +import ( + validatorschema "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/validator" + xpathschema "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/xpath" +) + +type Device string + +const ( + DevicePanorama Device = "panorama" + DeviceNgfw Device = "ngfw" +) + +type Location struct { + Name string `yaml:"name"` + Description string `yaml:"description"` + Devices []Device `yaml:"devices"` + Xpath xpathschema.Xpath `yaml:"xpath"` + Validators []*validatorschema.Validator `yaml:"validators"` +} diff --git a/pkg/schema/object/object.go b/pkg/schema/object/object.go new file mode 100644 index 00000000..2d87a676 --- /dev/null +++ b/pkg/schema/object/object.go @@ -0,0 +1,59 @@ +package object + +import ( + "gopkg.in/yaml.v3" + + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/imports" + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/location" + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/parameter" + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/validator" +) + +type TerraformConfig struct { + SkipResource bool `yaml:"skip_resource"` + SkipDatasource bool `yaml:"skip_datasource"` + SkipdatasourceListing bool `yaml:"skip_datasource_listing"` + Suffix string `yaml:"suffix"` +} + +type GoSdkConfig struct { + Package []string +} + +type Entry struct { + Name string `yaml:"name"` + Description string `yaml:"descripion"` + Validators []*validator.Validator `yaml:"validators"` +} + +type Spec struct { + Required bool `yaml:"required"` + Parameters []*parameter.Parameter `yaml:"params"` + Variants []*parameter.Parameter `yaml:"variants"` +} + +type Object struct { + Name string `yaml:"-"` + DisplayName string `yaml:"name"` + XpathSuffix []string `yaml:"xpath_suffix"` + TerraformConfig *TerraformConfig `yaml:"terraform_provider_config"` + Version string `yaml:"version"` + GoSdkConfig *GoSdkConfig `yaml:"go_sdk_config"` + Locations []location.Location `yaml:"locations"` + Entries []Entry `yaml:"entries"` + Imports []imports.Import `yaml:"imports"` + Spec *Spec `yaml:"spec"` +} + +func NewFromBytes(name string, objectBytes []byte) (*Object, error) { + var object Object + + err := yaml.Unmarshal(objectBytes, &object) + if err != nil { + return nil, err + } + + object.Name = name + + return &object, nil +} diff --git a/pkg/schema/object/object_suite_test.go b/pkg/schema/object/object_suite_test.go new file mode 100644 index 00000000..e4b6f34a --- /dev/null +++ b/pkg/schema/object/object_suite_test.go @@ -0,0 +1,15 @@ +package object_test + +import ( + "log/slog" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestObject(t *testing.T) { + slog.SetDefault(slog.New(slog.NewTextHandler(GinkgoWriter, &slog.HandlerOptions{Level: slog.LevelDebug}))) + RegisterFailHandler(Fail) + RunSpecs(t, "Object Suite") +} diff --git a/pkg/schema/parameter/parameter.go b/pkg/schema/parameter/parameter.go new file mode 100644 index 00000000..7b6106b6 --- /dev/null +++ b/pkg/schema/parameter/parameter.go @@ -0,0 +1,185 @@ +package parameter + +import ( + "fmt" + "log/slog" + + "gopkg.in/yaml.v3" + + "github.com/paloaltonetworks/pan-os-codegen/pkg/errors" + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/profile" + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/validator" +) + +// Parameter describes a single parameter for the given object spec. +// +// Parameter can describe both a top-level parameter of the object +// or nested parameter of another object parameter. +// +// Spec type is any, as its unmarshalling is done in a custom +// UnmarshalYAML function. +type Parameter struct { + Name string `yaml:"name"` + Description string `yaml:"description"` + Type string `yaml:"type"` + CodegenOverrides *CodegenOverrides `yaml:"codegen_overrides"` + Required bool `yaml:"required"` + Profiles []profile.Profile `yaml:"profiles"` + Validators []validator.Validator `yaml:"validators"` + Spec any `yaml:"-"` +} + +// SimpleSpec describes a parameter of a simple type. +type SimpleSpec struct { + Default any `yaml:"default"` + Required bool `yaml:"required"` +} + +// EnumSpecValue describes a single enum value. +type EnumSpecValue struct { + Value string `yaml:"value"` + Const string `yaml:"const"` +} + +type CodegenOverridesTerraform struct { + Computed bool `yaml:"computed"` +} + +type CodegenOverrides struct { + Terraform *CodegenOverridesTerraform `yaml:"terraform"` +} + +// EnumSpec describes a parameter of type enum +// +// Values is a list of EnumSpecValue, where each one consisting of the PAN-OS Value +// and its optional Const representation. This allows to generate a more meaningful +// types, for example when spec value is "color1", and its const is "red", the following +// type will be marshalled for pan-os-go SDK: +// +// ParameterRed ParameterType = "color1" +// +// when spec value is "up" and spec const is empty, the following type will be marshalled +// instead: +// +// ParameterUp ParameterType = "up" +type EnumSpec struct { + Required bool `yaml:"required"` + Default string `yaml:"default"` + Values []EnumSpecValue `yaml:"values"` +} + +type StructSpec struct { + Required bool `yaml:"required"` + Parameters []*Parameter `yaml:"params"` + Variants []*Parameter `yaml:"variants"` +} + +type ListSpecElement struct { + Type string `yaml:"type"` + Required bool `yaml:"required"` + Spec StructSpec `yaml:"spec"` +} + +type ListSpec struct { + Required bool `yaml:"required"` + Items ListSpecElement `yaml:"items"` +} + +type NilSpec struct{} + +// UnmarshalYAML implements custom unmarshalling logic for parameters +// +// When unmarshalling yaml objects into parameters, their spec is unmarshalled +// into different structures based on the spec type. This custom UnmarshalYAML +// functions handles this logic. +func (p *Parameter) UnmarshalYAML(n *yaml.Node) error { + // Create an empty Parameter value and a new temporary structure + // that is based on the parameter, but overrides Spec field to be + // of a generic yaml.Node type. + // This new type, and the casting below is needed so that yaml + // unmarshaller doesn't recursively call UnmarshalYAML. + type P Parameter + type S struct { + *P `yaml:",inline"` + Spec yaml.Node `yaml:"spec"` + } + + // Cast "this" parameter pointer to a new S type and then decode + // entire parameter yaml object into this new object. This will + // unmarshal spec field from yaml into yaml.Node Spec field in the + // temporary structure. + obj := &S{P: (*P)(p)} + if err := n.Decode(obj); err != nil { + return err + } + + // Now that we have unmarshalled entire parameter object into a temporary + // structure, we can assign proper structure to the parameter Spec field. + switch p.Type { + case "object": + p.Spec = new(StructSpec) + case "list": + p.Spec = new(ListSpec) + case "enum": + p.Spec = new(EnumSpec) + case "nil": + p.Spec = new(NilSpec) + case "string", "bool", "int64": + p.Spec = new(SimpleSpec) + default: + return errors.NewSchemaError(fmt.Sprintf("unsupported parameter type: '%s'", p.Type)) + } + + // Finally, decode obj.Spec (which is yaml.Node type) into the parameter + // spec structure + return obj.Spec.Decode(p.Spec) +} + +// SingularName returns a singular name for parameter. +// +// When Parameter type is list, and list profile type is either +// "entry" or "member", we us first path of an profile xpath array +// to determine a singular name for the given parameter. +// +// When called for non-list parameters, parameter name is returned +// instead. +func (p *Parameter) SingularName() string { + switch p.Spec.(type) { + case *ListSpec: + var singularName string + for _, profile := range p.Profiles { + switch profile.Type { + case "entry", "member": + if len(profile.Xpath) >= 1 { + singularName = profile.Xpath[0] + } + } + } + + if singularName == "" { + slog.Warn("Couldn't generate singular name for list parameter", "parameter", p.Name) + } + + return singularName + } + + return p.Name +} + +// SpecItemsType is a shorthand accessor to list items type +// +// When checking parameter list item type, parameter's spec has to +// be first cast to the ListSpec type. This function gives +// a quick access to the type without having to do casting manually. +// +// When called on any other parameter type, it returns an empty +// string, so the caller (mostly templates) must ensure that it's +// being called on list parameters. +func (p *Parameter) SpecItemsType() string { + switch spec := p.Spec.(type) { + case *ListSpec: + return spec.Items.Type + default: + return "" + } +} diff --git a/pkg/schema/parameter/parameter_suite_test.go b/pkg/schema/parameter/parameter_suite_test.go new file mode 100644 index 00000000..d3502190 --- /dev/null +++ b/pkg/schema/parameter/parameter_suite_test.go @@ -0,0 +1,13 @@ +package parameter_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestParameter(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Parameter Suite") +} diff --git a/pkg/schema/parameter/parameter_test.go b/pkg/schema/parameter/parameter_test.go new file mode 100644 index 00000000..58bf6d51 --- /dev/null +++ b/pkg/schema/parameter/parameter_test.go @@ -0,0 +1,81 @@ +package parameter_test + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "gopkg.in/yaml.v3" + + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/parameter" + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/profile" +) + +var _ = Describe("Parameter", func() { + Describe("When unmarshalling YAML object into parameter", func() { + Context("with parameter type set to nil", func() { + It("should unmarshal into Parameter with ParameterNilSpec Spec", func() { + bytes := []byte(`{name: test-param, type: nil, profiles: [], spec: {}}`) + var param parameter.Parameter + err := yaml.Unmarshal(bytes, ¶m) + Expect(err).ToNot(HaveOccurred()) + }) + }) + }) + Describe("When a list parameter is created", func() { + Context("with required set to true, items' type set to a simple type and with singular profile xpath", func() { + var param parameter.Parameter + BeforeEach(func() { + param = parameter.Parameter{ + Name: "test-params", + Required: true, + Type: "list", + Spec: ¶meter.ListSpec{ + Items: parameter.ListSpecElement{ + Type: "string", + }, + }, + Profiles: []profile.Profile{ + { + Type: "entry", + Xpath: []string{"test-param"}, + }, + }, + } + }) + It("the required state should be correct", func() { + Expect(param.Required).To(BeTrue()) + }) + It("the SpecItemsType shortcut should return correct type of the items", func() { + Expect(param.SpecItemsType()).To(Equal("string")) + }) + It("the singular name should be properly generated", func() { + Expect(param.SingularName()).To(Equal("test-param")) + }) + }) + Context("with required not set explicitly", func() { + var param parameter.Parameter + BeforeEach(func() { + param = parameter.Parameter{ + Name: "test-params", + Type: "list", + Spec: ¶meter.ListSpec{ + Items: parameter.ListSpecElement{ + Type: "object", + }, + }, + Profiles: []profile.Profile{ + { + Type: "entry", + Xpath: []string{"test-param", "entry"}, + }, + }, + } + }) + It("the required should return false", func() { + Expect(param.Required).To(BeFalse()) + }) + It("the singular name should be properly generated", func() { + Expect(param.SingularName()).To(Equal("test-param")) + }) + }) + }) +}) diff --git a/pkg/schema/profile/profile.go b/pkg/schema/profile/profile.go new file mode 100644 index 00000000..a9419d59 --- /dev/null +++ b/pkg/schema/profile/profile.go @@ -0,0 +1,16 @@ +package profile + +import "github.com/paloaltonetworks/pan-os-codegen/pkg/version" + +// Profile describes parameter versioning information +// +// MinimumVersion and MaximumVersion can be used to limit +// parameter visibility across PAN-OS versions. This is used +// in the marshalling/unmarshalling code to generate per-version +// structures and properly marshal objects into XML documents. +type Profile struct { + Type string `yaml:"type"` + MinimumVersion *version.Version `yaml:"min_version"` + MaximumVersion *version.Version `yaml:"max_version"` + Xpath []string `yaml:"xpath"` +} diff --git a/pkg/schema/validator/validators.go b/pkg/schema/validator/validators.go new file mode 100644 index 00000000..f4ad968e --- /dev/null +++ b/pkg/schema/validator/validators.go @@ -0,0 +1,101 @@ +package validator + +import ( + "fmt" + + "gopkg.in/yaml.v3" + + "github.com/paloaltonetworks/pan-os-codegen/pkg/errors" +) + +// Validator describes any validator that can be defined across +// xpath variables, locations, entries and parameters. +// +// Spec type is any, as its unmarshalling is done in a custom +// UnmarshalYAML function. +type Validator struct { + Type string `yaml:"type"` + Spec any `yaml:"-"` +} + +// UnmarshalYAML implements custom unmarshalling logic for parameters +// +// When unmarshalling yaml objects into parameters, their spec is unmarshalled +// into different structures based on the spec type. This custom UnmarshalYAML +// +// For a detailed description of how this is achieved check `parameter.Parameter` +// documentation. +func (v *Validator) UnmarshalYAML(n *yaml.Node) error { + type V Validator + type S struct { + *V `yaml:",inline"` + Spec yaml.Node `yaml:"spec"` + } + + obj := &S{V: (*V)(v)} + if err := n.Decode(obj); err != nil { + return err + } + + switch v.Type { + case "length": + v.Spec = new(StringLengthSpec) + case "values": + v.Spec = new(ValuesSpec) + case "not-values": + v.Spec = new(NotValuesSpec) + case "range": + v.Spec = new(RangeSpec) + case "count": + v.Spec = new(CountSpec) + case "regexp": + v.Spec = new(RegexpSpec) + case "required": + v.Spec = new(RequiredSpec) + default: + return errors.NewSchemaError(fmt.Sprintf("unsupported validator: '%s'", obj.Type)) + } + + return obj.Spec.Decode(v.Spec) +} + +// RequiredSpec validates that a given value is set. +type RequiredSpec struct{} + +// StringLengthSpec validates given string's length. +type StringLengthSpec struct { + Min int + Max int +} + +// ValuesSpec validates that a given value is within validator values. +type ValuesSpec struct { + Values []any +} + +type NotValuesSpecItem struct { + Value string + Error string +} + +// NotValuesSpec validates that a given value is not withing validator values. +type NotValuesSpec struct { + Values []NotValuesSpecItem +} + +// RangeSpec validates that a given numeric value is within a given range. +type RangeSpec struct { + Min int + Max int +} + +// CountSpec validates that a given slice length is within a given range. +type CountSpec struct { + Min int + Max int +} + +// RegexpSpec validates that a given value matches regex expression. +type RegexpSpec struct { + Expr string +} diff --git a/pkg/schema/xpath/xpath.go b/pkg/schema/xpath/xpath.go new file mode 100644 index 00000000..d70ed674 --- /dev/null +++ b/pkg/schema/xpath/xpath.go @@ -0,0 +1,57 @@ +package xpathschema + +import ( + "gopkg.in/yaml.v3" + + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/validator" +) + +type VariableType string + +const ( + VariableEntry VariableType = "entry" + VariableObject VariableType = "object" +) + +// Variable describes a single xpath variable +// +// Xpath variables are used to dynamically render parts of the +// object xpath, using custom logic from pan-os-go utils. +type Variable struct { + Name string `yaml:"name"` + Description string `yaml:"description"` + Required bool `yaml:"required"` + Type VariableType `yaml:"type"` + Default string `yaml:"default"` + Validators []validator.Validator `yaml:"validators"` +} + +// Xpath describes xpath as used by locations and imports +// +// Xpath Elements that start with '$' character are variables, +// defined in the Variables field. +type Xpath struct { + Elements []string `yaml:"path"` + Variables []Variable `yaml:"vars"` +} + +// UnmarshalYAML implements unmarshalling with default Type. +// +// This is temporary logic that sets default Type for all variables +// that have no type set explicitly. It can be removed once all +// schemas are generated from the XML source. +func (o *Variable) UnmarshalYAML(n *yaml.Node) error { + type V Variable + + obj := (*V)(o) + err := n.Decode(obj) + if err != nil { + return err + } + + if o.Type == "" { + o.Type = "entry" + } + + return nil +} diff --git a/pkg/schema/xpath/xpath_suite_test.go b/pkg/schema/xpath/xpath_suite_test.go new file mode 100644 index 00000000..5073a090 --- /dev/null +++ b/pkg/schema/xpath/xpath_suite_test.go @@ -0,0 +1,19 @@ +package xpathschema_test + +import ( + "log/slog" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestXpath(t *testing.T) { + handler := slog.NewTextHandler( + GinkgoWriter, + &slog.HandlerOptions{Level: slog.LevelDebug}, + ) + slog.SetDefault(slog.New(handler)) + RegisterFailHandler(Fail) + RunSpecs(t, "Xpath Suite") +} diff --git a/pkg/schema/xpath/xpath_test.go b/pkg/schema/xpath/xpath_test.go new file mode 100644 index 00000000..cbbace8d --- /dev/null +++ b/pkg/schema/xpath/xpath_test.go @@ -0,0 +1,34 @@ +package xpathschema_test + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "gopkg.in/yaml.v3" + + "github.com/paloaltonetworks/pan-os-codegen/pkg/schema/xpath" +) + +var _ = Describe("Variable", func() { + Describe("When unmarshalling yaml document", func() { + Context("with type set to non-empty string", func() { + It("should create a valid Variable", func() { + data := []byte(`{name: variable, type: object}`) + var variable xpathschema.Variable + err := yaml.Unmarshal(data, &variable) + Expect(err).ToNot(HaveOccurred()) + Expect(variable.Name).To(Equal("variable")) + Expect(variable.Type).To(Equal(xpathschema.VariableObject)) + }) + }) + Context("with type left unset", func() { + It("should create a valid Variable with type entry", func() { + data := []byte(`{name: variable}`) + var variable xpathschema.Variable + err := yaml.Unmarshal(data, &variable) + Expect(err).ToNot(HaveOccurred()) + Expect(variable.Name).To(Equal("variable")) + Expect(variable.Type).To(Equal(xpathschema.VariableEntry)) + }) + }) + }) +}) diff --git a/pkg/translate/structs.go b/pkg/translate/structs.go index ec7f7718..f289b152 100644 --- a/pkg/translate/structs.go +++ b/pkg/translate/structs.go @@ -182,7 +182,7 @@ func ParamSupportedInVersion(param *properties.SpecParam, deviceVersionStr strin if deviceVersionStr == "" { supported = listOfProfileSupportForNotDefinedDeviceVersion(param, supported) } else { - deviceVersion, err := version.New(deviceVersionStr) + deviceVersion, err := version.NewVersionFromString(deviceVersionStr) if err != nil { return false } @@ -209,12 +209,12 @@ func listOfProfileSupportForNotDefinedDeviceVersion(param *properties.SpecParam, func listOfProfileSupportForDefinedDeviceVersion(param *properties.SpecParam, supported []bool, deviceVersion version.Version) ([]bool, error) { for _, profile := range param.Profiles { if profile.FromVersion != "" { - paramProfileVersion, err := version.New(profile.FromVersion) + paramProfileVersion, err := version.NewVersionFromString(profile.FromVersion) if err != nil { return nil, err } - if deviceVersion.Gte(paramProfileVersion) { + if deviceVersion.GreaterThanOrEqualTo(paramProfileVersion) { supported = append(supported, !profile.NotPresent) } else { supported = append(supported, profile.NotPresent) diff --git a/pkg/translate/structs_test.go b/pkg/translate/structs_test.go index 44b57982..13d27f8e 100644 --- a/pkg/translate/structs_test.go +++ b/pkg/translate/structs_test.go @@ -1,6 +1,7 @@ package translate import ( + "os" "testing" "github.com/stretchr/testify/assert" @@ -8,56 +9,14 @@ import ( "github.com/paloaltonetworks/pan-os-codegen/pkg/properties" ) -const sampleSpec = `name: 'Address' -terraform_provider_config: - skip_resource: false - skip_datasource: false - skip_datasource_listing: false - suffix: address -go_sdk_path: - - 'objects' - - 'address' -xpath_suffix: - - 'address' -locations: - 'shared': - description: 'Located in shared.' - device: - panorama: true - ngfw: true - xpath: ['config', 'shared'] - 'device_group': - description: 'Located in a specific device group.' - device: - panorama: true - xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'device-group' - - '{{ Entry $device_group }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'device_group': - description: 'The device group.' - required: true - validation: - not_values: - 'shared': 'The device group cannot be "shared". Use the "shared" path instead.' -entry: - name: - description: 'The name of the address object.' - length: - min: 1 - max: 63 -version: '10.1.0' -` +const addressSpecPath = "../../specs/objects/address.yaml" func TestLocationType(t *testing.T) { + sampleSpec, err := os.ReadFile(addressSpecPath) + assert.Nil(t, err, "failed to read address spec") // given yamlParsedData, _ := properties.ParseSpec([]byte(sampleSpec)) + locationKeys := []string{"device_group", "shared"} locations := yamlParsedData.Locations var locationTypes []string @@ -102,6 +61,9 @@ func TestSpecParamType(t *testing.T) { } func TestOmitEmpty(t *testing.T) { + sampleSpec, err := os.ReadFile(addressSpecPath) + assert.Nil(t, err, "failed to read address spec") + // given yamlParsedData, _ := properties.ParseSpec([]byte(sampleSpec)) locationKeys := []string{"device_group", "shared"} diff --git a/pkg/version/version.go b/pkg/version/version.go index 7bcf8f4c..322e1874 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -1,72 +1,144 @@ package version import ( - "errors" "fmt" "strconv" "strings" + + "gopkg.in/yaml.v3" ) -// Version is the version number struct. +// Version represents PAN-OS version split into its components type Version struct { Major, Minor, Patch int Hotfix string } -// Gte tests if this version number is greater than or equal to the argument. -func (v Version) Gte(o Version) bool { - if v.Major != o.Major { - return v.Major > o.Major +// NewVersionFromString creates a new Version value from a given string +func NewVersionFromString(version string) (Version, error) { + parts := strings.Split(version, ".") + if len(parts) != 3 { + return Version{}, fmt.Errorf("invalid version string: not enough components") } - if v.Minor != o.Minor { - return v.Minor > o.Minor + major, err := strconv.Atoi(parts[0]) + if err != nil { + return Version{}, fmt.Errorf("invalid version string: major component must be a number") } - return v.Patch >= o.Patch -} + minor, err := strconv.Atoi(parts[1]) + if err != nil { + return Version{}, fmt.Errorf("invalid version string: minor component must be a number") + } -// String returns the version number as a string. -func (v Version) String() string { - if v.Hotfix == "" { - return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch) + patchParts := strings.Split(parts[2], "-") + + var patch int + var hotfix string + if len(patchParts) == 1 { + patch, err = strconv.Atoi(parts[2]) + if err != nil { + return Version{}, fmt.Errorf("invalid version string: patch component must be a number") + } } else { - return fmt.Sprintf("%d.%d.%d-%s", v.Major, v.Minor, v.Patch, v.Hotfix) + if patchParts[1] == "" { + return Version{}, fmt.Errorf("invalid version string: hotfix part must be set") + } + patch, err = strconv.Atoi(patchParts[0]) + if err != nil { + return Version{}, fmt.Errorf("invalid version string: patch component must be a number") + } + hotfix = patchParts[1] } + + return Version{ + Major: major, + Minor: minor, + Patch: patch, + Hotfix: hotfix, + }, nil + } -// New returns a version number from the given string. -func New(version string) (Version, error) { - parts := strings.Split(version, ".") - if len(parts) != 3 { - return Version{}, errors.New("invalid version") +// UnmarshalYAML implements custom unmarshalling of YAML data into Version +func (v *Version) UnmarshalYAML(node *yaml.Node) error { + var versionString string + if err := node.Decode(&versionString); err != nil { + return fmt.Errorf("failed to unmarshal YAML structure: %w", err) } - major, err := strconv.Atoi(parts[0]) + decoded, err := NewVersionFromString(versionString) if err != nil { - return Version{}, fmt.Errorf("major %s is not a number: %w", parts[0], err) + return err } - minor, err := strconv.Atoi(parts[1]) - if err != nil { - return Version{}, fmt.Errorf("minor %s is not a number: %w", parts[0], err) + *v = decoded + + return nil +} + +// String() returns a string representation of the Version value +func (v Version) String() string { + version := fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch) + if v.Hotfix != "" { + version = fmt.Sprintf("%s-%s", version, v.Hotfix) } - patchWithHotfix := strings.Split(parts[2], "-") + return version +} - var hotfix string - if len(patchWithHotfix) == 1 { - hotfix = "" - } else if len(patchWithHotfix) == 2 { - hotfix = patchWithHotfix[1] - } else { - return Version{}, fmt.Errorf("patch %s is not formatted as expected", parts[2]) +// LesserThan implements lesser than +// +// This function, just like other boolean comparisons ignore any value +// of the Hotfix field. +func (v Version) LesserThan(o Version) bool { + if v.Major != o.Major { + return v.Major < o.Major } - patch, err := strconv.Atoi(patchWithHotfix[0]) - if err != nil { - return Version{}, fmt.Errorf("patch %s is not a number: %w", parts[2], err) + if v.Minor != o.Minor { + return v.Minor < o.Minor + } + + return v.Patch < o.Patch +} + +// EqualTo implements equality comparison +// +// This function, just like other boolean comparisons ignore any value +// of the Hotfix field. +func (v Version) EqualTo(o Version) bool { + return v.Major == o.Major && v.Minor == o.Minor && v.Patch == o.Patch +} + +// GreaterThan implements greater than comparison +// +// This function, just like other boolean comparisons ignore any value +// of the Hotfix field. +func (v Version) GreaterThan(o Version) bool { + if v.Major != o.Major { + return v.Major > o.Major + } + + if v.Minor != o.Minor { + return v.Minor > o.Minor } - return Version{major, minor, patch, hotfix}, nil + return v.Patch > o.Patch +} + +// GreatherThanOrEqualTo implements greater or equal comparison +// +// This function, just like other boolean comparisons ignore any value +// of the Hotfix field. +func (v Version) GreaterThanOrEqualTo(o Version) bool { + return v.EqualTo(o) || v.GreaterThan(o) +} + +// LesserThanOrEqualTo implemets lesser or equal comparison +// +// This function, just like other boolean comparisons ignore any value +// of the Hotfix field. +func (v Version) LesserThanOrEqualTo(o Version) bool { + return v.EqualTo(o) || v.LesserThan(o) } diff --git a/pkg/version/version_suite_test.go b/pkg/version/version_suite_test.go new file mode 100644 index 00000000..a115d9d8 --- /dev/null +++ b/pkg/version/version_suite_test.go @@ -0,0 +1,15 @@ +package version_test + +import ( + "log/slog" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestVersion(t *testing.T) { + slog.SetDefault(slog.New(slog.NewTextHandler(GinkgoWriter, &slog.HandlerOptions{Level: slog.LevelDebug}))) + RegisterFailHandler(Fail) + RunSpecs(t, "Version Suite") +} diff --git a/pkg/version/version_test.go b/pkg/version/version_test.go index 54bd2665..12a7b772 100644 --- a/pkg/version/version_test.go +++ b/pkg/version/version_test.go @@ -1,50 +1,143 @@ -package version +package version_test import ( - "testing" + "fmt" - "github.com/stretchr/testify/assert" -) - -func TestCorrectVersion(t *testing.T) { - // given - - // when - version1011, err1011 := New("10.1.1") - version1011h2, err1011h2 := New("10.1.1-h2") - - // then - assert.NoError(t, err1011) - assert.Equal(t, 10, version1011.Major) - assert.Equal(t, 1, version1011.Minor) - assert.Equal(t, 1, version1011.Patch) - assert.Equal(t, "", version1011.Hotfix) - assert.NoError(t, err1011h2) - assert.Equal(t, 10, version1011h2.Major) - assert.Equal(t, 1, version1011h2.Minor) - assert.Equal(t, 1, version1011h2.Patch) - assert.Equal(t, "h2", version1011h2.Hotfix) -} + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "gopkg.in/yaml.v3" -func TestIncorrectVersion(t *testing.T) { - // given - - // when - _, err101 := New("10.1") - _, err1011h2h2 := New("10.1.1-h2-h2") - - // then - assert.Error(t, err101) - assert.Error(t, err1011h2h2) -} - -func TestVersionComparison(t *testing.T) { - // given + "github.com/paloaltonetworks/pan-os-codegen/pkg/version" +) - // when - v1, _ := New("10.1.1") - v2, _ := New("10.2.1-h2") +var _ = Describe("Version", func() { + Context("when version is unmarshalled from yaml", func() { + Context("with invalid yaml data", func() { + It("should return a wrapped error", func() { + data := "-" + var v version.Version + err := yaml.Unmarshal([]byte(data), &v) + Expect(err).Should(MatchError(MatchRegexp("failed to unmarshal YAML structure:.+"))) + }) + }) + Context("with an invalid string version", func() { + var v version.Version + Context("where not all components are set", func() { - // then - assert.True(t, v2.Gte(v1)) -} + It("should return an error", func() { + data := "10" + err := yaml.Unmarshal([]byte(data), &v) + Expect(err).Should(MatchError(fmt.Errorf("invalid version string: not enough components"))) + }) + }) + Context("where major component is not a number", func() { + It("should return an error", func() { + data := "a.b.c" + err := yaml.Unmarshal([]byte(data), &v) + Expect(err).Should(MatchError(MatchRegexp(".*major component must be a number$"))) + }) + }) + Context("where minor component is not a number", func() { + It("should return an error", func() { + data := "10.b.c" + err := yaml.Unmarshal([]byte(data), &v) + Expect(err).Should(MatchError(MatchRegexp(".*minor component must be a number$"))) + }) + }) + Context("where patch component is not a number", func() { + It("should return an error", func() { + data := "10.0.c" + err := yaml.Unmarshal([]byte(data), &v) + Expect(err).Should(MatchError(MatchRegexp(".*patch component must be a number$"))) + }) + }) + Context("where hotfix component is empty", func() { + It("should return an error", func() { + data := "10.0.0-" + err := yaml.Unmarshal([]byte(data), &v) + Expect(err).Should(MatchError(MatchRegexp(".*hotfix part must be set"))) + }) + }) + Context("where patch component is not a number, and there is hotfix component", func() { + It("should return an error", func() { + data := "10.0.a-hotfix1" + err := yaml.Unmarshal([]byte(data), &v) + Expect(err).Should(MatchError(MatchRegexp(".*patch component must be a number"))) + }) + }) + }) + Context("with a hotfix", func() { + It("should have a proper struct representation", func() { + data := "10.0.0-hotfix1" + var v version.Version + err := yaml.Unmarshal([]byte(data), &v) + Expect(err).ShouldNot(HaveOccurred()) + Expect(v).To(Equal(version.Version{Major: 10, Minor: 0, Patch: 0, Hotfix: "hotfix1"})) + }) + }) + Context("without a hotfix", func() { + It("should have a proper struct representation", func() { + data := "10.0.0" + var v version.Version + err := yaml.Unmarshal([]byte(data), &v) + Expect(err).ShouldNot(HaveOccurred()) + Expect(v).To(Equal(version.Version{Major: 10, Minor: 0, Patch: 0})) + }) + }) + }) + Context("when version is rendered to a string", func() { + Context("with a hotfix", func() { + It("should render to a valid string representation", func() { + expected := "10.0.0-hotfix1" + v := version.Version{Major: 10, Minor: 0, Patch: 0, Hotfix: "hotfix1"} + Expect(v.String()).To(Equal(expected)) + }) + }) + Context("wthout a hotfix", func() { + It("should render to a valid string representation", func() { + expected := "10.0.0" + v := version.Version{Major: 10, Minor: 0, Patch: 0} + Expect(v.String()).To(Equal(expected)) + }) + }) + }) + Context("When comparing version against another", func() { + this := version.Version{Major: 10, Minor: 0, Patch: 0} + Context("where both versions are missing hotfix", func() { + other := version.Version{Major: 10, Minor: 0, Patch: 0} + It("version should be EqualTo other version", func() { + Expect(this.EqualTo(other)).To(BeTrue()) + }) + It("version should be GreaterThanOrEqualTo other version", func() { + Expect(this.GreaterThanOrEqualTo(other)).To(BeTrue()) + }) + It("version should be LesserThanOrEqualTo other version", func() { + Expect(this.LesserThanOrEqualTo(other)).To(BeTrue()) + }) + It("version should not be GreaterThan other version", func() { + Expect(this.GreaterThan(other)).To(BeFalse()) + }) + It("version should not be LesserThan other version", func() { + Expect(this.LesserThan(other)).To(BeFalse()) + }) + }) + Context("where one of versions has a hotfix", func() { + other := version.Version{Major: 10, Minor: 0, Patch: 0, Hotfix: "hotfix1"} + It("version should be EqualTo other version", func() { + Expect(this.EqualTo(other)).To(BeTrue()) + }) + It("version should be GreaterThanOrEqualTo other version", func() { + Expect(this.GreaterThanOrEqualTo(other)).To(BeTrue()) + }) + It("version should be LesserThanOrEqualTo other version", func() { + Expect(this.LesserThanOrEqualTo(other)).To(BeTrue()) + }) + It("version should not be GreaterThan other version", func() { + Expect(this.GreaterThan(other)).To(BeFalse()) + }) + It("version should not be LesserThan other version", func() { + Expect(this.LesserThan(other)).To(BeFalse()) + }) + }) + }) +}) diff --git a/specs/device/dns.yaml b/specs/device/dns.yaml index 6a2b0dad..a1b44161 100644 --- a/specs/device/dns.yaml +++ b/specs/device/dns.yaml @@ -1,108 +1,116 @@ -name: 'DNS' +name: "DNS" terraform_provider_config: - suffix: 'dns' -go_sdk_path: - - 'device' - - 'services' - - 'dns' + suffix: "dns" +go_sdk_config: + package: + - "device" + - "services" + - "dns" locations: - 'system': - description: 'Located in a system settings.' - device: - panorama: true - ngfw: true + - name: "system" + description: "Located in a system settings." + devices: + - panorama + - ngfw xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'deviceconfig' - - 'system' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'template': - description: 'Located in a specific template.' - device: - panorama: true + path: + - "config" + - "devices" + - "$ngfw_device" + - "deviceconfig" + - "system" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "template" + description: "Located in a specific template." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'template' - - '{{ Entry $template }}' - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'deviceconfig' - - 'system' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'template': - description: 'The template.' - required: true - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'template-stack': - description: 'Located in a specific template stack.' - device: - panorama: true + path: + - "config" + - "devices" + - "$panorama_device" + - "template" + - "$template" + - "config" + - "devices" + - "$ngfw_device" + - "deviceconfig" + - "system" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template" + description: "The template." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "template-stack" + description: "Located in a specific template stack." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'template-stack' - - '{{ Entry $template_stack }}' - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'deviceconfig' - - 'system' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'template_stack': - description: 'The template stack.' - required: true - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + - "template-stack" + - "$template_stack" + - "config" + - "devices" + - "$ngfw_device" + - "deviceconfig" + - "system" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template_stack" + description: "The template stack." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" +version: "10.1.0" spec: params: - fqdn_refresh_time: - description: 'Seconds for Periodic Timer to refresh expired FQDN object entries' + - name: fqdn_refresh_time + description: "Seconds for Periodic Timer to refresh expired FQDN object entries" type: int64 - value: - min: 600 - max: 14399 + spec: default: 1800 + validators: + - type: range + spec: + min: 600 + max: 14399 profiles: - - - xpath: ["fqdn-refresh-time"] - dns_setting: - description: 'DNS settings' + - xpath: ["fqdn-refresh-time"] + - name: dns_setting + description: "DNS settings" + type: object profiles: - - - xpath: ["dns-setting"] + - xpath: ["dns-setting"] spec: params: - servers: - description: 'DNS servers' + - name: servers + description: "DNS servers" + type: object profiles: - - - xpath: ["servers"] + - xpath: ["servers"] spec: params: - primary: - description: 'Primary DNS server IP address' + - name: primary + description: "Primary DNS server IP address" + type: string profiles: - - xpath: [ "primary" ] - secondary: - description: 'Secondary DNS server IP address' + - xpath: ["primary"] + - name: secondary + description: "Secondary DNS server IP address" + type: string profiles: - - xpath: [ "secondary" ] + - xpath: ["secondary"] diff --git a/specs/device/ntp.yaml b/specs/device/ntp.yaml index 2fa22801..eed3feb9 100644 --- a/specs/device/ntp.yaml +++ b/specs/device/ntp.yaml @@ -1,214 +1,255 @@ name: "NTP" terraform_provider_config: suffix: "ntp" -go_sdk_path: - - "device" - - "services" - - "ntp" +go_sdk_config: + package: + - "device" + - "services" + - "ntp" locations: - "system": + - name: "system" description: "Located in a system settings." - device: - panorama: true - ngfw: true + devices: + - panorama + - ngfw xpath: - - "config" - - "devices" - - "{{ Entry $ngfw_device }}" - - "deviceconfig" - - "system" - vars: - "ngfw_device": - description: "The NGFW device." - default: "localhost.localdomain" - "template": + path: + - "config" + - "devices" + - "$ngfw_device" + - "deviceconfig" + - "system" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "template" description: "Located in a specific template." - device: - panorama: true + devices: + - panorama xpath: - - "config" - - "devices" - - "{{ Entry $panorama_device }}" - - "template" - - "{{ Entry $template }}" - - "config" - - "devices" - - "{{ Entry $ngfw_device }}" - - "deviceconfig" - - "system" - vars: - "panorama_device": - description: "The panorama device." - default: "localhost.localdomain" - "template": - description: "The template." - required: true - "ngfw_device": - description: "The NGFW device." - default: "localhost.localdomain" - "template-stack": + path: + - "config" + - "devices" + - "$panorama_device" + - "template" + - "$template" + - "config" + - "devices" + - "$ngfw_device" + - "deviceconfig" + - "system" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template" + description: "The template." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "template-stack" description: "Located in a specific template stack." - device: - panorama: true + devices: + - panorama xpath: - - "config" - - "devices" - - "{{ Entry $panorama_device }}" - - "template-stack" - - "{{ Entry $template_stack }}" - - "config" - - "devices" - - "{{ Entry $ngfw_device }}" - - "deviceconfig" - - "system" - vars: - "panorama_device": - description: "The panorama device." - default: "localhost.localdomain" - "template_stack": - description: "The template stack." - required: true - "ngfw_device": - description: "The NGFW device." - default: "localhost.localdomain" + path: + - "config" + - "devices" + - "$panorama_device" + - "template-stack" + - "$template_stack" + - "config" + - "devices" + - "$ngfw_device" + - "deviceconfig" + - "system" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template_stack" + description: "The template stack." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" version: "10.1.0" spec: params: - ntp_servers: + - name: ntp_servers + type: object description: "NTP servers" profiles: - xpath: ["ntp-servers"] spec: params: - primary_ntp_server: + - name: primary_ntp_server + type: object description: "Primary NTP Server Information" profiles: - xpath: ["primary-ntp-server"] spec: params: - ntp_server_address: + - name: ntp_server_address + type: string description: "NTP Server IP Address or Domain Name" profiles: - xpath: ["ntp-server-address"] - authentication_type: + - name: authentication_type + type: object description: "NTP Authentication" profiles: - xpath: ["authentication-type"] spec: - one_of: - none: + variants: + - name: none + type: nil description: "No NTP Authentication" profiles: - xpath: ["none"] - symmetric_key: + - name: symmetric_key + type: object description: "Symmetric Key Authentication" profiles: - xpath: ["symmetric-key"] spec: params: - key_id: + - name: key_id description: "Symmetric Key Number" type: int64 - value: - min: 1 - max: 65534 + validators: + - type: range + spec: + min: 1 + max: 65534 profiles: - xpath: ["key-id"] - one_of: - md5: + variants: + - name: md5 + type: string profiles: - xpath: ["algorithm", "md5"] spec: params: - authentication_key: + - name: authentication_key + type: string description: "Symmetric Key MD5 String" - sensitive: true + codegen_overrides: + terraform: + sensitive: true hashing: type: solo - length: - min: 6 - max: 32 + validators: + - type: length + spec: + min: 6 + max: 32 profiles: - xpath: ["authentication-key"] - sha1: + - name: sha1 + type: string profiles: - xpath: ["algorithm", "sha1"] spec: params: - authentication_key: + - name: authentication_key + type: string description: "Symmetric Key SHA1 Hexadecimal" - sensitive: true - length: - min: 40 - max: 40 + codegen_overrides: + terraform: + sensitive: true hashing: type: solo + validators: + - type: length + spec: + min: 40 + max: 40 profiles: - xpath: ["authentication-key"] - autokey: + - name: autokey + type: string description: "Autokey Authentication" profiles: - xpath: ["autokey"] - secondary_ntp_server: + - name: secondary_ntp_server + type: object description: "Secondary NTP Server Information" profiles: - xpath: ["secondary-ntp-server"] spec: params: - ntp_server_address: + - name: ntp_server_address + type: string description: "NTP Server IP Address or Domain Name" profiles: - xpath: ["ntp-server-address"] - authentication_type: + - name: authentication_type + type: object description: "NTP Authentication" profiles: - xpath: ["authentication-type"] spec: - one_of: - none: + variants: + - name: none + type: nil description: "No NTP Authentication" profiles: - xpath: ["none"] - symmetric_key: + - name: symmetric_key + type: object description: "Symmetric Key Authentication" profiles: - xpath: ["symmetric-key"] spec: params: - key_id: + - name: key_id description: "Symmetric Key Number" type: int64 - value: - min: 1 - max: 65534 + validators: + - type: range + spec: + min: 1 + max: 65534 profiles: - xpath: ["key-id"] - one_of: - md5: + variants: + - name: md5 + type: string profiles: - xpath: ["algorithm/md5"] spec: params: - authentication_key: + - name: authentication_key + type: string description: "Symmetric Key MD5 String" - length: - min: 6 - max: 32 + validators: + - type: length + spec: + min: 6 + max: 32 profiles: - xpath: ["authentication-key"] - sha1: + - name: sha1 + type: string profiles: - xpath: ["algorithm/sha1"] spec: params: - authentication_key: + - name: authentication_key + type: string description: "Symmetric Key SHA1 Hexadecimal" - length: - min: 40 - max: 40 + validators: + - type: length + spec: + min: 40 + max: 40 profiles: - xpath: ["authentication-key"] - autokey: + - name: autokey + type: string description: "Autokey Authentication" profiles: - xpath: ["autokey"] diff --git a/specs/network/interface/ethernet.yaml b/specs/network/interface/ethernet.yaml index 9e554242..16b40785 100644 --- a/specs/network/interface/ethernet.yaml +++ b/specs/network/interface/ethernet.yaml @@ -1,246 +1,291 @@ name: "Ethernet interface" terraform_provider_config: suffix: "ethernet_interface" -go_sdk_path: - - "network" - - "interface" - - "ethernet" +go_sdk_config: + package: + - "network" + - "interface" + - "ethernet" xpath_suffix: - "network" - "interface" - "ethernet" locations: - "ngfw": + - name: "ngfw" description: "Located in a specific NGFW." - device: - panorama: false - ngfw: true + devices: + - panorama + - ngfw xpath: - - "config" - - "devices" - - "{{ Entry $ngfw_device }}" - vars: - "ngfw_device": - description: "The NGFW device." - default: "localhost.localdomain" - "template": + path: + - "config" + - "devices" + - "$ngfw_device" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "template" description: "Located in a specific template." - device: - panorama: true + devices: + - panorama xpath: - - "config" - - "devices" - - "{{ Entry $panorama_device }}" - - "template" - - "{{ Entry $template }}" - - "config" - - "devices" - - "{{ Entry $ngfw_device }}" - vars: - "panorama_device": - description: "The panorama device." - default: "localhost.localdomain" - "template": - description: "The template." - required: true - "ngfw_device": - description: "The NGFW device." - default: "localhost.localdomain" - "template-stack": + path: + - "config" + - "devices" + - "$panorama_device" + - "template" + - "$template" + - "config" + - "devices" + - "$ngfw_device" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template" + description: "The template." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "template-stack" description: "Located in a specific template stack." - device: - panorama: true + devices: + - panorama xpath: - - "config" - - "devices" - - "{{ Entry $panorama_device }}" - - "template-stack" - - "{{ Entry $template_stack }}" - - "config" - - "devices" - - "{{ Entry $ngfw_device }}" - vars: - "panorama_device": - description: "The panorama device." - default: "localhost.localdomain" - "template_stack": - description: "The template stack." - required: true - "ngfw_device": - description: "The NGFW device." - default: "localhost.localdomain" -entry: - name: + path: + - "config" + - "devices" + - "$panorama_device" + - "template-stack" + - "$template_stack" + - "config" + - "devices" + - "$ngfw_device" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template_stack" + description: "The template stack." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" +entries: + - name: name description: "The name of the ethernet interface." + validators: + - type: length + spec: + min: 10 + max: 20 imports: - "template": + - name: template xpath: - - "config" - - "devices" - - "{{ Entry $ngfw_device }}" - - "vsys" - - "{{ Entry $vsys }}" - - "import" - - "network" - - "interfaces" - vars: - "ngfw_device": - description: "The NGFW device." - default: "localhost.localdomain" - "vsys": - description: "The vsys." - default: "vsys1" + path: + - "config" + - "devices" + - "$ngfw_device" + - "vsys" + - "$vsys" + - "import" + - "network" + - "interfaces" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "vsys" + description: "The vsys." + default: "vsys1" only_for_params: - layer3 version: "10.1.0" spec: params: - comment: + - name: comment type: string - length: - min: 0 - max: 1023 + validators: + - type: length + spec: + min: 0 + max: 1023 profiles: - xpath: ["comment"] - link-state: - type: string - default: "auto" - values: ["auto", "up", "down"] + - name: link-state + type: enum profiles: - xpath: ["link-state"] - one_of: - tap: + validators: + - type: values + spec: + values: + - "auto" + - "up" + - "down" + spec: + values: + - value: "auto" + - value: "up" + - value: "down" + default: "auto" + variants: + - name: tap + type: object description: "Tap mode interface" profiles: - xpath: ["tap"] spec: params: - netflow-profile: + - name: netflow-profile type: string profiles: - xpath: ["netflow-profile"] - ha: + - name: ha + type: object description: "HA mode interface" profiles: - xpath: ["ha"] spec: - params: - layer3: + params: [] + - name: layer3 + type: object description: "Layer 3 interface" profiles: - xpath: ["layer3"] spec: params: - ndp-proxy: + - name: ndp-proxy type: bool profiles: - xpath: ["ndp-proxy", "enabled"] - lldp: + - name: lldp type: bool profiles: - xpath: ["lldp", "enable"] - mtu: + - name: mtu type: int64 description: "Maximum Transfer Unit, up to 9216 in Jumbo-Frame mode, up to 1500 otherwise" - value: - min: 576 - max: 9216 + validators: + - type: range + spec: + min: 576 + max: 9216 profiles: - xpath: ["mtu"] - ips: + - name: ips type: list description: "IP addresses or address objects names" - items: - type: string profiles: - type: entry xpath: ["ip"] - ipv6: + spec: + items: + type: string + - name: ipv6 + type: object profiles: - xpath: ["ipv6"] spec: params: - enabled: - type: bool - profiles: - - xpath: ["enabled"] - addresses: + - name: addresses type: list - items: - type: entry profiles: - type: entry xpath: ["address", "entry"] spec: - params: - enable-on-interface: - type: bool - profiles: - - xpath: ["enable-on-interface"] - dhcp-client: + items: + type: object + spec: + params: + - name: name + type: string + profiles: + - xpath: [] + spec: + required: true + - name: enable-on-interface + type: bool + profiles: + - xpath: ["enable-on-interface"] + - name: dhcp-client + type: object profiles: - xpath: ["dhcp-client"] spec: params: - enable: + - name: enable type: bool - default: true profiles: - xpath: ["enable"] - create-default-route: + spec: + default: true + - name: create-default-route type: bool - default: true + spec: + default: true profiles: - xpath: ["create-default-route"] - default-route-metric: + - name: default-route-metric type: int64 - default: 10 - value: - min: 1 - max: 65535 + spec: + default: 10 + validators: + - type: range + spec: + min: 1 + max: 65535 profiles: - xpath: ["default-route-metric"] - send-hostname: + - name: send-hostname + type: object profiles: - xpath: ["send-hostname"] spec: params: - enable: + - name: enable type: bool profiles: - xpath: ["enable"] - hostname: + - name: hostname type: string profiles: - xpath: ["hostname"] - interface-management-profile: + - name: interface-management-profile type: string profiles: - xpath: ["interface-management-profile"] - netflow-profile: + - name: netflow-profile type: string profiles: - xpath: ["netflow-profile"] - adjust-tcp-mss: + - name: adjust-tcp-mss + type: object profiles: - xpath: ["adjust-tcp-mss"] spec: params: - enable: + - name: enable type: bool profiles: - xpath: ["enable"] - ipv4-mss-adjustment: + - name: ipv4-mss-adjustment type: int64 - values: - min: 40 - max: 300 + validators: + - type: range + spec: + min: 40 + max: 300 profiles: - xpath: ["ipv4-mss-adjustment"] - ipv6-mss-adjustment: + - name: ipv6-mss-adjustment type: int64 - values: - min: 40 - max: 300 + validators: + - type: range + spec: + min: 40 + max: 300 profiles: - xpath: ["ipv6-mss-adjustment"] diff --git a/specs/network/interface/loopback.yaml b/specs/network/interface/loopback.yaml index 4f744865..48824cc4 100644 --- a/specs/network/interface/loopback.yaml +++ b/specs/network/interface/loopback.yaml @@ -1,154 +1,176 @@ -name: 'Loopback interface' +name: "Loopback interface" terraform_provider_config: - suffix: 'loopback_interface' -go_sdk_path: - - 'network' - - 'interface' - - 'loopback' + suffix: "loopback_interface" +go_sdk_config: + package: + - "network" + - "interface" + - "loopback" xpath_suffix: - - 'network' - - 'interface' - - 'loopback' - - 'units' + - "network" + - "interface" + - "loopback" + - "units" locations: - 'ngfw': - description: 'Located in a specific NGFW.' - device: - panorama: false - ngfw: true + - name: "ngfw" + description: "Located in a specific NGFW." + devices: + - panorama + - ngfw xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'template': - description: 'Located in a specific template.' - device: - panorama: true + path: + - "config" + - "devices" + - "$ngfw_device" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "template" + description: "Located in a specific template." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'template' - - '{{ Entry $template }}' - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'template': - description: 'The template.' - required: true - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'template-stack': - description: 'Located in a specific template stack.' - device: - panorama: true + path: + - "config" + - "devices" + - "$panorama_device" + - "template" + - "$template" + - "config" + - "devices" + - "$ngfw_device" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template" + description: "The template." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "template-stack" + description: "Located in a specific template stack." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'template-stack' - - '{{ Entry $template_stack }}' - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'template_stack': - description: 'The template stack.' - required: true - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' -entry: - name: - description: 'The name of the loopback interface.' -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + - "template-stack" + - "$template_stack" + - "config" + - "devices" + - "$ngfw_device" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template_stack" + description: "The template stack." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" +entries: + - name: name + description: "The name of the loopback interface." +version: "10.1.0" spec: params: - comment: + - name: comment type: string - length: - min: 0 - max: 1023 + validators: + - type: length + spec: + min: 0 + max: 1023 profiles: - - xpath: [ "comment" ] - mtu: + - xpath: ["comment"] + - name: mtu type: int64 description: "Maximum Transfer Unit, up to 9216 in Jumbo-Frame mode, up to 1500 otherwise" - value: - min: 576 - max: 9216 + validators: + - type: range + spec: + min: 576 + max: 9216 profiles: - - xpath: [ "mtu" ] - ips: + - xpath: ["mtu"] + - name: ips type: list description: "IP addresses or address objects names(netmask is not allowed for loopback)" - items: - type: string + spec: + items: + type: string profiles: - type: entry - xpath: [ "ip" ] - ipv6: + xpath: ["ip"] + - name: ipv6 + type: object profiles: - - xpath: [ "ipv6" ] + - xpath: ["ipv6"] spec: params: - enabled: + - name: enabled type: bool profiles: - - xpath: [ "enabled" ] - addresses: + - xpath: ["enabled"] + - name: addresses type: list - items: - type: entry profiles: - type: entry - xpath: [ "address", "entry" ] + xpath: ["address", "entry"] spec: - params: - enable-on-interface: - type: bool - profiles: - - xpath: [ "enable-on-interface" ] - interface-management-profile: + items: + type: object + spec: + params: + - name: name + type: string + profiles: + - xpath: [] + spec: + required: true + - name: enable-on-interface + type: bool + profiles: + - xpath: ["enable-on-interface"] + - name: interface-management-profile type: string profiles: - - xpath: [ "interface-management-profile" ] - netflow-profile: + - xpath: ["interface-management-profile"] + - name: netflow-profile type: string profiles: - - xpath: [ "netflow-profile" ] - adjust-tcp-mss: + - xpath: ["netflow-profile"] + - name: adjust-tcp-mss + type: object profiles: - - xpath: [ "adjust-tcp-mss" ] + - xpath: ["adjust-tcp-mss"] spec: params: - enable: + - name: enable type: bool profiles: - - xpath: [ "enable" ] - ipv4-mss-adjustment: + - xpath: ["enable"] + - name: ipv4-mss-adjustment type: int64 - values: - min: 40 - max: 300 + validators: + - type: range + spec: + min: 40 + max: 300 profiles: - - xpath: [ "ipv4-mss-adjustment" ] - ipv6-mss-adjustment: + - xpath: ["ipv4-mss-adjustment"] + - name: ipv6-mss-adjustment type: int64 - values: - min: 40 - max: 300 + validators: + - type: range + spec: + min: 40 + max: 300 profiles: - - xpath: [ "ipv6-mss-adjustment" ] + - xpath: ["ipv6-mss-adjustment"] diff --git a/specs/network/profiles/interface-management-profile.yaml b/specs/network/profiles/interface-management-profile.yaml index 18845ac5..5aa59002 100644 --- a/specs/network/profiles/interface-management-profile.yaml +++ b/specs/network/profiles/interface-management-profile.yaml @@ -1,128 +1,133 @@ -name: 'Interface management profile' +name: "Interface management profile" terraform_provider_config: - suffix: 'interface_management_profile' -go_sdk_path: - - 'network' - - 'profiles' - - 'interface_management' + suffix: "interface_management_profile" +go_sdk_config: + package: + - "network" + - "profiles" + - "interface_management" xpath_suffix: - - 'network' - - 'profiles' - - 'interface-management-profile' + - "network" + - "profiles" + - "interface-management-profile" locations: - 'ngfw': - description: 'Located in a specific NGFW.' - device: - panorama: false - ngfw: true + - name: "ngfw" + description: "Located in a specific NGFW." + devices: + - panorama + - ngfw xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'template': - description: 'Located in a specific template.' - device: - panorama: true + path: + - "config" + - "devices" + - "$ngfw_device" + vars: + - name: ngfw_device + description: "The NGFW device." + default: "localhost.localdomain" + - name: "template" + description: "Located in a specific template." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'template' - - '{{ Entry $template }}' - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'template': - description: 'The template.' - required: true - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'template-stack': - description: 'Located in a specific template stack.' - device: - panorama: true + path: + - "config" + - "devices" + - "$panorama_device" + - "template" + - "$template" + - "config" + - "devices" + - "$ngfw_device" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template" + description: "The template." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "template-stack" + description: "Located in a specific template stack." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'template-stack' - - '{{ Entry $template_stack }}' - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'template_stack': - description: 'The template stack.' - required: true - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' -entry: - name: - description: 'The name of the interface management profile.' -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + - "template-stack" + - "$template_stack" + - "config" + - "devices" + - "$ngfw_device" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template_stack" + description: "The template stack." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" +entries: + - name: name + description: "The name of the interface management profile." +version: "10.1.0" spec: params: - http: + - name: http type: bool profiles: - - xpath: [ "http" ] - https: + - xpath: ["http"] + - name: https type: bool profiles: - - xpath: [ "https" ] - ping: + - xpath: ["https"] + - name: ping type: bool profiles: - - xpath: [ "ping" ] - response-pages: + - xpath: ["ping"] + - name: response-pages type: bool profiles: - - xpath: [ "response-pages" ] - userid-service: + - xpath: ["response-pages"] + - name: userid-service type: bool profiles: - - xpath: [ "userid-service" ] - userid-syslog-listener-ssl: + - xpath: ["userid-service"] + - name: userid-syslog-listener-ssl type: bool profiles: - - xpath: [ "userid-syslog-listener-ssl" ] - userid-syslog-listener-udp: + - xpath: ["userid-syslog-listener-ssl"] + - name: userid-syslog-listener-udp type: bool profiles: - - xpath: [ "userid-syslog-listener-udp" ] - ssh: + - xpath: ["userid-syslog-listener-udp"] + - name: ssh type: bool profiles: - - xpath: [ "ssh" ] - telnet: + - xpath: ["ssh"] + - name: telnet type: bool profiles: - - xpath: [ "telnet" ] - snmp: + - xpath: ["telnet"] + - name: snmp type: bool profiles: - - xpath: [ "snmp" ] - http-ocsp: + - xpath: ["snmp"] + - name: http-ocsp type: bool profiles: - - xpath: [ "http-ocsp" ] - permitted-ips: + - xpath: ["http-ocsp"] + - name: permitted-ips type: list - items: - type: string + spec: + items: + type: string profiles: - type: entry - xpath: [ "permitted-ip" ] + xpath: ["permitted-ip"] diff --git a/specs/network/virtual-router.yaml b/specs/network/virtual-router.yaml index 6d98ab58..66fa09f5 100644 --- a/specs/network/virtual-router.yaml +++ b/specs/network/virtual-router.yaml @@ -1,395 +1,453 @@ -name: 'Virtual router' +name: "Virtual router" terraform_provider_config: - suffix: 'virtual_router' -go_sdk_path: - - 'network' - - 'virtual_router' + suffix: "virtual_router" +go_sdk_config: + package: + - "network" + - "virtual_router" xpath_suffix: - - 'network' - - 'virtual-router' + - "network" + - "virtual-router" locations: - 'ngfw': - description: 'Located in a specific NGFW.' - device: - panorama: false - ngfw: true + - name: "ngfw" + description: "Located in a specific NGFW." + devices: + - panorama + - ngfw xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'template': - description: 'Located in a specific template.' - device: - panorama: true + path: + - "config" + - "devices" + - "$ngfw_device" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "template" + description: "Located in a specific template." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'template' - - '{{ Entry $template }}' - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'template': - description: 'The template.' - required: true - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'template-stack': - description: 'Located in a specific template stack.' - device: - panorama: true + path: + - "config" + - "devices" + - "$panorama_device" + - "template" + - "$template" + - "config" + - "devices" + - "$ngfw_device" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template" + description: "The template." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "template-stack" + description: "Located in a specific template stack." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'template-stack' - - '{{ Entry $template_stack }}' - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'template_stack': - description: 'The template stack.' - required: true - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' -entry: - name: - description: 'The name of the virtual router.' -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + - "template-stack" + - "$template_stack" + - "config" + - "devices" + - "$ngfw_device" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template_stack" + description: "The template stack." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" +entries: + - name: name + description: "The name of the virtual router." +version: "10.1.0" spec: params: - interfaces: + - name: interfaces type: list - items: - type: string + spec: + items: + type: string profiles: - - xpath: [ "interface" ] + - xpath: ["interface"] type: member - routing-table: + - name: routing-table + type: object profiles: - - xpath: [ "routing-table" ] + - xpath: ["routing-table"] spec: params: - ip: + - name: ip + type: object profiles: - - xpath: [ "ip" ] + - xpath: ["ip"] spec: params: - static-routes: + - name: static-routes type: list - items: - type: entry profiles: - - xpath: [ "static-route", "entry" ] + - xpath: ["static-route", "entry"] type: entry spec: - params: - destination: - type: string - profiles: - - xpath: [ "destination" ] - interface: - type: string - profiles: - - xpath: [ "interface" ] - next-hop: - profiles: - - xpath: [ "nexthop" ] - spec: - params: - ip-address: - type: string - profiles: - - xpath: [ "ip-address" ] - fqdn: - type: string - profiles: - - xpath: [ "fqdn" ] - next-vr: - type: string - profiles: - - xpath: [ "next-vr" ] - tunnel: - type: string - profiles: - - xpath: [ "tunnel" ] - admin-dist: - type: int64 - profiles: - - xpath: [ "admin-dist" ] - metric: - type: int64 - profiles: - - xpath: [ "metric" ] - route-table: - type: string - profiles: - - xpath: [ "route-table" ] - ipv6: + items: + type: object + spec: + params: + - name: destination + type: string + profiles: + - xpath: ["destination"] + - name: interface + type: string + profiles: + - xpath: ["interface"] + - name: next-hop + type: object + profiles: + - xpath: ["nexthop"] + spec: + params: + - name: ip-address + type: string + profiles: + - xpath: ["ip-address"] + - name: fqdn + type: string + profiles: + - xpath: ["fqdn"] + - name: next-vr + type: string + profiles: + - xpath: ["next-vr"] + - name: tunnel + type: string + profiles: + - xpath: ["tunnel"] + - name: admin-dist + type: int64 + profiles: + - xpath: ["admin-dist"] + - name: metric + type: int64 + profiles: + - xpath: ["metric"] + - name: route-table + type: string + profiles: + - xpath: ["route-table"] + - name: ipv6 + type: object profiles: - - xpath: [ "ipv6" ] + - xpath: ["ipv6"] spec: params: - static-routes: + - name: static-routes type: list - items: - type: entry profiles: - - xpath: [ "static-route", "entry" ] + - xpath: ["static-route", "entry"] type: entry spec: - params: - destination: - type: string - profiles: - - xpath: [ "destination" ] - interface: - type: string - profiles: - - xpath: [ "interface" ] - next-hop: - profiles: - - xpath: [ "nexthop" ] - spec: - params: - ipv6-address: - type: string - profiles: - - xpath: [ "ipv6-address" ] - fqdn: - type: string - profiles: - - xpath: [ "fqdn" ] - next-vr: - type: string - profiles: - - xpath: [ "next-vr" ] - tunnel: - type: string - profiles: - - xpath: [ "tunnel" ] - admin-dist: - type: int64 - profiles: - - xpath: [ "admin-dist" ] - metric: - type: int64 - profiles: - - xpath: [ "metric" ] - route-table: - type: string - profiles: - - xpath: [ "route-table" ] - protocol: + items: + type: object + spec: + params: + - name: destination + type: string + profiles: + - xpath: ["destination"] + - name: interface + type: string + profiles: + - xpath: ["interface"] + - name: next-hop + type: object + profiles: + - xpath: ["nexthop"] + spec: + params: + - name: ipv6-address + type: string + profiles: + - xpath: ["ipv6-address"] + - name: fqdn + type: string + profiles: + - xpath: ["fqdn"] + - name: next-vr + type: string + profiles: + - xpath: ["next-vr"] + - name: tunnel + type: string + profiles: + - xpath: ["tunnel"] + - name: admin-dist + type: int64 + profiles: + - xpath: ["admin-dist"] + - name: metric + type: int64 + profiles: + - xpath: ["metric"] + - name: route-table + type: string + profiles: + - xpath: ["route-table"] + - name: protocol + type: object profiles: - - xpath: [ "protocol" ] + - xpath: ["protocol"] spec: params: - bgp: + - name: bgp + type: object profiles: - - xpath: [ "bgp" ] + - xpath: ["bgp"] spec: params: - enable: + - name: enable type: bool profiles: - - xpath: [ "enable" ] - rip: + - xpath: ["enable"] + - name: rip + type: object profiles: - - xpath: [ "rip" ] + - xpath: ["rip"] spec: params: - enable: + - name: enable type: bool profiles: - - xpath: [ "enable" ] - ospf: + - xpath: ["enable"] + - name: ospf + type: object profiles: - - xpath: [ "ospf" ] + - xpath: ["ospf"] spec: params: - enable: + - name: enable type: bool profiles: - - xpath: [ "enable" ] - ospfv3: + - xpath: ["enable"] + - name: ospfv3 + type: object profiles: - - xpath: [ "ospfv3" ] + - xpath: ["ospfv3"] spec: params: - enable: + - name: enable type: bool profiles: - - xpath: [ "enable" ] - ecmp: + - xpath: ["enable"] + - name: ecmp + type: object profiles: - - xpath: [ "ecmp" ] + - xpath: ["ecmp"] spec: params: - enable: + - name: enable type: bool profiles: - - xpath: [ "enable" ] - symmetric-return: + - xpath: ["enable"] + - name: symmetric-return type: bool profiles: - - xpath: [ "symmetric-return" ] - strict-source-path: + - xpath: ["symmetric-return"] + - name: strict-source-path type: bool profiles: - - xpath: [ "strict-source-path" ] - max-paths: + - xpath: ["strict-source-path"] + - name: max-paths type: int64 - value: - min: 2 - max: 4 + validators: + - type: range + spec: + min: 2 + max: 4 profiles: - - xpath: [ "max-path" ] - algorithm: + - xpath: ["max-path"] + - name: algorithm + type: object profiles: - - xpath: [ "algorithm" ] + - xpath: ["algorithm"] spec: params: - ip-modulo: + - name: ip-modulo + type: object profiles: - - xpath: [ "ip-modulo" ] + - xpath: ["ip-modulo"] spec: - params: - ip-hash: + params: [] + - name: ip-hash + type: object profiles: - - xpath: [ "ip-hash" ] + - xpath: ["ip-hash"] spec: params: - src-only: + - name: src-only type: bool profiles: - - xpath: [ "src-only" ] - use-port: + - xpath: ["src-only"] + - name: use-port type: bool profiles: - - xpath: [ "use-port" ] - hash-seed: + - xpath: ["use-port"] + - name: hash-seed type: int64 - value: - min: 0 - max: 4294967295 + validators: + - type: range + spec: + min: 0 + max: 4294967295 profiles: - - xpath: [ "hash-seed" ] - weighted-round-robin: + - xpath: ["hash-seed"] + - name: weighted-round-robin + type: object profiles: - - xpath: [ "weighted-round-robin" ] + - xpath: ["weighted-round-robin"] spec: params: - interfaces: + - name: interfaces type: list - items: - type: entry profiles: - - xpath: [ "interface", "entry" ] + - xpath: ["interface", "entry"] type: entry spec: - params: - weight: - type: int64 - value: - min: 1 - max: 255 - profiles: - - xpath: [ "weight" ] - balanced-round-robin: + items: + type: object + spec: + params: + - name: weight + type: int64 + validators: + - type: range + spec: + min: 1 + max: 255 + profiles: + - xpath: ["weight"] + - name: balanced-round-robin + type: object profiles: - - xpath: [ "balanced-round-robin" ] + - xpath: ["balanced-round-robin"] spec: - params: - administrative-distances: + params: [] + - name: administrative-distances + type: object profiles: - - xpath: [ "admin-dists" ] + - xpath: ["admin-dists"] spec: params: - static: + - name: static type: int64 - default: 10 - value: - min: 10 - max: 240 + spec: + default: 10 + validators: + - type: range + spec: + min: 10 + max: 240 profiles: - - xpath: [ "static" ] - static-ipv6: + - xpath: ["static"] + - name: static-ipv6 type: int64 - default: 10 - value: - min: 10 - max: 240 + spec: + default: 10 + validators: + - type: range + spec: + min: 10 + max: 240 profiles: - - xpath: [ "static-ipv6" ] - ospf-int: + - xpath: ["static-ipv6"] + - name: ospf-int type: int64 - default: 30 - value: - min: 10 - max: 240 + spec: + default: 30 + validators: + - type: range + spec: + min: 10 + max: 240 profiles: - - xpath: [ "ospf-int" ] - ospf-ext: + - xpath: ["ospf-int"] + - name: ospf-ext type: int64 - default: 110 - value: - min: 10 - max: 240 + spec: + default: 110 + validators: + - type: range + spec: + min: 10 + max: 240 profiles: - - xpath: [ "ospf-ext" ] - ospfv3-int: + - xpath: ["ospf-ext"] + - name: ospfv3-int type: int64 - default: 30 - value: - min: 10 - max: 240 + spec: + default: 30 + validators: + - type: range + spec: + min: 10 + max: 240 profiles: - - xpath: [ "ospfv3-int" ] - ospfv3-ext: + - xpath: ["ospfv3-int"] + - name: ospfv3-ext type: int64 - default: 110 - value: - min: 10 - max: 240 + spec: + default: 110 + validators: + - type: range + spec: + min: 10 + max: 240 profiles: - - xpath: [ "ospfv3-ext" ] - ibgp: + - xpath: ["ospfv3-ext"] + - name: ibgp type: int64 - default: 200 - value: - min: 10 - max: 240 + spec: + default: 200 + validators: + - type: range + spec: + min: 10 + max: 240 profiles: - - xpath: [ "ibgp" ] - ebgp: + - xpath: ["ibgp"] + - name: ebgp type: int64 - default: 20 - value: - min: 10 - max: 240 + spec: + default: 20 + validators: + - type: range + spec: + min: 10 + max: 240 profiles: - - xpath: [ "ebgp" ] - rip: + - xpath: ["ebgp"] + - name: rip type: int64 - default: 120 - value: - min: 10 - max: 240 + spec: + default: 120 + validators: + - type: range + spec: + min: 10 + max: 240 profiles: - - xpath: [ "rip" ] + - xpath: ["rip"] diff --git a/specs/network/zone.yaml b/specs/network/zone.yaml index fe50559e..f118385b 100644 --- a/specs/network/zone.yaml +++ b/specs/network/zone.yaml @@ -1,214 +1,245 @@ -name: 'Zone' +name: "Zone" terraform_provider_config: - suffix: 'zone' -go_sdk_path: - - 'network' - - 'zone' + suffix: "zone" +go_sdk_config: + package: + - "network" + - "zone" xpath_suffix: - - 'zone' + - "zone" locations: - 'vsys': - description: 'Located in a specific vsys.' - device: - panorama: false - ngfw: true + - name: "vsys" + description: "Located in a specific vsys." + devices: + - panorama + - ngfw xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'from_panorama_vsys': - description: 'Located in a specific vsys in the config pushed from Panorama.' + path: + - "config" + - "devices" + - "$ngfw_device" + - "vsys" + - "$vsys" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: shared + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "from_panorama_vsys" + description: "Located in a specific vsys in the config pushed from Panorama." read_only: true - device: - ngfw: true + devices: + - ngfw xpath: - - 'config' - - 'panorama' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'template': - description: 'Located in a specific template.' - device: - panorama: true + path: + - "config" + - "panorama" + - "vsys" + - "$vsys" + vars: + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "template" + description: "Located in a specific template." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'template' - - '{{ Entry $template }}' - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'template': - description: 'The template.' - required: true - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'template-stack': - description: 'Located in a specific template stack.' - device: - panorama: true + path: + - "config" + - "devices" + - "$panorama_device" + - "template" + - "$template" + - "config" + - "devices" + - "$ngfw_device" + - "vsys" + - "$vsys" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template" + description: "The template." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "template-stack" + description: "Located in a specific template stack." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'template-stack' - - '{{ Entry $template_stack }}' - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'template_stack': - description: 'The template stack.' - required: true - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' -entry: - name: - description: 'The name of the zone.' -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + - "template-stack" + - "$template_stack" + - "config" + - "devices" + - "$ngfw_device" + - "vsys" + - "$vsys" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "template_stack" + description: "The template stack." + required: true + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' +entries: + - name: name + description: "The name of the zone." +version: "10.1.0" spec: params: - enable-user-identification: + - name: enable-user-identification type: bool profiles: - - xpath: [ "enable-user-identification" ] - enable-device-identification: + - xpath: ["enable-user-identification"] + - name: enable-device-identification type: bool profiles: - - xpath: [ "enable-device-identification" ] - user-acl: + - xpath: ["enable-device-identification"] + - name: user-acl + type: object profiles: - - xpath: [ "user-acl" ] + - xpath: ["user-acl"] spec: params: - include-list: + - name: include-list type: list - items: - type: string + spec: + items: + type: string profiles: - - xpath: [ "include-list" ] + - xpath: ["include-list"] type: member - exclude-list: + - name: exclude-list type: list - items: - type: string + spec: + items: + type: string profiles: - - xpath: [ "exclude-list" ] + - xpath: ["exclude-list"] type: member - device-acl: + - name: device-acl + type: object profiles: - - xpath: [ "device-acl" ] + - xpath: ["device-acl"] spec: params: - include-list: + - name: include-list type: list - items: - type: string + spec: + items: + type: string profiles: - - xpath: [ "include-list" ] + - xpath: ["include-list"] type: member - exclude-list: + - name: exclude-list type: list - items: - type: string + spec: + items: + type: string profiles: - - xpath: [ "exclude-list" ] + - xpath: ["exclude-list"] type: member - network: + - name: network + type: object profiles: - - xpath: [ "network" ] + - xpath: ["network"] spec: params: - enable-packet-buffer-protection: + - name: enable-packet-buffer-protection type: bool - default: true + spec: + default: true profiles: - - xpath: [ "enable-packet-buffer-protection" ] - zone-protection-profile: + - xpath: ["enable-packet-buffer-protection"] + - name: zone-protection-profile type: list - items: - type: string + spec: + items: + type: string profiles: - - xpath: [ "zone-protection-profile" ] + - xpath: ["zone-protection-profile"] type: member - log-setting: + - name: log-setting type: list - items: - type: string + spec: + items: + type: string profiles: - - xpath: [ "log-setting" ] + - xpath: ["log-setting"] type: member - one_of: - layer3: + variants: + - name: layer3 type: list - items: - type: string + spec: + items: + type: string profiles: - - xpath: [ "layer3" ] + - xpath: ["layer3"] type: member - layer2: + - name: layer2 type: list - items: - type: string + spec: + items: + type: string profiles: - - xpath: [ "layer2" ] + - xpath: ["layer2"] type: member - virtual-wire: + - name: virtual-wire type: list - items: - type: string + spec: + items: + type: string profiles: - - xpath: [ "virtual-wire" ] + - xpath: ["virtual-wire"] type: member - tap: + - name: tap type: list - items: - type: string + spec: + items: + type: string profiles: - - xpath: [ "tap" ] + - xpath: ["tap"] type: member diff --git a/specs/objects/address-group.yaml b/specs/objects/address-group.yaml index 3e7611c1..52f4603b 100644 --- a/specs/objects/address-group.yaml +++ b/specs/objects/address-group.yaml @@ -1,131 +1,158 @@ -name: 'Address group' +name: "Address group" terraform_provider_config: - suffix: 'address_group' -go_sdk_path: - - 'objects' - - 'address' - - 'group' + suffix: "address_group" +go_sdk_config: + package: + - "objects" + - "address" + - "group" xpath_suffix: - - 'address-group' + - "address-group" locations: - 'shared': - description: 'Located in shared.' - device: - panorama: true - ngfw: true - xpath: ['config', 'shared'] - 'vsys': - description: 'Located in a specific vsys.' - device: - panorama: true - ngfw: true + - name: "shared" + description: "Located in shared." + devices: + - panorama + - ngfw xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'from_panorama_shared': - description: 'Located in shared in the config pushed from Panorama.' + path: ["config", "shared"] + - name: "vsys" + description: "Located in a specific vsys." + devices: + - panorama + - ngfw + xpath: + path: + - "config" + - "devices" + - "$ngfw_device" + - "vsys" + - "$vsys" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "from_panorama_shared" + description: "Located in shared in the config pushed from Panorama." read_only: true - device: - ngfw: true + devices: + - ngfw xpath: - - 'config' - - 'panorama' - - 'shared' - 'from_panorama_vsys': - description: 'Located in a specific vsys in the config pushed from Panorama.' + path: + - "config" + - "panorama" + - "shared" + - name: "from_panorama_vsys" + description: "Located in a specific vsys in the config pushed from Panorama." read_only: true - device: - ngfw: true + devices: + - ngfw xpath: - - 'config' - - 'panorama' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'device_group': - description: 'Located in a specific device group.' - device: - panorama: true + path: + - "config" + - "panorama" + - "vsys" + - "$vsys" + vars: + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "device_group" + description: "Located in a specific device group." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'device-group' - - '{{ Entry $device_group }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'device_group': - description: 'The device group.' - required: true - validation: - not_values: - 'shared': 'The device group cannot be "shared". Use the "shared" path instead.' -entry: - name: - description: 'The name of the address group.' - length: - min: 1 - max: 63 -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + - "device-group" + - "$device_group" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "device_group" + description: "The device group." + required: true + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The device group cannot be "shared". Use the "shared" path instead.' +entries: + - name: name + description: "The name of the address group." + validators: + - type: length + spec: + min: 1 + max: 63 +version: "10.1.0" spec: params: - description: - description: 'The description.' + - name: description + description: "The description." type: string - length: - min: 0 - max: 1023 profiles: - - - xpath: ["description"] - tags: - description: 'The administrative tags.' + - xpath: ["description"] + validators: + - type: length + spec: + min: 0 + max: 1023 + - name: tags + description: "The administrative tags." type: list - count: - max: 64 - items: - type: string - length: - max: 127 profiles: - - - type: member + - type: member xpath: ["tag"] - one_of: - 'static': + validators: + - type: count + spec: + max: 64 + spec: + items: + type: string + validators: + - type: length + spec: + max: 127 + variants: + - name: "static" type: list - count: - min: 1 - items: - type: string profiles: - - xpath: [ "static" ] + - xpath: ["static"] type: member - 'dynamic': - length: - min: 1 - max: 2047 + validators: + - type: count + spec: + min: 1 + spec: + items: + type: string + - name: "dynamic" + type: string # FIXME: the original spec made no sense + validators: + - type: length + spec: + min: 1 + max: 2047 profiles: - - - xpath: ["dynamic/filter"] + - xpath: ["dynamic", "filter"] # FIXME: original xpath dynamic/filter made no sense diff --git a/specs/objects/address.yaml b/specs/objects/address.yaml index dde1244a..96ba445c 100644 --- a/specs/objects/address.yaml +++ b/specs/objects/address.yaml @@ -1,138 +1,164 @@ -name: 'Address' +name: "Address" terraform_provider_config: - suffix: 'address_object' -go_sdk_path: - - 'objects' - - 'address' + suffix: "address_object" +go_sdk_config: + package: + - "objects" + - "address" xpath_suffix: - - 'address' + - "address" locations: - 'shared': - description: 'Located in shared.' - device: - panorama: true - ngfw: true - xpath: ['config', 'shared'] - 'vsys': - description: 'Located in a specific vsys.' - device: - panorama: true - ngfw: true + - name: "shared" + description: "Located in shared." + devices: + - panorama + - ngfw xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'from_panorama_shared': - description: 'Located in shared in the config pushed from Panorama.' + path: ["config", "shared"] + - name: "vsys" + description: "Located in a specific vsys." + devices: + - panorama + - ngfw + xpath: + path: + - "config" + - "devices" + - "$ngfw_device" + - "vsys" + - "$vsys" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: invalid + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "from_panorama_shared" + description: "Located in shared in the config pushed from Panorama." read_only: true - device: - ngfw: true + devices: + - ngfw xpath: - - 'config' - - 'panorama' - - 'shared' - 'from_panorama_vsys': - description: 'Located in a specific vsys in the config pushed from Panorama.' + path: + - "config" + - "panorama" + - "shared" + - name: "from_panorama_vsys" + description: "Located in a specific vsys in the config pushed from Panorama." read_only: true - device: - ngfw: true + devices: + - ngfw xpath: - - 'config' - - 'panorama' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'device_group': - description: 'Located in a specific device group.' - device: - panorama: true + path: + - "config" + - "panorama" + - "vsys" + - "$vsys" + vars: + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "device_group" + description: "Located in a specific device group." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'device-group' - - '{{ Entry $device_group }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'device_group': - description: 'The device group.' - required: true - validation: - not_values: - 'shared': 'The device group cannot be "shared". Use the "shared" path instead.' -entry: - name: - description: 'The name of the address object.' - length: - min: 1 - max: 63 -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + - "device-group" + - "$device_group" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "device_group" + description: "The device group." + required: true + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The device group cannot be "shared". Use the "shared" path instead.' +entries: + - name: name + description: "The name of the address object." + validators: + - type: length + spec: + min: 1 + max: 63 +version: "10.1.0" spec: params: - description: - description: 'The description.' + - name: description + description: "The description." type: string - length: - min: 0 - max: 1023 + validators: + - type: length + spec: + min: 0 + max: 1023 profiles: - - - xpath: ["description"] - tags: - description: 'The administrative tags.' + - xpath: ["description"] + - name: tags + description: "The administrative tags." type: list - count: - max: 64 - items: - type: string - length: - max: 127 + validators: + - type: count + spec: + max: 64 + spec: + items: + type: string + validators: + - type: length + spec: + max: 127 profiles: - - - type: member + - type: member xpath: ["tag"] - one_of: - 'ip_netmask': - description: 'The IP netmask value.' + variants: + - name: "ip_netmask" + type: string + description: "The IP netmask value." profiles: - - - xpath: ["ip-netmask"] - 'ip_range': - description: 'The IP range value.' + - xpath: ["ip-netmask"] + - name: "ip_range" + type: string + description: "The IP range value." profiles: - - - xpath: ["ip-range"] - 'fqdn': - description: 'The FQDN value.' - regex: '^[a-zA-Z0-9_]([a-zA-Z0-9:_-])+[a-zA-Z0-9]$' - length: - min: 1 - max: 255 + - xpath: ["ip-range"] + - name: "fqdn" + type: string + description: "The FQDN value." + validators: + - type: regexp + spec: + expr: "^[a-zA-Z0-9_]([a-zA-Z0-9:_-])+[a-zA-Z0-9]$" + - type: length + spec: + min: 1 + max: 255 profiles: - - - xpath: ["fqdn"] - 'ip_wildcard': - description: 'The IP wildcard value.' + - xpath: ["fqdn"] + - name: "ip_wildcard" + type: string + description: "The IP wildcard value." profiles: - - - xpath: ["ip-wildcard"] + - xpath: ["ip-wildcard"] diff --git a/specs/objects/service-group.yaml b/specs/objects/service-group.yaml index ad676067..c1f3e1c2 100644 --- a/specs/objects/service-group.yaml +++ b/specs/objects/service-group.yaml @@ -1,124 +1,149 @@ -name: 'Service group' +name: "Service group" terraform_provider_config: - suffix: 'service_group' -go_sdk_path: - - 'objects' - - 'service' - - 'group' + suffix: "service_group" +go_sdk_config: + package: + - "objects" + - "service" + - "group" xpath_suffix: - - 'service-group' + - "service-group" locations: - 'shared': - description: 'Located in shared.' - device: - panorama: true - ngfw: true - xpath: ['config', 'shared'] - 'vsys': - description: 'Located in a specific vsys.' - device: - panorama: true - ngfw: true + - name: "shared" + description: "Located in shared." + devices: + - panorama + - ngfw xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'from_panorama_shared': - description: 'Located in shared in the config pushed from Panorama.' + path: ["config", "shared"] + - name: "vsys" + description: "Located in a specific vsys." + devices: + - panorama + - ngfw + xpath: + path: + - "config" + - "devices" + - "$ngfw_device" + - "vsys" + - "$vsys" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "from_panorama_shared" + description: "Located in shared in the config pushed from Panorama." read_only: true - device: - ngfw: true + devices: + - ngfw xpath: - - 'config' - - 'panorama' - - 'shared' - 'from_panorama_vsys': - description: 'Located in a specific vsys in the config pushed from Panorama.' + path: + - "config" + - "panorama" + - "shared" + - name: "from_panorama_vsys" + description: "Located in a specific vsys in the config pushed from Panorama." read_only: true - device: - ngfw: true + devices: + - ngfw xpath: - - 'config' - - 'panorama' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'device_group': - description: 'Located in a specific device group.' - device: - panorama: true + path: + - "config" + - "panorama" + - "vsys" + - "$vsys" + vars: + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "device_group" + description: "Located in a specific device group." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'device-group' - - '{{ Entry $device_group }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'device_group': - description: 'The device group.' - required: true - validation: - not_values: - 'shared': 'The device group cannot be "shared". Use the "shared" path instead.' -entry: - name: - description: 'The name of the service group.' - length: - min: 1 - max: 63 -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + - "device-group" + - "$device_group" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "device_group" + description: "The device group." + required: true + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The device group cannot be "shared". Use the "shared" path instead.' +entries: + - name: name + description: "The name of the service." + validators: + - type: length + spec: + min: 1 + max: 63 +version: "10.1.0" spec: params: - description: - description: 'The description.' + - name: description + description: "The description." type: string - length: - min: 0 - max: 1023 + validators: + - type: length + spec: + min: 0 + max: 1023 profiles: - - - xpath: ["description"] - members: - description: 'Service group members.' + - xpath: ["description"] + - name: members + description: "Service group members." type: list - count: - max: 63 - items: - type: string + validators: + - type: count + spec: + max: 63 + spec: + items: + type: string profiles: - - xpath: [ "members" ] + - xpath: ["members"] type: member - tags: - description: 'The administrative tags.' + - name: tags + description: "The administrative tags." type: list - count: - max: 64 - items: - type: string - length: - max: 127 + validators: + - type: count + spec: + max: 64 + spec: + items: + type: string + validators: + - type: length + spec: + max: 127 profiles: - - - type: member + - type: member xpath: ["tag"] diff --git a/specs/objects/service.yaml b/specs/objects/service.yaml index ac23d1a5..72700fd7 100644 --- a/specs/objects/service.yaml +++ b/specs/objects/service.yaml @@ -1,206 +1,240 @@ -name: 'Service' +name: "Service" terraform_provider_config: - suffix: 'service_object' -go_sdk_path: - - 'objects' - - 'service' + suffix: "service_object" +go_sdk_config: + package: + - "objects" + - "service" xpath_suffix: - - 'service' + - "service" locations: - 'shared': - description: 'Located in shared.' - device: - panorama: true - ngfw: true - xpath: ['config', 'shared'] - 'vsys': - description: 'Located in a specific vsys.' - device: - panorama: true - ngfw: true + - name: "shared" + description: "Located in shared." + devices: + - panorama + - ngfw xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'from_panorama_shared': - description: 'Located in shared in the config pushed from Panorama.' + path: ["config", "shared"] + - name: "vsys" + description: "Located in a specific vsys." + devices: + - panorama + - ngfw + xpath: + path: + - "config" + - "devices" + - "$ngfw_device" + - "vsys" + - "$vsys" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "from_panorama_shared" + description: "Located in shared in the config pushed from Panorama." read_only: true - device: - ngfw: true + devices: + - ngfw xpath: - - 'config' - - 'panorama' - - 'shared' - 'from_panorama_vsys': - description: 'Located in a specific vsys in the config pushed from Panorama.' + path: + - "config" + - "panorama" + - "shared" + - name: "from_panorama_vsys" + description: "Located in a specific vsys in the config pushed from Panorama." read_only: true - device: - ngfw: true + devices: + - ngfw xpath: - - 'config' - - 'panorama' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'device_group': - description: 'Located in a specific device group.' - device: - panorama: true + path: + - "config" + - "panorama" + - "vsys" + - "$vsys" + vars: + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "device_group" + description: "Located in a specific device group." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'device-group' - - '{{ Entry $device_group }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'device_group': - description: 'The device group.' - required: true - validation: - not_values: - 'shared': 'The device group cannot be "shared". Use the "shared" path instead.' -entry: - name: - description: 'The name of the service.' - length: - min: 1 - max: 63 -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + - "device-group" + - "$device_group" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "device_group" + description: "The device group." + required: true + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The device group cannot be "shared". Use the "shared" path instead.' +entries: + - name: name + description: "The name of the service." + validators: + - type: length + spec: + min: 1 + max: 63 +version: "10.1.0" spec: params: - description: - description: 'The description.' + - name: description + description: "The description." type: string - length: - min: 0 - max: 1023 + validators: + - type: length + spec: + min: 0 + max: 1023 profiles: - - - xpath: ["description"] - tags: - description: 'The administrative tags.' + - xpath: ["description"] + - name: tags + description: "The administrative tags." type: list - count: - max: 64 - items: - type: string - length: - max: 127 profiles: - - - type: member + - type: member xpath: ["tag"] - protocol: - description: 'The protocol (TCP or UDP).' + validators: + - type: count + spec: + max: 64 + spec: + items: + type: string + validators: + - type: length + spec: + max: 127 + - name: protocol + type: object + description: "The protocol (TCP or UDP)." profiles: - - - xpath: ["protocol"] + - xpath: ["protocol"] spec: - one_of: - tcp: - description: 'TCP protocol' + variants: + - name: tcp + type: object + description: "TCP protocol" profiles: - - - xpath: ["tcp"] + - xpath: ["tcp"] spec: params: - destination-port: - description: 'The destination port.' + - name: destination-port + description: "The destination port." type: int64 - value: - min: 0 - max: 1023 + validators: + - type: range + spec: + min: 0 + max: 1023 profiles: - - xpath: [ "port" ] - source-port: - description: 'The source port.' + - xpath: ["port"] + - name: source-port + description: "The source port." type: int64 - value: - min: 0 - max: 1023 + validators: + - type: range + spec: + min: 0 + max: 1023 profiles: - - xpath: [ "source-port" ] - override: - description: 'Override session timeout.' + - xpath: ["source-port"] + - name: override + type: object + description: "Override session timeout." profiles: - - xpath: [ "override", "yes" ] + - xpath: ["override", "yes"] spec: params: - 'timeout': - description: 'TCP session timeout value (in second)' + - name: "timeout" + description: "TCP session timeout value (in second)" type: int64 profiles: - - xpath: [ "timeout" ] - 'halfclose-timeout': - description: 'TCP session half-close timeout value (in second)' + - xpath: ["timeout"] + - name: "halfclose-timeout" + description: "TCP session half-close timeout value (in second)" type: int64 profiles: - - xpath: [ "halfclose-timeout" ] - 'timewait-timeout': - description: 'TCP session time-wait timeout value (in second)' + - xpath: ["halfclose-timeout"] + - name: "timewait-timeout" + description: "TCP session time-wait timeout value (in second)" type: int64 profiles: - - xpath: [ "timewait-timeout" ] - udp: - description: 'UDP protocol' + - xpath: ["timewait-timeout"] + - name: udp + type: object + description: "UDP protocol" profiles: - - - xpath: ["udp"] + - xpath: ["udp"] spec: params: - destination-port: - description: 'The destination port.' + - name: destination-port + description: "The destination port." type: int64 - value: - min: 0 - max: 1023 + validators: + - type: range + spec: + min: 0 + max: 1023 profiles: - - xpath: [ "port" ] - source-port: - description: 'The source port.' + - xpath: ["port"] + - name: source-port + description: "The source port." type: int64 - value: - min: 0 - max: 1023 + validators: + - type: range + spec: + min: 0 + max: 1023 profiles: - - xpath: [ "source-port" ] - override: - description: 'Override session timeout.' + - xpath: ["source-port"] + - name: override + type: object + description: "Override session timeout." profiles: - - xpath: [ "override" ] + - xpath: ["override"] spec: - one_of: - yes: + variants: + - name: yes + type: object profiles: - - - xpath: [ "yes"] + - xpath: ["yes"] spec: params: - 'timeout': - description: 'UDP session timeout value (in second)' + - name: "timeout" + type: int64 + description: "UDP session timeout value (in second)" profiles: - - xpath: [ "timeout" ] - no: + - xpath: ["timeout"] + - name: no + type: nil profiles: - - xpath: [ "no" ] + - xpath: ["no"] diff --git a/specs/objects/tag.yaml b/specs/objects/tag.yaml index 501f5751..e0097f42 100644 --- a/specs/objects/tag.yaml +++ b/specs/objects/tag.yaml @@ -1,191 +1,220 @@ -name: 'Tag' +name: "Tag" terraform_provider_config: - suffix: 'administrative_tag' -go_sdk_path: - - 'objects' - - 'tag' + suffix: "administrative_tag" +go_sdk_config: + package: + - "objects" + - "tag" xpath_suffix: - - 'tag' + - "tag" locations: - 'shared': - description: 'Located in shared.' - device: - panorama: true - ngfw: true - xpath: ['config', 'shared'] - 'vsys': - description: 'Located in a specific vsys.' - device: - panorama: true - ngfw: true + - name: "shared" + description: "Located in shared." + devices: + - panorama + - ngfw xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'from_panorama_shared': - description: 'Located in shared in the config pushed from Panorama.' + path: ["config", "shared"] + - name: "vsys" + description: "Located in a specific vsys." + devices: + - panorama + - ngfw + xpath: + path: + - "config" + - "devices" + - "$ngfw_device" + - "vsys" + - "$vsys" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "from_panorama_shared" + description: "Located in shared in the config pushed from Panorama." read_only: true - device: - ngfw: true + devices: + - ngfw xpath: - - 'config' - - 'panorama' - - 'shared' - 'from_panorama_vsys': - description: 'Located in a specific vsys in the config pushed from Panorama.' + path: + - "config" + - "panorama" + - "shared" + - name: "from_panorama_vsys" + description: "Located in a specific vsys in the config pushed from Panorama." read_only: true - device: - ngfw: true + devices: + - ngfw xpath: - - 'config' - - 'panorama' - - 'vsys' - - '{{ Entry $vsys }}' - vars: - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'device_group': - description: 'Located in a specific device group.' - device: - panorama: true + path: + - "config" + - "panorama" + - "vsys" + - "$vsys" + vars: + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "device_group" + description: "Located in a specific device group." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'device-group' - - '{{ Entry $device_group }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'device_group': - description: 'The device group.' - required: true - validation: - not_values: - 'shared': 'The device group cannot be "shared". Use the "shared" path instead.' -entry: - name: - description: 'The name of the tag.' - length: - min: 1 - max: 127 -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + - "device-group" + - "$device_group" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "device_group" + description: "The device group." + required: true + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The device group cannot be "shared". Use the "shared" path instead.' +entries: + - name: name + description: "The name of the tag." + validators: + - type: length + spec: + min: 1 + max: 127 +version: "10.1.0" spec: params: - color: - description: 'The color.' - type: string + - name: color + description: "The color." + type: enum + validators: + - type: values + spec: + values: ["color1", "color2", "color24"] + spec: + values: + - value: color1 + const: red + - value: color2 + const: green + - value: color24 + const: azure blue profiles: - - - xpath: ["color"] - comments: - description: 'Comments.' + - xpath: ["color"] + - name: comments + description: "Comments." type: string - length: - min: 0 - max: 1023 + validators: + - type: length + spec: + min: 0 + max: 1023 profiles: - - - xpath: ["comments"] -const: - color: - values: - red: - value: color1 - green: - value: color2 - blue: - value: color3 - yellow: - value: color4 - copper: - value: color5 - orange: - value: color6 - purple: - value: color7 - gray: - value: color8 - light green: - value: color9 - cyan: - value: color10 - light gray: - value: color11 - blue gray: - value: color12 - lime: - value: color13 - black: - value: color14 - gold: - value: color15 - brown: - value: color16 - olive: - value: color17 - maroon: - value: color19 - red-orange: - value: color20 - yellow-orange: - value: color21 - forest green: - value: color22 - turquoise blue: - value: color23 - azure blue: - value: color24 - cerulean blue: - value: color25 - midnight blue: - value: color26 - medium blue: - value: color27 - cobalt blue: - value: color28 - violet blue: - value: color29 - blue violet: - value: color30 - medium violet: - value: color31 - medium rose: - value: color32 - lavender: - value: color33 - orchid: - value: color34 - thistle: - value: color35 - peach: - value: color36 - salmon: - value: color37 - magenta: - value: color38 - red violet: - value: color39 - mahogany: - value: color40 - burnt sienna: - value: color41 - chestnut: - value: color42 + - xpath: ["comments"] +# const: +# color: +# values: +# red: +# color1 +# green: +# value: color2 +# blue: +# value: color3 +# yellow: +# value: color4 +# copper: +# value: color5 +# orange: +# value: color6 +# purple: +# value: color7 +# gray: +# value: color8 +# light green: +# value: color9 +# cyan: +# value: color10 +# light gray: +# value: color11 +# blue gray: +# value: color12 +# lime: +# value: color13 +# black: +# value: color14 +# gold: +# value: color15 +# brown: +# value: color16 +# olive: +# value: color17 +# maroon: +# value: color19 +# red-orange: +# value: color20 +# yellow-orange: +# value: color21 +# forest green: +# value: color22 +# turquoise blue: +# value: color23 +# azure blue: +# value: color24 +# cerulean blue: +# value: color25 +# midnight blue: +# value: color26 +# medium blue: +# value: color27 +# cobalt blue: +# value: color28 +# violet blue: +# value: color29 +# blue violet: +# value: color30 +# medium violet: +# value: color31 +# medium rose: +# value: color32 +# lavender: +# value: color33 +# orchid: +# value: color34 +# thistle: +# value: color35 +# peach: +# value: color36 +# salmon: +# value: color37 +# magenta: +# value: color38 +# red violet: +# value: color39 +# mahogany: +# value: color40 +# burnt sienna: +# value: color41 +# chestnut: +# value: color42 diff --git a/specs/panorama/device-group.yaml b/specs/panorama/device-group.yaml index 0ce1c7b7..a7f3c08e 100644 --- a/specs/panorama/device-group.yaml +++ b/specs/panorama/device-group.yaml @@ -1,61 +1,67 @@ -name: 'Device group' +name: "Device group" terraform_provider_config: - suffix: 'device_group' -go_sdk_path: - - 'panorama' - - 'device_group' + suffix: "device_group" +go_sdk_config: + package: + - "panorama" + - "device_group" xpath_suffix: - - 'device-group' + - "device-group" locations: - 'panorama': - description: 'Located in a specific Panorama.' - device: - panorama: true + - name: "panorama" + description: "Located in a specific Panorama." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - vars: - 'panorama_device': - description: 'The Panorama device.' - default: 'localhost.localdomain' -entry: - name: - description: 'The name of the device group.' - length: - min: 1 - max: 31 -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + vars: + - name: "panorama_device" + description: "The Panorama device." + default: "localhost.localdomain" +entries: + - name: name + description: "The name of the service." + validators: + - type: length + spec: + min: 1 + max: 63 +version: "10.1.0" spec: params: - description: - description: 'The description.' + - name: description + description: "The description." type: string - length: - min: 0 - max: 255 + validators: + - type: length + spec: + min: 0 + max: 255 profiles: - - - xpath: ["description"] - templates: - description: 'List of reference templates' + - xpath: ["description"] + - name: templates + description: "List of reference templates" type: list - items: - type: string + spec: + items: + type: string profiles: - - - type: member + - type: member xpath: ["reference-templates"] - devices: - description: 'List of devices' + - name: devices + description: "List of devices" type: list - items: - type: string + spec: + items: + type: string profiles: - type: member xpath: ["devices"] - authorization_code: - description: 'Authorization code' + - name: authorization_code + type: string + description: "Authorization code" profiles: - - - xpath: ["authorization-code"] + - xpath: ["authorization-code"] diff --git a/specs/panorama/template-stack.yaml b/specs/panorama/template-stack.yaml index f72c9f77..0c0b4504 100644 --- a/specs/panorama/template-stack.yaml +++ b/specs/panorama/template-stack.yaml @@ -1,72 +1,77 @@ -name: 'Template stack' +name: "Template stack" terraform_provider_config: - suffix: 'template_stack' -go_sdk_path: - - 'panorama' - - 'template_stack' + suffix: "template_stack" +go_sdk_config: + package: + - "panorama" + - "template_stack" xpath_suffix: - - 'template-stack' + - "template-stack" locations: - 'panorama': - description: 'Located in a specific Panorama.' - device: - panorama: true + - name: "panorama" + description: "Located in a specific Panorama." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - vars: - 'panorama_device': - description: 'The Panorama device.' - default: 'localhost.localdomain' -entry: - name: - description: 'The name of the template stack.' - length: - min: 1 - max: 63 -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + vars: + - name: "panorama_device" + description: "The Panorama device." + default: "localhost.localdomain" +entries: + - name: name + description: "The name of the service." + validators: + - type: length + spec: + min: 1 + max: 63 +version: "10.1.0" spec: params: - description: - description: 'The description.' + - name: description + description: "The description." type: string - length: - min: 0 - max: 255 + validators: + - type: length + spec: + min: 0 + max: 255 profiles: - - - xpath: ["description"] - templates: - description: 'List of templates' + - xpath: ["description"] + - name: templates + description: "List of templates" type: list - items: - type: string + spec: + items: + type: string profiles: - - - type: member + - type: member xpath: ["templates"] - devices: - description: 'List of devices' + - name: devices + description: "List of devices" type: list - items: - type: string + spec: + items: + type: string profiles: - - - type: entry + - type: entry xpath: ["devices"] - default-vsys: - description: 'Default virtual system' + - name: default-vsys + description: "Default virtual system" type: string profiles: - - - xpath: ["settings", "default-vsys"] - user-group-source: + - xpath: ["settings", "default-vsys"] + - name: user-group-source + type: object profiles: - xpath: ["user-group-source"] spec: params: - master-device: + - name: master-device type: string profiles: - xpath: ["master-device"] diff --git a/specs/panorama/template.yaml b/specs/panorama/template.yaml index e642dc71..a71fdb52 100644 --- a/specs/panorama/template.yaml +++ b/specs/panorama/template.yaml @@ -1,91 +1,95 @@ -name: 'Template' +name: "Template" terraform_provider_config: - suffix: 'template' -go_sdk_path: - - 'panorama' - - 'template' + suffix: "template" +go_sdk_config: + package: + - "panorama" + - "template" xpath_suffix: - - 'template' + - "template" locations: - 'panorama': - description: 'Located in a specific Panorama.' - device: - panorama: true + - name: "panorama" + description: "Located in a specific Panorama." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - vars: - 'panorama_device': - description: 'The Panorama device.' - default: 'localhost.localdomain' -entry: - name: - description: 'The name of the template.' - length: - min: 1 - max: 63 -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + vars: + - name: "panorama_device" + description: "The Panorama device." + default: "localhost.localdomain" +entries: + - name: name + description: "The name of the service." + validators: + - type: length + spec: + min: 1 + max: 63 +version: "10.1.0" spec: params: - description: - description: 'The description.' + - name: description + description: "The description." type: string - length: - min: 0 - max: 255 + validators: + - type: length + spec: + min: 0 + max: 255 profiles: - - - xpath: ["description"] - default-vsys: - description: 'Default virtual system' + - xpath: ["description"] + - name: default-vsys + description: "Default virtual system" type: string profiles: - - - xpath: ["settings", "default-vsys"] - config: + - xpath: ["settings", "default-vsys"] + - name: config + type: object profiles: - - - xpath: ["config"] + - xpath: ["config"] spec: params: - devices: + - name: devices type: list - items: - type: entry profiles: - - - xpath: ["devices", "entry"] + - xpath: ["devices", "entry"] type: entry spec: - params: - vsys: - type: list - items: - type: entry - profiles: - - - xpath: ["vsys", "entry"] - type: entry - spec: - params: - import: - profiles: - - - xpath: ["import"] - spec: - params: - network: - profiles: - - - xpath: ["network"] - spec: - params: - interfaces: - type: list - items: - type: string - profiles: - - - xpath: ["interface"] - type: member + items: + type: object + spec: + params: + - name: vsys + type: list + profiles: + - xpath: ["vsys", "entry"] + type: entry + spec: + items: + type: object + spec: + params: + - name: import + type: object + profiles: + - xpath: ["import"] + spec: + params: + - name: network + type: object + profiles: + - xpath: ["network"] + spec: + params: + - name: interfaces + type: list + profiles: + - xpath: ["interface"] + type: member + spec: + items: + type: string diff --git a/specs/policies/security-policy-rule.yaml b/specs/policies/security-policy-rule.yaml index 2a04b4dc..40047e63 100644 --- a/specs/policies/security-policy-rule.yaml +++ b/specs/policies/security-policy-rule.yaml @@ -1,399 +1,509 @@ -name: 'Security policy rule' +name: "Security policy rule" terraform_provider_config: - suffix: 'security_policy_rule' -go_sdk_path: - - 'policies' - - 'rules' - - 'security' + suffix: "security_policy_rule" +go_sdk_config: + package: + - "policies" + - "rules" + - "security" xpath_suffix: - - 'security' - - 'rules' + - "security" + - "rules" locations: - 'shared': - description: 'Located in shared.' - device: - panorama: true - ngfw: true + - name: "shared" + description: "Located in shared." + devices: + - panorama + - ngfw xpath: - - 'config' - - 'shared' - - '{{ Object $rulebase }}' - vars: - 'rulebase': - description: 'The rulebase.' - default: 'pre-rulebase' - validation: - values: ['post-rulebase', 'pre-rulebase'] - 'vsys': - description: 'Located in a specific vsys.' - device: - panorama: true - ngfw: true + path: + - "config" + - "shared" + - "$rulebase" + vars: + - name: "rulebase" + type: object + description: "The rulebase." + default: "pre-rulebase" + validators: + - type: values + spec: + values: ["post-rulebase", "pre-rulebase"] + - name: "vsys" + description: "Located in a specific vsys." + devices: + - panorama + - ngfw xpath: - - 'config' - - 'devices' - - '{{ Entry $ngfw_device }}' - - 'vsys' - - '{{ Entry $vsys }}' - - 'rulebase' - vars: - 'ngfw_device': - description: 'The NGFW device.' - default: 'localhost.localdomain' - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'rulebase': - description: 'The rulebase.' - default: 'pre-rulebase' - validation: - values: ['post-rulebase', 'pre-rulebase'] - 'from_panorama_vsys': - description: 'Located in a specific vsys in the config pushed from Panorama.' + path: + - "config" + - "devices" + - "$ngfw_device" + - "vsys" + - "$vsys" + - "rulebase" + vars: + - name: "ngfw_device" + description: "The NGFW device." + default: "localhost.localdomain" + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "rulebase" + description: "The rulebase." + default: "pre-rulebase" + validators: + - type: values + spec: + values: ["post-rulebase", "pre-rulebase"] + - name: "from_panorama_vsys" + description: "Located in a specific vsys in the config pushed from Panorama." read_only: true - device: - ngfw: true + devices: + - ngfw xpath: - - 'config' - - 'panorama' - - 'vsys' - - '{{ Entry $vsys }}' - - 'rulebase' - vars: - 'vsys': - description: 'The vsys.' - default: 'vsys1' - validation: - not_values: - 'shared': 'The vsys cannot be "shared". Use the "shared" path instead.' - 'device_group': - description: 'Located in a specific device group.' - device: - panorama: true + path: + - "config" + - "panorama" + - "vsys" + - "$vsys" + - "rulebase" + vars: + - name: "vsys" + description: "The vsys." + default: "vsys1" + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The vsys cannot be "shared". Use the "shared" path instead.' + - name: "device_group" + description: "Located in a specific device group." + devices: + - panorama xpath: - - 'config' - - 'devices' - - '{{ Entry $panorama_device }}' - - 'device-group' - - '{{ Entry $device_group }}' - - '{{ Object $rulebase }}' - vars: - 'panorama_device': - description: 'The panorama device.' - default: 'localhost.localdomain' - 'device_group': - description: 'The device group.' - required: true - validation: - not_values: - 'shared': 'The device group cannot be "shared". Use the "shared" path instead.' - 'rulebase': - description: 'The rulebase.' - default: 'pre-rulebase' - validation: - values: ['post-rulebase', 'pre-rulebase'] -entry: - name: - description: 'The name of the security policy rule.' - length: - min: 1 - max: 63 - validation: - not_values: - 'intrazone-default': 'The intrazone-default is a reserved name.' - 'interzone-default': 'The interzone-default is a reserved name.' -version: '10.1.0' + path: + - "config" + - "devices" + - "$panorama_device" + - "device-group" + - "$device_group" + - "$rulebase" + vars: + - name: "panorama_device" + description: "The panorama device." + default: "localhost.localdomain" + - name: "device_group" + description: "The device group." + required: true + validators: + - type: not-values + spec: + values: + - value: "shared" + error: 'The device group cannot be "shared". Use the "shared" path instead.' + - name: "rulebase" + type: object + description: "The rulebase." + default: "pre-rulebase" + validators: + - type: values + spec: + values: ["post-rulebase", "pre-rulebase"] +entries: + - name: name + description: "The name of the security policy rule." + validators: + - type: length + spec: + min: 1 + max: 63 + - type: not-values + spec: + values: + - value: "intrazone-default" + error: "The intrazone-default is a reserved name." + - value: "interzone-default" + error: "The interzone-default is a reserved name." +version: "10.1.0" spec: params: - description: - description: 'The description.' + - name: description + description: "The description." type: string - length: - min: 0 - max: 1023 + validators: + - type: length + spec: + min: 0 + max: 1023 profiles: - - - xpath: ["description"] - uuid: - description: 'The UUID value.' - regex: '[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}' - length: - min: 3 - max: 36 + - xpath: ["description"] + - name: uuid + type: string + description: "The UUID value." + codegen_overrides: + terraform: + computed: true + validators: + - type: regexp + spec: + expr: "[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}" + - type: length + spec: + min: 3 + max: 36 profiles: - - xpath: [ "uuid" ] - tags: - description: 'The administrative tags.' + - xpath: ["uuid"] + - name: tags + description: "The administrative tags." type: list - count: - max: 64 - items: - type: string - length: - max: 127 + validators: + - type: count + spec: + max: 64 + spec: + items: + type: string + validators: + - type: length + spec: + max: 127 profiles: - - - type: member + - type: member xpath: ["tag"] - source_zones: - description: 'Source zones' + - name: source_zones + description: "Source zones" type: list - count: - max: 31 - items: - type: string + validators: + - type: count + spec: + max: 31 + spec: + items: + type: string profiles: - - - type: member + - type: member xpath: ["from"] - destination_zones: - description: 'Destination zones' + - name: destination_zones + description: "Destination zones" type: list - count: - max: 31 - items: - type: string + validators: + - type: count + spec: + max: 31 + spec: + items: + type: string profiles: - - - type: member + - type: member xpath: ["to"] - source_addresses: - description: 'Source addresses' + - name: source_addresses + description: "Source addresses" type: list - count: - max: 63 - items: - type: string + validators: + - type: count + spec: + max: 63 + spec: + items: + type: string profiles: - - - type: member + - type: member xpath: ["source"] - destination_addresses: - description: 'Destination addresses' + - name: destination_addresses + description: "Destination addresses" type: list - count: - max: 63 - items: - type: string + validators: + - type: count + spec: + max: 63 + spec: + items: + type: string profiles: - - - type: member + - type: member xpath: ["destination"] - source_users: - description: 'Source users' + - name: source_users + description: "Source users" type: list - count: - max: 1023 - items: - type: string + validators: + - type: count + spec: + max: 1023 + spec: + items: + type: string profiles: - - - type: member + - type: member xpath: ["source-user"] - services: - description: 'Services' + - name: services + description: "Services" type: list - count: - max: 63 - items: - type: string + validators: + - type: count + spec: + max: 1023 + spec: + items: + type: string profiles: - - - type: member + - type: member xpath: ["service"] - categories: - description: 'Categories' + - name: categories + description: "Categories" type: list - count: - max: 63 - items: - type: string + validators: + - type: count + spec: + max: 63 + spec: + items: + type: string profiles: - - - type: member + - type: member xpath: ["category"] - applications: - description: 'Applications' + - name: applications + description: "Applications" type: list - count: - max: 63 - items: - type: string + validators: + - type: count + spec: + max: 63 + spec: + items: + type: string profiles: - - - type: member + - type: member xpath: ["application"] - source_hips: - description: 'Source HIPs' + - name: source_hips + description: "Source HIPs" type: list - count: - max: 63 - items: - type: string + validators: + - type: count + spec: + max: 63 + spec: + items: + type: string profiles: - - - type: member + - type: member xpath: ["source-hip"] - destination_hips: - description: 'Destination HIPs' + - name: destination_hips + description: "Destination HIPs" type: list - count: - max: 63 - items: - type: string + validators: + - type: count + spec: + max: 63 + spec: + items: + type: string profiles: - - - type: member + - type: member xpath: ["destination-hip"] - negate_source: - description: 'Negate source address' + - name: negate_source + description: "Negate source address" type: bool profiles: - - - xpath: ["negate-source"] - negate_destination: - description: 'Negate destination address' + - xpath: ["negate-source"] + - name: negate_destination + description: "Negate destination address" type: bool profiles: - - - xpath: ["negate-destination"] - disabled: - description: 'Disable the rule' + - xpath: ["negate-destination"] + - name: disabled + description: "Disable the rule" type: bool profiles: - - - xpath: ["disabled"] - action: - description: 'Action' - type: string - default: 'allow' - values: ['deny', 'allow', 'drop', 'reset-client', 'reset-server', 'reset-both'] + - xpath: ["disabled"] + - name: action + description: "Action" + type: enum + validators: + - type: values + spec: + values: + [ + "deny", + "allow", + "drop", + "reset-client", + "reset-server", + "reset-both", + ] + spec: + default: "allow" + values: + [ + { value: deny }, + { value: allow }, + { value: drop }, + { value: reset-client }, + { value: reset-server }, + { value: "reset-both" }, + ] profiles: - - - xpath: ["action"] - rule_type: - description: 'Rule type' - type: string - default: 'allow' - values: ['universal', 'intrazone', 'interzone'] + - xpath: ["action"] + - name: rule_type + description: "Rule type" + type: enum + validators: + - type: values + spec: + values: ["universal", "intrazone", "interzone"] + spec: + default: "intrazone" + values: + [ + { value: "universal" }, + { value: "intrazone" }, + { value: "interzone" }, + ] profiles: - - - xpath: ["rule-type"] - log_setting: - description: 'Log forwarding' + - xpath: ["rule-type"] + - name: log_setting + description: "Log forwarding" type: string - length: - min: 0 - max: 63 + validators: + - type: length + spec: + min: 0 + max: 63 profiles: - - - xpath: ["log-setting"] - log_start: - description: 'Log at session start' + - xpath: ["log-setting"] + - name: log_start + description: "Log at session start" type: bool profiles: - - - xpath: ["log-start"] - log_end: - description: 'Log at session end' + - xpath: ["log-start"] + - name: log_end + description: "Log at session end" type: bool - default: true + spec: + default: true profiles: - - - xpath: ["log-end"] - icmp_unreachable: - description: 'Send ICMP unreachable' + - xpath: ["log-end"] + - name: icmp_unreachable + description: "Send ICMP unreachable" type: bool profiles: - xpath: ["icmp-unreachable"] - disable_server_response_inspection: - description: 'Disable Server Response Inspection' + - name: disable_server_response_inspection + description: "Disable Server Response Inspection" type: bool profiles: - - xpath: [ "option", "disable-server-response-inspection" ] - profile_setting: + - xpath: ["option", "disable-server-response-inspection"] + - name: profile_setting + type: object profiles: - - xpath: [ "profile-setting" ] + - xpath: ["profile-setting"] spec: - one_of: - group: + variants: + - name: group + type: nil profiles: - - xpath: [ "group" ] - profiles: + - xpath: ["group"] + - name: profiles + type: object profiles: - - xpath: [ "profiles" ] + - xpath: ["profiles"] spec: params: - virus: - description: 'Antivirus profile' + - name: virus + description: "Antivirus profile" type: list - count: - max: 1 - items: - type: string + validators: + - type: count + spec: + max: 1 + spec: + items: + type: string profiles: - type: member - xpath: [ "virus" ] - spyware: - description: 'Anti-Spyware profile' + xpath: ["virus"] + - name: spyware + description: "Anti-Spyware profile" type: list - count: - max: 1 - items: - type: string + validators: + - type: count + spec: + max: 1 + spec: + items: + type: string profiles: - type: member - xpath: [ "spyware" ] - vulnerability: - description: 'Vulnerability Protection profile' + xpath: ["spyware"] + - name: vulnerability + description: "Vulnerability Protection profile" type: list - count: - max: 1 - items: - type: string + validators: + - type: count + spec: + max: 1 + spec: + items: + type: string profiles: - type: member - xpath: [ "vulnerability" ] - url_filtering: - description: 'URL filtering profile' + xpath: ["vulnerability"] + - name: url_filtering + description: "URL filtering profile" type: list - count: - max: 1 - items: - type: string + validators: + - type: count + spec: + max: 1 + spec: + items: + type: string profiles: - type: member - xpath: [ "url-filtering" ] - file_blocking: - description: 'File blocking profile' + xpath: ["url-filtering"] + - name: file_blocking + description: "File blocking profile" type: list - count: - max: 1 - items: - type: string + validators: + - type: count + spec: + max: 1 + spec: + items: + type: string profiles: - type: member - xpath: [ "file-blocking" ] - wildfire_analysis: - description: 'WildFire analysis profile' + xpath: ["file-blocking"] + - name: wildfire_analysis + description: "WildFire analysis profile" type: list - count: - max: 1 - items: - type: string + validators: + - type: count + spec: + max: 1 + spec: + items: + type: string profiles: - type: member - xpath: [ "wildfire-analysis" ] - data_filtering: - description: 'Data filtering profile' + xpath: ["wildfire-analysis"] + - name: data_filtering + description: "Data filtering profile" type: list - count: - max: 1 - items: - type: string + validators: + - type: count + spec: + max: 1 + spec: + items: + type: string profiles: - type: member - xpath: [ "data-filtering" ] + xpath: ["data-filtering"] diff --git a/specs/schema/import.schema.json b/specs/schema/import.schema.json new file mode 100644 index 00000000..fedbb4be --- /dev/null +++ b/specs/schema/import.schema.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "import.schema.json", + "type": "object", + "additionalProperties": false, + "required": ["name", "xpath"], + "properties": { + "name": { "type": "string" }, + "xpath": { "$ref": "xpath.schema.json" }, + "only_for_params": { + "type": "array", + "items": { "type": "string" } + } + } +} diff --git a/specs/schema/location.schema.json b/specs/schema/location.schema.json new file mode 100644 index 00000000..733e9222 --- /dev/null +++ b/specs/schema/location.schema.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "location.schema.json", + "title": "Codegen location schema", + "description": "Location schema describes PAN-OS location parameters", + "required": ["name", "description", "devices", "xpath"], + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "read_only": { + "type": "boolean" + }, + "devices": { + "type": "array", + "items": { + "type": "string", + "oneOf": [{ "enum": ["panorama", "ngfw"] }] + } + }, + "xpath": { + "$ref": "xpath.schema.json" + } + }, + "additionalProperties": false +} diff --git a/specs/schema/object.schema.json b/specs/schema/object.schema.json new file mode 100644 index 00000000..c455bf99 --- /dev/null +++ b/specs/schema/object.schema.json @@ -0,0 +1,80 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "id": "https://paloaltonetworks/codegen/object.schema.json", + "title": "Codegen object", + "description": "Top-level object describing XML API for Panorama and PAN-OS devices", + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "terraform_provider_config", + "go_sdk_config", + "locations", + "version", + "spec" + ], + "properties": { + "name": { "type": "string" }, + "terraform_provider_config": { + "type": "object", + "required": ["suffix"], + "properties": { + "suffix": { + "type": "string" + } + } + }, + "go_sdk_config": { + "type": "object", + "required": ["package"], + "properties": { + "package": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "xpath_suffix": { + "type": "array", + "items": { + "type": "string" + } + }, + "locations": { + "type": "array", + "items": { + "$ref": "location.schema.json" + } + }, + "entries": { + "type": "array", + "items": { + "$ref": "#/$defs/entry" + } + }, + "imports": { + "type": "array", + "items": { "$ref": "import.schema.json" } + }, + "version": { "type": "string" }, + "spec": { "$ref": "spec.schema.json" } + }, + "$defs": { + "entry": { + "type": "object", + "required": ["name", "description"], + "properties": { + "name": { "type": "string" }, + "description": { "type": "string" }, + "validators": { + "type": "array", + "items": { + "$ref": "validator.schema.json" + } + } + } + } + } +} diff --git a/specs/schema/profile.schema.json b/specs/schema/profile.schema.json new file mode 100644 index 00000000..9ef27b2b --- /dev/null +++ b/specs/schema/profile.schema.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "profile.schema.json", + "type": "object", + "required": ["xpath"], + "additionalProperties": false, + "properties": { + "type": { "type": "string" }, + "xpath": { "type": "array", "items": { "type": "string" } }, + "min_version": { "type": "string" }, + "max_version": { "type": "string" } + } +} diff --git a/specs/schema/schema.json b/specs/schema/schema.json new file mode 100644 index 00000000..c9f101ae --- /dev/null +++ b/specs/schema/schema.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "id": "https://paloaltonetworks/codegen/object.schema.json", + "title": "Codegen object", + "description": "Top-level object describing XML API for Panorama and PAN-OS devices", + "type": "object", + "required": [ + "name", + "terraform_provider_config", + "go_sdk_config", + "xpath_suffix", + "locations", + "entries", + "version", + "spec" + ], + "properties": { + "name": { + "type": "string" + }, + "terraform_provider_config": { + "type": "object", + "required": ["suffix"], + "properties": { + "suffix": { + "type": "string" + } + } + } + } +} diff --git a/specs/schema/spec.schema.json b/specs/schema/spec.schema.json new file mode 100644 index 00000000..f5956f18 --- /dev/null +++ b/specs/schema/spec.schema.json @@ -0,0 +1,121 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "additionalProperties": false, + "properties": { + "params": { + "type": "array", + "items": { "$ref": "#/$defs/item" } + }, + "variants": { + "type": "array", + "items": { "$ref": "#/$defs/item" } + } + }, + "$defs": { + "item": { + "type": "object", + "additionalProperties": false, + "required": ["name", "type"], + "properties": { + "name": { "type": "string" }, + "description": { "type": "string" }, + "codegen_overrides": { + "type": "object", + "additionalProperties": false, + "properties": { + "terraform": { + "type": "object", + "additionalProperties": false, + "properties": { + "codegen": { "type": "boolean" }, + "sensitive": { "type": "boolean" } + } + } + } + }, + "hashing": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { "type": "string" } + } + }, + "type": { "$ref": "#/$defs/type" }, + "profiles": { + "type": "array", + "items": { "$ref": "profile.schema.json" } + }, + "validators": { + "type": "array", + "items": { "$ref": "validator.schema.json" } + }, + "spec": { + "oneOf": [ + { "$ref": "#/$defs/simple" }, + { "$ref": "#/$defs/enum" }, + { "$ref": "#/$defs/list" }, + { "$ref": "#" } + ] + } + } + }, + "simple": { + "type": "object", + "additionalProperties": false, + "properties": { + "default": true, + "validators": { + "type": "array", + "items": { "$ref": "validator.schema.json" } + }, + "required": { "type": "boolean" } + } + }, + "enum": { + "type": "object", + "additionalProperties": false, + "required": ["values"], + "properties": { + "default": true, + "values": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["value"], + "properties": { + "value": { "type": "string" }, + "const": { "type": "string" } + } + } + } + } + }, + "list": { + "type": "object", + "additionalProperties": false, + "required": ["items"], + "properties": { + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { "$ref": "#/$defs/type" }, + "spec": { "$ref": "#" }, + "validators": { + "type": "array", + "items": { "$ref": "validator.schema.json" } + } + } + } + } + }, + "type": { + "type": "string", + "oneOf": [ + { "enum": ["string", "bool", "int64", "object", "list", "enum", "nil"] } + ] + } + } +} diff --git a/specs/schema/validator.schema.json b/specs/schema/validator.schema.json new file mode 100644 index 00000000..41ab0e61 --- /dev/null +++ b/specs/schema/validator.schema.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "validator.schema.json", + "type": "object", + "properties": { + "type": { "type": "string" }, + "spec": { + "type": "object", + "oneOf": [ + { "$ref": "#/$defs/validators/not-values" }, + { "$ref": "#/$defs/validators/values" }, + { "$ref": "#/$defs/validators/length" }, + { "$ref": "#/$defs/validators/regexp" } + ] + } + }, + "$defs": { + "validators": { + "not-values": { + "type": "object", + "required": ["values"], + "properties": { + "values": { + "type": "array", + "items": { + "type": "object", + "required": ["value", "error"], + "properties": { + "value": { "type": "string" }, + "error": { "type": "string" } + } + } + } + } + }, + "values": { + "type": "object", + "required": ["values"], + "properties": { + "values": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "length": { + "type": "object", + "additionalProperties": false, + "properties": { + "min": { "type": "number" }, + "max": { "type": "number" } + } + }, + "regexp": { + "type": "object", + "additionalProperties": false, + "properties": { + "expr": { "type": "string" } + } + } + } + } +} diff --git a/specs/schema/xpath.schema.json b/specs/schema/xpath.schema.json new file mode 100644 index 00000000..8b54ffe3 --- /dev/null +++ b/specs/schema/xpath.schema.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "xpath.schema.json", + "title": "Codegen Xpath schema", + "description": "Xpath schema describes Xpath used to define path of a given object", + "type": "object", + "required": ["path"], + "additionalProperties": false, + "properties": { + "path": { + "type": "array", + "items": { + "type": "string" + } + }, + "vars": { + "type": "array", + "items": { + "$ref": "#/$defs/xpath-variable" + } + } + }, + "$defs": { + "xpath-variable": { + "type": "object", + "required": ["name", "description"], + "properties": { + "name": { "type": "string" }, + "description": { "type": "string" }, + "default": { "type": "string" }, + "required": { "type": "boolean" }, + "validators": { + "type": "array", + "items": { + "$ref": "validator.schema.json" + } + } + } + } + } +}