Skip to content

Commit

Permalink
Allow json injection through "svcmgr create" stdin
Browse files Browse the repository at this point in the history
Example:

Clone service ha3 to ha4, removing app#0 and task#0 resources and setting
the app to "foo".

$ sudo svcmgr -s ha3 print config --format json | \
 jq 'del(."app#0",."task#0")' | \
 jq '.DEFAULT.app="foo"' | \
 sudo svcmgr -s ha4 create

$ ha3 print status
ha3                             up
`- instances
   |- nuc                       up         idle, started
   `- aubergine                 down       idle
      |- container#0    ....... down       docker container ha3.container.0@busybox
      |                                    info: can not find container id
      |- app#0          ..D../. n/a        app0
      |- sync#i0        ...O./. up         rsync svc config to nodes
      `- task#0         ...O... n/a        task

$ ha4 print status
ha4                             down
`- instances
   |- nuc                       down       frozen, idle
   `- aubergine                 down       frozen, idle
      |- container#0    ....... down       docker container ha4.container.0@busybox
      |                                    info: can not find container id
      `- sync#i0        ...O./. n/a        rsync svc config to nodes
                                           info: paused, service not up
  • Loading branch information
cvaroqui committed Feb 26, 2018
1 parent 735c9f9 commit 9960372
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 7 deletions.
46 changes: 43 additions & 3 deletions lib/node.py
Expand Up @@ -2722,6 +2722,27 @@ def install_svc_conf_from_file(svcname, fpath):
if dst_cf != src_cf:
shutil.copy2(src_cf, dst_cf)

@staticmethod
def install_svc_conf_from_data(svcname, data):
"""
Installs a service configuration file from section, keys and values
fed from a data structure.
"""
fpath = os.path.join(rcEnv.paths.pathetc, svcname+'.conf')
config = rcConfigParser.RawConfigParser()

for section_name, section in data.items():
if section_name != "DEFAULT":
config.add_section(section_name)
for key, value in section.items():
config.set(section_name, key, value)
try:
with open(fpath, 'w') as ofile:
config.write(ofile)
except:
print("failed to write %s"%fpath, file=sys.stderr)
raise Exception()

def install_service(self, svcname, fpath=None, template=None):
"""
Pick a collector's template, arbitrary uri, or local file service
Expand All @@ -2733,7 +2754,19 @@ def install_service(self, svcname, fpath=None, template=None):
raise ex.excError("only one service must be specified")
svcname = svcname[0]

if fpath is None and template is None:
import select
data = None
if sys.stdin and not sys.stdin.isatty():
feed = ""
for line in sys.stdin.readlines():
feed += line
if feed:
try:
data = json.loads("".join(feed))
except ValueError:
raise ex.excError("invalid json feed")

if fpath is None and template is None and data is None:
return

if fpath is not None and template is not None:
Expand All @@ -2744,20 +2777,27 @@ def install_service(self, svcname, fpath=None, template=None):
# action before we have the change to modify the service config
Freezer(svcname).freeze()

if template is not None:
if data is not None:
self.install_svc_conf_from_data(svcname, data)
elif template is not None:
if "://" in template:
self.install_svc_conf_from_uri(svcname, template)
elif os.path.exists(template):
self.install_svc_conf_from_file(svcname, template)
else:
self.install_svc_conf_from_templ(svcname, template)
else:
elif fpath is not None:
if "://" in fpath:
self.install_svc_conf_from_uri(svcname, fpath)
else:
self.install_svc_conf_from_file(svcname, fpath)
else:
# announce nothing was done
return 2

self.install_service_files(svcname)
self.wake_monitor()
return 0

@staticmethod
def install_service_files(svcname):
Expand Down
9 changes: 5 additions & 4 deletions lib/svcmgr.py
Expand Up @@ -137,13 +137,14 @@ def do_svc_create(node, svcnames, action, options, build_kwargs):
"""
ret = 0
try:
node.install_service(svcnames, fpath=options.config,
template=options.template)
ret = node.install_service(svcnames, fpath=options.config,
template=options.template)
except Exception as exc:
print(str(exc), file=sys.stderr)
ret = 1
return 1

if options.config is None and options.template is None:
if ret == 2:
# install_service() reports it did nothing
data = getattr(svcBuilder, action)(svcnames, options.resource,
provision=options.provision)
else:
Expand Down

0 comments on commit 9960372

Please sign in to comment.