Git Product home page Git Product logo

charm-k8s-grafana's Introduction

Juju Charm/Operator for Grafana on Kubernetes

CI Badges

Click on each badge for more details.

Branch Build Status Coverage
master Build Status (master) Coverage Status

Quick Start

git submodule update --init --recursive
sudo snap install juju --classic
sudo snap install microk8s --classic
sudo microk8s.enable dns dashboard registry storage
sudo usermod -a -G microk8s $(whoami)

Log out then log back in so that the new group membership is applied to your shell session.

juju bootstrap microk8s mk8s

Optional: Grab coffee/beer/tea or do a 5k run. Once the above is done, do:

juju create-storage-pool operator-storage kubernetes storage-class=microk8s-hostpath
juju add-model lma
juju deploy . --resource grafana-image=grafana/grafana:latest

Wait until juju status shows that the grafana app has a status of active.

Preview the Grafana GUI

Add the following entry to your machine's /etc/hosts file:

<microk8s-host-ip>	grafana.local

Run:

juju config grafana juju-external-hostname=grafana.local
juju expose grafana

Now browse to http://grafana.local.

A NOTE ABOUT THE EXTERNAL HOSTNAME: If you are using a k8s distribution other than microk8s, you need to ensure that there is an LB sitting in front of the k8s nodes and that you use that LB's IP address in place of <microk8s-host-ip>. Alternatively, instead of adding a static entry in /etc/hosts such as above, you may use an FQDN as the value to juju-external-hostname.

Use Prometheus as a Datasource

Follow the steps for deploying charm-k8s-prometheus. Once Prometheus is up and running, relate it with Grafana by running the following command:

juju relate grafana prometheus

Once Grafana has settled, head back to the Grafana UI to see the Prometheus datasource configured. Create a new dashboard and run the following query to test the connection:

rate(prometheus_tsdb_head_chunks_created_total[1m])

This Charm's Architecture

To learn how to navigate this charm's code and become an effective contributor, please read the Charmed LMA Operators Architecture reference doc.

Install Test Dependencies

  1. Install pyenv so that you can test with different versions of Python
curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash
  1. Append the following to your ~/.bashrc then log out and log back in
export PATH="/home/mark/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
  1. Install development packages
sudo apt install build-essential libssl-dev zlib1g-dev libbz2-dev \
    libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
    xz-utils tk-dev libffi-dev liblzma-dev python3-openssl git
  1. Install Python 3.6.x and 3.7.x
pyenv install 3.6.X
pyenv install 3.7.X

NOTE: Replace X with the correct minor version as listed in pyenv install --list

Running the Unit Tests on Your Workstation

To run the test using the default interpreter as configured in tox.ini, run:

tox

If you want to specify an interpreter that's present in your workstation, you may run it with:

tox -e py37

To view the coverage report that gets generated after running the tests above, run:

make coverage-server

The above command should output the port on your workstation where the server is listening on. If you are running the above command on Multipass, first get the Ubuntu VM's IP via multipass list and then browse to that IP and the abovementioned port.

NOTE: You can leave that static server running in one session while you continue to execute tox on another session. That server will pick up any new changes to the report automatically so you don't have to restart it each time.

Troubleshooting

Since Kubernetes charms are not supported by juju debug-hooks, the only way to intercept code execution is to initialize the non-tty-bound debugger session and connect to the session externally.

For this purpose, we chose the rpdb, the remote Python debugger based on pdb.

For example, given that you have already deployed an application named grafana in a Juju model named lma and you would like to debug your config-changed handler, execute the following:

kubectl exec -it pod/grafana-operator-0 -n lma -- /bin/sh

This will open an interactive shell within the operator pod. Then, install the editor and the RPDB:

apt update
apt install telnet vim -y
pip3 install rpdb

Open the charm entry point in the editor:

vim /var/lib/juju/agents/unit-grafana-0/charm/src/charm.py

Find a on_config_changed_handler function definition in the charm.py file. Modify it as follows:

