简体   繁体   中英

Capistrano :NoMethodError: undefined method `merge' for“ec2 private ip”:String

I am trying to deploy multiple EC2 instances via bastion host. I put my EC2 instances under ELB and always access via bastion.

require 'aws-sdk'
require 'net/ssh/proxy/command'

ec2 = Aws::EC2::Client.new(region: fetch(:aws_region))

ec2_filtered = ec2.describe_instances(
    filters:[
        {name: "tag:env", values: [fetch(:rails_env)]},
        {name: "tag:role", values: [fetch(:aws_tag_role)]},
        {name: 'instance-state-name', values: ['running']}
    ])

instances = ec2_filtered.reservations.map(&:instances)[0].map(&:private_ip_address)
instances = ec2_filtered.reservations.map(&:instances)[1].map(&:private_ip_address)

set :branch, 'master'

role :app, *instances
role :web, *instances
role :db, [instances.first]

server *instances,
  user: fetch(:deploy_user),
  ssh_options: {
    forward_agent: true,
    keys: fetch(:deploy_ssh_keys),
    proxy: Net::SSH::Proxy::Command::new('ssh bastion.mamorio -W %h:%p')
  }

The code above works but it's really redundant and I want to get the whole "private ip" at once.

I tried this code:

instances = ec2_filtered.reservations.map(&:instances).flatten.map(&:private_ip_address)

but I get the following error.

NoMethodError: undefined method `merge' for "10.0.xx.2xx":String

Any advice?

I think the problem is the value you are passing to Capistrano's role declaration.

role :app, *instances

The role method expects an array as the second argument, but in your example you are "splatting" the instances array into separate arguments.

Try this instead:

role :app, instances

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM