Thomas Cuthbert has proposed merging 
~tcuthbert/charm-k8s-wordpress:image-plugin-updates into 
charm-k8s-wordpress:master.

Requested reviews:
  Wordpress Charmers (wordpress-charmers)

For more details, see:
https://code.launchpad.net/~tcuthbert/charm-k8s-wordpress/+git/charm-k8s-wordpress-1/+merge/403555
-- 
Your team Wordpress Charmers is requested to review the proposed merge of 
~tcuthbert/charm-k8s-wordpress:image-plugin-updates into 
charm-k8s-wordpress:master.
diff --git a/image-builder/src/fetcher.py b/image-builder/src/fetcher.py
index b7085f2..e9d425f 100755
--- a/image-builder/src/fetcher.py
+++ b/image-builder/src/fetcher.py
@@ -3,8 +3,12 @@
 import os
 import shutil
 import subprocess
+import sys
 import urllib.request
 import zipfile
+from typing import Mapping, List
+from urllib.parse import urlparse
+from yaml import safe_load
 
 
 zip_plugins_to_get = {
@@ -98,11 +102,11 @@ def get_plugins(zip_plugins, branch_plugins):
         current_zip = current_zip + 1
         print('Downloading {} of {} zipped plugins: {} ...'.format(current_zip, total_zips, zip_plugin))
         url = 'https://downloads.wordpress.org/plugin/{}.latest-stable.zip'.format(zip_plugin)
-        file_name = os.path.join(os.getcwd(), 'files/plugins', os.path.basename(url))
+        file_name = os.path.join(os.getcwd(), 'plugins', os.path.basename(url))
         with urllib.request.urlopen(url) as response, open(file_name, 'wb') as out_file:
             shutil.copyfileobj(response, out_file)
         with zipfile.ZipFile(file_name, 'r') as zip_ref:
-            zip_ref.extractall(os.path.join(os.getcwd(), 'files/plugins'))
+            zip_ref.extractall(os.path.join(os.getcwd(), 'plugins'))
         os.remove(file_name)
 
     total_branches = len(branch_plugins)
@@ -116,7 +120,7 @@ def get_plugins(zip_plugins, branch_plugins):
             basename = basename[3:]
         if basename.startswith('wp-plugin-'):
             basename = basename[10:]
-        dest = os.path.join(os.getcwd(), 'files/plugins', basename)
+        dest = os.path.join(os.getcwd(), 'plugins', basename)
         if url.startswith('lp:'):
             cmd = ['bzr', 'branch', url, dest]
         elif url.startswith('https://git'):
@@ -139,7 +143,7 @@ def get_themes(branch_themes):
             basename = basename[3:]
         if basename.startswith('wp-theme-'):
             basename = basename[9:]
-        dest = os.path.join(os.getcwd(), 'files/themes/', basename)
+        dest = os.path.join(os.getcwd(), 'themes/', basename)
         if url.startswith('lp:'):
             cmd = ['bzr', 'branch', url, dest]
         elif url.startswith('https://git'):
@@ -150,6 +154,93 @@ def get_themes(branch_themes):
         _ = subprocess.check_output(cmd, universal_newlines=True, stderr=subprocess.STDOUT)
 
 
-if __name__ == '__main__':
+class Plugin:
+    name: str
+    _protocol: str
+    _url: str
+
+    def __init__(self, name: str, url: str):
+        self.name = name
+        self.url = url
+
+    def __str__(self) -> str:
+        return self.name
+
+    def __repr__(self) -> str:
+        kwargs = {"name": self.name, "url": self.url}
+        return "<Plugin>(name={name}, url={url})".format(**kwargs)
+
+    @property
+    def url(self):
+        return self._url
+
+    @url.setter
+    def url(self, url: str):
+        u = urlparse(url)
+        self._url = u.geturl()
+        self._protocol = u.scheme.split("+")[0]
+        self._protocol = self._protocol.replace("https", "git")
+
+    def is_available(self):
+        print("NOT IMPLEMENTED")
+
+    def is_bzr(self):
+        return self._protocol == "lp"
+
+    def is_git(self):
+        return self._protocol == "git"
+
+    def sync(self, dest: str):
+        self.__make_dest(dest)
+        failed = self.__call_sync(os.path.join(dest, self.name))
+        if failed:
+            raise RuntimeError("failed to sync plugin: {0}".format(self))
+
+    def __make_dest(self, dest: str):
+        os.makedirs(dest, mode=0o755, exist_ok=True)
+
+    def __build_cmd(self, dest: str) -> List[str]:
+        cmds = {
+            "git": ["git", "clone", self.url, dest],
+            "lp": ["bzr", "branch", self.url, dest],
+        }
+        return cmds[self._protocol]
+
+    def __call_sync(self, dest: str, verbose=True):
+        subprocess_kwargs = {}
+        subprocess_kwargs["universal_newlines"] = True
+        if verbose:
+            subprocess_kwargs["stderr"] = subprocess.STDOUT
+
+        rv = subprocess.run(self.__build_cmd(dest), **subprocess_kwargs)
+        return rv.returncode
+
+
+def sync_additional_plugins(additional_plugins: Mapping[str, str]):
+    """
+    Sync any additional WordPress plugins specified from the Container
+    environment variable: WORDPRESS_ADDITIONAL_PLUGINS.
+
+    WORDPRESS_ADDITIONAL_PLUGINS must be a valid YAML formatted map string.
+    """
+    dest_path = os.path.join(os.getcwd(), "plugins")
+    total_plugins = len(additional_plugins)
+    count = 0
+    for name, url in additional_plugins.items():
+        count += 1
+        plugin = Plugin(name, url)
+        print("Syncing {0} of {1} WordPress plugins: {2} ...".format(count, total_plugins, plugin))
+        plugin.sync(dest_path)
+
+
+if __name__ == "__main__":
+    if "WORDPRESS_ADDITIONAL_PLUGINS" in os.environ.keys():
+        additional_plugins = os.environ["WORDPRESS_ADDITIONAL_PLUGINS"]
+        if additional_plugins:
+            plugins = safe_load(additional_plugins.encode("utf-8"))
+            sync_additional_plugins(plugins)
+            # TODO: Script should have command-line flags instead of this.
+            print("DEBUG: we are running inside a container, no need to sync base plugins")
+        sys.exit(0)
     get_plugins(zip_plugins_to_get, branch_plugins_to_get)
     get_themes(branch_themes_to_get)
diff --git a/image-builder/tests/unit/test_fetcher.py b/image-builder/tests/unit/test_fetcher.py
new file mode 100644
index 0000000..edced66
--- /dev/null
+++ b/image-builder/tests/unit/test_fetcher.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+import unittest
+from unittest.mock import patch
+
+from fetcher import Plugin
+from fetcher import sync_additional_plugins
+
+
+class TestPlugin(unittest.TestCase):
+    test_name = "testPlugin"
+    test_url = "lp:~testUser/testProject/testBranch"
+
+    def setUp(self):
+        test_name = self.test_name
+        test_url = self.test_url
+        self.plugin = Plugin(test_name, test_url)
+
+    def test__init__(self):
+        plugin = Plugin(TestPlugin.test_name, TestPlugin.test_url)
+        name = plugin.name
+        protocol = plugin._protocol
+        url = plugin.url
+        self.assertEqual(name, TestPlugin.test_name)
+        self.assertEqual(protocol, TestPlugin.test_url.split(":")[0])
+        self.assertEqual(url, TestPlugin.test_url)
+
+    def test_is_available(self):
+        self.plugin.is_available()
+
+    def test_is_bzr(self):
+        self.assertTrue(self.plugin.is_bzr())
+
+    def test_is_git(self):
+        self.assertFalse(self.plugin.is_git())
+
+    @patch.object(Plugin, "_Plugin__make_dest")
+    @patch.object(Plugin, "_Plugin__call_sync")
+    def test_sync(self, mock_call_sync, mock_make_dest):
+
+        mock_call_sync.return_value = None
+        self.plugin.sync("test/path")
+
+        assert mock_call_sync.called
+        assert mock_make_dest.called
+
+        mock_call_sync.return_value = True
+        with self.assertRaises(RuntimeError) as cm:
+            self.plugin.sync("test/path")
+            self.assertTrue("failed to sync plugin" in str(cm.exception))
-- 
Mailing list: https://launchpad.net/~wordpress-charmers
Post to     : wordpress-charmers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~wordpress-charmers
More help   : https://help.launchpad.net/ListHelp

Reply via email to