Skip to content

Commit

Permalink
Merge branch 'NaverCloudPlatform:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Geun-Oh authored Sep 10, 2024
2 parents 38a96cc + 0d30a6f commit 79823ab
Show file tree
Hide file tree
Showing 8 changed files with 355 additions and 4 deletions.
50 changes: 50 additions & 0 deletions docs/data-sources/login_key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
subcategory: "Server"
---

# Data Source: ncloud_login_key

Get a list of Server login keys.

## Example Usage

```terraform
data "ncloud_login_key" "all" {
filter {
name = "key_name"
values = ["test-key1"]
}
output_file = "keys.json"
}
output "key_list" {
value = {
for key in data.ncloud_login_key.all.login_key_list:
key.key_name => key.fingerprint
}
}
```

Outputs:
```terraform
key_list = {
"test-key1": "2e:fa:e7:f8:fb:4c:18:0e:cd:f2:5b:20:79:c6:77:bd"
}
```

## Argument Reference

The following arguments are supported:
* `output_file` - (Optional) The name of file that can save data source after running `terraform plan`.
* `filter` - (Optional) Custom filter block as described below.
* `name` - (Required) The name of the field to filter by
* `vlaues` - (Required) Set of values that are accepted for the given field.
* `regex` - (Optional) is `values` treated as a regular expression.

## Attributes Reference

This data source exports the following attributes in addition to the argumments above:

* `login_key_list` - List of login keys.
* `key_name` - The name of login key.
* `fingerprint` - Fingerprint of the login key
* `create_date` - Login key create date.
2 changes: 1 addition & 1 deletion docs/data-sources/mssql_products.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ data "ncloud_mssql_products" "all" {
output "product_list" {
value = {
for product in data.ncloud_mssql_products.all.product_list :
image.product_name => image.product_code
product.product_name => product.product_code
}
}
```
Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/mysql_products.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ data "ncloud_mysql_products" "all" {
output "product_list" {
value = {
for product in data.ncloud_mysql_products.all.product_list :
image.product_name => image.product_code
product.product_name => product.product_code
}
}
```
Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/server_products.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ data "ncloud_server_products" "products" {
output "products" {
value = {
for product in data.ncloud_server_products.products.server_products:
for product in data.ncloud_server_products.products.server_products:
product.id => product.product_name
}
}
Expand Down
2 changes: 1 addition & 1 deletion examples/redis/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ data "ncloud_redis_products" "all" {

output "product_list" {
value = {
for product in data.ncloud_redis_products.all.product_list:
for product in data.ncloud_redis_products.all.product_list:
product.product_name => product.product_code
}
}
Expand Down
1 change: 1 addition & 0 deletions internal/provider/fwprovider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ func (p *fwprovider) DataSources(ctx context.Context) []func() datasource.DataSo
dataSources = append(dataSources, vpc.NewNatGatewayDataSource)
dataSources = append(dataSources, vpc.NewVpcPeeringDataSource)
dataSources = append(dataSources, server.NewInitScriptDataSource)
dataSources = append(dataSources, server.NewLoginKeyDataSource)
dataSources = append(dataSources, mysql.NewMysqlDataSource)
dataSources = append(dataSources, mysql.NewMysqlImageProductsDataSource)
dataSources = append(dataSources, mysql.NewMysqlProductsDataSource)
Expand Down
247 changes: 247 additions & 0 deletions internal/service/server/login_key_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
package server

import (
"context"
"encoding/json"
"fmt"

"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server"
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/terraform-providers/terraform-provider-ncloud/internal/common"
"github.com/terraform-providers/terraform-provider-ncloud/internal/conn"
)

var (
_ datasource.DataSource = &loginKeyDataSource{}
_ datasource.DataSourceWithConfigure = &loginKeyDataSource{}
)

func NewLoginKeyDataSource() datasource.DataSource {
return &loginKeyDataSource{}
}

type loginKeyDataSource struct {
config *conn.ProviderConfig
}

func (d *loginKeyDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_login_key"
}

func (d *loginKeyDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
if req.ProviderData == nil {
return
}

config, ok := req.ProviderData.(*conn.ProviderConfig)

if !ok {
resp.Diagnostics.AddError(
"Unexpected Data Source Configure Type",
fmt.Sprintf("Expected *ProviderConfig, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)
return
}

d.config = config
}

func (d *loginKeyDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
},
"output_file": schema.StringAttribute{
Optional: true,
},
"login_key_list": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"key_name": schema.StringAttribute{
Computed: true,
},
"fingerprint": schema.StringAttribute{
Computed: true,
},
"create_date": schema.StringAttribute{
Computed: true,
},
},
},
},
},
Blocks: map[string]schema.Block{
"filter": common.DataSourceFiltersBlock(),
},
}
}

func (d *loginKeyDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data loginKeyDataSourceModel

resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

output, err := GetLoginKeyList(d.config)
if err != nil {
resp.Diagnostics.AddError("READING ERROR", err.Error())
return
}

if output == nil {
resp.Diagnostics.AddError("READING ERROR", "no result. please change search criteria and try again.")
return
}

loginKeyList := flattenLoginKey(output)
fillteredList := common.FilterModels(ctx, data.Filters, loginKeyList)
data.refreshFromOutput(ctx, fillteredList)

if !data.OutputFile.IsNull() && data.OutputFile.String() != "" {
outputPath := data.OutputFile.ValueString()

if convertedList, err := convertToJsonStruct(data.KeyList.Elements()); err != nil {
resp.Diagnostics.AddError("OUTPUT FILE ERROR", err.Error())
} else if err := common.WriteToFile(outputPath, convertedList); err != nil {
resp.Diagnostics.AddError("OUTPUT FILE ERROR", err.Error())
}
}

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
}

