Git Product home page Git Product logo

senza's Introduction

Senza

Build Status Code Coverage PyPI Downloads Latest PyPI version License

THIS PROJECT IS NOT ACTIVELY MAINTAINED ANYMORE!

Senza is a command line tool that enables you to generate and execute AWS CloudFormation templates in a sane, simple way. With Senza, you can write YAML documents and reuse common application stack solutions such as load balancing, auto-scaling, IAM role management, and other configurations. Senza also provides base CloudFormation templates for web applications, background applications, PostgreSQL, Redis clusters, and Amazon ElastiCache stack types.

What Senza Solves

AWS CloudFormation is great for managing immutable stacks on AWS. However, writing CloudFormation templates in JSON format is not human-friendly, which hinders developer productivity. Also, many parts of a CloudFormation template are reusable among applications of the same kind and CloudFormation does not provide a way to reuse templates.

Senza addresses these problems by supporting CloudFormation templates as YAML input and adding its own 'components' on top. Components are predefined, easily configurable CloudFormation snippets that generate all the boilerplate JSON that CloudFormation requires.

Installation

$ sudo pip3 install --upgrade stups-senza

Command Line Usage

You can easily bootstrap Senza definitions to get started quickly:

$ senza init my-definition.yaml # bootstrap a new app
$ senza create ./my-definition.yaml 1 1.0

Create CloudFormation stacks from Senza definitions with the create command:

$ senza create myapp.yaml 1 0.1-SNAPSHOT

How to disable the automatic CloudFormation rollback-on-failure to do 'post-mortem' debugging (e.g. on an EC2 instance):

$ senza create --disable-rollback myerroneous-stack.yaml 1 0.1-SNAPSHOT

To pass parameters from a .yaml file:

$ senza create --parameter-file parameters.yaml myapp.yaml 1 0.1-SNAPSHOT

To list stacks, use the list command:

$ senza list myapp.yaml         # list only active stacks for myapp
$ senza list myapp.yaml --all   # list stacks for myapp (also deleted ones)
$ senza list                    # list all active stacks
$ senza list --all              # list all stacks (including deleted ones)
$ senza list "suite-.*" 1       # list stacks starting with "suite" and with version "1"
$ senza list ".*" 42            # list all stacks  with version "42"
$ senza list mystack ".*test"  # list all stacks for "mystack" with version ending in "test"

If you want more detailed information about your stacks, Senza provides additional commands:

$ senza resources myapp.yaml 1 # list all CF resources
$ senza events myapp.yaml 1    # list all CF events
$ senza instances myapp.yaml 1 # list EC2 instances and IPs
$ senza console myapp.yaml 1   # get EC2 console output for all stack instances
$ senza console 172.31.1.2     # get EC2 console output for single instance

Most commands take so-called STACK_REF arguments. You can either use an existing Senza definition YAML file (as shown above) or use the stack's name and version. You can also use regular expressions to match multiple applications and versions:

$ senza inst                    # all instances, no STACK_REF argument given
$ senza inst mystack            # list instances for all versions of "mystack"
$ senza inst mystack 1          # only list instances for "mystack" version "1"
$ senza inst "suite-.*" 1       # list instances starting with "suite" and with version "1"
$ senza inst ".*" 42            # list all instances  with version "42"
$ senza inst mystack ".*test"  # list all instances for "mystack" with version ending in "test"

Tip

All commands and subcommands can be abbreviated, i.e. the following lines are equivalent:

$ senza list
$ senza l

Routing Traffic

Traffic can be routed via Route53 DNS to your new stack:

$ senza traffic myapp.yaml      # show traffic distribution
$ senza traffic myapp.yaml 2 50 # give version 2 50% of traffic

Warning

Some clients use connection pools that - by default - reuse connections as long as there are requests to be processed. In such cases, senza traffic won't result in any redirection of the traffic, unfortunately. To force such clients to switch traffic from one stack to the other, you might want to manually disable the load balancer (ELB) of the old stack — for example, by changing the ELB listener port. This switches traffic entirely. Switching traffic slowly (via weighted DNS records) is only possible for NEW connections.

We recommend monitoring clients' behavior when traffic switching, and — if necessary — asking them to reconfigure their connection pools.

Deleting Old Stacks

To delete stacks that you're no longer using:

$ senza delete myapp.yaml 1
$ senza del mystack          # shortcut: delete the only version of "mystack"

