More careful variable extraction, without regexp

pull/1616/head
Ivan Gromov 2 years ago
parent 547711d83e
commit aa0fff068e

@ -1,9 +1,9 @@
import configparser
import json
import os
import re
import sys
from os.path import join, dirname, expanduser
from functools import reduce
import ansible_runner
import yaml
@ -55,12 +55,27 @@ task_program = ''
class Status:
RUNNING = 'running'
ERROR = 'error'
CANCELLED = 'cancelled'
DONE = 'done'
ERROR = 'failed'
TIMEOUT = 'timeout'
CANCELLED = 'canceled'
DONE = 'successful'
NEW = None
def by_path(data: dict, path: str):
def get(obj, attr):
if type(obj) is dict:
return obj.get(attr, None)
elif type(obj) is list:
try:
return obj[int(attr)]
except ValueError:
return None
else:
return None
return reduce(get, path.split('.'), data)
class Playbook:
def __init__(self):
@ -69,28 +84,40 @@ class Playbook:
self.events = []
self.config_vars = {}
self._runner = None
def parse(self, event: dict):
data = {}
if by_path(event, 'event_data.task') == 'Set subjectAltName as a fact':
ansible_ssh_host = by_path(event, 'event_data.res.ansible_facts.IP_subject_alt_name')
if ansible_ssh_host:
data['ansible_ssh_host'] = ansible_ssh_host
if by_path(event, 'event_data.play') == 'Configure the server and install required software':
local_service_ip = by_path(event, 'event_data.res.ansible_facts.ansible_lo.ipv4_secondaries.0.address')
ipv6 = by_path(event, 'event_data.res.ansible_facts.ansible_lo.ipv6.0.address')
p12_export_password = by_path(event, 'event_data.res.ansible_facts.p12_export_password')
if local_service_ip:
data['local_service_ip'] = local_service_ip
if ipv6:
data['ipv6'] = ipv6
if p12_export_password:
data['p12_export_password'] = p12_export_password
if by_path(event, 'event_data.play') == 'Provision the server':
host_name = by_path(event, 'event_data.res.add_host.host_name')
if host_name:
data['host_name'] = host_name
return data if data else None
def event_handler(self, data: dict) -> None:
if data['event'] == 'runner_on_ok':
# Looking for '-passout pass:"{{ CA_password }}"'
if 'Build the CA pair' in data['event_data']['task']:
m = re.match(r'-passout pass:\"(?P<password>.*)\"', data['event_data']['cmd'])
if m:
self.config_vars['CA_password'] = m.group('password')
# Looking for '-passout pass:"{{ p12_export_password }}"'
if "Build the client's p12" in data['event_data']['task']:
m = re.match(r'-passout pass:\"(?P<password>.*)\"', data['event_data']['cmd'])
if m:
self.config_vars['p12_export_password'] = m.group('password')
# Looking for 'DNS = {{ wireguard_dns_servers }}'
if "Generate QR codes" in data['event_data']['task']:
self.config_vars['host'] = data['event_data']['host']
m = re.match(r'DNS = (?P<dns>.*)\n\n', data['event_data']['cmd'])
if m:
self.config_vars['local_service_ip'] = m.group('dns')
self.events.append(data)
if self.parse(data):
self.config_vars.update(self.parse(data))
self.events.append(data)
def status_handler(self, status_data: dict, *args, **kwargs) -> None:
self.status = status_data.get('status')
def cancel_handler(self) -> bool:
if self.want_cancel:
@ -103,11 +130,14 @@ class Playbook:
def run(self, extra_vars: dict) -> None:
self.want_cancel = False
self.status = Status.RUNNING
_, runner = ansible_runner.run_async(private_data_dir='.',
playbook='main.yml',
extravars=extra_vars,
cancel_callback=self.cancel_handler,
event_handler=self.event_handler)
_, runner = ansible_runner.run_async(
private_data_dir='.',
playbook='main.yml',
extravars=extra_vars,
status_handler=self.status_handler,
cancel_callback=self.cancel_handler,
event_handler=self.event_handler
)
self._runner = runner
@ -282,12 +312,14 @@ async def check_vultr_config(request):
try:
open(os.environ['VULTR_API_CONFIG'], 'r').read()
response['has_secret'] = True
response['saved_to'] = os.environ.get('VULTR_API_CONFIG')
except IOError:
pass
try:
default_path = expanduser(join('~', '.vultr.ini'))
open(default_path, 'r').read()
response['has_secret'] = True
response['saved_to'] = default_path
except IOError:
pass
return web.json_response(response)

@ -71,10 +71,10 @@
<h1 class="mb-5 text-center" v-if="step === 'status-running'">
<span class="spin">🙂</span> Please be patient
</h1>
<h1 class="mb-5 text-center" v-if="step === 'status-error'">
<h1 class="mb-5 text-center" v-if="step === 'status-failed'">
😢 Set up failed
</h1>
<h1 class="mb-5 text-center" v-if="step === 'status-done'">
<h1 class="mb-5 text-center" v-if="step === 'status-successful'">
🥳 Congratulations, your Algo server is running!
</h1>
<h1 class="mb-5 text-center" v-if="step === 'status-exit'">
@ -82,7 +82,7 @@
</h1>
</h1>
<transition name="fade">
<div class="row" v-if="step == 'setup'">
<div class="row" v-if="step === 'setup'">
<user-config class="col-md-4 order-md-2 mb-4"></user-config>
<vpn-setup class="col-md-8 order-md-1"
v-bind:extra_args="extra_args"
@ -90,35 +90,35 @@
</div>
</transition>
<transition name="fade">
<provider-setup v-if="step == 'provider'"
<provider-setup v-if="step === 'provider'"
v-bind:extra_args="extra_args"
v-on:submit="step = 'command'">
</provider-setup>
</transition>
<transition name="fade">
<command-preview v-if="step == 'command'"
<command-preview v-if="step === 'command'"
v-bind:extra_args="extra_args"
v-on:submit="start(); step = 'status-running';">
</command-preview>
</transition>
<transition name="fade">
<status-running v-if="step == 'status-running'"
<status-running v-if="step === 'status-running'"
v-on:submit="stop(); step = 'setup';"
v-on:done="step = 'status-done'"
v-on:error="step = 'status-error'"
v-on:successful="step = 'status-successful'"
v-on:error="step = 'status-failed'"
v-on:cancelled="step = 'setup'">
</status-running>
</transition>
<transition name="fade">
<section v-if="step == 'status-error'" class="text-center">
<section v-if="step === 'status-failed'" class="text-center">
<p>Now its time to inspect console output</p>
<p>Restart console process to try again</p>
</section>
</transition>
<transition name="fade">
<status-done v-if="step == 'status-done'"
<status-successful v-if="step === 'status-successful'"
v-on:submit="exit(); step = 'status-exit'" >
</status-done>
</status-successful>
</transition>
</div>
@ -144,13 +144,13 @@
'provider-setup': window.httpVueLoader('/static/provider-setup.vue'),
'command-preview': window.httpVueLoader('/static/command-preview.vue'),
'status-running': window.httpVueLoader('/static/status-running.vue'),
'status-done': window.httpVueLoader('/static/status-done.vue')
'status-successful': window.httpVueLoader('/static/status-done.vue')
},
created() {
fetch("/playbook")
.then(r => r.json())
.catch(() => {
this.step = 'status-error';
this.step = 'status-failed';
})
.then(data => {
if (data.status && data.status !== 'cancelled'){

@ -85,6 +85,7 @@ module.exports = {
.then(response => {
if (response.has_secret) {
this.ui_token_from_env = true;
this.vultr_config = response.saved_to;
this.load_regions();
} else if (response.error) {
this.ui_config_error = response.error;
@ -138,10 +139,8 @@ module.exports = {
},
submit() {
let submit_value = {
region: this.region
}
if (!this.ui_token_from_env) {
submit_value['vultr_config'] = this.vultr_config;
region: this.region,
vultr_config: this.vultr_config
}
this.$emit("submit", submit_value);
},
@ -150,4 +149,4 @@ module.exports = {
"region-select": window.httpVueLoader("/static/region-select.vue"),
}
};
</script>
</script>

@ -7,7 +7,7 @@
<p v-if="result.local_service_ip">Local DNS resolver {{result.local_service_ip}}</p>
<p v-if="result.p12_export_password">The p12 and SSH keys password for new users is <code>{{result.p12_export_password}}</code></p>
<p v-if="result.CA_password">The CA key password is <code>{{result.CA_password}}</code></p>
<p v-if="result.ssh_access">Shell access: <code>ssh -F configs/{{result.ansible_ssh_host}}/ssh_config {{config.server_name}}</code></p>
<p v-if="result.ansible_ssh_host">Shell access: <code>ssh -F configs/{{result.ansible_ssh_host}}/ssh_config {{config.server_name}}</code></p>
<p>Read more on how to set up clients at the <a href="https://github.com/trailofbits/algo" target="_blank" rel="noopener noopener">Algo home page</a></p>
</section>
<section>

@ -8,7 +8,7 @@
</p>
<p>Dont close terminal!</p>
<transition-group name="console" tag="div">
<code class="console-item" v-for="(event, i) in last_n_events" v-bind:key="event.counter">[{{ event.counter }}]: {{ event.stdout }}</code>
<code class="console-item" v-for="(event, i) in last_n_events" v-bind:key="event.counter">{{ event.stdout }}</code>
</transition-group>
</section>
</template>
@ -43,8 +43,12 @@ module.exports = {
})
.then(data => {
this.events = data.events;
if (data.status && data.status === 'done') {
this.$emit('done');
if (data.status && data.status === 'successful') {
this.$emit('successful');
throw new Error();
}
if (data.status && data.status === 'failed') {
this.$emit('error');
throw new Error();
}
if (!data.status || data.status === 'cancelled') {

Loading…
Cancel
Save