816 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			816 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "execute_cmd.h"
 | 
						|
#include "rds_vpc.h"
 | 
						|
 | 
						|
RDS::RDS(char* cluster)
 | 
						|
{
 | 
						|
    cluster_name_intern = cluster;
 | 
						|
    subnets_intern = NULL;
 | 
						|
    N_intern = 0;
 | 
						|
}
 | 
						|
 | 
						|
const char* RDS::get_instance_name(json_t* instance)
 | 
						|
{
 | 
						|
    json_t* instance_name = json_object_get(instance, "DBInstanceIdentifier");
 | 
						|
    return json_string_value(instance_name);
 | 
						|
}
 | 
						|
 | 
						|
json_t* RDS::get_cluster_descr(char* json)
 | 
						|
{
 | 
						|
    json_t* root;
 | 
						|
    json_error_t error;
 | 
						|
 | 
						|
    root = json_loads(json, 0, &error);
 | 
						|
    if (!root)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    json_t* clusters = json_object_get(root, "DBClusters");
 | 
						|
    // cluster_intern =
 | 
						|
    return json_array_get(clusters, 0);
 | 
						|
}
 | 
						|
 | 
						|
json_t* RDS::get_subnets_group_descr(char* json)
 | 
						|
{
 | 
						|
    json_t* root;
 | 
						|
    json_error_t error;
 | 
						|
 | 
						|
    root = json_loads(json, 0, &error);
 | 
						|
    if (!root)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    json_t* subnets = json_object_get(root, "DBSubnetGroups");
 | 
						|
    return json_array_get(subnets, 0);
 | 
						|
}
 | 
						|
 | 
						|
json_t* RDS::get_cluster_nodes()
 | 
						|
{
 | 
						|
    return get_cluster_nodes(cluster_intern);
 | 
						|
}
 | 
						|
 | 
						|
json_t* RDS::get_cluster_nodes(json_t* cluster)
 | 
						|
{
 | 
						|
    json_t* members = json_object_get(cluster, "DBClusterMembers");
 | 
						|
    size_t members_N = json_array_size(members);
 | 
						|
    json_t* member;
 | 
						|
    json_t* node_names = json_array();
 | 
						|
 | 
						|
    for (size_t i = 0; i < members_N; i++)
 | 
						|
    {
 | 
						|
        member = json_array_get(members, i);
 | 
						|
        json_array_append(node_names, json_string(get_instance_name(member)));
 | 
						|
    }
 | 
						|
    return node_names;
 | 
						|
}
 | 
						|
 | 
						|