Bash Completion

Bash's programmable completion feature permits typing a partial command, then pressing the [Tab] key to autocomplete the command sequence. If multiple completions are possible, then [Tab] lists them all.

To activate bash completion for the Senza CLI, just run:

$ eval "$(_SENZA_COMPLETE=source senza)"

Put the eval line into your .bashrc:

$ echo 'eval "$(_SENZA_COMPLETE=source senza)"' >> ~/.bashrc

Controlling Command Output

The Senza CLI supports three different output formats:

text
Default ANSI-colored output for human users.
json
JSON output of tables for scripting.
tsv
Print tables as tab-separated values (TSV).

JSON is best for handling the output programmatically via various languages or with jq (a command-line JSON processor). The text format is easy for humans to read, and "tsv" format works well with traditional Unix text processing tools like sed, grep, and awk:

$ senza list --output json | jq .
$ senza instances my-stack --output tsv | awk -F\\t '{ print $6 }'

Senza Definition

A minimal Senza definition without any Senza components would look like:

Description: "A minimal Cloud Formation stack creating a SQS queue"
SenzaInfo:
  StackName: example
Resources:
  MyQueue:
    Type: AWS::SQS::Queue

Tip: Use senza init to quickly bootstrap a new Senza definition YAML for most common use cases (e.g. a web application).

The SenzaInfo Key

The SenzaInfo key configures global Senza behavior and must always be present in the definition YAML. Available properties for the SenzaInfo section:

StackName
The stack name (required).
OperatorTopicId
Optional SNS topic name or ARN for CloudFormation notifications. As an example: You can use this to send notifications about deployments to a mailing list.
Parameters
Custom Senza definition parameters. Use to dynamically substitute variables in the CloudFormation template.
# basic information for generating and executing this definition
SenzaInfo:
  StackName: kio
  OperatorTopicId: kio-operators
  Parameters:
      - ImageVersion:
          Description: "Docker image version of Kio."

# a list of Senza components to apply to the definition
SenzaComponents:
  - Configuration:
      Type: Senza::StupsAutoConfiguration # auto-detect network setup
  # will create a launch configuration and auto scaling group with min/max=1
  - AppServer:
      Type: Senza::TaupageAutoScalingGroup
      InstanceType: t2.micro
      SecurityGroups: [app-kio] # can be either name or id ("sg-..")
      ElasticLoadBalancer: AppLoadBalancer
      TaupageConfig:
        runtime: Docker
        source: stups/kio:{{Arguments.ImageVersion}}
        ports:
          8080: 8080
        environment:
          PGSSLMODE: verify-full
          DB_SUBNAME: "//kio.example.eu-west-1.rds.amazonaws.com:5432/kio?ssl=true"
          DB_USER: kio
          DB_PASSWORD: aws:kms:abcdef1234567890abcdef=
  # creates an ELB entry and Route53 domains to this ELB
  - AppLoadBalancer:
      Type: Senza::WeightedDnsElasticLoadBalancer
      HTTPPort: 8080
      HealthCheckPath: /ui/
      SecurityGroups: [app-kio-lb]
      Scheme: internet-facing

# Plain CloudFormation definitions are fully supported:
Outputs:
  URL:
    Description: "The ELB URL of the new Kio deployment."
    Value:
      "Fn::Join":
        - ""
        -
          - "http://"
          - "Fn::GetAtt":
              - AppLoadBalancer
              - DNSName

During evaluation, you can do mustache templating with access to the rendered definition, including the SenzaInfo, SenzaComponents and Arguments keys (containing all given arguments).

You can also specify the parameters by name, which makes the Senza CLI more readable. This might come handy in complex scenarios with sizeable number of parameters:

$ senza create example.yaml 3 example MintBucket=<mint-bucket> ImageVersion=latest

Here, the ApplicationId is given as a positional parameter. The two other parameters follow, specified by their names. The named parameters on the command line can be given in any order, but no positional parameter is allowed to follow the named ones.

Note

The name=value named parameters are split on the first =, so you can still include a literal = in the value part. Just pass this parameter with the name, to prevent Senza from treating the part of the parameter value before the first = as the parameter name.

You can pass any of the supported CloudFormation Properties such as AllowedPattern, AllowedValues, MinLength, MaxLength, etc. Senza itself will not enforce these, but CloudFormation will evaluate the generated template and raise an exception if any of the properties are not met. For example:

