Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[AWS::CodeBuild::Fleet] - [Coverage] - add reserved capacity fleets with VPC-support #2047

Open
rgoltz opened this issue May 20, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@rgoltz
Copy link

rgoltz commented May 20, 2024

Name of the resource

AWS::CodeBuild::Fleet

Resource name

No response

Description

Normally CodeBuild provides only on-demand fleets, which are destroyed when the build finishes. Now, CodeBuild also offers reserved capacity fleets with VPC-support (EC2 that are maintained by CodeBuild) - These hosts remain available to receive subsequent build requests, which reduces build start-up latencies:

Following the "Working with reserved capacity"-docs, the API Reference should already Support Reserved Capacity for CreateFleet, UpdateFleet and BatchGetFleets. In order to use this capability, please add support within CloudFormation.

Other Details

No response

@FarrOut
Copy link

FarrOut commented May 28, 2024

FleetVpcConfig and OverflowBehavior has been implemented.

Please find test code below

class CodeBuildNest(NestedStack):

    def __init__(
        self,
        scope: Construct,
        construct_id: str,
        subnet_id: str,
        removal_policy: RemovalPolicy = RemovalPolicy.RETAIN,
        vpc: ec2.IVpc = None,
        **kwargs,
    ) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # subnet_id = str(vpc.private_subnets[0].subnet_id)
        subnet_arn = f"arn:aws:ec2:{self.region}:{self.account}:subnet/{subnet_id}"
        # subnet = ec2.Subnet.from_subnet_id(self, "subnet", subnet_id)

        role = iam.Role(
            self,
            "CodeBuildRole",
            assumed_by=iam.ServicePrincipal("codebuild.amazonaws.com"),
        )

        CfnOutput(self, "CodeBuildRoleArn", value=role.role_arn)

        policy = iam.Policy(
            self,
            "codebuild-fleet-policy",
            statements=[
                iam.PolicyStatement(
                    actions=[
                        "ec2:CreateNetworkInterface",
                        "ec2:DescribeDhcpOptions",
                        "ec2:DescribeNetworkInterfaces",
                        "ec2:DeleteNetworkInterface",
                        "ec2:DescribeSubnets",
                        "ec2:DescribeSecurityGroups",
                        "ec2:DescribeVpcs",
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=["*"],
                ),
                iam.PolicyStatement(
                    actions=[
                        "ec2:CreateNetworkInterfacePermission",
                        "ec2:ModifyNetworkInterfaceAttribute",
                    ],
                    effect=iam.Effect.ALLOW,
                    resources=[
                        f"arn:aws:ec2:{self.region}:{self.account}:network-interface/*"
                    ],
                    conditions={
                        # Doesn't work for some reason
                        # "StringEquals": {
                        #     "ec2:AuthorizedService": "codebuild.amazonaws.com"
                        # },
                        "ArnEquals": {"ec2:Subnet": [subnet_arn]},
                    },
                ),
            ],
        )
        policy.attach_to_role(role)

        fleet = codebuild.CfnFleet(
            self,
            "MyCfnFleet",
            base_capacity=3,
            compute_type="BUILD_GENERAL1_SMALL",
            environment_type="LINUX_CONTAINER",            
            tags=[CfnTag(key="Name", value="MyLinuxFleet")],
        )
        fleet.apply_removal_policy(removal_policy)

        # To avoid "Not authorized to perform DescribeSecurityGroups"
        # https://stackoverflow.com/a/60776576
        fleet.add_depends_on(policy.node.default_child)

        fleet.add_override("Properties.FleetVpcConfig.VpcId", vpc.vpc_id)
        fleet.add_override(
            "Properties.FleetVpcConfig.Subnets",
            [subnet_id],
        )

        sg = ec2.SecurityGroup(self, "BuildFleetSecurityGroup", vpc=vpc)
        fleet.add_override(
            "Properties.FleetVpcConfig.SecurityGroupIds", [sg.security_group_id]
        )

        fleet.add_override(
            "Properties.FleetServiceRole",
            role.role_arn,
        )

        fleet.add_override("Properties.OverflowBehavior", "QUEUE")

        CfnOutput(self, "FleetId", value=fleet.ref)
        CfnOutput(self, "FleetArn", value=fleet.attr_arn)
        CfnOutput(self, "FleetName", value=str(fleet.name))
{
 "Resources": {
  "CodeBuildRole728CBADE": {
   "Type": "AWS::IAM::Role",
   "Properties": {
    "AssumeRolePolicyDocument": {
     "Statement": [
      {
       "Action": "sts:AssumeRole",
       "Effect": "Allow",
       "Principal": {
        "Service": "codebuild.amazonaws.com"
       }
      }
     ],
     "Version": "2012-10-17"
    }
   }
  },
  "codebuildfleetpolicyC442E78B": {
   "Type": "AWS::IAM::Policy",
   "Properties": {
    "PolicyDocument": {
     "Statement": [
      {
       "Action": [
        "ec2:CreateNetworkInterface",
        "ec2:DeleteNetworkInterface",
        "ec2:DescribeDhcpOptions",
        "ec2:DescribeNetworkInterfaces",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeSubnets",
        "ec2:DescribeVpcs"
       ],
       "Effect": "Allow",
       "Resource": "*"
      },
      {
       "Action": [
        "ec2:CreateNetworkInterfacePermission",
        "ec2:ModifyNetworkInterfaceAttribute"
       ],
       "Condition": {
        "ArnEquals": {
         "ec2:Subnet": [
          "arn:aws:ec2:eu-west-1:000000000000:subnet/subnet-xxxxxxxxxxxxxxxxx"
         ]
        }
       },
       "Effect": "Allow",
       "Resource": "arn:aws:ec2:eu-west-1:000000000000:network-interface/*"
      }
     ],
     "Version": "2012-10-17"
    },
    "PolicyName": "codebuildfleetpolicyC442E78B",
    "Roles": [
     {
      "Ref": "CodeBuildRole728CBADE"
     }
    ]
   }
  },
  "MyCfnFleet": {
   "Type": "AWS::CodeBuild::Fleet",
   "Properties": {
    "BaseCapacity": 3,
    "ComputeType": "BUILD_GENERAL1_SMALL",
    "EnvironmentType": "LINUX_CONTAINER",
    "Tags": [
     {
      "Key": "Name",
      "Value": "MyLinuxFleet"
     }
    ],
    "FleetVpcConfig": {
     "VpcId": {
      "Fn::ImportValue": "CdkPythonNetworkingStack:VpcId"
     },
     "Subnets": [
      "subnet-xxxxxxxxxxxxxxxxx"
     ],
     "SecurityGroupIds": [
      {
       "Fn::GetAtt": [
        "BuildFleetSecurityGroup647CEC48",
        "GroupId"
       ]
      }
     ]
    },
    "FleetServiceRole": {
     "Fn::GetAtt": [
      "CodeBuildRole728CBADE",
      "Arn"
     ]
    },
    "OverflowBehavior": "QUEUE"
   },
   "DependsOn": [
    "codebuildfleetpolicyC442E78B"
   ],
   "UpdateReplacePolicy": "Delete",
   "DeletionPolicy": "Delete"
  },
  "BuildFleetSecurityGroup647CEC48": {
   "Type": "AWS::EC2::SecurityGroup",
   "Properties": {
    "GroupDescription": "CodeBuildStack/CodeBuildNest/BuildFleetSecurityGroup",
    "SecurityGroupEgress": [
     {
      "CidrIp": "0.0.0.0/0",
      "Description": "Allow all outbound traffic by default",
      "IpProtocol": "-1"
     }
    ],
    "VpcId": {
     "Fn::ImportValue": "CdkPythonNetworkingStack:VpcId"
    }
   }
  }
 },
 "Outputs": {
  "CodeBuildRoleArn": {
   "Value": {
    "Fn::GetAtt": [
     "CodeBuildRole728CBADE",
     "Arn"
    ]
   }
  },
  "FleetId": {
   "Value": {
    "Ref": "MyCfnFleet"
   }
  },
  "FleetArn": {
   "Value": {
    "Fn::GetAtt": [
     "MyCfnFleet",
     "Arn"
    ]
   }
  },
  "FleetName": {
   "Value": "None"
  }
 }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants