文档

ROS CDK入门应用示例

更新时间:

本文以创建阿里云专有网络(VPC)实例及其关联的交换机(vSwitch)实例为例,介绍在不同语言环境下如何使用ROS CDK。

应用场景

如果您想通过熟悉的编程语言完成对应资源的创建和配置,而不是依赖繁琐的JSON和YAML模板语法,您可以选择使用ROS CDK实现自动化部署及运维。更多信息,请参见概览

支持的语言

  • TypeScript

  • JavaScript

  • Java

  • Python

  • C#

前提条件

  • Java语言请确保JDK和Maven满足以下版本要求:

    • JDK:8及以上。

    • Maven:3.6及以上。

  • Python语言请确保Python版本在3.7及以上。

  • C#语言请确保本地存在.NET Core3.1版本,并且.NET SDK版本在5.0及以上。

步骤一:初始化工程

每个ROS CDK应用都要求创建在一个独立的工程目录下,且该应用需要使用独立工程目录中模块的依赖项。所以在创建应用之前,需要先创建一个工程目录并进行初始化。

执行以下命令,创建工程目录并初始化工程。

TypeScript

mkdir demo
cd demo
ros-cdk init --language=typescript --generate-only=true

JavaScript

mkdir demo
cd demo
ros-cdk init --language=javascript --generate-only=true

Java

mkdir demo
cd demo
ros-cdk init --language=java --generate-only=true

Python

mkdir demo
cd demo
ros-cdk init --language=python --generate-only=true

执行以下命令,创建一个属于当前工程的虚拟环境。

Python工程的运行依赖于虚拟环境(virtualenv),所以在初始化Python工程之后需要创建一个属于当前工程的虚拟环境。

python3 -m venv .venv

执行以下命令,进入虚拟环境。

source .venv/bin/activate

C#

mkdir demo
cd demo
ros-cdk init --language=csharp --generate-only=true

步骤二:配置阿里云凭证信息

  1. 执行以下命令,配置阿里云凭证信息。

    ros-cdk config
  2. 根据界面提示输入配置信息。

    endpoint(optional, default:https://ros.aliyuncs.com):
    defaultRegionId(optional, default:cn-hangzhou):cn-beijing
    
    [1] AK
    [2] StsToken
    [3] RamRoleArn
    [4] EcsRamRole
    [0] CANCEL
    
    Authenticate mode [1...4 / 0]: 1
    accessKeyId:************************
    accessKeySecret:******************************
    
     ✅ Your cdk configuration has been saved successfully!

    配置内容说明如下:

    • endpoint:ROS服务地址。默认值为https://ros.aliyuncs.com。

    • defaultRegionId:ROS资源栈部署的地域。默认值为cn-hangzhou。

    • Authenticate mode:鉴权方式。本示例的鉴权方式为AccessKey,您需要输入AccessKey ID和AccessKey Secret。关于如何获取AccessKey,请参见交互式配置(快速配置)

(可选)步骤三:预览工程结构

执行以下命令,预览工程结构。

tree .

执行命令后,输出以下内容:

TypeScript

.
├── README.md
├── bin
│   └── demo.ts
├── cdk.json
├── jest.config.js
├── lib
│   └── demo-stack.ts
├── package.json
├── test
│   └── demo.test.ts
└── tsconfig.json

4 directories, 8 files

工程结构说明如下:

  • bin/demo.ts:入口文件。

    说明

    一个工程有且仅有一个应用。

    示例中创建了一个应用(类型为ros.App)和一个资源栈(类型为DemoStack,名称为DemoStack),并将资源栈添加到应用中。demo.ts文件内容如下:

    #!/usr/bin/env node
    import * as ros from '@alicloud/ros-cdk-core';
    import { DemoStack } from '../lib/demo-stack';
    
    const app = new ros.App({outdir: './cdk.out'});
    new DemoStack(app, 'DemoStack');
    app.synth();
  • lib/demo-stack.ts:资源栈的定义文件。

    您可以将资源添加到资源栈中,动态构建资源栈。初始化生成的代码中,只为资源栈添加了描述信息。demo-stack.ts文件内容如下:

    import * as ros from '@alicloud/ros-cdk-core';
    
    export class DemoStack extends ros.Stack {
      constructor(scope: ros.Construct, id: string, props?: ros.StackProps) {
        super(scope, id, props);
        new ros.RosInfo(this, ros.RosInfo.description, "This is the simple ros cdk app example.");
        // The code that defines your stack goes here
      }
    }
    
  • test/demo.test.ts:单元测试文件。

    用于验证构建资源栈的逻辑是否符合预期。demo.test.ts文件内容如下:

    import { expect as expectCDK, matchTemplate, MatchStyle } from '@alicloud/ros-cdk-assert';
    import * as ros from '@alicloud/ros-cdk-core';
    import * as Demo from '../lib/demo-stack';
    
    test('Stack with version.', () => {
      const app = new ros.App();
      // WHEN
      const stack = new Demo.DemoStack(app, 'MyTestStack');
      // THEN
      expectCDK(stack).to(
        matchTemplate(
          {
            ROSTemplateFormatVersion: '2015-09-01',
            Description: "This is the simple ros cdk app example.",
            Metadata: {
                "ALIYUN::ROS::Interface": {
                    "TemplateTags" : [
                        "Create by ROS CDK"
                    ]
                }
            }
          },
          MatchStyle.EXACT,
        ),
      );
    });
    

JavaScript

.
├── README.md
├── bin
│   └── demo.js
├── cdk.json
├── jest.config.js
├── lib
│   └── demo-stack.js
├── package.json
└── test
    └── demo.test.js

4 directories, 7 files

工程结构说明如下:

  • bin/demo.js:入口文件。

    说明

    一个工程有且仅有一个应用。

    示例中创建了一个应用(类型为ros.App)和一个资源栈(类型为DemoStack,名称为DemoStack),并将资源栈添加到应用中。demo.js文件内容如下:

    #!/usr/bin/env node
    
    const ros = require('@alicloud/ros-cdk-core');
    const { DemoStack } = require('../lib/demo-stack');
    
    const app = new ros.App();
    new DemoStack(app, 'DemoStack');
    app.synth();
    
  • lib/demo-stack.js:资源栈的定义文件。

    您可以将资源添加到资源栈中,动态构建资源栈。初始化生成的代码中,只为资源栈添加了描述信息。demo-stack.js文件内容如下:

    const ros = require('@alicloud/ros-cdk-core');
    
    class DemoStack extends ros.Stack {
      /**
       *
       * @param {ros.Construct} scope
       * @param {string} id
       * @param {ros.StackProps} props
       */
      constructor(scope, id, props) {
        super(scope, id, props);
        new ros.RosInfo(this, ros.RosInfo.description, "This is the simple ros cdk app example.");
        // The code that defines your stack goes here
      }
    }
    
    module.exports = { DemoStack }
    
  • test/demo.test.js:单元测试文件。

    用于验证构建资源栈的逻辑是否符合预期。demo.test.js文件内容如下:

    const { expect, matchTemplate, MatchStyle } = require('@alicloud/ros-cdk-assert');
    const ros = require('@alicloud/ros-cdk-core');
    const Demo = require('../lib/demo-stack');
    
    test('Stack with version.', () => {
        const app = new ros.App();
        // WHEN
        const stack = new Demo.DemoStack(app, 'MyTestStack');
        // THEN
        expect(stack).to(matchTemplate({
            ROSTemplateFormatVersion: '2015-09-01',
            Description: "This is the simple ros cdk app example.",
            Metadata: {
                "ALIYUN::ROS::Interface": {
                    "TemplateTags" : [
                        "Create by ROS CDK"
                    ]
                }
            }
        }, MatchStyle.EXACT))
    });
    

Java

.
├── README.md
├── cdk.json
├── pom.xml
└── src
    ├── main
    │   └── java
    │       └── com
    │           └── myorg
    │               ├── DemoApp.java
    │               └── DemoStack.java
    └── test
        └── java
            └── com
                └── myorg
                    └── DemoTest.java

10 directories, 6 files

工程结构说明如下:

  • src/main/java/com/myorg/DemoApp.java:入口文件。

    说明

    一个工程有且仅有一个应用。

    示例中创建了一个应用(类型为App)和一个资源栈(类型为DemoStack,名称为DemoStack),并将资源栈添加到应用中。DemoApp.java文件内容如下:

    package com.myorg;
    
    import com.aliyun.ros.cdk.core.*;
    
    import java.util.Arrays;
    
    public class DemoApp {
        public static void main(final String[] args) {
            App app = new App();
    
            new DemoStack(app, "DemoStack");
    
            app.synth();
        }
    }
    
  • src/main/java/com/myorg/DemoStack.java:资源栈的定义文件。

    您可以将资源添加到资源栈中,动态构建资源栈。初始化生成的代码中,只为资源栈添加了描述信息。DemoStack.java文件内容如下:

    package com.myorg;
    
    import com.aliyun.ros.cdk.core.*;
    
    public class DemoStack extends Stack {
        public DemoStack(final Construct scope, final String id) {
            this(scope, id, null);
        }
    
        public DemoStack(final Construct scope, final String id, final StackProps props) {
            super(scope, id, props);
    
            // The code that defines your stack goes here
        }
    }
    
  • src/test/java/com/myorg/DemoTest.java:单元测试文件。

    用于验证构建资源栈的逻辑是否符合预期。DemoTest.java文件内容如下:

    package com.myorg;
    
    import com.aliyun.ros.cdk.core.*;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.SerializationFeature;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    import org.junit.Test;
    import com.fasterxml.jackson.databind.node.ArrayNode;
    
    import java.io.IOException;
    
    import static org.junit.Assert.assertEquals;
    
    public class DemoTest {
        private final static ObjectMapper JSON =
            new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true);
    
        @Test
        public void testStack() throws IOException {
            App app = new App();
            DemoStack stack = new DemoStack(app, "test");
    
            // synthesize the stack to a ROS template and compare against
            // a checked-in JSON file.
            JsonNode actual = JSON.valueToTree(app.synth().getStackArtifact(stack.getArtifactId()).getTemplate());
            ObjectNode expected = new ObjectMapper().createObjectNode();
            expected.put("ROSTemplateFormatVersion", "2015-09-01");
            ObjectNode metadata = expected.putObject("Metadata");
            ObjectNode rosInterface = metadata.putObject("ALIYUN::ROS::Interface");
            ArrayNode templateTags = rosInterface.putArray("TemplateTags");
            templateTags.add("Create by ROS CDK");
            assertEquals(expected, actual);
        }
    }
    

Python

.
├── README.md
├── app.py
├── cdk.json
├── demo
│   ├── __init__.py
│   └── demo_stack.py
├── requirements.txt
├── setup.py
├── source.bat
└── test
    ├── __init__.py
    └── test_demo.py

3 directories, 10 files

工程结构说明如下:

  • app.py:入口文件。

    说明

    一个工程有且仅有一个应用。

    示例中创建了一个应用(类型为core.App)和一个资源栈(类型为DemoStack,名称为demo),并将资源栈添加到应用中。app.py文件内容如下:

    #!/usr/bin/env python3
    
    import ros_cdk_core as core
    
    from demo.demo_stack import DemoStack
    
    
    app = core.App()
    
    DemoStack(app, "demo")
    
    app.synth()
    
  • demo/demo_stack.py:资源栈的定义文件。

    您可以将资源添加到资源栈中,动态构建资源栈。初始化生成的代码中,只为资源栈添加了描述信息。demo_stack.py文件内容如下:

    import ros_cdk_core as core
    
    
    class DemoStack(core.Stack):
    
        def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
            super().__init__(scope, construct_id, **kwargs)
    
            # The code that defines your stack goes here
    
  • test/test_demo.py:单元测试文件。

    用于验证构建资源栈的逻辑是否符合预期。test_demo.py文件内容如下:

    #!/usr/bin/env python3
    import unittest
    import ros_cdk_core as core
    from demo.demo_stack import DemoStack
    
    
    class TestStack(unittest.TestCase):
        def setUp(self):
            pass
    
        def test_stack(self):
            app = core.App()
            stack = DemoStack(app, "testdemo")
            artifact = app.synth().get_stack_artifact(stack.artifact_id).template
            expect = {
                       "Metadata": {
                         "ALIYUN::ROS::Interface": {
                           "TemplateTags": [
                             "Create by ROS CDK"
                           ]
                         }
                       },
                       "ROSTemplateFormatVersion": "2015-09-01"
                     }
            self.assertDictContainsSubset(artifact, expect)
    
        def tearDown(self):
            pass
    
    
    if __name__ == '__main__':
        unittest.main()

C#

.
├── README.md
├── cdk.json
├── global.sln
└── src
    ├── Demo
    │   ├── Demo.csproj
    │   ├── DemoStack.cs
    │   ├── GlobalSuppressions.cs
    │   └── Program.cs
    └── DemoTest
        ├── DemoTest.cs
        └── DemoTest.csproj

4 directories, 9 files

初始化工程之后默认会定义一个应用文件(Program.cs),与一个资源栈文件(DemoStack.cs)。您可以在DemoStack.cs中通过自定义代码的方式动态构建资源栈。资源栈将被默认添加到应用中,每个工程只允许存在一个应用。工程结构说明如下:

  • src/Demo/DemoStack.cs:资源栈文件。

    初始化生成的代码中,只为资源栈添加了描述信息。DemoStack.cs文件内容如下:

    using AlibabaCloud.SDK.ROS.CDK.Core;
    
    namespace Demo
    {
        public class DemoStack : Stack
        {
            public DemoStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
            {
                // The code that defines your stack goes here
            }
        }
    }
    
  • src/Demo/Program.cs:应用文件。

    您可以将资源栈添加到应用中。Program.cs文件内容如下:

    using AlibabaCloud.SDK.ROS.CDK.Core;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace Demo
    {
        sealed class Program
        {
            public static void Main(string[] args)
            {
                var app = new App();
                new DemoStack(app, "DemoStack");
                app.Synth();
            }
        }
    }
    
  • src/DemoTest/DemoTest.cs:单元测试文件。

    用于验证构建资源栈的逻辑是否符合预期。DemoTest.cs文件内容如下:

    using AlibabaCloud.SDK.ROS.CDK.Core;
    using NUnit.Framework;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using Demo;
    
    namespace Stack.UnitTests.Services
    {
        [TestFixture]
        public class Stack_IsStackShould
        {
            [Test]
            public void DemoStack_IsStackShould()
            {
                var app = new App();
                var testStack = new DemoStack(app, "TestStack");
                var result = app.Synth().GetStackArtifact(testStack.ArtifactId).Template;
                var actualJson = JsonConvert.SerializeObject(result);
                JObject obj = new JObject();
                JObject metadata = new JObject();
                JObject rosInterface = new JObject();
                JArray templateTags = new JArray();
                metadata.Add("ALIYUN::ROS::Interface", rosInterface);
                rosInterface.Add("TemplateTags", templateTags);
                templateTags.Add("Create by ROS CDK");
                obj.Add("Metadata", metadata);
                obj.Add("ROSTemplateFormatVersion", "2015-09-01");
                var expected = JsonConvert.SerializeObject(obj);
                Assert.AreEqual(actualJson, expected);
            }
        }
    }
    