$ senza create example.yaml 3 example latest mint-bucket "Way too long greeting"
Generating Cloud Formation template.. OK
Creating Cloud Formation stack hello-world-3.. EXCEPTION OCCURRED: An error occurred (ValidationError) when calling the CreateStack operation: Parameter 'GreetingText' must contain at most 15 characters
Traceback (most recent call last):
[...]

Using the Default attribute, you can give any parameter a default value. If a parameter was not specified on the command line (either as positional or named), the default value is used. We suggest putting all default-value parameters at the bottom of your parameter definition list. Otherwise, there will be no way to map them to proper positions, and you'll have to specify all the following parameters using a name=value.

There is an option to pass parameters from a file (the file needs to be formatted in .yaml):

$ senza create --parameter-file parameters.yaml example.yaml 3 1.0-SNAPSHOT

An example of a parameter file:

ApplicationId: example-app-id
MintBucket: your-mint-bucket

You can also combine parameter files and parameters from the command line, but you can't name the same parameter twice. Also, the parameter can't exist both in a file and on the command line:

$ senza create --parameter-file parameters.yaml example.yaml 3 1.0-SNAPSHOT Param=Example1

AccountInfo

Senza templates offer the following properties:

{{AccountInfo.Region}}: the AWS region where the stack is created. Ex: 'eu-central-1'. In many parts of a template, you can also use {"Ref" : "AWS::Region"}.

{{AccountInfo.AccountAlias}}: the alias name of the AWS account. Ex: 'super-team1-account'.

{{AccountInfo.AccountID}}: the AWS account id. Ex: '353272323354'.

{{AccountInfo.TeamID}}: the team ID. Ex: 'super-team1'.

{{AccountInfo.Domain}}: the AWS account domain. Ex: 'super-team1.net'.

Mappings

Senza mappings are essentially key-value pairs, and behave just like CloudFormation mappings. Use mappings for Images, ServerSubnets or LoadBalancerSubnets.

An example:

Mappings:
   Images:
      eu-west-1:
         MyImage: "ami-123123"
# (..)
Image: MyImage

Senza Components

Configure all your Senza components in a list below the top-level SenzaComponents key. The structure is as follows:

SenzaComponents:
  - ComponentName1:
      Type: ComponentType1
      SomeComponentProperty: "some value"
  - ComponentName2:
      Type: ComponentType2

Note

Each list item below SenzaComponents is a map with only one key (the component name). The YAML "flow-style" syntax would be: SenzaComponents: [{CompName: {Type: CompType}}].

AutoScaling

AutoScaling properties include:

Minimum
Minimum number of instances to spawn.
Maximum
Maximum number of instances to spawn.
SuccessRequires:
During startup of the stack, it defines when CloudFormation considers your ASG healthy. Defaults to one healthy instance/15 minutes. You can change settings — for example, "four healthy instances/1:20:30" would look like "4 within 1h20m30s". You can omit hours/minutes/seconds as you please. Values that look like integers will be counted as healthy instances: for example, "2" is interpreted as two healthy instances within the default timeout of 15 minutes.
MetricType
Metric for doing auto-scaling that creates automatic alarms in CloudWatch for you. Must be either CPU, NetworkIn or NetworkOut. If you don't supply any info, your auto-scaling group will not dynamically scale and you'll have to define your own alerts.
ScaleUpThreshold
The upper scaling threshold of the metric value. For the "CPU" metric: a value of 70 means 70% CPU usage. For network metrics, a value of 100 means 100 bytes. You can pass the unit (KB/GB/TB), e.g. "100 GB".
ScaleDownThreshold
The lower scaling threshold of the metric value. For the "CPU" metric: a value of 40 means 40% CPU usage. For network metrics, a value of 2 means 2 bytes. You can pass the unit (KB/GB/TB), e.g. "2 GB".
ScalingAdjustment
Number of instances added/removed per scaling action. Defaults to 1.
Cooldown:
After a scaling action occurs, do not scale again for this amount of time (in seconds). Defaults to 60 (one minute).
Statistic
Which statistic to track when deciding your scaling thresholds are met. Defaults to "Average", but can also be "SampleCount", "Sum", "Minimum", "Maximum".
Period
Period (in seconds) over which statistic is calculated. Defaults to 300 (five minutes).
EvaluationPeriods
The number of periods over which data is compared to the specified threshold. Defaults to 2.

BlockDeviceMappings & Ebs Properties

BlockDeviceMappings properties are DeviceName (for example, /dev/xvdk) and Ebs (map of EBS options). VolumeSize, an Ebs property, is for determining how much GB an EBS should have.

WeightedDnsElasticLoadBalancer

Senza's WeightedDnsElasticLoadBalancer component type creates one HTTPs ELB resource with Route 53 weighted domains. You can either auto-detect the SSL certificate name used by the ELB, or name it SSLCertificateId. Specify the main domain (MainDomain) or the default Route53 hosted zone will apply.

An internal load balancer is created by default, which differs from AWS's default behavior. To create an Internet-facing ELB, explicitly set the Scheme to internet-facing.

SenzaComponents:
  - AppLoadBalancer:
      Type: Senza::WeightedDnsElasticLoadBalancer
      HTTPPort: 8080
      SecurityGroups:
        - app-myapp-lb

The WeightedDnsElasticLoadBalancer component supports the following configuration properties:

HTTPPort
The HTTP port used by the EC2 instances.
HealthCheckPath
The HTTP path to use for health checks, e.g. "/health". Must return 200.
HealthCheckPort
Optional. Port used for the health check. Defaults to HTTPPort.
SecurityGroups
List of security groups to use for the ELB. The security groups must allow SSL traffic.
MainDomain
Main domain to use, e.g. "myapp.example.org".
VersionDomain
Version domain to use, e.g. "myapp-1.example.org". You can use the usual templating feature to integrate the stack version, e.g. myapp-{{SenzaInfo.StackVersion}}.example.org.
Scheme
The load balancer scheme. Either internal or internet-facing. Defaults to internal.
SSLCertificateId
Name or ARN ID of the uploaded SSL/TLS server certificate to use, e.g. myapp-example-org-letsencrypt or arn:aws:acm:eu-central-1:123123123:certificate/abcdefgh-ijkl-mnop-qrst-uvwxyz012345. You can check available IAM server certificates with aws iam list-server-certificates. For ACM certificates, use aws acm list-certificates.

Additionally, you can specify any of the valid AWS CloudFormation ELB properties (e.g. to overwrite Listeners).

WeightedDnsElasticLoadBalancerV2

Similar to the WeightedDnsElasticLoadBalancer component WeightedDnsElasticLoadBalancerV2 creates one HTTPs ELBv2 resource with Route 53 weighted domains. ELBv2 listeners support SNI, hence you can specify multiple SSL certificates.

SenzaComponents:
  - AppLoadBalancer:
      Type: Senza::WeightedDnsElasticLoadBalancerV2
      HTTPPort: 8080
      SecurityGroups:
        - app-myapp-lb

The WeightedDnsElasticLoadBalancerV2 component supports the following configuration properties:

HTTPPort
The HTTP port used by the EC2 instances.
HealthCheckPath
The HTTP path to use for health checks, e.g. "/health". Must return 200.
HealthCheckPort
Optional. Port used for the health check. Defaults to HTTPPort.
SecurityGroups
List of security groups to use for the ELBv2. The security groups must allow SSL traffic.
MainDomain
Main domain to use, e.g. "myapp.example.org".
VersionDomain
Version domain to use, e.g. "myapp-1.example.org". You can use the usual templating feature to integrate the stack version, e.g. myapp-{{SenzaInfo.StackVersion}}.example.org.
Scheme
The load balancer scheme. Either internal or internet-facing. Defaults to internal.
SSLCertificateId
A comma-separated list of names or ARN ID of the uploaded SSL/TLS server certificates to use, e.g. myapp-example-org-letsencrypt or arn:aws:acm:eu-central-1:123123123:certificate/abcdefgh-ijkl-mnop-qrst-uvwxyz012345. You can check available IAM server certificates with aws iam list-server-certificates. For ACM certificates, use aws acm list-certificates.

Cross-Stack References

Traditional CloudFormation templates only allow you to reference resources located in the same template. This can be quite limiting. To compensate, Senza selectively supports special cross-stack references in some parts of your template — for instance, in SecurityGroups and IamRoles:

