How to associate floating IP to a port using openstacksdk? - openstacksdk

I am programming openstack operations using openstacksdk. I was taking reference from this link. I have to achieve below using openstacksdk:
#openstack floating ip set --port <port ID> <FIP>
But am not able to find any functions described in openstasksdk.

I did not find any straight forward sdk library for this. But I achieved using below:
create_stack(name, tags=None, template_file=None, template_url=None, template_object=None, files=None, rollback=True, wait=False, timeout=3600, environment_files=None, **parameters)
and HOT:
heat_template_version: 2013-05-23
parameters:
ingress_fip_id:
type: string
description: Floating ip address ID to associate it with ingress port.
ingress_port_id:
type: string
description: ingress port ID.
resources:
associate_fip:
type: OS::Neutron::FloatingIPAssociation
properties:
floatingip_id: { get_param: ingress_fip_id }
port_id: { get_param: ingress_port_id }

Related

Get attribute of EC2 created via LaunchConfiguration

I would like to get the PrivateIP attribute of EC2s that i create via LaunchConfiguration.
I need that attribute so that i can assign a type A dns record to the instance for other purposes.
Here is my code:
Resources:
webLaunchConfig:
Type: 'AWS::AutoScaling::LaunchConfiguration'
Properties:
ImageId: !Ref webEc2AMI
InstanceType: !Ref ec2WebInstanceType
SecurityGroups: !Ref webEc2SG
UserData:
'Fn::Base64': !Sub >
#!/bin/bash -xe
apt update -y
dnsWebServerName:
Type: 'AWS::Route53::RecordSet'
Properties:
HostedZoneId: !Ref hostedZoneId
Comment: DNS name for my db server.
Name: !Ref dnsWebServerNamePar
Type: A
TTL: '900'
ResourceRecords:
- !GetAtt webLaunchConfig.PrivateIp
... and when i try to launch it i get this error:
Template contains errors.: Template error: resource webLaunchConfig
does not support attribute type PrivateIp in Fn::GetAtt
... indicating me that what i am trying to do is not supported. Though there must be a way to achieve this.
Do you know how to do it? Or a workaround for this?
Sadly you can't do this. AWS::AutoScaling::LaunchConfiguration is only a blueprint of an instance to be launched. Thus it does not provide information about instance PrivateIp. The get the PrivateIp you have to actually launch the instance.
To do so you have to use AWS::EC2::Instance. However AWS::EC2::Instance does not support launching from ``AWS::AutoScaling::LaunchConfiguration. So either you have to change your LaunchConfigurationintoLaunchTemplateor just create instance directly usingAWS::EC2::Instance` rather then any templates.

CloudFormation - DHCPOptions - Array of DomainNameServers doesn't maintain order

I have a DHCPOptions defined in my CloudFormation template as so:
DhcpOptionSet:
Type: AWS::EC2::DHCPOptions
DependsOn:
- DnsInstance
- DnsSecondaryInstance
Properties:
DomainName: test.local
DomainNameServers:
- !GetAtt DnsInstance.PrivateIp
- !GetAtt DnsSecondaryInstance.PrivateIp
- AmazonProvidedDNS
Tags:
- Key: Name
Value: test-option-set
However, when CF creates the DHCP OptionSet, the order of the Name Servers doesn't match what I've defined in the template. It seems that no matter what order I put them in for my template, they end up as:
DnsSecondaryInstance.PrivateIp,AmazonProvidedDNS,DnsInstance.PrivateIp
This causes the resolv.conf on servers to be in the wrong order.
Is there anyway to ensure the ordering of the OptionSet?
What worked for me was to specify the list of DNS address as a comma separated list. The technique is described in the description of the DomainNameServers parameter under https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html which states:
If specifying more than one domain name server, specify the IP addresses in a single parameter, separated by commas.
To be more specific, assuming the DNS IP addresses are 10.10.0.1, 10.10.0.2, 10.10.0.3.
Properties:
DomainNameServers:
- 10.10.0.1, 10.10.0.2, 10.10.0.3

Specify HostedZone NameServers as CloudFormation Outputs

I am creating a CFN stack for a number of domains. The domain are not with the AWS registry, but a third-party one.
I want to have the list of nameservers from the SOA as part of the stack Outputs. However, as they aren't returned as a string but, according to the docs, a "set", I can't figure out how to extract and return them.
Details:
According to the docs for AWS::Route53::HostedZone, you can obtain the list of nameservers with
Return Values
[...]
Fn::GetAtt
Fn::GetAtt returns a value for a specified attribute of this type. The
following are the available attributes and sample return values.
NameServers
Returns the **set** of name servers for the specific hosted zone. For example: ns1.example.com.
This attribute is not supported for private hosted zones.
So, I tried to do:
Resources:
MyZone:
Type: 'AWS::Route53::HostedZone'
Properties:
Name: my.domain.
...
Outputs:
MyZone:
Value: !Ref MyZone
MyZoneServers:
Value: !GetAtt MyZone.NameServers
but that gives:
An error occurred (ValidationError) when calling the UpdateStack operation: Template format error: The Value field of every Outputs member must evaluate to a String.
When I only output the zone ref, it works just fine and get the Z... string for the zone.
I've tried various other tricks and approaches, mostly with various intrinsic functions such as !Split, !Select, etc. Nowhere can I seem to find what this "set" is: a list? a comma-separated string? (in which case !Split should work)
I could retrieve the nameservers via the describe function of Route53 after the stack is created, but my feeling is that I'm missing something totally obvious so don't want to add that extra step.
The set of nameservers is an array of strings. In order to output it you need to use !Join like this:
Resources:
MyZone:
Type: 'AWS::Route53::HostedZone'
Properties:
Name: my.domain.
...
Outputs:
MyZone:
Value: !Ref MyZone
MyZoneServers:
Value: !Join [',', !GetAtt MyZone.NameServers] # or any other delimiter that suits you
You should see the following Outputs:

Add AWS::Route53::RecordSet DnsRecord to a serverless Cloudfront Distribution

I found this on how to associate a route53 dns record with a S3 bucket in a serverless.yml file.
I've tried to adapt that to the case of deploying a cloudfront distrib
DnsRecord:
Type: "AWS::Route53::RecordSet"
Properties:
AliasTarget:
DNSName: <cloudfrontdistribution id>
HostedZoneId: Z21DNDUVLTQW6Q
HostedZoneName: ${self:custom.appFQDN}.
Name:
Ref: WebAppCloudFrontDistribution
Type: 'CNAME'
but am struggling with how to get the distribution id as a ref rather than a fixed string.
How would I do this?
To set up an AliasTarget, you actually just need to provide the CloudFront DNS name for the DNSName parameter, not the distribution ID. You can do this with:
!GetAtt WebAppCloudFrontDistribution.DomainName
I'm assuming that WebAppCloudFrontDistribution is the logical ID of an AWS::CloudFront::Distribution resource in your template and not a parameter. If this is actually a parameter, just set the value of the parameter to the DNS name listed for the distribution in the AWS console dashboard for CloudFront.
There are some other things you'll need to fix in your template:
HostedZoneName should be the name of the Route53 hosted zone, not the FQDN you want to use. Personally, I prefer to use the HostedZoneId property for AWS::Route53::RecordSet resources instead since it's clearer what the meaning of this property is, but to each their own. (Note: HostedZoneId property for the AWS::Route53::RecordSet resource should be the HostedZoneId for YOUR hosted zone, not the same value as the AliasTarget HostedZoneId.)
Name should be the DNS name that you want to be a CNAME for the CloudFront distribution resource.
I know it's a bit weird, but with alias targets, you have to set the type to either "A" (for IPv4) or "AAAA" (IPv6). I recommend doing both - you can do this by creating a duplicate of your AWS::Route53::RecordSet resource but set type to "AAAA" instead of "A".
Finally, note that in order for this to work, you will also need to make sure to add the FQDN as an alternate name for the CloudFront distribution resource - you can set this using the "Aliases" property of the "DistributionConfig" property of the distribution resource in your template, or by configuring this manually for the distribution settings in the AWS console if you're not creating the resource in this template.
I struggled to create a AWS::Route53::RecordSet with CloudFormation producing unspecific, unhelpful error messages of the type "The resource failed to create". The key for me was to use HostedZoneId rather than HostedZoneName to specify the parent "hosted zone". This is what I ended up with:
NaaaaaComDNSEntry:
Type: 'AWS::Route53::RecordSet'
DependsOn: NaaaaaComCloudFront
Properties:
AliasTarget:
DNSName: !GetAtt NaaaaaComCloudFront.DomainName
# For CloudFront, HostedZoneId is always Z2FDTNDATAQYW2, see:
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget.html#cfn-route53-aliastarget-hostedzoneid
HostedZoneId: Z2FDTNDATAQYW2
# HostedZoneId is for ID for 'naaaaa.com.'; In theory its valid to use `HostedZoneName` OR `HostedZoneId`
# but in practice the recordset always failed to create if I used `HostedZoneName`
HostedZoneId: ZABCDEFGHIJK5M
Name: 'www.naaaaa.com.'
Type: 'A'
This is what my working config looks like in serverless templates:
DnsRecord:
Type: "AWS::Route53::RecordSet"
Properties:
AliasTarget:
DNSName:
Fn::GetAtt:
- CloudFrontDistribution
- DomainName
# Looks like it is always the same for CloudFront distribs.
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget.html
# https://docs.aws.amazon.com/general/latest/gr/rande.html#cf_region
HostedZoneId: ${self:custom.zoneId}
HostedZoneName: ${self:custom.secondLevelDomain}.
Name: ${self:custom.appFQDN}
Type: 'A'
And
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
...
Aliases:
- ${self:custom.appFQDN}
Also courtesy of an example by Tom McLaughlin:
https://github.com/ServerlessOpsIO/serverless-zombo.com/blob/master/serverless.yml

logstash access with readonly rest plugin

we have a problem with the readonly rest plugin for elasticsearch: we don't get logstash running when the plugin is enabled. We use logstash with filebeat. Can this be the problem? The logstash config is below.
The error message:
[401] Forbidden {:class=>"Elasticsearch::Transport::Transport::Errors::Unauthorized", :level=>:error}
In elasticsearch we have defined the roles as you see below.
readonlyrest:
enable: true
response_if_req_forbidden: <h1>Forbidden</h1>
access_control_rules:
- name: Developer (reads only logstash indices, but can create new charts/dashboards)
auth_key: dev:dev
type: allow
kibana_access: ro+
indices: ["<no-index>", ".kibana*", "logstash*", "default"]
- name: Kibana Server (we trust this server side component, full access granted via HTTP authentication)
auth_key: admin:passwd1
type: allow
- name: "Logstash can write and create its own indices"
auth_key: logstash:logstash
type: allow
actions: ["cluster:*", "indices:data/read/*","indices:data/write/*","indices:admin/*"]
indices: ["logstash*", "filebeat-*", "<no_index>"]
the logstash config:
output{
elasticsearch {
hosts => ["localhost:9200"]
manage_template => true
index => "%{[#metadata][beat]}-%{+YYYY.MM.dd}"
document_type => "%{[#metadata][type]}"
document_id => "%{fingerprint}"
user => ["logstash"]
password => ["logstash"]
}
}
I believe you are not giving logstash the ability to create indexes with your setup. It can write and read, but I am not seeing create.
From the example of the website, can you change your logstash config to:
- name: "Logstash can write and create its own indices"
auth_key: logstash:logstash
type: allow
actions: ["indices:data/read/*","indices:data/write/*","indices:admin/template/*","indices:admin/create"]
indices: ["logstash-*", "<no_index>"]
This setup works for me.
I don't think it has anything to do with filebeat since the output doesn't actually talk to filebeat anymore? But then again, I am using file inputs instead.
Hope that solves the issue.
Artur