json_t* RDS::get_subnets()
 | 
						|
{
 | 
						|
    char cmd[1024];
 | 
						|
    char* result;
 | 
						|
    sprintf(cmd, "aws rds describe-db-subnet-groups --db-subnet-group-name %s", subnets_group_name_intern);
 | 
						|
    if (execute_cmd(cmd, &result) != 0)
 | 
						|
    {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    json_t* subnets_group = get_subnets_group_descr(result);
 | 
						|
 | 
						|
    json_t* members = json_object_get(subnets_group, "Subnets");
 | 
						|
    vpc_id_intern = json_string_value(json_object_get(subnets_group, "VpcId"));
 | 
						|
    size_t members_N = json_array_size(members);
 | 
						|
    json_t* member;
 | 
						|
    json_t* subnets_names = json_array();
 | 
						|
 | 
						|
    for (size_t i = 0; i < members_N; i++)
 | 
						|
    {
 | 
						|
        member = json_array_get(members, i);
 | 
						|
        json_array_append(subnets_names, json_object_get(member, "SubnetIdentifier"));
 | 
						|
    }
 | 
						|
    subnets_intern = subnets_names;
 | 
						|
    return subnets_names;
 | 
						|
}
 | 
						|
 | 
						|
const char* RDS::get_subnetgroup_name()
 | 
						|
{
 | 
						|
    if (cluster_intern != NULL)
 | 
						|
    {
 | 
						|
        subnets_group_name_intern = json_string_value(json_object_get(cluster_intern, "DBSubnetGroup"));
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        subnets_group_name_intern = cluster_name_intern;
 | 
						|
    }
 | 
						|
 | 
						|
    return subnets_group_name_intern;
 | 
						|
}
 | 
						|
 | 
						|
json_t* RDS::get_cluster()
 | 
						|
{
 | 
						|
    char cmd[1024];
 | 
						|
    char* result;
 | 
						|
    sprintf(cmd, "aws rds describe-db-clusters --db-cluster-identifier=%s", cluster_name_intern);
 | 
						|
    execute_cmd(cmd, &result);
 | 
						|
    return get_cluster_descr(result);
 | 
						|
}
 | 
						|
 | 
						|
int RDS::destroy_nodes(json_t* node_names)
 | 
						|
{
 | 
						|
    size_t N = json_array_size(node_names);
 | 
						|
 | 
						|
    char cmd[1024];
 | 
						|
    char* res;
 | 
						|
    json_t* node;
 | 
						|
    int err = 0;
 | 
						|
    for (size_t i = 0; i < N; i++)
 | 
						|
    {
 | 
						|
        node = json_array_get(node_names, i);
 | 
						|
        sprintf(cmd,
 | 
						|
                "aws rds delete-db-instance --skip-final-snapshot --db-instance-identifier=%s",
 | 
						|
                json_string_value(node));
 | 
						|
        printf("%s\n", cmd);
 | 
						|
        if (execute_cmd(cmd, &res) != 0)
 | 
						|
        {
 | 
						|
            err = -1;
 | 
						|
            fprintf(stderr, "error: can not delete node %s\n", json_string_value(node));
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return err;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::destroy_subnets()
 | 
						|
{
 | 
						|
    size_t N = json_array_size(subnets_intern);
 | 
						|
 | 
						|
    char cmd[1024];
 | 
						|
    char* res;
 | 
						|
    json_t* subnet;
 | 
						|
    int err = 0;
 | 
						|
    for (size_t i = 0; i < N; i++)
 | 
						|
    {
 | 
						|
        subnet = json_array_get(subnets_intern, i);
 | 
						|
        sprintf(cmd, "aws ec2 delete-subnet --subnet-id=%s", json_string_value(subnet));
 | 
						|
        printf("%s\n", cmd);
 | 
						|
        execute_cmd(cmd, &res);
 | 
						|
        if (execute_cmd(cmd, &res) != 0)
 | 
						|
        {
 | 
						|
            err = -1;
 | 
						|
            fprintf(stderr, "error: can not delete subnet %s\n", json_string_value(subnet));
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return err;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::destroy_route_tables()
 | 
						|
{
 | 
						|
    json_t* root;
 | 
						|
    char cmd[1024];
 | 
						|
    char* json;
 | 
						|
 | 
						|
    sprintf(cmd, "aws ec2 describe-vpcs --vpc-ids=%s", vpc_id_intern);
 | 
						|
    if (execute_cmd(cmd, &json))
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not get internet gateways description\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    root = get_cluster_descr(json);
 | 
						|
    if (!root)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not get cluster description\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    json_t* route_tables = json_object_get(root, "RouteTables");
 | 
						|
 | 
						|
    size_t i;
 | 
						|
    json_t* route_table;
 | 
						|
    const char* rt_id;
 | 
						|
    const char* vpc_id;
 | 
						|
    json_array_foreach(route_tables, i, route_table)
 | 
						|
    {
 | 
						|
        rt_id = json_string_value(json_object_get(route_table, "RouteTableId"));
 | 
						|
        vpc_id = json_string_value(json_object_get(route_table, "VpcId"));
 | 
						|
        if (strcmp(vpc_id_intern, vpc_id) == 0)
 | 
						|
        {
 | 
						|
            sprintf(cmd, "aws ec2 delete-route-table --route-table-id %s", rt_id);
 | 
						|
            system(cmd);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::detach_and_destroy_gw()
 | 
						|
{
 | 
						|
    json_t* root;
 | 
						|
    json_error_t error;
 | 
						|
    char cmd[1024];
 | 
						|
    char* json;
 | 
						|
 | 
						|
    sprintf(cmd,
 | 
						|
            "aws ec2 describe-internet-gateways --filters Name=attachment.vpc-id,Values=%s",
 | 
						|
            vpc_id_intern);
 | 
						|
    if (execute_cmd(cmd, &json))
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not get internet gateways description\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    root = json_loads(json, 0, &error);
 | 
						|
    if (!root)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    json_t* gws = json_object_get(root, "InternetGateways");
 | 
						|
    if (gws == NULL)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not parse internet gateways description\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    size_t i;
 | 
						|
    json_t* gw;
 | 
						|
    const char* gw_id;
 | 
						|
    json_array_foreach(gws, i, gw)
 | 
						|
    {
 | 
						|
        gw_id = json_string_value(json_object_get(gw, "InternetGatewayId"));
 | 
						|
        sprintf(cmd,
 | 
						|
                "aws ec2 detach-internet-gateway --internet-gateway-id=%s --vpc-id=%s",
 | 
						|
                gw_id,
 | 
						|
                vpc_id_intern);
 | 
						|
        printf("%s\n", cmd);
 | 
						|
        if (system(cmd) != 0)
 | 
						|
        {
 | 
						|
            fprintf(stderr, "error: can not detach gateway %s from vpc %s\n", gw_id, vpc_id_intern);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        sprintf(cmd, "aws ec2 delete-internet-gateway --internet-gateway-id=%s", gw_id);
 | 
						|
        printf("%s\n", cmd);
 | 
						|
        if (system(cmd) != 0)
 | 
						|
        {
 | 
						|
            fprintf(stderr, "error: can not delete gateway %s\n", gw_id);
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::create_vpc(const char** vpc_id)
 | 
						|
{
 | 
						|
    json_t* root;
 | 
						|
    json_error_t error;
 | 
						|
    char* result;
 | 
						|
    char cmd[1024];
 | 
						|
 | 
						|
    if (execute_cmd((char*) "aws ec2 create-vpc --cidr-block 172.30.0.0/16", &result) != 0)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not create VPC\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    root = json_loads(result, 0, &error);
 | 
						|
    if (!root)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    *vpc_id = json_string_value(json_object_get(json_object_get(root, "Vpc"), "VpcId"));
 | 
						|
    if (*vpc_id == NULL)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not parse output of create-vpc command\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    vpc_id_intern = * vpc_id;
 | 
						|
 | 
						|
    sprintf(cmd, "aws ec2 modify-vpc-attribute --enable-dns-support --vpc-id %s", *vpc_id);
 | 
						|
    if (system(cmd) != 0)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not enable dns support\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    sprintf(cmd, "aws ec2 modify-vpc-attribute --enable-dns-hostnames --vpc-id %s", *vpc_id);
 | 
						|
    if (system(cmd) != 0)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not enable dns hostnames\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::create_subnet(const char* az, const char* cidr, const char** subnet_id)
 | 
						|
{
 | 
						|
    json_t* root;
 | 
						|
    json_error_t error;
 | 
						|
    char* result;
 | 
						|
    char cmd[1024];
 | 
						|
 | 
						|
    *subnet_id = NULL;
 | 
						|
    sprintf(cmd,
 | 
						|
            "aws ec2 create-subnet --cidr-block %s --availability-zone %s --vpc-id %s",
 | 
						|
            cidr,
 | 
						|
            az,
 | 
						|
            vpc_id_intern);
 | 
						|
    puts(cmd);
 | 
						|
    if (execute_cmd(cmd, &result) != 0)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not create subnet\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    root = json_loads(result, 0, &error);
 | 
						|
    if (!root)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    *subnet_id = json_string_value(json_object_get(json_object_get(root, "Subnet"), "SubnetId"));
 | 
						|
    if (*subnet_id == NULL)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not parse output of create-vpc command\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (subnets_intern == NULL)
 | 
						|
    {
 | 
						|
        subnets_intern = json_array();
 | 
						|
    }
 | 
						|
    json_array_append(subnets_intern, json_string(*subnet_id));
 | 
						|
 | 
						|
    sprintf(cmd, "aws ec2 modify-subnet-attribute --map-public-ip-on-launch --subnet-id %s", *subnet_id);
 | 
						|
    if (system(cmd) != 0)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not modify subnet attribute\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::create_subnet_group()
 | 
						|
{
 | 
						|
    char cmd[1024];
 | 
						|
    size_t i;
 | 
						|
    json_t* subnet;
 | 
						|
 | 
						|
    sprintf(cmd,
 | 
						|
            "aws rds create-db-subnet-group --db-subnet-group-name %s --db-subnet-group-description maxscale --subnet-ids",
 | 
						|
            cluster_name_intern);
 | 
						|
    json_array_foreach(subnets_intern, i, subnet)
 | 
						|
    {
 | 
						|
        strcat(cmd, " ");
 | 
						|
        strcat(cmd, json_string_value(subnet));
 | 
						|
    }
 | 
						|
    subnets_group_name_intern = cluster_name_intern;
 | 
						|
    if (system(cmd) != 0)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not create subnets group\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::create_gw(const char** gw_id)
 | 
						|
{
 | 
						|
    char* result;
 | 
						|
    char cmd[1024];
 | 
						|
    json_error_t error;
 | 
						|
 | 
						|
    *gw_id = NULL;
 | 
						|
    gw_intern = NULL;
 | 
						|
    if (execute_cmd((char*) "aws ec2 create-internet-gateway", &result) != 0)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not create internet gateway\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    json_t* root = json_loads(result, 0, &error);
 | 
						|
    if (!root)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    *gw_id =
 | 
						|
        json_string_value(json_object_get(json_object_get(root, "InternetGateway"), "InternetGatewayId"));
 | 
						|
    if (*gw_id == NULL)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not parse output of create-internet-gateway command\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    gw_intern = *gw_id;
 | 
						|
 | 
						|
    sprintf(cmd,
 | 
						|
            "aws ec2 attach-internet-gateway --internet-gateway-id %s --vpc-id %s",
 | 
						|
            *gw_id,
 | 
						|
            vpc_id_intern);
 | 
						|
    if (system(cmd) != 0)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not attach gateway to VPC\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::configure_route_table(const char** rt)
 | 
						|
{
 | 
						|
    char* result;
 | 
						|
    char cmd[1024];
 | 
						|
    json_error_t error;
 | 
						|
 | 
						|
    *rt = NULL;
 | 
						|
    if (execute_cmd((char*) "aws ec2 describe-route-tables", &result) != 0)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not get route tables description\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    json_t* root = json_loads(result, 0, &error);
 | 
						|
    if (!root)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    json_t* route_tables = json_object_get(root, "RouteTables");
 | 
						|
    if (route_tables == NULL)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not parse route tables description\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    size_t i;
 | 
						|
    json_t* rtb;
 | 
						|
    const char* rt_vpc;
 | 
						|
 | 
						|
    json_array_foreach(route_tables, i, rtb)
 | 
						|
    {
 | 
						|
        rt_vpc = json_string_value(json_object_get(rtb, "VpcId"));
 | 
						|
        if (strcmp(vpc_id_intern, rt_vpc) == 0)
 | 
						|
        {
 | 
						|
            // add route to route table which belongs to give VPC
 | 
						|
            *rt = json_string_value(json_object_get(rtb, "RouteTableId"));
 | 
						|
            sprintf(cmd,
 | 
						|
                    "aws ec2 create-route --route-table-id %s --gateway-id %s --destination-cidr-block 0.0.0.0/0",
 | 
						|
                    *rt,
 | 
						|
                    gw_intern);
 | 
						|
            if (system(cmd) != 0)
 | 
						|
            {
 | 
						|
                fprintf(stderr, "error: can not create route\n");
 | 
						|
                return -1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (*rt == NULL)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not find route table\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::create_cluster()
 | 
						|
{
 | 
						|
    char cmd[1024];
 | 
						|
    char* result;
 | 
						|
    json_error_t error;
 | 
						|
    size_t i;
 | 
						|
 | 
						|
    sprintf(cmd,
 | 
						|
            "aws rds create-db-cluster --database-name=test --engine=aurora --master-username=skysql --master-user-password=skysqlrds --db-cluster-identifier=%s --db-subnet-group-name=%s",
 | 
						|
            cluster_name_intern,
 | 
						|
            cluster_name_intern);
 | 
						|
 | 
						|
    execute_cmd(cmd, &result);
 | 
						|
    json_t* root = json_loads(result, 0, &error);
 | 
						|
    if (!root)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    json_t* cluster = json_object_get(root, "DBCluster");
 | 
						|
    cluster_intern = cluster;
 | 
						|
    json_t* security_groups = json_object_get(cluster, "VpcSecurityGroups");
 | 
						|
    json_t* sg;
 | 
						|
    const char* sg_id;
 | 
						|
 | 
						|
    json_array_foreach(security_groups, i, sg)
 | 
						|
    {
 | 
						|
        sg_id = json_string_value(json_object_get(sg, "VpcSecurityGroupId"));
 | 
						|
        printf("Security group %s\n", sg_id);
 | 
						|
        sprintf(cmd,
 | 
						|
                "aws ec2 authorize-security-group-ingress --group-id %s --protocol tcp --port 3306 --cidr 0.0.0.0/0",
 | 
						|
                sg_id);
 | 
						|
        system(cmd);
 | 
						|
    }
 | 
						|
    sg_intern = sg_id;
 | 
						|
 | 
						|
    for (size_t i = 0; i < N_intern; i++)
 | 
						|
    {
 | 
						|
        sprintf(cmd,
 | 
						|
                "aws rds create-db-instance --db-cluster-identifier=%s --engine=aurora --db-instance-class=db.t2.medium --publicly-accessible --db-instance-identifier=node%03lu",
 | 
						|
                cluster_name_intern,
 | 
						|
                i);
 | 
						|
        printf("%s\n", cmd);
 | 
						|
        system(cmd);
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::get_writer(const char** writer_name)
 | 
						|
{
 | 
						|
    char* json;
 | 
						|
    char cmd[1024];
 | 
						|
    sprintf(cmd, "aws rds describe-db-clusters --db-cluster-identifier=%s", cluster_name_intern);
 | 
						|
    execute_cmd(cmd, &json);
 | 
						|
    json_t* cluster = get_cluster_descr(json);
 | 
						|
    json_t* nodes = json_object_get(cluster, "DBClusterMembers");
 | 
						|
 | 
						|
    // char * s = json_dumps(nodes, JSON_INDENT(4));
 | 
						|
    // puts(s);
 | 
						|
 | 
						|
    bool writer;
 | 
						|
    json_t* node;
 | 
						|
    size_t i = 0;
 | 
						|
 | 
						|
    do
 | 
						|
    {
 | 
						|
        node = json_array_get(nodes, i);
 | 
						|
        writer = json_is_true(json_object_get(node, "IsClusterWriter"));
 | 
						|
        i++;
 | 
						|
    }
 | 
						|
    while (!writer);
 | 
						|
    * writer_name = json_string_value(json_object_get(node, "DBInstanceIdentifier"));
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::destroy_vpc()
 | 
						|
{
 | 
						|
    char cmd[1024];
 | 
						|
    sprintf(cmd, "aws ec2 delete-vpc --vpc-id=%s", vpc_id_intern);
 | 
						|
    return system(cmd);
 | 
						|
}
 | 
						|
 | 
						|
int RDS::destroy_cluster()
 | 
						|
{
 | 
						|
    char cmd[1024];
 | 
						|
    char* result;
 | 
						|
    sprintf(cmd,
 | 
						|
            "aws rds delete-db-cluster --db-cluster-identifier=%s --skip-final-snapshot",
 | 
						|
            cluster_name_intern);
 | 
						|
    return execute_cmd(cmd, &result);
 | 
						|
}
 | 
						|
 | 
						|
int RDS::destroy_subnets_group()
 | 
						|
{
 | 
						|
    char cmd[1024];
 | 
						|
    char* result;
 | 
						|
    sprintf(cmd, "aws rds delete-db-subnet-group --db-subnet-group-name %s", get_subnetgroup_name());
 | 
						|
    puts(cmd);
 | 
						|
    return execute_cmd(cmd, &result);
 | 
						|
}
 | 
						|
 | 
						|
int RDS::create_rds_db(int N)
 | 
						|
{
 | 
						|
    const char* vpc;
 | 
						|
    const char* subnet1;
 | 
						|
    const char* subnet2;
 | 
						|
    const char* gw;
 | 
						|
    const char* rt;
 | 
						|
 | 
						|
    N_intern = N;
 | 
						|
 | 
						|
    printf("Create VPC\n");
 | 
						|
    if (create_vpc(&vpc) != 0)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "error: can not create VPC\n");
 | 
						|
        destroy_vpc();
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    printf("vpc id: %s\n", vpc);
 | 
						|
 | 
						|
    printf("Create subnets\n");
 | 
						|
    create_subnet("eu-west-1b", "172.30.0.0/24", &subnet1);
 | 
						|
    create_subnet("eu-west-1a", "172.30.1.0/24", &subnet2);
 | 
						|
 | 
						|
    printf("Create subnets group\n");
 | 
						|
    if (create_subnet_group() != 0)
 | 
						|
    {
 | 
						|
        destroy_subnets();
 | 
						|
        destroy_subnets_group();
 | 
						|
        destroy_vpc();
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    printf("Create internet gateway\n");
 | 
						|
    if (create_gw(&gw) != 0)
 | 
						|
    {
 | 
						|
        detach_and_destroy_gw();
 | 
						|
        destroy_subnets();
 | 
						|
        destroy_subnets_group();
 | 
						|
        destroy_vpc();
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    printf("Gateway: %s\n", gw);
 | 
						|
 | 
						|
    printf("Configure route table\n");
 | 
						|
    if (configure_route_table(&rt) != 0)
 | 
						|
    {
 | 
						|
        detach_and_destroy_gw();
 | 
						|
        destroy_subnets();
 | 
						|
        destroy_subnets_group();
 | 
						|
        destroy_vpc();
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    printf("Route table: %s\n", rt);
 | 
						|
 | 
						|
    printf("Create RDS cluster\n");
 | 
						|
    if (create_cluster() != 0)
 | 
						|
    {
 | 
						|
        destroy_nodes(get_cluster_nodes());
 | 
						|
        destroy_cluster();
 | 
						|
        detach_and_destroy_gw();
 | 
						|
        destroy_subnets();
 | 
						|
        destroy_subnets_group();
 | 
						|
        destroy_vpc();
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::delete_rds_cluster()
 | 
						|
{
 | 
						|
    char* result;
 | 
						|
    char cmd[1024];
 | 
						|
    json_t* current_cluster;
 | 
						|
 | 
						|
    printf("Get cluster\n");
 | 
						|
    cluster_intern = get_cluster();
 | 
						|
    printf("Get cluster NODES\n");
 | 
						|
    json_t* nodes = get_cluster_nodes();
 | 
						|
 | 
						|
    printf("Get subnets group: %s\n", get_subnetgroup_name());
 | 
						|
 | 
						|
    printf("Get subnets\n");
 | 
						|
    get_subnets();
 | 
						|
 | 
						|
    printf("Get VPC: %s\n", vpc_id_intern);
 | 
						|
 | 
						|
    size_t alive_nodes = json_array_size(nodes);
 | 
						|
 | 
						|
    printf("Destroy nodes\n");
 | 
						|
    destroy_nodes(nodes);
 | 
						|
 | 
						|
    do
 | 
						|
    {
 | 
						|
        printf("Waiting for nodes to be deleted, now %lu nodes are still alive\n", alive_nodes);
 | 
						|
        sleep(5);
 | 
						|
        current_cluster = get_cluster();
 | 
						|
        nodes = get_cluster_nodes(current_cluster);
 | 
						|
        alive_nodes = json_array_size(nodes);
 | 
						|
    }
 | 
						|
    while (alive_nodes > 0);
 | 
						|
 | 
						|
    printf("Destroy cluster\n");
 | 
						|
    destroy_cluster();
 | 
						|
 | 
						|
    do
 | 
						|
    {
 | 
						|
        printf("Waiting for cluster to be deleted\n");
 | 
						|
        sleep(5);
 | 
						|
        sprintf(cmd, "aws rds describe-db-clusters --db-cluster-identifier=%s", cluster_name_intern);
 | 
						|
        execute_cmd(cmd, &result);
 | 
						|
    }
 | 
						|
    while (get_cluster_descr(result) != NULL);
 | 
						|
 | 
						|
    printf("Destroy subnets\n");
 | 
						|
    destroy_subnets();
 | 
						|
 | 
						|
    printf("Destroy subnet group\n");
 | 
						|
    destroy_subnets_group();
 | 
						|
 | 
						|
    printf("Get and destroy Internet Gateways\n");
 | 
						|
    detach_and_destroy_gw();
 | 
						|
 | 
						|
    printf("Destroy vpc\n");
 | 
						|
    return destroy_vpc();
 | 
						|
}
 | 
						|
 | 
						|
int RDS::wait_for_nodes(size_t N)
 | 
						|
{
 | 
						|
    char* result;
 | 
						|
    size_t active_nodes = 0;
 | 
						|
    size_t i = 0;
 | 
						|
    json_t* node;
 | 
						|
    char cmd[1024];
 | 
						|
    json_t* nodes;
 | 
						|
    json_t* instances;
 | 
						|
    json_t* instance;
 | 
						|
    json_error_t error;
 | 
						|
 | 
						|
    do
 | 
						|
    {
 | 
						|
        printf("Waiting for nodes to be active, now %lu are active\n", active_nodes);
 | 
						|
        sleep(5);
 | 
						|
        cluster_intern = get_cluster();
 | 
						|
        nodes = get_cluster_nodes();
 | 
						|
 | 
						|
        active_nodes = 0;
 | 
						|
        json_array_foreach(nodes, i, node)
 | 
						|
        {
 | 
						|
            sprintf(cmd,
 | 
						|
                    "aws rds describe-db-instances --db-instance-identifier=%s",
 | 
						|
                    json_string_value(node));
 | 
						|
            execute_cmd(cmd, &result);
 | 
						|
            instances = json_loads(result, 0, &error);
 | 
						|
            if (!instances)
 | 
						|
            {
 | 
						|
                fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
 | 
						|
                return -1;
 | 
						|
            }
 | 
						|
            instance = json_array_get(json_object_get(instances, "DBInstances"), 0);
 | 
						|
            // puts(json_dumps(instance, JSON_INDENT(4)));
 | 
						|
            if (strcmp(json_string_value(json_object_get(instance, "DBInstanceStatus")), "available") == 0)
 | 
						|
            {
 | 
						|
                active_nodes++;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    while (active_nodes != N);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RDS::do_failover()
 | 
						|
{
 | 
						|
    char* result;
 | 
						|
    const char* writer;
 | 
						|
    const char* new_writer;
 | 
						|
    char cmd[1024];
 | 
						|
    if (get_writer(&writer) != 0)
 | 
						|
    {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    sprintf(cmd, "aws rds failover-db-cluster --db-cluster-identifier=%s", cluster_name_intern);
 | 
						|
    if (execute_cmd(cmd, &result) != 0)
 | 
						|
    {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    do
 | 
						|
    {
 | 
						|
        if (get_writer(&new_writer) != 0)
 | 
						|
        {
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        printf("writer: %s\n", new_writer);
 | 
						|
        sleep(5);
 | 
						|
    }
 | 
						|
    while (strcmp(writer, new_writer) == 0);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
json_t* RDS::get_endpoints()
 | 
						|
{
 | 
						|
    char cmd[1024];
 | 
						|
    char* result;
 | 
						|
 | 
						|
    json_t* root;
 | 
						|
    json_error_t error;
 | 
						|
 | 
						|
    json_t* node;
 | 
						|
    json_t* node_json;
 | 
						|
    json_t* endpoint;
 | 
						|
 | 
						|
    json_t* endpoints;
 | 
						|
 | 
						|
    endpoints = json_array();
 | 
						|
 | 
						|
    cluster_intern = get_cluster();
 | 
						|
    json_t* nodes = get_cluster_nodes();
 | 
						|
    // puts(json_dumps(nodes, JSON_INDENT(4)));
 | 
						|
 | 
						|
    size_t i;
 | 
						|
    json_array_foreach(nodes, i, node)
 | 
						|
    {
 | 
						|
        sprintf(cmd, "aws rds describe-db-instances --db-instance-identifier=%s", json_string_value(node));
 | 
						|
        if (execute_cmd(cmd, &result) != 0)
 | 
						|
        {
 | 
						|
            fprintf(stderr, "error: executing aws rds describe-db-instances\n");
 | 
						|
            return NULL;
 | 
						|
        }
 | 
						|
        root = json_loads(result, 0, &error);
 | 
						|
        if (!root)
 | 
						|
        {
 | 
						|
            fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
 | 
						|
            return NULL;
 | 
						|
        }
 | 
						|
        node_json = json_array_get(json_object_get(root, "DBInstances"), 0);
 | 
						|
        endpoint = json_object_get(node_json, "Endpoint");
 | 
						|
        json_array_append(endpoints, endpoint);
 | 
						|
    }
 | 
						|
    return endpoints;
 | 
						|
}
 |