class Chef::Provider::AwsNetworkInterface

Public Instance Methods

action_create() click to toggle source
Calls superclass method
# File lib/chef/provider/aws_network_interface.rb, line 23
def action_create
  eni = super

  update_eni(eni) unless new_resource.machine.nil?
end

Protected Instance Methods

create_aws_object() click to toggle source
# File lib/chef/provider/aws_network_interface.rb, line 31
def create_aws_object
  eni = nil
  converge_by "create new #{new_resource} in #{region}" do
    ec2_resource = ::Aws::EC2::Resource.new(new_resource.driver.ec2)
    # we require all the parameter from options except :device_index so deleted & then passed.
    option_without_device_index = options.dup.tap { |h| h.delete(:device_index) }
    eni = ec2_resource.create_network_interface(option_without_device_index)
    retry_with_backoff(::Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound) do
      ec2_resource.create_tags(resources: [eni.id], tags: [{ key: "Name", value: new_resource.name }])
    end
    eni
  end

  converge_by "wait for new #{new_resource} in #{region} to become available" do
    wait_for_status(eni, :available)
    eni
  end
end
destroy_aws_object(eni) click to toggle source
# File lib/chef/provider/aws_network_interface.rb, line 92
def destroy_aws_object(eni)
  detach(eni) if eni.status == "in-use"
  delete(eni)
end
update_aws_object(eni) click to toggle source
# File lib/chef/provider/aws_network_interface.rb, line 50
def update_aws_object(eni)
  if options.key?(:subnet_id)
    if Chef::Resource::AwsSubnet.get_aws_object(options[:subnet_id], resource: new_resource).id != eni.subnet.id
      raise "#{new_resource} subnet is #{new_resource.subnet}, but actual network interface has subnet set to #{eni.subnet_id}.  Cannot be modified!"
    end
  end

  # TODO: implement private ip reassignment
  if options.key?(:private_ip_address)
    if options[:private_ip_address] != eni.private_ip_address
      raise "#{new_resource} private IP is #{new_resource.private_ip_address}, but actual network interface has private IP set to #{eni.private_ip_address}.  Private IP reassignment not implemented. Cannot be modified!"
    end
  end

  if options.key?(:description)
    if options[:description] != eni.description
      converge_by "set #{new_resource} description to #{new_resource.description}" do
        eni.client.modify_network_interface_attribute(network_interface_id: eni.network_interface_id,
                                                      description: {
                                                        value: new_resource.description
                                                      })
      end
    end
  end

  if options.key?(:groups)
    groups = new_resource.security_groups
    eni_security_groups = []
    eni.groups.each do |group|
      eni_security_groups.push(group.group_id)
    end

    if groups.sort != eni_security_groups.sort
      converge_by "set #{new_resource} security groups to #{groups}" do
        eni.client.modify_network_interface_attribute(network_interface_id: eni.network_interface_id, groups: groups)
      end
    end
  end

  eni
end

Private Instance Methods

attach(eni) click to toggle source
# File lib/chef/provider/aws_network_interface.rb, line 170
def attach(eni)
  converge_by "attach #{new_resource} to #{new_resource.machine} (#{expected_instance.id})" do
    eni.attach(instance_id: expected_instance.id, device_index: options[:device_index])
  end

  converge_by "wait for #{new_resource} to attach" do
    wait_for_status(eni, :in_use)
    eni
  end
end
current_attachment(eni) click to toggle source
# File lib/chef/provider/aws_network_interface.rb, line 181
def current_attachment(eni)
  eni.attachment
end
delete(eni) click to toggle source
# File lib/chef/provider/aws_network_interface.rb, line 185
def delete(eni)
  converge_by "delete #{new_resource} in #{region}" do
    eni.delete
  end

  converge_by "wait for #{new_resource} in #{region} to delete" do
    log_callback = proc {
      Chef::Log.info("waiting for network interface to delete...")
    }

    Retryable.retryable(tries: 30, sleep: 2, on: NetworkInterfaceStatusTimeoutError, ensure: log_callback) do
      result = new_resource.driver.ec2_resource.network_interface(eni.id) if eni.id
      raise NetworkInterfaceStatusTimeoutError.new(new_resource, "exists", "deleted") if new_resource.exists?(result)
    end
    eni
  end
end
detach(eni) click to toggle source
# File lib/chef/provider/aws_network_interface.rb, line 157
def detach(eni)
  attachment = current_attachment(eni)

  converge_by "detach #{new_resource} from #{attachment.instance_id}" do
    eni.detach
  end

  converge_by "wait for #{new_resource} to detach" do
    wait_for_status(eni, :available)
    eni
  end
end
expected_instance() click to toggle source
# File lib/chef/provider/aws_network_interface.rb, line 99
def expected_instance
  # use instance if already set
  @expected_instance ||= new_resource.machine ?
      # if not, and machine is set, find and return the instance
      Chef::Resource::AwsInstance.get_aws_object(new_resource.machine, resource: new_resource) :
      # otherwise return nil
      nil
end
options() click to toggle source
# File lib/chef/provider/aws_network_interface.rb, line 108
def options
  @options ||= begin
    options = {}
    options[:subnet_id] = new_resource.subnet unless new_resource.subnet.nil?
    options[:private_ip_address] = new_resource.private_ip_address unless new_resource.private_ip_address.nil?
    options[:description] = new_resource.description unless new_resource.description.nil?
    options[:groups] = new_resource.security_groups unless new_resource.security_groups.nil?
    options[:device_index] = new_resource.device_index unless new_resource.device_index.nil?

    AWSResource.lookup_options(options, resource: new_resource)
  end
end
update_eni(eni) click to toggle source
# File lib/chef/provider/aws_network_interface.rb, line 121
def update_eni(eni)
  status = new_resource.driver.ec2_resource.network_interface(eni.id).status
  #
  # If we were told to attach the network interface to a machine, do so
  #
  if expected_instance.is_a?(::Aws::EC2::Instance) || expected_instance.is_a?(::Aws::EC2::Instance)
    case status
    when "available"
      attach(eni)
    when "in-use"
      # We don't want to attempt to reattach to the same instance or device index
      attachment = current_attachment(eni)
      if attachment.instance_id != expected_instance.id || (options[:device_index] && attachment.device_index != new_resource.device_index)
        detach(eni)
        attach(eni)
      end
    when nil
      raise NetworkInterfaceNotFoundError, new_resource
    else
      raise NetworkInterfaceInvalidStatusError.new(new_resource, status)
    end

  #
  # If we were told to set the machine to false, detach it.
  #
  else
    case status
    when nil
      Chef::Log.warn NetworkInterfaceNotFoundError.new(new_resource)
    when "in-use"
      detach(eni)
    end
  end
  eni
end