saltstack / salt

Software to automate the management and configuration of any infrastructure or application at scale. Install Salt from the Salt package repositories here:
https://docs.saltproject.io/salt/install-guide/en/latest/
Apache License 2.0
14.19k stars 5.48k forks source link

boto_route53 state doesn't create a record #27374

Closed mool closed 9 years ago

mool commented 9 years ago

I have a state to create a DNS record for a minion

dns-record:
  boto_route53.present:
    - name: {{ grains['id'] }}.example.com.
    - value: {{ grains['ip4_interfaces']['eth0'][0] }}
    - zone: example.com.
    - ttl: 60
    - record_type: A
    - region: us-east-1
    - keyid: {{pillar['route53']['keyid']}}
    - key: {{pillar['route53']['key']}}

When I run the state, i don't get any error but it doesn't make any changes and the record isn't created.

----------
          ID: dns-record
    Function: boto_route53.present
        Name: minion.example.com.
      Result: True
     Comment:
     Started: 17:38:39.910178
    Duration: 0.714 ms
     Changes:

I have tried with different IAM permissions and using IAM instance roles, but always is the same.

salt-minion --version
salt-minion 2015.5.3 (Lithium)
jfindlay commented 9 years ago

@mool, thanks for the report.

rallytime commented 9 years ago

@mool Is it possible for you to look at the debug logs to see if there is anything in there that might offer a clue to what is happening here?

mool commented 9 years ago

@rallytime here are the debug logs...

root@minion:~# salt-call state.sls hostname.route53 --log-level=debug
[DEBUG   ] Reading configuration from /etc/salt/minion
[DEBUG   ] Including configuration from '/etc/salt/minion.d/99-keepalive.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/99-keepalive.conf
[DEBUG   ] Including configuration from '/etc/salt/minion.d/99-master-address.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/99-master-address.conf
[DEBUG   ] Including configuration from '/etc/salt/minion.d/_schedule.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/_schedule.conf
[DEBUG   ] Including configuration from '/etc/salt/minion.d/mine.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/mine.conf
[DEBUG   ] Using cached minion ID from /etc/salt/minion_id: minion.example.com
[DEBUG   ] Configuration file path: /etc/salt/minion
[DEBUG   ] Reading configuration from /etc/salt/minion
[DEBUG   ] Including configuration from '/etc/salt/minion.d/99-keepalive.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/99-keepalive.conf
[DEBUG   ] Including configuration from '/etc/salt/minion.d/99-master-address.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/99-master-address.conf
[DEBUG   ] Including configuration from '/etc/salt/minion.d/_schedule.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/_schedule.conf
[DEBUG   ] Including configuration from '/etc/salt/minion.d/mine.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/mine.conf
[DEBUG   ] Initializing new SAuth for ('/etc/salt/pki/minion', 'minion.example.com', 'tcp://10.100.1.201:4506')
[DEBUG   ] Decrypting the current master AES key
[DEBUG   ] Loaded minion key: /etc/salt/pki/minion/minion.pem
[DEBUG   ] Loaded minion key: /etc/salt/pki/minion/minion.pem
[DEBUG   ] LazyLoaded jinja.render
[DEBUG   ] LazyLoaded yaml.render
[DEBUG   ] LazyLoaded state.sls
[DEBUG   ] LazyLoaded saltutil.is_running
[DEBUG   ] LazyLoaded grains.get
[DEBUG   ] Re-using SAuth for ('/etc/salt/pki/minion', 'minion.example.com', 'tcp://10.100.1.201:4506')
[DEBUG   ] Reading configuration from /etc/salt/minion
[DEBUG   ] Including configuration from '/etc/salt/minion.d/99-keepalive.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/99-keepalive.conf
[DEBUG   ] Including configuration from '/etc/salt/minion.d/99-master-address.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/99-master-address.conf
[DEBUG   ] Including configuration from '/etc/salt/minion.d/_schedule.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/_schedule.conf
[DEBUG   ] Including configuration from '/etc/salt/minion.d/mine.conf'
[DEBUG   ] Reading configuration from /etc/salt/minion.d/mine.conf
[DEBUG   ] Re-using SAuth for ('/etc/salt/pki/minion', 'minion.example.com', 'tcp://10.100.1.201:4506')
[DEBUG   ] Loaded minion key: /etc/salt/pki/minion/minion.pem
[INFO    ] Loading fresh modules for state activity
[DEBUG   ] LazyLoaded jinja.render
[DEBUG   ] LazyLoaded yaml.render
[DEBUG   ] LazyLoaded gpg.render
[DEBUG   ] Fetching file from saltenv 'base', ** attempting ** 'salt://hostname/route53.sls'
[INFO    ] Fetching file from saltenv 'base', ** done ** 'hostname/route53.sls'
[DEBUG   ] LazyLoaded cmd.run
[DEBUG   ] Jinja search path: ['/var/cache/salt/minion/files/base']
[DEBUG   ] Rendered data from file: /var/cache/salt/minion/files/base/hostname/route53.sls:
dns-record:
  boto_route53.present:
    - name: minion.example.com.
    - value: 10.100.1.226
    - zone: example.com.
    - ttl: 60
    - record_type: A
    - region: us-east-1
    - keyid: XXXXXXXXXXXXXXXXXXXX
    - key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

