how to get an aws instance given I have the instance's ip - ruby

Given I have an aws instance IP, how can I get the EC2 instance collection object via the ruby aws-sdk's filter option. For example
#ec2.instances.filter(valid_filter_name, ec2_instance_ip)
I've tried 'public_ip_address' and 'public_ip' as the filter name but those didn't work. I'm using this API doc http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/EC2/FilteredCollection.html#filter-instance_method, but it's does not mentioned what the valid parameters are.

It turns out the correct parameter to use (by trial & error) is 'ip-address'. Here's an example:
#ec2.instances.filter('ip-address', ec2_instance_ip)

Related

Ruby: Undefined method `bucket' for #<Aws::S3::Client>

Using the aws-sdk-s3 gem, I am currently able to upload items to buckets and create signed URLs, and am trying to determine if an object exists in a bucket or not. All the documentation I see says client.bucket('bucketname') should work, but in my case it is not. I've tried:
client.bucket('bucketname')
client.bucket['bucketname']
client.buckets('bucketname')
client.buckets['bucketname']
but none work. This suggestion using head_object is a possibility (https://github.com/cloudyr/aws.s3/issues/160), but I'm still curious why bucket isn't working.
DOCS:
https://gist.github.com/hartfordfive/19097441d3803d9aa75ffe5ecf0696da
https://docs.aws.amazon.com/sdk-for-ruby/v3/api/index.html#Resource_Interfaces
You should call bucket or buckets on Aws::S3::Resource instance and not on Aws::S3::Client instance as an error states.
And the links you provided as well as docs show that:
s3 = Aws::S3::Resource.new(
region: 'us-east-1',
credentials: Aws::InstanceProfileCredentials.new()
)
bucket = s3.bucket('my-daily-backups')

How to use kubebuilder's client.List method?

I'm working on a custom controller for a custom resource using kubebuilder (version 1.0.8). I have a scenario where I need to get a list of all the instances of my custom resource so I can sync up with an external database.
All the examples I've seen for kubernetes controllers use either client-go or just call the api server directly over http. However, kubebuilder has also given me this client.Client object to get and list resources. So I'm trying to use that.
After creating a client instance by using the passed in Manager instance (i.e. do mgr.GetClient()), I then tried to write some code to get the list of all the Environment resources I created.
func syncClusterWithDatabase(c client.Client, db *dynamodb.DynamoDB) {
// Sync environments
// Step 1 - read all the environments the cluster knows about
clusterEnvironments := &cdsv1alpha1.EnvironmentList{}
c.List(context.Background(), /* what do I put here? */, clusterEnvironments)
}
The example in the documentation for the List method shows:
c.List(context.Background, &result);
which doesn't even compile.
I saw a few method in the client package to limit the search to particular labels, or for a specific field with a specific value, but nothing to limit the result to a specific resource kind.
Is there a way to do this via the Client object? Should I do something else entirely?
So figured it out - the answer is to pass nil for the second parameter. The type of the output pointer determines which sort of resource it actually retrieves.
According to the latest documentation, the List method is defined as follows,
List(ctx context.Context, list ObjectList, opts ...ListOption) error
If the List method you are calling has the same definition as above, your code should compile. As it has variadic options to set the namespace and field match, the mandatory arguments are Context and objectList.
Ref: KubeBuilder Book

List Tag Value - EC2 Boto3

My understanding is I'm supposed to use resource when using Boto3 :)
The following returns all the key/value pairs; how would I get a specific key value? I'm looking print out the name given to the instance.
ec2 = boto3.resource('ec2')
for instance in ec2.instances.all():
print (instance.tags)
You can use either the boto3 resource or client interfaces. The resource interface is a higher level which is easier (simpler) to work with. The client interface is lower layer and you have more fine grained control. Start off with using resource and later switch to client as you better understand Python / boto3 / AWS SDKs.
Here is an example that will print the Value value.
The key parts to understand is that instance.tags is an array of Python dict (dictionary). You need to loop thru this array to get to each "Value". When accessing a dict you use this syntax ['name_of_item'].
AWS stores tags as Key and Value. These are the names to use when processing the dict.
import boto3
ec2 = boto3.resource('ec2')
for instance in ec2.instances.all():
print (instance.tags)
for tag in instance.tags:
print(tag['Value'])

passing variables to cloud-config chef?

I'm trying to create a user-data script with cloud-init using the chef features. I've run into a limitation and I'm wondering if there's a way around it. I need my node names to be unique since the chef server will only accept a client with a unique name. I've tried several things to pass either a datetime variable or the instance ID, but I can't seem to pass variables to the node_name section.
node_name: "server-app-$INSTANCE_ID"
or
node_name: "server-app-$(date +%s)"
Is there a way to escape this so that it doesn't get interpreted literally?
Chef encountered an error attempting to create the client "server-app-$INSTANCE_ID"
You'll have to do the expansion before you write out the client.rb:
echo "node_name '$(date +%s)' >> /etc/chef/client.rb"
Not that this could still collide if two machines boot in the same second. I would highly recommend using the EC2 instance ID or IP address instead. You can fetch these from the metadata server. See https://github.com/coderanger/brix/blob/master/packer/client-bootstrap.sh#L26-L37 for an example.

Ruby calling AWS ELB functions

I'm writing some Ruby scripts to wrap AWS ELB command line calls, mostly so that I can act on several ELB instances simultaneously. One task is to use the elb-describe-instance-health call to see what instance IDs are attached to this ELB.
I want to match the Instance ID to a nickname we have set up for those instances, so that I can see at a glance what machines area connected to the ELB, without having to look up the instance names.
So I am issuing:
cmd = "elb-describe-instance-health #{elbName}"
value = `#{cmd}`
Passing the elb name into the call. This returns output such as:
INSTANCE_ID i-jfjtktykg InService N/A N/A
INSTANCE_ID i-ujelforos InService N/A N/A
One line appear for each instance in the ELB. There are two spaces between each field.
What I need to get is the second field, which is the actual instance ID. Basically I'm trying to get each line returned, turn it into an array, get the 2nd field, which I can then use to lookup our server nickname.
Not sure if this is the right approach, but any suggestions on how to get this done are very welcome.
The newly released aws-sdk gem supports Elastic Load Balancing (AWS::ELB). If you want to get a list of instance ids attached to your load balancer you can do the following:
AWS.config(:access_key_id => '...', :secret_access_key => '...')
elb = AWS::ELB.new
intsance_ids = elb.load_balancers['LOAD_BALANCER_NAME'].instances.collect(&:id)
You could also use EC2 to store your instance nicknames.
ec2 = AWS::EC2.new
ec2.instances['INSTANCE_ID'].tags['nickname'] = 'NICKNAME'
Assuming your instances are tagged with their nicknames, you could collect them like so:
elb = AWS::ELB.new
elb.load_balancers['LOAD_BALANCER_NAME'].instances.collect{|i| i.tags['nickname'] }
A simple way to extract the second column would be something like this:
ids = value.split("\n").collect { |line| line.split(/\s+/)[1] }
This will leave the second column values in the Array ids. All this does is breaks the value into lines, breaks each line into whitespace delimited columns, and then extracts the second column.
There's probably no need to try to be too clever for something like this, a simple and straight forward solution should be sufficient.
References:
collect
split

Resources