fabric commands examples fabric

Useof Connection, cd, run

from fabric import Connection

## Define your remote server's hostname and your username
hostname = "load-testing"
username = "pvergain"

## Create a connection to the remote server
c = Connection(host=hostname, user=username)

## Run a shell command on the remote server
with c.cd("~/informatique/terraform/tf-debian-packer/environments/bioseal"):
    result = c.run('uname -a')
    result = c.run('ls -als')

Use of Connection, cd, put, run

from fabric import Connection
c = Connection('web1')
c.put('myfiles.tgz', '/opt/mydata')
c.run('tar -C /opt/mydata -xzvf /opt/mydata/myfiles.tgz')

You could (but don’t have to) turn such blocks of code into functions, parameterized with a Connection object from the caller, to encourage reuse:

def upload_and_unpack(c):
    c.put('myfiles.tgz', '/opt/mydata')
    c.run('tar -C /opt/mydata -xzvf /opt/mydata/myfiles.tgz')

As you’ll see below, such functions can be handed to other API methods to enable more complex use cases as well.

Use of SerialGroup, run

In [6]: from fabric import SerialGroup
In [7]: result = SerialGroup("load-testing").run('hostname')
load-testing

In [8]:
def disk_free(c):
    uname = c.run('uname -s', hide=True)
    if 'Linux' in uname.stdout:
        command = "df -h / | tail -n1 | awk '{print $5}'"
        return c.run(command, hide=True).stdout.strip()
    err = "No idea how to get disk space on {}!".format(uname)
    raise Exit(err)
print(disk_free(Connection('load-testing')))
3%

Use of the fab command + task, cd, run

A fabfile.py example

 1 """fabfile.py
 2
 3 Calling examples
 4 ===================
 5
 6 - fab --list
 7 - fab -H machine uname
 8 - fab -H machine update
 9 """
10 from fabric import task
11
12
13 ## Define a task to upgrade the remote server's packages
14 @task
15 def uname(c):
16     c.run('uname -a')
17
18
19 ## Define a task to update the remote server's package index
20 @task
21 def update(c):
22     with c.cd('/tmp'):
23         c.run('sudo apt-get update')
24
25 ## Define a task to upgrade the remote server's packages
26 @task
27 def upgrade(c):
28     with c.cd('/tmp'):
29         c.run('sudo apt-get upgrade -y')
30
31 ## Define a task to install a package on the remote server
32 @task
33 def install_package(c, package_name):
34     with c.cd('/tmp'):
35         c.run(f'sudo apt-get install -y {package_name}')

Use of the fab command + task, cd, run + git + c.config.run.env (environment variables) + stderr

  1 """fabfile.py
  2
  3 Calling examples
  4
  5 - fab -H load-testing build-vm
  6 - fab -H load-testing update-compose--infra
  7 - fab -H load-testing build--api
  8 - fab -H load-testing load-testing
  9
 10 """
 11
 12 import os
 13
 14 from fabric import task
 15 from jinja2 import Environment
 16 from jinja2 import FileSystemLoader
 17
 18
 19 credentials_vsphere_password = os.getenv("SUT_CREDENTIALS_VSPHERE_PASSWORD")
 20 vsphere_vm_cpu = os.getenv("SUT_VSPHERE_VM_CPU")  # Example: 2, 4, 8, 10
 21 vsphere_vm_memory = os.getenv("SUT_VSPHERE_VM_MEMORY")  # Example : 4096
 22 pool_size = int(os.getenv("SUT_POOL_SIZE"))
 23 thead_count = int(os.getenv("SUT_THREAD_COUNT"))
 24 xmx = int(vsphere_vm_memory) // 1024
 25 xmx_g = f"{xmx}g"
 26 memory_g = f"{xmx}g"
 27
 28
 29 command_create_terraform = (
 30     f"""terraform apply
 31     -var credentials_vpshere_user=terraform
 32     -var credentials_vsphere_password={credentials_vsphere_password}
 33     -var vsphere_vm_cpu={vsphere_vm_cpu} -var vsphere_vm_memory={vsphere_vm_memory}
 34     -auto-approve
 35     """
 36 ).replace("\n", " ")
 37
 38 command_destroy_terraform = (
 39     f"""terraform destroy
 40     -var credentials_vpshere_user=terraform
 41     -var credentials_vsphere_password={credentials_vsphere_password}
 42     -var vsphere_vm_cpu={vsphere_vm_cpu} -var vsphere_vm_memory={vsphere_vm_memory}
 43     -auto-approve
 44     """
 45 ).replace("\n", " ")
 46
 47
 48 @task
 49 def build_debian(c):
 50     """Step 1. Build debian 12 template once a month"""
 51     try:
 52         command_curl = 'curl --request POST --header "PRIVATE-TOKEN: glpat-4yrxr9NXi4Ghsfvd2TC1" "https://gitlab.xx/api/v4/projects/672/pipeline?ref=benchmark_pv"'
 53         c.run(command_curl)
 54     except Exception as error:
 55         print(f"{error=}")
 56
 57
 58 @task
 59 def apply_vm(c):
 60     """Step 2. Create the virtual machine -benchmark.xx
 61     with the 2 parameters
 62
 63     - vsphere_vm_cpu
 64     - vsphere_vm_memory
 65
 66     See: https://pv_biometrics.gitlab.xx/applis/tools/locust-ci-doc/installations/sut/2-creer--benchmark/2-creer--benchmark.html
 67     """
 68     try:
 69         print(f"{vsphere_vm_cpu=} {vsphere_vm_memory=}")
 70         with c.cd("~/informatique/terraform/tf-debian-packer/environments/bioseal"):
 71             c.run("uname -a")
 72             c.run("ls -als")
 73             c.run(command_create_terraform)
 74     except Exception as error:
 75         print(f"{error=}")
 76
 77
 78 @task
 79 def destroy_vm(c):
 80     try:
 81         with c.cd("~/informatique/terraform/tf-debian-packer/environments/bioseal"):
 82             c.run("uname -a")
 83             c.run("ls -als")
 84             c.run(command_destroy_terraform)
 85     except Exception as error:
 86         print(f"{error=}")
 87
 88
 89 def build_docker_compose_file() -> None:
 90     """Part of Step 3. Build a docker-compose.yml file with a jinja2 template file
 91     and 5 variables:
 92
 93     - vsphere_vm_memory
 94     - xmx
 95     - memory
 96     - pool_size
 97     - thead_count
 98     """
 99     env = Environment(loader=FileSystemLoader("templates"))
