Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENG-12292: Add: SQL Server settings (version field) #438

Merged
merged 12 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,8 @@ docker-compose/docs:
sweep:
@echo "WARNING: This will destroy infrastructure. Use only for development control planes."
go test $(SWEEPDIR) -v -sweep=dummy-region $(SWEEPARGS) -timeout 15m

# update module and test dependencies to latest minor and patch level
up-deps:
$(GOGET) -u ./...
$(GOGET) -t ./...
18 changes: 10 additions & 8 deletions cyral/data_source_cyral_sidecar_listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import (
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could you please delete this blank line so that all 3rd party imports are in the same block?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

"github.com/cyralinc/terraform-provider-cyral/client"
"golang.org/x/exp/slices"

"github.com/cyralinc/terraform-provider-cyral/client"
)

const (
Expand All @@ -33,13 +34,14 @@ func (data ReadDataSourceSidecarListenerAPIResponse) WriteToSchema(d *schema.Res
if (repoTypeFilter == "" || slices.Contains(listenerConfig.RepoTypes, repoTypeFilter)) &&
(portFilter == 0 || listenerConfig.NetworkAddress.Port == portFilter) {
listener := map[string]any{
ListenerIDKey: listenerConfig.ListenerId,
SidecarIDKey: d.Get(SidecarIDKey).(string),
RepoTypesKey: listenerConfig.RepoTypes,
NetworkAddressKey: listenerConfig.NetworkAddressAsInterface(),
MySQLSettingsKey: listenerConfig.MySQLSettingsAsInterface(),
S3SettingsKey: listenerConfig.S3SettingsAsInterface(),
DynamoDbSettingsKey: listenerConfig.DynamoDbSettingsAsInterface(),
ListenerIDKey: listenerConfig.ListenerId,
SidecarIDKey: d.Get(SidecarIDKey).(string),
RepoTypesKey: listenerConfig.RepoTypes,
NetworkAddressKey: listenerConfig.NetworkAddressAsInterface(),
MySQLSettingsKey: listenerConfig.MySQLSettingsAsInterface(),
S3SettingsKey: listenerConfig.S3SettingsAsInterface(),
DynamoDbSettingsKey: listenerConfig.DynamoDbSettingsAsInterface(),
SQLServerSettingsKey: listenerConfig.SQLServerSettingsAsInterface(),
}
log.Printf("[DEBUG] listener: %q", listener)
listenersList = append(listenersList, listener)
Expand Down
99 changes: 81 additions & 18 deletions cyral/resource_cyral_sidecar_listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,36 @@ import (
// create a constant block for schema keys

const (
RepoTypesKey = "repo_types"
NetworkAddressKey = "network_address"
MySQLSettingsKey = "mysql_settings"
DbVersionKey = "db_version"
CharacterSetKey = "character_set"
S3SettingsKey = "s3_settings"
ProxyModeKey = "proxy_mode"
DynamoDbSettingsKey = "dynamodb_settings"
RepoTypesKey = "repo_types"
NetworkAddressKey = "network_address"
MySQLSettingsKey = "mysql_settings"
DbVersionKey = "db_version"
CharacterSetKey = "character_set"
S3SettingsKey = "s3_settings"
ProxyModeKey = "proxy_mode"
DynamoDbSettingsKey = "dynamodb_settings"
SQLServerSettingsKey = "sqlserver_settings"
VersionKey = "version"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about (for clarity)?

Suggested change
VersionKey = "version"
SQLServerVersionKey = "version"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I took your suggestion. Thanks

)

func tlsModes() []string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bring this change in later (since it's not being planned for implementation right now)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you, leftover from refactor. Missed this one.

return []string{
"allow", // default, must be kept at position 0
"require",
"disable",
}
}

// SidecarListener struct for sidecar listener.
type SidecarListener struct {
SidecarId string `json:"-"`
ListenerId string `json:"id"`
RepoTypes []string `json:"repoTypes"`
NetworkAddress *NetworkAddress `json:"address,omitempty"`
MySQLSettings *MySQLSettings `json:"mysqlSettings,omitempty"`
S3Settings *S3Settings `json:"s3Settings,omitempty"`
DynamoDbSettings *DynamoDbSettings `json:"dynamoDbSettings,omitempty"`
SidecarId string `json:"-"`
ListenerId string `json:"id"`
RepoTypes []string `json:"repoTypes"`
NetworkAddress *NetworkAddress `json:"address,omitempty"`
MySQLSettings *MySQLSettings `json:"mysqlSettings,omitempty"`
S3Settings *S3Settings `json:"s3Settings,omitempty"`
DynamoDbSettings *DynamoDbSettings `json:"dynamoDbSettings,omitempty"`
SQLServerSettings *SQLServerSettings `json:"sqlServerSettings,omitempty"`
}
type NetworkAddress struct {
Host string `json:"host,omitempty"`
Expand All @@ -49,6 +60,10 @@ type DynamoDbSettings struct {
ProxyMode bool `json:"proxyMode,omitempty"`
}

type SQLServerSettings struct {
Version string `json:"version,omitempty"`
}

var ReadSidecarListenersConfig = ResourceOperationConfig{
Name: "SidecarListenersResourceRead",
HttpMethod: http.MethodGet,
Expand Down Expand Up @@ -83,6 +98,7 @@ func (data ReadSidecarListenerAPIResponse) WriteToSchema(d *schema.ResourceData)
_ = d.Set(S3SettingsKey, data.ListenerConfig.S3SettingsAsInterface())
_ = d.Set(MySQLSettingsKey, data.ListenerConfig.MySQLSettingsAsInterface())
_ = d.Set(DynamoDbSettingsKey, data.ListenerConfig.DynamoDbSettingsAsInterface())
_ = d.Set(SQLServerSettingsKey, data.ListenerConfig.SQLServerSettingsAsInterface())
}
log.Printf("[DEBUG] End ReadSidecarListenerAPIResponse.WriteToSchema")
return nil
Expand Down Expand Up @@ -175,6 +191,22 @@ func (l *SidecarListener) DynamoDbSettingsFromInterface(anInterface []interface{
ProxyMode: anInterface[0].(map[string]interface{})[ProxyModeKey].(bool),
}
}
func (l *SidecarListener) SQLServerSettingsAsInterface() []interface{} {
if l.SQLServerSettings == nil {
return nil
}
return []interface{}{map[string]interface{}{
VersionKey: l.SQLServerSettings.Version,
}}
}
func (l *SidecarListener) SQLServerSettingsFromInterface(anInterface []interface{}) {
if len(anInterface) == 0 {
return
}
l.SQLServerSettings = &SQLServerSettings{
Version: anInterface[0].(map[string]interface{})[VersionKey].(string),
}
}

// SidecarListenerResource represents the payload of a create or update a listener request
type SidecarListenerResource struct {
Expand All @@ -192,6 +224,8 @@ func (s *SidecarListenerResource) ReadFromSchema(d *schema.ResourceData) error {
s.ListenerConfig.MySQLSettingsFromInterface(d.Get(MySQLSettingsKey).(*schema.Set).List())
s.ListenerConfig.S3SettingsFromInterface(d.Get(S3SettingsKey).(*schema.Set).List())
s.ListenerConfig.DynamoDbSettingsFromInterface(d.Get(DynamoDbSettingsKey).(*schema.Set).List())
s.ListenerConfig.SQLServerSettingsFromInterface(d.Get(SQLServerSettingsKey).(*schema.Set).List())

return nil
}

Expand All @@ -205,7 +239,7 @@ func resourceSidecarListener() *schema.Resource {
return &schema.Resource{
Description: "Manages [sidecar listeners](https://cyral.com/docs/sidecars/sidecar-listeners)." +
"\n~> **Warning** Multiple listeners can be associated to a single sidecar as long as " +
"`host` and `port` are unique. If `host` is ommitted, then `port` must be unique.",
"`host` and `port` are unique. If `host` is omitted, then `port` must be unique.",
CreateContext: CreateResource(
ResourceOperationConfig{
Name: "SidecarListenersResourceCreate",
Expand Down Expand Up @@ -315,7 +349,7 @@ func getSidecarListenerSchema() map[string]*schema.Schema {
Optional: true,
// Notice the MaxItems: 1 here. This ensures that the user can only specify one this block.
MaxItems: 1,
ConflictsWith: []string{S3SettingsKey, DynamoDbSettingsKey},
ConflictsWith: []string{S3SettingsKey, DynamoDbSettingsKey, SQLServerSettingsKey},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
DbVersionKey: {
Expand Down Expand Up @@ -352,7 +386,7 @@ func getSidecarListenerSchema() map[string]*schema.Schema {
Optional: true,
// Notice the MaxItems: 1 here. This ensures that the user can only specify one this block.
MaxItems: 1,
ConflictsWith: []string{MySQLSettingsKey, DynamoDbSettingsKey},
ConflictsWith: []string{MySQLSettingsKey, DynamoDbSettingsKey, SQLServerSettingsKey},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also update the ConflictsWith in DynamoDbSettingsKey?

ConflictsWith: []string{S3SettingsKey, MySQLSettingsKey, SQLServerSettingsKey}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, sorry. Fixed

Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
ProxyModeKey: {
Expand Down Expand Up @@ -402,5 +436,34 @@ func getSidecarListenerSchema() map[string]*schema.Schema {
},
},
},
SQLServerSettingsKey: {
Description: "SQL Server settings.",
Type: schema.TypeSet,
Optional: true,
// Notice the MaxItems: 1 here. This ensures that the user can only specify one this block.
MaxItems: 1,
ConflictsWith: []string{S3SettingsKey, MySQLSettingsKey, DynamoDbSettingsKey},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
VersionKey: {
Description: "Advertised SQL Server version. Required (and only relevant) for " +
"Listeners of type 'sqlserver' " +
"The format of the version should be <major>.<minor>.<build_number> " +
"API will validate that the version is a valid version number. " +
"Major version is an integer in range 0-255. " +
"Minor version is an integer in range 0-255. " +
"Build number is an integer in range 0-65535. " +
"Example: 16.0.1000 " +
"To get the version of the SQL Server runtime, run the following query: " +
"SELECT SERVERPROPERTY('productversion') " +
"Note: If the query returns a four part version number, only the first three parts " +
"should be used. Example: 16.0.1000.6 -> 16.0.1000",
Type: schema.TypeString,
Optional: false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Optional: false,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In API Sqlserver settings is optional, if provided though, it has to carry the version so I believe we want to align with that here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, my intention here is just to point out that there's no need to specify Optional: false - it can be omitted from the schema declaration, especially because we are already defining Required: true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, sorry I didn't get that at first :) Want me to remove and push or leave it be?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gengdahlCyral thats just a nit, so up to you! Let me know once we can merge the PR and I can help with that, changes look good to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I removed this line, it's a bit confusing to have optional and required mixed (and not really valid when I read the docs).
Feel free to merge. @VictorGFM

Required: true,
},
},
},
},
}
}
15 changes: 15 additions & 0 deletions cyral/resource_cyral_sidecar_listener_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,17 @@ func settingsTest() []resource.TestStep {
ProxyMode: true,
},
}
// SQL Server settings test step
sqlServerSettings := SidecarListener{
RepoTypes: []string{"sqlserver"},
NetworkAddress: &NetworkAddress{
Port: 8004,
Host: "https://sqlserver.test.com",
},
SQLServerSettings: &SQLServerSettings{
Version: "16.0.1000",
},
}

return []resource.TestStep{
setupSidecarListenerTestStep(
Expand All @@ -153,6 +164,10 @@ func settingsTest() []resource.TestStep {
"dynamo_db_with_proxy",
dynamodb,
),
setupSidecarListenerTestStep(
"sql_server_settings",
sqlServerSettings,
),
}
}

Expand Down
9 changes: 9 additions & 0 deletions docs/data-sources/sidecar_listener.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Read-Only:
- `repo_types` (List of String)
- `s3_settings` (Set of Object) (see [below for nested schema](#nestedobjatt--listener_list--s3_settings))
- `sidecar_id` (String)
- `sqlserver_settings` (Set of Object) (see [below for nested schema](#nestedobjatt--listener_list--sqlserver_settings))

<a id="nestedobjatt--listener_list--dynamodb_settings"></a>

Expand Down Expand Up @@ -89,3 +90,11 @@ Read-Only:
Read-Only:

- `proxy_mode` (Boolean)

<a id="nestedobjatt--listener_list--sqlserver_settings"></a>

### Nested Schema for `listener_list.sqlserver_settings`

Read-Only:

- `version` (String)
11 changes: 10 additions & 1 deletion docs/resources/sidecar_listener.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# cyral_sidecar_listener (Resource)

Manages [sidecar listeners](https://cyral.com/docs/sidecars/sidecar-listeners).
~> **Warning** Multiple listeners can be associated to a single sidecar as long as `host` and `port` are unique. If `host` is ommitted, then `port` must be unique.
~> **Warning** Multiple listeners can be associated to a single sidecar as long as `host` and `port` are unique. If `host` is omitted, then `port` must be unique.

-> Import ID syntax is `{sidecar_id}/{listener_id}`.

Expand Down Expand Up @@ -106,6 +106,7 @@ resource "cyral_sidecar_listener" "listener_dynamodb" {
- `dynamodb_settings` (Block Set, Max: 1) DynamoDB settings. (see [below for nested schema](#nestedblock--dynamodb_settings))
- `mysql_settings` (Block Set, Max: 1) MySQL settings represents the listener settings for a [`mysql`, `galera`, `mariadb`] data repository. (see [below for nested schema](#nestedblock--mysql_settings))
- `s3_settings` (Block Set, Max: 1) S3 settings. (see [below for nested schema](#nestedblock--s3_settings))
- `sqlserver_settings` (Block Set, Max: 1) SQL Server settings. (see [below for nested schema](#nestedblock--sqlserver_settings))

### Read-Only

Expand Down Expand Up @@ -148,3 +149,11 @@ Optional:
Optional:

- `proxy_mode` (Boolean) S3 proxy mode. Only relevant for S3 listeners. Allowed values: [true, false]. Defaults to `false`. When `true`, instructs the sidecar to operate as an HTTP Proxy server. Client applications need to be explicitly configured to send the traffic through an HTTP proxy server, represented by the Cyral sidecar endpoint + the S3 listening port. It is indicated when connecting from CLI applications, such as `aws cli`, or through the AWS SDK. This listener mode is functional for client applications using either AWS native credentials, e.g. Access Key ID/Secret Access Key, or Cyral-Provided access tokens (Single Sign-On connections). When `false`, instructs the sidecar to mimic the actual behavior of AWS S3, meaning client applications will not be aware of a middleware HTTP proxy in the path to S3. This listener mode is only compatible with applications using Cyral-Provided access tokens and is must used when configuring the Cyral S3 Browser. This mode is currently not recommended for any other use besides the Cyral S3 Browser.

<a id="nestedblock--sqlserver_settings"></a>

### Nested Schema for `sqlserver_settings`

Required:

- `version` (String) Advertised SQL Server version. Required (and only relevant) for Listeners of type 'sqlserver' The format of the version should be <major>.<minor>.<build_number> API will validate that the version is a valid version number. Major version is an integer in range 0-255. Minor version is an integer in range 0-255. Build number is an integer in range 0-65535. Example: 16.0.1000 To get the version of the SQL Server runtime, run the following query: SELECT SERVERPROPERTY('productversion') Note: If the query returns a four part version number, only the first three parts should be used. Example: 16.0.1000.6 -> 16.0.1000
56 changes: 28 additions & 28 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,76 +3,76 @@ module github.com/cyralinc/terraform-provider-cyral
go 1.19

require (
github.com/aws/aws-sdk-go v1.39.4
github.com/aws/aws-sdk-go v1.44.327
github.com/google/uuid v1.3.0
github.com/hashicorp/terraform-plugin-docs v0.16.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.25.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.27.0
github.com/stretchr/testify v1.8.4
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df
golang.org/x/oauth2 v0.4.0
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
golang.org/x/oauth2 v0.11.0
)

require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect
github.com/agext/levenshtein v1.2.2 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
github.com/hashicorp/go-hclog v1.4.0 // indirect
github.com/hashicorp/go-hclog v1.5.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-plugin v1.4.8 // indirect
github.com/hashicorp/go-plugin v1.4.10 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/hc-install v0.5.2 // indirect
github.com/hashicorp/hcl/v2 v2.16.1 // indirect
github.com/hashicorp/hcl/v2 v2.17.0 // indirect
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform-exec v0.18.1 // indirect
github.com/hashicorp/terraform-json v0.17.1 // indirect
github.com/hashicorp/terraform-plugin-go v0.14.3 // indirect
github.com/hashicorp/terraform-plugin-log v0.8.0 // indirect
github.com/hashicorp/terraform-registry-address v0.1.0 // indirect
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect
github.com/hashicorp/terraform-plugin-go v0.18.0 // indirect
github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect
github.com/hashicorp/terraform-registry-address v0.2.2 // indirect
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mitchellh/cli v1.1.5 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/oklog/run v1.0.0 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/posener/complete v1.2.3 // indirect
github.com/russross/blackfriday v1.6.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
github.com/vmihailenco/tagparser v0.1.1 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/zclconf/go-cty v1.13.2 // indirect
golang.org/x/crypto v0.8.0 // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
google.golang.org/grpc v1.53.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878 // indirect
google.golang.org/grpc v1.57.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading