@gati-framework/cli
Version:
CLI tool for Gati framework - create, develop, build and deploy cloud-native applications
267 lines • 9.33 kB
JavaScript
/**
* @module plugins/aws/vpc
* @description VPC and networking configuration for AWS EKS
*/
/**
* Generate CloudFormation template for VPC
*/
export function generateVPCTemplate(config, clusterName) {
const template = {
AWSTemplateFormatVersion: '2010-09-09',
Description: `VPC for Gati EKS cluster: ${clusterName}`,
Parameters: {
ClusterName: {
Type: 'String',
Default: clusterName,
Description: 'Name of the EKS cluster',
},
},
Resources: {
VPC: {
Type: 'AWS::EC2::VPC',
Properties: {
CidrBlock: config.cidr,
EnableDnsHostnames: true,
EnableDnsSupport: true,
Tags: [
{ Key: 'Name', Value: `${clusterName}-vpc` },
{ Key: 'kubernetes.io/cluster/' + clusterName, Value: 'shared' },
],
},
},
InternetGateway: {
Type: 'AWS::EC2::InternetGateway',
Properties: {
Tags: [{ Key: 'Name', Value: `${clusterName}-igw` }],
},
},
InternetGatewayAttachment: {
Type: 'AWS::EC2::VPCGatewayAttachment',
Properties: {
InternetGatewayId: { Ref: 'InternetGateway' },
VpcId: { Ref: 'VPC' },
},
},
...generateSubnetResources(config, clusterName),
...generateRouteTableResources(config, clusterName),
...(config.enableNat ? generateNATResources(config, clusterName) : {}),
},
Outputs: {
VpcId: {
Value: { Ref: 'VPC' },
Export: { Name: `${clusterName}-VpcId` },
},
PublicSubnetIds: {
Value: {
'Fn::Join': [
',',
config.publicSubnets.map((_, i) => ({ Ref: `PublicSubnet${i + 1}` })),
],
},
Export: { Name: `${clusterName}-PublicSubnetIds` },
},
PrivateSubnetIds: {
Value: {
'Fn::Join': [
',',
config.privateSubnets.map((_, i) => ({ Ref: `PrivateSubnet${i + 1}` })),
],
},
Export: { Name: `${clusterName}-PrivateSubnetIds` },
},
},
};
return JSON.stringify(template, null, 2);
}
/**
* Generate subnet resources
*/
function generateSubnetResources(config, clusterName) {
const resources = {};
// Public subnets
config.publicSubnets.forEach((cidr, index) => {
const subnetName = `PublicSubnet${index + 1}`;
resources[subnetName] = {
Type: 'AWS::EC2::Subnet',
Properties: {
VpcId: { Ref: 'VPC' },
CidrBlock: cidr,
AvailabilityZone: config.availabilityZones[index % config.availabilityZones.length],
MapPublicIpOnLaunch: true,
Tags: [
{ Key: 'Name', Value: `${clusterName}-public-${index + 1}` },
{ Key: 'kubernetes.io/role/elb', Value: '1' },
{ Key: 'kubernetes.io/cluster/' + clusterName, Value: 'shared' },
],
},
};
});
// Private subnets
config.privateSubnets.forEach((cidr, index) => {
const subnetName = `PrivateSubnet${index + 1}`;
resources[subnetName] = {
Type: 'AWS::EC2::Subnet',
Properties: {
VpcId: { Ref: 'VPC' },
CidrBlock: cidr,
AvailabilityZone: config.availabilityZones[index % config.availabilityZones.length],
MapPublicIpOnLaunch: false,
Tags: [
{ Key: 'Name', Value: `${clusterName}-private-${index + 1}` },
{ Key: 'kubernetes.io/role/internal-elb', Value: '1' },
{ Key: 'kubernetes.io/cluster/' + clusterName, Value: 'shared' },
],
},
};
});
return resources;
}
/**
* Generate route table resources
*/
function generateRouteTableResources(config, clusterName) {
const resources = {};
// Public route table
resources['PublicRouteTable'] = {
Type: 'AWS::EC2::RouteTable',
Properties: {
VpcId: { Ref: 'VPC' },
Tags: [{ Key: 'Name', Value: `${clusterName}-public-rt` }],
},
};
resources['PublicRoute'] = {
Type: 'AWS::EC2::Route',
DependsOn: 'InternetGatewayAttachment',
Properties: {
RouteTableId: { Ref: 'PublicRouteTable' },
DestinationCidrBlock: '0.0.0.0/0',
GatewayId: { Ref: 'InternetGateway' },
},
};
// Associate public subnets with public route table
config.publicSubnets.forEach((_, index) => {
resources[`PublicSubnetRouteTableAssociation${index + 1}`] = {
Type: 'AWS::EC2::SubnetRouteTableAssociation',
Properties: {
RouteTableId: { Ref: 'PublicRouteTable' },
SubnetId: { Ref: `PublicSubnet${index + 1}` },
},
};
});
// Private route tables (one per AZ if NAT enabled)
if (config.enableNat) {
config.privateSubnets.forEach((_, index) => {
const rtName = `PrivateRouteTable${index + 1}`;
resources[rtName] = {
Type: 'AWS::EC2::RouteTable',
Properties: {
VpcId: { Ref: 'VPC' },
Tags: [{ Key: 'Name', Value: `${clusterName}-private-rt-${index + 1}` }],
},
};
resources[`PrivateRoute${index + 1}`] = {
Type: 'AWS::EC2::Route',
Properties: {
RouteTableId: { Ref: rtName },
DestinationCidrBlock: '0.0.0.0/0',
NatGatewayId: { Ref: `NATGateway${index + 1}` },
},
};
resources[`PrivateSubnetRouteTableAssociation${index + 1}`] = {
Type: 'AWS::EC2::SubnetRouteTableAssociation',
Properties: {
RouteTableId: { Ref: rtName },
SubnetId: { Ref: `PrivateSubnet${index + 1}` },
},
};
});
}
return resources;
}
/**
* Generate NAT gateway resources
*/
function generateNATResources(config, clusterName) {
const resources = {};
// Create NAT gateway for each public subnet
config.publicSubnets.forEach((_, index) => {
resources[`NATGatewayEIP${index + 1}`] = {
Type: 'AWS::EC2::EIP',
DependsOn: 'InternetGatewayAttachment',
Properties: {
Domain: 'vpc',
Tags: [{ Key: 'Name', Value: `${clusterName}-nat-eip-${index + 1}` }],
},
};
resources[`NATGateway${index + 1}`] = {
Type: 'AWS::EC2::NATGateway',
Properties: {
AllocationId: { 'Fn::GetAtt': [`NATGatewayEIP${index + 1}`, 'AllocationId'] },
SubnetId: { Ref: `PublicSubnet${index + 1}` },
Tags: [{ Key: 'Name', Value: `${clusterName}-nat-${index + 1}` }],
},
};
});
return resources;
}
/**
* Validate VPC configuration
*/
export function validateVPCConfig(config) {
const errors = [];
// Validate CIDR block
if (!isValidCIDR(config.cidr)) {
errors.push(`Invalid VPC CIDR: ${config.cidr}`);
}
// Validate subnets
if (config.publicSubnets.length === 0) {
errors.push('At least one public subnet is required');
}
if (config.privateSubnets.length === 0) {
errors.push('At least one private subnet is required');
}
// Validate availability zones
if (config.availabilityZones.length < 2) {
errors.push('At least two availability zones are required for high availability');
}
// Validate subnet CIDRs
[...config.publicSubnets, ...config.privateSubnets].forEach((cidr) => {
if (!isValidCIDR(cidr)) {
errors.push(`Invalid subnet CIDR: ${cidr}`);
}
});
return {
valid: errors.length === 0,
errors,
};
}
/**
* Simple CIDR validation
*/
function isValidCIDR(cidr) {
const cidrRegex = /^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/;
return cidrRegex.test(cidr);
}
/**
* Generate default VPC configuration
*/
export function getDefaultVPCConfig(region) {
// Get availability zones for region (simplified - would query AWS in production)
const azSuffixes = ['a', 'b', 'c'];
const availabilityZones = azSuffixes.map((suffix) => `${region}${suffix}`);
return {
cidr: '10.0.0.0/16',
availabilityZones: availabilityZones.slice(0, 2), // Use 2 AZs
publicSubnets: [
'10.0.1.0/24',
'10.0.2.0/24',
],
privateSubnets: [
'10.0.10.0/24',
'10.0.11.0/24',
],
enableNat: true,
enableFlowLogs: false,
};
}
//# sourceMappingURL=vpc.js.map