c7n package

Subpackages

Submodules

c7n.actions module

Actions to take on resources

class c7n.actions.Action(data=None, manager=None, log_dir=None)[source]

Bases: object

executor_factory

alias of ThreadPoolExecutor

get_permissions()[source]
log = <logging.Logger object>
metrics = ()
name
permissions = ()
process(resources)[source]
schema = {u'type': u'object'}
validate()[source]
class c7n.actions.ActionRegistry(*args, **kw)[source]

Bases: c7n.registry.PluginRegistry

factory(data, manager)[source]
parse(data, manager)[source]
class c7n.actions.AutoTagUser(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.EventAction

Tag a resource with the user who created/modified it.

policies:
  - name: ec2-auto-tag-ownercontact
    resource: ec2
    description: |
      Triggered when a new EC2 Instance is launched. Checks to see if
      it's missing the OwnerContact tag. If missing it gets created
      with the value of the ID of whomever called the RunInstances API
    mode:
      type: cloudtrail
      role: arn:aws:iam::123456789000:role/custodian-auto-tagger
      events:
        - RunInstances
    filters:
     - tag:OwnerContact: absent
    actions:
     - type: auto-tag-user
       tag: OwnerContact

There’s a number of caveats to usage. Resources which don’t include tagging as part of their api may have some delay before automation kicks in to create a tag. Real world delay may be several minutes, with worst case into hours[0]. This creates a race condition between auto tagging and automation.

In practice this window is on the order of a fraction of a second, as we fetch the resource and evaluate the presence of the tag before attempting to tag it.

References
get_permissions()[source]
process(resources, event)[source]
schema = {u'properties': {u'user-type': {u'type': u'array', u'items': {u'type': u'string', u'enum': [u'IAMUser', u'AssumedRole', u'FederatedUser']}}, u'type': {u'enum': [u'auto-tag-user']}, u'tag': {u'type': u'string'}, u'update': {u'type': u'boolean'}, u'principal_id_tag': {u'type': u'string'}}, u'type': u'object', u'additionalProperties': False, u'required': [u'tag', u'type']}
validate()[source]
c7n.actions.BaseAction

alias of Action

class c7n.actions.EventAction(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.Action

Actions which receive lambda event if present

class c7n.actions.LambdaInvoke(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.EventAction

Invoke an arbitrary lambda

serialized invocation parameters

  • resources / collection of resources
  • policy / policy that is invoke the lambda
  • action / action that is invoking the lambda
  • event / cloud trail event if any
  • version / version of custodian invoking the lambda

We automatically batch into sets of 250 for invocation, We try to utilize async invocation by default, this imposes some greater size limits of 128kb which means we batch invoke.

Example:

- type: invoke-lambda
  function: my-function
get_permissions()[source]
permissions = (u'lambda:InvokeFunction',)
process(resources, event=None)[source]
schema = {u'properties': {u'type': {u'enum': [u'invoke-lambda']}, 'batch_size': {u'type': u'integer'}, 'function': {u'type': u'string'}, 'async': {u'type': u'boolean'}, 'qualifier': {u'type': u'string'}}, u'type': u'object', u'additionalProperties': False, u'required': (u'function',)}
class c7n.actions.ModifyVpcSecurityGroupsAction(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.Action

Common actions for modifying security groups on a resource

Can target either physical groups as a list of group ids or symbolic groups like ‘matched’ or ‘all’. ‘matched’ uses the annotations of the ‘security-group’ interface filter.

Note an interface always gets at least one security group, so we mandate the specification of an isolation/quarantine group that can be specified if there would otherwise be no groups.

type: modify-security-groups
add: [] remove: [] | matched isolation-group: sg-xyz
get_groups(resources, metadata_key=None)[source]

Parse policies to get lists of security groups to attach to each resource

For each input resource, parse the various add/remove/isolation- group policies for ‘modify-security-groups’ to find the resulting set of VPC security groups to attach to that resource.

The ‘metadata_key’ parameter can be used for two purposes at the moment; The first use is for resources’ APIs that return a list of security group IDs but use a different metadata key than ‘Groups’ or ‘SecurityGroups’.

The second use is for when there are richer objects in the ‘Groups’ or ‘SecurityGroups’ lists. The custodian actions need to act on lists of just security group IDs, so the metadata_key can be used to select IDs from the richer objects in the provided lists.

Returns a list of lists containing the resulting VPC security groups that should end up on each resource passed in.

Parameters:
  • resources – List of resources containing VPC Security Groups
  • metadata_key – Metadata key for security groups list
Returns:

List of lists of security groups per resource

schema = {u'properties': {u'type': {u'enum': [u'modify-security-groups']}, u'add': {u'oneOf': [{u'type': u'string', u'pattern': u'^sg-*'}, {u'type': u'array', u'items': {u'type': u'string', u'pattern': u'^sg-*'}}]}, u'isolation-group': {u'oneOf': [{u'type': u'string', u'pattern': u'^sg-*'}, {u'type': u'array', u'items': {u'type': u'string', u'pattern': u'^sg-*'}}]}, u'remove': {u'oneOf': [{u'type': u'array', u'items': {u'type': u'string', u'pattern': u'^sg-*'}}, {u'enum': [u'matched', u'all', {u'type': u'string', u'pattern': u'^sg-*'}]}]}}, u'type': u'object', u'anyOf': [{u'required': [u'isolation-group', u'remove', u'type']}, {u'required': [u'add', u'remove', u'type']}, {u'required': [u'add', u'type']}], u'additionalProperties': False}
class c7n.actions.Notify(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.EventAction

Flexible notifications require quite a bit of implementation support on pluggable transports, templates, address resolution, variable extraction, batch periods, etc.

For expedience and flexibility then, we instead send the data to an sqs queue, for processing. ie. actual communications is DIY atm.

Example:

policies:
  - name: ec2-bad-instance-kill
    resource: ec2
    filters:
     - Name: bad-instance
    actions:
     - terminate
     - type: notify
       to:
        - event-user
        - resource-creator
        - email@address
       # which template for the email should we use
       template: policy-template
       transport:
         type: sqs
         region: us-east-1
         queue: xyz
C7N_DATA_MESSAGE = u'maidmsg/1.0'
batch_size = 250
expand_variables(message)[source]

expand any variables in the action to_from/cc_from fields.

get_permissions()[source]
pack(message)[source]
process(resources, event=None)[source]
schema = {u'properties': {u'cc_from': {u'properties': {u'expr': {u'oneOf': [{u'type': u'integer'}, {u'type': u'string'}]}, u'url': {u'type': u'string'}, u'format': {u'enum': [u'csv', u'json', u'txt', u'csv2dict']}}, u'type': u'object', u'additionalProperties': u'False', u'required': [u'url']}, u'to': {u'type': u'array', u'items': {u'type': u'string'}}, u'from': {u'type': u'string'}, u'subject': {u'type': u'string'}, u'transport': {u'oneOf': [{u'properties': {u'type': {u'enum': [u'sqs']}, u'queue': {u'type': u'string'}}, u'type': u'object', u'required': [u'type', u'queue']}, {u'properties': {u'type': {u'enum': [u'sns']}, u'topic': {u'type': u'string'}}, u'type': u'object', u'required': [u'type', u'topic']}]}, u'to_from': {u'properties': {u'expr': {u'oneOf': [{u'type': u'integer'}, {u'type': u'string'}]}, u'url': {u'type': u'string'}, u'format': {u'enum': [u'csv', u'json', u'txt', u'csv2dict']}}, u'type': u'object', u'additionalProperties': u'False', u'required': [u'url']}, u'type': {u'enum': [u'notify']}, u'assume_role': {u'type': u'boolean'}, u'cc_manager': {u'type': u'boolean'}, u'cc': {u'type': u'array', u'items': {u'type': u'string'}}, u'template': {u'type': u'string'}}, u'type': u'object', u'anyOf': [{u'required': [u'type', u'transport', u'to']}, {u'required': [u'type', u'transport', u'to_from']}]}
send_data_message(message)[source]
send_sns(message)[source]
send_sqs(message)[source]
class c7n.actions.PutMetric(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.Action

Action to put metrics based on an expression into CloudWatch metrics

Example:

op and units are optional and will default to simple Counts.

permissions = set([u'cloudwatch:PutMetricData'])
process(resources)[source]
schema = {u'properties': {u'type': {u'enum': [u'put-metric']}, u'units': {u'enum': [u'Seconds', u'Microseconds', u'Milliseconds', u'Bytes', u'Kilobytes', u'Megabytes', u'Gigabytes', u'Terabytes', u'Bits', u'Kilobits', u'Megabits', u'Gigabits', u'Terabits', u'Bytes/Second', u'Kilobytes/Second', u'Megabytes/Second', u'Gigabytes/Second', u'Terabytes/Second', u'Bits/Second', u'Kilobits/Second', u'Megabits/Second', u'Gigabits/Second', u'Terabits/Second', u'Count/Second', u'Percent', u'Count', u'None']}, u'metric_name': {u'type': u'string'}, u'dimensions': {u'type': u'array', u'items': {u'type': u'object'}}, u'key': {u'type': u'string'}, u'namespace': {u'type': u'string'}, u'op': {u'enum': [u'average', u'distinct_count', u'sum', u'count']}}, u'type': u'object', u'required': [u'type', u'key', u'namespace', u'metric_name']}
class c7n.actions.RemovePolicyBase(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.Action

process_policy(policy, resource, matched_key)[source]
schema = {u'properties': {u'type': {u'enum': [u'remove-statements']}, 'statement_ids': {u'oneOf': [{u'enum': [u'matched']}, {u'type': u'array', u'items': {u'type': u'string'}}]}}, u'type': u'object', u'additionalProperties': False, u'required': [u'statement_ids', u'type']}
c7n.actions.add_auto_tag_user(registry, _)[source]
c7n.actions.average(numbers)[source]
c7n.actions.distinct_count(values)[source]

c7n.cache module

Provide basic caching services to avoid extraneous queries over multiple policies on the same resource type.

class c7n.cache.FileCacheManager(config)[source]

Bases: object

get(key)[source]
load()[source]
save(key, data)[source]
class c7n.cache.InMemoryCache[source]

Bases: object

get(key)[source]
load()[source]
save(key, data)[source]
class c7n.cache.NullCache(config)[source]

Bases: object

get(key)[source]
load()[source]
save(key, data)[source]
c7n.cache.factory(config)[source]

c7n.cli module

c7n.cli.main()[source]
c7n.cli.setproctitle(t)[source]
c7n.cli.setup_parser()[source]

c7n.commands module

c7n.commands.logs(options)[source]
c7n.commands.metrics_cmd(options)[source]
c7n.commands.policy_command(f)[source]
c7n.commands.report(options)[source]
c7n.commands.run(options)[source]
c7n.commands.schema_cmd(options)[source]

Print info about the resources, actions and filters available.

c7n.commands.schema_completer(prefix)[source]

For tab-completion via argcomplete, return completion options.

For the given prefix so far, return the possible options. Note that filtering via startswith happens after this list is returned.

c7n.commands.validate(options)[source]
c7n.commands.version_cmd(options)[source]

c7n.credentials module

Authentication utilities

class c7n.credentials.SessionFactory(region, profile=None, assume_role=None, external_id=None)[source]

Bases: object

c7n.credentials.assumed_session(role_arn, session_name, session=None, region=None, external_id=None)[source]

STS Role assume a boto3.Session

With automatic credential renewal.

Args:
role_arn: iam role arn to assume session_name: client session identifier session: an optional extant session, note session is captured in a function closure for renewing the sts assumed role.
Returns:a boto3 session using the sts assumed role credentials

Notes: We have to poke at botocore internals a few times

c7n.ctx module

class c7n.ctx.ExecutionContext(session_factory, policy, options)[source]

Bases: object

Policy Execution Context.

log_dir

c7n.cwe module

class c7n.cwe.CloudWatchEvents[source]

Bases: object

A mapping of events to resource types.

classmethod get(event_name)[source]
classmethod get_ids(event, mode)[source]
classmethod get_trail_ids(event, mode)[source]

extract resources ids from a cloud trail event.

classmethod match(event)[source]

Match a given cwe event as cloudtrail with an api call

That has its information filled out.

trail_events = {u'CreateDBInstance': {u'source': u'rds.amazonaws.com', u'ids': u'requestParameters.dBInstanceIdentifier'}, u'CreateBucket': {u'source': u's3.amazonaws.com', u'ids': u'requestParameters.bucketName'}, u'CreateVolume': {u'source': u'ec2.amazonaws.com', u'ids': u'responseElements.volumeId'}, u'CreateTable': {u'source': u'dynamodb.amazonaws.com"', u'ids': u'requestParameters.tableName'}, u'CreateCluster': {u'source': u'redshift.amazonaws.com', u'ids': u'requestParameters.clusterIdentifier'}, u'CreateLoadBalancer': {u'source': u'elasticloadbalancing.amazonaws.com', u'ids': u'requestParameters.loadBalancerName'}, u'ConsoleLogin': {u'source': u'signin.amazonaws.com', u'ids': u'userIdentity.arn'}, u'SetLoadBalancerPoliciesOfListener': {u'source': u'elasticloadbalancing.amazonaws.com', u'ids': u'requestParameters.loadBalancerName'}, u'RunInstances': {u'source': u'ec2.amazonaws.com', u'ids': u'responseElements.instancesSet.items[].instanceId'}, u'UpdateAutoScalingGroup': {u'source': u'autoscaling.amazonaws.com', u'ids': u'requestParameters.autoScalingGroupName'}, u'CreateElasticsearchDomain': {u'source': u'es.amazonaws.com', u'ids': u'requestParameters.domainName'}, u'CreateLoadBalancerPolicy': {u'source': u'elasticloadbalancing.amazonaws.com', u'ids': u'requestParameters.loadBalancerName'}, u'CreateAutoScalingGroup': {u'source': u'autoscaling.amazonaws.com', u'ids': u'requestParameters.autoScalingGroupName'}}

c7n.executor module

class c7n.executor.ExecutorRegistry(plugin_type)[source]

Bases: c7n.registry.PluginRegistry

class c7n.executor.MainThreadExecutor(*args, **kw)[source]

Bases: object

For running tests.

async == True -> catch exceptions and store them in the future. async == False -> let exceptions bubble up.

async = True
map(func, iterable)[source]
submit(func, *args, **kw)[source]
type = u'main'
class c7n.executor.MainThreadFuture(value, exception=None)[source]

Bases: object

add_done_callback(fn)[source]
cancel()[source]
cancelled()[source]
done()[source]
exception()[source]
result(timeout=None)[source]
c7n.executor.executor(name, **kw)[source]

c7n.handler module

Cloud-Custodian Lambda Entry Point

Mostly this serves to load up the policy and dispatch an event.

class c7n.handler.Config[source]

Bases: dict

classmethod empty(**kw)[source]
c7n.handler.dispatch_event(event, context)[source]

c7n.log module

Python Standard Logging integration with CloudWatch Logs

Double Buffered with background thread delivery.

We do an initial buffering on the log handler directly, to avoid some of the overhead of pushing to the queue (albeit dubious as std logging does default lock acquisition around handler emit). also uses a single thread for all outbound. Background thread uses a separate session.

class c7n.log.CloudWatchLogHandler(log_group='c7n.log', log_stream=None, session_factory=None)[source]

Bases: logging.Handler

Python Log Handler to Send to Cloud Watch Logs

http://goo.gl/eZGAEK

batch_interval = 40
batch_min_buffer = 10
batch_size = 20
close()[source]
emit(message)[source]

Send logs

flush()[source]

Ensure all logging output has been flushed.

flush_buffers(force=False)[source]
format_message(msg)[source]

format message.

start_transports()[source]

start thread transports.

class c7n.log.Error[source]

Bases: object

AlreadyAccepted = u'DataAlreadyAcceptedException'
InvalidToken = u'InvalidSequenceTokenException'
ResourceExists = u'ResourceAlreadyExistsException'
static code(e)[source]
class c7n.log.Transport(queue, batch_size, batch_interval, session_factory)[source]

Bases: object

create_stream(group, stream)[source]
loop()[source]
send()[source]
send_group(k, messages)[source]

c7n.logs_support module

Supporting utilities for various implementations of PolicyExecutionMode.get_logs()

c7n.logs_support.get_records(bucket, key, session_factory)[source]
c7n.logs_support.log_entries_from_group(session, group_name, start, end)[source]

Get logs for a specific log group

c7n.logs_support.log_entries_from_s3(session_factory, output, start, end)[source]
c7n.logs_support.log_entries_in_range(entries, start, end)[source]

filter out entries before start and after end

c7n.logs_support.normalized_log_entries(raw_entries)[source]

Mimic the format returned by LambdaManager.logs()

c7n.manager module

class c7n.manager.ResourceManager(ctx, data)[source]

Bases: object

action_registry = None
executor_factory

alias of ThreadPoolExecutor

filter_registry = None
filter_resources(resources, event=None)[source]
format_json(resources, fh)[source]
get_model()[source]

Returns the resource meta-model.

classmethod get_permissions()[source]
get_resource_manager(resource_type, data=None)[source]
get_resources(resource_ids)[source]

Retrieve a set of resources by id.

match_ids(ids)[source]

return ids that match this resource type’s id format.

resources()[source]
retry = None

c7n.mu module

Cloud Custodian Lambda Provisioning Support

docs/lambda.rst

class c7n.mu.AbstractLambdaFunction[source]

Bases: object

Abstract base class for lambda functions.

alias = None
dead_letter_config
description
environment
get_archive()[source]

Return the lambda distribution archive object.

get_config()[source]
get_events(session_factory)[source]

event sources that should be bound to this lambda.

handler
kms_key_arn
memory_size
name

Name for the lambda function

role
runtime
security_groups
subnets
tags
timeout
tracing_config
class c7n.mu.BucketLambdaNotification(data, session_factory, bucket)[source]

Bases: object

Subscribe a lambda to bucket notifications directly.

add(func)[source]
delta(src, tgt)[source]
remove(func)[source]
class c7n.mu.BucketSNSNotification(session_factory, bucket, topic=None)[source]

Bases: c7n.mu.SNSSubscription

Subscribe a lambda to bucket notifications via SNS.

get_topic(bucket)[source]
class c7n.mu.CloudWatchEventSource(data, session_factory, prefix=u'custodian-')[source]

Bases: object

Subscribe a lambda to cloud watch events.

Cloud watch events supports a number of different event sources, from periodic timers with cron syntax, to real time instance state notifications, cloud trail events, and realtime asg membership changes.

Event Pattern for Instance State

{
  "source": ["aws.ec2"],
  "detail-type": ["EC2 Instance State-change Notification"],
  "detail": { "state": ["pending"]}
}

Event Pattern for Cloud Trail API

{
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
     "eventSource": ["s3.amazonaws.com"],
     "eventName": ["CreateBucket", "DeleteBucket"]
  }
}
ASG_EVENT_MAPPING = {u'launch-success': u'EC2 Instance Launch Successful', u'terminate-success': u'EC2 Instance Terminate Successful', u'terminate-failure': u'EC2 Instance Terminate Unsuccessful', u'launch-failure': u'EC2 Instance Launch Unsuccessful'}
add(func)[source]
static delta(src, tgt)[source]

Given two cwe rules determine if the configuration is the same.

Name is already implied.

get(rule_name)[source]
pause(func)[source]
remove(func)[source]
render_event_pattern()[source]
resolve_cloudtrail_payload(payload)[source]
resume(func)[source]
update(func)[source]
class c7n.mu.CloudWatchLogSubscription(session_factory, log_groups, filter_pattern)[source]

Bases: object

Subscribe a lambda to a log group[s]

add(func)[source]
iam_delay = 1.5
remove(func)[source]
class c7n.mu.ConfigRule(data, session_factory)[source]

Bases: object

Use a lambda as a custom config rule.

add(func)[source]
static delta(rule, params)[source]
get(rule_name)[source]
get_rule_params(func)[source]
remove(func)[source]
class c7n.mu.LambdaFunction(func_data, archive)[source]

Bases: c7n.mu.AbstractLambdaFunction

dead_letter_config
description
environment
get_archive()[source]
get_events(session_factory)[source]
handler
kms_key_arn
memory_size
name
role
runtime
security_groups
subnets
tags
timeout
tracing_config
class c7n.mu.LambdaManager(session_factory, s3_asset_path=None)[source]

Bases: object

Provides CRUD operations around lambda functions

static delta_function(old_config, new_config)[source]
static diff_tags(old_tags, new_tags)[source]
get(func_name, qualifier=None)[source]
list_functions(prefix=None)[source]
logs(func, start, end)[source]
metrics(funcs, start, end, period=300)[source]
publish(func, alias=None, role=None, s3_uri=None)[source]
publish_alias(func_data, alias)[source]

Create or update an alias for the given function.

remove(func, alias=None)[source]
class c7n.mu.PolicyLambda(policy)[source]

Bases: c7n.mu.AbstractLambdaFunction

Wraps a custodian policy to turn it into a lambda function.

dead_letter_config
description
environment
get_archive()[source]
get_events(session_factory)[source]
handler = u'custodian_policy.run'
kms_key_arn
memory_size
name
role
runtime
security_groups
subnets
tags
timeout
tracing_config
class c7n.mu.PythonPackageArchive(*modules)[source]

Bases: object

Creates a zip file for python lambda functions.

Parameters:modules (tuple) – the Python modules to add to the archive

Amazon doesn’t give us straightforward docs here, only an example, from which we can infer that they simply unzip the file into a directory on sys.path. So what we do is locate all of the modules specified, and add all of the .py files we find for these modules to a zip file.

In addition to the modules specified during instantiation, you can add arbitrary additional files to the archive using add_file() and add_contents(). For example, since we only add *.py files for you, you’ll need to manually add files for any compiled extension modules that your Lambda requires.

add_contents(dest, contents)[source]

Add file contents to the archive under dest.

If dest is a path, it will be added compressed and world-readable (user-writeable). You may also pass a ZipInfo for custom behavior.

add_directory(path)[source]

Add *.py files under the directory path to the archive.

add_file(src, dest=None)[source]

Add the file at src to the archive.

If dest is None then it is added under just the original filename. So add_file('foo/bar.txt') ends up at bar.txt in the archive, while add_file('bar.txt', 'foo/bar.txt') ends up at foo/bar.txt.

add_modules(*modules)[source]

Add the named Python modules to the archive. For consistency’s sake we only add *.py files, not *.pyc. We also don’t add other files, including compiled modules. You’ll have to add such files manually using add_file().

add_py_file(src, dest=None)[source]

This is a special case of add_file() that helps for adding a py when a pyc may be present as well. So for example, if __file__ is foo.pyc and you do:

archive.add_py_file(__file__)

then this method will add foo.py instead if it exists, and raise IOError if it doesn’t.

close()[source]

Close the zip file.

Note underlying tempfile is removed when archive is garbage collected.

get_bytes()[source]

Return the entire zip file as a byte string.

get_checksum()[source]

Return the b64 encoded sha256 checksum of the archive.

get_filenames()[source]

Return a list of filenames in the archive.

get_reader()[source]

Return a read-only ZipFile.

path
remove()[source]

Dispose of the temp file for garbage collection.

size
class c7n.mu.SNSSubscription(session_factory, topic_arns)[source]

Bases: object

Subscribe a lambda to one or more SNS topics.

add(func)[source]
iam_delay = 1.5
remove(func)[source]
c7n.mu.checksum(fh, hasher, blocksize=65536)[source]
c7n.mu.custodian_archive()[source]

Create a lambda code archive for running custodian.

c7n.mu.resource_exists(op, NotFound=u'ResourceNotFoundException', *args, **kw)[source]
c7n.mu.zinfo(fname)[source]

Amazon lambda exec environment setup can break itself if zip files aren’t constructed a particular way.

ie. It respects file perm attributes from the zip including those that prevent lambda from working. Namely lambda extracts code as one user, and executes code as a different user. Without permissions for the executing user to read the file the lambda function is broken.

Python’s default zipfile.writestr does a 0600 perm which we modify here as a workaround.

c7n.output module

Outputs metrics, logs, structured records across a variety of sources.

See docs/usage/outputs.rst

class c7n.output.CloudWatchLogOutput(ctx)[source]

Bases: c7n.output.LogOutput

get_handler()[source]
log_format = u'%(asctime)s - %(levelname)s - %(name)s - %(message)s'
class c7n.output.DirectoryOutput(ctx)[source]

Bases: c7n.output.FSOutput

permissions = ()
use_s3()[source]
class c7n.output.FSOutput(ctx)[source]

Bases: c7n.output.LogOutput

compress()[source]
get_handler()[source]
static join(*parts)[source]
static select(path)[source]
use_s3()[source]
class c7n.output.LogOutput(ctx)[source]

Bases: object

get_handler()[source]
join_log()[source]
leave_log()[source]
log_format = u'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
class c7n.output.MetricsOutput(ctx, namespace=u'CloudMaid')[source]

Bases: object

Send metrics data to cloudwatch

flush()[source]
permissions = (u'cloudWatch:PutMetricData',)
put_metric(key, value, unit, buffer=False, **dimensions)[source]
static retry(func, *args, **kw)
static select(metrics_enabled)[source]
class c7n.output.NullMetricsOutput(ctx, namespace=u'CloudMaid')[source]

Bases: c7n.output.MetricsOutput

format_metric(m)[source]
permissions = ()
class c7n.output.S3Output(ctx)[source]

Bases: c7n.output.FSOutput

Usage:

with S3Output(session_factory, 's3://bucket/prefix'):
    log.info('xyz')  # -> log messages sent to custodian-run.log.gz
static join(*parts)[source]
permissions = (u'S3:PutObject',)
upload()[source]
use_s3()[source]
c7n.output.s3_join(*parts)

c7n.policy module

class c7n.policy.ASGInstanceState(policy)[source]

Bases: c7n.policy.LambdaMode

a lambda policy that executes on an asg’s ec2 instance state changes.

class c7n.policy.CloudTrailMode(policy)[source]

Bases: c7n.policy.LambdaMode

A lambda policy using cloudwatch events rules on cloudtrail api logs.

validate()[source]
class c7n.policy.ConfigRuleMode(policy)[source]

Bases: c7n.policy.LambdaMode

a lambda policy that executes as a config service rule. http://docs.aws.amazon.com/config/latest/APIReference/API_PutConfigRule.html

cfg_event = None
resolve_resources(event)[source]
run(event, lambda_context)[source]
class c7n.policy.EC2InstanceState(policy)[source]

Bases: c7n.policy.LambdaMode

a lambda policy that executes on ec2 instance state changes.

class c7n.policy.LambdaMode(policy)[source]

Bases: c7n.policy.PolicyExecutionMode

A policy that runs/executes in lambda.

POLICY_METRICS = (u'ResourceCount',)
expand_variables(variables)[source]

expand variables in the mode role fields.

get_logs(start, end)[source]
get_metrics(start, end, period)[source]
provision()[source]
resolve_resources(event)[source]
run(event, lambda_context)[source]

Run policy in push mode against given event.

Lambda automatically generates cloud watch logs, and metrics for us, albeit with some deficienies, metrics no longer count against valid resources matches, but against execution. Fortunately we already have replacements.

TODO: better customization around execution context outputs TODO: support centralized lambda exec across accounts.

class c7n.policy.PeriodicMode(policy)[source]

Bases: c7n.policy.LambdaMode, c7n.policy.PullMode

A policy that runs in pull mode within lambda.

POLICY_METRICS = (u'ResourceCount', u'ResourceTime', u'ActionTime')
run(event, lambda_context)[source]
class c7n.policy.Policy(data, options, session_factory=None)[source]

Bases: object

EXEC_MODE_MAP = {u'cloudtrail': <class 'c7n.policy.CloudTrailMode'>, u'periodic': <class 'c7n.policy.PeriodicMode'>, u'ec2-instance-state': <class 'c7n.policy.EC2InstanceState'>, u'asg-instance-state': <class 'c7n.policy.ASGInstanceState'>, u'pull': <class 'c7n.policy.PullMode'>, u'config-rule': <class 'c7n.policy.ConfigRuleMode'>}
get_execution_mode()[source]
get_logs(start, end)[source]
get_metrics(start, end, period)[source]
get_permissions()[source]

get permissions needed by this policy

get_resource_manager()[source]
is_lambda
log = <logging.Logger object>
max_resources
name
poll()[source]

Query resources and apply policy.

provision()[source]

Provision policy as a lambda function.

push(event, lambda_ctx)[source]
region
resource_type
run()

Run policy in default mode

tags
validate()[source]
class c7n.policy.PolicyCollection(policies, options)[source]

Bases: object

expand_regions(regions)[source]

Return a set of policies targetted to the given regions.

Supports symbolic regions like ‘all’. This will automatically filter out policies if their being targetted to a region that does not support the service. Global services will target a single region (us-east-1 if only all specified, else first region in the list).

Note for region partitions (govcloud and china) an explicit region from the partition must be passed in.

filter(policy_name=None, resource_type=None)[source]
classmethod from_data(data, options)[source]
log = <logging.Logger object>
resource_types

resource types used by the collection.

classmethod session_factory()[source]
class c7n.policy.PolicyExecutionMode(policy)[source]

Bases: object

Policy execution semantics

POLICY_METRICS = (u'ResourceCount', u'ResourceTime', u'ActionTime')
get_logs(start, end)[source]

Retrieve logs for the policy

get_metrics(start, end, period)[source]

Retrieve any associated metrics for the policy.

provision()[source]

Provision any resources needed for the policy.

run(event=None, lambda_context=None)[source]

Run the actual policy.

validate()[source]

Validate configuration settings for execution mode.

class c7n.policy.PullMode(policy)[source]

Bases: c7n.policy.PolicyExecutionMode

Pull mode execution of a policy.

Queries resources from cloud provider for filtering and actions.

get_logs(start, end)[source]
run(*args, **kw)[source]
c7n.policy.get_service_region_map(regions, resource_types)[source]
c7n.policy.load(options, path, format=u'yaml', validate=True, vars=None)[source]

c7n.query module

Query capability built on skew metamodel

tags_spec -> s3, elb, rds

class c7n.query.ChildDescribeSource(manager)[source]

Bases: c7n.query.DescribeSource

type = u'describe-child'
class c7n.query.ChildResourceManager(data, options)[source]

Bases: c7n.query.QueryResourceManager

source_type
class c7n.query.ChildResourceQuery(session_factory, manager)[source]

Bases: c7n.query.ResourceQuery

A resource query for resources that must be queried with parent information.

Several resource types can only be queried in the context of their parents identifiers. ie. efs mount targets (parent efs), route53 resource records (parent hosted zone), ecs services (ecs cluster).

filter(resource_manager, **params)[source]

Query a set of resources.

class c7n.query.ConfigSource(manager)[source]

Bases: object

augment(resources)[source]
get_permissions()[source]
get_resources(ids, cache=True)[source]
load_resource(item)[source]
resources(query=None)[source]
static retry(func, *args, **kw)
type = u'config'
class c7n.query.DescribeSource(manager)[source]

Bases: object

augment(resources)[source]
get_permissions()[source]
get_resources(ids, cache=True)[source]
resources(query)[source]
type = u'describe'
class c7n.query.QueryMeta[source]

Bases: type

class c7n.query.QueryResourceManager(data, options)[source]

Bases: c7n.manager.ResourceManager

account_id

Return the current account ID.

This should now be passed in using the –account-id flag, but for a period of time we will support the old behavior of inferring this from IAM.

action_registry = <c7n.actions.ActionRegistry object>
augment(resources)[source]

subclasses may want to augment resources with additional information.

ie. we want tags by default (rds, elb), and policy, location, acl for s3 buckets.

chunk_size = 20
filter_registry = <c7n.filters.core.FilterRegistry object>
generate_arn

Generates generic arn if ID is not already arn format.

get_arns(resources)[source]
classmethod get_model()[source]
get_permissions()[source]
get_resources(ids, cache=True)[source]
get_source(source_type)[source]
classmethod match_ids(ids)[source]

return ids that match this resource type’s id format.

max_workers = 3
permissions = ()
resource_type = u''
resources(query=None)[source]
retry = None
source_type
class c7n.query.ResourceQuery(session_factory)[source]

Bases: object

filter(resource_manager, **params)[source]

Query a set of resources.

get(resource_manager, identities)[source]

Get resources by identities

static resolve(resource_type)[source]
c7n.query.pager(p, retry)[source]

c7n.registry module

class c7n.registry.PluginRegistry(plugin_type)[source]

Bases: object

A plugin registry

Custodian is intended to be innately pluggable both internally and externally, for resource types and their filters and actions.

This plugin registry abstraction provides the core mechanism for that. Its a simple string to class map, with python package entry_point loading for external plugins.

As an example of defining an external plugin using a python package

setup(
    name="custodian_cmdb",
    description="Custodian filters for interacting with internal CMDB"
    version='1.0',
    packages=find_packages(),
    entry_points={
         'console_scripts': [
              'custodian.ec2.filters = custodian_cmdb:filter_ec2']},
    )

For loading the plugins we can simply invoke method:load_plugins like so:

PluginRegistry('ec2.filters').load_plugins()
EVENTS = (0, 1)
EVENT_FINAL = 1
EVENT_REGISTER = 0
get(name)[source]
items()[source]
keys()[source]
load_plugins()[source]

Load external plugins.

Custodian is intended to interact with internal and external systems that are not suitable for embedding into the custodian code base.

notify(event, key=None)[source]
register(name, klass=None)[source]
subscribe(event, func)[source]
unregister(name)[source]

c7n.resolver module

class c7n.resolver.URIResolver(session_factory, cache)[source]

Bases: object

get_s3_uri(uri)[source]
resolve(uri)[source]
class c7n.resolver.ValuesFrom(data, manager)[source]

Bases: object

Retrieve values from a url.

Supports json, csv and line delimited text files and expressions to retrieve a subset of values.

Expression syntax - on json, a jmespath expr is evaluated - on csv, an integer column or jmespath expr can be specified - on csv2dict, a jmespath expr (the csv is parsed into a dictionary where the keys are the headers and the values are the remaining columns)

Text files are expected to be line delimited values.

Examples:

value_from:
   url: s3://bucket/xyz/foo.json
   expr: [].AppId

values_from:
   url: http://foobar.com/mydata
   format: json
   expr: Region."us-east-1"[].ImageId

value_from:
   url: s3://bucket/abc/foo.csv
   format: csv2dict
   expr: key[1]

 # inferred from extension
 format: [json, csv, csv2dict, txt]
get_contents()[source]
get_values()[source]
schema = {u'properties': {u'expr': {u'oneOf': [{u'type': u'integer'}, {u'type': u'string'}]}, u'url': {u'type': u'string'}, u'format': {u'enum': [u'csv', u'json', u'txt', u'csv2dict']}}, u'type': u'object', u'additionalProperties': u'False', u'required': [u'url']}
supported_formats = (u'json', u'txt', u'csv', u'csv2dict')

c7n.schema module

Jsonschema validation of cloud custodian config.

We start with a walkthrough of the various class registries of resource types and assemble and generate the schema.

We do some specialization to reduce overall schema size via reference usage, although in some cases we prefer copies, due to issues with inheritance via reference ( allowedProperties and enum extension).

All filters and actions are annotated with schema typically using the utils.type_schema function.

c7n.schema.generate(resource_types=())[source]
c7n.schema.json_dump(resource=None)[source]
c7n.schema.process_resource(type_name, resource_type, resource_defs)[source]
c7n.schema.resource_vocabulary()[source]
c7n.schema.specific_error(error)[source]

Try to find the best error for humans to resolve

The jsonschema.exceptions.best_match error is based purely on a mix of a strong match (ie. not anyOf, oneOf) and schema depth, this often yields odd results that are semantically confusing, instead we can use a bit of structural knowledge of schema to provide better results.

c7n.schema.summary(vocabulary)[source]
c7n.schema.validate(data, schema=None)[source]

c7n.sqsexec module

concurrent.futures implementation over sqs

Scatter/Gather or Map/Reduce style over two sqs queues.

class c7n.sqsexec.MessageIterator(client, queue_url, limit=0, timeout=10)[source]

Bases: object

ack(m)[source]
msg_attributes = [u'sequence_id', u'op', u'ser']
next()
class c7n.sqsexec.SQSExecutor(session_factory, map_queue, reduce_queue)[source]

Bases: concurrent.futures._base.Executor

gather()[source]

Fetch results from separate queue

submit(func, *args, **kwargs)[source]
class c7n.sqsexec.SQSFuture(sequence_id)[source]

Bases: concurrent.futures._base.Future

marker = <object object>
class c7n.sqsexec.SQSWorker(session_factory, map_queue, reduce_queue, limit=0)[source]

Bases: object

process_message(m)[source]
run()[source]
stop()[source]
stopped = False
c7n.sqsexec.named(o)[source]
c7n.sqsexec.resolve(o)[source]

c7n.tags module

Generic EC2 Resource Tag / Filters and actions

These work for the whole family of resources associated to ec2 (subnets, vpc, security-groups, volumes, instances, snapshots).

class c7n.tags.NormalizeTag(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.Action

Transform the value of a tag.

Set the tag value to uppercase, title, lowercase, or strip text from a tag key.

policies:
  - name: ec2-service-transform-lower
    resource: ec2
    comment: |
      ec2-service-tag-value-to-lower
    query:
      - instance-state-name: running
    filters:
      - "tag:testing8882": present
    actions:
      - type: normalize-tag
        key: lower_key
        action: lower

  - name: ec2-service-strip
    resource: ec2
    comment: |
      ec2-service-tag-strip-blah
    query:
      - instance-state-name: running
    filters:
      - "tag:testing8882": present
    actions:
      - type: normalize-tag
        key: strip_key
        action: strip
        value: blah
create_set(instances)[source]
create_tag(client, ids, key, value)[source]
filter_resources(resources)[source]
permissions = (u'ec2:CreateTags',)
process(resources)[source]
process_transform(tag_value, resource_set)[source]

Transform tag value

  • Collect value from tag
  • Transform Tag value
  • Assign new value for key
schema = {u'properties': {u'type': {u'enum': [u'normalize-tag']}, 'value': {u'type': u'string'}, 'action': {u'type': u'string', u'items': {u'enum': [u'upper', u'lower', u'titlestrip', u'replace']}}, 'key': {u'type': u'string'}}, u'type': u'object', u'additionalProperties': False, u'required': [u'type']}
class c7n.tags.RemoveTag(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.Action

Remove tags from ec2 resources.

batch_size = 100
concurrency = 2
permissions = (u'ec2:DeleteTags',)
process(resources)[source]
process_resource_set(vol_set, tag_keys)[source]
schema = {u'properties': {u'type': {u'enum': [u'untag', u'unmark', u'remove-tag']}, 'tags': {u'type': u'array', u'items': {u'type': u'string'}}}, u'type': u'object', u'additionalProperties': False, u'required': [u'type']}
class c7n.tags.RenameTag(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.Action

Create a new tag with identical value & remove old tag

create_set(instances)[source]
create_tag(client, ids, key, value)[source]
delete_tag(client, ids, key, value)[source]
filter_resources(resources)[source]
permissions = (u'ec2:CreateTags', u'ec2:DeleteTags')
process(resources)[source]
process_rename(tag_value, resource_set)[source]

Move source tag value to destination tag value

  • Collect value from old tag
  • Delete old tag
  • Create new tag & assign stored value
schema = {u'properties': {u'type': {u'enum': [u'rename-tag']}, 'new_key': {u'type': u'string'}, 'old_key': {u'type': u'string'}}, u'type': u'object', u'additionalProperties': False, u'required': [u'type']}
tag_count_max = 50
class c7n.tags.Tag(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.Action

Tag an ec2 resource.

batch_size = 25
concurrency = 2
permissions = (u'ec2:CreateTags',)
process(resources)[source]
process_resource_set(resource_set, tags)[source]
schema = {u'properties': {'value': {u'type': u'string'}, u'type': {u'enum': [u'tag', u'mark']}, 'tags': {u'type': u'object'}, 'tag': {u'type': u'string'}, 'key': {u'type': u'string'}}, u'type': u'object', u'additionalProperties': False, u'required': [u'type']}
validate()[source]
class c7n.tags.TagActionFilter(data, manager=None)[source]

Bases: c7n.filters.core.Filter

Filter resources for tag specified future action

Filters resources by a ‘custodian_status’ tag which specifies a future date for an action.

The filter parses the tag values looking for an ‘op@date’ string. The date is parsed and compared to do today’s date, the filter succeeds if today’s date is gte to the target date.

The optional ‘skew’ parameter provides for incrementing today’s date a number of days into the future. An example use case might be sending a final notice email a few days before terminating an instance, or snapshotting a volume prior to deletion.

- policies:
  - name: ec2-stop-marked
    resource: ec2
    filters:
      - type: marked-for-op
        # The default tag used is custodian_status
        # but that is configurable
        tag: custodian_status
        op: stop
        # Another optional tag is skew
    actions:
      - stop
current_date = None
schema = {u'properties': {u'type': {u'enum': [u'marked-for-op']}, 'op': {u'type': u'string'}, 'skew': {u'type': u'number', u'minimum': 0}, 'tag': {u'type': u'string'}}, u'type': u'object', u'additionalProperties': False, u'required': [u'type']}
validate()[source]
class c7n.tags.TagCountFilter(data, manager=None)[source]

Bases: c7n.filters.core.Filter

Simplify tag counting..

ie. these two blocks are equivalent

- filters:
    - type: value
      key: "[length(Tags)][0]"
      op: gte
      value: 8

- filters:
    - type: tag-count
      value: 8
schema = {u'properties': {u'type': {u'enum': [u'tag-count']}, 'op': {u'enum': [u'ni', u'contains', u'glob', u'eq', u'gt', u'lt', u'not-in', u'lte', u'equal', u'ge', u'ne', u'less-than', u'intersect', u'regex', u'le', u'greater-than', u'in', u'gte', u'not-equal']}, 'count': {u'type': u'integer', u'minimum': 0}}, u'type': u'object', u'additionalProperties': False, u'required': [u'type']}
class c7n.tags.TagDelayedAction(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.Action

Tag resources for future action.

- policies:
  - name: ec2-stop-marked
    resource: ec2
    filters:
      - type: marked-for-op
        # The default tag used is custodian_status
        # but that is configurable
        tag: custodian_status
        op: stop
        # Another optional tag is skew
    actions:
      - stop
batch_size = 200
concurrency = 2
default_template = u'Resource does not meet policy: {op}@{action_date}'
permissions = (u'ec2:CreateTags',)
process(resources)[source]
process_resource_set(resource_set, tags)[source]
schema = {u'properties': {u'type': {u'enum': [u'mark-for-op']}, 'op': {u'type': u'string'}, 'msg': {u'type': u'string'}, 'days': {u'type': u'integer', u'minimum': 0, u'exclusiveMinimum': True}, 'tag': {u'type': u'string'}}, u'type': u'object', u'additionalProperties': False, u'required': [u'type']}
validate()[source]
class c7n.tags.TagTrim(data=None, manager=None, log_dir=None)[source]

Bases: c7n.actions.Action

Automatically remove tags from an ec2 resource.

EC2 Resources have a limit of 10 tags, in order to make additional tags space on a set of resources, this action can be used to remove enough tags to make the desired amount of space while preserving a given set of tags.

- policies:
   - name: ec2-tag-trim
     comment: |
       Any instances with 8 or more tags get tags removed until
       they match the target tag count, in this case 7 so we
       that we free up a tag slot for another usage.
     resource: ec2
     filters:
         # Filter down to resources which already have 8 tags
         # as we need space for 3 more, this also ensures that
         # metrics reporting is correct for the policy.
         type: value
         key: "[length(Tags)][0]"
         op: ge
         value: 8
     actions:
       - type: tag-trim
         space: 3
         preserve:
          - OwnerContact
          - ASV
          - CMDBEnvironment
          - downtime
          - custodian_status
max_tag_count = 50
permissions = (u'ec2:DeleteTags',)
process(resources)[source]
process_resource(i)[source]
process_tag_removal(resource, tags)[source]
schema = {u'properties': {u'type': {u'enum': [u'tag-trim']}, 'space': {u'type': u'integer'}, 'preserve': {u'type': u'array', u'items': {u'type': u'string'}}}, u'type': u'object', u'additionalProperties': False, u'required': [u'type']}
class c7n.tags.UniversalTag(data=None, manager=None, log_dir=None)[source]

Bases: c7n.tags.Tag

Applies one or more tags to the specified resources.

batch_size = 20
permissions = (u'resourcegroupstaggingapi:TagResources',)
process(resources)[source]
process_resource_set(resource_set, tags)[source]
class c7n.tags.UniversalTagDelayedAction(data=None, manager=None, log_dir=None)[source]

Bases: c7n.tags.TagDelayedAction

Tag resources for future action.

Example:
policies:
- name: ec2-mark-stop
  resource: ec2
  filters:
    - type: image-age
      op: ge
      days: 90
  actions:
    - type: mark-for-op
      tag: custodian_cleanup
      op: terminate
      days: 4
batch_size = 20
concurrency = 2
permissions = (u'resourcegroupstaggingapi:TagResources',)
process(resources)[source]
process_resource_set(resource_set, tags)[source]
class c7n.tags.UniversalUntag(data=None, manager=None, log_dir=None)[source]

Bases: c7n.tags.RemoveTag

Removes the specified tags from the specified resources.

batch_size = 20
permissions = (u'resourcegroupstaggingapi:UntagResources',)
process_resource_set(resource_set, tag_keys)[source]
c7n.tags.register_ec2_tags(filters, actions)[source]
c7n.tags.register_universal_tags(filters, actions)[source]
c7n.tags.universal_augment(self, resources)[source]

c7n.utils module

class c7n.utils.Bag[source]

Bases: dict

class c7n.utils.DateTimeEncoder(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, encoding='utf-8', default=None)[source]

Bases: json.encoder.JSONEncoder

default(obj)[source]
class c7n.utils.IPv4Network(address, strict=True)[source]

Bases: ipaddress.IPv4Network

supernet_of(other)[source]
exception c7n.utils.VarsSubstitutionError[source]

Bases: exceptions.Exception

c7n.utils.annotation(i, k)[source]
c7n.utils.backoff_delays(start, stop, factor=2.0, jitter=False)[source]

Geometric backoff sequence w/ jitter

c7n.utils.camelResource(obj)[source]

Some sources from apis return lowerCased where as describe calls

always return TitleCase, this function turns the former to the later

c7n.utils.chunks(iterable, size=50)[source]

Break an iterable into lists of size

c7n.utils.dumps(data, fh=None, indent=0)[source]
c7n.utils.format_event(evt)[source]
c7n.utils.format_string_values(obj, *args, **kwargs)[source]

Format all string values in an object. Return the updated object

c7n.utils.generate_arn(service, resource, partition=u'aws', region=None, account_id=None, resource_type=None, separator=u'/')[source]

Generate an Amazon Resource Name. See http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html.

c7n.utils.get_account_alias_from_sts(session)[source]
c7n.utils.get_account_id_from_sts(session)[source]
c7n.utils.get_profile_session(options)[source]
c7n.utils.get_retry(codes=(), max_attempts=8, min_delay=1, log_retries=False)[source]

Decorator for retry boto3 api call on transient errors.

https://www.awsarchitectureblog.com/2015/03/backoff.html https://en.wikipedia.org/wiki/Exponential_backoff

Parameters:
  • codes – A sequence of retryable error codes.
  • max_attempts – The max number of retries, by default the delay time is proportional to the max number of attempts.
  • log_retries – Whether we should log retries, if specified specifies the level at which the retry should be logged.
  • _max_delay – The maximum delay for any retry interval note this parameter is only exposed for unit testing, as its derived from the number of attempts.

Returns a function for invoking aws client calls that retries on retryable error codes.

c7n.utils.group_by(resources, key)[source]

Return a mapping of key value to resources with the corresponding value.

Key may be specified as dotted form for nested dictionary lookup

c7n.utils.load_file(path, format=None, vars=None)[source]
c7n.utils.loads(body)[source]
c7n.utils.local_session(factory)[source]

Cache a session thread local for up to 45m

c7n.utils.parse_cidr(value)[source]

Process cidr ranges.

c7n.utils.parse_s3(s3_path)[source]
c7n.utils.query_instances(session, client=None, **query)[source]

Return a list of ec2 instances for the query.

c7n.utils.reformat_schema(model)[source]

Reformat schema to be in a more displayable format.

c7n.utils.reset_session_cache()[source]
c7n.utils.set_annotation(i, k, v)[source]
>>> x = {}
>>> set_annotation(x, 'marker', 'a')
>>> annotation(x, 'marker')
['a']
c7n.utils.snapshot_identifier(prefix, db_identifier)[source]

Return an identifier for a snapshot of a database or cluster.

c7n.utils.type_schema(type_name, inherits=None, rinherit=None, aliases=None, required=None, **props)[source]

jsonschema generation helper

params:
  • type_name: name of the type
  • inherits: list of document fragments that are required via anyOf[$ref]
  • rinherit: use another schema as a base for this, basically work around
    inherits issues with additionalProperties and type enums.
  • aliases: additional names this type maybe called
  • required: list of required properties, by default ‘type’ is required
  • props: additional key value properties
c7n.utils.worker(f)[source]

Generic wrapper to log uncaught exceptions in a function.

When we cross concurrent.futures executor boundaries we lose our traceback information, and when doing bulk operations we may tolerate transient failures on a partial subset. However we still want to have full accounting of the error in the logs, in a format that our error collection (cwl subscription) can still pickup.

c7n.utils.yaml_load(value)[source]

c7n.version module

Module contents