步骤四:安装依赖

  1. 添加ECS依赖包。

    TypeScript

    修改package.json文件。

    {
      "name": "demo",
      "version": "0.1.0",
      "bin": {
        "demo": "bin/demo.js"
      },
      "scripts": {
        "build": "tsc",
        "test": "jest"
      },
      "devDependencies": {
        "@types/jest": "^25.2.1",
        "@types/node": "10.17.5",
        "typescript": "^3.9.7",
        "jest": "^25.5.0",
        "ts-jest": "^25.3.1",
        "ts-node": "^8.1.0",
        "babel-jest": "^26.6.3",
        "@babel/core": "^7.12.9",
        "@babel/preset-env": "7.12.7",
        "@babel/preset-typescript": "^7.12.7",
        "@alicloud/ros-cdk-assert": "^1.0.25"
      },
      "dependencies": {
        "@alicloud/ros-cdk-core": "^1.0.25",
        "@alicloud/ros-cdk-ecs": "^1.0.23"
      }
    }
    

    JavaScript

    修改package.json文件。

    {
      "name": "demo",
      "version": "0.1.0",
      "bin": {
        "demo": "bin/demo.js"
      },
      "scripts": {
        "build": "echo \"The build step is not required when using JavaScript!\" && exit 0",
        "cdk": "cdk",
        "test": "jest"
      },
      "devDependencies": {
        "@types/jest": "^25.2.1",
        "@types/node": "10.17.5",
        "typescript": "^3.9.7",
        "jest": "^25.5.0",
        "ts-jest": "^25.3.1",
        "ts-node": "^8.1.0",
        "babel-jest": "^26.6.3",
        "@babel/core": "^7.12.9",
        "@babel/preset-env": "7.12.7",
        "@babel/preset-typescript": "^7.12.7",
        "@alicloud/ros-cdk-assert": "^1.0.25"
      },
      "dependencies": {
        "@alicloud/ros-cdk-core": "^1.0.25",
        "@alicloud/ros-cdk-ecs": "^1.0.23"
      }
    }
    

    Java

    修改pom.xml文件。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
             xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.myorg</groupId>
        <artifactId>demo</artifactId>
        <version>0.1</version>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <cdk.version>1.0.25</cdk.version>
        </properties>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
    
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>1.6.0</version>
                    <configuration>
                        <mainClass>com.myorg.DemoApp</mainClass>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
        <dependencies>
            <!-- AliCloud ROS Cloud Development Kit (ROS CDK) -->
            <dependency>
                <groupId>com.aliyun</groupId>
                <artifactId>ros-cdk-core</artifactId>
                <version>1.0.25</version>
            </dependency>
            <dependency>
                <groupId>com.aliyun</groupId>
                <artifactId>ros-cdk-ecs</artifactId>
                <version>1.0.23</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/junit/junit -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </project>
    

    Python

    修改requirements.txt文件。

    ros-cdk-core==1.0.25
    ros-cdk-ecs==1.0.23

    C#

    修改 src/Demo/Demo.csproj文件。

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp3.1</TargetFramework>
        <!-- Roll forward to future major versions of the netcoreapp as needed -->
        <RollForward>Major</RollForward>
      </PropertyGroup>
    
      <ItemGroup>
        <!-- CDK Construct Library dependencies -->
        <PackageReference Include="AlibabaCloud.SDK.ROS.CDK.Core" Version="1.0.25" />
        <PackageReference Include="AlibabaCloud.SDK.ROS.CDK.Ecs" Version="1.0.23" />
    
    
        <!-- jsii Roslyn analyzers (un-comment to obtain compile-time checks for missing required props
        <PackageReference Include="Amazon.Jsii.Analyzers" Version="*" PrivateAssets="all" />
        -->
    
      </ItemGroup>
    
    </Project>
    
  2. 执行以下命令,安装依赖。

    TypeScript

    npm install

    JavaScript

    npm install

    Java

    mvn compile

    Python

    • 方法一:

      pip install -r requirements.txt
    • 方法二:

      pip install ros-cdk-core ros-cdk-ecs

    C#示例

    说明

    该语言无需命令行安装依赖。

步骤五:添加资源

  1. 添加一个VPC和一台vSwitch。

    TypeScript

    修改lib/demo-stack.ts文件。

    import * as ros from '@alicloud/ros-cdk-core';
    import * as ecs from '@alicloud/ros-cdk-ecs';
    
    export class DemoStack extends ros.Stack {
      constructor(scope: ros.Construct, id: string, props?: ros.StackProps) {
        super(scope, id, props);
        new ros.RosInfo(this, ros.RosInfo.description, "This is the simple ros cdk app example.");
        // The code that defines your stack goes here
    
        const vpc = new ecs.Vpc(this, 'vpc-from-ros-cdk', {
          vpcName: 'test-ros-cdk',
          cidrBlock: '10.0.0.0/8',
          description: 'This is ros cdk test'
        });
    
        new ecs.VSwitch(this, 'vsw-from-ros-cdk', {
          vSwitchName: 'test-ros-cdk',
          cidrBlock: '10.0.0.0/16',
          zoneId: 'cn-hangzhou-i',
          vpcId: vpc.ref
        });
      }
    }
    

    JavaScript

    修改lib/demo-stack.js文件。

    const ros = require('@alicloud/ros-cdk-core');
    const ecs = require('@alicloud/ros-cdk-ecs');
    
    class DemoStack extends ros.Stack {
      /**
       *
       * @param {ros.Construct} scope
       * @param {string} id
       * @param {ros.StackProps} props
       */
      constructor(scope, id, props) {
        super(scope, id, props);
        new ros.RosInfo(this, ros.RosInfo.description, "This is the simple ros cdk app example.");
        // The code that defines your stack goes here
        const vpc = new ecs.Vpc(this, 'vpc-from-ros-cdk', {
          vpcName: 'test-ros-cdk-javascript',
          cidrBlock: '10.0.0.0/8',
          description: 'This is ros cdk test',
        });
    
        new ecs.VSwitch(this, 'vsw-from-ros-cdk', {
          vSwitchName: 'test-ros-cdk-javascript',
          cidrBlock: '10.0.0.0/16',
          zoneId: 'cn-hangzhou-i',
          vpcId: vpc.ref,
        });
      }
    }
    
    module.exports = { DemoStack }
    

    Java

    修改DemoStack.java文件。

    package com.myorg;
    
    import com.aliyun.ros.cdk.core.*;
    import com.aliyun.ros.cdk.ecs.*;
    
    public class DemoStack extends Stack {
        public DemoStack(final Construct scope, final String id) {
            this(scope, id, null);
        }
    
        public DemoStack(final Construct scope, final String id, final StackProps props) {
            super(scope, id, props);
    
            // The code that defines your stack goes here
    
            Vpc vpc = Vpc.Builder.create(this, "vpc-from-ros-cdk").vpcName("TestJavaCDK").description("This is ros java cdk test").
                    cidrBlock("10.0.0.0/8").build();
    
            VSwitch vsw = VSwitch.Builder.create(this, "vsw-from-ros-cdk").vSwitchName("TestJavaCDK").zoneId("cn-hangzhou-i").
                    cidrBlock("10.0.0.0/16").vpcId(vpc.getRef()).build();
        }
    }

    Python

    修改demo_stack.py文件。

    import ros_cdk_core as core
    import ros_cdk_ecs as ecs
    
    
    class DemoStack(core.Stack):
    
        def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
            super().__init__(scope, construct_id, **kwargs)
    
            # The code that defines your stack goes here
            vpc = ecs.Vpc(self, "MyVPC", ecs.VPCProps(
                cidr_block='10.0.0.0/8',
                vpc_name='test-ros-cdk-python',
                description='This is ros python cdk test'
            ))
    
            ecs.VSwitch(self, "MyVSwitch", ecs.VSwitchProps(
                cidr_block='10.0.0.0/16',
                v_switch_name='test-ros-cdk-python',
                zone_id='cn-hangzhou-i',
                vpc_id=vpc.ref
            ))

    C#

    修改DemoStack.cs文件。

    using AlibabaCloud.SDK.ROS.CDK.Core;
    using AlibabaCloud.SDK.ROS.CDK.Ecs;
    
    namespace Demo
    {
        public class DemoStack : Stack
        {
            public DemoStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
            {
                var vpc = new Vpc(this, "vpc-from-ros-cdk", new VPCProps
                {
                    VpcName = "test-ros-cdk-csharp",
                    CidrBlock = "10.0.0.0/8",
                    Description = "This is ros cdk test"
                });
    
                new VSwitch(this, "vsw-from-ros-cdk", new VSwitchProps
                {
                    VSwitchName = "test-ros-cdk-csharp",
                    CidrBlock = "10.0.0.0/16",
                    ZoneId="cn-hangzhou-i",
                    VpcId=vpc.Ref,
                });
            }
        }
    }
  2. (可选)执行以下命令,生成模板文件。

    TypeScript

    ros-cdk synth --json

    JavaScript

    ros-cdk synth --json

    Java

    mvn compile
    ros-cdk synth --json

    Python

    ros-cdk synth --json

    C#

    ros-cdk synth --json

    执行命令后,输出以下内容:

    TypeScript

    {
      "Description": "This is the simple ros cdk app example.",
      "Metadata": {
        "ALIYUN::ROS::Interface": {
          "TemplateTags": [
            "Create by ROS CDK"
          ]
        }
      },
      "ROSTemplateFormatVersion": "2015-09-01",
      "Resources": {
        "vpc-from-ros-cdk": {
          "Type": "ALIYUN::ECS::VPC",
          "Properties": {
            "CidrBlock": "10.0.0.0/8",
            "Description": "This is ros cdk test",
            "EnableIpv6": false,
            "VpcName": "test-ros-cdk"
          }
        },
        "vsw-from-ros-cdk": {
          "Type": "ALIYUN::ECS::VSwitch",
          "Properties": {
            "CidrBlock": "10.0.0.0/16",
            "VpcId": {
              "Ref": "vpc-from-ros-cdk"
            },
            "ZoneId": "cn-hangzhou-i",
            "VSwitchName": "test-ros-cdk"
          }
        }
      }
    }

    JavaScript

    {
      "Description": "This is the simple ros cdk app example.",
      "Metadata": {
        "ALIYUN::ROS::Interface": {
          "TemplateTags": [
            "Create by ROS CDK"
          ]
        }
      },
      "ROSTemplateFormatVersion": "2015-09-01",
      "Resources": {
        "vpc-from-ros-cdk": {
          "Type": "ALIYUN::ECS::VPC",
          "Properties": {
            "CidrBlock": "10.0.0.0/8",
            "Description": "This is ros cdk test",
            "EnableIpv6": false,
            "VpcName": "test-ros-cdk-javascript"
          }
        },
        "vsw-from-ros-cdk": {
          "Type": "ALIYUN::ECS::VSwitch",
          "Properties": {
            "CidrBlock": "10.0.0.0/16",
            "VpcId": {
              "Ref": "vpc-from-ros-cdk"
            },
            "ZoneId": "cn-hangzhou-i",
            "VSwitchName": "test-ros-cdk-javascript"
          }
        }
      }
    }

    Java

    {
      "Metadata": {
        "ALIYUN::ROS::Interface": {
          "TemplateTags": [
            "Create by ROS CDK"
          ]
        }
      },
      "ROSTemplateFormatVersion": "2015-09-01",
      "Resources": {
        "vpc-from-ros-cdk": {
          "Type": "ALIYUN::ECS::VPC",
          "Properties": {
            "CidrBlock": "10.0.0.0/8",
            "Description": "This is ros java cdk test",
            "EnableIpv6": false,
            "VpcName": "TestJavaCDK"
          }
        },
        "vsw-from-ros-cdk": {
          "Type": "ALIYUN::ECS::VSwitch",
          "Properties": {
            "CidrBlock": "10.0.0.0/16",
            "VpcId": {
              "Ref": "vpc-from-ros-cdk"
            },
            "ZoneId": "cn-hangzhou-i",
            "VSwitchName": "TestJavaCDK"
          }
        }
      }
    }

    Python

    {
      "Metadata": {
        "ALIYUN::ROS::Interface": {
          "TemplateTags": [
            "Create by ROS CDK"
          ]
        }
      },
      "ROSTemplateFormatVersion": "2015-09-01",
      "Resources": {
        "MyVPC": {
          "Type": "ALIYUN::ECS::VPC",
          "Properties": {
            "CidrBlock": "10.0.0.0/8",
            "Description": "This is ros python cdk test",
            "EnableIpv6": false,
            "VpcName": "test-ros-cdk-python"
          }
        },
        "MyVSwitch": {
          "Type": "ALIYUN::ECS::VSwitch",
          "Properties": {
            "CidrBlock": "10.0.0.0/16",
            "VpcId": {
              "Ref": "MyVPC"
            },
            "ZoneId": "cn-hangzhou-i",
            "VSwitchName": "test-ros-cdk-python"
          }
        }
      }
    }

    C#

    {
      "Metadata": {
        "ALIYUN::ROS::Interface": {
          "TemplateTags": [
            "Create by ROS CDK"
          ]
        }
      },
      "ROSTemplateFormatVersion": "2015-09-01",
      "Resources": {
        "vpc-from-ros-cdk": {
          "Type": "ALIYUN::ECS::VPC",
          "Properties": {
            "CidrBlock": "10.0.0.0/8",
            "Description": "This is ros cdk test",
            "EnableIpv6": false,
            "VpcName": "test-ros-cdk-csharp"
          }
        },
        "vsw-from-ros-cdk": {
          "Type": "ALIYUN::ECS::VSwitch",
          "Properties": {
            "CidrBlock": "10.0.0.0/16",
            "VpcId": {
              "Ref": "vpc-from-ros-cdk"
            },
            "ZoneId": "cn-hangzhou-i",
            "VSwitchName": "test-ros-cdk-csharp"
          }
        }
      }
    }

(可选)步骤六:单元测试

  1. 验证资源栈创建VPC和VSwitch的可行性。

    TypeScript

    修改test/demo.test.ts文件。

    import { expect as expectCDK, matchTemplate, MatchStyle } from '@alicloud/ros-cdk-assert';
    import * as ros from '@alicloud/ros-cdk-core';
    import * as Demo from '../lib/demo-stack';
    
    test('Stack with version.', () => {
      const app = new ros.App();
      // WHEN
      const stack = new Demo.DemoStack(app, 'MyTestStack');
      // THEN
      expectCDK(stack).to(
        matchTemplate(
          {
            "Description": "This is the simple ros cdk app example.",
            "Metadata": {
              "ALIYUN::ROS::Interface": {
                "TemplateTags": [
                  "Create by ROS CDK"
                ]
              }
            },
            "ROSTemplateFormatVersion": "2015-09-01",
            "Resources": {
              "vpc-from-ros-cdk": {
                "Type": "ALIYUN::ECS::VPC",
                "Properties": {
                  "CidrBlock": "10.0.0.0/8",
                  "Description": "This is ros cdk test",
                  "EnableIpv6": false,
                  "VpcName": "test-ros-cdk"
                }
              },
              "vsw-from-ros-cdk": {
                "Type": "ALIYUN::ECS::VSwitch",
                "Properties": {
                  "CidrBlock": "10.0.0.0/16",
                  "VpcId": {
                    "Ref": "vpc-from-ros-cdk"
                  },
                  "ZoneId": "cn-hangzhou-i",
                  "VSwitchName": "test-ros-cdk"
                }
              }
            }
          },
          MatchStyle.EXACT,
        ),
      );
    });
    

    JavaScript

    修改demo.test.js文件。

    const { expect, matchTemplate, MatchStyle } = require('@alicloud/ros-cdk-assert');
    const ros = require('@alicloud/ros-cdk-core');
    const Demo = require('../lib/demo-stack');
    
    test('Stack with version.', () => {
        const app = new ros.App();
        // WHEN
        const stack = new Demo.DemoStack(app, 'MyTestStack');
        // THEN
        expect(stack).to(matchTemplate({
            "Description": "This is the simple ros cdk app example.",
            "Metadata": {
              "ALIYUN::ROS::Interface": {
                "TemplateTags": [
                  "Create by ROS CDK"
                ]
              }
            },
            "ROSTemplateFormatVersion": "2015-09-01",
            "Resources": {
              "vpc-from-ros-cdk": {
                "Type": "ALIYUN::ECS::VPC",
                "Properties": {
                  "CidrBlock": "10.0.0.0/8",
                  "Description": "This is ros cdk test",
                  "EnableIpv6": false,
                  "VpcName": "test-ros-cdk-javascript"
                }
              },
              "vsw-from-ros-cdk": {
                "Type": "ALIYUN::ECS::VSwitch",
                "Properties": {
                  "CidrBlock": "10.0.0.0/16",
                  "VpcId": {
                    "Ref": "vpc-from-ros-cdk"
                  },
                  "ZoneId": "cn-hangzhou-i",
                  "VSwitchName": "test-ros-cdk-javascript"
                }
              }
            }
          }, MatchStyle.EXACT))
    });
    

    Java

    修改DemoTest.java文件。

    package com.myorg;
    
    import com.aliyun.ros.cdk.core.*;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.SerializationFeature;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    import org.junit.Test;
    import com.fasterxml.jackson.databind.node.ArrayNode;
    
    import java.io.IOException;
    
    import static org.junit.Assert.assertEquals;
    
    public class DemoTest {
        private final static ObjectMapper JSON =
            new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true);
    
        @Test
        public void testStack() throws IOException {
            App app = new App();
            DemoStack stack = new DemoStack(app, "test");
    
            // synthesize the stack to a ROS template and compare against
            // a checked-in JSON file.
            JsonNode actual = JSON.valueToTree(app.synth().getStackArtifact(stack.getArtifactId()).getTemplate());
            ObjectNode expected = new ObjectMapper().createObjectNode();
            expected.put("ROSTemplateFormatVersion", "2015-09-01");
            ObjectNode metadata = expected.putObject("Metadata");
            ObjectNode rosInterface = metadata.putObject("ALIYUN::ROS::Interface");
            ArrayNode templateTags = rosInterface.putArray("TemplateTags");
            templateTags.add("Create by ROS CDK");
            ObjectNode resources = expected.putObject("Resources");
    
            ObjectNode vpc = resources.putObject("vpc-from-ros-cdk");
            vpc.put("Type","ALIYUN::ECS::VPC");
            ObjectNode vpcProperties = vpc.putObject("Properties");
            vpcProperties.put("CidrBlock","10.0.0.0/8");
            vpcProperties.put("Description","This is ros java cdk test");
            vpcProperties.put("EnableIpv6",false);
            vpcProperties.put("VpcName","TestJavaCDK");
    
            ObjectNode vsw = resources.putObject("vsw-from-ros-cdk");
            vsw.put("Type","ALIYUN::ECS::VSwitch");
            ObjectNode vswProperties = vsw.putObject("Properties");
            vswProperties.put("CidrBlock","10.0.0.0/16");
            ObjectNode vpcId = vswProperties.putObject("VpcId");
            vpcId.put("Ref","vpc-from-ros-cdk");
            vswProperties.put("ZoneId","cn-hangzhou-i");
            vswProperties.put("VSwitchName","TestJavaCDK");
    
            assertEquals(expected, actual);
        }
    }

    Python

    修改test_demo.py文件。

    #!/usr/bin/env python3
    import unittest
    import ros_cdk_core as core
    from demo.demo_stack import DemoStack
    
    
    class TestStack(unittest.TestCase):
        def setUp(self):
            pass
    
        def test_stack(self):
            app = core.App()
            stack = DemoStack(app, "testdemo")
            artifact = app.synth().get_stack_artifact(stack.artifact_id).template
            expect = {
              "Metadata": {
                "ALIYUN::ROS::Interface": {
                  "TemplateTags": [
                    "Create by ROS CDK"
                  ]
                }
              },
              "ROSTemplateFormatVersion": "2015-09-01",
              "Resources": {
                "MyVPC": {
                  "Type": "ALIYUN::ECS::VPC",
                  "Properties": {
                    "CidrBlock": "10.0.0.0/8",
                    "Description": "This is ros python cdk test",
                    "EnableIpv6": False,
                    "VpcName": "test-ros-cdk-python"
                  }
                },
                "MyVSwitch": {
                  "Type": "ALIYUN::ECS::VSwitch",
                  "Properties": {
                    "CidrBlock": "10.0.0.0/16",
                    "VpcId": {
                      "Ref": "MyVPC"
                    },
                    "ZoneId": "cn-hangzhou-i",
                    "VSwitchName": "test-ros-cdk-python"
                  }
                }
              }
            }
            self.assertDictContainsSubset(artifact, expect)
    
        def tearDown(self):
            pass
    
    
    if __name__ == '__main__':
        unittest.main()

    C#

    修改DemoTest.cs文件。

    using AlibabaCloud.SDK.ROS.CDK.Core;
    using NUnit.Framework;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using Demo;
    
    namespace Stack.UnitTests.Services
    {
        [TestFixture]
        public class Stack_IsStackShould
        {
            [Test]
            public void DemoStack_IsStackShould()
            {
                var app = new App();
                var testStack = new DemoStack(app, "TestStack");
                var result = app.Synth().GetStackArtifact(testStack.ArtifactId).Template;
                var actualJson = JsonConvert.SerializeObject(result);
                JObject obj = new JObject();
                JObject Resources = new JObject();
                JObject VPC = new JObject();
                JObject VSW = new JObject();
                JObject vpcProperties = new JObject();
                JObject vswProperties = new JObject();
                JObject metadata = new JObject();
                JObject rosInterface = new JObject();
                JArray templateTags = new JArray();
                JObject vpcId = new JObject();
                metadata.Add("ALIYUN::ROS::Interface", rosInterface);
                rosInterface.Add("TemplateTags", templateTags);
                templateTags.Add("Create by ROS CDK");
                obj.Add("Metadata", metadata);
                VPC.Add("Type", "ALIYUN::ECS::VPC");
                VPC.Add("Properties", vpcProperties);
                Resources.Add("vpc-from-ros-cdk", VPC);
                vpcProperties.Add("CidrBlock", "10.0.0.0/8");
                vpcProperties.Add("Description", "This is ros cdk test");
                vpcProperties.Add("EnableIpv6", false);
                vpcProperties.Add("VpcName", "test-ros-cdk-csharp");
                VSW.Add("Type", "ALIYUN::ECS::VSwitch");
                VSW.Add("Properties", vswProperties);
                Resources.Add("vsw-from-ros-cdk", VSW);
                vswProperties.Add("CidrBlock", "10.0.0.0/16");
                vpcId.Add("Ref", "vpc-from-ros-cdk");
                vswProperties.Add("VpcId", vpcId);
                vswProperties.Add("ZoneId", "cn-hangzhou-i");
                vswProperties.Add("VSwitchName", "test-ros-cdk-csharp");
                obj.Add("ROSTemplateFormatVersion", "2015-09-01");
                obj.Add("Resources", Resources);
                var expected = JsonConvert.SerializeObject(obj);
                Assert.AreEqual(actualJson, expected);
            }
        }
    }
  2. 执行以下命令,进行单元测试。

    TypeScript

    npm test

    JavaScript

    npm test

    Java

    mvn test

    Python

    python -m unittest  -v

    C#

    dotnet test

    执行命令后,输出以下内容:

    TypeScript

    > demo@0.1.0 test
    > jest
    
     PASS  test/demo.test.ts
      ✓ Stack with version. (89ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        1.731s
    Ran all test suites.

    JavaScript

    > demo@0.1.0 test
    > jest
    
     PASS  test/demo.test.js
      ✓ Stack with version. (94ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        1.298s
    Ran all test suites.

    Java

    [INFO] -------------------------------------------------------
    [INFO]  T E S T S
    [INFO] -------------------------------------------------------
    [INFO] Running com.myorg.DemoTest
    [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.892 s -- in com.myorg.DemoTest
    [INFO] 
    [INFO] Results:
    [INFO] 
    [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    [INFO] 
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  3.319 s
    [INFO] Finished at: 2024-03-26T14:20:08+08:00
    [INFO] ------------------------------------------------------------------------

    Python

    test_stack (test.test_demo.TestStack) ... ok
    
    ----------------------------------------------------------------------
    Ran 1 test in 0.021s
    
    OK

    C#

    正在启动测试执行,请稍候...
    总共 1 个测试文件与指定模式相匹配。
    
    已通过! - 失败:     0,通过:     1,已跳过:     0,总计:     1,持续时间: 1 s - DemoTest.dll (netcoreapp3.1)
    

步骤七:部署资源栈

您可以使用ROS CDK命令,创建、查询或删除资源栈。

执行以下命令,创建资源栈。

ros-cdk deploy --region cn-hangzhou

执行命令后,输出以下内容:

✅ The deployment(create stack) has completed!
StackId: 701ecf04-d758-457f-a0fc-7e00e2b6****

(可选)步骤八:查询资源栈

执行以下命令,查询资源栈。

ros-cdk list-stacks

执行命令后,输出以下内容:

✅ The Stacks list in cn-hangzhou is:
 [
	{
		"Status": "CREATE_COMPLETE",
		"OperationInfo": {},
		"ResourceGroupId": "rg-acfm2xwmxvr****",
		"ServiceManaged": false,
		"StatusReason": "Stack CREATE completed successfully",
		"CreateTime": "2024-03-25T06:02:10",
		"DeletionProtection": "Disabled",
		"StackType": "ROS",
		"RegionId": "cn-hangzhou",
		"DisableRollback": false,
		"StackName": "DemoStack",
		"Tags": [
			{
				"Value": "rg-acfm2xwmxvr****",
				"Key": "acs:rm:rgId"
			}
		],
		"TimeoutInMinutes": 20,
		"StackId": "701ecf04-d758-457f-a0fc-7e00e2b6****"
	}
] 

(可选)步骤九:更新资源栈

  1. 更新VPC描述,并删除vSwitch资源

    TypeScript

    修改lib/demo-stack.ts文件。

    import * as ros from '@alicloud/ros-cdk-core';
    import * as ecs from '@alicloud/ros-cdk-ecs';
    
    export class DemoStack extends ros.Stack {
      constructor(scope: ros.Construct, id: string, props?: ros.StackProps) {
        super(scope, id, props);
        new ros.RosInfo(this, ros.RosInfo.description, "This is the simple ros cdk app example.");
        // The code that defines your stack goes here
    
        const vpc = new ecs.Vpc(this, 'vpc-from-ros-cdk', {
          vpcName: 'test-ros-cdk',
          cidrBlock: '10.0.0.0/8',
          description: 'Test update vpc name by ros cdk.'
        });
      }
    }
    

    JavaScript

    修改lib/demo-stack.js文件。

    const ros = require('@alicloud/ros-cdk-core');
    const ecs = require('@alicloud/ros-cdk-ecs');
    
    class DemoStack extends ros.Stack {
      /**
       *
       * @param {ros.Construct} scope
       * @param {string} id
       * @param {ros.StackProps} props
       */
      constructor(scope, id, props) {
        super(scope, id, props);
        new ros.RosInfo(this, ros.RosInfo.description, "This is the simple ros cdk app example.");
        // The code that defines your stack goes here
        const vpc = new ecs.Vpc(this, 'vpc-from-ros-cdk', {
          vpcName: 'test-ros-cdk-javascript',
          cidrBlock: '10.0.0.0/8',
          description: 'Test update vpc name by ros cdk.',
        });
      }
    }
    
    module.exports = { DemoStack }
    

    Java

    修改DemoStack.java文件。

    package com.myorg;
    
    import com.aliyun.ros.cdk.core.*;
    import com.aliyun.ros.cdk.ecs.*;
    
    public class DemoStack extends Stack {
        public DemoStack(final Construct scope, final String id) {
            this(scope, id, null);
        }
    
        public DemoStack(final Construct scope, final String id, final StackProps props) {
            super(scope, id, props);
    
            // The code that defines your stack goes here
    
            Vpc.Builder.create(this, "VPC").vpcName("TestJavaCDK").description("Test update vpc name by ros cdk.").
                    cidrBlock("10.0.0.0/8").build();
        }
    }

    Python

    修改demo_stack.py文件。

    import ros_cdk_core as core
    import ros_cdk_ecs as ecs
    
    
    class DemoStack(core.Stack):
    
        def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
            super().__init__(scope, construct_id, **kwargs)
    
            # The code that defines your stack goes here
            vpc = ecs.Vpc(self, "MyVPC", ecs.VPCProps(
                cidr_block='10.0.0.0/8',
                vpc_name='test-ros-cdk-python',
                description='Test update vpc name by ros cdk.'
            ))

    C#

    修改DemoStack.cs文件。

    using AlibabaCloud.SDK.ROS.CDK.Core;
    using AlibabaCloud.SDK.ROS.CDK.Ecs;
    
    namespace Demo
    {
        public class DemoStack : Stack
        {
            public DemoStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
            {
                var vpc = new Vpc(this, "vpc-from-ros-cdk", new VPCProps
                {
                    VpcName = "test-ros-cdk-csharp",
                    CidrBlock = "10.0.0.0/8",
                    Description = "Test update vpc name by ros cdk."
                });
            }
        }
    }
  2. 重新执行以下命令,更新资源栈。

    ros-cdk deploy --region cn-hangzhou

    执行命令后,输出以下内容:

     ✅ The deployment(update stack) has completed!
    StackId: 701ecf04-d758-457f-a0fc-7e00e2b6****

步骤十:删除资源栈

  1. 执行以下命令,删除资源栈。

    ros-cdk destroy
  2. 根据界面提示,确认删除。

    The following stack(s) will be destroyed(Only deployed stacks will be displayed).
    
    DemoStack
    
    Please confirm.(Y/N)
    Y

    执行命令后,输出以下内容:

     ✅ Deleted
    RequestedId: 1BF864E1-7965-4148-A302-E6ABFF80****