Unverified Commit 8e9b91d6 authored by Russell Cohen's avatar Russell Cohen Committed by GitHub
Browse files

Add support for AWS-config and related improvements (#570)

* add AwsConfig example

* Error if tier 1 service fails to generate

* Generate `values` for named enum variants
parent bef52781
Loading
Loading
Loading
Loading
+15 −7
Original line number Diff line number Diff line
@@ -68,7 +68,6 @@ val tier1Services = setOf(
    "rdsdata",
    "rds",
    "route53",
    "runtime",
    "s3",
    "sagemakera2iruntime",
    "sagemakeredge",
@@ -82,6 +81,7 @@ val tier1Services = setOf(
    "sts",
    "cloudwatch",
    "ecr",
    "config",
    "eks"
)

@@ -111,7 +111,7 @@ val generateOnly: Set<String>? = null
 */
fun discoverServices(allServices: Boolean): List<AwsService> {
    val models = project.file("aws-models")
    return fileTree(models).mapNotNull { file ->
    val services = fileTree(models).mapNotNull { file ->
        val model = Model.assembler().addImport(file.absolutePath).assemble().result.get()
        val services: List<ServiceShape> = model.shapes(ServiceShape::class.java).sorted().toList()
        if (services.size > 1) {
@@ -136,12 +136,20 @@ fun discoverServices(allServices: Boolean): List<AwsService> {
            }
            AwsService(service = service.id.toString(), module = sdkId, modelFile = file, extraFiles = extras)
        }
    }.filterNot { disableServices.contains(it.module) }
        .filter {
    }.filterNot {
        disableServices.contains(it.module)
    }.filter {
        allServices || (generateOnly != null && generateOnly.contains(it.module)) || (generateOnly == null && tier1Services.contains(
            it.module
        ))
    }
    if (generateOnly == null) {
        val modules = services.map { it.module }.toSet()
        tier1Services.forEach { service ->
            check(modules.contains(service)) { "Service $service was in list of tier 1 services but not generated!" }
        }
    }
    return services
}

fun generateSmithyBuild(tests: List<AwsService>): String {
+14 −0
Original line number Diff line number Diff line
[package]
name = "config-code-examples"
version = "0.1.0"
authors = ["Russell Cohen <rcoh@amazon.com>", "Doug Schwartz <dougsch@amazon.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
config = { package = "aws-sdk-config", path = "../../build/aws-sdk/config" }
aws-types = { path = "../../build/aws-sdk/aws-types" }
tokio = { version = "1", features = ["full"] }
structopt = { version = "0.3", default-features = false }
tracing-subscriber = "0.2.18"
+80 −0
Original line number Diff line number Diff line
use aws_types::region;
use aws_types::region::ProvideRegion;
use config::model::ResourceType;
use config::{Client, Config, Error, Region};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
struct Opt {
    /// The default AWS Region.
    #[structopt(short, long)]
    default_region: Option<String>,

    /// The resource id.
    #[structopt(long)]
    resource_id: String,

    /// The resource type, eg. "AWS::EC2::SecurityGroup"
    #[structopt(long)]
    resource_type: String,

    /// Whether to display additional information.
    #[structopt(short, long)]
    verbose: bool,
}

/// Lists the configuration history for a resource
///
/// NOTE: AWS Config must be enabled to discover resources
/// # Arguments
///
/// * `[-d DEFAULT-REGION]` - The Region in which the client is created.
///   If not supplied, uses the value of the **AWS_REGION** environment variable.
///   If the environment variable is not set, defaults to **us-west-2**.
/// * `[-v]` - Whether to display information.
#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt::init();
    let Opt {
        default_region,
        resource_id,
        resource_type,
        verbose,
    } = Opt::from_args();

    let region = region::ChainProvider::first_try(default_region.map(Region::new))
        .or_default_provider()
        .or_else(Region::new("us-west-2"));

    println!();

    if verbose {
        println!("Config client version: {}", config::PKG_VERSION);
        println!("Region:               {:?}", region.region());
        println!();
    }

    let conf = Config::builder().region(region).build();
    // parse resource type from user input
    let parsed = ResourceType::from(resource_type.as_str());
    if matches!(parsed, ResourceType::Unknown(_)) {
        panic!(
            "unknown resource type: `{}`. Valid resource types: {:#?}",
            &resource_type,
            ResourceType::values()
        )
    }
    let client = Client::from_conf(conf);
    let rsp = client
        .get_resource_config_history()
        .resource_id(&resource_id)
        .resource_type(parsed)
        .send()
        .await?;
    println!("configuration history for {}:", resource_id);
    for item in rsp.configuration_items.unwrap_or_default() {
        println!("item: {:?}", item);
    }

    Ok(())
}
+7 −0
Original line number Diff line number Diff line
@@ -159,6 +159,13 @@ class EnumGenerator(
                    write("$enumName::$UnknownVariant(s) => s.as_ref()")
                }
            }

            writer.rustBlock("pub fn $Values() -> &'static [&'static str]") {
                withBlock("&[", "]") {
                    val memberList = sortedMembers.joinToString(", ") { it.value.doubleQuote() }
                    write(memberList)
                }
            }
        }
    }