Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
ansible
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
ansible
Commits
03f93e0f
Commit
03f93e0f
authored
Mar 16, 2014
by
Michael DeHaan
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'homebrew_cask' of
git://github.com/danieljaouen/ansible
into devel
parents
1a90890f
911a3930
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
513 additions
and
0 deletions
+513
-0
library/packaging/homebrew_cask
+513
-0
No files found.
library/packaging/homebrew_cask
0 → 100644
View file @
03f93e0f
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2013, Daniel Jaouen <dcj24@cornell.edu>
#
# This module is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION
=
'''
---
module
:
homebrew_cask
author
:
Daniel
Jaouen
short_description
:
Install
/
uninstall
homebrew
casks
.
description
:
-
Manages
Homebrew
casks
.
version_added
:
"1.5"
options
:
name
:
description
:
-
name
of
cask
to
install
/
remove
required
:
true
state
:
description
:
-
state
of
the
cask
choices
:
[
'
installed
'
,
'
uninstalled
'
]
required
:
false
default
:
present
'''
EXAMPLES
=
'''
-
homebrew_cask
:
name
=
alfred
state
=
present
-
homebrew_cask
:
name
=
alfred
state
=
absent
'''
import
os
.
path
import
re
# exceptions -------------------------------------------------------------- {{{
class
HomebrewCaskException
(
Exception
)
:
pass
# /exceptions ------------------------------------------------------------- }}}
# utils ------------------------------------------------------------------- {{{
def
_create_regex_group
(
s
)
:
lines
=
(
line
.
strip
()
for
line
in
s
.
split
(
'\n'
)
if
line
.
strip
())
chars
=
filter
(
None
,
(
line
.
split
(
'#'
)[
0
].
strip
()
for
line
in
lines
))
group
=
r
'
[
^
'
+
r
''
.
join
(
chars
)
+
r
']'
return
re
.
compile
(
group
)
# /utils ------------------------------------------------------------------ }}}
class
HomebrewCask
(
object
)
:
'''
A
class
to
manage
Homebrew
casks
.
'''
# class regexes ------------------------------------------------ {{{
VALID_PATH_CHARS
=
r
'''
\
w
#
alphanumeric
characters
(
i
.
e
.,
[
a
-
zA
-
Z0
-
9
_
])
\
s
#
spaces
:
#
colons
{
sep
}
#
the
OS
-
specific
path
separator
-
#
dashes
'''
.
format
(
sep
=
os
.
path
.
sep
)
VALID_BREW_PATH_CHARS
=
r
'''
\
w
#
alphanumeric
characters
(
i
.
e
.,
[
a
-
zA
-
Z0
-
9
_
])
\
s
#
spaces
{
sep
}
#
the
OS
-
specific
path
separator
-
#
dashes
'''
.
format
(
sep
=
os
.
path
.
sep
)
VALID_CASK_CHARS
=
r
'''
\
w
#
alphanumeric
characters
(
i
.
e
.,
[
a
-
zA
-
Z0
-
9
_
])
-
#
dashes
'''
INVALID_PATH_REGEX
=
_create_regex_group
(
VALID_PATH_CHARS
)
INVALID_BREW_PATH_REGEX
=
_create_regex_group
(
VALID_BREW_PATH_CHARS
)
INVALID_CASK_REGEX
=
_create_regex_group
(
VALID_CASK_CHARS
)
# /class regexes ----------------------------------------------- }}}
# class validations -------------------------------------------- {{{
@classmethod
def
valid_path
(
cls
,
path
)
:
'''
`
path
`
must
be
one
of
:
-
list
of
paths
-
a
string
containing
only
:
-
alphanumeric
characters
-
dashes
-
spaces
-
colons
-
os
.
path
.
sep
'''
if
isinstance
(
path
,
basestring
)
:
return
not
cls
.
INVALID_PATH_REGEX
.
search
(
path
)
try
:
iter
(
path
)
except
TypeError
:
return
False
else
:
paths
=
path
return
all
(
cls
.
valid_brew_path
(
path_
)
for
path_
in
paths
)
@classmethod
def
valid_brew_path
(
cls
,
brew_path
)
:
'''
`
brew_path
`
must
be
one
of
:
-
None
-
a
string
containing
only
:
-
alphanumeric
characters
-
dashes
-
spaces
-
os
.
path
.
sep
'''
if
brew_path
is
None
:
return
True
return
(
isinstance
(
brew_path
,
basestring
)
and
not
cls
.
INVALID_BREW_PATH_REGEX
.
search
(
brew_path
)
)
@classmethod
def
valid_cask
(
cls
,
cask
)
:
'''
A
valid
cask
is
either
None
or
alphanumeric
+
backslashes
.
'''
if
cask
is
None
:
return
True
return
(
isinstance
(
cask
,
basestring
)
and
not
cls
.
INVALID_CASK_REGEX
.
search
(
cask
)
)
@classmethod
def
valid_state
(
cls
,
state
)
:
'''
A
valid
state
is
one
of
:
-
installed
-
absent
'''
if
state
is
None
:
return
True
else
:
return
(
isinstance
(
state
,
basestring
)
and
state
.
lower
()
in
(
'
installed
'
,
'
absent
'
,
)
)
@classmethod
def
valid_module
(
cls
,
module
)
:
'''
A
valid
module
is
an
instance
of
AnsibleModule
.
'''
return
isinstance
(
module
,
AnsibleModule
)
# /class validations ------------------------------------------- }}}
# class properties --------------------------------------------- {{{
@property
def
module
(
self
)
:
return
self
.
_module
@module
.
setter
def
module
(
self
,
module
)
:
if
not
self
.
valid_module
(
module
)
:
self
.
_module
=
None
self
.
failed
=
True
self
.
message
=
'
Invalid
module
:
{
0
}.
'
.
format
(
module
)
raise
HomebrewCaskException
(
self
.
message
)
else
:
self
.
_module
=
module
return
module
@property
def
path
(
self
)
:
return
self
.
_path
@path
.
setter
def
path
(
self
,
path
)
:
if
not
self
.
valid_path
(
path
)
:
self
.
_path
=
[]
self
.
failed
=
True
self
.
message
=
'
Invalid
path
:
{
0
}.
'
.
format
(
path
)
raise
HomebrewCaskException
(
self
.
message
)
else
:
if
isinstance
(
path
,
basestring
)
:
self
.
_path
=
path
.
split
(
':'
)
else
:
self
.
_path
=
path
return
path
@property
def
brew_path
(
self
)
:
return
self
.
_brew_path
@brew
_path
.
setter
def
brew_path
(
self
,
brew_path
)
:
if
not
self
.
valid_brew_path
(
brew_path
)
:
self
.
_brew_path
=
None
self
.
failed
=
True
self
.
message
=
'
Invalid
brew_path
:
{
0
}.
'
.
format
(
brew_path
)
raise
HomebrewCaskException
(
self
.
message
)
else
:
self
.
_brew_path
=
brew_path
return
brew_path
@property
def
params
(
self
)
:
return
self
.
_params
@params
.
setter
def
params
(
self
,
params
)
:
self
.
_params
=
self
.
module
.
params
return
self
.
_params
@property
def
current_cask
(
self
)
:
return
self
.
_current_cask
@current
_cask
.
setter
def
current_cask
(
self
,
cask
)
:
if
not
self
.
valid_cask
(
cask
)
:
self
.
_current_cask
=
None
self
.
failed
=
True
self
.
message
=
'
Invalid
cask
:
{
0
}.
'
.
format
(
cask
)
raise
HomebrewCaskException
(
self
.
message
)
else
:
self
.
_current_cask
=
cask
return
cask
# /class properties -------------------------------------------- }}}
def
__init__
(
self
,
module
,
path
=
None
,
casks
=
None
,
state
=
None
)
:
self
.
_setup_status_vars
()
self
.
_setup_instance_vars
(
module
=
module
,
path
=
path
,
casks
=
casks
,
state
=
state
)
self
.
_prep
()
# prep --------------------------------------------------------- {{{
def
_setup_status_vars
(
self
)
:
self
.
failed
=
False
self
.
changed
=
False
self
.
changed_count
=
0
self
.
unchanged_count
=
0
self
.
message
=
''
def
_setup_instance_vars
(
self
,
**
kwargs
)
:
for
key
,
val
in
kwargs
.
iteritems
()
:
setattr
(
self
,
key
,
val
)
def
_prep
(
self
)
:
self
.
_prep_path
()
self
.
_prep_brew_path
()
def
_prep_path
(
self
)
:
if
not
self
.
path
:
self
.
path
=
[
'
/
usr
/
local
/
bin
'
]
def
_prep_brew_path
(
self
)
:
if
not
self
.
module
:
self
.
brew_path
=
None
self
.
failed
=
True
self
.
message
=
'
AnsibleModule
not
set
.
'
raise
HomebrewCaskException
(
self
.
message
)
self
.
brew_path
=
self
.
module
.
get_bin_path
(
'
brew
'
,
required
=
True
,
opt_dirs
=
self
.
path
,
)
if
not
self
.
brew_path
:
self
.
brew_path
=
None
self
.
failed
=
True
self
.
message
=
'
Unable
to
locate
homebrew
executable
.
'
raise
HomebrewCaskException
(
'
Unable
to
locate
homebrew
executable
.
'
)
return
self
.
brew_path
def
_status
(
self
)
:
return
(
self
.
failed
,
self
.
changed
,
self
.
message
)
# /prep -------------------------------------------------------- }}}
def
run
(
self
)
:
try
:
self
.
_run
()
except
HomebrewCaskException
:
pass
if
not
self
.
failed
and
(
self
.
changed_count
+
self
.
unchanged_count
>
1
)
:
self
.
message
=
"Changed: %d, Unchanged: %d"
%
(
self
.
changed_count
,
self
.
unchanged_count
,
)
(
failed
,
changed
,
message
)
=
self
.
_status
()
return
(
failed
,
changed
,
message
)
# checks ------------------------------------------------------- {{{
def
_current_cask_is_installed
(
self
)
:
if
not
self
.
valid_cask
(
self
.
current_cask
)
:
self
.
failed
=
True
self
.
message
=
'
Invalid
cask
:
{
0
}.
'
.
format
(
self
.
current_cask
)
raise
HomebrewCaskException
(
self
.
message
)
cmd
=
[
self
.
brew_path
,
'
cask
'
,
'
list
'
]
rc
,
out
,
err
=
self
.
module
.
run_command
(
cmd
)
if
'
nothing
to
list
'
in
err
:
return
False
elif
rc
==
0
:
casks
=
[
cask_
.
strip
()
for
cask_
in
out
.
split
(
'\n'
)
if
cask_
.
strip
()]
return
self
.
current_cask
in
casks
else
:
self
.
failed
=
True
self
.
message
=
err
.
strip
()
raise
HomebrewCaskException
(
self
.
message
)
# /checks ------------------------------------------------------ }}}
# commands ----------------------------------------------------- {{{
def
_run
(
self
)
:
if
self
.
state
==
'
installed
'
:
return
self
.
_install_casks
()
elif
self
.
state
==
'
absent
'
:
return
self
.
_uninstall_casks
()
if
self
.
command
:
return
self
.
_command
()
# updated -------------------------------- {{{
def
_update_homebrew
(
self
)
:
rc
,
out
,
err
=
self
.
module
.
run_command
([
self
.
brew_path
,
'
update
'
,
])
if
rc
==
0
:
if
out
and
isinstance
(
out
,
basestring
)
:
already_updated
=
any
(
re
.
search
(
r
'
Already
up
-
to
-
date
.
'
,
s
.
strip
(),
re
.
IGNORECASE
)
for
s
in
out
.
split
(
'\n'
)
if
s
)
if
not
already_updated
:
self
.
changed
=
True
self
.
message
=
'
Homebrew
updated
successfully
.
'
else
:
self
.
message
=
'
Homebrew
already
up
-
to
-
date
.
'
return
True
else
:
self
.
failed
=
True
self
.
message
=
err
.
strip
()
raise
HomebrewCaskException
(
self
.
message
)
# /updated ------------------------------- }}}
# installed ------------------------------ {{{
def
_install_current_cask
(
self
)
:
if
not
self
.
valid_cask
(
self
.
current_cask
)
:
self
.
failed
=
True
self
.
message
=
'
Invalid
cask
:
{
0
}.
'
.
format
(
self
.
current_cask
)
raise
HomebrewCaskException
(
self
.
message
)
if
self
.
_current_cask_is_installed
()
:
self
.
unchanged_count
+=
1
self
.
message
=
'
Cask
already
installed
:
{
0
}
'
.
format
(
self
.
current_cask
,
)
return
True
if
self
.
module
.
check_mode
:
self
.
changed
=
True
self
.
message
=
'
Cask
would
be
installed
:
{
0
}
'
.
format
(
self
.
current_cask
)
raise
HomebrewCaskException
(
self
.
message
)
cmd
=
[
opt
for
opt
in
(
self
.
brew_path
,
'
cask
'
,
'
install
'
,
self
.
current_cask
)
if
opt
]
rc
,
out
,
err
=
self
.
module
.
run_command
(
cmd
)
if
self
.
_current_cask_is_installed
()
:
self
.
changed_count
+=
1
self
.
changed
=
True
self
.
message
=
'
Cask
installed
:
{
0
}
'
.
format
(
self
.
current_cask
)
return
True
else
:
self
.
failed
=
True
self
.
message
=
err
.
strip
()
raise
HomebrewCaskException
(
self
.
message
)
def
_install_casks
(
self
)
:
for
cask
in
self
.
casks
:
self
.
current_cask
=
cask
self
.
_install_current_cask
()
return
True
# /installed ----------------------------- }}}
# uninstalled ---------------------------- {{{
def
_uninstall_current_cask
(
self
)
:
if
not
self
.
valid_cask
(
self
.
current_cask
)
:
self
.
failed
=
True
self
.
message
=
'
Invalid
cask
:
{
0
}.
'
.
format
(
self
.
current_cask
)
raise
HomebrewCaskException
(
self
.
message
)
if
not
self
.
_current_cask_is_installed
()
:
self
.
unchanged_count
+=
1
self
.
message
=
'
Cask
already
uninstalled
:
{
0
}
'
.
format
(
self
.
current_cask
,
)
return
True
if
self
.
module
.
check_mode
:
self
.
changed
=
True
self
.
message
=
'
Cask
would
be
uninstalled
:
{
0
}
'
.
format
(
self
.
current_cask
)
raise
HomebrewCaskException
(
self
.
message
)
cmd
=
[
opt
for
opt
in
(
self
.
brew_path
,
'
cask
'
,
'
uninstall
'
,
self
.
current_cask
)
if
opt
]
rc
,
out
,
err
=
self
.
module
.
run_command
(
cmd
)
if
not
self
.
_current_cask_is_installed
()
:
self
.
changed_count
+=
1
self
.
changed
=
True
self
.
message
=
'
Cask
uninstalled
:
{
0
}
'
.
format
(
self
.
current_cask
)
return
True
else
:
self
.
failed
=
True
self
.
message
=
err
.
strip
()
raise
HomebrewCaskException
(
self
.
message
)
def
_uninstall_casks
(
self
)
:
for
cask
in
self
.
casks
:
self
.
current_cask
=
cask
self
.
_uninstall_current_cask
()
return
True
# /uninstalled ----------------------------- }}}
# /commands ---------------------------------------------------- }}}
def
main
()
:
module
=
AnsibleModule
(
argument_spec
=
dict
(
name
=
dict
(
aliases
=
[
"cask"
],
required
=
False
),
path
=
dict
(
required
=
False
),
state
=
dict
(
default
=
"present"
,
choices
=
[
"present"
,
"installed"
,
"absent"
,
"removed"
,
"uninstalled"
,
],
),
),
supports_check_mode
=
True
,
)
p
=
module
.
params
if
p
[
'
name
'
]
:
casks
=
p
[
'
name
'
].
split
(
','
)
else
:
casks
=
None
path
=
p
[
'
path
'
]
if
path
:
path
=
path
.
split
(
':'
)
else
:
path
=
[
'
/
usr
/
local
/
bin
'
]
state
=
p
[
'
state
'
]
if
state
in
(
'
present
'
,
'
installed
'
)
:
state
=
'
installed
'
if
state
in
(
'
absent
'
,
'
removed
'
,
'
uninstalled
'
)
:
state
=
'
absent
'
brew_cask
=
HomebrewCask
(
module
=
module
,
path
=
path
,
casks
=
casks
,
state
=
state
)
(
failed
,
changed
,
message
)
=
brew_cask
.
run
()
if
failed
:
module
.
fail_json
(
msg
=
message
)
else
:
module
.
exit_json
(
changed
=
changed
,
msg
=
message
)
# this is magic, see lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
main
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment