GithubHelp home page GithubHelp logo

capistrano-elbas's People

Contributors

eman8519 avatar jbritten avatar kragej avatar lserman avatar satyricon avatar sebatyler avatar thebentern avatar twohlix 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

Watchers

 avatar  avatar  avatar  avatar

capistrano-elbas's Issues

InstanceCollection only returns one instance, despite multiple running instances

I'm experiencing an issue where Capistrano only deploys to a single server, despite having multiple running servers in my AutoScalingGroup.

My setup on AWS:
A launch template (id: lt-xxx, name: preprod)
An autoscaling group (name: preprod)
2 running instances launched by the ASG (Ids: i-x1 and i-x2)

Below is the output of instantiating an Elbas::AWS::AutoscaleGroup, calling instances.running, and creating a new Elbas::AWS::InstanceCollection with the IDs I can see in the ASG:

asg = Elbas::AWS::AutoscaleGroup.new preprod
=> #<Elbas::AWS::AutoscaleGroup:0x000000000351efc0
 @aws_client=#<Aws::AutoScaling::Client>,
 @aws_counterpart=
  #<struct Aws::AutoScaling::Types::AutoScalingGroup
   auto_scaling_group_name="preprod",
   auto_scaling_group_arn="arn:xxx",
   launch_configuration_name=nil,
   launch_template=#<struct Aws::AutoScaling::Types::LaunchTemplateSpecification launch_template_id="lt-xxx", launch_template_name="preprod", version="$Latest">,
   mixed_instances_policy=nil,
   min_size=0,
   max_size=2,
   desired_capacity=2,
   default_cooldown=300,
   availability_zones=["eu-west-1b", "eu-west-1a"],
   load_balancer_names=[],
   target_group_arns=["arn:xxx"],
   health_check_type="EC2",
   health_check_grace_period=300,
   instances=
    [#<struct Aws::AutoScaling::Types::Instance
      instance_id="i-x1",
      availability_zone="eu-west-1b",
      lifecycle_state="InService",
      health_status="Healthy",
      launch_configuration_name=nil,
      launch_template=#<struct Aws::AutoScaling::Types::LaunchTemplateSpecification launch_template_id="lt-xxx", launch_template_name="preprod", version="3">,
      protected_from_scale_in=false>,
     #<struct Aws::AutoScaling::Types::Instance
      instance_id="i-x2",
      availability_zone="eu-west-1a",
      lifecycle_state="InService",
      health_status="Healthy",
      launch_configuration_name=nil,
      launch_template=#<struct Aws::AutoScaling::Types::LaunchTemplateSpecification launch_template_id="lt-xxx", launch_template_name="preprod", version="3">,
      protected_from_scale_in=false>],
   created_time=2019-02-25 14:44:39 UTC,
   suspended_processes=[],
   placement_group=nil,
   vpc_zone_identifier="subnet-xxx,subnet-xxx",
   enabled_metrics=[],
   status=nil,
   tags=[],
   termination_policies=["Default"],
   new_instances_protected_from_scale_in=false,
   service_linked_role_arn="arn:aws:iam::xxx:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling">,
 @name="preprod">

 asg.instances.running
=> [#<Elbas::AWS::Instance:0x00000000094de348
  @aws_client=#<Aws::EC2::Client>,
  @aws_counterpart=#<Aws::EC2::Instance:0x00000000094a4530 @client=#<Aws::EC2::Client>, @data=nil, @id="i-x1">,
  @id="i-x1",
  @public_dns="xxx.eu-west-1.compute.amazonaws.com",
  @state=16>]

 collection = Elbas::AWS::InstanceCollection.new ["i-x1", "i-x2"]
  => #<Elbas::AWS::InstanceCollection:0x0000000008976be0
 @aws_client=#<Aws::EC2::Client>,
 @ids=["i-x1", "i-x2"],
 @instances=
  [#<Elbas::AWS::Instance:0x000000000885dad8
    @aws_client=#<Aws::EC2::Client>,
    @aws_counterpart=#<Aws::EC2::Instance:0x00000000087f9e70 @client=#<Aws::EC2::Client>, @data=nil, @id="i-x1">,
    @id="i-x1",
    @public_dns="xxx.eu-west-1.compute.amazonaws.com",
    @state=16>]>

As you can see, when I instantiate the ASG, I can see 2 instances (i-x1 and i-x2), but calling

asg.instances.running

or

Elbas::AWS::InstanceCollection.new ["i-x1", "i-x2"]

I only get the first instance.

The issue seems to be in Elbas::AWS::InstanceCollection#query_instances_by_ids, which only looks at the first reservation in the response from describe_instances.

I'm submitting a PR, which changes the method to:

def query_instances_by_ids(ids)
  aws_client
    .describe_instances(instance_ids: @ids)
    .reservations.map(&:instances).flatten
end

can aws_no_reboot_on_create_ami be set to false?

I am about to start using elbas as it looks like a great way to automate our autoscaling deployments.
However, I notice that you recommend this setting:

set :aws_no_reboot_on_create_ami, true

Creating an AMI without reboot does not guarantee that the AMI will be in a consistent state. There are warnings about this throughout the AWS docs.

I would think that since this is an autoscaling group, it's really not a big deal for a single instance to go down while creating the AMI since the ELB will route traffic to the other instances in the meantime.

Any particular reason for not rebooting the instance to create the AMI with elbas?

Assumed role

In our setup developer are authenticated through our company but use a role on client company to deploy on their behalf and on their account.

Therefore we ask our client to create a role for us which we can assume for the intervention we do on their account.

I've added this patch which check for a aws_assumed_role_arn key in capistrano config and if present start a special session.

I do not know how frequent our setup is but I'm sharing the code back with you since your gem basically saved me days of work :)

require 'aws/sts'
require 'elbas/aws/credentials'


Elbas::AWS::Credentials.module_eval do


  def overidden_credentials
    @_credentials ||= begin
      _credentials = {
        access_key_id: fetch(:aws_access_key_id, ENV['AWS_ACCESS_KEY_ID']),
        secret_access_key: fetch(:aws_secret_access_key, ENV['AWS_SECRET_ACCESS_KEY'])
      }

      _credentials.merge! region: fetch(:aws_region) if fetch(:aws_region)
      _credentials
    end
  end

  def credentials
    return @patched_credentials if defined?(@patched_credentials)

    credential_hash = overidden_credentials
    assumed_role_arn = fetch(:aws_assumed_role_arn)


    if assumed_role_arn
      sts = ::AWS::STS.new(credential_hash)
      role_credentials = sts.assume_role(
        role_arn: assumed_role_arn,
        role_session_name: "capistrano-session",
      )
      @patched_credentials = role_credentials[:credentials].merge(region: credential_hash[:region])

    else
      @patched_credentials = credential_hash
    end

    @patched_credentials
  end

end

Capistrano DSL#error no longer exists

In the capistrano.rb there exists an older style DSL for erroring in Capistrano:

    error <<~MESSAGE
      Could not create AMI because no running instances were found in the specified
      AutoScale group. Ensure that the AutoScale group name is correct and that
      there is at least one running instance attached to it.
    MESSAGE

which is apparently not a method in capistrano dsl anymore. Just tracking the issue.

NameError: uninitialized constant AWS

** Invoke production (first_time)
** Execute production
** Invoke load:defaults (first_time)
** Execute load:defaults
cap aborted!
NameError: uninitialized constant AWS
Did you mean?  Aws
/Users/me/.rvm/gems/ruby-2.3.4/gems/elbas-0.0.4/lib/elbas/capistrano.rb:24:in `autoscaling'
/Users/me/.rvm/gems/ruby-2.3.4/gems/elbas-0.0.4/lib/elbas/capistrano.rb:9:in `autoscale'
config/deploy/production.rb:4:in `<top (required)>'
/Users/me/.rvm/gems/ruby-2.3.4/gems/capistrano-3.7.2/lib/capistrano/setup.rb:28:in `load'
/Users/me/.rvm/gems/ruby-2.3.4/gems/capistrano-3.7.2/lib/capistrano/setup.rb:28:in `block (3 levels) in <top (required)>'
/Users/me/.rvm/gems/ruby-2.3.4/gems/capistrano-3.7.2/lib/capistrano/configuration/variables.rb:32:in `untrusted!'
/Users/me/.rvm/rubies/ruby-2.3.4/lib/ruby/2.3.0/delegate.rb:83:in `method_missing'
/Users/me/.rvm/gems/ruby-2.3.4/gems/capistrano-3.7.2/lib/capistrano/setup.rb:26:in `block (2 levels) in <top (required)>'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/task.rb:251:in `block in execute'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/task.rb:251:in `each'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/task.rb:251:in `execute'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/task.rb:195:in `block in invoke_with_call_chain'
/Users/me/.rvm/rubies/ruby-2.3.4/lib/ruby/2.3.0/monitor.rb:214:in `mon_synchronize'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/task.rb:188:in `invoke_with_call_chain'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/task.rb:181:in `invoke'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/application.rb:160:in `invoke_task'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/application.rb:116:in `each'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/application.rb:116:in `block in top_level'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/application.rb:125:in `run_with_threads'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/application.rb:110:in `top_level'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/application.rb:83:in `block in run'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/me/.rvm/gems/ruby-2.3.4/gems/rake-12.3.0/lib/rake/application.rb:80:in `run'
/Users/me/.rvm/gems/ruby-2.3.4/gems/capistrano-3.7.2/lib/capistrano/application.rb:14:in `run'
/Users/me/.rvm/gems/ruby-2.3.4/gems/capistrano-3.7.2/bin/cap:3:in `<top (required)>'
/Users/me/.rvm/gems/ruby-2.3.4/bin/cap:23:in `load'
/Users/me/.rvm/gems/ruby-2.3.4/bin/cap:23:in `<main>'
/Users/me/.rvm/gems/ruby-2.3.4/bin/ruby_executable_hooks:15:in `eval'
/Users/me/.rvm/gems/ruby-2.3.4/bin/ruby_executable_hooks:15:in `<main>'
Tasks: TOP => production

multi-template x multi-asg support?

have a situation where we would prefer to run two different auto-scale groups (asg), one for web and one for workers, both based on the same ami, and only update the ami once.

Additionally, have a need to be able to create two different ami's, one for each asg

It appears that the task that updates the amis would only run once since capistrano only runs them once if we don't use invoke!.

does elbas support multiple asgs where each has a separate launch template?
does elbas support multiple asg's where they all use the same launch template?

Add command for displaying server public IPs attached to an environment

Sometimes you need to run rails c on your servers or something and it's a pain with an ELB. You don't know the server IPs of your instances without checking the AWS console so you cannot SSH into one of them to run whatever you need to run.

Since elbas has knowledge of your load balancer, environment, and AWS credentials, it would be great if you could run something like bin/cap production elbas:server_ips or something to see a list of public IPs (if available) on that environment's ELB.

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.