Blog Feed

Base dockerized squid proxy

Here the dockerfile for an alpine based squid proxy working with default installation

FROM alpine
RUN apk update && \
apk add squid
CMD ["/usr/sbin/squid", "-NCd1"]

Build the image:

docker build -t basic_squid .

and create the container by running:

docker run -d --rm --name squid-test -p 3128:3128 basic_squid

test it by running curl:

curl -x http://localhost:3128 -L http://x.x.x.x

Jenkins: variables in freestyle projects

Let’s say you are running a freestyle project in jenkins and you need a variable to use between building steps. One way is to install and use different plugins to give you the option to add custom global variables. However, there is an alternative by using linux bash commands without any further installations. (this assumes that jenkins is running on linux. Same can be applied to windows with the appropriate syntax change)

Inside a jenkins freestyle project, each “Execute Shell” box works as an individual bash script running in the workspace. It not only works for running arbitrary commands:

but also to write a full bash script:

You can then create a variable in one shell step, save it as text in the workspace and open it later in a different step using native bash:

very useful when you need unique variables or identifiers per run, with multiple steps doing different stuff.

Ansible Module Parameters

When writing new modules, the ansible documentation is quite vague. Here more information about it.

The official documentation link,

https://docs.ansible.com/ansible/latest/reference_appendices/module_utils.html

Give you only the definition of the module class:
class ansible.module_utils.basic.AnsibleModule(argument_spec, bypass_checks=False, no_log=False, check_invalid_arguments=None, mutually_exclusive=None, required_together=None, required_one_of=None, add_file_common_args=False, supports_check_mode=False, required_if=None, required_by=None)

Here a useful blog that explains some of the options:

https://mobygeek.net/blog/2016/02/16/ansible-module-development-parameters/

And some extra notes about required_if:
Make sure you are consistent with the lists required. If you write:

required_if=[['show_uplink', 'True', 'vlanid']]

Ansible will give you:

TASK [Test] *
fatal: [host]: FAILED! => {“ansible_facts”: {“discovered_interpreter_python”: “/usr/bin/python”}, “changed”: false, “msg”: “show_uplink is True but all of the following are missing: v, l, a, n, i, d“}

You get the point.

Running ansible through python via subprocess

One way to achieving this is using the ansible API which all information is listed here:

https://docs.ansible.com/ansible/latest/dev_guide/developing_api.html

You can also find a library that will do this for you.

As an alternative, you can use subprocess, a native library, and run ansible as any other command:

import subprocess
cmd = ["ansible-playbook", "-i", "inventory.ini", "playbook.yml"]
 process = subprocess.Popen(cmd,stdout=subprocess.PIPE) 
 while True: 
         output = str(process.stdout.readline(), encoding="utf-8") 
         if process.poll() is not None: 
             break 
         else: 
             print(output)

    In this case the idea is to print line by line from python. But it can be modified to any other application.

Here some references:

https://www.endpoint.com/blog/2015/01/28/getting-realtime-output-using-python
https://github.com/uehara1414/ansible-subprocess/blob/master/ansible_subprocess/main.py

tkinter – grid, pack, canvas, scrolling

Omitting the basics of what each of these objects means (plenty of information in the web), will compile some tricks to go beyond simple layouts with tkinter.

Layout management

You cannot mixed different managers in the same container. You’ll get the famous error

_tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack

If the GUI you are creating requires a combination of these (e.g. displaying dataframes), the solution is using containers such as frames or canvas. Use pack to organize the containers inside the same window and then use grid (or any other) inside each container:

import tkinter as tk
parent = tk.Tk()
frame = tk.Frame(parent)frame.pack()
tk.Label(parent, text='label1').pack()
tk.Label(frame, text='label2').grid(row=0, column=0)
tk.Label(frame, text='label3').grid(row=0, column=1)
parent.mainloop() 

Result:

Scrolling

If you need scrolling for viewing multiple objects, a frame won’t work as it doesn’t support scrolling. One of the alternatives is to use the object canvas and insert a frame with the widgets you want on it:

import tkinter as tk
parent = tk.Tk()
frame = tk.Frame(parent)
frame.pack()
canvas = tk.Canvas(frame)
scrolly = tk.Scrollbar(frame, orient="vertical", command=canvas.yview)
frameCanvas = tk.Frame(canvas)
for i in range(20):
    tk.Label(frameCanvas, text='label %i' % i).pack()
canvas.create_window(0, 0, anchor='nw', window=frameCanvas)
canvas.configure(scrollregion=(0,0,100,500), yscrollcommand=scrolly.set)
canvas.pack(side='left')
scrolly.pack(fill='y', side='right')
parent.mainloop() 

Result:

Notice how the scroll region does not accurately match the position of the inner widgets. To get actual box size of the canvas, the canvas method bbox can be used. However remember to always update the canvas, otherwise you will get the size of the canvas when it was created:

...
canvas.create_window(0, 0, anchor='nw', window=frameCanvas)
canvas.update()
canvas.config(scrollregion=canvas.bbox('all'), yscrollcommand=scrolly.set)
canvas.pack(side='left')
scrolly.pack(fill='y', side='right')               
parent.mainloop() 

Result: