diff --git a/api/.openapi-generator/FILES b/api/.openapi-generator/FILES index 6232be534..8903f1828 100644 --- a/api/.openapi-generator/FILES +++ b/api/.openapi-generator/FILES @@ -122,8 +122,8 @@ docs/TsdbRoleConfig.md docs/TypesAPIMetricsGetOutput.md docs/TypesAPIMetricsRecord.md docs/TypesAPIMetricsRole.md -docs/TypesDHCPOption.md docs/TypesOIDCConfig.md +docs/TypesOption.md git_push.sh go.mod go.sum @@ -223,18 +223,7 @@ model_tsdb_role_config.go model_types_api_metrics_get_output.go model_types_api_metrics_record.go model_types_api_metrics_role.go -model_types_dhcp_option.go model_types_oidc_config.go +model_types_option.go response.go -test/api_cluster_instances_test.go -test/api_cluster_test.go -test/api_roles_api_test.go -test/api_roles_backup_test.go -test/api_roles_dhcp_test.go -test/api_roles_discovery_test.go -test/api_roles_dns_test.go -test/api_roles_etcd_test.go -test/api_roles_monitoring_test.go -test/api_roles_tftp_test.go -test/api_roles_tsdb_test.go utils.go diff --git a/api/README.md b/api/README.md index 30b7a1b70..d272b6933 100644 --- a/api/README.md +++ b/api/README.md @@ -243,8 +243,8 @@ Class | Method | HTTP request | Description - [TypesAPIMetricsGetOutput](docs/TypesAPIMetricsGetOutput.md) - [TypesAPIMetricsRecord](docs/TypesAPIMetricsRecord.md) - [TypesAPIMetricsRole](docs/TypesAPIMetricsRole.md) - - [TypesDHCPOption](docs/TypesDHCPOption.md) - [TypesOIDCConfig](docs/TypesOIDCConfig.md) + - [TypesOption](docs/TypesOption.md) ## Documentation For Authorization diff --git a/api/api/openapi.yaml b/api/api/openapi.yaml index 030c28d45..8b2b2ab27 100644 --- a/api/api/openapi.yaml +++ b/api/api/openapi.yaml @@ -2541,24 +2541,32 @@ components: zone: zone addZoneInHostname: true options: - - value64: + - valueLegacy: valueLegacy + value64: - value64 - value64 + def: def valueHex: - valueHex - valueHex tag: 0 tagName: tagName - value: value - - value64: + value: + - value + - value + - valueLegacy: valueLegacy + value64: - value64 - value64 + def: def valueHex: - valueHex - valueHex tag: 0 tagName: tagName - value: value + value: + - value + - value ttl: 5 statistics: usable: 0 @@ -2577,7 +2585,7 @@ components: type: object options: items: - $ref: '#/components/schemas/TypesDHCPOption' + $ref: '#/components/schemas/TypesOption' nullable: true type: array scope: @@ -2629,24 +2637,32 @@ components: zone: zone addZoneInHostname: true options: - - value64: + - valueLegacy: valueLegacy + value64: - value64 - value64 + def: def valueHex: - valueHex - valueHex tag: 0 tagName: tagName - value: value - - value64: + value: + - value + - value + - valueLegacy: valueLegacy + value64: - value64 - value64 + def: def valueHex: - valueHex - valueHex tag: 0 tagName: tagName - value: value + value: + - value + - value ttl: 5 statistics: usable: 0 @@ -2664,24 +2680,32 @@ components: zone: zone addZoneInHostname: true options: - - value64: + - valueLegacy: valueLegacy + value64: - value64 - value64 + def: def valueHex: - valueHex - valueHex tag: 0 tagName: tagName - value: value - - value64: + value: + - value + - value + - valueLegacy: valueLegacy + value64: - value64 - value64 + def: def valueHex: - valueHex - valueHex tag: 0 tagName: tagName - value: value + value: + - value + - value ttl: 5 statistics: usable: 0 @@ -2736,24 +2760,32 @@ components: zone: zone addZoneInHostname: true options: - - value64: + - valueLegacy: valueLegacy + value64: - value64 - value64 + def: def valueHex: - valueHex - valueHex tag: 0 tagName: tagName - value: value - - value64: + value: + - value + - value + - valueLegacy: valueLegacy + value64: - value64 - value64 + def: def valueHex: - valueHex - valueHex tag: 0 tagName: tagName - value: value + value: + - value + - value ttl: 0 properties: default: @@ -2769,7 +2801,7 @@ components: type: object options: items: - $ref: '#/components/schemas/TypesDHCPOption' + $ref: '#/components/schemas/TypesOption' nullable: true type: array subnetCidr: @@ -3584,38 +3616,6 @@ components: - system - dns type: string - TypesDHCPOption: - example: - value64: - - value64 - - value64 - valueHex: - - valueHex - - valueHex - tag: 0 - tagName: tagName - value: value - properties: - tag: - minimum: 0 - nullable: true - type: integer - tagName: - type: string - value: - nullable: true - type: string - value64: - items: - type: string - nullable: true - type: array - valueHex: - items: - type: string - nullable: true - type: array - type: object TypesOIDCConfig: example: tokenUsernameField: tokenUsernameField @@ -3643,3 +3643,42 @@ components: tokenUsernameField: type: string type: object + TypesOption: + example: + valueLegacy: valueLegacy + value64: + - value64 + - value64 + def: def + valueHex: + - valueHex + - valueHex + tag: 0 + tagName: tagName + value: + - value + - value + properties: + def: + type: string + tag: + minimum: 0 + type: integer + tagName: + type: string + value: + items: + format: base64 + type: string + type: array + value64: + items: + type: string + type: array + valueHex: + items: + type: string + type: array + valueLegacy: + type: string + type: object diff --git a/api/docs/DhcpAPIScope.md b/api/docs/DhcpAPIScope.md index 57fbdfd0c..087089f70 100644 --- a/api/docs/DhcpAPIScope.md +++ b/api/docs/DhcpAPIScope.md @@ -8,7 +8,7 @@ Name | Type | Description | Notes **Dns** | Pointer to [**DhcpScopeDNS**](DhcpScopeDNS.md) | | [optional] **Hook** | **string** | | **Ipam** | **map[string]string** | | -**Options** | [**[]TypesDHCPOption**](TypesDHCPOption.md) | | +**Options** | [**[]TypesOption**](TypesOption.md) | | **Scope** | **string** | | **Statistics** | [**DhcpAPIScopeStatistics**](DhcpAPIScopeStatistics.md) | | **SubnetCidr** | **string** | | @@ -18,7 +18,7 @@ Name | Type | Description | Notes ### NewDhcpAPIScope -`func NewDhcpAPIScope(default_ bool, hook string, ipam map[string]string, options []TypesDHCPOption, scope string, statistics DhcpAPIScopeStatistics, subnetCidr string, ttl int32, ) *DhcpAPIScope` +`func NewDhcpAPIScope(default_ bool, hook string, ipam map[string]string, options []TypesOption, scope string, statistics DhcpAPIScopeStatistics, subnetCidr string, ttl int32, ) *DhcpAPIScope` NewDhcpAPIScope instantiates a new DhcpAPIScope object This constructor will assign default values to properties that have it defined, @@ -130,20 +130,20 @@ SetIpam sets Ipam field to given value. UnsetIpam ensures that no value is present for Ipam, not even an explicit nil ### GetOptions -`func (o *DhcpAPIScope) GetOptions() []TypesDHCPOption` +`func (o *DhcpAPIScope) GetOptions() []TypesOption` GetOptions returns the Options field if non-nil, zero value otherwise. ### GetOptionsOk -`func (o *DhcpAPIScope) GetOptionsOk() (*[]TypesDHCPOption, bool)` +`func (o *DhcpAPIScope) GetOptionsOk() (*[]TypesOption, bool)` GetOptionsOk returns a tuple with the Options field if it's non-nil, zero value otherwise and a boolean to check if the value has been set. ### SetOptions -`func (o *DhcpAPIScope) SetOptions(v []TypesDHCPOption)` +`func (o *DhcpAPIScope) SetOptions(v []TypesOption)` SetOptions sets Options field to given value. diff --git a/api/docs/DhcpAPIScopesPutInput.md b/api/docs/DhcpAPIScopesPutInput.md index 88a290e41..d77fc1688 100644 --- a/api/docs/DhcpAPIScopesPutInput.md +++ b/api/docs/DhcpAPIScopesPutInput.md @@ -8,7 +8,7 @@ Name | Type | Description | Notes **Dns** | Pointer to [**DhcpScopeDNS**](DhcpScopeDNS.md) | | [optional] **Hook** | **string** | | **Ipam** | Pointer to **map[string]string** | | [optional] -**Options** | [**[]TypesDHCPOption**](TypesDHCPOption.md) | | +**Options** | [**[]TypesOption**](TypesOption.md) | | **SubnetCidr** | **string** | | **Ttl** | **int32** | | @@ -16,7 +16,7 @@ Name | Type | Description | Notes ### NewDhcpAPIScopesPutInput -`func NewDhcpAPIScopesPutInput(default_ bool, hook string, options []TypesDHCPOption, subnetCidr string, ttl int32, ) *DhcpAPIScopesPutInput` +`func NewDhcpAPIScopesPutInput(default_ bool, hook string, options []TypesOption, subnetCidr string, ttl int32, ) *DhcpAPIScopesPutInput` NewDhcpAPIScopesPutInput instantiates a new DhcpAPIScopesPutInput object This constructor will assign default values to properties that have it defined, @@ -133,20 +133,20 @@ HasIpam returns a boolean if a field has been set. UnsetIpam ensures that no value is present for Ipam, not even an explicit nil ### GetOptions -`func (o *DhcpAPIScopesPutInput) GetOptions() []TypesDHCPOption` +`func (o *DhcpAPIScopesPutInput) GetOptions() []TypesOption` GetOptions returns the Options field if non-nil, zero value otherwise. ### GetOptionsOk -`func (o *DhcpAPIScopesPutInput) GetOptionsOk() (*[]TypesDHCPOption, bool)` +`func (o *DhcpAPIScopesPutInput) GetOptionsOk() (*[]TypesOption, bool)` GetOptionsOk returns a tuple with the Options field if it's non-nil, zero value otherwise and a boolean to check if the value has been set. ### SetOptions -`func (o *DhcpAPIScopesPutInput) SetOptions(v []TypesDHCPOption)` +`func (o *DhcpAPIScopesPutInput) SetOptions(v []TypesOption)` SetOptions sets Options field to given value. diff --git a/api/docs/RolesDhcpApi.md b/api/docs/RolesDhcpApi.md index 60cb6a2b1..22739dc0b 100644 --- a/api/docs/RolesDhcpApi.md +++ b/api/docs/RolesDhcpApi.md @@ -546,7 +546,7 @@ import ( func main() { scope := "scope_example" // string | - dhcpAPIScopesPutInput := *openapiclient.NewDhcpAPIScopesPutInput(false, "Hook_example", []openapiclient.TypesDHCPOption{*openapiclient.NewTypesDHCPOption()}, "SubnetCidr_example", int32(123)) // DhcpAPIScopesPutInput | (optional) + dhcpAPIScopesPutInput := *openapiclient.NewDhcpAPIScopesPutInput(false, "Hook_example", []openapiclient.TypesOption{*openapiclient.NewTypesOption()}, "SubnetCidr_example", int32(123)) // DhcpAPIScopesPutInput | (optional) configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) diff --git a/api/docs/TypesOption.md b/api/docs/TypesOption.md new file mode 100644 index 000000000..1aebfdd1c --- /dev/null +++ b/api/docs/TypesOption.md @@ -0,0 +1,212 @@ +# TypesOption + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Def** | Pointer to **string** | | [optional] +**Tag** | Pointer to **int32** | | [optional] +**TagName** | Pointer to **string** | | [optional] +**Value** | Pointer to **[]string** | | [optional] +**Value64** | Pointer to **[]string** | | [optional] +**ValueHex** | Pointer to **[]string** | | [optional] +**ValueLegacy** | Pointer to **string** | | [optional] + +## Methods + +### NewTypesOption + +`func NewTypesOption() *TypesOption` + +NewTypesOption instantiates a new TypesOption object +This constructor will assign default values to properties that have it defined, +and makes sure properties required by API are set, but the set of arguments +will change when the set of required properties is changed + +### NewTypesOptionWithDefaults + +`func NewTypesOptionWithDefaults() *TypesOption` + +NewTypesOptionWithDefaults instantiates a new TypesOption object +This constructor will only assign default values to properties that have it defined, +but it doesn't guarantee that properties required by API are set + +### GetDef + +`func (o *TypesOption) GetDef() string` + +GetDef returns the Def field if non-nil, zero value otherwise. + +### GetDefOk + +`func (o *TypesOption) GetDefOk() (*string, bool)` + +GetDefOk returns a tuple with the Def field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetDef + +`func (o *TypesOption) SetDef(v string)` + +SetDef sets Def field to given value. + +### HasDef + +`func (o *TypesOption) HasDef() bool` + +HasDef returns a boolean if a field has been set. + +### GetTag + +`func (o *TypesOption) GetTag() int32` + +GetTag returns the Tag field if non-nil, zero value otherwise. + +### GetTagOk + +`func (o *TypesOption) GetTagOk() (*int32, bool)` + +GetTagOk returns a tuple with the Tag field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetTag + +`func (o *TypesOption) SetTag(v int32)` + +SetTag sets Tag field to given value. + +### HasTag + +`func (o *TypesOption) HasTag() bool` + +HasTag returns a boolean if a field has been set. + +### GetTagName + +`func (o *TypesOption) GetTagName() string` + +GetTagName returns the TagName field if non-nil, zero value otherwise. + +### GetTagNameOk + +`func (o *TypesOption) GetTagNameOk() (*string, bool)` + +GetTagNameOk returns a tuple with the TagName field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetTagName + +`func (o *TypesOption) SetTagName(v string)` + +SetTagName sets TagName field to given value. + +### HasTagName + +`func (o *TypesOption) HasTagName() bool` + +HasTagName returns a boolean if a field has been set. + +### GetValue + +`func (o *TypesOption) GetValue() []string` + +GetValue returns the Value field if non-nil, zero value otherwise. + +### GetValueOk + +`func (o *TypesOption) GetValueOk() (*[]string, bool)` + +GetValueOk returns a tuple with the Value field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetValue + +`func (o *TypesOption) SetValue(v []string)` + +SetValue sets Value field to given value. + +### HasValue + +`func (o *TypesOption) HasValue() bool` + +HasValue returns a boolean if a field has been set. + +### GetValue64 + +`func (o *TypesOption) GetValue64() []string` + +GetValue64 returns the Value64 field if non-nil, zero value otherwise. + +### GetValue64Ok + +`func (o *TypesOption) GetValue64Ok() (*[]string, bool)` + +GetValue64Ok returns a tuple with the Value64 field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetValue64 + +`func (o *TypesOption) SetValue64(v []string)` + +SetValue64 sets Value64 field to given value. + +### HasValue64 + +`func (o *TypesOption) HasValue64() bool` + +HasValue64 returns a boolean if a field has been set. + +### GetValueHex + +`func (o *TypesOption) GetValueHex() []string` + +GetValueHex returns the ValueHex field if non-nil, zero value otherwise. + +### GetValueHexOk + +`func (o *TypesOption) GetValueHexOk() (*[]string, bool)` + +GetValueHexOk returns a tuple with the ValueHex field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetValueHex + +`func (o *TypesOption) SetValueHex(v []string)` + +SetValueHex sets ValueHex field to given value. + +### HasValueHex + +`func (o *TypesOption) HasValueHex() bool` + +HasValueHex returns a boolean if a field has been set. + +### GetValueLegacy + +`func (o *TypesOption) GetValueLegacy() string` + +GetValueLegacy returns the ValueLegacy field if non-nil, zero value otherwise. + +### GetValueLegacyOk + +`func (o *TypesOption) GetValueLegacyOk() (*string, bool)` + +GetValueLegacyOk returns a tuple with the ValueLegacy field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetValueLegacy + +`func (o *TypesOption) SetValueLegacy(v string)` + +SetValueLegacy sets ValueLegacy field to given value. + +### HasValueLegacy + +`func (o *TypesOption) HasValueLegacy() bool` + +HasValueLegacy returns a boolean if a field has been set. + + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/api/model_dhcp_api_scope.go b/api/model_dhcp_api_scope.go index 861767c98..c479884a2 100644 --- a/api/model_dhcp_api_scope.go +++ b/api/model_dhcp_api_scope.go @@ -23,7 +23,7 @@ type DhcpAPIScope struct { Dns *DhcpScopeDNS `json:"dns,omitempty"` Hook string `json:"hook"` Ipam map[string]string `json:"ipam"` - Options []TypesDHCPOption `json:"options"` + Options []TypesOption `json:"options"` Scope string `json:"scope"` Statistics DhcpAPIScopeStatistics `json:"statistics"` SubnetCidr string `json:"subnetCidr"` @@ -34,7 +34,7 @@ type DhcpAPIScope struct { // This constructor will assign default values to properties that have it defined, // and makes sure properties required by API are set, but the set of arguments // will change when the set of required properties is changed -func NewDhcpAPIScope(default_ bool, hook string, ipam map[string]string, options []TypesDHCPOption, scope string, statistics DhcpAPIScopeStatistics, subnetCidr string, ttl int32) *DhcpAPIScope { +func NewDhcpAPIScope(default_ bool, hook string, ipam map[string]string, options []TypesOption, scope string, statistics DhcpAPIScopeStatistics, subnetCidr string, ttl int32) *DhcpAPIScope { this := DhcpAPIScope{} this.Default = default_ this.Hook = hook @@ -162,10 +162,10 @@ func (o *DhcpAPIScope) SetIpam(v map[string]string) { } // GetOptions returns the Options field value -// If the value is explicit nil, the zero value for []TypesDHCPOption will be returned -func (o *DhcpAPIScope) GetOptions() []TypesDHCPOption { +// If the value is explicit nil, the zero value for []TypesOption will be returned +func (o *DhcpAPIScope) GetOptions() []TypesOption { if o == nil { - var ret []TypesDHCPOption + var ret []TypesOption return ret } @@ -175,7 +175,7 @@ func (o *DhcpAPIScope) GetOptions() []TypesDHCPOption { // GetOptionsOk returns a tuple with the Options field value // and a boolean to check if the value has been set. // NOTE: If the value is an explicit nil, `nil, true` will be returned -func (o *DhcpAPIScope) GetOptionsOk() ([]TypesDHCPOption, bool) { +func (o *DhcpAPIScope) GetOptionsOk() ([]TypesOption, bool) { if o == nil || IsNil(o.Options) { return nil, false } @@ -183,7 +183,7 @@ func (o *DhcpAPIScope) GetOptionsOk() ([]TypesDHCPOption, bool) { } // SetOptions sets field value -func (o *DhcpAPIScope) SetOptions(v []TypesDHCPOption) { +func (o *DhcpAPIScope) SetOptions(v []TypesOption) { o.Options = v } diff --git a/api/model_dhcp_api_scopes_put_input.go b/api/model_dhcp_api_scopes_put_input.go index 4fef3b381..ef85ca4b0 100644 --- a/api/model_dhcp_api_scopes_put_input.go +++ b/api/model_dhcp_api_scopes_put_input.go @@ -23,7 +23,7 @@ type DhcpAPIScopesPutInput struct { Dns *DhcpScopeDNS `json:"dns,omitempty"` Hook string `json:"hook"` Ipam map[string]string `json:"ipam,omitempty"` - Options []TypesDHCPOption `json:"options"` + Options []TypesOption `json:"options"` SubnetCidr string `json:"subnetCidr"` Ttl int32 `json:"ttl"` } @@ -32,7 +32,7 @@ type DhcpAPIScopesPutInput struct { // This constructor will assign default values to properties that have it defined, // and makes sure properties required by API are set, but the set of arguments // will change when the set of required properties is changed -func NewDhcpAPIScopesPutInput(default_ bool, hook string, options []TypesDHCPOption, subnetCidr string, ttl int32) *DhcpAPIScopesPutInput { +func NewDhcpAPIScopesPutInput(default_ bool, hook string, options []TypesOption, subnetCidr string, ttl int32) *DhcpAPIScopesPutInput { this := DhcpAPIScopesPutInput{} this.Default = default_ this.Hook = hook @@ -164,10 +164,10 @@ func (o *DhcpAPIScopesPutInput) SetIpam(v map[string]string) { } // GetOptions returns the Options field value -// If the value is explicit nil, the zero value for []TypesDHCPOption will be returned -func (o *DhcpAPIScopesPutInput) GetOptions() []TypesDHCPOption { +// If the value is explicit nil, the zero value for []TypesOption will be returned +func (o *DhcpAPIScopesPutInput) GetOptions() []TypesOption { if o == nil { - var ret []TypesDHCPOption + var ret []TypesOption return ret } @@ -177,7 +177,7 @@ func (o *DhcpAPIScopesPutInput) GetOptions() []TypesDHCPOption { // GetOptionsOk returns a tuple with the Options field value // and a boolean to check if the value has been set. // NOTE: If the value is an explicit nil, `nil, true` will be returned -func (o *DhcpAPIScopesPutInput) GetOptionsOk() ([]TypesDHCPOption, bool) { +func (o *DhcpAPIScopesPutInput) GetOptionsOk() ([]TypesOption, bool) { if o == nil || IsNil(o.Options) { return nil, false } @@ -185,7 +185,7 @@ func (o *DhcpAPIScopesPutInput) GetOptionsOk() ([]TypesDHCPOption, bool) { } // SetOptions sets field value -func (o *DhcpAPIScopesPutInput) SetOptions(v []TypesDHCPOption) { +func (o *DhcpAPIScopesPutInput) SetOptions(v []TypesOption) { o.Options = v } diff --git a/api/model_types_option.go b/api/model_types_option.go new file mode 100644 index 000000000..d093d6a03 --- /dev/null +++ b/api/model_types_option.go @@ -0,0 +1,340 @@ +/* +gravity + +No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + +API version: 0.26.1 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package api + +import ( + "encoding/json" +) + +// checks if the TypesOption type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &TypesOption{} + +// TypesOption struct for TypesOption +type TypesOption struct { + Def *string `json:"def,omitempty"` + Tag *int32 `json:"tag,omitempty"` + TagName *string `json:"tagName,omitempty"` + Value []string `json:"value,omitempty"` + Value64 []string `json:"value64,omitempty"` + ValueHex []string `json:"valueHex,omitempty"` + ValueLegacy *string `json:"valueLegacy,omitempty"` +} + +// NewTypesOption instantiates a new TypesOption object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewTypesOption() *TypesOption { + this := TypesOption{} + return &this +} + +// NewTypesOptionWithDefaults instantiates a new TypesOption object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewTypesOptionWithDefaults() *TypesOption { + this := TypesOption{} + return &this +} + +// GetDef returns the Def field value if set, zero value otherwise. +func (o *TypesOption) GetDef() string { + if o == nil || IsNil(o.Def) { + var ret string + return ret + } + return *o.Def +} + +// GetDefOk returns a tuple with the Def field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TypesOption) GetDefOk() (*string, bool) { + if o == nil || IsNil(o.Def) { + return nil, false + } + return o.Def, true +} + +// HasDef returns a boolean if a field has been set. +func (o *TypesOption) HasDef() bool { + if o != nil && !IsNil(o.Def) { + return true + } + + return false +} + +// SetDef gets a reference to the given string and assigns it to the Def field. +func (o *TypesOption) SetDef(v string) { + o.Def = &v +} + +// GetTag returns the Tag field value if set, zero value otherwise. +func (o *TypesOption) GetTag() int32 { + if o == nil || IsNil(o.Tag) { + var ret int32 + return ret + } + return *o.Tag +} + +// GetTagOk returns a tuple with the Tag field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TypesOption) GetTagOk() (*int32, bool) { + if o == nil || IsNil(o.Tag) { + return nil, false + } + return o.Tag, true +} + +// HasTag returns a boolean if a field has been set. +func (o *TypesOption) HasTag() bool { + if o != nil && !IsNil(o.Tag) { + return true + } + + return false +} + +// SetTag gets a reference to the given int32 and assigns it to the Tag field. +func (o *TypesOption) SetTag(v int32) { + o.Tag = &v +} + +// GetTagName returns the TagName field value if set, zero value otherwise. +func (o *TypesOption) GetTagName() string { + if o == nil || IsNil(o.TagName) { + var ret string + return ret + } + return *o.TagName +} + +// GetTagNameOk returns a tuple with the TagName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TypesOption) GetTagNameOk() (*string, bool) { + if o == nil || IsNil(o.TagName) { + return nil, false + } + return o.TagName, true +} + +// HasTagName returns a boolean if a field has been set. +func (o *TypesOption) HasTagName() bool { + if o != nil && !IsNil(o.TagName) { + return true + } + + return false +} + +// SetTagName gets a reference to the given string and assigns it to the TagName field. +func (o *TypesOption) SetTagName(v string) { + o.TagName = &v +} + +// GetValue returns the Value field value if set, zero value otherwise. +func (o *TypesOption) GetValue() []string { + if o == nil || IsNil(o.Value) { + var ret []string + return ret + } + return o.Value +} + +// GetValueOk returns a tuple with the Value field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TypesOption) GetValueOk() ([]string, bool) { + if o == nil || IsNil(o.Value) { + return nil, false + } + return o.Value, true +} + +// HasValue returns a boolean if a field has been set. +func (o *TypesOption) HasValue() bool { + if o != nil && !IsNil(o.Value) { + return true + } + + return false +} + +// SetValue gets a reference to the given []string and assigns it to the Value field. +func (o *TypesOption) SetValue(v []string) { + o.Value = v +} + +// GetValue64 returns the Value64 field value if set, zero value otherwise. +func (o *TypesOption) GetValue64() []string { + if o == nil || IsNil(o.Value64) { + var ret []string + return ret + } + return o.Value64 +} + +// GetValue64Ok returns a tuple with the Value64 field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TypesOption) GetValue64Ok() ([]string, bool) { + if o == nil || IsNil(o.Value64) { + return nil, false + } + return o.Value64, true +} + +// HasValue64 returns a boolean if a field has been set. +func (o *TypesOption) HasValue64() bool { + if o != nil && !IsNil(o.Value64) { + return true + } + + return false +} + +// SetValue64 gets a reference to the given []string and assigns it to the Value64 field. +func (o *TypesOption) SetValue64(v []string) { + o.Value64 = v +} + +// GetValueHex returns the ValueHex field value if set, zero value otherwise. +func (o *TypesOption) GetValueHex() []string { + if o == nil || IsNil(o.ValueHex) { + var ret []string + return ret + } + return o.ValueHex +} + +// GetValueHexOk returns a tuple with the ValueHex field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TypesOption) GetValueHexOk() ([]string, bool) { + if o == nil || IsNil(o.ValueHex) { + return nil, false + } + return o.ValueHex, true +} + +// HasValueHex returns a boolean if a field has been set. +func (o *TypesOption) HasValueHex() bool { + if o != nil && !IsNil(o.ValueHex) { + return true + } + + return false +} + +// SetValueHex gets a reference to the given []string and assigns it to the ValueHex field. +func (o *TypesOption) SetValueHex(v []string) { + o.ValueHex = v +} + +// GetValueLegacy returns the ValueLegacy field value if set, zero value otherwise. +func (o *TypesOption) GetValueLegacy() string { + if o == nil || IsNil(o.ValueLegacy) { + var ret string + return ret + } + return *o.ValueLegacy +} + +// GetValueLegacyOk returns a tuple with the ValueLegacy field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *TypesOption) GetValueLegacyOk() (*string, bool) { + if o == nil || IsNil(o.ValueLegacy) { + return nil, false + } + return o.ValueLegacy, true +} + +// HasValueLegacy returns a boolean if a field has been set. +func (o *TypesOption) HasValueLegacy() bool { + if o != nil && !IsNil(o.ValueLegacy) { + return true + } + + return false +} + +// SetValueLegacy gets a reference to the given string and assigns it to the ValueLegacy field. +func (o *TypesOption) SetValueLegacy(v string) { + o.ValueLegacy = &v +} + +func (o TypesOption) MarshalJSON() ([]byte, error) { + toSerialize, err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o TypesOption) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.Def) { + toSerialize["def"] = o.Def + } + if !IsNil(o.Tag) { + toSerialize["tag"] = o.Tag + } + if !IsNil(o.TagName) { + toSerialize["tagName"] = o.TagName + } + if !IsNil(o.Value) { + toSerialize["value"] = o.Value + } + if !IsNil(o.Value64) { + toSerialize["value64"] = o.Value64 + } + if !IsNil(o.ValueHex) { + toSerialize["valueHex"] = o.ValueHex + } + if !IsNil(o.ValueLegacy) { + toSerialize["valueLegacy"] = o.ValueLegacy + } + return toSerialize, nil +} + +type NullableTypesOption struct { + value *TypesOption + isSet bool +} + +func (v NullableTypesOption) Get() *TypesOption { + return v.value +} + +func (v *NullableTypesOption) Set(val *TypesOption) { + v.value = val + v.isSet = true +} + +func (v NullableTypesOption) IsSet() bool { + return v.isSet +} + +func (v *NullableTypesOption) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableTypesOption(val *TypesOption) *NullableTypesOption { + return &NullableTypesOption{value: val, isSet: true} +} + +func (v NullableTypesOption) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableTypesOption) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/pkg/convert/ms_dhcp/convert.go b/pkg/convert/ms_dhcp/convert.go index aa845508e..8e6175bc1 100644 --- a/pkg/convert/ms_dhcp/convert.go +++ b/pkg/convert/ms_dhcp/convert.go @@ -91,7 +91,7 @@ func (c *Converter) convertScope(sc Scope, ctx context.Context) error { "range_start": sc.StartRange, "range_end": sc.EndRange, }, - Options: []api.TypesDHCPOption{}, + Options: []api.TypesOption{}, Hook: "", } for _, optv := range sc.OptionValues.OptionValue { @@ -102,9 +102,9 @@ func (c *Converter) convertScope(sc Scope, ctx context.Context) error { } t := int32(tag) v := optv.Value[0] - gscope.Options = append(gscope.Options, api.TypesDHCPOption{ - Tag: *api.NewNullableInt32(&t), - Value: *api.NewNullableString(&v), + gscope.Options = append(gscope.Options, api.TypesOption{ + Tag: api.PtrInt32(t), + ValueLegacy: api.PtrString(v), }) } name := slug.Make(sc.Name) diff --git a/pkg/instance/instance.go b/pkg/instance/instance.go index 8c7faa75f..cfc6422d9 100644 --- a/pkg/instance/instance.go +++ b/pkg/instance/instance.go @@ -190,7 +190,7 @@ func (i *Instance) bootstrap(ctx context.Context) { rootInstance.AddEventListener(types.EventTopicRoleRestart, i.eventRoleRestart) rootInstance.DispatchEvent( types.EventTopicInstanceBootstrapped, - roles.NewEvent(i.rootContext, map[string]interface{}{}), + roles.NewEvent(ctx, map[string]interface{}{}), ) i.checkFirstStart(ctx) wg := sync.WaitGroup{} diff --git a/pkg/roles/dhcp/leases.go b/pkg/roles/dhcp/leases.go index 2e6b4941b..1cbeb01e8 100644 --- a/pkg/roles/dhcp/leases.go +++ b/pkg/roles/dhcp/leases.go @@ -14,6 +14,7 @@ import ( "beryju.io/gravity/pkg/extconfig" "beryju.io/gravity/pkg/roles" + "beryju.io/gravity/pkg/roles/dhcp/options" "beryju.io/gravity/pkg/roles/dhcp/types" "beryju.io/gravity/pkg/roles/dns/utils" "github.com/insomniacslk/dhcp/dhcpv4" @@ -245,9 +246,10 @@ func (l *Lease) createReply(req *Request4) *dhcpv4.DHCPv4 { rep.UpdateOption(dhcpv4.OptServerIdentifier(rep.ServerIPAddr)) rep.YourIPAddr = net.ParseIP(l.Address) + // Legacy custom option handling for _, opt := range l.scope.Options { finalVal := make([]byte, 0) - if opt == nil || opt.Tag == nil && opt.TagName == "" { + if opt == nil || opt.Tag == 0 && opt.TagName == "" { continue } if opt.TagName != "" { @@ -256,14 +258,14 @@ func (l *Lease) createReply(req *Request4) *dhcpv4.DHCPv4 { req.log.Warn("invalid tag name", zap.String("tagName", opt.TagName)) continue } - opt.Tag = &tag + opt.Tag = uint32(tag) } // Values which are directly converted from string to byte - if opt.Value != nil { - finalVal = []byte(*opt.Value) - if _, ok := types.IPTags[*opt.Tag]; ok { - i := net.ParseIP(*opt.Value) + if opt.ValueLegacy != "" { + finalVal = []byte(opt.ValueLegacy) + if _, ok := types.IPTags[uint8(opt.Tag)]; ok { + i := net.ParseIP(opt.ValueLegacy) finalVal = dhcpv4.IPs([]net.IP{i}).ToBytes() } } @@ -293,11 +295,13 @@ func (l *Lease) createReply(req *Request4) *dhcpv4.DHCPv4 { } finalVal = valuesHex } - dopt := dhcpv4.OptGeneric(dhcpv4.GenericOptionCode(*opt.Tag), finalVal) + dopt := dhcpv4.OptGeneric(dhcpv4.GenericOptionCode(opt.Tag), finalVal) rep.UpdateOption(dopt) if dopt.Code.Code() == uint8(dhcpv4.OptionBootfileName) { rep.BootFileName = dhcpv4.GetString(dopt.Code, rep.Options) } } + // New definition-based option handling + options.ApplyToResponse(l.scope.Options, l.scope.role.optionDefinitions, req.DHCPv4, rep) return rep } diff --git a/pkg/roles/dhcp/options/bootstrap.go b/pkg/roles/dhcp/options/bootstrap.go new file mode 100644 index 000000000..449eafa6e --- /dev/null +++ b/pkg/roles/dhcp/options/bootstrap.go @@ -0,0 +1,96 @@ +package options + +import ( + "beryju.io/gravity/pkg/roles" + "beryju.io/gravity/pkg/roles/dhcp/options/types" + dhcpTypes "beryju.io/gravity/pkg/roles/dhcp/types" + "github.com/insomniacslk/dhcp/dhcpv4" + "google.golang.org/protobuf/proto" +) + +func OptionsIP() []dhcpv4.OptionCode { + return []dhcpv4.OptionCode{ + dhcpv4.OptionBroadcastAddress, + dhcpv4.OptionRequestedIPAddress, + dhcpv4.OptionServerIdentifier, + } +} + +func OptionsIPS() []dhcpv4.OptionCode { + return []dhcpv4.OptionCode{ + dhcpv4.OptionRouter, + dhcpv4.OptionNTPServers, + dhcpv4.OptionDomainNameServer, + } +} + +func OptionsMask() []dhcpv4.OptionCode { + return []dhcpv4.OptionCode{ + dhcpv4.OptionSubnetMask, + } +} + +func OptionsString() []dhcpv4.OptionCode { + return []dhcpv4.OptionCode{ + dhcpv4.OptionHostName, + dhcpv4.OptionDomainName, + dhcpv4.OptionRootPath, + dhcpv4.OptionBootfileName, + dhcpv4.OptionTFTPServerName, + dhcpv4.OptionClassIdentifier, + dhcpv4.OptionUserClassInformation, + // dhcpv4.OptionMessage, + } +} + +func Bootstrap(r roles.Instance) func(ev *roles.Event) { + return func(ev *roles.Event) { + opts := []*types.OptionDefinition{} + for _, opt := range OptionsIP() { + opts = append(opts, &types.OptionDefinition{ + Name: opt.String(), + Code: int32(opt.Code()), + IsArray: false, + Type: types.DataType_IP_ADDRESS, + }) + } + for _, opt := range OptionsIPS() { + opts = append(opts, &types.OptionDefinition{ + Name: opt.String(), + Code: int32(opt.Code()), + IsArray: true, + Type: types.DataType_IP_ADDRESS, + }) + } + for _, opt := range OptionsMask() { + opts = append(opts, &types.OptionDefinition{ + Name: opt.String(), + Code: int32(opt.Code()), + IsArray: false, + Type: types.DataType_IP_MASK, + }) + } + for _, opt := range OptionsString() { + opts = append(opts, &types.OptionDefinition{ + Name: opt.String(), + Code: int32(opt.Code()), + IsArray: false, + Type: types.DataType_STRING, + }) + } + for _, opt := range opts { + rv, err := proto.Marshal(opt) + if err != nil { + continue + } + _, err = r.KV().Put(ev.Context, r.KV().Key( + dhcpTypes.KeyRole, + dhcpTypes.KeyOptionDefinitions, + opt.Name, + ).String(), string(rv)) + if err != nil { + continue + } + } + } +} diff --git a/pkg/roles/dhcp/options/option.go b/pkg/roles/dhcp/options/option.go new file mode 100644 index 000000000..d745f8c72 --- /dev/null +++ b/pkg/roles/dhcp/options/option.go @@ -0,0 +1,58 @@ +package options + +import ( + "net" + + "beryju.io/gravity/pkg/roles/dhcp/options/types" + "beryju.io/gravity/pkg/storage/watcher" + "github.com/insomniacslk/dhcp/dhcpv4" +) + +type Option struct { + *types.Option + def *types.OptionDefinition +} + +func ApplyToResponse( + options []*types.Option, + defs *watcher.Watcher[*types.OptionDefinition], + req *dhcpv4.DHCPv4, + reply *dhcpv4.DHCPv4, +) { + for _, ropt := range options { + def, found := defs.GetPrefix(ropt.Def) + if !found { + continue + } + opt := &Option{ + Option: ropt, + def: def, + } + reply.UpdateOption(opt.toDHCPv4()) + } +} + +func (op *Option) toDHCPv4() dhcpv4.Option { + v := []byte{} + for idx, vv := range op.Data { + if idx > 1 && !op.def.IsArray { + break + } + v = append(v, op.encodeSingle(vv)...) + } + return dhcpv4.OptGeneric(dhcpv4.GenericOptionCode(op.def.Code), v) +} + +func (op *Option) encodeSingle(raw *types.OptionData) []byte { + switch op.def.Type { + case types.DataType_BYTE: + return raw.GetDataByte() + case types.DataType_STRING: + return dhcpv4.String(raw.GetDataString()).ToBytes() + case types.DataType_IP_ADDRESS: + return dhcpv4.IP(net.IP(raw.GetIp())) + case types.DataType_IP_MASK: + return dhcpv4.IPMask(net.IPMask(raw.GetIp())) + } + return []byte{} // unreachable +} diff --git a/pkg/roles/dhcp/options/types/role_dhcp_option.pb.go b/pkg/roles/dhcp/options/types/role_dhcp_option.pb.go new file mode 100644 index 000000000..0e515fafe --- /dev/null +++ b/pkg/roles/dhcp/options/types/role_dhcp_option.pb.go @@ -0,0 +1,273 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc v5.29.3 +// source: protobuf/role_dhcp_option.proto + +package types + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type OptionData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Data: + // + // *OptionData_DataByte + // *OptionData_Ip + // *OptionData_DataString + Data isOptionData_Data `protobuf_oneof:"data"` +} + +func (x *OptionData) Reset() { + *x = OptionData{} + if protoimpl.UnsafeEnabled { + mi := &file_protobuf_role_dhcp_option_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OptionData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OptionData) ProtoMessage() {} + +func (x *OptionData) ProtoReflect() protoreflect.Message { + mi := &file_protobuf_role_dhcp_option_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OptionData.ProtoReflect.Descriptor instead. +func (*OptionData) Descriptor() ([]byte, []int) { + return file_protobuf_role_dhcp_option_proto_rawDescGZIP(), []int{0} +} + +func (m *OptionData) GetData() isOptionData_Data { + if m != nil { + return m.Data + } + return nil +} + +func (x *OptionData) GetDataByte() []byte { + if x, ok := x.GetData().(*OptionData_DataByte); ok { + return x.DataByte + } + return nil +} + +func (x *OptionData) GetIp() []byte { + if x, ok := x.GetData().(*OptionData_Ip); ok { + return x.Ip + } + return nil +} + +func (x *OptionData) GetDataString() string { + if x, ok := x.GetData().(*OptionData_DataString); ok { + return x.DataString + } + return "" +} + +type isOptionData_Data interface { + isOptionData_Data() +} + +type OptionData_DataByte struct { + DataByte []byte `protobuf:"bytes,10,opt,name=data_byte,json=dataByte,proto3,oneof"` +} + +type OptionData_Ip struct { + Ip []byte `protobuf:"bytes,11,opt,name=ip,proto3,oneof"` +} + +type OptionData_DataString struct { + DataString string `protobuf:"bytes,12,opt,name=data_string,json=dataString,proto3,oneof"` +} + +func (*OptionData_DataByte) isOptionData_Data() {} + +func (*OptionData_Ip) isOptionData_Data() {} + +func (*OptionData_DataString) isOptionData_Data() {} + +type Option struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Tag uint32 `protobuf:"varint,1,opt,name=tag,proto3" json:"tag,omitempty"` + Data []*OptionData `protobuf:"bytes,2,rep,name=data,proto3" json:"data,omitempty"` +} + +func (x *Option) Reset() { + *x = Option{} + if protoimpl.UnsafeEnabled { + mi := &file_protobuf_role_dhcp_option_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Option) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Option) ProtoMessage() {} + +func (x *Option) ProtoReflect() protoreflect.Message { + mi := &file_protobuf_role_dhcp_option_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Option.ProtoReflect.Descriptor instead. +func (*Option) Descriptor() ([]byte, []int) { + return file_protobuf_role_dhcp_option_proto_rawDescGZIP(), []int{1} +} + +func (x *Option) GetTag() uint32 { + if x != nil { + return x.Tag + } + return 0 +} + +func (x *Option) GetData() []*OptionData { + if x != nil { + return x.Data + } + return nil +} + +var File_protobuf_role_dhcp_option_proto protoreflect.FileDescriptor + +var file_protobuf_role_dhcp_option_proto_rawDesc = []byte{ + 0x0a, 0x1f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, + 0x64, 0x68, 0x63, 0x70, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x68, 0x0a, 0x0a, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, + 0x1d, 0x0a, 0x09, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x0c, 0x48, 0x00, 0x52, 0x08, 0x64, 0x61, 0x74, 0x61, 0x42, 0x79, 0x74, 0x65, 0x12, 0x10, + 0x0a, 0x02, 0x69, 0x70, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x02, 0x69, 0x70, + 0x12, 0x21, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x42, 0x06, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x3b, 0x0a, 0x06, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x1f, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, + 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x1e, 0x5a, 0x1c, 0x70, 0x6b, 0x67, 0x2f, + 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2f, 0x64, 0x68, 0x63, 0x70, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_protobuf_role_dhcp_option_proto_rawDescOnce sync.Once + file_protobuf_role_dhcp_option_proto_rawDescData = file_protobuf_role_dhcp_option_proto_rawDesc +) + +func file_protobuf_role_dhcp_option_proto_rawDescGZIP() []byte { + file_protobuf_role_dhcp_option_proto_rawDescOnce.Do(func() { + file_protobuf_role_dhcp_option_proto_rawDescData = protoimpl.X.CompressGZIP(file_protobuf_role_dhcp_option_proto_rawDescData) + }) + return file_protobuf_role_dhcp_option_proto_rawDescData +} + +var file_protobuf_role_dhcp_option_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_protobuf_role_dhcp_option_proto_goTypes = []any{ + (*OptionData)(nil), // 0: OptionData + (*Option)(nil), // 1: Option +} +var file_protobuf_role_dhcp_option_proto_depIdxs = []int32{ + 0, // 0: Option.data:type_name -> OptionData + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_protobuf_role_dhcp_option_proto_init() } +func file_protobuf_role_dhcp_option_proto_init() { + if File_protobuf_role_dhcp_option_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_protobuf_role_dhcp_option_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*OptionData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_protobuf_role_dhcp_option_proto_msgTypes[1].Exporter = func(v any, i int) any { + switch v := v.(*Option); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_protobuf_role_dhcp_option_proto_msgTypes[0].OneofWrappers = []any{ + (*OptionData_DataByte)(nil), + (*OptionData_Ip)(nil), + (*OptionData_DataString)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_protobuf_role_dhcp_option_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_protobuf_role_dhcp_option_proto_goTypes, + DependencyIndexes: file_protobuf_role_dhcp_option_proto_depIdxs, + MessageInfos: file_protobuf_role_dhcp_option_proto_msgTypes, + }.Build() + File_protobuf_role_dhcp_option_proto = out.File + file_protobuf_role_dhcp_option_proto_rawDesc = nil + file_protobuf_role_dhcp_option_proto_goTypes = nil + file_protobuf_role_dhcp_option_proto_depIdxs = nil +} diff --git a/pkg/roles/dhcp/options/types/role_dhcp_option_definition.pb.go b/pkg/roles/dhcp/options/types/role_dhcp_option_definition.pb.go new file mode 100644 index 000000000..b77229f93 --- /dev/null +++ b/pkg/roles/dhcp/options/types/role_dhcp_option_definition.pb.go @@ -0,0 +1,243 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc v5.29.3 +// source: protobuf/role_dhcp_option_definition.proto + +package types + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type DataType int32 + +const ( + DataType_BYTE DataType = 0 + DataType_IP_ADDRESS DataType = 1 + DataType_IP_MASK DataType = 2 + DataType_STRING DataType = 3 +) + +// Enum value maps for DataType. +var ( + DataType_name = map[int32]string{ + 0: "BYTE", + 1: "IP_ADDRESS", + 2: "IP_MASK", + 3: "STRING", + } + DataType_value = map[string]int32{ + "BYTE": 0, + "IP_ADDRESS": 1, + "IP_MASK": 2, + "STRING": 3, + } +) + +func (x DataType) Enum() *DataType { + p := new(DataType) + *p = x + return p +} + +func (x DataType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DataType) Descriptor() protoreflect.EnumDescriptor { + return file_protobuf_role_dhcp_option_definition_proto_enumTypes[0].Descriptor() +} + +func (DataType) Type() protoreflect.EnumType { + return &file_protobuf_role_dhcp_option_definition_proto_enumTypes[0] +} + +func (x DataType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DataType.Descriptor instead. +func (DataType) EnumDescriptor() ([]byte, []int) { + return file_protobuf_role_dhcp_option_definition_proto_rawDescGZIP(), []int{0} +} + +type OptionDefinition struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Type DataType `protobuf:"varint,2,opt,name=type,proto3,enum=DataType" json:"type,omitempty"` + IsArray bool `protobuf:"varint,3,opt,name=isArray,proto3" json:"isArray,omitempty"` + Code int32 `protobuf:"varint,4,opt,name=code,proto3" json:"code,omitempty"` + Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` +} + +func (x *OptionDefinition) Reset() { + *x = OptionDefinition{} + if protoimpl.UnsafeEnabled { + mi := &file_protobuf_role_dhcp_option_definition_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OptionDefinition) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OptionDefinition) ProtoMessage() {} + +func (x *OptionDefinition) ProtoReflect() protoreflect.Message { + mi := &file_protobuf_role_dhcp_option_definition_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OptionDefinition.ProtoReflect.Descriptor instead. +func (*OptionDefinition) Descriptor() ([]byte, []int) { + return file_protobuf_role_dhcp_option_definition_proto_rawDescGZIP(), []int{0} +} + +func (x *OptionDefinition) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *OptionDefinition) GetType() DataType { + if x != nil { + return x.Type + } + return DataType_BYTE +} + +func (x *OptionDefinition) GetIsArray() bool { + if x != nil { + return x.IsArray + } + return false +} + +func (x *OptionDefinition) GetCode() int32 { + if x != nil { + return x.Code + } + return 0 +} + +func (x *OptionDefinition) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +var File_protobuf_role_dhcp_option_definition_proto protoreflect.FileDescriptor + +var file_protobuf_role_dhcp_option_definition_proto_rawDesc = []byte{ + 0x0a, 0x2a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, + 0x64, 0x68, 0x63, 0x70, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x66, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x95, 0x01, 0x0a, + 0x10, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x12, + 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, + 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x3d, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x08, 0x0a, 0x04, 0x42, 0x59, 0x54, 0x45, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x50, + 0x5f, 0x41, 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x50, + 0x5f, 0x4d, 0x41, 0x53, 0x4b, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, + 0x47, 0x10, 0x03, 0x42, 0x1e, 0x5a, 0x1c, 0x70, 0x6b, 0x67, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, + 0x2f, 0x64, 0x68, 0x63, 0x70, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_protobuf_role_dhcp_option_definition_proto_rawDescOnce sync.Once + file_protobuf_role_dhcp_option_definition_proto_rawDescData = file_protobuf_role_dhcp_option_definition_proto_rawDesc +) + +func file_protobuf_role_dhcp_option_definition_proto_rawDescGZIP() []byte { + file_protobuf_role_dhcp_option_definition_proto_rawDescOnce.Do(func() { + file_protobuf_role_dhcp_option_definition_proto_rawDescData = protoimpl.X.CompressGZIP(file_protobuf_role_dhcp_option_definition_proto_rawDescData) + }) + return file_protobuf_role_dhcp_option_definition_proto_rawDescData +} + +var file_protobuf_role_dhcp_option_definition_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_protobuf_role_dhcp_option_definition_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_protobuf_role_dhcp_option_definition_proto_goTypes = []any{ + (DataType)(0), // 0: DataType + (*OptionDefinition)(nil), // 1: OptionDefinition +} +var file_protobuf_role_dhcp_option_definition_proto_depIdxs = []int32{ + 0, // 0: OptionDefinition.type:type_name -> DataType + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_protobuf_role_dhcp_option_definition_proto_init() } +func file_protobuf_role_dhcp_option_definition_proto_init() { + if File_protobuf_role_dhcp_option_definition_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_protobuf_role_dhcp_option_definition_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*OptionDefinition); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_protobuf_role_dhcp_option_definition_proto_rawDesc, + NumEnums: 1, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_protobuf_role_dhcp_option_definition_proto_goTypes, + DependencyIndexes: file_protobuf_role_dhcp_option_definition_proto_depIdxs, + EnumInfos: file_protobuf_role_dhcp_option_definition_proto_enumTypes, + MessageInfos: file_protobuf_role_dhcp_option_definition_proto_msgTypes, + }.Build() + File_protobuf_role_dhcp_option_definition_proto = out.File + file_protobuf_role_dhcp_option_definition_proto_rawDesc = nil + file_protobuf_role_dhcp_option_definition_proto_goTypes = nil + file_protobuf_role_dhcp_option_definition_proto_depIdxs = nil +} diff --git a/pkg/roles/dhcp/role.go b/pkg/roles/dhcp/role.go index 85b3f5615..e30d2a6e9 100644 --- a/pkg/roles/dhcp/role.go +++ b/pkg/roles/dhcp/role.go @@ -7,8 +7,11 @@ import ( "strings" "beryju.io/gravity/pkg/extconfig" + instanceTypes "beryju.io/gravity/pkg/instance/types" "beryju.io/gravity/pkg/roles" apitypes "beryju.io/gravity/pkg/roles/api/types" + "beryju.io/gravity/pkg/roles/dhcp/options" + optTypes "beryju.io/gravity/pkg/roles/dhcp/options/types" "beryju.io/gravity/pkg/roles/dhcp/oui" "beryju.io/gravity/pkg/roles/dhcp/types" "beryju.io/gravity/pkg/storage/watcher" @@ -26,8 +29,9 @@ type Role struct { i roles.Instance ctx context.Context - scopes *watcher.Watcher[*Scope] - leases *watcher.Watcher[*Lease] + scopes *watcher.Watcher[*Scope] + leases *watcher.Watcher[*Lease] + optionDefinitions *watcher.Watcher[*optTypes.OptionDefinition] cfg *RoleConfig @@ -58,8 +62,8 @@ func New(instance roles.Instance) *Role { s.calculateUsage() return s, nil }, - instance.KV(), - instance.KV().Key( + r.i.KV(), + r.i.KV().Key( types.KeyRole, types.KeyScopes, ).Prefix(true), @@ -73,7 +77,7 @@ func New(instance roles.Instance) *Role { } return s, nil }, - instance.KV(), + r.i.KV(), r.i.KV().Key( types.KeyRole, types.KeyLeases, @@ -85,9 +89,18 @@ func New(instance roles.Instance) *Role { }), ) + r.optionDefinitions = watcher.NewProto[*optTypes.OptionDefinition]( + r.i.KV(), + r.i.KV().Key( + types.KeyRole, + types.KeyOptionDefinitions, + ).Prefix(true), + ) + r.s4 = &handler4{ role: r, } + r.i.AddEventListener(instanceTypes.EventTopicInstanceBootstrapped, options.Bootstrap(r.i)) r.i.AddEventListener(types.EventTopicDHCPCreateLease, r.eventCreateLease) r.i.AddEventListener(apitypes.EventTopicAPIMuxSetup, func(ev *roles.Event) { svc := ev.Payload.Data["svc"].(*web.Service) diff --git a/pkg/roles/dhcp/scopes.go b/pkg/roles/dhcp/scopes.go index 623646fd1..860da1295 100644 --- a/pkg/roles/dhcp/scopes.go +++ b/pkg/roles/dhcp/scopes.go @@ -26,22 +26,21 @@ type ScopeDNS struct { type Scope struct { ipam IPAM inst roles.Instance - DNS *ScopeDNS `json:"dns"` - - IPAM map[string]string `json:"ipam"` role *Role log *zap.Logger - cidr netip.Prefix - Name string `json:"-"` - - etcdKey string + Name string `json:"-"` + DNS *ScopeDNS `json:"dns"` + IPAM map[string]string `json:"ipam"` SubnetCIDR string `json:"subnetCidr"` Options []*types.DHCPOption `json:"options"` TTL int64 `json:"ttl"` Default bool `json:"default"` Hook string `json:"hook"` + + cidr netip.Prefix + etcdKey string } func (r *Role) NewScope(name string) *Scope { diff --git a/pkg/roles/dhcp/types/role.go b/pkg/roles/dhcp/types/role.go index a5ef2699f..1ca84f61e 100644 --- a/pkg/roles/dhcp/types/role.go +++ b/pkg/roles/dhcp/types/role.go @@ -1,7 +1,8 @@ package types const ( - KeyRole = "dhcp" - KeyLeases = "leases" - KeyScopes = "scopes" + KeyRole = "dhcp" + KeyLeases = "leases" + KeyScopes = "scopes" + KeyOptionDefinitions = "option_definitions" ) diff --git a/pkg/roles/tsdb/types/role_tsdb_record.pb.go b/pkg/roles/tsdb/types/role_tsdb_record.pb.go index 66365860c..14aa7a3da 100644 --- a/pkg/roles/tsdb/types/role_tsdb_record.pb.go +++ b/pkg/roles/tsdb/types/role_tsdb_record.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v5.28.3 +// protoc v5.29.3 // source: protobuf/role_tsdb_record.proto package types diff --git a/pkg/storage/watcher/proto.go b/pkg/storage/watcher/proto.go new file mode 100644 index 000000000..7a0ecacf0 --- /dev/null +++ b/pkg/storage/watcher/proto.go @@ -0,0 +1,26 @@ +package watcher + +import ( + "beryju.io/gravity/pkg/storage" + "go.etcd.io/etcd/api/v3/mvccpb" + "google.golang.org/protobuf/proto" +) + +func NewProto[T proto.Message]( + client *storage.Client, + prefix *storage.Key, + opts ...func(w *Watcher[T]), +) *Watcher[T] { + _ = new(T) + return New( + func(kv *mvccpb.KeyValue) (T, error) { + obj := new(T) + err := proto.Unmarshal(kv.Value, *obj) + if err != nil { + return *obj, err + } + return *obj, nil + }, + client, prefix, opts..., + ) +} diff --git a/protobuf/role_dhcp_option.proto b/protobuf/role_dhcp_option.proto new file mode 100644 index 000000000..9cc15f6f9 --- /dev/null +++ b/protobuf/role_dhcp_option.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +option go_package = "pkg/roles/dhcp/options/types"; + +message OptionData { + oneof data { + bytes data_byte = 10; + bytes ip = 11; + string data_string = 12; + } +} + +message Option { + uint32 tag = 1; + repeated OptionData data = 2; +} diff --git a/protobuf/role_dhcp_option_definition.proto b/protobuf/role_dhcp_option_definition.proto new file mode 100644 index 000000000..90200d97b --- /dev/null +++ b/protobuf/role_dhcp_option_definition.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +option go_package = "pkg/roles/dhcp/options/types"; + +enum DataType { + BYTE = 0; + IP_ADDRESS = 1; + IP_MASK = 2; + STRING = 3; +} + +message OptionDefinition { + string name = 1; + DataType type = 2; + bool isArray = 3; + int32 code = 4; + string description = 5; +} diff --git a/schema.yml b/schema.yml index 5ed0038c9..e4ecd7b14 100644 --- a/schema.yml +++ b/schema.yml @@ -2116,7 +2116,7 @@ components: type: object options: items: - $ref: '#/components/schemas/TypesDHCPOption' + $ref: '#/components/schemas/TypesOption' nullable: true type: array scope: @@ -2193,7 +2193,7 @@ components: type: object options: items: - $ref: '#/components/schemas/TypesDHCPOption' + $ref: '#/components/schemas/TypesOption' nullable: true type: array subnetCidr: @@ -2742,28 +2742,6 @@ components: - system - dns type: string - TypesDHCPOption: - properties: - tag: - minimum: 0 - nullable: true - type: integer - tagName: - type: string - value: - nullable: true - type: string - value64: - items: - type: string - nullable: true - type: array - valueHex: - items: - type: string - nullable: true - type: array - type: object TypesOIDCConfig: properties: clientID: @@ -2782,3 +2760,28 @@ components: tokenUsernameField: type: string type: object + TypesOption: + properties: + def: + type: string + tag: + minimum: 0 + type: integer + tagName: + type: string + value: + items: + format: base64 + type: string + type: array + value64: + items: + type: string + type: array + valueHex: + items: + type: string + type: array + valueLegacy: + type: string + type: object diff --git a/tests/dhcp_e2e_test.go b/tests/dhcp_e2e_test.go index 6aa80f727..2f3a01e87 100644 --- a/tests/dhcp_e2e_test.go +++ b/tests/dhcp_e2e_test.go @@ -47,7 +47,7 @@ func TestDHCP_Simple(t *testing.T) { "type": "internal", "should_ping": "true", }, - Options: []api.TypesDHCPOption{}, + Options: []api.TypesOption{}, }).Scope("network-A").Execute() assert.NoError(t, err) @@ -113,7 +113,7 @@ func TestDHCP_Parallel(t *testing.T) { "range_start": "10.100.0.100", "type": "internal", }, - Options: []api.TypesDHCPOption{}, + Options: []api.TypesOption{}, }).Scope("network-A").Execute() assert.NoError(t, err) @@ -203,7 +203,7 @@ func TestDHCP_Relay(t *testing.T) { "range_start": "10.100.0.100", "type": "internal", }, - Options: []api.TypesDHCPOption{}, + Options: []api.TypesOption{}, }).Scope("network-A").Execute() assert.NoError(t, err) _, err = ac.RolesDhcpApi.DhcpPutScopes(ctx).DhcpAPIScopesPutInput(api.DhcpAPIScopesPutInput{ @@ -214,7 +214,7 @@ func TestDHCP_Relay(t *testing.T) { "range_start": "10.101.0.100", "type": "internal", }, - Options: []api.TypesDHCPOption{}, + Options: []api.TypesOption{}, }).Scope("network-B").Execute() assert.NoError(t, err) @@ -301,7 +301,7 @@ func TestDHCP_WOL(t *testing.T) { "type": "internal", "should_ping": "true", }, - Options: []api.TypesDHCPOption{}, + Options: []api.TypesOption{}, }).Scope("network-A").Execute() assert.NoError(t, err)