Import of core OSM charm layers
[osm/SO.git] / charms / layers / sshproxy / reactive / sshproxy.py
diff --git a/charms/layers/sshproxy/reactive/sshproxy.py b/charms/layers/sshproxy/reactive/sshproxy.py
new file mode 100644 (file)
index 0000000..e1508ca
--- /dev/null
@@ -0,0 +1,73 @@
+##
+# Copyright 2016 Canonical Ltd.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+##
+
+from charmhelpers.core.hookenv import (
+    action_fail,
+    action_get,
+    action_set,
+    config,
+)
+from charms.reactive import (
+    remove_state,
+    set_state,
+    when,
+)
+import charms.sshproxy
+import subprocess
+
+
+@when('config.changed')
+def ssh_configured():
+    """ Checks to see if the charm is configured with SSH credentials. If so,
+    set a state flag that can be used to execute ssh-only actions.
+
+    For example:
+
+    @when('sshproxy.configured')
+    def run_remote_command(cmd):
+        ...
+
+    @when_not('sshproxy.configured')
+    def run_local_command(cmd):
+        ...
+    """
+    cfg = config()
+    if all(k in cfg for k in ['ssh-hostname', 'ssh-username',
+                              'ssh-password', 'ssh-private-key']):
+        set_state('sshproxy.configured')
+    else:
+        remove_state('sshproxy.configured')
+
+
+@when('actions.run')
+def run_command():
+    """
+    Run an arbitrary command, either locally or over SSH with the configured
+    credentials.
+    """
+    try:
+        cmd = action_get('command')
+        output, err = charms.sshproxy._run(cmd)
+        if len(err):
+            action_fail("Command '{}' returned error code {}".format(cmd, err))
+        else:
+            action_set({'output': output})
+    except subprocess.CalledProcessError as e:
+        action_fail('Command failed: %s (%s)' %
+                    (' '.join(e.cmd), str(e.output)))
+    finally:
+        remove_state('actions.run')