Removes a lot of innecesaries directories generated by composer install
ogdhcp/pipeline/tag There was a failure building this commit
Details
ogdhcp/pipeline/tag There was a failure building this commit
Details
parent
44a73d0bbf
commit
5f07a03986
Binary file not shown.
Before Width: | Height: | Size: 665 B |
Binary file not shown.
Before Width: | Height: | Size: 628 B |
|
@ -1,16 +0,0 @@
|
|||
html {
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: #fafafa;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<!-- HTML for static distribution bundle build -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Swagger UI</title>
|
||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
|
||||
<link rel="stylesheet" type="text/css" href="index.css" />
|
||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
|
||||
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
|
||||
<script src="./swagger-initializer.js" charset="UTF-8"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,9 +0,0 @@
|
|||
<?php
|
||||
|
||||
use App\Kernel;
|
||||
|
||||
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
|
||||
|
||||
return function (array $context) {
|
||||
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||
};
|
|
@ -1,79 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title>Swagger UI: OAuth2 Redirect</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
'use strict';
|
||||
function run () {
|
||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||
var sentState = oauth2.state;
|
||||
var redirectUrl = oauth2.redirectUrl;
|
||||
var isValid, qp, arr;
|
||||
|
||||
if (/code|token|error/.test(window.location.hash)) {
|
||||
qp = window.location.hash.substring(1).replace('?', '&');
|
||||
} else {
|
||||
qp = location.search.substring(1);
|
||||
}
|
||||
|
||||
arr = qp.split("&");
|
||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
|
||||
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||
function (key, value) {
|
||||
return key === "" ? value : decodeURIComponent(value);
|
||||
}
|
||||
) : {};
|
||||
|
||||
isValid = qp.state === sentState;
|
||||
|
||||
if ((
|
||||
oauth2.auth.schema.get("flow") === "accessCode" ||
|
||||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
|
||||
oauth2.auth.schema.get("flow") === "authorization_code"
|
||||
) && !oauth2.auth.code) {
|
||||
if (!isValid) {
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "warning",
|
||||
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
|
||||
});
|
||||
}
|
||||
|
||||
if (qp.code) {
|
||||
delete oauth2.state;
|
||||
oauth2.auth.code = qp.code;
|
||||
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
||||
} else {
|
||||
let oauthErrorMsg;
|
||||
if (qp.error) {
|
||||
oauthErrorMsg = "["+qp.error+"]: " +
|
||||
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
||||
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
||||
}
|
||||
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "error",
|
||||
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
|
||||
});
|
||||
}
|
||||
} else {
|
||||
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
||||
}
|
||||
window.close();
|
||||
}
|
||||
|
||||
if (document.readyState !== 'loading') {
|
||||
run();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
run();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,20 +0,0 @@
|
|||
window.onload = function() {
|
||||
//<editor-fold desc="Changeable Configuration Block">
|
||||
|
||||
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
|
||||
window.ui = SwaggerUIBundle({
|
||||
url: "http://192.168.0.27:8080/swagger.json",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
});
|
||||
|
||||
//</editor-fold>
|
||||
};
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,549 +0,0 @@
|
|||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "Ogdhcp API",
|
||||
"version": "1.0"
|
||||
},
|
||||
"paths": {
|
||||
"/opengnsys3/rest/dhcp/subnets": {
|
||||
"get": {
|
||||
"operationId": "8f92a1cbcb8cd176bdc4ae272b3ad303",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Devuelve todas las subredes",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Subnet"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Error al obtener las subredes"
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"summary": "Add a new DHCP subnet",
|
||||
"operationId": "88949bae5e7784ce2721ffafe7c88c0a",
|
||||
"requestBody": {
|
||||
"description": "JSON payload",
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"subnetId": {
|
||||
"type": "integer",
|
||||
"example": 2
|
||||
},
|
||||
"mask": {
|
||||
"type": "string",
|
||||
"example": "255.255.255.0"
|
||||
},
|
||||
"address": {
|
||||
"type": "string",
|
||||
"example": "192.168.1.0"
|
||||
},
|
||||
"nextServer": {
|
||||
"type": "string",
|
||||
"example": "192.168.1.1"
|
||||
},
|
||||
"bootFileName": {
|
||||
"type": "string",
|
||||
"example": "pxelinux.0"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Subnet added successfully",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Error occurred",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/opengnsys3/rest/dhcp/subnets/{subnetId}": {
|
||||
"put": {
|
||||
"summary": "Modify a DHCP subnet",
|
||||
"operationId": "548b55fc0e1ad59ea5b5c909dfd07c71",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "subnetId",
|
||||
"in": "path",
|
||||
"description": "ID of the subnet to modify",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"description": "Data to modify the subnet",
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"mask": {
|
||||
"type": "string"
|
||||
},
|
||||
"address": {
|
||||
"type": "string"
|
||||
},
|
||||
"nextServer": {
|
||||
"type": "string"
|
||||
},
|
||||
"bootFileName": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Subnet modified successfully",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Error occurred",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Delete a DHCP subnet",
|
||||
"operationId": "c1c1c34729bdd85857b22e6e2bdc41de",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "subnetId",
|
||||
"in": "path",
|
||||
"description": "ID of the subnet to delete",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Subnet deleted successfully",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Error occurred",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts": {
|
||||
"get": {
|
||||
"summary": "Get all hosts in a subnet",
|
||||
"operationId": "0989ca622a6a7e23f5af8e3bdd6f6b05",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "subnetId",
|
||||
"in": "path",
|
||||
"description": "The ID of the subnet",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "List of hosts in the subnet",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Host"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Error occurred",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Server error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"summary": "Update a DHCP host",
|
||||
"operationId": "1541441cd53685aaf6df45ab48befaa8",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "subnetId",
|
||||
"in": "path",
|
||||
"description": "The ID of the subnet",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"description": "Data for the host to update",
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"host": {
|
||||
"type": "string",
|
||||
"example": "pc11"
|
||||
},
|
||||
"oldMacAddress": {
|
||||
"type": "string",
|
||||
"example": "56:6f:c7:4f:00:4f"
|
||||
},
|
||||
"oldAddress": {
|
||||
"type": "string",
|
||||
"example": "192.168.1.11"
|
||||
},
|
||||
"macAddress": {
|
||||
"type": "string",
|
||||
"example": "56:6f:c7:4f:01:01"
|
||||
},
|
||||
"address": {
|
||||
"type": "string",
|
||||
"example": "192.168.1.11"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Host updated successfully",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Error occurred",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"summary": "Add a DHCP host to a subnet",
|
||||
"operationId": "3f897dcd7c04787ac9c42ddbb57cb800",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "subnetId",
|
||||
"in": "path",
|
||||
"description": "ID of the subnet to add the host to",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"description": "Data for the new host",
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"host": {
|
||||
"type": "string",
|
||||
"example": "pc11"
|
||||
},
|
||||
"macAddress": {
|
||||
"type": "string",
|
||||
"example": "56:6f:c7:4f:00:4f"
|
||||
},
|
||||
"address": {
|
||||
"type": "string",
|
||||
"example": "172.30.4.11"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Host added successfully",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Error occurred",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Delete a DHCP host from a specific subnet",
|
||||
"operationId": "f652c52b39d57d283401df66a7930b5f",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "subnetId",
|
||||
"in": "path",
|
||||
"description": "The ID of the subnet",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"description": "Data for the host to delete",
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"host": {
|
||||
"type": "string",
|
||||
"example": "pc11"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Host deleted successfully",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Error occurred",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Subnet": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "The ID of the subnet",
|
||||
"type": "integer"
|
||||
},
|
||||
"subnet": {
|
||||
"description": "The name of the subnet",
|
||||
"type": "string"
|
||||
},
|
||||
"next-server": {
|
||||
"description": "The next server in the subnet",
|
||||
"type": "string"
|
||||
},
|
||||
"boot-file-name": {
|
||||
"description": "The boot file name for the subnet",
|
||||
"type": "string"
|
||||
},
|
||||
"reservations": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "The reservations in the subnet",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"Host": {
|
||||
"properties": {
|
||||
"host": {
|
||||
"type": "string",
|
||||
"example": "pc11"
|
||||
},
|
||||
"macAddress": {
|
||||
"type": "string",
|
||||
"example": "56:6f:c7:4f:00:4f"
|
||||
},
|
||||
"address": {
|
||||
"type": "string",
|
||||
"example": "172.30.4.11"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}Welcome!{% endblock %}</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text></svg>">
|
||||
{# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
|
||||
{% block stylesheets %}
|
||||
{{ encore_entry_link_tags('app') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ encore_entry_script_tags('app') }}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
|
@ -1,20 +0,0 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Hello DhcpController!{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<style>
|
||||
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
|
||||
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
|
||||
</style>
|
||||
|
||||
<div class="example-wrapper">
|
||||
<h1>Hello {{ controller_name }}! ✅</h1>
|
||||
|
||||
This friendly message is coming from:
|
||||
<ul>
|
||||
<li>Your controller at <code><a href="{{ '/home/luis/dhcp_symfony/src/Controller/DhcpController.php'|file_link(0) }}">src/Controller/DhcpController.php</a></code></li>
|
||||
<li>Your template at <code><a href="{{ '/home/luis/dhcp_symfony/templates/dhcp/index.html.twig'|file_link(0) }}">templates/dhcp/index.html.twig</a></code></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,118 +0,0 @@
|
|||
pipeline {
|
||||
agent {
|
||||
node {
|
||||
label 'jenkins-slave'
|
||||
}
|
||||
}
|
||||
options {
|
||||
// Deshabilita ejecuciones concurrentes
|
||||
disableConcurrentBuilds()
|
||||
}
|
||||
environment {
|
||||
ESXI_PASS = credentials('VI_PASSWORD')
|
||||
QINDEL_PASS = credentials('jenkins-user-slave-password')
|
||||
PATH = "/home/qindel/bin/ovftool:${env.PATH}"
|
||||
}
|
||||
stages {
|
||||
stage('Prepare environment') {
|
||||
steps {
|
||||
dir ('tests/API-dhcp') {
|
||||
echo "Install vagrant plugin"
|
||||
sh '''
|
||||
if ! vagrant plugin list | grep -q vagrant-vmware-esxi; then
|
||||
echo "Vagrant plugin vagrant-vmware-esxi not found. Installing..."
|
||||
vagrant plugin install vagrant-vmware-esxi
|
||||
else
|
||||
echo "Vagrant plugin vagrant-vmware-esxi is already installed."
|
||||
fi
|
||||
'''
|
||||
echo "Deploy API server for DHCP with Vagrant"
|
||||
sh 'vagrant up --provider=vmware_esxi --provision'
|
||||
echo 'Create Python venv to work with robotframework'
|
||||
sh '''
|
||||
python3 -m venv robotframework
|
||||
. robotframework/bin/activate
|
||||
pip install -r requirements.txt
|
||||
'''
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Check Installation') {
|
||||
steps {
|
||||
dir ('tests/API-dhcp') {
|
||||
echo "Get IP of API server for DHCP with Vagrant"
|
||||
sh '''
|
||||
set -e
|
||||
new_ip=$(vagrant ssh -c "hostname -I" | tr -d '\r\n' | sed 's/^[^0-9]*//' | sed 's/[[:space:]]*$//')
|
||||
echo $new_ip > ip.txt
|
||||
echo "$QINDEL_PASS" | sudo -S bash -c "echo '$new_ip api-test' >> /etc/hosts"
|
||||
echo "IP: $new_ip"
|
||||
curl -X 'GET' "http://$new_ip/ogdhcp/v1/subnets" -H 'accept: /'
|
||||
'''
|
||||
script {
|
||||
def new_ip = readFile('ip.txt').trim()
|
||||
env.NEW_IP = new_ip
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Run API tests') {
|
||||
steps {
|
||||
dir ('tests/API-dhcp') {
|
||||
|
||||
echo 'Running API tests'
|
||||
|
||||
sh '''
|
||||
. robotframework/bin/activate
|
||||
robot --variable BASE_URL:http://${NEW_IP}/ogdhcp/v1 -d results/ robot/
|
||||
'''
|
||||
}
|
||||
// Aquí incluirías los comandos para ejecutar tus pruebas
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
// Si el trabajo ha sido exitoso, destruir la máquina de Vagrant
|
||||
echo "El trabajo ha finalizado con éxito. Destruyendo máquina Vagrant..."
|
||||
dir ('tests/API-dhcp') {
|
||||
sh 'vagrant destroy -f'
|
||||
}
|
||||
}
|
||||
always {
|
||||
// Recoger los resultados de los tests
|
||||
dir ('tests/API-dhcp') {
|
||||
robot outputPath: 'results',
|
||||
outputFileName: 'output.xml',
|
||||
logFileName: 'log.html',
|
||||
reportFileName: 'report.html',
|
||||
passThreshold: 100.0,
|
||||
unstableThreshold: 75.0
|
||||
}
|
||||
// Siempre se ejecutará, independientemente del resultado
|
||||
script {
|
||||
// Elimina la entrada del /etc/hosts
|
||||
sh "echo '$QINDEL_PASS' | sudo -S sed -i '/api-test/d' /etc/hosts"
|
||||
def recipientEmail = env.BUILD_USER_EMAIL ?: getCommitterEmail()
|
||||
|
||||
mail to: recipientEmail,
|
||||
subject: "Jenkins Job Completed: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
|
||||
body: """
|
||||
El job '${env.JOB_NAME}' con número de build ${env.BUILD_NUMBER} ha finalizado.
|
||||
|
||||
Estado: ${currentBuild.currentResult}
|
||||
|
||||
Revisa los detalles del build en: ${env.BUILD_URL}
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def getCommitterEmail() {
|
||||
return sh(
|
||||
script: 'git log -1 --pretty=format:"%ae"',
|
||||
returnStdout: true
|
||||
).trim()
|
||||
}
|
|
@ -1,163 +0,0 @@
|
|||
#
|
||||
# Fully documented Vagrantfile available
|
||||
# in the wiki: https://github.com/josenk/vagrant-vmware-esxi/wiki
|
||||
|
||||
$script = <<SCRIPT
|
||||
SERVER_NAME=localhost
|
||||
echo "Provisioning with shell script..."
|
||||
cd /vagrant/installer
|
||||
chmod +x ogdhcp_installer.sh && ./ogdhcp_installer.sh
|
||||
SCRIPT
|
||||
|
||||
Vagrant.configure('2') do |config|
|
||||
config.vm.box = 'dummy'
|
||||
VM_TEMPLATE = 'template-ubuntu24'
|
||||
# Use rsync and NFS synced folders. (or use the option to disable them)
|
||||
# https://www.vagrantup.com/docs/synced-folders/
|
||||
#config.vm.synced_folder('.', '/vagrant', type: 'rsync')
|
||||
config.vm.synced_folder('../../', '/vagrant', type: 'rsync')
|
||||
|
||||
# Vagrant can configure additional network interfaces using a static IP or
|
||||
# DHCP. Use public_network or private_network to manually set a static IP and
|
||||
# optionally netmask. ESXi doesn't use the concept of public or private
|
||||
# networks so both are valid here. The primary network interface is considered the
|
||||
# "vagrant management" interface and cannot be changed and this plugin
|
||||
# supports 10 NICS, so you can specify 9 entries here!
|
||||
#
|
||||
# https://www.vagrantup.com/docs/networking/public_network.html
|
||||
# https://www.vagrantup.com/docs/networking/private_network.html
|
||||
#
|
||||
# *** Invalid settings could cause 'vagrant up' to fail ***
|
||||
#config.vm.network 'private_network', ip: '192.168.10.170', netmask: '255.255.255.0'
|
||||
#config.vm.network 'private_network', ip: '192.168.11.170'
|
||||
#config.vm.network 'public_network', ip: '192.168.12.170'
|
||||
|
||||
#
|
||||
# Provider (esxi) settings
|
||||
#
|
||||
config.vm.provision 'shell', inline: $script
|
||||
config.vm.provider :vmware_esxi do |esxi|
|
||||
|
||||
# REQUIRED! ESXi hostname/IP
|
||||
esxi.esxi_hostname = 'esxi-jenkins.evlt.uma.es'
|
||||
|
||||
# ESXi username
|
||||
esxi.esxi_username = 'root'
|
||||
|
||||
# IMPORTANT! Set ESXi password.
|
||||
# 1) 'prompt:'
|
||||
# 2) 'file:' or 'file:my_secret_file'
|
||||
# 3) 'env:' or 'env:my_secret_env_var'
|
||||
# 4) 'key:' or key:~/.ssh/some_ssh_private_key'
|
||||
# 5) or esxi.esxi_password = 'my_esxi_password'
|
||||
#
|
||||
esxi.esxi_password = 'env:ESXI_PASS'
|
||||
|
||||
# SSH port.
|
||||
#esxi.esxi_hostport = 22
|
||||
|
||||
# HIGHLY RECOMMENDED! ESXi Virtual Network
|
||||
# You should specify an ESXi Virtual Network! If it's not specified, the
|
||||
# default is to use the first found. You can specify up to 10 virtual
|
||||
# networks using an array format.
|
||||
esxi.esxi_virtual_network = ['vLan_742']
|
||||
|
||||
# OPTIONAL. Specify a Disk Store
|
||||
#esxi.esxi_disk_store = 'DS_001'
|
||||
|
||||
# OPTIONAL. Resource Pool
|
||||
# Vagrant will NOT create a Resource pool it for you.
|
||||
esxi.esxi_resource_pool = '/'
|
||||
|
||||
# Optional. Specify a VM to clone instead of uploading a box.
|
||||
# Vagrant can use any stopped VM as the source 'box'. The VM must be
|
||||
# registered, stopped and must have the vagrant insecure ssh key installed.
|
||||
# If the VM is stored in a resource pool, it must be specified.
|
||||
# See wiki: https://github.com/josenk/vagrant-vmware-esxi/wiki/How-to-clone_from_vm
|
||||
esxi.clone_from_vm = VM_TEMPLATE
|
||||
|
||||
# OPTIONAL. Guest VM name to use.
|
||||
# The Default will be automatically generated.
|
||||
#esxi.guest_name = 'Custom-Guest-VM_Name'
|
||||
|
||||
# OPTIONAL. When automatically naming VMs, use this prefix.
|
||||
#esxi.guest_name_prefix = 'V-'
|
||||
|
||||
# OPTIONAL. Set the guest username login. The default is 'vagrant'.
|
||||
#esxi.guest_username = 'vagrant'
|
||||
|
||||
# OPTIONAL. Memory size override
|
||||
#esxi.guest_memsize = '2048'
|
||||
|
||||
# OPTIONAL. Virtual CPUs override
|
||||
#esxi.guest_numvcpus = '2'
|
||||
|
||||
# OPTIONAL & RISKY. Specify up to 10 MAC addresses
|
||||
# The default is ovftool to automatically generate a MAC address.
|
||||
# You can specify an array of MAC addresses using upper or lower case,
|
||||
# separated by colons ':'.
|
||||
#esxi.guest_mac_address = ['00:50:56:aa:bb:cc', '00:50:56:01:01:01','00:50:56:02:02:02','00:50:56:BE:AF:01' ]
|
||||
|
||||
# OPTIONAL & RISKY. Specify a guest_nic_type
|
||||
# The validated list of guest_nic_types are 'e1000', 'e1000e', 'vmxnet',
|
||||
# 'vmxnet2', 'vmxnet3', 'Vlance', and 'Flexible'.
|
||||
#esxi.guest_nic_type = 'e1000'
|
||||
|
||||
# OPTIONAL. Specify a disk type.
|
||||
# If unspecified, it will be set to 'thin'. Otherwise, you can set to
|
||||
# 'thin', 'thick', or 'eagerzeroedthick'
|
||||
#esxi.guest_disk_type = 'thick'
|
||||
|
||||
# OPTIONAL. Boot disk size.
|
||||
# If unspecified, the boot disk size will be the same as the original
|
||||
# box. You can specify a larger boot disk size in GB. The extra disk space
|
||||
# will NOT automatically be available to your OS. You will need to
|
||||
# create or modify partitions, LVM and/or filesystems.
|
||||
#esxi.guest_boot_disk_size = 50
|
||||
|
||||
# OPTIONAL. Create additional storage for guests.
|
||||
# You can specify an array of up to 13 virtual disk sizes (in GB) that you
|
||||
# would like the provider to create once the guest has been created. You
|
||||
# can optionally specify the size and datastore using a hash.
|
||||
#esxi.guest_storage = [ 10, 20, { size: 30, datastore: 'datastore1' } ]
|
||||
|
||||
# OPTIONAL. specify snapshot options.
|
||||
#esxi.guest_snapshot_includememory = 'true'
|
||||
#esxi.guest_snapshot_quiesced = 'true'
|
||||
|
||||
# RISKY. guest_guestos
|
||||
# https://github.com/josenk/vagrant-vmware-esxi/wiki/VMware-ESXi-6.5-guestOS-types
|
||||
#esxi.guest_guestos = 'centos-64'
|
||||
|
||||
# OPTIONAL. guest_virtualhw_version
|
||||
# ESXi 6.7 supports these versions. 4,7,8,9,10,11,12,13 & 14.
|
||||
#esxi.guest_virtualhw_version = '9'
|
||||
|
||||
# OPTIONAL. Guest Autostart
|
||||
# Guest VM will autostart when esxi host is booted. 'true' or 'false'(default)
|
||||
#esxi.guest_autostart = 'false'
|
||||
|
||||
# RISKY. guest_custom_vmx_settings
|
||||
#esxi.guest_custom_vmx_settings = [['vhv.enable','TRUE'], ['floppy0.present','TRUE']]
|
||||
|
||||
# OPTIONAL. local_lax
|
||||
#esxi.local_lax = 'true'
|
||||
|
||||
# OPTIONAL. Guest IP Caching
|
||||
#esxi.local_use_ip_cache = 'True'
|
||||
|
||||
# DANGEROUS! Allow Overwrite
|
||||
# If unspecified, the default is to produce an error if overwriting
|
||||
# VMs and packages.
|
||||
#esxi.local_allow_overwrite = 'True'
|
||||
|
||||
# Advanced Users.
|
||||
# If set to 'True', all WARNINGS will produce a FAILURE and Vagrant will stop.
|
||||
#esxi.local_failonwarning = 'True'
|
||||
|
||||
# Plugin debug output.
|
||||
# Please send any bug reports with this debug output...
|
||||
#esxi.debug = 'true'
|
||||
|
||||
end
|
||||
end
|
|
@ -1,374 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from flask import Flask, jsonify, request
|
||||
import ipaddress
|
||||
import json
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
def convert_to_cidr(address, mask):
|
||||
"""
|
||||
Convert an IP address and subnet mask to CIDR notation.
|
||||
|
||||
Args:
|
||||
address (str): The IP address in dotted decimal format (e.g., '192.168.1.1').
|
||||
mask (str): The subnet mask in dotted decimal format (e.g., '255.255.255.0').
|
||||
|
||||
Returns:
|
||||
str: The CIDR notation of the network (e.g., '192.168.1.1/24').
|
||||
None: If there is an error in conversion, returns None and prints an error message.
|
||||
|
||||
Raises:
|
||||
ValueError: If the provided address or mask is invalid.
|
||||
"""
|
||||
# Convertir dirección y máscara a formato CIDR
|
||||
try:
|
||||
# Convertir la máscara de red de formato largo a formato corto
|
||||
# Cada octeto se convierte a su representación binaria y se cuenta el número de bits '1'
|
||||
cidr_mask = ipaddress.IPv4Network(f"0.0.0.0/{mask}").prefixlen
|
||||
red_objeto = f"{address}/{cidr_mask}"
|
||||
return red_objeto
|
||||
except ValueError as e:
|
||||
print(f"Error al convertir a CIDR: {e}")
|
||||
return None
|
||||
|
||||
|
||||
|
||||
subnets_collection = [{"id": 1,"subnet": "192.168.1.0/24", "next-server": "192.168.1.1", "boot-file-name": "pxelinux.0", "reservations": [] }]
|
||||
|
||||
|
||||
|
||||
# Endpoint GET /ogdhcp/v1/status
|
||||
"""
|
||||
Endpoint to get the status of the DHCP service.
|
||||
|
||||
This endpoint returns a JSON response with the current status of the DHCP service,
|
||||
including disk usage, subnets configuration, and the status of various services.
|
||||
|
||||
Returns:
|
||||
Response: A JSON response with the following structure:
|
||||
"total": str, # Total disk space
|
||||
"used": str, # Used disk space
|
||||
"available": str, # Available disk space
|
||||
"percentage": str # Percentage of disk space used
|
||||
"id": int, # Subnet ID
|
||||
"subnet": str, # Subnet address
|
||||
"pools": [
|
||||
"pool": str # IP address pool range
|
||||
"reservations": [
|
||||
"ip-address": str, # Reserved IP address
|
||||
"hw-address": str # Hardware address associated with the reservation
|
||||
]
|
||||
...
|
||||
"kea-ctrl-agent": str, # Status of kea-ctrl-agent service
|
||||
"kea-dhcp4": str, # Status of kea-dhcp4 service
|
||||
"nginx": str # Status of nginx service
|
||||
HTTP Status Code:
|
||||
200: If the request was successful.
|
||||
"""
|
||||
@app.route('/ogdhcp/v1/status', methods=['GET'])
|
||||
def get_status():
|
||||
# Simular respuesta de éxito
|
||||
return jsonify({
|
||||
"success": "Mensaje éxito",
|
||||
"message": {
|
||||
"disk_usage": {
|
||||
"total": "20G",
|
||||
"used": "15G",
|
||||
"available": "5G",
|
||||
"percentage": "75%"
|
||||
},
|
||||
"subnets": [
|
||||
{
|
||||
"id": 1,
|
||||
"subnet": "192.168.1.0/24",
|
||||
"pools": [{"pool": "192.168.1.10-192.168.1.100"}],
|
||||
"reservations": [{"ip-address": "192.168.1.20", "hw-address": "00:0c:29:6b:5e:71"}]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"subnet": "10.0.0.0/24",
|
||||
"pools": [{"pool": "10.0.0.10-10.0.0.100"}],
|
||||
"reservations": []
|
||||
}
|
||||
],
|
||||
"services_status": {
|
||||
"kea-ctrl-agent": "active",
|
||||
"kea-dhcp4": "active",
|
||||
"nginx": "active"
|
||||
}
|
||||
}
|
||||
}), 200
|
||||
|
||||
# Endpoint GET /ogdhcp/v1/subnets
|
||||
|
||||
@app.route('/ogdhcp/v1/subnets', methods=['GET'])
|
||||
def get_subnets():
|
||||
# Simular respuesta de éxito
|
||||
return jsonify({
|
||||
"success": "Subredes obtenidas correctamente",
|
||||
"message": subnets_collection
|
||||
}), 200
|
||||
|
||||
# Endpoint POST /ogdhcp/v1/subnets
|
||||
"""
|
||||
Create a new subnet.
|
||||
Endpoint: /ogdhcp/v1/subnets
|
||||
Method: POST
|
||||
Request Body (JSON):
|
||||
{
|
||||
"id": <str>, # Unique identifier for the subnet
|
||||
"address": <str>, # IP address of the subnet
|
||||
"mask": <str>, # Subnet mask
|
||||
"nextServer": <str>, # (Optional) Next server IP address
|
||||
"bootFileName": <str> # (Optional) Boot file name
|
||||
}
|
||||
Responses:
|
||||
200 OK:
|
||||
{
|
||||
"message": <new_subnet>
|
||||
}
|
||||
400 Bad Request:
|
||||
- "Invalid JSON"
|
||||
- "Missing 'id', 'address' or 'mask' key"
|
||||
- {
|
||||
"error": "Error: La subred con el id '<id>' ya existe."
|
||||
}
|
||||
- {
|
||||
"error": "Error: La subred con la dirección '<subnet>' ya existe."
|
||||
}
|
||||
- "Invalid data format"
|
||||
Description:
|
||||
This endpoint allows the creation of a new subnet. It expects a JSON payload with the subnet details.
|
||||
The function checks if the provided JSON is valid and contains the required keys ('id', 'address', 'mask').
|
||||
It also ensures that the subnet ID and subnet address do not already exist in the collection.
|
||||
If the validation passes, the new subnet is added to the collection and a success response is returned.
|
||||
"""
|
||||
@app.route('/ogdhcp/v1/subnets', methods=['POST'])
|
||||
def create_subnet():
|
||||
try:
|
||||
new_subnet = json.loads(request.data)
|
||||
new_subnet["next-server"] = new_subnet.get("nextServer")
|
||||
new_subnet["boot-file-name"] = new_subnet.get("bootFileName")
|
||||
except json.JSONDecodeError:
|
||||
return "Invalid JSON", 400
|
||||
|
||||
|
||||
|
||||
if isinstance(new_subnet, dict):
|
||||
if "id" in new_subnet and "address" in new_subnet and "mask" in new_subnet:
|
||||
new_subnet_cidr = convert_to_cidr(new_subnet["address"], new_subnet["mask"])
|
||||
# Comprobar si el id ya existe en la colección
|
||||
for subnet in subnets_collection:
|
||||
if subnet.get("id") == new_subnet["id"]:
|
||||
return jsonify({
|
||||
"error": f"Error: La subred con el id '{new_subnet['id']}' ya existe."
|
||||
}), 400
|
||||
if subnet.get("subnet") == new_subnet_cidr:
|
||||
return jsonify({
|
||||
"error": f"Error: La subred con la dirección '{new_subnet_cidr}' ya existe."
|
||||
}), 400
|
||||
|
||||
# Si el id no existe, continuar con la creación de la subred
|
||||
new_subnet["subnet"] = convert_to_cidr(new_subnet["address"], new_subnet["mask"])
|
||||
subnets_collection.append(new_subnet)
|
||||
return jsonify({
|
||||
"success": "Subred agregada correctamente",
|
||||
"message": new_subnet
|
||||
}), 200
|
||||
|
||||
else:
|
||||
return "Missing 'id', 'address' or 'mask' key", 400
|
||||
else:
|
||||
return "Invalid data format", 400
|
||||
|
||||
|
||||
# Endpoint DELETE /ogdhcp/v1/subnets/<subnetId>
|
||||
"""
|
||||
Deletes a subnet from the subnets_collection based on the provided subnetId.
|
||||
|
||||
Args:
|
||||
subnetId (int): The ID of the subnet to be deleted.
|
||||
|
||||
Returns:
|
||||
Response: A JSON response indicating the success or failure of the deletion.
|
||||
- If the subnet is successfully deleted, returns a JSON response with a success message and HTTP status 200.
|
||||
- If the subnet with the given ID does not exist, returns a JSON response with an error message and HTTP status 404.
|
||||
"""
|
||||
@app.route('/ogdhcp/v1/subnets/<int:subnetId>', methods=['DELETE'])
|
||||
def delete_subnet(subnetId):
|
||||
subnet_to_delete = None
|
||||
for subnet in subnets_collection:
|
||||
if int(subnet["id"]) == subnetId:
|
||||
subnet_to_delete = subnet
|
||||
break
|
||||
if subnet_to_delete:
|
||||
print (f"Subnet Collection {subnets_collection}")
|
||||
print (f"Subnet to delete {subnet_to_delete}")
|
||||
subnets_collection.remove(subnet_to_delete)
|
||||
print (f"Subnet Collection {subnets_collection}")
|
||||
return jsonify({
|
||||
"success": "Subred eliminada correctamente"
|
||||
}), 200
|
||||
else:
|
||||
return jsonify({
|
||||
"error": f"Error: La subred con el id '{subnetId}' no existe"
|
||||
}), 404
|
||||
|
||||
# Endpoint PUT /ogdhcp/v1/subnets/<subnetId>
|
||||
"""
|
||||
Updates a subnet with the given subnetId based on the provided JSON data in the request.
|
||||
Args:
|
||||
subnetId (str): The ID of the subnet to be updated.
|
||||
Returns:
|
||||
Response: A JSON response indicating the success or failure of the update operation.
|
||||
- On success: Returns a JSON response with a success message and the updated subnet data, with a status code of 200.
|
||||
- On failure: Returns a JSON response with an error message and a status code of 400.
|
||||
Raises:
|
||||
json.JSONDecodeError: If the request data is not valid JSON.
|
||||
The function performs the following steps:
|
||||
1. Parses the JSON data from the request.
|
||||
2. Validates the presence of required fields ('address' and 'mask') in the JSON data.
|
||||
3. Converts the 'address' and 'mask' fields to a 'subnet' field in CIDR notation.
|
||||
4. Searches for the subnet with the given subnetId in the subnets_collection.
|
||||
5. Updates the subnet fields ('subnet', 'nextServer', 'bootFileName') if they are present in the JSON data.
|
||||
6. Returns a success response if the subnet is found and updated.
|
||||
7. Returns an error response if the subnet is not found.
|
||||
"""
|
||||
@app.route('/ogdhcp/v1/subnets/<int:subnetId>', methods=['PUT'])
|
||||
def update_subnet(subnetId):
|
||||
|
||||
|
||||
if subnetId == 0:
|
||||
return jsonify({
|
||||
"error": "Error al guardar la configuración en Kea DHCP: Unable to save configuration"
|
||||
}), 400
|
||||
try:
|
||||
modify_data = json.loads(request.data)
|
||||
except json.JSONDecodeError:
|
||||
return "Invalid JSON", 400
|
||||
|
||||
print ("Modify data", modify_data)
|
||||
print ("Modify data type", type(modify_data))
|
||||
if modify_data.get("address") != None and modify_data.get("mask") == None:
|
||||
print ("Address", modify_data.get("address"))
|
||||
return jsonify({
|
||||
"error": f"Error: La máscara de red es requerida con el parametro 'address'"
|
||||
}), 400
|
||||
if modify_data.get("mask") != None and modify_data.get("address") == None:
|
||||
return jsonify({
|
||||
"error": f"Error: La dirección de red es requerida con el parametro 'mask'"
|
||||
}), 400
|
||||
|
||||
subnet_to_update = None
|
||||
|
||||
for subnet in subnets_collection:
|
||||
# Casting subnet["id"] to int to avoid type mismatch
|
||||
if str(subnet["id"]) == str(subnetId):
|
||||
# subnet_to_update = subnet
|
||||
if modify_data.get("subnet"):
|
||||
subnet["subnet"] = modify_data["subnet"]
|
||||
|
||||
if modify_data.get("nextServer"):
|
||||
subnet["next-server"] = modify_data["nextServer"]
|
||||
|
||||
if modify_data.get("bootFileName"):
|
||||
subnet["boot-file-name"] = modify_data["bootFileName"]
|
||||
subnet_to_update = subnet
|
||||
break
|
||||
|
||||
if subnet_to_update:
|
||||
# subnet_to_update.update(modify_data)
|
||||
print ("Subnet to update", subnet_to_update)
|
||||
return jsonify({
|
||||
"success": "Subred modificada correctamente",
|
||||
"message": subnet_to_update
|
||||
}), 200
|
||||
|
||||
else:
|
||||
# Si no se encuentra la subred, devolver un error
|
||||
print (f"Subnet Collection {subnets_collection}")
|
||||
response = jsonify({
|
||||
"error": f"Error: La subred con el id '{subnetId}' no existe"
|
||||
})
|
||||
response.status_code = 404
|
||||
response.headers["Content-Type"] = "application/json"
|
||||
return response
|
||||
|
||||
|
||||
# Endpoint GET /ogdhcp/v1/subnets/<subnetId>/hosts
|
||||
@app.route('/ogdhcp/v1/subnets/<int:subnetId>/hosts', methods=['GET'])
|
||||
def get_hosts(subnetId):
|
||||
# Simular respuesta de éxito
|
||||
return jsonify({
|
||||
"success": "Hosts retrieved successfully",
|
||||
"message": [
|
||||
{"ip-address": "192.168.1.10", "hw-address": "00:0c:29:6b:5e:71", "hostname": "host1"},
|
||||
{"ip-address": "192.168.1.20", "hw-address": "00:0c:29:6b:5e:72", "hostname": "host2"}
|
||||
]
|
||||
}), 200
|
||||
|
||||
# Endpoint POST /ogdhcp/v1/subnets/<subnetId>/hosts
|
||||
@app.route('/ogdhcp/v1/subnets/<int:subnetId>/hosts', methods=['POST'])
|
||||
def create_host(subnetId):
|
||||
# Simular respuesta de éxito
|
||||
return jsonify({
|
||||
"success": "Host agregado correctamente",
|
||||
"message": {
|
||||
"id": 1,
|
||||
"subnet": "192.168.1.0/24",
|
||||
"next-server": "192.168.1.1",
|
||||
"boot-file-name": "pxelinux.0",
|
||||
"reservations": [
|
||||
{"hostname": "pc11", "hw-address": "56:6f:c7:4f:00:4f", "ip-address": "172.30.4.11"}
|
||||
]
|
||||
}
|
||||
}), 200
|
||||
|
||||
# Endpoint DELETE /ogdhcp/v1/subnets/<subnetId>/hosts
|
||||
@app.route('/ogdhcp/v1/subnets/<int:subnetId>/hosts', methods=['DELETE'])
|
||||
def delete_host(subnetId):
|
||||
# Simular respuesta de éxito
|
||||
return jsonify({
|
||||
"success": "Host eliminado correctamente",
|
||||
"message": {
|
||||
"id": 1,
|
||||
"subnet": "192.168.1.0/24",
|
||||
"next-server": "192.168.1.1",
|
||||
"boot-file-name": "pxelinux.0",
|
||||
"reservations": [
|
||||
{"hostname": "host2", "hw-address": "00:0c:29:6b:5e:72", "ip-address": "172.30.4.12"}
|
||||
]
|
||||
}
|
||||
}), 200
|
||||
|
||||
# Endpoint PUT /ogdhcp/v1/subnets/<subnetId>/hosts
|
||||
@app.route('/ogdhcp/v1/subnets/<int:subnetId>/hosts', methods=['PUT'])
|
||||
def update_host(subnetId):
|
||||
# Simular respuesta de éxito
|
||||
return jsonify({
|
||||
"success": "Host actualizado correctamente",
|
||||
"message": {
|
||||
"id": 1,
|
||||
"subnet": "192.168.1.0/24",
|
||||
"next-server": "192.168.1.1",
|
||||
"boot-file-name": "pxelinux.0",
|
||||
"reservations": [
|
||||
{"hostname": "pc11", "hw-address": "56:6f:c7:4f:01:01", "ip-address": "192.168.1.11"},
|
||||
{"hostname": "host2", "hw-address": "00:0c:29:6b:5e:72", "ip-address": "192.168.1.12"}
|
||||
]
|
||||
}
|
||||
}), 200
|
||||
|
||||
# Endpoint POST /ogdhcp/v1/backup
|
||||
@app.route('/ogdhcp/v1/backup', methods=['POST'])
|
||||
def backup_config():
|
||||
# Simular respuesta de éxito
|
||||
return jsonify({
|
||||
"success": "Configuración cargada correctamente"
|
||||
}), 200
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True, port=8006)
|
|
@ -1,2 +0,0 @@
|
|||
robotframework
|
||||
robotframework-requests
|
|
@ -1,215 +0,0 @@
|
|||
*** Settings ***
|
||||
Documentation This is a basic skeleton for a Robot Framework test suite.
|
||||
Library Collections
|
||||
Library RequestsLibrary
|
||||
|
||||
|
||||
|
||||
*** Variables ***
|
||||
${BASE_URL} http://localhost:8006/ogdhcp/v1
|
||||
${headers} Create Dictionary Content-Type application/json
|
||||
${modified_subnet} Create Dictionary mask=255.255.192.0 address=192.168.1.0 nextServer=192.168.1.1 bootFileName=pxelinux.0
|
||||
${wrong_subnet_data_netmask} Create Dictionary mask=333.333.333.333 address=192.168.1.0 nextServer=192.168.1.1 bootFileName=pxelinux.0
|
||||
${wrong_subnet_data_address} Create Dictionary mask=255.255.255.0 address=444.168.1.0 nextServer=192.168.1.1 bootFileName=pxelinux.0
|
||||
${wrong_subnet_data_server} Create Dictionary mask=255.255.255.0 address=192.168.1.0 nextServer=555.168.1.1 bootFileName=pxelinux.0
|
||||
${invalid_net_id} 999
|
||||
${valid_net_id} 2
|
||||
${subnet_error} 0
|
||||
|
||||
*** Test Cases ***
|
||||
Get Status of the DHCP server
|
||||
[Documentation] Get status of the dhcp server and check services status
|
||||
[Tags] status
|
||||
${response}= GET ${BASE_URL}/status
|
||||
Status Should Be 200 ${response}
|
||||
Log ${response.json()}
|
||||
# Convertir la respuesta a JSON usando ${response.json()}
|
||||
${json}= Convert to Dictionary ${response.json()}
|
||||
Dictionary Should Contain Key ${json} success
|
||||
Dictionary Should Contain Key ${json} message
|
||||
Should Contain ${response.json()['message']} disk_usage
|
||||
Should Contain ${response.json()['message']} subnets
|
||||
Should Contain ${response.json()['message']['disk_usage']} total
|
||||
|
||||
|
||||
Get All Subnets
|
||||
[Documentation] Este test verifica que la API retorna las subredes correctamente con el código 200.
|
||||
[Tags] subnets
|
||||
${response}= GET ${BASE_URL}/subnets
|
||||
# Verificar código de estado HTTP
|
||||
Should Be Equal As Numbers ${response.status_code} 200
|
||||
${json}= Convert To Dictionary ${response.json()}
|
||||
# Verificar que la respuesta contiene las claves 'success' y 'message'
|
||||
Dictionary Should Contain Key ${json} success
|
||||
Dictionary Should Contain Key ${json} message
|
||||
# Validar el mensaje de éxito
|
||||
Should Be Equal ${json['success']} Subredes obtenidas correctamente
|
||||
# Verificar que 'message' es una lista
|
||||
# Should Be True ${json['message']} is list
|
||||
# Verificar que cada subred en 'message' tiene los campos esperados
|
||||
FOR ${subred} IN @{json['message']}
|
||||
Dictionary Should Contain Key ${subred} id
|
||||
Dictionary Should Contain Key ${subred} subnet
|
||||
END
|
||||
|
||||
Post a new subnet
|
||||
[Documentation] Post a new subnet
|
||||
[Tags] subnets
|
||||
${new_subnet} Create Dictionary
|
||||
... subnetId=${valid_net_id}
|
||||
... mask=255.255.255.0
|
||||
... address=192.168.2.0
|
||||
... nextServer=192.168.2.1
|
||||
... bootFileName=pxelinux.0
|
||||
${headers}= Create Dictionary Content-Type=application/json
|
||||
${response}= POST ${BASE_URL}/subnets json=${new_subnet} headers=${headers}
|
||||
Status Should Be 200 ${response}
|
||||
${json}= Convert to Dictionary ${response.json()}
|
||||
Dictionary Should Contain Key ${json} success
|
||||
Dictionary Should Contain Key ${json} message
|
||||
Should Contain ${json["success"]} Subred agregada correctamente
|
||||
Should Be Equal As Numbers ${json["message"]["id"]} ${valid_net_id}
|
||||
|
||||
|
||||
Post a new subnet with existing id
|
||||
[Documentation] Post a new subnet with invalid data
|
||||
[Tags] subnets
|
||||
${new_subnet} Create Dictionary
|
||||
... subnetId=2
|
||||
... mask=255.255.255.0
|
||||
... address=192.168.3.0
|
||||
... nextServer=192.168.3.1
|
||||
... bootFileName=pxelinux.0
|
||||
${headers}= Create Dictionary Content-Type=application/json
|
||||
${response}= POST ${BASE_URL}/subnets json=${new_subnet} headers=${headers} expected_status=400
|
||||
Status Should Be 400 ${response}
|
||||
${json}= Convert to Dictionary ${response.json()}
|
||||
Dictionary Should Contain Key ${json} error
|
||||
Should Contain ${response.json()["error"]} La subred con el id '${valid_net_id}' ya existe.
|
||||
|
||||
Post a new subnet with existing address
|
||||
[Documentation] Post a new subnet with invalid data
|
||||
[Tags] subnets
|
||||
${headers}= Create Dictionary Content-Type=application/json
|
||||
${new_subnet_invalid} Create Dictionary
|
||||
... subnetId=3
|
||||
... mask=255.255.255.0
|
||||
... address=192.168.1.0
|
||||
... nextServer=192.168.1.1
|
||||
... bootFileName=pxelinux.0
|
||||
|
||||
${response}= POST ${BASE_URL}/subnets json=${new_subnet_invalid} headers=${headers} expected_status=400
|
||||
Status Should Be 400 ${response}
|
||||
${json}= Convert to Dictionary ${response.json()}
|
||||
Dictionary Should Contain Key ${json} error
|
||||
Should Contain ${response.json()['error']} La subred con la dirección '192.168.1.0/24' ya existe
|
||||
|
||||
|
||||
Modify an existing subnet by id
|
||||
[Documentation] Modify a subnet by id
|
||||
[Tags] subnets
|
||||
${headers}= Create Dictionary Content-Type=application/json
|
||||
${modified_subnet}= Create Dictionary
|
||||
... mask=255.255.192.0
|
||||
... address=192.168.1.0
|
||||
... nextServer=192.168.1.1
|
||||
... bootFileName=pxelinux.0
|
||||
# Modificar la subred con id=2
|
||||
${response}= PUT ${BASE_URL}/subnets/2 json=${modified_subnet} headers=${headers} expected_status=200
|
||||
Status Should Be 200 ${response}
|
||||
${json}= Convert to Dictionary ${response.json()}
|
||||
# Verificar que la respuesta contiene clave 'success'
|
||||
Dictionary Should Contain Key ${json} success
|
||||
|
||||
# Validar el contenido del mensaje de éxito
|
||||
Should Be Equal ${json['success']} Subred modificada correctamente
|
||||
Should Be Equal ${json['message']['id']} 2
|
||||
|
||||
|
||||
Modify a subnet with invalid id
|
||||
[Documentation] Este test verifica que la modificación de una subred falla cuando el ID no existe.
|
||||
[Tags] subnets
|
||||
${headers}= Create Dictionary Content-Type=application/json
|
||||
${modificar_subred}= Create Dictionary mask=255.255.192.0 address=192.168.1.0 nextServer=192.168.1.1 bootFileName=pxelinux.0
|
||||
${response}= PUT ${BASE_URL}/ogdhcp/v1/subnets/${invalid_net_id} json=${modificar_subred} headers=${headers} expected_status=404
|
||||
|
||||
# Verificar código de estado HTTP
|
||||
Should Be Equal As Numbers ${response.status_code} 404
|
||||
|
||||
|
||||
|
||||
Modify subnet with error to save configuration
|
||||
[Documentation] Este test verifica que la modificación falla cuando hay un error al guardar la configuración en Kea DHCP.
|
||||
[Tags] subnets
|
||||
${headers}= Create Dictionary Content-Type=application/json
|
||||
${modificar_subred}= Create Dictionary subnet="192.168.1.0" mask="255.255.255.0" nextServer="192.168.1.1" bootFileName="pxelinux.0"
|
||||
${response}= PUT ${BASE_URL}/subnets/${subnet_error} json=${modificar_subred} headers=${headers} expected_status=400
|
||||
|
||||
# Verificar código de estado HTTP
|
||||
Should Be Equal As Numbers ${response.status_code} 400
|
||||
|
||||
${json}= Convert To Dictionary ${response.json()}
|
||||
|
||||
# Verificar que la respuesta contiene el error esperado
|
||||
Should Be Equal ${json['error']} Error al guardar la configuración en Kea DHCP: Unable to save configuration
|
||||
|
||||
Modify subnet with invalid configuration address without netmask
|
||||
[Documentation] Este test verifica que la modificación falla cuando hay un error en la configuración de Kea DHCP.
|
||||
[Tags] subnets
|
||||
${headers}= Create Dictionary Content-Type=application/json
|
||||
${modificar_subred}= Create Dictionary address="192.168.1.0" nextServer="192.168.1.1" bootFileName="pxelinux.0"
|
||||
|
||||
${response}= PUT ${BASE_URL}/subnets/2 json=${modificar_subred} headers=${headers} expected_status=400
|
||||
|
||||
# Verificar código de estado HTTP
|
||||
Should Be Equal As Numbers ${response.status_code} 400
|
||||
|
||||
${json}= Convert To Dictionary ${response.json()}
|
||||
|
||||
# Verificar que la respuesta contiene el error esperado
|
||||
Should Be Equal ${json['error']} Falta un parámetro requerido: mask
|
||||
|
||||
Modify subnet with invalid configuration netmask without address
|
||||
[Documentation] Este test verifica que la modificación falla cuando hay un error en la configuración de Kea DHCP.
|
||||
[Tags] subnets
|
||||
${headers}= Create Dictionary Content-Type=application/json
|
||||
${modificar_subred}= Create Dictionary mask="255.255.255.0" nextServer="192.168.1.1" bootFileName="pxelinux.0"
|
||||
|
||||
${response}= PUT ${BASE_URL}/subnets/2 json=${modificar_subred} headers=${headers} expected_status=400
|
||||
|
||||
# Verificar código de estado HTTP
|
||||
Should Be Equal As Numbers ${response.status_code} 400
|
||||
|
||||
${json}= Convert To Dictionary ${response.json()}
|
||||
|
||||
# Verificar que la respuesta contiene el error esperado
|
||||
Should Be Equal ${json['error']} Falta un parámetro requerido: address
|
||||
|
||||
Delete subnet by id
|
||||
[Documentation] Este test verifica que la subred se elimina correctamente con el código 200.
|
||||
[Tags] subnets
|
||||
${response}= DELETE ${BASE_URL}/subnets/${valid_net_id}
|
||||
# Verificar código de estado HTTP
|
||||
Should Be Equal As Numbers ${response.status_code} 200
|
||||
${json}= Convert To Dictionary ${response.json()}
|
||||
# Verificar que la respuesta contiene la clave 'success'
|
||||
Dictionary Should Contain Key ${json} success
|
||||
# Validar el mensaje de éxito
|
||||
Should Be Equal ${json['success']} Subred eliminada correctamente
|
||||
|
||||
Delete subnet - Error: wrong subnet Id
|
||||
[Documentation] Este test verifica que la eliminación falla si la subred con el ID no existe.
|
||||
[Tags] subnets
|
||||
${response}= DELETE ${BASE_URL}/subnets/${invalid_net_id} expected_status=404
|
||||
# Verificar código de estado HTTP
|
||||
Should Be Equal As Numbers ${response.status_code} 404
|
||||
${json}= Convert To Dictionary ${response.json()}
|
||||
# Verificar que la respuesta contiene la clave 'error'
|
||||
Dictionary Should Contain Key ${json} error
|
||||
# Validar el mensaje de error
|
||||
Should Be Equal ${json['error']} La subred con el id '999' no existe
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Symfony\Component\Dotenv\Dotenv;
|
||||
|
||||
require dirname(__DIR__).'/vendor/autoload.php';
|
||||
|
||||
if (file_exists(dirname(__DIR__).'/config/bootstrap.php')) {
|
||||
require dirname(__DIR__).'/config/bootstrap.php';
|
||||
} elseif (method_exists(Dotenv::class, 'bootEnv')) {
|
||||
(new Dotenv())->bootEnv(dirname(__DIR__).'/.env');
|
||||
}
|
Loading…
Reference in New Issue