Repository: juju/python-libjuju

Issue:
travis ci broken?
every single commit in this repo for many moons and every single pr on this repo are failing status checks, which conveys a connotation of a project thats not really working. if your not using travis then remove the .travis.yml config from this repo or fix.

Discussion:
petevg: $$merge$$
petevg: $$merge$$
wallyworld: $$merge$$
johnsca: I cherry-picked #418 into this hoping to get a full passing run.  Uncovered at least #420 and #421 
johnsca: !!build!!
johnsca: $$merge$$

Patch:
diff --git a/.github/workflows/tox.yaml b/.github/workflows/tox.yaml
new file mode 100644
index 0000000..2a48ae8
--- /dev/null
+++ b/.github/workflows/tox.yaml
@@ -0,0 +1,40 @@
+name: Run tests with Tox
+
+on: [push]
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        python: [3.6, 3.7, 3.8]
+        juju: [stable, edge]
+
+    steps:
+      - uses: actions/checkout@v2
+      - name: Setup Python
+        uses: actions/setup-python@v1
+        with:
+          python-version: ${{ matrix.python }}
+      - name: Install Tox and any other packages
+        run: pip install tox
+      - name: Run Lint and Unit Tests
+        run: tox -e lint,py3
+      - name: Install Snaps
+        run: |
+          sudo snap install lxd
+          sudo snap install juju --classic --channel ${{ matrix.juju }}
+          sudo snap install juju-wait --classic
+      - name: Configure LXD
+        run: |
+          sudo lxd waitready --timeout 30
+          sudo chmod 666 /var/snap/lxd/common/lxd/unix.socket
+          lxd init --auto --network-address='[::]' --network-port=8443 --storage-backend=dir
+          lxc network set lxdbr0 ipv6.address none
+      - name: Bootstrap Juju Controller
+        run: juju bootstrap localhost test --config 'identity-url=https://api.staging.jujucharms.com/identity' --config 'allow-model-access=true' --config 'test-mode=true'
+      - name: Run Integration Tests
+        run: tox -e integration,serial
+        env:
+          TEST_AGENTS: '{"agents":[{"url":"https://api.staging.jujucharms.com/identity","username":"libjuju-ci@yellow"}],"key":{"private":"88OOCxIHQNguRG7zFg2y2Hx5Ob0SeVKKBRnjyehverc=","public":"fDn20+5FGyN2hYO7z0rFUyoHGUnfrleslUNtoYsjNSs="}}'
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 50ba3e2..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,52 +0,0 @@
-dist: xenial
-sudo: required
-language: python
-cache: pip
-before_install:
-  - if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then sudo add-apt-repository -y ppa:jonathonf/python-3.6; fi
-  - if [[ $TRAVIS_PYTHON_VERSION == '3.7-dev' ]]; then sudo add-apt-repository -y ppa:deadsnakes/ppa; fi
-  - sudo apt-get update -q
-  - sudo apt-get remove -qy --purge lxd lxd-client
-  - sudo apt-get install snapd libsodium-dev -y
-install:
-  - sudo snap install lxd || true  # ignore failures so that unit tests will still run, at least
-  - sudo sh -c 'echo PATH=/snap/bin:$PATH >> /etc/environment';
-  - sudo snap install jq || true
-  - sudo snap install juju --classic --$JUJU_CHANNEL || true
-  - sudo snap install juju-wait --classic || true
-  - pip install tox-travis
-env:
-  global: >
-    TEST_AGENTS='{"agents":[{"url":"https://api.staging.jujucharms.com/identity","username":"libjuju-ci@yellow"}],"key":{"private":"88OOCxIHQNguRG7zFg2y2Hx5Ob0SeVKKBRnjyehverc=","public":"fDn20+5FGyN2hYO7z0rFUyoHGUnfrleslUNtoYsjNSs="}}'
-    PATH="/snap/bin:$PATH"
-    LXD_DIR="/var/snap/lxd/common/lxd"
-
-matrix:
-  include:
-  - python: 3.6
-    env: JUJU_CHANNEL=edge
-  - python: 3.6
-    env: JUJU_CHANNEL=stable
-  - python: 3.7-dev
-    env: JUJU_CHANNEL=stable
-  - python: 3.7-dev
-    env: JUJU_CHANNEL=edge
-before_script:
-  - set -e
-  # Run lint and unit tests before performing more expensive operations (fail fast/early)
-  - tox -e lint,py3
-
-  # init lxd for tests
-  - sudo lxd waitready --timeout 30
-  - sudo chmod 666 /var/snap/lxd/common/lxd/unix.socket
-  - lxd init --auto --network-address='[::]' --network-port=8443 --storage-backend=dir
-  - lxc network set lxdbr0 ipv6.address none
-
-  # Horrible workaround to LP Bug #1738614
-  - sudo mkdir /var/snap/lxd/common/lxd/storage-pools/juju-zfs
-  - lxc storage create juju-zfs dir source=/var/snap/lxd/common/lxd/storage-pools/juju-zfs
-
-script:
-  - set -e
-  - juju bootstrap localhost test --config 'identity-url=https://api.staging.jujucharms.com/identity' --config 'allow-model-access=true'
-  - tox -e integration,serial
diff --git a/juju/application.py b/juju/application.py
index ccc63e9..d94ab79 100644
--- a/juju/application.py
+++ b/juju/application.py
@@ -311,7 +311,7 @@ class Application(model.ModelEntity):
                 actions = result.actions
                 break
         if not schema:
