From eb1286ce6f2e39b062e1d571b0ad39e041a82ddc Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Tue, 19 Nov 2024 00:18:28 +0900 Subject: [PATCH 01/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20terraform=EC=9D=84=20?= =?UTF-8?q?=EC=9D=B4=EC=9A=A9=ED=95=98=EC=97=AC=20NCloud=20server=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=95=98=EB=8A=94=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terraform/outputs.tf | 0 apps/terraform/provider.tf | 0 apps/terraform/server.tf | 0 apps/terraform/terraform.tfvars | 0 apps/terraform/variables.tf | 0 apps/terraform/vpc.tf | 0 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/terraform/outputs.tf create mode 100644 apps/terraform/provider.tf create mode 100644 apps/terraform/server.tf create mode 100644 apps/terraform/terraform.tfvars create mode 100644 apps/terraform/variables.tf create mode 100644 apps/terraform/vpc.tf diff --git a/apps/terraform/outputs.tf b/apps/terraform/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/apps/terraform/provider.tf b/apps/terraform/provider.tf new file mode 100644 index 00000000..e69de29b diff --git a/apps/terraform/server.tf b/apps/terraform/server.tf new file mode 100644 index 00000000..e69de29b diff --git a/apps/terraform/terraform.tfvars b/apps/terraform/terraform.tfvars new file mode 100644 index 00000000..e69de29b diff --git a/apps/terraform/variables.tf b/apps/terraform/variables.tf new file mode 100644 index 00000000..e69de29b diff --git a/apps/terraform/vpc.tf b/apps/terraform/vpc.tf new file mode 100644 index 00000000..e69de29b From 0cde3580145b3851c95893de5f8e792d2a6fca3c Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Tue, 19 Nov 2024 19:01:11 +0900 Subject: [PATCH 02/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20=EA=B0=81=20=EB=A6=AC?= =?UTF-8?q?=EC=86=8C=EC=8A=A4=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- apps/terraform/interface/ACG.ts | 6 ++++++ apps/terraform/interface/ACGRule.ts | 6 ++++++ apps/terraform/interface/NetworkInterface.ts | 6 ++++++ apps/terraform/interface/Provider.ts | 6 ++++++ apps/terraform/interface/PublicIp.ts | 5 +++++ apps/terraform/interface/Server.ts | 9 +++++++++ apps/terraform/interface/Subnet.ts | 10 ++++++++++ apps/terraform/interface/VPC.ts | 10 ++++++++++ 8 files changed, 58 insertions(+) create mode 100644 apps/terraform/interface/ACG.ts create mode 100644 apps/terraform/interface/ACGRule.ts create mode 100644 apps/terraform/interface/NetworkInterface.ts create mode 100644 apps/terraform/interface/Provider.ts create mode 100644 apps/terraform/interface/PublicIp.ts create mode 100644 apps/terraform/interface/Server.ts create mode 100644 apps/terraform/interface/Subnet.ts create mode 100644 apps/terraform/interface/VPC.ts diff --git a/apps/terraform/interface/ACG.ts b/apps/terraform/interface/ACG.ts new file mode 100644 index 00000000..7775794c --- /dev/null +++ b/apps/terraform/interface/ACG.ts @@ -0,0 +1,6 @@ +export interface ACG { + id: string; + name: string; + vpcNo: string; + description: string; +} \ No newline at end of file diff --git a/apps/terraform/interface/ACGRule.ts b/apps/terraform/interface/ACGRule.ts new file mode 100644 index 00000000..62cfac62 --- /dev/null +++ b/apps/terraform/interface/ACGRule.ts @@ -0,0 +1,6 @@ +export interface ACGRule { + protocol: string; + ipBlock: string; + portRange: string; + description: string; +} \ No newline at end of file diff --git a/apps/terraform/interface/NetworkInterface.ts b/apps/terraform/interface/NetworkInterface.ts new file mode 100644 index 00000000..cabcd519 --- /dev/null +++ b/apps/terraform/interface/NetworkInterface.ts @@ -0,0 +1,6 @@ +export interface NetworkInterface { + id: string; + name: string; + subnetNo: string; + accessControlGroups: string[]; +} \ No newline at end of file diff --git a/apps/terraform/interface/Provider.ts b/apps/terraform/interface/Provider.ts new file mode 100644 index 00000000..0f2a984d --- /dev/null +++ b/apps/terraform/interface/Provider.ts @@ -0,0 +1,6 @@ +export interface Provider { + accessKey: string; + secretKey: string; + region: string; + site: string; +} \ No newline at end of file diff --git a/apps/terraform/interface/PublicIp.ts b/apps/terraform/interface/PublicIp.ts new file mode 100644 index 00000000..0f265b85 --- /dev/null +++ b/apps/terraform/interface/PublicIp.ts @@ -0,0 +1,5 @@ +export interface PublicIp { + id: string; + publicIp: string; + serverInstanceNo: string; +} \ No newline at end of file diff --git a/apps/terraform/interface/Server.ts b/apps/terraform/interface/Server.ts new file mode 100644 index 00000000..fb1940ad --- /dev/null +++ b/apps/terraform/interface/Server.ts @@ -0,0 +1,9 @@ +export interface Server { + id: string; + name: string; + subnetNo: string; + serverImageProductCode: string; + serverProductCode: string; + loginKeyName: string; + networkInterfaceNo: string; +} \ No newline at end of file diff --git a/apps/terraform/interface/Subnet.ts b/apps/terraform/interface/Subnet.ts new file mode 100644 index 00000000..2d3ef458 --- /dev/null +++ b/apps/terraform/interface/Subnet.ts @@ -0,0 +1,10 @@ +export interface Subnet { + id: string; + name: string; + vpcNo: string; + subnet: string; + zone: string; + networkAclNo: string; + subnetType: string; + usageType: string; +} \ No newline at end of file diff --git a/apps/terraform/interface/VPC.ts b/apps/terraform/interface/VPC.ts new file mode 100644 index 00000000..9500e524 --- /dev/null +++ b/apps/terraform/interface/VPC.ts @@ -0,0 +1,10 @@ +export interface VPC { + id: string; + name: string; + region: string; + ipv4CidrBlock: string; + defaultNetworkAclNo: string; + defaultAccessControlGroupNo: string; + defaultPublicRouteTableNo: string; + defaultPrivateRouteTableNo: string; +} \ No newline at end of file From 815b67a8b7815ebdfdd2d9f9b3ca2dc03e8c3e2a Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Tue, 19 Nov 2024 22:52:02 +0900 Subject: [PATCH 03/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20nCloud=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- apps/terraform/interface/NCloudModel.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 apps/terraform/interface/NCloudModel.ts diff --git a/apps/terraform/interface/NCloudModel.ts b/apps/terraform/interface/NCloudModel.ts new file mode 100644 index 00000000..ba3933e7 --- /dev/null +++ b/apps/terraform/interface/NCloudModel.ts @@ -0,0 +1,5 @@ +export interface NCloudModel { + name: string; + serviceType: string; + getProperties(): { [key: string]: any }; +} \ No newline at end of file From a3ef4a670ec44ba5a4fd07095146c373604d0971 Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Tue, 19 Nov 2024 22:52:35 +0900 Subject: [PATCH 04/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20nCloud=20Resource=20?= =?UTF-8?q?=EB=AA=A8=EB=8D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- apps/terraform/model/NCloudACG.ts | 23 +++++++++++ .../terraform/model/NCloudNetworkInterface.ts | 24 ++++++++++++ apps/terraform/model/NCloudProvider.ts | 30 ++++++++++++++ apps/terraform/model/NCloudServer.ts | 39 +++++++++++++++++++ apps/terraform/model/NCloudSubnet.ts | 31 +++++++++++++++ apps/terraform/model/NCloudVPC.ts | 33 ++++++++++++++++ 6 files changed, 180 insertions(+) create mode 100644 apps/terraform/model/NCloudACG.ts create mode 100644 apps/terraform/model/NCloudNetworkInterface.ts create mode 100644 apps/terraform/model/NCloudProvider.ts create mode 100644 apps/terraform/model/NCloudServer.ts create mode 100644 apps/terraform/model/NCloudSubnet.ts create mode 100644 apps/terraform/model/NCloudVPC.ts diff --git a/apps/terraform/model/NCloudACG.ts b/apps/terraform/model/NCloudACG.ts new file mode 100644 index 00000000..efd2da6b --- /dev/null +++ b/apps/terraform/model/NCloudACG.ts @@ -0,0 +1,23 @@ +import { ACG } from '../interface/ACG'; +import { NCloudModel } from '../interface/NCloudModel'; + +export class NCloudACG implements ACG, NCloudModel { + id: string; + name: string; + vpcNo: string; + description: string; + serviceType: string; + + constructor(json: any) { + this.serviceType = 'ncloud_access_control_group'; + Object.assign(this, json); + } + + getProperties() { + return { + name: this.name, + vpc_no: "ncloud_vpc.vpc.id", + description: this.description + }; + } +} diff --git a/apps/terraform/model/NCloudNetworkInterface.ts b/apps/terraform/model/NCloudNetworkInterface.ts new file mode 100644 index 00000000..3f314e8d --- /dev/null +++ b/apps/terraform/model/NCloudNetworkInterface.ts @@ -0,0 +1,24 @@ +import { NetworkInterface } from '../interface/NetworkInterface'; +import { NCloudModel } from '../interface/NCloudModel'; + +export class NCloudNetworkInterface implements NetworkInterface, NCloudModel { + id: string; + name: string; + subnetNo: string; + accessControlGroups: string[]; + serviceType: string; + + constructor(json: any) { + this.serviceType = 'ncloud_network_interface'; + Object.assign(this, json); + } + + getProperties() { + return { + subnet_no: "ncloud_subnet.subnet.id", + name: this.name, + access_control_groups: this.accessControlGroups + }; + } +} + diff --git a/apps/terraform/model/NCloudProvider.ts b/apps/terraform/model/NCloudProvider.ts new file mode 100644 index 00000000..ba2a5735 --- /dev/null +++ b/apps/terraform/model/NCloudProvider.ts @@ -0,0 +1,30 @@ +import { Provider } from '../interface/Provider'; +import { NCloudModel } from '../interface/NCloudModel'; + +export class NCloudProvider implements Provider, NCloudModel { + accessKey: string; + secretKey: string; + region: string; + site: string; + name: string; + serviceType: string; + + constructor(json: any) { + this.serviceType = 'provider'; + this.name = 'ncloud'; + this.accessKey = json.accessKey; + this.secretKey = json.secretKey; + this.region = json.region; + this.site = json.site; + } + + getProperties() { + return { + access_key: this.accessKey, + secret_key: this.secretKey, + region: this.region, + site: this.site, + support_vpc: true + }; + } +} diff --git a/apps/terraform/model/NCloudServer.ts b/apps/terraform/model/NCloudServer.ts new file mode 100644 index 00000000..5d11ac38 --- /dev/null +++ b/apps/terraform/model/NCloudServer.ts @@ -0,0 +1,39 @@ +import { Server } from '../interface/Server'; +import { NCloudModel } from '../interface/NCloudModel'; + +export class NCloudServer implements Server, NCloudModel { + id: string; + name: string; + subnetNo: string; + serverImageProductCode: string; + serverProductCode: string; + loginKeyName: string; + networkInterfaceNo: string; + serviceType: string; + + constructor(json: any) { + this.serviceType = 'ncloud_server'; + this.id = json.id; + this.name = json.name; + this.subnetNo = json.subnetNo; + this.serverImageProductCode = json.serverImageProductCode; + this.serverProductCode = json.serverProductCode; + this.loginKeyName = json.loginKeyName; + this.networkInterfaceNo = json.networkInterfaceNo; + } + + getProperties() { + return { + subnet_no: this.subnetNo, + name: this.name, + server_image_product_code: this.serverImageProductCode, + server_product_code: this.serverProductCode, + login_key_name: this.loginKeyName, + network_interface: { + network_interface_no: this.networkInterfaceNo, + order: 0 + } + }; + } +} + diff --git a/apps/terraform/model/NCloudSubnet.ts b/apps/terraform/model/NCloudSubnet.ts new file mode 100644 index 00000000..966793cc --- /dev/null +++ b/apps/terraform/model/NCloudSubnet.ts @@ -0,0 +1,31 @@ +import { Subnet } from '../interface/Subnet'; +import { NCloudModel } from '../interface/NCloudModel'; + +export class NCloudSubnet implements Subnet, NCloudModel { + id: string; + name: string; + vpcNo: string; + subnet: string; + zone: string; + networkAclNo: string; + subnetType: string; + usageType: string; + serviceType: string; + + constructor(json: any) { + this.serviceType = 'ncloud_subnet'; + Object.assign(this, json); + } + + getProperties() { + return { + vpc_no: "ncloud_vpc.vpc.id", + subnet: this.subnet, + zone: this.zone, + network_acl_no: "ncloud_vpc.vpc.default_network_acl_no", + subnet_type: this.subnetType, + name: this.name, + usage_type: this.usageType + }; + } +} diff --git a/apps/terraform/model/NCloudVPC.ts b/apps/terraform/model/NCloudVPC.ts new file mode 100644 index 00000000..e23ba23b --- /dev/null +++ b/apps/terraform/model/NCloudVPC.ts @@ -0,0 +1,33 @@ +import { VPC } from '../interface/VPC'; +import { NCloudModel } from '../interface/NCloudModel'; + +export class NCloudVPC implements VPC, NCloudModel { + id: string; + name: string; + region: string; + ipv4CidrBlock: string; + defaultNetworkAclNo: string; + defaultAccessControlGroupNo: string; + defaultPublicRouteTableNo: string; + defaultPrivateRouteTableNo: string; + serviceType: string; + + constructor(json: any) { + this.serviceType = 'ncloud_vpc'; + this.id = json.id; + this.name = json.name; + this.region = json.region; + this.ipv4CidrBlock = json.ipv4CidrBlock; + this.defaultNetworkAclNo = json.defaultNetworkAclNo; + this.defaultAccessControlGroupNo = json.defaultAccessControlGroupNo; + this.defaultPublicRouteTableNo = json.defaultPublicRouteTableNo; + this.defaultPrivateRouteTableNo = json.defaultPrivateRouteTableNo; + } + + getProperties() { + return { + name: this.name, + ipv4_cidr_block: this.ipv4CidrBlock + }; + } +} From 77a62bb174245db7a3f7f965c13c78dd48442ae7 Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 01:43:57 +0900 Subject: [PATCH 05/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20networkACL,=20PublicI?= =?UTF-8?q?P,=20LoginKey=20=EB=AA=A8=EB=8D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- apps/terraform/model/NCloudLoginKey.ts | 20 +++++++++++++++++++ apps/terraform/model/NCloudNetworkACL.ts | 25 ++++++++++++++++++++++++ apps/terraform/model/NCloudPublicIP.ts | 20 +++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 apps/terraform/model/NCloudLoginKey.ts create mode 100644 apps/terraform/model/NCloudNetworkACL.ts create mode 100644 apps/terraform/model/NCloudPublicIP.ts diff --git a/apps/terraform/model/NCloudLoginKey.ts b/apps/terraform/model/NCloudLoginKey.ts new file mode 100644 index 00000000..0dd88052 --- /dev/null +++ b/apps/terraform/model/NCloudLoginKey.ts @@ -0,0 +1,20 @@ +import { NCloudModel } from '../interface/NCloudModel'; +import { ResourcePriority } from '../enum/ResourcePriority'; + +export class NCloudLoginKey implements NCloudModel { + name: string; + serviceType: string; + priority: ResourcePriority; + + constructor(json: any) { + this.serviceType = 'ncloud_login_key'; + this.priority = ResourcePriority.LOGIN_KEY; + this.name = json.name; + } + + getProperties() { + return { + key_name: this.name + }; + } +} diff --git a/apps/terraform/model/NCloudNetworkACL.ts b/apps/terraform/model/NCloudNetworkACL.ts new file mode 100644 index 00000000..f72dd098 --- /dev/null +++ b/apps/terraform/model/NCloudNetworkACL.ts @@ -0,0 +1,25 @@ +import { NetworkACL } from '../interface/NetworkACL'; +import { NCloudModel } from '../interface/NCloudModel'; +import { ResourcePriority } from '../enum/ResourcePriority'; + +export class NCloudNetworkACL implements NetworkACL, NCloudModel { + id: string; + name: string; + vpcNo: string; + serviceType: string; + priority: ResourcePriority; + + constructor(json: any) { + this.serviceType = 'ncloud_network_acl'; + this.priority = ResourcePriority.NETWORK_ACL; + this.id = json.id; + this.name = json.name || 'nacl'; + this.vpcNo = json.vpcNo; + } + + getProperties() { + return { + vpc_no: "ncloud_vpc.vpc.id" + }; + } +} diff --git a/apps/terraform/model/NCloudPublicIP.ts b/apps/terraform/model/NCloudPublicIP.ts new file mode 100644 index 00000000..3d0759ab --- /dev/null +++ b/apps/terraform/model/NCloudPublicIP.ts @@ -0,0 +1,20 @@ +import { ResourcePriority } from '../enum/ResourcePriority'; +import { NCloudModel } from '../interface/NCloudModel'; + +export class NCloudPublicIP implements NCloudModel { + name: string; + serviceType: string; + priority: ResourcePriority; + + constructor(json: any) { + this.serviceType = 'ncloud_public_ip'; + this.priority = ResourcePriority.PUBLIC_IP; + this.name = json.name; + } + + getProperties() { + return { + server_instance_no: "ncloud_server.my-server.id" + }; + } +} From 5e4a16f5235b4a67ea26395c6a3721c4465e16bc Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 01:44:42 +0900 Subject: [PATCH 06/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20=EB=AA=A8=EB=8D=B8=20?= =?UTF-8?q?priority=20=EC=86=8D=EC=84=B1=20=EC=B6=94=EA=B0=80=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EC=8B=A4=ED=96=89=20=EC=88=9C=EC=84=9C=20=EC=A0=9C?= =?UTF-8?q?=EC=96=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terraform/model/NCloudACG.ts | 3 ++ apps/terraform/model/NCloudACGRule.ts | 34 +++++++++++++++++++ .../terraform/model/NCloudNetworkInterface.ts | 5 ++- apps/terraform/model/NCloudProvider.ts | 30 ++++++++++++---- apps/terraform/model/NCloudServer.ts | 9 +++-- apps/terraform/model/NCloudSubnet.ts | 3 ++ apps/terraform/model/NCloudVPC.ts | 4 +++ 7 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 apps/terraform/model/NCloudACGRule.ts diff --git a/apps/terraform/model/NCloudACG.ts b/apps/terraform/model/NCloudACG.ts index efd2da6b..c3c1fa32 100644 --- a/apps/terraform/model/NCloudACG.ts +++ b/apps/terraform/model/NCloudACG.ts @@ -1,5 +1,6 @@ import { ACG } from '../interface/ACG'; import { NCloudModel } from '../interface/NCloudModel'; +import { ResourcePriority } from '../enum/ResourcePriority'; export class NCloudACG implements ACG, NCloudModel { id: string; @@ -7,9 +8,11 @@ export class NCloudACG implements ACG, NCloudModel { vpcNo: string; description: string; serviceType: string; + priority: ResourcePriority; constructor(json: any) { this.serviceType = 'ncloud_access_control_group'; + this.priority = ResourcePriority.ACG; Object.assign(this, json); } diff --git a/apps/terraform/model/NCloudACGRule.ts b/apps/terraform/model/NCloudACGRule.ts new file mode 100644 index 00000000..901881c6 --- /dev/null +++ b/apps/terraform/model/NCloudACGRule.ts @@ -0,0 +1,34 @@ +import { NCloudModel } from '../interface/NCloudModel'; +import { ResourcePriority } from '../enum/ResourcePriority'; + +export class NCloudACGRule implements NCloudModel { + name: string; + protocol: string; + ipBlock: string; + portRange: string; + description: string; + serviceType: string; + priority: ResourcePriority; + + constructor(json: any) { + this.serviceType = 'ncloud_access_control_group_rule'; + this.priority = ResourcePriority.ACG_RULE; + this.name = json.name || 'acg-rule'; + this.protocol = json.protocol; + this.ipBlock = json.ipBlock; + this.portRange = json.portRange; + this.description = json.description; + } + + getProperties() { + return { + access_control_group_no: "ncloud_access_control_group.acg.id", + inbound: [{ + protocol: this.protocol, + ip_block: this.ipBlock, + port_range: this.portRange, + description: this.description + }] + }; + } +} diff --git a/apps/terraform/model/NCloudNetworkInterface.ts b/apps/terraform/model/NCloudNetworkInterface.ts index 3f314e8d..dfc27b48 100644 --- a/apps/terraform/model/NCloudNetworkInterface.ts +++ b/apps/terraform/model/NCloudNetworkInterface.ts @@ -1,5 +1,6 @@ import { NetworkInterface } from '../interface/NetworkInterface'; import { NCloudModel } from '../interface/NCloudModel'; +import { ResourcePriority } from '../enum/ResourcePriority'; export class NCloudNetworkInterface implements NetworkInterface, NCloudModel { id: string; @@ -7,9 +8,11 @@ export class NCloudNetworkInterface implements NetworkInterface, NCloudModel { subnetNo: string; accessControlGroups: string[]; serviceType: string; + priority: ResourcePriority; constructor(json: any) { this.serviceType = 'ncloud_network_interface'; + this.priority = ResourcePriority.NETWORK_INTERFACE; Object.assign(this, json); } @@ -17,7 +20,7 @@ export class NCloudNetworkInterface implements NetworkInterface, NCloudModel { return { subnet_no: "ncloud_subnet.subnet.id", name: this.name, - access_control_groups: this.accessControlGroups + access_control_groups: "[ncloud_access_control_group.acg.id]", }; } } diff --git a/apps/terraform/model/NCloudProvider.ts b/apps/terraform/model/NCloudProvider.ts index ba2a5735..8c16fbe4 100644 --- a/apps/terraform/model/NCloudProvider.ts +++ b/apps/terraform/model/NCloudProvider.ts @@ -1,13 +1,16 @@ import { Provider } from '../interface/Provider'; import { NCloudModel } from '../interface/NCloudModel'; +import { ResourcePriority } from '../enum/ResourcePriority'; -export class NCloudProvider implements Provider, NCloudModel { +export class NCloudProvider implements Provider { accessKey: string; secretKey: string; region: string; site: string; name: string; serviceType: string; + requiredVersion: string; + source: string; constructor(json: any) { this.serviceType = 'provider'; @@ -15,16 +18,29 @@ export class NCloudProvider implements Provider, NCloudModel { this.accessKey = json.accessKey; this.secretKey = json.secretKey; this.region = json.region; - this.site = json.site; + this.site = json.site || 'public'; + this.requiredVersion = '>= 0.13'; + this.source = 'NaverCloudPlatform/ncloud'; } getProperties() { return { - access_key: this.accessKey, - secret_key: this.secretKey, - region: this.region, - site: this.site, - support_vpc: true + terraform: { + required_providers: { + ncloud: { + source: this.source + } + }, + required_version: this.requiredVersion + }, + provider: { + access_key: "var.access_key", + secret_key: "var.secret_key", + region: "var.region", + site: this.site, + support_vpc: true + } }; } + } diff --git a/apps/terraform/model/NCloudServer.ts b/apps/terraform/model/NCloudServer.ts index 5d11ac38..31318073 100644 --- a/apps/terraform/model/NCloudServer.ts +++ b/apps/terraform/model/NCloudServer.ts @@ -1,5 +1,6 @@ import { Server } from '../interface/Server'; import { NCloudModel } from '../interface/NCloudModel'; +import { ResourcePriority } from '../enum/ResourcePriority'; export class NCloudServer implements Server, NCloudModel { id: string; @@ -10,9 +11,11 @@ export class NCloudServer implements Server, NCloudModel { loginKeyName: string; networkInterfaceNo: string; serviceType: string; + priority: ResourcePriority; constructor(json: any) { this.serviceType = 'ncloud_server'; + this.priority = ResourcePriority.SERVER; this.id = json.id; this.name = json.name; this.subnetNo = json.subnetNo; @@ -24,13 +27,13 @@ export class NCloudServer implements Server, NCloudModel { getProperties() { return { - subnet_no: this.subnetNo, + subnet_no: "ncloud_subnet.subnet.id", name: this.name, server_image_product_code: this.serverImageProductCode, server_product_code: this.serverProductCode, - login_key_name: this.loginKeyName, + login_key_name: "ncloud_login_key.my-key.key_name", network_interface: { - network_interface_no: this.networkInterfaceNo, + network_interface_no: "ncloud_network_interface.my-nic.id", order: 0 } }; diff --git a/apps/terraform/model/NCloudSubnet.ts b/apps/terraform/model/NCloudSubnet.ts index 966793cc..9851c5d5 100644 --- a/apps/terraform/model/NCloudSubnet.ts +++ b/apps/terraform/model/NCloudSubnet.ts @@ -1,5 +1,6 @@ import { Subnet } from '../interface/Subnet'; import { NCloudModel } from '../interface/NCloudModel'; +import { ResourcePriority } from '../enum/ResourcePriority'; export class NCloudSubnet implements Subnet, NCloudModel { id: string; @@ -11,9 +12,11 @@ export class NCloudSubnet implements Subnet, NCloudModel { subnetType: string; usageType: string; serviceType: string; + priority: ResourcePriority; constructor(json: any) { this.serviceType = 'ncloud_subnet'; + this.priority = ResourcePriority.SUBNET; Object.assign(this, json); } diff --git a/apps/terraform/model/NCloudVPC.ts b/apps/terraform/model/NCloudVPC.ts index e23ba23b..c2b92d63 100644 --- a/apps/terraform/model/NCloudVPC.ts +++ b/apps/terraform/model/NCloudVPC.ts @@ -1,5 +1,6 @@ import { VPC } from '../interface/VPC'; import { NCloudModel } from '../interface/NCloudModel'; +import { ResourcePriority } from '../enum/ResourcePriority'; export class NCloudVPC implements VPC, NCloudModel { id: string; @@ -11,9 +12,12 @@ export class NCloudVPC implements VPC, NCloudModel { defaultPublicRouteTableNo: string; defaultPrivateRouteTableNo: string; serviceType: string; + priority: ResourcePriority; + constructor(json: any) { this.serviceType = 'ncloud_vpc'; + this.priority = ResourcePriority.VPC; this.id = json.id; this.name = json.name; this.region = json.region; From 3647eb7dbb47950db503d6d78d9a801650e779e9 Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 01:45:55 +0900 Subject: [PATCH 07/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20netwrokACL=20interfac?= =?UTF-8?q?e=EC=B6=94=EA=B0=80=20=EB=B0=8F=20NCloud=20=EB=AA=A8=EB=8D=B8?= =?UTF-8?q?=EC=97=90=20priority=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- apps/terraform/interface/NCloudModel.ts | 3 +++ apps/terraform/interface/NetworkACL.ts | 5 +++++ 2 files changed, 8 insertions(+) create mode 100644 apps/terraform/interface/NetworkACL.ts diff --git a/apps/terraform/interface/NCloudModel.ts b/apps/terraform/interface/NCloudModel.ts index ba3933e7..fb7956c6 100644 --- a/apps/terraform/interface/NCloudModel.ts +++ b/apps/terraform/interface/NCloudModel.ts @@ -1,5 +1,8 @@ +import { ResourcePriority } from '../enum/ResourcePriority'; + export interface NCloudModel { name: string; serviceType: string; + priority: ResourcePriority; getProperties(): { [key: string]: any }; } \ No newline at end of file diff --git a/apps/terraform/interface/NetworkACL.ts b/apps/terraform/interface/NetworkACL.ts new file mode 100644 index 00000000..e83d9808 --- /dev/null +++ b/apps/terraform/interface/NetworkACL.ts @@ -0,0 +1,5 @@ +export interface NetworkACL { + id: string; + name: string; + vpcNo: string; +} \ No newline at end of file From 1f073cfef7c61a1cac70a465c4bb7852726aab5a Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 01:46:25 +0900 Subject: [PATCH 08/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20resource=20Priority?= =?UTF-8?q?=20enum=20=ED=83=80=EC=9E=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- apps/terraform/enum/ResourcePriority.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 apps/terraform/enum/ResourcePriority.ts diff --git a/apps/terraform/enum/ResourcePriority.ts b/apps/terraform/enum/ResourcePriority.ts new file mode 100644 index 00000000..f1f46f34 --- /dev/null +++ b/apps/terraform/enum/ResourcePriority.ts @@ -0,0 +1,11 @@ +export enum ResourcePriority { + VPC = 1, + NETWORK_ACL = 2, + SUBNET = 3, + ACG = 4, + ACG_RULE = 5, + LOGIN_KEY = 6, + NETWORK_INTERFACE = 7, + SERVER = 8, + PUBLIC_IP = 9 +} \ No newline at end of file From 25afd78a7a2a53cb1e9e99cc8b6f33706a488b4e Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 01:46:57 +0900 Subject: [PATCH 09/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20=ED=85=8C=EB=9D=BC?= =?UTF-8?q?=ED=8F=BC=20=EC=BD=94=EB=93=9C=EB=A1=9C=20=EB=B0=94=EA=BF=94?= =?UTF-8?q?=EC=A3=BC=EB=8A=94=20terraform=20Convertor=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- .../terraform/convertor/TerraformConvertor.ts | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 apps/terraform/convertor/TerraformConvertor.ts diff --git a/apps/terraform/convertor/TerraformConvertor.ts b/apps/terraform/convertor/TerraformConvertor.ts new file mode 100644 index 00000000..cd688dd0 --- /dev/null +++ b/apps/terraform/convertor/TerraformConvertor.ts @@ -0,0 +1,93 @@ +import { NCloudModel } from '../interface/NCloudModel'; +import { NCloudProvider } from '../model/NCloudProvider'; + +export class TerraformConvertor { + private resources: NCloudModel[]; + private provider: NCloudProvider; + + constructor(provider: NCloudProvider) { + this.provider = provider; + this.resources = []; + } + + addResource(resource: NCloudModel) { + this.resources.push(resource); + } + + private formatValue(value: any): string { + if (typeof value === 'string') { + if (value.includes('ncloud_') && value.includes('.') && value.includes('_')) { + return value.replace(/"/g, ''); + } + if (value.startsWith('var.')) { + return value; + } + return `"${value}"`; + } + return value; + } + + private formatProperties(properties: { [key: string]: any }): string { + const maxKeyLength = Math.max(...Object.keys(properties).map(key => key.length)); + + return Object.entries(properties) + .map(([key, value]) => { + if (Array.isArray(value)) { + const formattedArray = value.map(item => { + if (typeof item === 'object') { + return ` ${key} { +${this.formatProperties(item)} + }`; + } + return ` ${key} = ${this.formatValue(item)}`; + }).join('\n'); + return formattedArray; + } + + if (typeof value === 'object' && value !== null) { + return ` ${key} { +${this.formatProperties(value)} + }`; + } + + const padding = ' '.repeat(maxKeyLength - key.length); + return ` ${key}${padding} = ${this.formatValue(value)}`; + }) + .join('\n'); + } + + generate(): string { + const providerProperties = this.provider.getProperties(); + + const terraformBlock = ` +terraform { + required_providers { + ncloud = { + source = "${providerProperties.terraform.required_providers.ncloud.source}" + } + } + required_version = "${providerProperties.terraform.required_version}" +}`; + + const providerBlock = ` +provider "${this.provider.name}" { +${this.formatProperties(providerProperties.provider)} +}`; + + const resourceBlocks = this.resources + .sort((a, b) => a.priority - b.priority) + .map(resource => ` +resource "${resource.serviceType}" "${resource.name}" { +${this.formatProperties(resource.getProperties())} +}`); + + return [terraformBlock, providerBlock, ...resourceBlocks].join('\n'); + } + + async saveToFile(filePath: string): Promise { + const fs = require('fs').promises; + const terraformCode = this.generate(); + console.log(terraformCode); + await fs.writeFile(filePath, terraformCode); + } +} From 9fc7a0c9a63c944e98e2fa13d37896b2f5acd6b5 Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 01:47:53 +0900 Subject: [PATCH 10/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20terraform=20convertor?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B0=80=EB=8A=A5=ED=95=9C=20?= =?UTF-8?q?main=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- apps/terraform/main.ts | 104 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 apps/terraform/main.ts diff --git a/apps/terraform/main.ts b/apps/terraform/main.ts new file mode 100644 index 00000000..4672a9fe --- /dev/null +++ b/apps/terraform/main.ts @@ -0,0 +1,104 @@ +import { exec } from 'child_process'; +import { promisify } from 'util'; +import { NCloudProvider } from './model/NCloudProvider'; +import { TerraformConvertor } from './convertor/TerraformConvertor'; +import { NCloudVPC } from './model/NCloudVPC'; +import { NCloudSubnet } from './model/NCloudSubnet'; +import { NCloudNetworkACL } from './model/NCloudNetworkACL'; +import { NCloudACG } from './model/NCloudACG'; +import { NCloudACGRule } from './model/NCloudACGRule'; +import { NCloudLoginKey } from './model/NCloudLoginKey'; +import { NCloudNetworkInterface } from './model/NCloudNetworkInterface'; +import { NCloudServer } from './model/NCloudServer'; +import { NCloudPublicIP } from './model/NCloudPublicIP'; +const execAsync = promisify(exec); + +async function main() { + const provider = new NCloudProvider({ + accessKey: "var.access_key", + secretKey: "var.secret_key", + region: "var.region", + site: "public" + }); + + const generator = new TerraformConvertor(provider); + + const vpc = new NCloudVPC({ + name: "vpc", + ipv4CidrBlock: "172.16.0.0/16" + }); + generator.addResource(vpc); + + const nacl = new NCloudNetworkACL({ + name: "nacl" + }); + generator.addResource(nacl); + + const subnet = new NCloudSubnet({ + name: "subnet", + subnet: "172.16.10.0/24", + zone: "KR-2", + subnetType: "PUBLIC", + usageType: "GEN" + }); + generator.addResource(subnet); + + const acg = new NCloudACG({ + name: "acg", + description: "My ACG" + }); + generator.addResource(acg); + + const acgRule = new NCloudACGRule({ + protocol: "TCP", + ipBlock: "0.0.0.0/0", + portRange: "80", + description: "HTTP" + }); + generator.addResource(acgRule); + + const loginKey = new NCloudLoginKey({ + name: "my-key" + }); + generator.addResource(loginKey); + + const nic = new NCloudNetworkInterface({ + name: "my-nic" + }); + generator.addResource(nic); + + const server = new NCloudServer({ + name: "my-server", + serverImageProductCode: "SW.VSVR.OS.LNX64.CNTOS.0708.B050", + serverProductCode: "SVR.VSVR.HICPU.C002.M004.NET.HDD.B050.G002" + }); + generator.addResource(server); + + const publicIp = new NCloudPublicIP({ + name: "public-ip" + }); + generator.addResource(publicIp); + + try { + await generator.saveToFile('main.tf'); + console.log('Terraform configuration has been generated.'); + + const { execSync } = require('child_process'); + + console.log('Running terraform init...'); + execSync('terraform init'); + + console.log('Running terraform plan...'); + execSync('terraform plan'); + + console.log('Running terraform apply...'); + execSync('terraform apply -auto-approve'); + + console.log('Infrastructure has been successfully created!'); + } catch (error) { + console.error('Error:', error); + } +} + +main().catch(console.error); + From b279228c6151a8ce0cc4efa2a85713b03e12f938 Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 01:49:17 +0900 Subject: [PATCH 11/24] =?UTF-8?q?=F0=9F=A4=96=20Refactor:=20=ED=85=8C?= =?UTF-8?q?=EB=9D=BC=ED=8F=BC=20=EC=84=9C=EB=B2=84=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EB=B0=8F=20variables.tf=20=EC=9E=AC=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- apps/terraform/provider.tf | 0 apps/terraform/server.tf | 0 apps/terraform/variables.tf | 12 ++++++++++++ apps/terraform/vpc.tf | 0 4 files changed, 12 insertions(+) delete mode 100644 apps/terraform/provider.tf delete mode 100644 apps/terraform/server.tf delete mode 100644 apps/terraform/vpc.tf diff --git a/apps/terraform/provider.tf b/apps/terraform/provider.tf deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/terraform/server.tf b/apps/terraform/server.tf deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/terraform/variables.tf b/apps/terraform/variables.tf index e69de29b..4e8abed7 100644 --- a/apps/terraform/variables.tf +++ b/apps/terraform/variables.tf @@ -0,0 +1,12 @@ +variable "access_key" { + type = string +} + +variable "secret_key" { + type = string +} + +variable "region" { + type = string + default = "KR" +} \ No newline at end of file diff --git a/apps/terraform/vpc.tf b/apps/terraform/vpc.tf deleted file mode 100644 index e69de29b..00000000 From 072b46c4fc9f81bdbe94a6fbdf04d5a95091c335 Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 14:20:11 +0900 Subject: [PATCH 12/24] =?UTF-8?q?=F0=9F=92=84=20Style:=20terraform=20conve?= =?UTF-8?q?rtor=20=EC=BD=94=EB=93=9C=20=ED=8F=AC=EB=A7=B7=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../terraform/convertor/TerraformConvertor.ts | 51 +++++++++---------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/apps/terraform/convertor/TerraformConvertor.ts b/apps/terraform/convertor/TerraformConvertor.ts index cd688dd0..51c1b7d7 100644 --- a/apps/terraform/convertor/TerraformConvertor.ts +++ b/apps/terraform/convertor/TerraformConvertor.ts @@ -16,12 +16,10 @@ export class TerraformConvertor { private formatValue(value: any): string { if (typeof value === 'string') { - if (value.includes('ncloud_') && value.includes('.') && value.includes('_')) { - return value.replace(/"/g, ''); - } - if (value.startsWith('var.')) { - return value; - } + if (value.includes('ncloud_') && value.includes('.') && value.includes('_')) return value.replace(/"/g, ''); + + if (value.startsWith('var.')) return value; + return `"${value}"`; } return value; @@ -36,8 +34,8 @@ export class TerraformConvertor { const formattedArray = value.map(item => { if (typeof item === 'object') { return ` ${key} { -${this.formatProperties(item)} - }`; + ${this.formatProperties(item)} + }`; } return ` ${key} = ${this.formatValue(item)}`; }).join('\n'); @@ -46,8 +44,8 @@ ${this.formatProperties(item)} if (typeof value === 'object' && value !== null) { return ` ${key} { -${this.formatProperties(value)} - }`; + ${this.formatProperties(value)} + }`; } const padding = ' '.repeat(maxKeyLength - key.length); @@ -59,27 +57,24 @@ ${this.formatProperties(value)} generate(): string { const providerProperties = this.provider.getProperties(); - const terraformBlock = ` -terraform { - required_providers { - ncloud = { - source = "${providerProperties.terraform.required_providers.ncloud.source}" - } - } - required_version = "${providerProperties.terraform.required_version}" -}`; - - const providerBlock = ` -provider "${this.provider.name}" { -${this.formatProperties(providerProperties.provider)} -}`; + const terraformBlock = `terraform { + required_providers { + ncloud = { + source = "${providerProperties.terraform.required_providers.ncloud.source}" + } + } + required_version = "${providerProperties.terraform.required_version}" + }`; + + const providerBlock = `provider "${this.provider.name}" { + ${this.formatProperties(providerProperties.provider)} + }`; const resourceBlocks = this.resources .sort((a, b) => a.priority - b.priority) - .map(resource => ` -resource "${resource.serviceType}" "${resource.name}" { -${this.formatProperties(resource.getProperties())} -}`); + .map(resource => `resource "${resource.serviceType}" "${resource.name}" { + ${this.formatProperties(resource.getProperties())} + }`); return [terraformBlock, providerBlock, ...resourceBlocks].join('\n'); } From b9e0a155df9d1c9fc5b886ec2af9a9c1b8b157fe Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 20:20:14 +0900 Subject: [PATCH 13/24] =?UTF-8?q?=F0=9F=A4=96=20Refactor:=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20import=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terraform/main.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/terraform/main.ts b/apps/terraform/main.ts index 4672a9fe..9bc64406 100644 --- a/apps/terraform/main.ts +++ b/apps/terraform/main.ts @@ -1,5 +1,3 @@ -import { exec } from 'child_process'; -import { promisify } from 'util'; import { NCloudProvider } from './model/NCloudProvider'; import { TerraformConvertor } from './convertor/TerraformConvertor'; import { NCloudVPC } from './model/NCloudVPC'; @@ -11,7 +9,6 @@ import { NCloudLoginKey } from './model/NCloudLoginKey'; import { NCloudNetworkInterface } from './model/NCloudNetworkInterface'; import { NCloudServer } from './model/NCloudServer'; import { NCloudPublicIP } from './model/NCloudPublicIP'; -const execAsync = promisify(exec); async function main() { const provider = new NCloudProvider({ From 74cf37bb2ea3820211aab313e42921cc0f0899a6 Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 20:37:47 +0900 Subject: [PATCH 14/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20jSON=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=EB=A5=BC=20=EB=B0=9B=EC=95=84=20=ED=8C=8C?= =?UTF-8?q?=EC=8B=B1=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20interface=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terraform/interface/CloudCanvasNode.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 apps/terraform/interface/CloudCanvasNode.ts diff --git a/apps/terraform/interface/CloudCanvasNode.ts b/apps/terraform/interface/CloudCanvasNode.ts new file mode 100644 index 00000000..dd7b3e70 --- /dev/null +++ b/apps/terraform/interface/CloudCanvasNode.ts @@ -0,0 +1,5 @@ +export interface CloudCanvasNode { + id: string; + type: string; + properties: { [key: string]: any }; +} \ No newline at end of file From 0f6748a1d74515ae576653b1b10117c860bd761a Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 20:39:52 +0900 Subject: [PATCH 15/24] =?UTF-8?q?=F0=9F=A4=96=20Refactor:=20=ED=95=84?= =?UTF-8?q?=EC=9A=94=EC=97=86=EB=8A=94=20import=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terraform/model/NCloudProvider.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/terraform/model/NCloudProvider.ts b/apps/terraform/model/NCloudProvider.ts index 8c16fbe4..67f5b152 100644 --- a/apps/terraform/model/NCloudProvider.ts +++ b/apps/terraform/model/NCloudProvider.ts @@ -1,6 +1,4 @@ import { Provider } from '../interface/Provider'; -import { NCloudModel } from '../interface/NCloudModel'; -import { ResourcePriority } from '../enum/ResourcePriority'; export class NCloudProvider implements Provider { accessKey: string; From 17435ace05d98ed591aa8f7d0a49c738ff7753ca Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 20:53:40 +0900 Subject: [PATCH 16/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20resource=20json=20Dat?= =?UTF-8?q?a=20=EB=B0=9B=EC=95=84=EC=84=9C=20=EB=AA=A8=EB=8D=B8=EB=A1=9C?= =?UTF-8?q?=20=ED=8C=8C=EC=8B=B1=ED=95=B4=EC=A3=BC=EB=8A=94=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terraform/util/resourceParser.ts | 79 +++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 apps/terraform/util/resourceParser.ts diff --git a/apps/terraform/util/resourceParser.ts b/apps/terraform/util/resourceParser.ts new file mode 100644 index 00000000..0678a66f --- /dev/null +++ b/apps/terraform/util/resourceParser.ts @@ -0,0 +1,79 @@ +import { CloudCanvasNode } from '../interface/CloudCanvasNode'; +import { NCloudModel } from '../interface/NCloudModel'; +import { NCloudVPC } from '../model/NCloudVPC'; +import { NCloudNetworkACL } from '../model/NCloudNetworkACL'; +import { NCloudSubnet } from '../model/NCloudSubnet'; +import { NCloudACG } from '../model/NCloudACG'; +import { NCloudACGRule } from '../model/NCloudACGRule'; +import { NCloudLoginKey } from '../model/NCloudLoginKey'; +import { NCloudNetworkInterface } from '../model/NCloudNetworkInterface'; +import { NCloudServer } from '../model/NCloudServer'; +import { NCloudPublicIP } from '../model/NCloudPublicIP'; + + +export function parseToNCloudModel(resource: CloudCanvasNode ): NCloudModel { + const { type, properties } = resource; + + switch (type.toLowerCase()) { + case 'vpc': + return new NCloudVPC({ + name: properties.name || 'vpc', + ipv4CidrBlock: properties.cidrBlock + }); + + case 'networkacl': + return new NCloudNetworkACL({ + name: properties.name || 'nacl' + }); + + case 'subnet': + return new NCloudSubnet({ + name: properties.name || 'subnet', + subnet: properties.subnet, + zone: properties.zone, + subnetType: properties.subnetType, + usageType: properties.usageType + }); + + case 'acg': + case 'accesscontrolgroup': + return new NCloudACG({ + name: properties.name || 'acg', + description: properties.description + }); + + case 'acgrule': + case 'accesscontrolgrouprule': + return new NCloudACGRule({ + protocol: properties.protocol, + ipBlock: properties.ipBlock, + portRange: properties.portRange, + description: properties.description + }); + + case 'loginkey': + return new NCloudLoginKey({ + name: properties.name || 'login-key' + }); + + case 'networkinterface': + return new NCloudNetworkInterface({ + name: properties.name || 'nic' + }); + + case 'server': + return new NCloudServer({ + name: properties.name || 'server', + serverImageProductCode: properties.serverImageProductCode, + serverProductCode: properties.serverProductCode + }); + + case 'publicip': + return new NCloudPublicIP({ + name: properties.name || 'public-ip' + }); + + default: + throw new Error(`Unsupported resource type: ${type}`); + } +} \ No newline at end of file From a51c087bdd98f88170e320b697a3f5945a73baab Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Wed, 20 Nov 2024 21:03:54 +0900 Subject: [PATCH 17/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20resource=20json=20Dat?= =?UTF-8?q?a=EB=A5=BC=20=EB=B0=9B=EC=95=84=EC=84=9C=20=EB=AA=A8=EB=8D=B8?= =?UTF-8?q?=EC=9D=84=20=EC=9D=B4=EC=9A=A9=ED=95=B4=20=ED=8C=8C=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../terraform/convertor/TerraformConvertor.ts | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/apps/terraform/convertor/TerraformConvertor.ts b/apps/terraform/convertor/TerraformConvertor.ts index 51c1b7d7..e9c77720 100644 --- a/apps/terraform/convertor/TerraformConvertor.ts +++ b/apps/terraform/convertor/TerraformConvertor.ts @@ -1,5 +1,7 @@ import { NCloudModel } from '../interface/NCloudModel'; import { NCloudProvider } from '../model/NCloudProvider'; +import { CloudCanvasNode } from '../interface/CloudCanvasNode'; +import { parseToNCloudModel } from '../util/resourceParser'; export class TerraformConvertor { private resources: NCloudModel[]; @@ -10,6 +12,17 @@ export class TerraformConvertor { this.resources = []; } + addResourceFromJson(jsonData: { nodes?: CloudCanvasNode[] }) { + jsonData.nodes?.forEach((node => { + try { + const resource = parseToNCloudModel(node); + this.addResource(resource); + }catch (error) { + console.warn(`Skipping unsupported node type: ${node.type}`); + } + })); + } + addResource(resource: NCloudModel) { this.resources.push(resource); } @@ -34,8 +47,8 @@ export class TerraformConvertor { const formattedArray = value.map(item => { if (typeof item === 'object') { return ` ${key} { - ${this.formatProperties(item)} - }`; +${this.formatProperties(item)} + }`; } return ` ${key} = ${this.formatValue(item)}`; }).join('\n'); @@ -44,8 +57,8 @@ export class TerraformConvertor { if (typeof value === 'object' && value !== null) { return ` ${key} { - ${this.formatProperties(value)} - }`; +${this.formatProperties(value)} + }`; } const padding = ' '.repeat(maxKeyLength - key.length); @@ -57,24 +70,27 @@ export class TerraformConvertor { generate(): string { const providerProperties = this.provider.getProperties(); - const terraformBlock = `terraform { - required_providers { - ncloud = { - source = "${providerProperties.terraform.required_providers.ncloud.source}" - } - } - required_version = "${providerProperties.terraform.required_version}" - }`; - - const providerBlock = `provider "${this.provider.name}" { - ${this.formatProperties(providerProperties.provider)} - }`; + const terraformBlock = ` +terraform { + required_providers { + ncloud = { + source = "${providerProperties.terraform.required_providers.ncloud.source}" + } + } + required_version = "${providerProperties.terraform.required_version}" +}`; + + const providerBlock = ` +provider "${this.provider.name}" { +${this.formatProperties(providerProperties.provider)} +}`; const resourceBlocks = this.resources .sort((a, b) => a.priority - b.priority) - .map(resource => `resource "${resource.serviceType}" "${resource.name}" { - ${this.formatProperties(resource.getProperties())} - }`); + .map(resource => ` +resource "${resource.serviceType}" "${resource.name}" { +${this.formatProperties(resource.getProperties())} +}`); return [terraformBlock, providerBlock, ...resourceBlocks].join('\n'); } From 4cd75bf092915ffaebe45fa8bcd90a4fecc8cf47 Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Thu, 21 Nov 2024 14:19:15 +0900 Subject: [PATCH 18/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20nCloud=20subnet=20?= =?UTF-8?q?=EC=B0=B8=EC=A1=B0=EA=B0=92=20=EC=B2=98=EB=A6=AC=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- .../terraform/convertor/TerraformConvertor.ts | 48 ++++++++++++++++--- apps/terraform/model/NCloudSubnet.ts | 18 +++---- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/apps/terraform/convertor/TerraformConvertor.ts b/apps/terraform/convertor/TerraformConvertor.ts index e9c77720..8dc7c43d 100644 --- a/apps/terraform/convertor/TerraformConvertor.ts +++ b/apps/terraform/convertor/TerraformConvertor.ts @@ -6,10 +6,12 @@ import { parseToNCloudModel } from '../util/resourceParser'; export class TerraformConvertor { private resources: NCloudModel[]; private provider: NCloudProvider; + private resourceMap: Map; constructor(provider: NCloudProvider) { this.provider = provider; this.resources = []; + this.resourceMap = new Map(); } addResourceFromJson(jsonData: { nodes?: CloudCanvasNode[] }) { @@ -17,7 +19,7 @@ export class TerraformConvertor { try { const resource = parseToNCloudModel(node); this.addResource(resource); - }catch (error) { + } catch (error) { console.warn(`Skipping unsupported node type: ${node.type}`); } })); @@ -25,13 +27,44 @@ export class TerraformConvertor { addResource(resource: NCloudModel) { this.resources.push(resource); + this.resourceMap.set(resource.serviceType, resource.name); } + getResourceName(serviceType: string): string { + return this.resourceMap.get(serviceType) || ''; + } + + private replaceReferences(properties: { [key: string]: any }): { [key: string]: any } { + const result = { ...properties }; + + for (const [key, value] of Object.entries(result)) { + if (typeof value === 'string') { + if (value === 'VPC_ID_PLACEHOLDER') { + const vpcName = this.resourceMap.get('ncloud_vpc'); + result[key] = `ncloud_vpc.${vpcName}.id`; + } + if (value === 'VPC_ACL_PLACEHOLDER') { + const vpcName = this.resourceMap.get('ncloud_vpc'); + result[key] = `ncloud_vpc.${vpcName}.default_network_acl_no`; + } + } else if (typeof value === 'object' && value !== null) { + result[key] = this.replaceReferences(value); + } + } + + return result; + } + + private formatValue(value: any): string { if (typeof value === 'string') { - if (value.includes('ncloud_') && value.includes('.') && value.includes('_')) return value.replace(/"/g, ''); + const ncloudRefPattern = /^ncloud_[a-zA-Z_]+\.[a-zA-Z_-]+\.[a-zA-Z_]+$/; - if (value.startsWith('var.')) return value; + const varRefPattern = /^var\.[a-zA-Z_]+$/; + + if (ncloudRefPattern.test(value) || varRefPattern.test(value)) { + return value; + } return `"${value}"`; } @@ -87,10 +120,13 @@ ${this.formatProperties(providerProperties.provider)} const resourceBlocks = this.resources .sort((a, b) => a.priority - b.priority) - .map(resource => ` + .map(resource => { + const properties = this.replaceReferences(resource.getProperties()); + return ` resource "${resource.serviceType}" "${resource.name}" { -${this.formatProperties(resource.getProperties())} -}`); +${this.formatProperties(properties)} +}`; + }); return [terraformBlock, providerBlock, ...resourceBlocks].join('\n'); } diff --git a/apps/terraform/model/NCloudSubnet.ts b/apps/terraform/model/NCloudSubnet.ts index 9851c5d5..643c25b5 100644 --- a/apps/terraform/model/NCloudSubnet.ts +++ b/apps/terraform/model/NCloudSubnet.ts @@ -1,14 +1,11 @@ -import { Subnet } from '../interface/Subnet'; -import { NCloudModel } from '../interface/NCloudModel'; import { ResourcePriority } from '../enum/ResourcePriority'; +import { NCloudModel } from '../interface/NCloudModel'; -export class NCloudSubnet implements Subnet, NCloudModel { +export class NCloudSubnet implements NCloudModel { id: string; name: string; - vpcNo: string; subnet: string; zone: string; - networkAclNo: string; subnetType: string; usageType: string; serviceType: string; @@ -17,18 +14,23 @@ export class NCloudSubnet implements Subnet, NCloudModel { constructor(json: any) { this.serviceType = 'ncloud_subnet'; this.priority = ResourcePriority.SUBNET; - Object.assign(this, json); + this.name = json.name || 'subnet'; + this.subnet = json.subnet; + this.zone = json.zone; + this.subnetType = json.subnetType; + this.usageType = json.usageType; } getProperties() { return { - vpc_no: "ncloud_vpc.vpc.id", + vpc_no: "VPC_ID_PLACEHOLDER", subnet: this.subnet, zone: this.zone, - network_acl_no: "ncloud_vpc.vpc.default_network_acl_no", + network_acl_no: "VPC_ACL_PLACEHOLDER", subnet_type: this.subnetType, name: this.name, usage_type: this.usageType }; } } + From bac41567b80f468b642027e42114ecfbbc721ee5 Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Thu, 21 Nov 2024 14:25:35 +0900 Subject: [PATCH 19/24] =?UTF-8?q?=E2=9C=A8=20Feat:=20=EB=82=98=EB=A8=B8?= =?UTF-8?q?=EC=A7=80=20=EB=A6=AC=EC=86=8C=EC=8A=A4=EB=93=A4=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=B0=B8=EC=A1=B0=EA=B0=92=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- .../terraform/convertor/TerraformConvertor.ts | 51 ++++++++++++++----- apps/terraform/model/NCloudACG.ts | 2 +- apps/terraform/model/NCloudACGRule.ts | 2 +- apps/terraform/model/NCloudNetworkACL.ts | 2 +- .../terraform/model/NCloudNetworkInterface.ts | 4 +- apps/terraform/model/NCloudPublicIP.ts | 2 +- apps/terraform/model/NCloudServer.ts | 6 +-- 7 files changed, 47 insertions(+), 22 deletions(-) diff --git a/apps/terraform/convertor/TerraformConvertor.ts b/apps/terraform/convertor/TerraformConvertor.ts index 8dc7c43d..b2f768b2 100644 --- a/apps/terraform/convertor/TerraformConvertor.ts +++ b/apps/terraform/convertor/TerraformConvertor.ts @@ -6,12 +6,12 @@ import { parseToNCloudModel } from '../util/resourceParser'; export class TerraformConvertor { private resources: NCloudModel[]; private provider: NCloudProvider; - private resourceMap: Map; + private resourceNameMap: Map; constructor(provider: NCloudProvider) { this.provider = provider; this.resources = []; - this.resourceMap = new Map(); + this.resourceNameMap = new Map(); } addResourceFromJson(jsonData: { nodes?: CloudCanvasNode[] }) { @@ -27,26 +27,50 @@ export class TerraformConvertor { addResource(resource: NCloudModel) { this.resources.push(resource); - this.resourceMap.set(resource.serviceType, resource.name); + this.resourceNameMap.set(resource.serviceType, resource.name); } - getResourceName(serviceType: string): string { - return this.resourceMap.get(serviceType) || ''; - } + private replaceReferences(properties: { [key: string]: any }): { [key: string]: any } { const result = { ...properties }; for (const [key, value] of Object.entries(result)) { if (typeof value === 'string') { - if (value === 'VPC_ID_PLACEHOLDER') { - const vpcName = this.resourceMap.get('ncloud_vpc'); - result[key] = `ncloud_vpc.${vpcName}.id`; - } - if (value === 'VPC_ACL_PLACEHOLDER') { - const vpcName = this.resourceMap.get('ncloud_vpc'); - result[key] = `ncloud_vpc.${vpcName}.default_network_acl_no`; + switch(value) { + case 'VPC_ID_PLACEHOLDER': + const vpcName = this.resourceNameMap.get('ncloud_vpc'); + result[key] = `ncloud_vpc.${vpcName}.id`; + break; + case 'VPC_ACL_PLACEHOLDER': + const vpcAclName = this.resourceNameMap.get('ncloud_vpc'); + result[key] = `ncloud_vpc.${vpcAclName}.default_network_acl_no`; + break; + case 'SUBNET_ID_PLACEHOLDER': + const subnetName = this.resourceNameMap.get('ncloud_subnet'); + result[key] = `ncloud_subnet.${subnetName}.id`; + break; + case 'ACG_ID_PLACEHOLDER': + const acgName = this.resourceNameMap.get('ncloud_access_control_group'); + result[key] = `ncloud_access_control_group.${acgName}.id`; + break; + case 'LOGIN_KEY_NAME_PLACEHOLDER': + const loginKeyName = this.resourceNameMap.get('ncloud_login_key'); + result[key] = `ncloud_login_key.${loginKeyName}.key_name`; + break; + case 'NIC_ID_PLACEHOLDER': + const nicName = this.resourceNameMap.get('ncloud_network_interface'); + result[key] = `ncloud_network_interface.${nicName}.id`; + break; + case 'SERVER_ID_PLACEHOLDER': + const serverName = this.resourceNameMap.get('ncloud_server'); + result[key] = `ncloud_server.${serverName}.id`; + break; } + } else if (Array.isArray(value)) { + result[key] = value.map(item => + typeof item === 'string' ? this.replaceReferences({temp: item}).temp : this.replaceReferences(item) + ); } else if (typeof value === 'object' && value !== null) { result[key] = this.replaceReferences(value); } @@ -56,6 +80,7 @@ export class TerraformConvertor { } + private formatValue(value: any): string { if (typeof value === 'string') { const ncloudRefPattern = /^ncloud_[a-zA-Z_]+\.[a-zA-Z_-]+\.[a-zA-Z_]+$/; diff --git a/apps/terraform/model/NCloudACG.ts b/apps/terraform/model/NCloudACG.ts index c3c1fa32..6a7c1c20 100644 --- a/apps/terraform/model/NCloudACG.ts +++ b/apps/terraform/model/NCloudACG.ts @@ -19,7 +19,7 @@ export class NCloudACG implements ACG, NCloudModel { getProperties() { return { name: this.name, - vpc_no: "ncloud_vpc.vpc.id", + vpc_no: "VPC_ID_PLACEHOLDER", description: this.description }; } diff --git a/apps/terraform/model/NCloudACGRule.ts b/apps/terraform/model/NCloudACGRule.ts index 901881c6..744d11fc 100644 --- a/apps/terraform/model/NCloudACGRule.ts +++ b/apps/terraform/model/NCloudACGRule.ts @@ -22,7 +22,7 @@ export class NCloudACGRule implements NCloudModel { getProperties() { return { - access_control_group_no: "ncloud_access_control_group.acg.id", + access_control_group_no: "ACG_ID_PLACEHOLDER", inbound: [{ protocol: this.protocol, ip_block: this.ipBlock, diff --git a/apps/terraform/model/NCloudNetworkACL.ts b/apps/terraform/model/NCloudNetworkACL.ts index f72dd098..8bef2f72 100644 --- a/apps/terraform/model/NCloudNetworkACL.ts +++ b/apps/terraform/model/NCloudNetworkACL.ts @@ -19,7 +19,7 @@ export class NCloudNetworkACL implements NetworkACL, NCloudModel { getProperties() { return { - vpc_no: "ncloud_vpc.vpc.id" + vpc_no: "VPC_ID_PLACEHOLDER" }; } } diff --git a/apps/terraform/model/NCloudNetworkInterface.ts b/apps/terraform/model/NCloudNetworkInterface.ts index dfc27b48..aa55f485 100644 --- a/apps/terraform/model/NCloudNetworkInterface.ts +++ b/apps/terraform/model/NCloudNetworkInterface.ts @@ -18,9 +18,9 @@ export class NCloudNetworkInterface implements NetworkInterface, NCloudModel { getProperties() { return { - subnet_no: "ncloud_subnet.subnet.id", + subnet_no: 'SUBNET_ID_PLACEHOLDER', name: this.name, - access_control_groups: "[ncloud_access_control_group.acg.id]", + access_control_groups: ['ACG_ID_PLACEHOLDER'] }; } } diff --git a/apps/terraform/model/NCloudPublicIP.ts b/apps/terraform/model/NCloudPublicIP.ts index 3d0759ab..9685fd3e 100644 --- a/apps/terraform/model/NCloudPublicIP.ts +++ b/apps/terraform/model/NCloudPublicIP.ts @@ -14,7 +14,7 @@ export class NCloudPublicIP implements NCloudModel { getProperties() { return { - server_instance_no: "ncloud_server.my-server.id" + server_instance_no: "SERVER_ID_PLACEHOLDER" }; } } diff --git a/apps/terraform/model/NCloudServer.ts b/apps/terraform/model/NCloudServer.ts index 31318073..d79d7818 100644 --- a/apps/terraform/model/NCloudServer.ts +++ b/apps/terraform/model/NCloudServer.ts @@ -27,13 +27,13 @@ export class NCloudServer implements Server, NCloudModel { getProperties() { return { - subnet_no: "ncloud_subnet.subnet.id", + subnet_no: "SUBNET_ID_PLACEHOLDER", name: this.name, server_image_product_code: this.serverImageProductCode, server_product_code: this.serverProductCode, - login_key_name: "ncloud_login_key.my-key.key_name", + login_key_name: "LOGIN_KEY_NAME_PLACEHOLDER", network_interface: { - network_interface_no: "ncloud_network_interface.my-nic.id", + network_interface_no: "NIC_ID_PLACEHOLDER", order: 0 } }; From f9525d29b792008c57421e71055ae3d4473b576a Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Thu, 21 Nov 2024 19:33:27 +0900 Subject: [PATCH 20/24] =?UTF-8?q?=F0=9F=90=9E=20Fix:=20json=20=ED=8C=8C?= =?UTF-8?q?=EC=8B=B1=EC=97=90=EC=84=9C=20properties=EC=95=88=EC=97=90=20?= =?UTF-8?q?=EC=9E=88=EB=8D=98=20name=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- apps/terraform/interface/CloudCanvasNode.ts | 1 + apps/terraform/main.ts | 181 ++++++++++---------- apps/terraform/util/resourceParser.ts | 18 +- 3 files changed, 102 insertions(+), 98 deletions(-) diff --git a/apps/terraform/interface/CloudCanvasNode.ts b/apps/terraform/interface/CloudCanvasNode.ts index dd7b3e70..69a47251 100644 --- a/apps/terraform/interface/CloudCanvasNode.ts +++ b/apps/terraform/interface/CloudCanvasNode.ts @@ -1,5 +1,6 @@ export interface CloudCanvasNode { id: string; type: string; + name: string; properties: { [key: string]: any }; } \ No newline at end of file diff --git a/apps/terraform/main.ts b/apps/terraform/main.ts index 9bc64406..bc6d5d67 100644 --- a/apps/terraform/main.ts +++ b/apps/terraform/main.ts @@ -1,101 +1,104 @@ +import { CloudCanvasNode } from './interface/CloudCanvasNode'; import { NCloudProvider } from './model/NCloudProvider'; import { TerraformConvertor } from './convertor/TerraformConvertor'; -import { NCloudVPC } from './model/NCloudVPC'; -import { NCloudSubnet } from './model/NCloudSubnet'; -import { NCloudNetworkACL } from './model/NCloudNetworkACL'; -import { NCloudACG } from './model/NCloudACG'; -import { NCloudACGRule } from './model/NCloudACGRule'; -import { NCloudLoginKey } from './model/NCloudLoginKey'; -import { NCloudNetworkInterface } from './model/NCloudNetworkInterface'; -import { NCloudServer } from './model/NCloudServer'; -import { NCloudPublicIP } from './model/NCloudPublicIP'; -async function main() { - const provider = new NCloudProvider({ - accessKey: "var.access_key", - secretKey: "var.secret_key", - region: "var.region", - site: "public" - }); - - const generator = new TerraformConvertor(provider); - - const vpc = new NCloudVPC({ - name: "vpc", - ipv4CidrBlock: "172.16.0.0/16" - }); - generator.addResource(vpc); - - const nacl = new NCloudNetworkACL({ - name: "nacl" - }); - generator.addResource(nacl); - - const subnet = new NCloudSubnet({ - name: "subnet", - subnet: "172.16.10.0/24", - zone: "KR-2", - subnetType: "PUBLIC", - usageType: "GEN" - }); - generator.addResource(subnet); - - const acg = new NCloudACG({ - name: "acg", - description: "My ACG" - }); - generator.addResource(acg); - - const acgRule = new NCloudACGRule({ - protocol: "TCP", - ipBlock: "0.0.0.0/0", - portRange: "80", - description: "HTTP" - }); - generator.addResource(acgRule); - - const loginKey = new NCloudLoginKey({ - name: "my-key" - }); - generator.addResource(loginKey); - - const nic = new NCloudNetworkInterface({ - name: "my-nic" - }); - generator.addResource(nic); - - const server = new NCloudServer({ +const sampleNodes: CloudCanvasNode[] = [ + { + id: "vpc1", + type: "VPC", + name: "my-vpc", + properties: { + cidrBlock: "172.16.0.0/16" + } + }, + { + id: "nacl1", + type: "NetworkACL", + name: "my-nacl", + properties: { + } + }, + { + id: "subnet1", + type: "Subnet", + name: "my-subnet", + properties: { + subnet: "172.16.10.0/24", + zone: "KR-2", + subnetType: "PUBLIC", + usageType: "GEN" + } + }, + { + id: "acg1", + type: "ACG", + name: "my-acg", + properties: { + description: "My ACG" + } + }, + { + id: "acgrule1", + type: "ACGRule", + name: "", + properties: { + protocol: "TCP", + ipBlock: "0.0.0.0/0", + portRange: "80", + description: "HTTP" + } + }, + { + id: "loginkey1", + type: "LoginKey", + name: "my-key", + properties: { + } + }, + { + id: "nic1", + type: "NetworkInterface", + name: "my-nic", + properties: {} + }, + { + id: "server1", + type: "Server", name: "my-server", - serverImageProductCode: "SW.VSVR.OS.LNX64.CNTOS.0708.B050", - serverProductCode: "SVR.VSVR.HICPU.C002.M004.NET.HDD.B050.G002" - }); - generator.addResource(server); - - const publicIp = new NCloudPublicIP({ - name: "public-ip" - }); - generator.addResource(publicIp); + properties: { + serverImageProductCode: "SW.VSVR.OS.LNX64.CNTOS.0708.B050", + serverProductCode: "SVR.VSVR.HICPU.C002.M004.NET.HDD.B050.G002" + } + }, + { + id: "publicip1", + type: "PublicIP", + name: "my-public-ip", + properties: {} + } +]; +async function main() { try { - await generator.saveToFile('main.tf'); - console.log('Terraform configuration has been generated.'); - - const { execSync } = require('child_process'); + const provider = new NCloudProvider({ + accessKey: "var.access_key", + secretKey: "var.secret_key", + region: "var.region", + site: "public" + }); + + const convertor = new TerraformConvertor(provider); + + convertor.addResourceFromJson({ nodes: sampleNodes }); + await convertor.saveToFile('main.tf'); + console.log('\nGenerated Terraform code:'); + console.log('----------------------------------------'); + console.log(convertor.generate()); + console.log('----------------------------------------'); - console.log('Running terraform init...'); - execSync('terraform init'); - - console.log('Running terraform plan...'); - execSync('terraform plan'); - - console.log('Running terraform apply...'); - execSync('terraform apply -auto-approve'); - - console.log('Infrastructure has been successfully created!'); } catch (error) { - console.error('Error:', error); + console.error('Error generating Terraform configuration:', error); } } main().catch(console.error); - diff --git a/apps/terraform/util/resourceParser.ts b/apps/terraform/util/resourceParser.ts index 0678a66f..f4236cee 100644 --- a/apps/terraform/util/resourceParser.ts +++ b/apps/terraform/util/resourceParser.ts @@ -12,23 +12,23 @@ import { NCloudPublicIP } from '../model/NCloudPublicIP'; export function parseToNCloudModel(resource: CloudCanvasNode ): NCloudModel { - const { type, properties } = resource; + const { type, name, properties } = resource; switch (type.toLowerCase()) { case 'vpc': return new NCloudVPC({ - name: properties.name || 'vpc', + name: name || 'vpc', ipv4CidrBlock: properties.cidrBlock }); case 'networkacl': return new NCloudNetworkACL({ - name: properties.name || 'nacl' + name: name || 'nacl' }); case 'subnet': return new NCloudSubnet({ - name: properties.name || 'subnet', + name: name || 'subnet', subnet: properties.subnet, zone: properties.zone, subnetType: properties.subnetType, @@ -38,7 +38,7 @@ export function parseToNCloudModel(resource: CloudCanvasNode ): NCloudModel { case 'acg': case 'accesscontrolgroup': return new NCloudACG({ - name: properties.name || 'acg', + name: name || 'acg', description: properties.description }); @@ -53,24 +53,24 @@ export function parseToNCloudModel(resource: CloudCanvasNode ): NCloudModel { case 'loginkey': return new NCloudLoginKey({ - name: properties.name || 'login-key' + name: name || 'login-key' }); case 'networkinterface': return new NCloudNetworkInterface({ - name: properties.name || 'nic' + name: name || 'nic' }); case 'server': return new NCloudServer({ - name: properties.name || 'server', + name: name || 'server', serverImageProductCode: properties.serverImageProductCode, serverProductCode: properties.serverProductCode }); case 'publicip': return new NCloudPublicIP({ - name: properties.name || 'public-ip' + name: name || 'public-ip' }); default: From 3112fe402e254d604a1886a248000220ba538df9 Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Thu, 21 Nov 2024 20:21:11 +0900 Subject: [PATCH 21/24] =?UTF-8?q?=F0=9F=90=9E=20Fix:=20=EB=B0=B0=EC=97=B4?= =?UTF-8?q?=20=EB=A6=AC=EC=86=8C=EC=8A=A4=20=EC=B0=B8=EC=A1=B0=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISSUES CLOSED: #78 --- .../terraform/convertor/TerraformConvertor.ts | 33 ++++++++----------- apps/terraform/model/NCloudACGRule.ts | 4 +-- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/apps/terraform/convertor/TerraformConvertor.ts b/apps/terraform/convertor/TerraformConvertor.ts index b2f768b2..e98c360f 100644 --- a/apps/terraform/convertor/TerraformConvertor.ts +++ b/apps/terraform/convertor/TerraformConvertor.ts @@ -68,9 +68,13 @@ export class TerraformConvertor { break; } } else if (Array.isArray(value)) { - result[key] = value.map(item => - typeof item === 'string' ? this.replaceReferences({temp: item}).temp : this.replaceReferences(item) - ); + result[key] = value.map(item => { + if (typeof item === 'string') { + const replacedValue = this.replaceReferences({ temp: item }).temp; + return replacedValue; + } + return this.replaceReferences(item); + }); } else if (typeof value === 'object' && value !== null) { result[key] = this.replaceReferences(value); } @@ -79,12 +83,13 @@ export class TerraformConvertor { return result; } - - private formatValue(value: any): string { + if (Array.isArray(value)) { + return `[${value.map(item => this.formatValue(item)).join(', ')}]`; + } + if (typeof value === 'string') { const ncloudRefPattern = /^ncloud_[a-zA-Z_]+\.[a-zA-Z_-]+\.[a-zA-Z_]+$/; - const varRefPattern = /^var\.[a-zA-Z_]+$/; if (ncloudRefPattern.test(value) || varRefPattern.test(value)) { @@ -101,30 +106,18 @@ export class TerraformConvertor { return Object.entries(properties) .map(([key, value]) => { - if (Array.isArray(value)) { - const formattedArray = value.map(item => { - if (typeof item === 'object') { - return ` ${key} { -${this.formatProperties(item)} - }`; - } - return ` ${key} = ${this.formatValue(item)}`; - }).join('\n'); - return formattedArray; - } + const padding = ' '.repeat(maxKeyLength - key.length); - if (typeof value === 'object' && value !== null) { + if (typeof value === 'object' && value !== null && !Array.isArray(value)) { return ` ${key} { ${this.formatProperties(value)} }`; } - const padding = ' '.repeat(maxKeyLength - key.length); return ` ${key}${padding} = ${this.formatValue(value)}`; }) .join('\n'); } - generate(): string { const providerProperties = this.provider.getProperties(); diff --git a/apps/terraform/model/NCloudACGRule.ts b/apps/terraform/model/NCloudACGRule.ts index 744d11fc..ea3b7092 100644 --- a/apps/terraform/model/NCloudACGRule.ts +++ b/apps/terraform/model/NCloudACGRule.ts @@ -23,12 +23,12 @@ export class NCloudACGRule implements NCloudModel { getProperties() { return { access_control_group_no: "ACG_ID_PLACEHOLDER", - inbound: [{ + inbound: { protocol: this.protocol, ip_block: this.ipBlock, port_range: this.portRange, description: this.description - }] + } }; } } From df185525d12b7c3824582fe88044717a005387c7 Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Fri, 22 Nov 2024 16:54:29 +0900 Subject: [PATCH 22/24] =?UTF-8?q?=F0=9F=A4=96=20Refactor:=20terraformConve?= =?UTF-8?q?rtor=20=EA=B0=81=20=EC=97=AD=ED=95=A0=EC=9D=B4=20=EB=AA=85?= =?UTF-8?q?=ED=99=95=ED=95=98=EA=B2=8C=20=ED=8C=8C=EC=9D=BC=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../terraform/convertor/TerraformConvertor.ts | 152 ++---------------- apps/terraform/util/file.ts | 57 +++++++ apps/terraform/util/formatter.ts | 46 ++++++ apps/terraform/util/generator.ts | 28 ++++ apps/terraform/util/reference.ts | 41 +++++ apps/terraform/variables.tf | 12 -- 6 files changed, 185 insertions(+), 151 deletions(-) create mode 100644 apps/terraform/util/file.ts create mode 100644 apps/terraform/util/formatter.ts create mode 100644 apps/terraform/util/generator.ts create mode 100644 apps/terraform/util/reference.ts delete mode 100644 apps/terraform/variables.tf diff --git a/apps/terraform/convertor/TerraformConvertor.ts b/apps/terraform/convertor/TerraformConvertor.ts index e98c360f..d2ffdd76 100644 --- a/apps/terraform/convertor/TerraformConvertor.ts +++ b/apps/terraform/convertor/TerraformConvertor.ts @@ -1,158 +1,32 @@ -import { NCloudModel } from '../interface/NCloudModel'; +import { ResourceManager } from '../type/ResourceManager'; +import { CodeGenerator } from '../type/TerraformGenerator'; import { NCloudProvider } from '../model/NCloudProvider'; import { CloudCanvasNode } from '../interface/CloudCanvasNode'; import { parseToNCloudModel } from '../util/resourceParser'; export class TerraformConvertor { - private resources: NCloudModel[]; - private provider: NCloudProvider; - private resourceNameMap: Map; + private readonly resourceManager: ResourceManager; + private readonly codeGenerator: CodeGenerator; + private readonly provider: NCloudProvider; constructor(provider: NCloudProvider) { this.provider = provider; - this.resources = []; - this.resourceNameMap = new Map(); + this.resourceManager = new ResourceManager(); + this.codeGenerator = new CodeGenerator(this.resourceManager); } - addResourceFromJson(jsonData: { nodes?: CloudCanvasNode[] }) { - jsonData.nodes?.forEach((node => { + addResourceFromJson(jsonData: { nodes?: CloudCanvasNode[] }): void { + jsonData.nodes?.forEach(node => { try { const resource = parseToNCloudModel(node); - this.addResource(resource); + this.resourceManager.addResource(resource); } catch (error) { console.warn(`Skipping unsupported node type: ${node.type}`); } - })); + }); } - addResource(resource: NCloudModel) { - this.resources.push(resource); - this.resourceNameMap.set(resource.serviceType, resource.name); - } - - - - private replaceReferences(properties: { [key: string]: any }): { [key: string]: any } { - const result = { ...properties }; - - for (const [key, value] of Object.entries(result)) { - if (typeof value === 'string') { - switch(value) { - case 'VPC_ID_PLACEHOLDER': - const vpcName = this.resourceNameMap.get('ncloud_vpc'); - result[key] = `ncloud_vpc.${vpcName}.id`; - break; - case 'VPC_ACL_PLACEHOLDER': - const vpcAclName = this.resourceNameMap.get('ncloud_vpc'); - result[key] = `ncloud_vpc.${vpcAclName}.default_network_acl_no`; - break; - case 'SUBNET_ID_PLACEHOLDER': - const subnetName = this.resourceNameMap.get('ncloud_subnet'); - result[key] = `ncloud_subnet.${subnetName}.id`; - break; - case 'ACG_ID_PLACEHOLDER': - const acgName = this.resourceNameMap.get('ncloud_access_control_group'); - result[key] = `ncloud_access_control_group.${acgName}.id`; - break; - case 'LOGIN_KEY_NAME_PLACEHOLDER': - const loginKeyName = this.resourceNameMap.get('ncloud_login_key'); - result[key] = `ncloud_login_key.${loginKeyName}.key_name`; - break; - case 'NIC_ID_PLACEHOLDER': - const nicName = this.resourceNameMap.get('ncloud_network_interface'); - result[key] = `ncloud_network_interface.${nicName}.id`; - break; - case 'SERVER_ID_PLACEHOLDER': - const serverName = this.resourceNameMap.get('ncloud_server'); - result[key] = `ncloud_server.${serverName}.id`; - break; - } - } else if (Array.isArray(value)) { - result[key] = value.map(item => { - if (typeof item === 'string') { - const replacedValue = this.replaceReferences({ temp: item }).temp; - return replacedValue; - } - return this.replaceReferences(item); - }); - } else if (typeof value === 'object' && value !== null) { - result[key] = this.replaceReferences(value); - } - } - - return result; - } - - private formatValue(value: any): string { - if (Array.isArray(value)) { - return `[${value.map(item => this.formatValue(item)).join(', ')}]`; - } - - if (typeof value === 'string') { - const ncloudRefPattern = /^ncloud_[a-zA-Z_]+\.[a-zA-Z_-]+\.[a-zA-Z_]+$/; - const varRefPattern = /^var\.[a-zA-Z_]+$/; - - if (ncloudRefPattern.test(value) || varRefPattern.test(value)) { - return value; - } - - return `"${value}"`; - } - return value; - } - - private formatProperties(properties: { [key: string]: any }): string { - const maxKeyLength = Math.max(...Object.keys(properties).map(key => key.length)); - - return Object.entries(properties) - .map(([key, value]) => { - const padding = ' '.repeat(maxKeyLength - key.length); - - if (typeof value === 'object' && value !== null && !Array.isArray(value)) { - return ` ${key} { -${this.formatProperties(value)} - }`; - } - - return ` ${key}${padding} = ${this.formatValue(value)}`; - }) - .join('\n'); - } generate(): string { - const providerProperties = this.provider.getProperties(); - - const terraformBlock = ` -terraform { - required_providers { - ncloud = { - source = "${providerProperties.terraform.required_providers.ncloud.source}" - } - } - required_version = "${providerProperties.terraform.required_version}" -}`; - - const providerBlock = ` -provider "${this.provider.name}" { -${this.formatProperties(providerProperties.provider)} -}`; - - const resourceBlocks = this.resources - .sort((a, b) => a.priority - b.priority) - .map(resource => { - const properties = this.replaceReferences(resource.getProperties()); - return ` -resource "${resource.serviceType}" "${resource.name}" { -${this.formatProperties(properties)} -}`; - }); - - return [terraformBlock, providerBlock, ...resourceBlocks].join('\n'); - } - - async saveToFile(filePath: string): Promise { - const fs = require('fs').promises; - const terraformCode = this.generate(); - console.log(terraformCode); - await fs.writeFile(filePath, terraformCode); + return this.codeGenerator.generateCode(this.provider); } -} +} \ No newline at end of file diff --git a/apps/terraform/util/file.ts b/apps/terraform/util/file.ts new file mode 100644 index 00000000..2ff83b7e --- /dev/null +++ b/apps/terraform/util/file.ts @@ -0,0 +1,57 @@ +import { FileOption } from '../interface/FileOption'; + +export const writeFile = async ( + filePath: string, + content: string, + options: FileOption = {} +): Promise => { + const fs = require('fs').promises; + await fs.writeFile(filePath, content); + + if (options.log) { + console.log(`\nGenerated ${filePath}:`); + console.log('----------------------------------------'); + console.log(content); + console.log('----------------------------------------'); + } +}; + +export const generateVariablesContent = (): string => ` +variable "access_key" { + type = string +} + +variable "secret_key" { + type = string +} + +variable "region" { + type = string + default = "KR" +}`; + +export const generateTfvarsContent = (): string => ` +access_key = "your_access_key" +secret_key = "your_secret_key" +region = "KR"`; + +export const saveTerraformFiles = async ( + terraformCode: string, + options: FileOption = {} +): Promise => { + try { + await writeFile('main.tf', terraformCode, options); + + const variablesContent = generateVariablesContent(); + await writeFile('variables.tf', variablesContent); + + const tfvarsContent = generateTfvarsContent(); + await writeFile('terraform.tfvars.example', tfvarsContent); + + console.log('\n테라폼 파일 생성 완료'); + console.log('terraform.tfvars 파일을 생성하고 key를 넣어주세요'); + + } catch (error) { + throw new Error(`Failed to save Terraform files: ${error instanceof Error ? error.message : 'Unknown error'}`); + } +}; diff --git a/apps/terraform/util/formatter.ts b/apps/terraform/util/formatter.ts new file mode 100644 index 00000000..43a74927 --- /dev/null +++ b/apps/terraform/util/formatter.ts @@ -0,0 +1,46 @@ +export const isNcloudReference = (value: string): boolean => { + const ncloudRefPattern = /^ncloud_[a-zA-Z_]+\.[a-zA-Z_-]+\.[a-zA-Z_]+$/; + return ncloudRefPattern.test(value); +}; + +export const isVariableReference = (value: string): boolean => { + const varRefPattern = /^var\.[a-zA-Z_]+$/; + return varRefPattern.test(value); +}; + +export const formatValue = (value: any): string => { + if (Array.isArray(value)) { + return `[${value.map(item => formatValue(item)).join(', ')}]`; + } + + if (typeof value === 'string') { + if (isNcloudReference(value) || isVariableReference(value)) { + return value; + } + return `"${value}"`; + } + + return String(value); +}; + +export const formatProperties = ( + properties: { [key: string]: any }, + indentLevel: number = 1 +): string => { + const indent = ' '.repeat(indentLevel); + const maxKeyLength = Math.max(...Object.keys(properties).map(key => key.length)); + + return Object.entries(properties) + .map(([key, value]) => { + const padding = ' '.repeat(maxKeyLength - key.length); + + if (typeof value === 'object' && value !== null && !Array.isArray(value)) { + return `${indent}${key} { +${formatProperties(value, indentLevel + 1)} +${indent}}`; + } + + return `${indent}${key}${padding} = ${formatValue(value)}`; + }) + .join('\n'); +}; diff --git a/apps/terraform/util/generator.ts b/apps/terraform/util/generator.ts new file mode 100644 index 00000000..09fdcfc8 --- /dev/null +++ b/apps/terraform/util/generator.ts @@ -0,0 +1,28 @@ +import { formatProperties } from './formatter'; + +export const generateTerraformBlock = (providerSource: string, version: string): string => ` +terraform { + required_providers { + ncloud = { + source = "${providerSource}" + } + } + required_version = "${version}" +}`; + +export const generateProviderBlock = ( + name: string, + properties: { [key: string]: any } +): string => ` +provider "${name}" { +${formatProperties(properties)} +}`; + +export const generateResourceBlock = ( + serviceType: string, + name: string, + properties: { [key: string]: any } +): string => ` +resource "${serviceType}" "${name}" { +${formatProperties(properties)} +}`; \ No newline at end of file diff --git a/apps/terraform/util/reference.ts b/apps/terraform/util/reference.ts new file mode 100644 index 00000000..0599f1eb --- /dev/null +++ b/apps/terraform/util/reference.ts @@ -0,0 +1,41 @@ +type ReferenceMap = Map; + +export const resolveReference = ( + placeholder: string, + resourceNameMap: ReferenceMap +): string => { + const references: { [key: string]: string } = { + 'VPC_ID_PLACEHOLDER': `ncloud_vpc.${resourceNameMap.get('ncloud_vpc')}.id`, + 'VPC_ACL_PLACEHOLDER': `ncloud_vpc.${resourceNameMap.get('ncloud_vpc')}.default_network_acl_no`, + 'SUBNET_ID_PLACEHOLDER': `ncloud_subnet.${resourceNameMap.get('ncloud_subnet')}.id`, + 'ACG_ID_PLACEHOLDER': `ncloud_access_control_group.${resourceNameMap.get('ncloud_access_control_group')}.id`, + 'LOGIN_KEY_NAME_PLACEHOLDER': `ncloud_login_key.${resourceNameMap.get('ncloud_login_key')}.key_name`, + 'NIC_ID_PLACEHOLDER': `ncloud_network_interface.${resourceNameMap.get('ncloud_network_interface')}.id`, + 'SERVER_ID_PLACEHOLDER': `ncloud_server.${resourceNameMap.get('ncloud_server')}.id` + }; + + return references[placeholder] || placeholder; +}; + +export const replaceReferences = ( + properties: { [key: string]: any }, + resourceNameMap: ReferenceMap +): { [key: string]: any } => { + const result = { ...properties }; + + for (const [key, value] of Object.entries(result)) { + if (typeof value === 'string') { + result[key] = resolveReference(value, resourceNameMap); + } else if (Array.isArray(value)) { + result[key] = value.map(item => + typeof item === 'string' + ? resolveReference(item, resourceNameMap) + : replaceReferences({ value: item }, resourceNameMap).value + ); + } else if (typeof value === 'object' && value !== null) { + result[key] = replaceReferences(value, resourceNameMap); + } + } + + return result; +}; diff --git a/apps/terraform/variables.tf b/apps/terraform/variables.tf deleted file mode 100644 index 4e8abed7..00000000 --- a/apps/terraform/variables.tf +++ /dev/null @@ -1,12 +0,0 @@ -variable "access_key" { - type = string -} - -variable "secret_key" { - type = string -} - -variable "region" { - type = string - default = "KR" -} \ No newline at end of file From 7b38f1c0c19fae14e34254b3fc49bcbe228a9b2a Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Fri, 22 Nov 2024 16:55:13 +0900 Subject: [PATCH 23/24] =?UTF-8?q?=F0=9F=A4=96=20Refactor:=20=EC=8B=A4?= =?UTF-8?q?=ED=96=89=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EA=B0=81=20=EA=B8=B0=EB=8A=A5=EC=9D=B4=20=EB=AA=85=ED=99=95?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=ED=8C=8C=EC=9D=BC=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terraform/interface/FileOption.ts | 3 + apps/terraform/main.ts | 114 +++++-------------------- apps/terraform/sample/sampleData.ts | 77 +++++++++++++++++ 3 files changed, 103 insertions(+), 91 deletions(-) create mode 100644 apps/terraform/interface/FileOption.ts create mode 100644 apps/terraform/sample/sampleData.ts diff --git a/apps/terraform/interface/FileOption.ts b/apps/terraform/interface/FileOption.ts new file mode 100644 index 00000000..9eee3c0f --- /dev/null +++ b/apps/terraform/interface/FileOption.ts @@ -0,0 +1,3 @@ +export interface FileOption { + log?: boolean; +} \ No newline at end of file diff --git a/apps/terraform/main.ts b/apps/terraform/main.ts index bc6d5d67..f65cf53d 100644 --- a/apps/terraform/main.ts +++ b/apps/terraform/main.ts @@ -1,103 +1,35 @@ import { CloudCanvasNode } from './interface/CloudCanvasNode'; import { NCloudProvider } from './model/NCloudProvider'; import { TerraformConvertor } from './convertor/TerraformConvertor'; +import { sampleNodes } from './sample/sampleData'; +import { saveTerraformFiles } from './util/file'; -const sampleNodes: CloudCanvasNode[] = [ - { - id: "vpc1", - type: "VPC", - name: "my-vpc", - properties: { - cidrBlock: "172.16.0.0/16" - } - }, - { - id: "nacl1", - type: "NetworkACL", - name: "my-nacl", - properties: { - } - }, - { - id: "subnet1", - type: "Subnet", - name: "my-subnet", - properties: { - subnet: "172.16.10.0/24", - zone: "KR-2", - subnetType: "PUBLIC", - usageType: "GEN" - } - }, - { - id: "acg1", - type: "ACG", - name: "my-acg", - properties: { - description: "My ACG" - } - }, - { - id: "acgrule1", - type: "ACGRule", - name: "", - properties: { - protocol: "TCP", - ipBlock: "0.0.0.0/0", - portRange: "80", - description: "HTTP" - } - }, - { - id: "loginkey1", - type: "LoginKey", - name: "my-key", - properties: { - } - }, - { - id: "nic1", - type: "NetworkInterface", - name: "my-nic", - properties: {} - }, - { - id: "server1", - type: "Server", - name: "my-server", - properties: { - serverImageProductCode: "SW.VSVR.OS.LNX64.CNTOS.0708.B050", - serverProductCode: "SVR.VSVR.HICPU.C002.M004.NET.HDD.B050.G002" - } - }, - { - id: "publicip1", - type: "PublicIP", - name: "my-public-ip", - properties: {} - } -]; +async function generateTerraformCode(): Promise { + const provider = new NCloudProvider({ + accessKey: "var.access_key", + secretKey: "var.secret_key", + region: "var.region", + site: "public" + }); -async function main() { - try { - const provider = new NCloudProvider({ - accessKey: "var.access_key", - secretKey: "var.secret_key", - region: "var.region", - site: "public" - }); + const converter = new TerraformConvertor(provider); + converter.addResourceFromJson({ nodes: sampleNodes }); - const convertor = new TerraformConvertor(provider); + return converter.generate(); +} - convertor.addResourceFromJson({ nodes: sampleNodes }); - await convertor.saveToFile('main.tf'); - console.log('\nGenerated Terraform code:'); - console.log('----------------------------------------'); - console.log(convertor.generate()); - console.log('----------------------------------------'); +async function main() { + try { + const terraformCode = await generateTerraformCode(); + await saveTerraformFiles(terraformCode, { log: true }); } catch (error) { - console.error('Error generating Terraform configuration:', error); + if (error instanceof Error) { + console.error('Error generating Terraform configuration:', error.message); + } else { + console.error('An unknown error occurred'); + } + process.exit(1); } } diff --git a/apps/terraform/sample/sampleData.ts b/apps/terraform/sample/sampleData.ts new file mode 100644 index 00000000..2a1a81a0 --- /dev/null +++ b/apps/terraform/sample/sampleData.ts @@ -0,0 +1,77 @@ +import { CloudCanvasNode } from '../interface/CloudCanvasNode'; + +export const sampleNodes: CloudCanvasNode[] = [ + { + id: "vpc1", + type: "VPC", + name: "my-vpc", + properties: { + cidrBlock: "172.16.0.0/16" + } + }, + { + id: "nacl1", + type: "NetworkACL", + name: "my-nacl", + properties: { + } + }, + { + id: "subnet1", + type: "Subnet", + name: "my-subnet", + properties: { + subnet: "172.16.10.0/24", + zone: "KR-2", + subnetType: "PUBLIC", + usageType: "GEN" + } + }, + { + id: "acg1", + type: "ACG", + name: "my-acg", + properties: { + description: "My ACG" + } + }, + { + id: "acgrule1", + type: "ACGRule", + name: "", + properties: { + protocol: "TCP", + ipBlock: "0.0.0.0/0", + portRange: "80", + description: "HTTP" + } + }, + { + id: "loginkey1", + type: "LoginKey", + name: "my-key", + properties: { + } + }, + { + id: "nic1", + type: "NetworkInterface", + name: "my-nic", + properties: {} + }, + { + id: "server1", + type: "Server", + name: "my-server", + properties: { + serverImageProductCode: "SW.VSVR.OS.LNX64.CNTOS.0708.B050", + serverProductCode: "SVR.VSVR.HICPU.C002.M004.NET.HDD.B050.G002" + } + }, + { + id: "publicip1", + type: "PublicIP", + name: "my-public-ip", + properties: {} + } +]; From 60f46ea0aa233f37b4013948cc4323f17a35be5f Mon Sep 17 00:00:00 2001 From: Gdm0714 Date: Fri, 22 Nov 2024 16:55:54 +0900 Subject: [PATCH 24/24] =?UTF-8?q?=F0=9F=A4=96=20Refactor:=20terrformConver?= =?UTF-8?q?tor=20=EA=B0=81=20=EA=B8=B0=EB=8A=A5=EC=9D=B4=20=EB=AA=85?= =?UTF-8?q?=ED=99=95=ED=95=98=EA=B2=8C=20=ED=8C=8C=EC=9D=BC=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terraform/type/ResourceManager.ts | 24 ++++++++++++ apps/terraform/type/TerraformGenerator.ts | 45 +++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 apps/terraform/type/ResourceManager.ts create mode 100644 apps/terraform/type/TerraformGenerator.ts diff --git a/apps/terraform/type/ResourceManager.ts b/apps/terraform/type/ResourceManager.ts new file mode 100644 index 00000000..b1621c51 --- /dev/null +++ b/apps/terraform/type/ResourceManager.ts @@ -0,0 +1,24 @@ +import { NCloudModel } from '../interface/NCloudModel'; + +export class ResourceManager { + private resources: NCloudModel[]; + private readonly nameMap: Map; + + constructor() { + this.resources = []; + this.nameMap = new Map(); + } + + addResource(resource: NCloudModel): void { + this.resources.push(resource); + this.nameMap.set(resource.serviceType, resource.name); + } + + getResources(): NCloudModel[] { + return [...this.resources].sort((a, b) => a.priority - b.priority); + } + + getNameMap(): Map { + return this.nameMap; + } +} diff --git a/apps/terraform/type/TerraformGenerator.ts b/apps/terraform/type/TerraformGenerator.ts new file mode 100644 index 00000000..ed4ce4fd --- /dev/null +++ b/apps/terraform/type/TerraformGenerator.ts @@ -0,0 +1,45 @@ +import { replaceReferences } from '../util/reference'; +import { generateProviderBlock, generateResourceBlock, generateTerraformBlock } from '../util/generator'; +import { ResourceManager } from './ResourceManager'; +import { NCloudProvider } from '../model/NCloudProvider'; + +export class CodeGenerator { + private resourceManager: ResourceManager; + + constructor(resourceManager: ResourceManager) { + this.resourceManager = resourceManager; + } + + generateCode(provider: NCloudProvider): string { + const providerProperties = provider.getProperties(); + + const blocks = [ + generateTerraformBlock( + providerProperties.terraform.required_providers.ncloud.source, + providerProperties.terraform.required_version + ), + generateProviderBlock( + provider.name, + providerProperties.provider + ), + ...this.generateResourceBlocks() + ]; + + return blocks.join('\n'); + } + + private generateResourceBlocks(): string[] { + return this.resourceManager.getResources().map(resource => { + const properties = replaceReferences( + resource.getProperties(), + this.resourceManager.getNameMap() + ); + + return generateResourceBlock( + resource.serviceType, + resource.name, + properties + ); + }); + } +} \ No newline at end of file