[DEBUG   ] LazyLoaded config.get
[DEBUG   ] Results of YAML rendering:
OrderedDict([('dns-record', OrderedDict([('boto_route53.present', [OrderedDict([('name', 'minion.example.com.')]), OrderedDict([('value', '10.100.1.226')]), OrderedDict([('zone', 'example.com.')]), OrderedDict([('ttl', 60)]), OrderedDict([('record_type', 'A')]), OrderedDict([('region', 'us-east-1')]), OrderedDict([('keyid', 'XXXXXXXXXXXXXXXXXXXX')]), OrderedDict([('key', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')])])]))])
[DEBUG   ] Reading GPG keys from: /etc/salt/gpgkeys
[DEBUG   ] ['gpg', '--status-fd', '2', '--no-tty', '--homedir', '/etc/salt/gpgkeys', '--version']
[DEBUG   ] stderr reader: <Thread(Thread-1, initial daemon)>
[DEBUG   ] stdout reader: <Thread(Thread-2, initial daemon)>
[DEBUG   ] chunk: 'gpg (GnuPG) 1.4.16\nCopyright (C) 2013 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permit'
[DEBUG   ] LazyLoaded boto_route53.get_record
[DEBUG   ] LazyLoaded boto_route53.present
[INFO    ] Running state [minion.example.com.] at time 19:24:09.832944
[INFO    ] Executing state boto_route53.present for minion.example.com.
[INFO    ] No changes made for minion.example.com.
[INFO    ] Completed state [minion.example.com.] at time 19:24:09.833640
[DEBUG   ] File /var/cache/salt/minion/accumulator/140159078215056 does not exist, no need to cleanup.
[DEBUG   ] LazyLoaded config.option
[DEBUG   ] Re-using SAuth for ('/etc/salt/pki/minion', 'minion.example.com', 'tcp://10.100.1.201:4506')
[DEBUG   ] LazyLoaded highstate.output
local:
----------
          ID: dns-record
    Function: boto_route53.present
        Name: minion.example.com.
      Result: True
     Comment:
     Started: 19:24:09.832944
    Duration: 0.696 ms
     Changes:

Summary
------------
Succeeded: 1
Failed:    0
------------
Total states run:     1
jbouse commented 9 years ago

Are you sure you have python-boto installed on the minion you're executing the state on? Looking at the debug log you submitted I don't see anything that indicates it actually tried to check route53... I only have my logs on INFO and I get the following when I run my route53.present entry:

2015-10-07 20:41:39,888 [salt.state       ][INFO    ][28988] Running state [secure.example.net] at time 20:41:39.887492
2015-10-07 20:41:39,888 [salt.state       ][INFO    ][28988] Executing state boto_route53.present for secure.example.net
2015-10-07 20:41:40,238 [salt.state       ][INFO    ][28988] secure.example.net exists.
2015-10-07 20:41:40,238 [salt.state       ][INFO    ][28988] Completed state [secure.example.net] at time 20:41:40.238257
2015-10-07 20:41:40,239 [salt.state       ][INFO    ][28988] Running state [secure.example.com] at time 20:41:40.238491
2015-10-07 20:41:40,239 [salt.state       ][INFO    ][28988] Executing state boto_route53.present for secure.example.com
2015-10-07 20:41:40,522 [salt.state       ][INFO    ][28988] secure.example.com exists.
2015-10-07 20:41:40,523 [salt.state       ][INFO    ][28988] Completed state [secure.example.com] at time 20:41:40.522483

That is from my state file which reads:

secure_net_a_record:
  boto_route53.present:
    - name: secure.example.net
    - value: {{ ipaddr }}
    - zone: example.net.
    - ttl: 300
    - record_type: A
    - profile: my_aws_profile

secure_com_a_record:
  boto_route53.present:
    - name: secure.example.com
    - value: {{ ipaddr }}
    - zone: example.com.
    - ttl: 300
    - record_type: A
    - profile: my_aws_profile
mool commented 9 years ago

@jbouse yes, I have python-boto installed. I've also tried with a wrong key and keyid to see if I get any authentication error, but it's the same... nothing happens

jbouse commented 9 years ago

@mool is the keyid and key jinja templating a typo? I noticed that there isn't spaces around it..

dns-record:
  boto_route53.present:
    - name: {{ grains['id'] }}.example.com.
    - value: {{ grains['ip4_interfaces']['eth0'][0] }}
    - zone: example.com.
    - ttl: 60
    - record_type: A
    - region: us-east-1
    - keyid: {{pillar['route53']['keyid']}}
    - key: {{pillar['route53']['key']}}

as opposed to

dns-record:
  boto_route53.present:
    - name: {{ grains['id'] }}.example.com.
    - value: {{ grains['ip4_interfaces']['eth0'][0] }}
    - zone: example.com.
    - ttl: 60
    - record_type: A
    - region: us-east-1
    - keyid: {{ pillar['route53']['keyid'] }}
    - key: {{ pillar['route53']['key'] }}

My own route53 state contains:

r53_a_record:
  boto_route53.present:
    - name: {{ grains.id }}
    - value: {{ grains.ip_interfaces['eth0'][0] }}
    - zone: {{ grains.domain }}.
    - ttl: 300
    - record_type: A
    - profile: my_aws_profile

Then in my pillar I have:

my_aws_profile:
  keyid: xxxxxxxxxxxxxxxxxxxx
  key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  region: us-east-1
rallytime commented 9 years ago

@mool I can reproduce this when invalid credentials are used. The call to get the boto_route53 record on the 2015.8 branch has been refactored to throw a SaltInvocationError when invalid credentials are used, but the same call on 2015.5 just returns None, which allows the function to continue onward. If errors aren't hit, the state, incorrectly returns True.

Here's my reproduction of your bug:

local:
----------
          ID: dns-record
    Function: boto_route53.present
        Name: rallytime.example.com.
      Result: True
     Comment:
     Started: 17:10:08.077883
    Duration: 1005.306 ms
     Changes:

Summary
------------
Succeeded: 1
Failed:    0
------------
Total states run:     1

And here's what it looks like when we check to see if the record returns None:

local:
----------
          ID: dns-record
    Function: boto_route53.present
        Name: rallytime.example.com.
      Result: False
     Comment: Error: Something went wrong getting the record. Check your credentials.
     Started: 17:12:45.257608
    Duration: 1006.383 ms
     Changes:

Summary
------------
Succeeded: 0
Failed:    1
------------
Total states run:     1

I've fixed the bug in 2015.5 with #28213 to return False if a record isn't found (like the example right above this paragraph). In 2015.8, if invalid credentials are passed, the SaltInvocationError displays a stacktrace. I've cleaned up this stacktrace with #28214 on the 2015.8 branch.

Given this information, is it alright if we close this once the pull requests are merged?

rallytime commented 9 years ago

Since the fixes mentioned above were merged, I'm going to close this. If this pops up again, please leave a comment and we will be happy to take another look. Thanks!