100     compose_template = env.get_template("docker-compose.yml.jinja2")
101     print(f"{pool_size=} {thead_count=} {xmx_g=} {memory_g=}")
102     context = {
103         "vsphere_vm_memory": vsphere_vm_memory,
104         "xmx": xmx_g,
105         "memory": memory_g,
106         "pool_size": pool_size,
107         "thead_count": thead_count,
108     }
109     docker_compose_file = "docker-compose.yml"
110     with open(docker_compose_file, mode="w", encoding="utf-8") as compose:
111         compose.write(compose_template.render(context))
112         print(f"... wrote {docker_compose_file}")
113
114
115 @task
116 def update_compose_infra(c):
117     """Step 3.1 Update the Informatique/biosdeal-infra docker-compose.yml file
118
119     Calling update-compose-_infra task
120     ============================================
121
122     ::
123
124         fab -H load-testing update-compose--infra
125
126     See
127
128     - https://gitlab.xx/Informatique/-infra/-/blob/benchmark-pv/deployment/compose/docker-compose.yml?ref_type=heads
129     - https://gitlab.xx/Informatique/-infra/-/commits/benchmark-pv
130     """
131     try:
132         build_docker_compose_file()
133         with c.cd("~/informatique/-infra/deployment/compose"):
134             c.run("git switch benchmark-pv")
135             c.put(
136                 "docker-compose.yml",
137                 "/home/pvergain/informatique/-infra/deployment/compose/",
138             )
139             # c.run("cat docker-compose.yml")
140             c.run("git add .")
141             # see https://gitlab.xx/Informatique/-infra/-/commits/benchmark-pv
142             c.run(
143                 f"git commit -m 'Update docker-compose {pool_size=} {thead_count=} {vsphere_vm_cpu=} {vsphere_vm_memory=} {xmx=}'"
144             )
145             c.run("git branch")
146             c.run("git push")
147     except Exception as error:
148         print(f"Exception: {error=}")
149
150
151 @task
152 def build_api(c):
153     """Step 3.2 install the -api on the -benchmark.xx. Apparemment pas nécessaire.
154
155     Calling build--api
156     ============================
157
158     ::
159
160         fab -H load-testing build--api
161
162     See
163
164     - https://gitlab.xx/Informatique/-infra/-/pipelines
165     """
166     try:
167         command_curl = 'curl --request POST --header "PRIVATE-TOKEN: XXXXXXXXXXXx" "https://gitlab.xx/api/v4/projects/207/pipeline?ref=benchmark-pv"'
168         c.run(command_curl)
169     except Exception as error:
170         print(f"{error=}")
171
172
173 @task
174 def load_testing(c):
175     """Step 4 the loading tests
176     ::
177
178         fab -H load-testing load-testing
179
180     See
181
182     - https://gitlab.xx/biometrics/applis/tools/benchmark/-/boards
183     """
184     try:
185         with c.cd("~/biometrics/applis/tools/locust-ci"):
186             c.config.run.env = {
187                 "SUT_SERVER": os.getenv("SUT_SERVER"),
188                 "SUT_API_KEY": os.getenv("SUT_API_KEY"),
189                 "LOCUST_NB_USERS": os.getenv("LOCUST_NB_USERS"),
190                 "LOCUST_RUN_TIME": os.getenv("LOCUST_RUN_TIME"),
191                 "LOCUST_SPAWN_RATE": os.getenv("LOCUST_SPAWN_RATE"),
192                 "LOCUST_TIMESCALE": os.getenv("LOCUST_TIMESCALE"),
193                 "LOCUST_GRAFANA_URL": os.getenv("LOCUST_GRAFANA_URL"),
194                 "PGHOST": os.getenv("PGHOST"),
195                 "PGPORT": os.getenv("PGPORT"),
196                 "PGUSER": os.getenv("PGUSER"),
197                 "PGDATABASE": os.getenv("PGDATABASE"),
198                 "PGPASSWORD": os.getenv("PGPASSWORD"),
199             }
200             result = c.run("source .venv/bin/activate; type locust; ./send_locust_commands.bash", hide=True)
201             print(f"{result=}")
202             for line in result.stderr.split('\n'):
203                 if 'Report' in line:
204                     s = line.split('Report:')
205                     print(f"The report is here:{s[-1].strip()}")
206
207     except Exception as error:
208         print(f"{error=}")