AppServer:
   Type: Senza::TaupageAutoScalingGroup
   InstanceType: c4.xlarge
   SecurityGroups:
     - Stack: base-1
       LogicalId: ApplicationSecurityGroup
   IamRoles:
     - Stack: base-1
       LogicalId: ApplicationRole

With these references, you can have an additional special stack per application that defines common security groups and IAM roles shared across different versions. Note that this in contrast to using senza init.

Unit Tests

$ python3 setup.py test --cov-html=true

Releasing

$ ./release.sh <NEW-VERSION>

senza's People

Contributors

a1exsh avatar adyach avatar aermakov-zalando avatar alexeyklyukin avatar chutium avatar csenol avatar duergner avatar feikesteenbergen avatar gargravarr avatar grzegorzjeziorski avatar hjacobs avatar hughcapet avatar inikolaev avatar jan-m avatar jbspeakr avatar jmcs avatar kenden avatar lmineiro avatar marek-obuchowicz avatar mnatsakanyank avatar mrandi avatar olevchyk avatar pc-alves avatar prayerslayer avatar rafaelcaricio avatar sarnowski avatar tmuehl avatar tuxlife avatar whiskeysierra avatar wssbck avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

senza's Issues

Add a flag to disable check for the docker image

There are some use cases where the AWS instrumentation is not allowed to access the Docker repository (or fails temporarily for some reason) and it should still be possible to print/create.

I suggest a boolean flag to disable such check. Default behavior could be to do the check (as of now)

Support "senza update"

$ senza update
should trigger a stack update. that is useful for stateful applications in order to leverage the rolling update policies of cloud formation

Add some special variables that can be used in the templates

It would be nice to be able to reference "Well Known Variables" to the senza templates like:

  • AWS Account ID
  • Region
  • MainDomain
  • TeamID
  • ...

We could use them in some of the conventions we've been using like the mint bucket, etcd cluster and many others:

      TaupageConfig:
        etcd_discovery_domain: "etcd.{{Variables.MainDomain}}"
        mint_bucket: "zalando-stups-mint-{{Variables.AccountId}}-{{Variables.Region}}"

Avoid long load balancer names

"LoadBalancer name cannot be longer than 32 characters"

Senza could automatically shorten too long names, or give users the option to define their own names. This does not affect DNS entries (they should remain long and readable, of course) or the stack name, but only the name of the ELB.

Instances listing should ignore terminated instances by default

Whenever you use senza instances ... you, sometimes, get the terminated instances in the listing. They usual don't have an IP address which allows you to filter them out (grep -v null, for ex.).

I believe in most cases you don't care about terminated instances but one should still be able to list them if a specific option is used, for ex., --terminated.

senza list wrong line length

When running senza listwithout a stack name the output is broken:

image

When I run senza list <stackname> then it is fine:

image

I tried looking into the code but could not understand where the problem comes from.

(OSX 10.10, python 3.4.3 from homebrew and pip3 install stups)

Senza fails with ugly traceback in case of missing ~/.aws/credentials

$ rm ~/.aws/credentials
$ senza li
Traceback (most recent call last):
File "/usr/local/bin/senza", line 11, in
sys.exit(main())
File "/usr/local/lib/python3.4/dist-packages/senza/cli.py", line 699, in main
cli()
File "/usr/local/lib/python3.4/dist-packages/click/core.py", line 664, in call
return self.main(_args, *_kwargs)
File "/usr/local/lib/python3.4/dist-packages/click/core.py", line 644, in main
rv = self.invoke(ctx)
File "/usr/local/lib/python3.4/dist-packages/click/core.py", line 991, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/local/lib/python3.4/dist-packages/click/core.py", line 837, in invoke
return ctx.invoke(self.callback, _ctx.params)
File "/usr/local/lib/python3.4/dist-packages/click/core.py", line 464, in invoke
return callback(_args, **kwargs)
File "/usr/local/lib/python3.4/dist-packages/senza/cli.py", line 294, in list_stacks
region = get_region(region)
File "/usr/local/lib/python3.4/dist-packages/senza/cli.py", line 246, in get_region
cf = boto.cloudformation.connect_to_region(region)
File "/usr/local/lib/python3.4/dist-packages/boto/cloudformation/init.py", line 55, in connect_to_region
return region.connect(
_kw_params)
File "/usr/local/lib/python3.4/dist-packages/boto/regioninfo.py", line 187, in connect
return self.connection_cls(region=self, *_kw_params)
File "/usr/local/lib/python3.4/dist-packages/boto/cloudformation/connection.py", line 89, in init
profile_name=profile_name)
File "/usr/local/lib/python3.4/dist-packages/boto/connection.py", line 1100, in init
provider=provider)
File "/usr/local/lib/python3.4/dist-packages/boto/connection.py", line 569, in init
host, config, self.provider, self._required_auth_capability())
File "/usr/local/lib/python3.4/dist-packages/boto/auth.py", line 987, in get_auth_handler
'Check your credentials' % (len(names), str(names)))
boto.exception.NoAuthHandlerFound: No handler was ready to authenticate. 1 handlers were checked. ['HmacAuthV4Handler'] Check your credentials

Sometimes "senza events -w" seems to crash with BotoServerError: 400 Bad Request

Running senza events -w seems to sometimes crash with the following stack trace:

Traceback (most recent call last):
  File "/usr/local/bin/senza", line 9, in <module>
    load_entry_point('stups-senza==0.65', 'console_scripts', 'senza')()
  File "/usr/local/lib/python3.4/site-packages/senza/cli.py", line 938, in main
    handle_exceptions(cli)()
  File "/usr/local/lib/python3.4/site-packages/senza/cli.py", line 223, in wrapper
    func()
  File "/usr/local/lib/python3.4/site-packages/click/core.py", line 664, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.4/site-packages/click/core.py", line 644, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.4/site-packages/click/core.py", line 991, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.4/site-packages/click/core.py", line 837, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.4/site-packages/click/core.py", line 464, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.4/site-packages/senza/cli.py", line 521, in events
    events = cf.describe_stack_events(stack.stack_name)
  File "/usr/local/lib/python3.4/site-packages/boto/cloudformation/connection.py", line 580, in describe_stack_events
    StackEvent)])
  File "/usr/local/lib/python3.4/site-packages/boto/connection.py", line 1186, in get_list
    raise self.ResponseError(response.status, response.reason, body)
boto.exception.BotoServerError: BotoServerError: 400 Bad Request
<ErrorResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
  <Error>
    <Type>Sender</Type>
    <Code>Throttling</Code>
    <Message>Rate exceeded</Message>
  </Error>
  <RequestId>d7a8ef15-2c70-11e5-a49b-87ddc69fdc5a</RequestId>
</ErrorResponse>

I don't have much more details, except that the last event from CloudFormation to the console before crash was:

applicationname         1    AutoScaling::AutoScalingGroup      AppServer                CREATE_IN_PROGRESS Resource creation Initiated                         64s ago

and the next one (from AWS web console) was:

CREATE_FAILED   AWS::AutoScaling::AutoScalingGroup  AppServer   Failed to receive 1 resource signal(s) within the specified duration

Senza init sometimes failes to create security groups

I got this exception several times. Not only when creating the LB security group, but also for the app security group.

Maybe there is a short waiting period needed, before newly created security groups can be used.

senza init hello-andre.yaml
Please select the project template
1) bgapp: Background app with single EC2 instance
2) postgresapp: HA Postgres app, which needs an S3 bucket to store WAL files
3) webapp: HTTP app with auto scaling, ELB and DNS
Please select (1-3): 3
Application ID [hello-world]: hello-andre
Docker image without tag/version (e.g. "pierone.example.org/myteam/myapp") [stups/hello-world]:
HTTP port [8080]:
HTTP health check path [/]:
EC2 instance type [t2.micro]:
Mint S3 bucket name [sensitive_data_ stripped]:
Checking security group app-hello-andre.. OK
Security group app-hello-andre does not exist. Do you want Senza to create it now? [Y/n]:
Checking security group app-hello-andre-lb.. OK
Security group app-hello-andre-lb does not exist. Do you want Senza to create it now? [Y/n]:
Traceback (most recent call last):
  File "/usr/local/bin/senza", line 9, in <module>
    load_entry_point('stups-senza==0.53', 'console_scripts', 'senza')()
  File "/usr/local/lib/python3.4/site-packages/senza/cli.py", line 798, in main
    handle_exceptions(cli)()
  File "/usr/local/lib/python3.4/site-packages/senza/cli.py", line 219, in wrapper
    func()
  File "/usr/local/lib/python3.4/site-packages/click/core.py", line 664, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.4/site-packages/click/core.py", line 644, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.4/site-packages/click/core.py", line 991, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.4/site-packages/click/core.py", line 837, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.4/site-packages/click/core.py", line 464, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.4/site-packages/senza/cli.py", line 552, in init
    variables = module.gather_user_variables(variables, region)
  File "/usr/local/lib/python3.4/site-packages/senza/templates/webapp.py", line 77, in gather_user_variables
    rules_missing = check_security_group(sg_name + '-lb', [('tcp', 443)], region)
  File "/usr/local/lib/python3.4/site-packages/senza/templates/_helper.py", line 45, in check_security_group
    sg.add_tags({'Name': sg_name})
  File "/usr/local/lib/python3.4/site-packages/boto/ec2/ec2object.py", line 97, in add_tags
    dry_run=dry_run
  File "/usr/local/lib/python3.4/site-packages/boto/ec2/connection.py", line 4203, in create_tags
    return self.get_status('CreateTags', params, verb='POST')
  File "/usr/local/lib/python3.4/site-packages/boto/connection.py", line 1227, in get_status
    raise self.ResponseError(response.status, response.reason, body)