type loginKeyDataSourceModel struct {
ID types.String `tfsdk:"id"`
KeyList types.List `tfsdk:"login_key_list"`
OutputFile types.String `tfsdk:"output_file"`
Filters types.Set `tfsdk:"filter"`
}

type loginKeyModel struct {
KeyName types.String `tfsdk:"key_name"`
Fingerprint types.String `tfsdk:"fingerprint"`
CreateDate types.String `tfsdk:"create_date"`
}

type loginKeyToJsonConvert struct {
KeyName string `json:"key_name"`
Fingerprint string `json:"fingerprint"`
CreateDate string `json:"create_date"`
}

func (d loginKeyModel) attrTypes() map[string]attr.Type {
return map[string]attr.Type{
"key_name": types.StringType,
"fingerprint": types.StringType,
"create_date": types.StringType,
}
}

type loginKeyStruct struct {
KeyName *string `json:"key_name,omitempty"`
Fingerprint *string `json:"fingerprint,omitempty"`
CreateDate *string `json:"create_date,omitempty"`
}

func convertToJsonStruct(keys []attr.Value) ([]loginKeyToJsonConvert, error) {
var loginKeyToConvert = []loginKeyToJsonConvert{}

for _, key := range keys {
keyJson := loginKeyToJsonConvert{}
if err := json.Unmarshal([]byte(key.String()), &keyJson); err != nil {
return nil, err
}
loginKeyToConvert = append(loginKeyToConvert, keyJson)
}

return loginKeyToConvert, nil
}

func flattenLoginKey(list []*loginKeyStruct) []*loginKeyModel {
var outputs []*loginKeyModel

for _, v := range list {
var output loginKeyModel
output.refreshFromOutput(v)

outputs = append(outputs, &output)
}
return outputs
}

func (d *loginKeyDataSourceModel) refreshFromOutput(ctx context.Context, output []*loginKeyModel) {
keyListValue, _ := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: loginKeyModel{}.attrTypes()}, output)
d.KeyList = keyListValue
d.ID = types.StringValue("")
}

func (d *loginKeyModel) refreshFromOutput(output *loginKeyStruct) {
d.KeyName = types.StringPointerValue(output.KeyName)
d.Fingerprint = types.StringPointerValue(output.Fingerprint)
d.CreateDate = types.StringPointerValue(output.CreateDate)
}

func GetLoginKeyList(config *conn.ProviderConfig) ([]*loginKeyStruct, error) {
if config.SupportVPC {
return getVpcLoginKeyList(config)
} else {
return getClassicLoginKeyList(config)
}
}

func getVpcLoginKeyList(config *conn.ProviderConfig) ([]*loginKeyStruct, error) {
resp, err := config.Client.Vserver.V2Api.GetLoginKeyList(&vserver.GetLoginKeyListRequest{})

if err != nil {
return nil, err
}

if len(resp.LoginKeyList) < 1 {
return nil, nil
}

var loginKeys []*loginKeyStruct
for _, l := range resp.LoginKeyList {
loginKeys = append(loginKeys, &loginKeyStruct{
KeyName: l.KeyName,
Fingerprint: l.Fingerprint,
CreateDate: l.CreateDate,
})
}

return loginKeys, nil
}

func getClassicLoginKeyList(config *conn.ProviderConfig) ([]*loginKeyStruct, error) {
resp, err := config.Client.Server.V2Api.GetLoginKeyList(&server.GetLoginKeyListRequest{})

if err != nil {
return nil, err
}

if len(resp.LoginKeyList) < 1 {
return nil, nil
}

var loginKeys []*loginKeyStruct
for _, l := range resp.LoginKeyList {
loginKeys = append(loginKeys, &loginKeyStruct{
KeyName: l.KeyName,
Fingerprint: l.Fingerprint,
CreateDate: l.CreateDate,
})
}

return loginKeys, nil
}
53 changes: 53 additions & 0 deletions internal/service/server/login_key_data_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package server_test

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
. "github.com/terraform-providers/terraform-provider-ncloud/internal/acctest"
)

func TestAccDataSourceNcloudLoginKey_classic_basic(t *testing.T) {
testAccDataSourceNcloudLoginKeyBasic(t, false)
}

func TestAccDataSourceNcloudLoginKey_vpc_basic(t *testing.T) {
testAccDataSourceNcloudLoginKeyBasic(t, true)
}

func testAccDataSourceNcloudLoginKeyBasic(t *testing.T, isVpc bool) {
dataName := "data.ncloud_login_key.all"
testKeyName := "test-key"

resource.Test(t, resource.TestCase{
PreCheck: func() { TestAccPreCheck(t) },
ProtoV6ProviderFactories: getProvidersBasedOnVpc(isVpc),
Steps: []resource.TestStep{
{
Config: testAccDataSourceLoginKeyConfig(testKeyName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataName, "login_key_list.0.key_name", "test-key1"),
resource.TestCheckResourceAttr(dataName, "login_key_list.1.key_name", "test-key2"),
),
},
},
})
}

func testAccDataSourceLoginKeyConfig(keyName string) string {
return fmt.Sprintf(`
resource "ncloud_login_key" "loginkey1" {
key_name = "%[1]s1"
}
resource "ncloud_login_key" "loginkey2" {
key_name = "%[1]s2"
}
data "ncloud_login_key" "all" {
filter {
name = "key_name"
values = [ncloud_login_key.loginkey1.key_name, ncloud_login_key.loginkey2.key_name]
}
}
`, keyName)
}

0 comments on commit 79823ab

Please sign in to comment.