FredericHeem/starhackit

View on GitHub
deploy/grucloud-aws/iac.js

Summary

Maintainability
C
1 day
Test Coverage
const { AwsProvider } = require("@grucloud/provider-aws");
const assert = require("assert");

const createResources = async ({ provider, resources: { keyPair } }) => {
  const { config } = provider;
  const { domainName, stage } = config;

  const AvailabilityZone = `${config.region}${config.availabilityZoneSuffix}`;

  const Device = "/dev/sdf";
  const deviceMounted = "/dev/xvdf";
  const mountPoint = "/data";
  const vpc = provider.EC2.makeVpc({
    name: "vpc",
    properties: () => ({
      CidrBlock: "10.1.0.0/16",
    }),
  });
  const ig = provider.EC2.makeInternetGateway({
    name: "ig",
    dependencies: { vpc },
  });

  const subnet = provider.EC2.makeSubnet({
    name: "subnet",
    dependencies: { vpc },
    properties: () => ({
      CidrBlock: "10.1.0.1/24",
      AvailabilityZone,
    }),
  });

  const routeTable = provider.EC2.makeRouteTable({
    name: "route-table",
    dependencies: { vpc, subnets: [subnet] },
  });

  const route = provider.EC2.makeRoute({
    name: "route-ig",
    dependencies: { routeTable, ig },
  });

  const securityGroup = provider.EC2.makeSecurityGroup({
    name: "securityGroup",
    dependencies: { vpc, subnet },
    properties: () => ({
      //https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/EC2.html#createSecurityGroup-property
      Description: "Security Group Description",
    }),
  });
  const sgRuleIngressSsh = provider.EC2.makeSecurityGroupRuleIngress({
    name: "sg-rule-ingress-ssh",
    dependencies: {
      securityGroup,
    },
    properties: () => ({
      IpPermission: {
        FromPort: 22,
        IpProtocol: "tcp",
        IpRanges: [
          {
            CidrIp: "0.0.0.0/0",
          },
        ],
        Ipv6Ranges: [
          {
            CidrIpv6: "::/0",
          },
        ],
        ToPort: 22,
      },
    }),
  });
  const sgRuleIngressHttp = provider.EC2.makeSecurityGroupRuleIngress({
    name: "sg-rule-ingress-http",
    dependencies: {
      securityGroup,
    },
    properties: () => ({
      IpPermission: {
        FromPort: 80,
        IpProtocol: "tcp",
        IpRanges: [
          {
            CidrIp: "0.0.0.0/0",
          },
        ],
        Ipv6Ranges: [
          {
            CidrIpv6: "::/0",
          },
        ],
        ToPort: 80,
      },
    }),
  });
  const sgRuleIngressHttps = provider.EC2.makeSecurityGroupRuleIngress({
    name: "sg-rule-ingress-https",
    dependencies: {
      securityGroup,
    },
    properties: () => ({
      IpPermission: {
        FromPort: 443,
        IpProtocol: "tcp",
        IpRanges: [
          {
            CidrIp: "0.0.0.0/0",
          },
        ],
        Ipv6Ranges: [
          {
            CidrIpv6: "::/0",
          },
        ],
        ToPort: 443,
      },
    }),
  });
  const sgRuleIngressIcmp = provider.EC2.makeSecurityGroupRuleIngress({
    name: "sg-rule-ingress-icmp",
    dependencies: {
      securityGroup,
    },
    properties: () => ({
      IpPermission: {
        FromPort: -1,
        IpProtocol: "icmp",
        IpRanges: [
          {
            CidrIp: "0.0.0.0/0",
          },
        ],
        Ipv6Ranges: [
          {
            CidrIpv6: "::/0",
          },
        ],
        ToPort: -1,
      },
    }),
  });

  const eip = provider.EC2.makeElasticIpAddress({
    name: "ip",
  });

  const image = provider.EC2.useImage({
    name: "ubuntu 20.04",
    properties: () => ({
      Filters: [
        {
          Name: "architecture",
          Values: ["x86_64"],
        },
        {
          Name: "description",
          Values: ["Canonical, Ubuntu, 20.04 LTS, amd64 focal*"],
        },
      ],
    }),
  });

  const volume = provider.EC2.makeVolume({
    name: "volume",
    properties: () => ({
      Size: 10,
      VolumeType: "standard",
      Device,
      AvailabilityZone,
    }),
  });

  // Allocate a server
  const server = provider.EC2.makeInstance({
    name: "server",
    dependencies: {
      keyPair,
      subnet,
      securityGroups: [securityGroup],
      eip,
      image,
      volumes: [volume],
    },
    properties: () => ({
      UserData: volume.spec.setupEbsVolume({ deviceMounted, mountPoint }),
      InstanceType: "t2.micro",
      Placement: { AvailabilityZone },
    }),
  });

  const domain = provider.Route53Domains.useDomain({
    name: domainName,
  });

  const hostedZoneName = `${domainName}.`;
  const hostedZone = provider.Route53.makeHostedZone({
    name: hostedZoneName,
    dependencies: { domain },
    properties: ({}) => ({}),
  });

  const recordA = provider.Route53.makeRecord({
    name: `app.${hostedZoneName}`,
    dependencies: { hostedZone, eip },
    properties: ({ dependencies: { eip } }) => {
      return {
        Name: `app.${hostedZoneName}`,
        Type: "A",
        ResourceRecords: [
          {
            Value: eip.live?.PublicIp,
          },
        ],
        TTL: 60,
      };
    },
  });

  const recordAGitPage = provider.Route53.makeRecord({
    name: `${hostedZoneName}`,
    dependencies: { hostedZone },
    properties: ({ dependencies }) => {
      return {
        Name: `${hostedZoneName}`,
        Type: "A",
        ResourceRecords: [
          {
            Value: "185.199.108.153",
          },
          {
            Value: "185.199.109.153",
          },
        ],
        TTL: 86400,
      };
    },
  });
  const recordWww = provider.Route53.makeRecord({
    name: `${hostedZoneName}-gitpage-record-www`,
    dependencies: { hostedZone },
    properties: () => {
      return {
        Name: `www.${hostedZoneName}`,
        Type: "CNAME",
        ResourceRecords: [
          {
            Value: "grucloud.github.io.",
          },
        ],
        TTL: 86400,
      };
    },
  });

  const recordMx = provider.Route53.makeRecord({
    name: `${hostedZoneName}-mx`,
    dependencies: { hostedZone },
    properties: () => {
      return {
        Name: `${hostedZoneName}`,
        Type: "MX",
        ResourceRecords: [
          {
            Value: "1 ASPMX.L.GOOGLE.COM.",
          },
          {
            Value: "5 ALT1.ASPMX.L.GOOGLE.COM.",
          },
        ],
        TTL: 86400,
      };
    },
  });
  return {
    vpc,
    ig,
    subnet,
    routeTable,
    securityGroup,
    eip,
    server,
    //hostedZone, recordA
  };
};

exports.createResources = createResources;

//TODO
exports.createStack = async ({ config, stage }) => {
  // Create a AWS provider
  const provider = AwsProvider({ config, stage });
  const { keyPairName } = provider.config;
  assert(keyPairName);

  const keyPair = provider.EC2.useKeyPair({
    name: keyPairName,
  });
  const resources = await createResources({ provider, resources: { keyPair } });
  return { provider, resources };
};