-            actions = {k: v['description'] for k, v in actions.items()}
+            actions = {k: v.description for k, v in actions.items()}
         return actions
 
     async def get_resources(self):
diff --git a/juju/unit.py b/juju/unit.py
index 0456255..db619cc 100644
--- a/juju/unit.py
+++ b/juju/unit.py
@@ -279,25 +279,27 @@ class Unit(model.ModelEntity):
 
         # Is the application a subordinate? If so change our data variables to
         # the parent
-        if status.applications[app].get('subordinate-to'):
+        if status.applications[app].subordinate_to:
             is_subordinate = True
-            target_apps = status.applications[app]['subordinate-to']
+            target_apps = status.applications[app].subordinate_to
 
         for target_app in target_apps:
             app_data = status.applications[target_app]
 
-            if not app_data.get('units'):
+            if not app_data.units:
                 continue
 
-            if app_data['units'].get(self.name):
-                return app_data['units'][self.name].get('leader', False)
+            if app_data.units.get(self.name):
+                is_leader = app_data.units[self.name].leader
+                return is_leader if is_leader else False
 
             if not is_subordinate:
                 continue
 
-            for key, unit in app_data['units'].items():
-                if unit.get('subordinates') and unit['subordinates'].get(self.name):
-                    return unit['subordinates'][self.name].get('leader', False)
+            for key, unit in app_data.units.items():
+                if unit.subordinates and unit.subordinates.get(self.name):
+                    is_leader = unit.subordinates[self.name].leader
+                    return is_leader if is_leader else False
 
         return False
 
diff --git a/tox.ini b/tox.ini
index 29a7665..80cc2c3 100644
--- a/tox.ini
+++ b/tox.ini
@@ -39,7 +39,6 @@ commands =
     py.test --tb native -ra -v -s -n auto -k 'not integration' -m 'not serial' {posargs}
 
 [testenv:lint]
-envdir = {toxworkdir}/py3
 commands =
     flake8 --ignore E501,W504,E402 {posargs} juju tests examples
 deps =
@@ -56,7 +55,11 @@ commands =
 [testenv:serial]
 # tests that can't be run in parallel
 envdir = {toxworkdir}/py3
-commands = py.test --tb native -ra -v -s {posargs:-m 'serial'}
+commands =
+    # These need to be installed in a specific order
+    pip install urllib3==1.25.7
+    pip install pylxd
+    py.test --tb native -ra -v -s {posargs:-m 'serial'}
 
 [testenv:example]
 envdir = {toxworkdir}/py3


Test patch:
diff --git a/tests/integration/test_unit.py b/tests/integration/test_unit.py
index 95e932d..6983454 100644
--- a/tests/integration/test_unit.py
+++ b/tests/integration/test_unit.py
@@ -57,10 +57,25 @@ async def test_run_action(event_loop):
 
         for unit in app.units:
             action = await run_action(unit)
-            assert action.results == {'dir': '/var/git/myrepo.git'}
+            assert action.results == {
+                'Code': '0',
+                'Stdout': "Adding group `myrepo' (GID 1001) ...\n"
+                          'Done.\n'
+                          'Initialized empty Git repository in '
+                          '/var/git/myrepo.git/\n',
+                'dir': '/var/git/myrepo.git',
+            }
             out = await model.get_action_output(action.entity_id, wait=5)
-            assert out == {'dir': '/var/git/myrepo.git'}
-            status = await model.get_action_status(uuid_or_prefix=action.entity_id)
+            assert out == {
+                'Code': '0',
+                'Stdout': "Adding group `myrepo' (GID 1001) ...\n"
+                          'Done.\n'
+                          'Initialized empty Git repository in '
+                          '/var/git/myrepo.git/\n',
+                'dir': '/var/git/myrepo.git',
+            }
+            status = await model.get_action_status(
+                uuid_or_prefix=action.entity_id)
             assert status[action.entity_id] == 'completed'
             break
 
diff --git a/tests/unit/test_unit.py b/tests/unit/test_unit.py
index 527cc6e..e52fe36 100644
--- a/tests/unit/test_unit.py
+++ b/tests/unit/test_unit.py
@@ -4,6 +4,7 @@ import pytest
 
 from juju.model import Model
 from juju.unit import Unit
+from juju.client._definitions import FullStatus
 
 from .. import base
 
@@ -137,8 +138,7 @@ async def test_unit_is_leader(mock_cf):
     model._connector = mock.MagicMock()
 
     for test in tests:
-        status = mock.Mock()
-        status.applications = test['applications']
+        status = FullStatus.from_json(test)
         client_facade = mock_cf.from_connection()
         client_facade.FullStatus = base.AsyncMock(return_value=status)