def on_config_changed_handler(event, fw_adapter):
    import rpdb
    rpdb.set_trace()
    # < ... rest of the code ... >

Save the file (:wq). Do not close the current shell session!

Open another terminal session and trigger the config-changed hook as follows:

juju config grafana external-labels='{"foo": "bar"}'

Do a juju status, until you will see the following:

Unit           Workload  Agent      Address    Ports     Message
grafana/0*  active    executing  10.1.28.2  9090/TCP  (config-changed)

This message means, that unit has started the config-changed hook routine and it was already intercepted by the rpdb.

Now, return back to the operator pod session.

Enter the interactive debugger:

telnet localhost 4444

You should see the debugger interactive console.

# telnet localhost 4444
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
> /var/lib/juju/agents/unit-grafana-0/charm/hooks/config-changed(91)on_config_changed_handler()
-> set_juju_pod_spec(fw_adapter)
(Pdb) where
  /var/lib/juju/agents/unit-grafana-0/charm/hooks/config-changed(141)<module>()
-> main(Charm)
  /var/lib/juju/agents/application-grafana/charm/lib/ops/main.py(212)main()
-> _emit_charm_event(charm, juju_event_name)
  /var/lib/juju/agents/application-grafana/charm/lib/ops/main.py(128)_emit_charm_event()
-> event_to_emit.emit(*args, **kwargs)
  /var/lib/juju/agents/application-grafana/charm/lib/ops/framework.py(205)emit()
-> framework._emit(event)
  /var/lib/juju/agents/application-grafana/charm/lib/ops/framework.py(710)_emit()
-> self._reemit(event_path)
  /var/lib/juju/agents/application-grafana/charm/lib/ops/framework.py(745)_reemit()
-> custom_handler(event)
  /var/lib/juju/agents/unit-grafana-0/charm/hooks/config-changed(68)on_config_changed()
-> on_config_changed_handler(event, self.fw_adapter)
> /var/lib/juju/agents/unit-grafana-0/charm/hooks/config-changed(91)on_config_changed_handler()
-> set_juju_pod_spec(fw_adapter)
(Pdb)

From this point forward, the usual pdb commands apply. For more information on how to use pdb, see the official pdb documentation

Relying on More Comprehensive Unit Tests

To ensure that this charm is tested on the widest number of platforms possible, we make use of Travis CI which also automatically reports the coverage report to a publicly available Coveralls.io page. To get a view of what the state of each relevant branch is, click on the appropriate badges found at the top of this README.

References

  1. Grafana Docker Image Configuration

Much of how this charm is architected is guided by the following classic references. It will do well for future contributors to read and take them to heart:

  1. Hexagonal Architecture by Alistair Cockburn
  2. Boundaries (Video) by Gary Bernhardt
  3. Domain Driven Design (Book) by Eric Evans

charm-k8s-grafana's People

Contributors

relaxdiego avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

charm-k8s-grafana's Issues

Remove `charm-k8s-` in application name

From this discourse comment

It would be more normal to just call the charm by the application it is deploying rather than ‘charm-k8s-*’. So you would do:
juju deploy grafana
If you look at microk8s.kubectl -n lma get pods we already have grafana-operator vs grafana. The extra ‘charm-k8s’ is just noise in the deploy.

Grafana GPG key rotation

Grafana recently rotated their GPG key. As a result, the charm fails to install Grafana:

unit-grafana-1: 14:30:06 INFO juju.worker.uniter found queued "install" hook
unit-grafana-1: 14:30:29 WARNING unit.grafana/1.install ERROR: launchpadlib 1.10.13 requires testresources, which is not installed.
unit-grafana-1: 14:30:31 INFO unit.grafana/1.juju-log Reactive main running for hook install
unit-grafana-1: 14:30:31 ERROR unit.grafana/1.juju-log Unable to find implementation for relation: requires of register-application
unit-grafana-1: 14:30:31 INFO unit.grafana/1.juju-log Initializing Snap Layer
unit-grafana-1: 14:30:31 INFO unit.grafana/1.juju-log Invoking reactive handler: reactive/grafana.py:205:install_packages
unit-grafana-1: 14:30:37 WARNING unit.grafana/1.install W: GPG error: https://packages.grafana.com/oss/deb stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9E439B102CF3C0C6
unit-grafana-1: 14:30:37 WARNING unit.grafana/1.install E: The repository 'https://packages.grafana.com/oss/deb stable InRelease' is not signed.
unit-grafana-1: 14:30:37 INFO unit.grafana/1.juju-log Failed executing 'add-apt-repository --yes deb https://packages.grafana.com/oss/deb stable main'. Will retry in 10 seconds
unit-grafana-1: 14:30:50 WARNING unit.grafana/1.install W: GPG error: https://packages.grafana.com/oss/deb stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9E439B102CF3C0C6
unit-grafana-1: 14:30:50 WARNING unit.grafana/1.install E: The repository 'https://packages.grafana.com/oss/deb stable InRelease' is not signed.
unit-grafana-1: 14:30:50 INFO unit.grafana/1.juju-log Couldn't acquire DPKG lock. Will retry in 10 seconds
unit-grafana-1: 14:31:02 WARNING unit.grafana/1.install W: GPG error: https://packages.grafana.com/oss/deb stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9E439B102CF3C0C6
unit-grafana-1: 14:31:02 WARNING unit.grafana/1.install E: The repository 'https://packages.grafana.com/oss/deb stable InRelease' is not signed.
unit-grafana-1: 14:31:02 INFO unit.grafana/1.juju-log Couldn't acquire DPKG lock. Will retry in 10 seconds
unit-grafana-1: 14:31:14 WARNING unit.grafana/1.install W: GPG error: https://packages.grafana.com/oss/deb stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9E439B102CF3C0C6
unit-grafana-1: 14:31:14 WARNING unit.grafana/1.install E: The repository 'https://packages.grafana.com/oss/deb stable InRelease' is not signed.
unit-grafana-1: 14:31:14 INFO unit.grafana/1.juju-log Couldn't acquire DPKG lock. Will retry in 10 seconds
unit-grafana-1: 14:31:25 WARNING unit.grafana/1.install W: GPG error: https://packages.grafana.com/oss/deb stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9E439B102CF3C0C6
unit-grafana-1: 14:31:25 WARNING unit.grafana/1.install E: The repository 'https://packages.grafana.com/oss/deb stable InRelease' is not signed.
unit-grafana-1: 14:31:25 INFO unit.grafana/1.juju-log Couldn't acquire DPKG lock. Will retry in 10 seconds
unit-grafana-1: 14:31:37 WARNING unit.grafana/1.install W: GPG error: https://packages.grafana.com/oss/deb stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9E439B102CF3C0C6
unit-grafana-1: 14:31:37 WARNING unit.grafana/1.install E: The repository 'https://packages.grafana.com/oss/deb stable InRelease' is not signed.
unit-grafana-1: 14:31:37 INFO unit.grafana/1.juju-log Couldn't acquire DPKG lock. Will retry in 10 seconds
unit-grafana-1: 14:31:49 WARNING unit.grafana/1.install W: GPG error: https://packages.grafana.com/oss/deb stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9E439B102CF3C0C6
unit-grafana-1: 14:31:49 WARNING unit.grafana/1.install E: The repository 'https://packages.grafana.com/oss/deb stable InRelease' is not signed.
unit-grafana-1: 14:31:49 INFO unit.grafana/1.juju-log Couldn't acquire DPKG lock. Will retry in 10 seconds
unit-grafana-1: 14:32:01 WARNING unit.grafana/1.install W: GPG error: https://packages.grafana.com/oss/deb stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9E439B102CF3C0C6
unit-grafana-1: 14:32:01 WARNING unit.grafana/1.install E: The repository 'https://packages.grafana.com/oss/deb stable InRelease' is not signed.
unit-grafana-1: 14:32:01 INFO unit.grafana/1.juju-log Couldn't acquire DPKG lock. Will retry in 10 seconds
unit-grafana-1: 14:32:12 WARNING unit.grafana/1.install W: GPG error: https://packages.grafana.com/oss/deb stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9E439B102CF3C0C6
unit-grafana-1: 14:32:12 WARNING unit.grafana/1.install E: The repository 'https://packages.grafana.com/oss/deb stable InRelease' is not signed.
unit-grafana-1: 14:32:12 INFO unit.grafana/1.juju-log Couldn't acquire DPKG lock. Will retry in 10 seconds
unit-grafana-1: 14:32:24 WARNING unit.grafana/1.install W: GPG error: https://packages.grafana.com/oss/deb stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9E439B102CF3C0C6
unit-grafana-1: 14:32:24 WARNING unit.grafana/1.install E: The repository 'https://packages.grafana.com/oss/deb stable InRelease' is not signed.
unit-grafana-1: 14:32:24 INFO unit.grafana/1.juju-log Couldn't acquire DPKG lock. Will retry in 10 seconds
unit-grafana-1: 14:32:36 WARNING unit.grafana/1.install W: GPG error: https://packages.grafana.com/oss/deb stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9E439B102CF3C0C6
unit-grafana-1: 14:32:36 WARNING unit.grafana/1.install E: The repository 'https://packages.grafana.com/oss/deb stable InRelease' is not signed.
unit-grafana-1: 14:32:36 INFO unit.grafana/1.juju-log Couldn't acquire DPKG lock. Will retry in 10 seconds
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install W: GPG error: https://packages.grafana.com/oss/deb stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9E439B102CF3C0C6
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install E: The repository 'https://packages.grafana.com/oss/deb stable InRelease' is not signed.
unit-grafana-1: 14:32:48 ERROR unit.grafana/1.juju-log Hook error:
Traceback (most recent call last):
  File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charms/reactive/__init__.py", line 74, in main
    bus.dispatch(restricted=restricted_mode)
  File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charms/reactive/bus.py", line 390, in dispatch
    _invoke(other_handlers)
  File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charms/reactive/bus.py", line 359, in _invoke
    handler.invoke()
  File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charms/reactive/bus.py", line 181, in invoke
    self._action(*args)
  File "/var/lib/juju/agents/unit-grafana-1/charm/reactive/grafana.py", line 258, in install_packages
    fetch.configure_sources(update=True)
  File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charmhelpers/fetch/__init__.py", line 149, in configure_sources
    _fetch_update(fatal=True)
  File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charmhelpers/fetch/ubuntu.py", line 400, in apt_update
    _run_apt_command(cmd, fatal)
  File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charmhelpers/fetch/ubuntu.py", line 945, in _run_apt_command
    _run_with_retries(
  File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charmhelpers/fetch/ubuntu.py", line 922, in _run_with_retries
    result = subprocess.check_call(cmd, env=env, **kwargs)
  File "/usr/lib/python3.8/subprocess.py", line 364, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['apt-get', 'update']' returned non-zero exit status 100.

unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install Traceback (most recent call last):
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install   File "/var/lib/juju/agents/unit-grafana-1/charm/hooks/install", line 22, in <module>
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install     main()
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install   File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charms/reactive/__init__.py", line 74, in main
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install     bus.dispatch(restricted=restricted_mode)
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install   File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charms/reactive/bus.py", line 390, in dispatch
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install     _invoke(other_handlers)
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install   File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charms/reactive/bus.py", line 359, in _invoke
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install     handler.invoke()
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install   File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charms/reactive/bus.py", line 181, in invoke
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install     self._action(*args)
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install   File "/var/lib/juju/agents/unit-grafana-1/charm/reactive/grafana.py", line 258, in install_packages
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install     fetch.configure_sources(update=True)
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install   File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charmhelpers/fetch/__init__.py", line 149, in configure_sources
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install     _fetch_update(fatal=True)
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install   File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charmhelpers/fetch/ubuntu.py", line 400, in apt_update
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install     _run_apt_command(cmd, fatal)
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install   File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charmhelpers/fetch/ubuntu.py", line 945, in _run_apt_command
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install     _run_with_retries(
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install   File "/var/lib/juju/agents/unit-grafana-1/.venv/lib/python3.8/site-packages/charmhelpers/fetch/ubuntu.py", line 922, in _run_with_retries
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install     result = subprocess.check_call(cmd, env=env, **kwargs)
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install   File "/usr/lib/python3.8/subprocess.py", line 364, in check_call
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install     raise CalledProcessError(retcode, cmd)
unit-grafana-1: 14:32:48 WARNING unit.grafana/1.install subprocess.CalledProcessError: Command '['apt-get', 'update']' returned non-zero exit status 100.
unit-grafana-1: 14:32:48 ERROR juju.worker.uniter.operation hook "install" (via explicit, bespoke hook script) failed: exit status 1
unit-grafana-1: 14:32:48 INFO juju.worker.uniter awaiting error resolution for "install" hook

Reconsider the "FrameworkAdapter" infrastructure

It's a layer above many things. A quite lightweight one, though, so there's not a lot of work hidden in that layer, but as it's a layer above several other things, to where each property belongs is not easily discoverable.

Most of the FrameworkAdapter attributes are from the Model, so they can always be accessed doing self.framework.model in the charm. But note that the charm already has shortcuts like app or unit (check the docs here).

So, for example you're currently doing...

juju_app = fw_adapter.get_app_name()

...and it's shorter and more accurate to do...

juju_app = self.framework.app.name

It's even absurd to have the separation layer when doing exactly the same thing, forcing you to write...

            self.fw_adapter.observe(event, delegator)

...when it's just doing exactly the same that you would be doing by...

            self.framework.observe(event, delegator)

This in general lowers a lot the learnability of this code. People getting here needs to learn this new abstraction layer instead of just using the Framework, as they are used to do.

An example of that is the developer needing to learn/understand what you're doing in...

    if not fw_adapter.am_i_leader():

...when it's simple (as long you know the Framework, which is a knowledge it's expected to have) to understand what the code does in...

    if not self.unit.is_leader():

It's fine IMO to have some layers/adapters as you have (for building the build_juju_pod_spec, for example).

But in the case of the Framework, which is by design tightly coupled with the Charm (and the Model), I would totally recommend to not have this adapter.

Consider replacing `kubectl port-forward` with `juju expose`

From this discourse comment

The kubectl ... port-forward is also interesting, as I would have thought that juju expose grafana would be the way to interact with it. Certainly a goal would be to not have to know the exact ports that the charm uses, but have things like juju expose to do the work for you. Also hopefully expose would mean that you don’t have to rerun the command when a new unit comes up.

Handle the case where the unit is not (yet) the leader

2020-02-20 08:41:26 DEBUG start Traceback (most recent call last):
2020-02-20 08:41:26 DEBUG start   File "/var/lib/juju/agents/unit-charm-k8s-grafana-1/charm/hooks/start", line 67, in <module>
2020-02-20 08:41:26 DEBUG start     main(Charm)
2020-02-20 08:41:26 DEBUG start   File "lib/ops/main.py", line 187, in main
2020-02-20 08:41:26 DEBUG start     _emit_charm_event(charm, juju_event_name)
2020-02-20 08:41:26 DEBUG start   File "lib/ops/main.py", line 118, in _emit_charm_event
2020-02-20 08:41:26 DEBUG start     event_to_emit.emit(*args, **kwargs)
2020-02-20 08:41:26 DEBUG start   File "lib/ops/framework.py", line 192, in emit
2020-02-20 08:41:26 DEBUG start     framework._emit(event)
2020-02-20 08:41:26 DEBUG start   File "lib/ops/framework.py", line 602, in _emit
2020-02-20 08:41:26 DEBUG start     self._reemit(event_path)
2020-02-20 08:41:26 DEBUG start   File "lib/ops/framework.py", line 637, in _reemit
2020-02-20 08:41:26 DEBUG start     custom_handler(event)
2020-02-20 08:41:26 DEBUG start   File "/var/lib/juju/agents/unit-charm-k8s-grafana-1/charm/hooks/start", line 48, in on_start_delegator
2020-02-20 08:41:26 DEBUG start     self.adapter.set_pod_spec(output.spec)
2020-02-20 08:41:26 DEBUG start   File "/var/lib/juju/agents/application-charm-k8s-grafana/charm/src/adapters.py", line 28, in set_pod_spec
2020-02-20 08:41:26 DEBUG start     self._framework.model.pod.set_spec(spec_obj)
2020-02-20 08:41:26 DEBUG start   File "lib/ops/model.py", line 452, in set_spec
2020-02-20 08:41:26 DEBUG start     raise ModelError('cannot set a pod spec as this unit is not a leader')
2020-02-20 08:41:26 DEBUG start ops.model.ModelError: cannot set a pod spec as this unit is not a leader
2020-02-20 08:41:27 ERROR juju.worker.uniter.operation runhook.go:132 hook "start" failed: exit status 1
2020-02-20 08:41:37 DEBUG start Traceback (most recent call last):
2020-02-20 08:41:37 DEBUG start   File "/var/lib/juju/agents/unit-charm-k8s-grafana-1/charm/hooks/start", line 67, in <module>
2020-02-20 08:41:37 DEBUG start     main(Charm)
2020-02-20 08:41:37 DEBUG start   File "lib/ops/main.py", line 187, in main
2020-02-20 08:41:37 DEBUG start     _emit_charm_event(charm, juju_event_name)
2020-02-20 08:41:37 DEBUG start   File "lib/ops/main.py", line 118, in _emit_charm_event
2020-02-20 08:41:37 DEBUG start     event_to_emit.emit(*args, **kwargs)
2020-02-20 08:41:37 DEBUG start   File "lib/ops/framework.py", line 192, in emit
2020-02-20 08:41:37 DEBUG start     framework._emit(event)
2020-02-20 08:41:37 DEBUG start   File "lib/ops/framework.py", line 602, in _emit
2020-02-20 08:41:37 DEBUG start     self._reemit(event_path)
2020-02-20 08:41:37 DEBUG start   File "lib/ops/framework.py", line 637, in _reemit
2020-02-20 08:41:37 DEBUG start     custom_handler(event)
2020-02-20 08:41:37 DEBUG start   File "/var/lib/juju/agents/unit-charm-k8s-grafana-1/charm/hooks/start", line 48, in on_start_delegator
2020-02-20 08:41:37 DEBUG start     self.adapter.set_pod_spec(output.spec)
2020-02-20 08:41:37 DEBUG start   File "/var/lib/juju/agents/application-charm-k8s-grafana/charm/src/adapters.py", line 28, in set_pod_spec
2020-02-20 08:41:37 DEBUG start     self._framework.model.pod.set_spec(spec_obj)
2020-02-20 08:41:37 DEBUG start   File "lib/ops/model.py", line 452, in set_spec
2020-02-20 08:41:37 DEBUG start     raise ModelError('cannot set a pod spec as this unit is not a leader')
2020-02-20 08:41:37 DEBUG start ops.model.ModelError: cannot set a pod spec as this unit is not a leader
2020-02-20 08:41:37 ERROR juju.worker.uniter.operation runhook.go:132 hook "start" failed: exit status 1

Simplify ImageMeta

It looks its only purpose is to provide a "holder" to move some data around, so you can do...

                'imagePath': image_meta.image_path,

...instead of...

                'imagePath': image_meta['registrypath'],

As it doesn't have other functionality, you could just use a namedtuple:

>>> from collections import namedtuple
>>> ImageMeta = namedtuple('ImageMeta', 'image_path repo_username repo_password')
>>> rd = dict(registrypath='foo', username='bar', password='baz')
>>> im = ImageMeta(image_path=rd['registrypath'], repo_username=rd['username'], repo_password=rd['password'])
>>> im.image_path
'foo'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.