qb 0.1.60 → 0.1.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/qb/options.rb +6 -6
- data/lib/qb/role.rb +20 -33
- data/lib/qb/role/errors.rb +30 -0
- data/lib/qb/version.rb +1 -1
- data/library/path_facts +304 -0
- data/plugins/lookup_plugins/every.py +165 -0
- data/roles/qb.facts/defaults/main.yml +3 -0
- data/roles/{qb.yarn → qb.facts}/meta/main.yml +1 -1
- data/roles/{qb.yarn → qb.facts}/meta/qb.yml +21 -26
- data/roles/qb.facts/tasks/main.yml +10 -0
- data/roles/qb.git_repo/defaults/main.yml +1 -0
- data/roles/qb.git_repo/meta/main.yml +1 -9
- data/roles/qb.git_repo/tasks/main.yml +26 -1
- data/roles/qb.qb_role/templates/qb.yml.j2 +8 -0
- data/roles/qb.role/defaults/main.yml +1 -1
- data/roles/qb.role/tasks/main.yml +1 -1
- data/roles/qb.yarn_release/defaults/main.yml +4 -0
- data/roles/{qb.release_yarn → qb.yarn_release}/meta/main.yml +1 -1
- data/roles/{qb.release_yarn → qb.yarn_release}/meta/qb.yml +1 -1
- data/roles/qb.yarn_release/tasks/main.yml +73 -0
- data/roles/qb.yarn_setup/defaults/main.yml +11 -0
- data/roles/qb.yarn_setup/meta/main.yml +8 -0
- data/roles/qb.yarn_setup/meta/qb.yml +100 -0
- data/roles/qb.yarn_setup/tasks/distribution/MacOSX/brew_create.yml +59 -0
- data/roles/qb.yarn_setup/tasks/distribution/MacOSX/main.yml +42 -0
- data/roles/qb.yarn_setup/tasks/main.yml +11 -0
- data/roles/qb.yarn_setup/templates/yarn@M.m.p.rb.j2 +22 -0
- metadata +20 -12
- data/lib/qb/options/errors.rb +0 -11
- data/roles/qb.release_yarn/defaults/main.yml +0 -4
- data/roles/qb.release_yarn/tasks/main.yml +0 -73
- data/roles/qb.yarn/defaults/main.yml +0 -5
- data/roles/qb.yarn/tasks/distribution/MacOSX.yml +0 -7
- data/roles/qb.yarn/tasks/main.yml +0 -11
@@ -0,0 +1,165 @@
|
|
1
|
+
"""
|
2
|
+
DOCUMENTATION:
|
3
|
+
lookup: every
|
4
|
+
version_added: "QB-0.1.61"
|
5
|
+
short_description: Returns true for a key every X time delta (per host).
|
6
|
+
description:
|
7
|
+
- Returns `True` if more than a specified amount of time has passed
|
8
|
+
since it last returned `True` for that key for the current
|
9
|
+
`inventory_hostname` fact.
|
10
|
+
|
11
|
+
If it's never returned `True` for the `key` / `inventory_hostname`
|
12
|
+
combo it will.
|
13
|
+
|
14
|
+
This is useful to control updating - things like "run
|
15
|
+
`apt-get update` if it doesn't look like it's been run in a day",
|
16
|
+
etcetera.
|
17
|
+
|
18
|
+
** WARNING: NOT AT ALL THREAD / CONCURRENCY SAFE **
|
19
|
+
|
20
|
+
This is meant for things that you're *rather not* have run too
|
21
|
+
often, it is not indented for and should not be used for
|
22
|
+
controlling stuff that *must not* be run more than a certain
|
23
|
+
frequency because it's a shit-simple implementation with
|
24
|
+
**NO LOCKING / CONCURRENCY SUPPORT** so if another thread or
|
25
|
+
process is trying to do the same thing at the same time they will
|
26
|
+
potentially both return `True` or who really knows what else.
|
27
|
+
|
28
|
+
Data is stored at `~/.ansible/qb/data/every.yml`. This should
|
29
|
+
probably be configurable for for the moment it will do.
|
30
|
+
|
31
|
+
options:
|
32
|
+
key:
|
33
|
+
description:
|
34
|
+
- Required single positional argument, used as the key to
|
35
|
+
store / retrieve data.
|
36
|
+
required: True
|
37
|
+
**kwargs:
|
38
|
+
description:
|
39
|
+
- Accepts all the Python `datetime.timedelta` constructor
|
40
|
+
keywords. Requires at least one.
|
41
|
+
|
42
|
+
You can set the delta to zero (so it returns True every
|
43
|
+
call) by providing `days=0` or similar (useful to test
|
44
|
+
stuff out maybe).
|
45
|
+
required: True
|
46
|
+
EXAMPLES:
|
47
|
+
|
48
|
+
- name: Install Yarn via Homebrew, updating Homebrew at most once per day
|
49
|
+
homebrew:
|
50
|
+
name: yarn
|
51
|
+
update_homebrew: "{{ lookup('every', 'update_homebrew' days=1) }}"
|
52
|
+
|
53
|
+
RETURN:
|
54
|
+
|
55
|
+
`True` if it's been more than the provided period since the lookup returned
|
56
|
+
`True` last for this key /
|
57
|
+
|
58
|
+
"""
|
59
|
+
|
60
|
+
from __future__ import (absolute_import, division, print_function)
|
61
|
+
__metaclass__ = type
|
62
|
+
|
63
|
+
from ansible.errors import AnsibleError
|
64
|
+
from ansible.plugins.lookup import LookupBase
|
65
|
+
|
66
|
+
try:
|
67
|
+
from __main__ import display
|
68
|
+
except ImportError:
|
69
|
+
from ansible.utils.display import Display
|
70
|
+
display = Display()
|
71
|
+
|
72
|
+
from datetime import datetime, timedelta
|
73
|
+
import os
|
74
|
+
import errno
|
75
|
+
import yaml
|
76
|
+
|
77
|
+
def mkdir_p(path):
|
78
|
+
"""
|
79
|
+
Can't believe Python doesn't have this built-in...
|
80
|
+
"""
|
81
|
+
try:
|
82
|
+
os.makedirs(path)
|
83
|
+
except OSError as exc:
|
84
|
+
if exc.errno == errno.EEXIST and os.path.isdir(path):
|
85
|
+
pass
|
86
|
+
else:
|
87
|
+
raise
|
88
|
+
|
89
|
+
|
90
|
+
class LookupModule(LookupBase):
|
91
|
+
def run(self, terms, variables=None, **kwargs):
|
92
|
+
# Check args
|
93
|
+
|
94
|
+
if len(terms) != 1:
|
95
|
+
raise AnsibleError(
|
96
|
+
"Requires exacty one positional argument (key)."
|
97
|
+
)
|
98
|
+
|
99
|
+
if len(kwargs) == 0:
|
100
|
+
raise AnsibleError(
|
101
|
+
"Requires at least one Python timedelta keyword arg."
|
102
|
+
)
|
103
|
+
|
104
|
+
# Setup variables
|
105
|
+
|
106
|
+
key = terms[0]
|
107
|
+
host = variables['inventory_hostname']
|
108
|
+
|
109
|
+
data_path = os.path.join(
|
110
|
+
variables['ansible_env']['HOME'],
|
111
|
+
'.ansible',
|
112
|
+
'qb',
|
113
|
+
'data',
|
114
|
+
'every.yml'
|
115
|
+
)
|
116
|
+
|
117
|
+
delta = timedelta(**kwargs)
|
118
|
+
now = datetime.now()
|
119
|
+
|
120
|
+
# Default to empty data
|
121
|
+
data = {}
|
122
|
+
|
123
|
+
# No idea how / where to see this output...
|
124
|
+
# display.debug("Seeing if %s has been done in last %s" % (key, delta))
|
125
|
+
|
126
|
+
# Ensure the data directory exists
|
127
|
+
mkdir_p(os.path.dirname(data_path))
|
128
|
+
|
129
|
+
# Read the data file, overwriting `data` var (if file it exists)
|
130
|
+
try:
|
131
|
+
with open(data_path, 'r') as f:
|
132
|
+
data = yaml.safe_load(f)
|
133
|
+
except IOError as error:
|
134
|
+
pass
|
135
|
+
|
136
|
+
# If there's no entry for this host default to empty dict
|
137
|
+
if host not in data:
|
138
|
+
data[host] = {}
|
139
|
+
|
140
|
+
# Default `should` (our return value) to True: if it's never returned
|
141
|
+
# `True` it will now.
|
142
|
+
should = True
|
143
|
+
|
144
|
+
# If we have `data[host][key]['last']`, see if's been at least `delta`
|
145
|
+
# and set `should`
|
146
|
+
if key in data[host]:
|
147
|
+
if 'last' in data[host][key]:
|
148
|
+
should = (now - delta) >= data[host][key]['last']
|
149
|
+
else:
|
150
|
+
# Create a new dict at `data[host][key]` so we can write `now` to
|
151
|
+
# it
|
152
|
+
data[host][key] = {}
|
153
|
+
|
154
|
+
# If we're gonna return `True`, set `last` to `now` and write back
|
155
|
+
# to the path.
|
156
|
+
#
|
157
|
+
# WARNING Not at all thread / concurrency safe!
|
158
|
+
if should:
|
159
|
+
data[host][key]['last'] = now
|
160
|
+
|
161
|
+
with open(data_path, 'w') as f:
|
162
|
+
yaml.safe_dump(data, f, default_flow_style=False)
|
163
|
+
|
164
|
+
# And return our result
|
165
|
+
return should
|
@@ -1,11 +1,11 @@
|
|
1
1
|
---
|
2
|
-
# meta/qb.yml file for qb.
|
2
|
+
# meta/qb.yml file for qb.facts
|
3
3
|
#
|
4
4
|
# qb settings for this role. see README.md for more info.
|
5
5
|
#
|
6
6
|
|
7
7
|
# description of the role to show in it's help output.
|
8
|
-
description:
|
8
|
+
description: null
|
9
9
|
|
10
10
|
# prefix for role variables
|
11
11
|
var_prefix: null
|
@@ -34,39 +34,34 @@ var_prefix: null
|
|
34
34
|
# - starting at the current direcotry and climbing up to parent
|
35
35
|
# directories, use the first one that contains FILENAME. error
|
36
36
|
# if none is found.
|
37
|
-
default_dir:
|
37
|
+
default_dir: cwd
|
38
|
+
|
39
|
+
# If `true`, QB will ensure the default dir exists before starting the play.
|
40
|
+
#
|
41
|
+
# For legacy reasons, this defaults to `true` if not present, but we want to
|
42
|
+
# default declare it as `false` here so new roles can turn it on only if
|
43
|
+
# they need it.
|
44
|
+
#
|
45
|
+
mkdir: false
|
38
46
|
|
39
47
|
# default user to become for play
|
40
48
|
default_user: null
|
41
49
|
|
42
50
|
# set to false to not save options in .qb-options.yml files
|
43
|
-
save_options:
|
51
|
+
save_options: false
|
44
52
|
|
45
|
-
#
|
46
|
-
|
53
|
+
# options to pass to ansible-playbook
|
54
|
+
ansible_options: {}
|
47
55
|
|
48
|
-
options:
|
56
|
+
options:
|
49
57
|
# - name: example
|
50
58
|
# description: an example of a variable.
|
51
59
|
# required: false
|
52
60
|
# type: boolean # boolean (default) | string
|
53
61
|
# short: e
|
54
|
-
- name:
|
55
|
-
description:
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
description: >
|
61
|
-
present to install, absent to uninstall. the rest of the options are up to
|
62
|
-
you to much around with if you like.
|
63
|
-
see:
|
64
|
-
- http://docs.ansible.com/ansible/homebrew_module.html
|
65
|
-
type:
|
66
|
-
one_of:
|
67
|
-
- present
|
68
|
-
- absent
|
69
|
-
- latest
|
70
|
-
- head
|
71
|
-
- linked
|
72
|
-
- unlinked
|
62
|
+
- name: github_api
|
63
|
+
description: >-
|
64
|
+
If path is a git repo with a GitHub origin, contact the GitHub API for
|
65
|
+
additonal facts (including privacy status).
|
66
|
+
type: boolean
|
67
|
+
short: g
|
@@ -1,12 +1,4 @@
|
|
1
1
|
---
|
2
2
|
# meta file for qb.git_repo
|
3
3
|
|
4
|
-
dependencies:
|
5
|
-
- role: qb.gitignore
|
6
|
-
gitignore_name: Global/macOS
|
7
|
-
gitignore_dest: "{{ git_repo_dest }}"
|
8
|
-
when: ansible_distribution == "MacOSX"
|
9
|
-
|
10
|
-
- role: qb.gitignore
|
11
|
-
gitignore_name: QB
|
12
|
-
gitignore_dest: "{{ git_repo_dest }}"
|
4
|
+
dependencies: []
|
@@ -6,4 +6,29 @@
|
|
6
6
|
args:
|
7
7
|
chdir: "{{ git_repo_dest }}"
|
8
8
|
creates: "{{ git_repo_dest }}/.git"
|
9
|
-
|
9
|
+
|
10
|
+
- name: Tell Git to ignore OSX artifacts
|
11
|
+
when: ansible_distribution == "MacOSX"
|
12
|
+
include_role:
|
13
|
+
name: qb.gitignore
|
14
|
+
vars:
|
15
|
+
gitignore_name: Global/macOS
|
16
|
+
gitignore_dest: "{{ git_repo_dest }}"
|
17
|
+
|
18
|
+
- name: Tell Git to ignore QB artifacts
|
19
|
+
include_role:
|
20
|
+
name: qb.gitignore
|
21
|
+
vars:
|
22
|
+
gitignore_name: QB
|
23
|
+
gitignore_dest: "{{ git_repo_dest }}"
|
24
|
+
|
25
|
+
- name: >-
|
26
|
+
Tell Git to ignore each of <git_repo_gitignores>
|
27
|
+
with_items: "{{ git_repo_gitignores }}"
|
28
|
+
loop_control:
|
29
|
+
loop_var: name
|
30
|
+
include_role:
|
31
|
+
name: qb.gitignore
|
32
|
+
vars:
|
33
|
+
gitignore_name: "{{ name }}"
|
34
|
+
gitignore_dest: "{{ git_repo_dest }}"
|
@@ -36,6 +36,14 @@ var_prefix: null
|
|
36
36
|
# if none is found.
|
37
37
|
default_dir: null
|
38
38
|
|
39
|
+
# If `true`, QB will ensure the default dir exists before starting the play.
|
40
|
+
#
|
41
|
+
# For legacy reasons, this defaults to `true` if not present, but we want to
|
42
|
+
# default declare it as `false` here so new roles can turn it on only if
|
43
|
+
# they need it.
|
44
|
+
#
|
45
|
+
mkdir: false
|
46
|
+
|
39
47
|
# default user to become for play
|
40
48
|
default_user: null
|
41
49
|
|
@@ -0,0 +1,73 @@
|
|
1
|
+
---
|
2
|
+
# tasks file for qb.yarn_release
|
3
|
+
|
4
|
+
- name: load package.json
|
5
|
+
include_vars:
|
6
|
+
file: "{{ yarn_release_package_dir }}/package.json"
|
7
|
+
name: yarn_release_package_json
|
8
|
+
|
9
|
+
- name: get current version
|
10
|
+
set_fact:
|
11
|
+
yarn_release_current_version: "{{ yarn_release_package_json.version }}"
|
12
|
+
|
13
|
+
- name: create release version
|
14
|
+
set_fact:
|
15
|
+
yarn_release_release_version: >-
|
16
|
+
{{ yarn_release_current_version | semver_inc(yarn_release_level) }}
|
17
|
+
|
18
|
+
- name: >
|
19
|
+
increment to version {{ yarn_release_release_version }}
|
20
|
+
and create the git tag
|
21
|
+
command: "yarn version --new-version={{ yarn_release_release_version }}"
|
22
|
+
args:
|
23
|
+
chdir: "{{ yarn_release_package_dir }}"
|
24
|
+
|
25
|
+
- name: >
|
26
|
+
git push the v{{ yarn_release_release_version }} tag
|
27
|
+
command: "git push origin v{{ yarn_release_release_version }}"
|
28
|
+
args:
|
29
|
+
chdir: "{{ yarn_release_package_dir }}"
|
30
|
+
|
31
|
+
- name: >
|
32
|
+
npm publish v{{ yarn_release_release_version }}
|
33
|
+
command: npm publish
|
34
|
+
args:
|
35
|
+
chdir: "{{ yarn_release_package_dir }}"
|
36
|
+
|
37
|
+
- name: create the next -dev version
|
38
|
+
set_fact:
|
39
|
+
yarn_release_next_version: "{{
|
40
|
+
yarn_release_release_version | semver_inc(
|
41
|
+
level='prerelease',
|
42
|
+
preid='dev'
|
43
|
+
)
|
44
|
+
}}"
|
45
|
+
|
46
|
+
- name: >
|
47
|
+
increment to {{ yarn_release_next_version }} version
|
48
|
+
command: >
|
49
|
+
yarn version
|
50
|
+
--new-version={{ yarn_release_next_version }}
|
51
|
+
--no-git-tag-version
|
52
|
+
args:
|
53
|
+
chdir: "{{ yarn_release_package_dir }}"
|
54
|
+
|
55
|
+
- name: git add package.json
|
56
|
+
command: git add package.json
|
57
|
+
args:
|
58
|
+
chdir: "{{ yarn_release_package_dir }}"
|
59
|
+
|
60
|
+
- name: >
|
61
|
+
git commit next dev version
|
62
|
+
command: git commit -m "start {{ yarn_release_next_version }}"
|
63
|
+
args:
|
64
|
+
chdir: "{{ yarn_release_package_dir }}"
|
65
|
+
|
66
|
+
- name: git push next dev version
|
67
|
+
command: git push
|
68
|
+
args:
|
69
|
+
chdir: "{{ yarn_release_package_dir }}"
|
70
|
+
|
71
|
+
- debug:
|
72
|
+
msg: >
|
73
|
+
v{{ yarn_release_release_version }} released.
|
@@ -0,0 +1,11 @@
|
|
1
|
+
---
|
2
|
+
# defaults file for qb.yarn_setup
|
3
|
+
yarn_setup_version: null
|
4
|
+
yarn_setup_state: present
|
5
|
+
yarn_setup_global_packages: []
|
6
|
+
|
7
|
+
yarn_setup_force: false
|
8
|
+
|
9
|
+
yarn_setup_brew_create: true
|
10
|
+
yarn_setup_brew_tap: "{{ qb_git_user_name }}/versions"
|
11
|
+
yarn_setup_brew_link: true
|