boto.exception.EC2ResponseError: EC2ResponseError: 400 Bad Request
<?xml version="1.0" encoding="UTF-8"?>
<Response><Errors><Error><Code>InvalidGroup.NotFound</Code><Message>The security group 'sg-5d023b38' does not exist</Message></Error></Errors><RequestID>...</RequestID></Response>

Allow CloudFormation Ref function in TaupageConfig

I would like to create cloudformation resources like SQS queues or RDS databases in my app.yml and handover resource properties directly into the instances configuration. As environment variables f.e. This would need senza to parse the TaupageConfig section and look for "Ref: foo" statements to process prior to base64 encoding.

Senza "status" crashes for stacks during creation

Traceback (most recent call last):
File "/usr/local/bin/senza", line 9, in
load_entry_point('stups-senza==0.37', 'console_scripts', 'senza')()
File "/usr/local/lib/python3.4/dist-packages/senza/cli.py", line 690, in main
cli()
File "/usr/local/lib/python3.4/dist-packages/click/core.py", line 664, in call
return self.main(_args, *_kwargs)
File "/usr/local/lib/python3.4/dist-packages/click/core.py", line 644, in main
rv = self.invoke(ctx)
File "/usr/local/lib/python3.4/dist-packages/click/core.py", line 991, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/local/lib/python3.4/dist-packages/click/core.py", line 837, in invoke
return ctx.invoke(self.callback, *_ctx.params)
File "/usr/local/lib/python3.4/dist-packages/click/core.py", line 464, in invoke
return callback(_args, **kwargs)
File "/usr/local/lib/python3.4/dist-packages/senza/cli.py", line 601, in status
answers = dns.resolver.query(name, 'CNAME')
File "/usr/local/lib/python3.4/dist-packages/dns/resolver.py", line 979, in query
raise_on_no_answer, source_port)
File "/usr/local/lib/python3.4/dist-packages/dns/resolver.py", line 784, in query
if qname.is_absolute():
AttributeError: 'NoneType' object has no attribute 'is_absolute'

Change instance profile setting to roles list

It would be nice to be able to specify a list of roles instead of one instance profile ID. Senza should generate an instance profile on-the-fly with all roles attached. This is especially helpful as not all types of roles automatically have an instance profile ID. This way its also easier to compose different roles for the server (which will be important for getting credentials via berry).

See simplestack: https://github.com/zalando/simplestack/blob/master/resources/simplestack/template.json#L134

Improve senza create command line parameters handling

Surprisingly, I couldn't find this being brought up before, so here goes.

Senza create doesn't check for extra parameters on the command line. Nor can it help you if you misplaced a parameter. And you have to put them in the certain order, dictated by the .yaml file.

Imagine a .yaml where two numeric parameters follow one another: you run

senza create my.yaml bla-bla-bla 3 60 <image> ...

but you have misplaced the params, and instead of 3 instances with some check timeout of 60 seconds you are now creating 60 instances with 3 seconds timeout! So to avoid that you have to keep the .yaml file before your eyes in order to check the order of the parameters.

Wouldn't it be more convenient to provide parameters as key=value? You can then specify them in any order and the command line becomes self-documenting, e.g.:

senza create my.yaml APPID=bla-bla-bla NODES=3 TIMEOUT=60 IMAGE=<image> ...

I think for backwards compatibility, we could also keep the current positional approach and support a mix of them (like the Python itself does by the way).

Cheers!

Enable request rate throttling for instance list

I would like to check the health of all my instances. I'm happy to wait longer if it's needed.
Currently with > 25 stacks I get an "Rate exceeded" error response when executing "senza inst".

It would be cool if I could provide a value from the command line, which would enable rate limiting with a certain factor (N times higher delay between requests) or similar.

  File "/usr/local/lib/python3.4/dist-packages/boto/connection.py", line 1186, in get_list
    raise self.ResponseError(response.status, response.reason, body)
boto.exception.BotoServerError: BotoServerError: 400 Bad Request
<ErrorResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
  <Error>
    <Type>Sender</Type>
    <Code>Throttling</Code>
    <Message>Rate exceeded</Message>
  </Error>
  <RequestId>...</RequestId>
</ErrorResponse>

Support multiple VPCs

Senza's STUPS components currently assume a single VPC per region (Seven Seconds only configures a single VPC). There might be valid reasons to have multiple VPCs (e.g. a special VPC with VPN tunnel to some 3rd party location), so Senza needs to support that, too.

Components names should update VPC DHCP to allow service discovery

Assuming component names are unique in Senza it would be convenient to setup the VPC DHCP or some internal DNS within the VPC so N deployed background components designed to work together but without exposing them through a public DNS can communicate with an internal hostname that resolves to the AWS private ip of the instances:

SenzaComponents:
  - ComponentName1:
      Type: ComponentType1
      SomeComponentProperty: "some value"
  - ComponentName2:
      Type: ComponentType2

e.g. component-name-1.local resolves to 172.31.144.180
e.g. component-name-2.local resolves to 172.31.144.181

Or instead of local could also be eu-west-1.compute.internal varying on the region for example.

Should be technically possible

By default, all instances in a nondefault VPC receive an unresolvable host name that AWS assigns (for example, ip-10-0-0-202). You can assign your own domain name to your instances

Google Cloud apparently solves it out of the box: https://cloud.google.com/compute/docs/instances-and-network#communicating_with_instances

Perhaps this is the wrong approach and my use case can be solved via etcd? in which case how? I searched etcd in http://stups.readthedocs.org/ but couldn't find it.

AWS seems to spawn new instances when trying to create a new stack with an existing version

If there are at least 2 versions of a stack available and one tries to deploy the uppermost version again AWS respawns new instances of the lower version according to the stack definition.
To reproduce there must be running instances of the uppermost version available and no active (terminated) instances of the lower one. Maybe reproducible in any other constellation.
I didn't try it with more than 2 stack versions so i don't know if it's an issue with just 2 of them.

Allow default values for Parameters

It would be nice to be able to specify a default value for Parameters. For ex.

Parameters:
  - ClusterSize:
    Description: "The size (number of nodes) for the new Cassandra cluster."
    DefaultValue: 5

This can be challenging, due to the order based parameter mapping. Eventually, Optional parameters would have to be at the end and not possible to skip them.

It would be a nice addition.

Senza does not recognize referenced Security Groups

senza currently only supports Security Groups which are already created beforehand, not the ones created in the Resources section. Should be supported the same way as IAM roles, or is there a reasons why this is not yet implemented?

Allow to specify matching stacks in a flexible way on the CLI

It should convenient to list resources/stacks/instances by allowing partial matches:

$ senza instances            # simply list all CF-managed EC2 instances
$ senza instances test.yaml  # list EC2 instances for all stack versions
$ senza instances test-1     # list EC2 instances for "test-1" stack
$ senza instances test       # list EC2 instances for all "test" stacks

Cleanup output

This output looks messy... it's enough to show error message once and it does not make sense to show "usage" here (the error case is: stack with the name already exists)

>> senza create phoenix-authorization-staging.yaml 4 4
Generating Cloud Formation template.. OK
Creating Cloud Formation stack phoenix-authorization-staging-4.. EXCEPTION OCCURRED: Stack phoenix-authorization-staging-4 already exists. Please choose another version.
Usage: senza create [OPTIONS] DEFINITION VERSION [PARAMETER]...

Error: Stack phoenix-authorization-staging-4 already exists. Please choose another version.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.