Skip to content

Commit

Permalink
feat: wip - starting on trying to stream output to labyrinth
Browse files Browse the repository at this point in the history
  • Loading branch information
amunchet committed Nov 6, 2024
1 parent cdec697 commit 48c98db
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 78 deletions.
21 changes: 2 additions & 19 deletions backend/ansible_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,24 +185,7 @@ def run_ansible(
f.write(vault_password)

# Run ansible and return HTML
try:
a = ansible_runner.run(
private_data_dir=RUN_DIR,
playbook="{}.yml".format(playbook),
cmdline="-vvvvv --vault-password-file ../vault.pass",
)
raise Exception("Done.")
except Exception:
# Delete Vault Password
if "vault.pass" in os.listdir(RUN_DIR):
os.remove("{}/vault.pass".format(RUN_DIR))

if os.path.exists("/vault.pass"):
os.remove("/vault.pass")

z = ansi2html.Ansi2HTMLConverter()
output = z.convert("".join(a.stdout))
# Delete all files
shutil.rmtree(RUN_DIR)
return RUN_DIR, playbook

return output

52 changes: 43 additions & 9 deletions backend/serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
from PIL import Image
from pid import PidFile


import ansible_runner
import ansible_helper

from concurrent.futures import ThreadPoolExecutor
Expand Down Expand Up @@ -1197,6 +1199,7 @@ def run_ansible(inp_data=""): # pragma: no cover
data = request.form.get("data")
else: # pragma: no cover
return "Invalid data", 481


data = json.loads(data)
if (
Expand All @@ -1210,17 +1213,48 @@ def run_ansible(inp_data=""): # pragma: no cover
if "ssh_key" not in data:
data["ssh_key"] = ""

return (
ansible_helper.run_ansible(
data["hosts"],
data["playbook"],
data["vault_password"],
data["become_file"],
ssh_key_file=data["ssh_key"],
),
200,

RUN_DIR, playbook = ansible_helper.run_ansible(
data["hosts"],
data["playbook"],
data["vault_password"],
data["become_file"],
ssh_key_file=data["ssh_key"],
)

try:
thread,runner = ansible_runner.run_async(
private_data_dir=RUN_DIR,
playbook="{}.yml".format(playbook),
cmdline="-vvvvv --vault-password-file ../vault.pass",
)
except Exception as e:
# Delete Vault Password
if "vault.pass" in os.listdir(RUN_DIR):
os.remove("{}/vault.pass".format(RUN_DIR))

if os.path.exists("/vault.pass"):
os.remove("/vault.pass")
shutil.rmtree(RUN_DIR)
return f"Error: {e}", 200

def ansible_stream():
while thread.is_alive():
line = runner.stdout.readline()
if line:
yield line
else:
time.sleep(0.1) # Prevent busy waiting


if os.path.exists("/vault.pass"):
os.remove("/vault.pass")

# Delete all files
shutil.rmtree(RUN_DIR)

return Response(ansible_stream(), mimetype='text/plain')


@app.route("/mac/<old_mac>/<new_mac>/")
@requires_auth_write
Expand Down
53 changes: 41 additions & 12 deletions frontend/labyrinth/src/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,34 +148,63 @@ export default {
command,
auth,
arr,
isUpload
isUpload,
raw
) /* istanbul ignore next */ {
var profile = auth["profile"]["email"];
var full_url = "";
if (window.location.host.indexOf(devel_port) != -1) {
if (window.location.host.indexOf(devel_port) !== -1) {
full_url = local_backend + url;
} else {
full_url = "/api/" + url;
}

console.log(url);
console.log(service);
console.log(command)
console.log(auth)
console.log(arr)
console.log(isUpload)
console.log(raw)





return auth.getAccessToken().then((accessToken) => {
let headers;
headers = {
let headers = {
Authorization: `Bearer ${accessToken}`,
Email: profile,
};

if (isUpload != undefined) {
if (isUpload !== undefined) {
headers["Content-Type"] = "multipart/form-data";
}

return axios({
method: "post",
url: full_url + service + "/" + command,
data: arr,
return fetch(full_url + service + "/" + command, {
method: "POST",
headers: headers,
}).then((response) => {
return response.data;
});
body: arr,
})
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return raw ? response : response.text();
})
.then((data) => {
if (raw === undefined) {
return data;
} else {
console.log("RETVAL");
console.log(data);
return data;
}
})
.catch((error) => {
console.error("Error:", error);
throw error;
});
});
},
};
81 changes: 43 additions & 38 deletions frontend/labyrinth/src/views/Deploy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,8 @@
>Deploy to host<span v-if="ips.length != 0">s</span></b-button
>
<hr />
AAAA:
{{playbook_result}}
<div
class="playbook_result mb-4"
v-html="$sanitize(playbook_result)"
Expand Down Expand Up @@ -760,7 +762,7 @@ export default {
},
runPlaybook: /* istanbul ignore next */ async function () {
if (this.selected["become"] == "") {
if (this.selected["become"] === "") {
this.$store.commit(
"updateError",
"Error: No Become Password file selected"
Expand All @@ -770,52 +772,55 @@ export default {
let auth = this.$auth;
this.running = true;
if (this.ips.length > 0) {
this.ips.forEach((host) => {
let formData = new FormData();
let data = {
hosts: host,
playbook: this.selected_playbook.replace(".yml", ""),
vault_password: this.vault_password,
become_file: this.selected["become"].replace(".yml", ""),
ssh_key: this.selected["ssh"],
};
formData.append("data", JSON.stringify(data));
this.$forceUpdate();
Helper.apiPost("ansible_runner", "", "", auth, formData)
.then((res) => {
this.playbook_results[host] = res;
this.$forceUpdate();
})
.catch((e) => {
this.$store.commit("updateError", e);
});
});
return true;
}
let formData = new FormData();
let host = this.selected_host;
this.playbook_loaded = false;
// Prepare data for the API call
let data = {
hosts: host,
hosts: this.ips.length > 0 ? this.ips.join(",") : this.selected_host,
playbook: this.selected_playbook.replace(".yml", ""),
vault_password: this.vault_password,
become_file: this.selected["become"].replace(".yml", ""),
ssh_key: this.selected["ssh"],
};
// Use FormData to prepare the request
let formData = new FormData();
formData.append("data", JSON.stringify(data));
Helper.apiPost("ansible_runner", "", "", auth, formData)
.then((res) => {
this.playbook_result = res;
this.playbook_loaded = true;
})
.catch((e) => {
this.$store.commit("updateError", e);
this.playbook_loaded = true;
});
try {
// Use apiPost to initiate the streaming response
let response = await Helper.apiPost(
"ansible_runner", // URL
"", // Service (empty string if not needed)
"", // Command (empty string if not needed)
auth, // Auth object
formData, // Data
false, // isUpload set to true for multipart/form-data
1
);
// Handle the streaming response
console.log(response)
const reader = response.body.getReader();
const decoder = new TextDecoder("utf-8");
let result = "";
let truth = 1
// Read the response stream
while (truth) {
const { done, value } = await reader.read();
if (done) break; // End of stream
result += decoder.decode(value, { stream: true });
this.playbook_result = result; // Update the result
this.$forceUpdate(); // Re-render the component
}
} catch (error) {
// Handle any errors
console.log(error)
this.$store.commit("updateError", error);
} finally {
this.running = false;
this.playbook_loaded = true;
}
},
loadIP: /* istanbul ignore next */ async function () {
Expand Down

0 comments on commit 48c98db

Please sign in to comment.