Hospedaje estático del panel de administración en una Azure Storage Account

Sitio dedicado a Microsoft Azure y otras tecnologías Cloud

Web Hosting estático de las cuentas de almacenamiento

En esté y esté artículo he compartido cómo he construido a robotijo, una function que me permite realizar operaciones muy básicas con mi máquina virtual de desarrollo y formación en Azure.

Sin embargo lo de invocar a las operaciones directamente a la API de la function me parece poco elegante, quiero hacer algo tan sencillo como publicar una página con los botones mínimos necesarios para las dos operaciones fundamentales: encender/apagar.

El reto viene que no voy a montar todo un App Plan para algo tan pequeñito, y me he decantado por utilizar las capacidades hospedaje de Web estáticas en las cuentas de almacenamiento.

Dando de alta Web estática

La primera pregunta que te vendrá a la mente es: «gañan, ¿y porqué no usas el App Plan de la propia function?«. Y la respuesta es de esas peculiaridades que tienen los servicios de Azure que provocan fastidio al ser lo más parecido a la letra pequeña de los contratos.

Cuando he creado la function, le he dicho que creara la cuenta de almacenamiento que necesita… y me ha la ha creado V1. Y como no podía ser de otra forma, las static web solamente están habilitadas y funcionan en la V2. Manda cataplines que me haya pasado cuando no paro de repetirle a mis alumnos que no utilicen V1 nunca más, todo en V2.

Disclamer: me acabo de dar cuenta que nunca he publicado aquí las diferencias entre la V1 y la V2… a ver si esta misma semana lo corrijo.

Osea, en resumen creo una nueva cuenta de almacenamiento de tipo V2, y de tipo Hot (más adelante lo voy a cambiar a Cool para pagar menos), le activo el Static Website.

Enabled Static web site

Solo tengo que hacer cuatro cosas:

  1. Activar el servicio de Static website.
  2. Apuntar la url en donde se va a publicar mi sitio.
  3. Introducir la página de inicio del website que, comúnmente, va a ser index.htm o index.html
  4. Introducir (es opcional) la página que se va a devolver si hay algún error.

Y ya está. con esto tengo montado un sitio Web a un precio ridículo. Sin exagerar, no debe llegar ni a los 20 céntimos de euro al año, o menos. Ten en cuenta que solamente pago por el almacenamiento; y que en West Europe me va a costa unos 0,02€ al més por un GB mientras yo voy a consumir 2 Kb.

Coste del host estático según la calculadora de Azure

 

Show me the code

Vale, ¿y ahora qué quiero publicar en este sitio?

Pues dos tristes botones: uno de «Start» y otro de «Stop», y una etiqueta que me confirmara el estado de la máquina virtual. Para ello los botones iban a hacer la llamada a la API de robotijo (la function en Azure).

Así que -iluso de mí- me dije que era el momento de practicar un poquito con React o con Angular. Pero oiga, el volumen de dependencias que debía descargar y almacenar era (y es) absurdo. Incluso, dándole vueltas a la interacción y experiencia de usuario que quería implementar, algo como bootstrap y jQuery también era matar moscas a cañonazos. Por lo cual me decanté por HTMNL5 y Javascript vanilla (chuminá de denominación que se han inventado).

Así mi super aplicación está compuesta por tres ficheros diferentes: index.html, JavaScript.js y StyleSheet.css.

En index.html tengo la referencia al fichero css en donde voy a meter el diseño, la definición de los dos botones y el enlace al fichero javascript donde tengo la lógica de representación y las llamadas a la API del robotijo (la function en Azure).

<html>
<body>
    <link href="StyleSheet.css" rel="stylesheet" />

    <label id="Status" class="status">Request status...</label>
    <br />&nbsp;
    <br />&nbsp;
    <button id="Start" type="button" class="button disabled">Start</button>
    <button id="Stop" type="button" class="button disabled">Stop</button>
</body>
</html>

<script src="JavaScript.js"></script>

El JavaScript ers un poquito más complejo, pero básicamente lo que hago es cambiar los colores de los botones según estén o no habilitados. Por defecto no lo están hasta que no haya recuperado el estatus de la VM, y entonces me enciende y habilita el botón que puede cambiar dicho estatus. Es decir si la VM está apagada, está habilitado el botón de «Start».

Y me aseguro también que cuando pulso un botón se deshabilitan los botones mientras se está realizando la operación, así no me pueden las ansias y mando doscientas peticiones a la API.

var btnStart = document.getElementById("Start");
var btnStop = document.getElementById("Stop");
var lblStatus = document.getElementById("Status");

window.addEventListener('load', function () {
    allDisabled();
    httpGetAsync("status");
});

function getstatus() {

    if (lblStatus.innerText === "PowerState/running") {
        startDisabled();
        stoptEnabled();
    } else if (lblStatus.innerText === "PowerState/deallocated") {
        startEnabled();
        stoptDisabled();
    } else {
        httpGetAsync("status");
    }
}

function startEnabled() {
    btnStart.disabled = false;
    btnStart.className = "button start";
}
function startDisabled() {
    btnStart.disabled = true;
    btnStart.className = "button disabled";
}
function stoptEnabled() {
    btnStop.disabled = false;
    btnStop.className = "button stop";
}
function stoptDisabled() {
    btnStop.disabled = true;
    btnStop.className = "button disabled";
}
function allDisabled() {
    btnStart.disabled = true;
    btnStart.className = "button disabled";
    btnStop.disabled = true;
    btnStop.className = "button disabled";
}


btnStart.addEventListener('click', function (event) {
    allDisabled();
    httpGetAsync("start");
});

btnStop.addEventListener('click', function (event) {
    allDisabled();
    httpGetAsync("stop");
});

function httpGetAsync(command) {
    lblStatus.innerHTML = "Running...";
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
            lblStatus.innerHTML = this.responseText;
            getstatus();
        }
    };
    var theUrl = "https://algunlugar.azurewebsites.net/api/OperacionesVM?code=/<aquí va un token de seguridad que no te voy a decir cual es>==&op=" + command;

    xmlHttp.open("GET", theUrl, true);
    xmlHttp.send(null);
}

Por último, envío la petición Get a la API del robotijo y recupero el estátus de forma asincrona, para actualizar el estado de los botones.

Sin duda se podría hacer de forma mucho más compacta y elegante… pero es que son dos botones y no tengo vergüenza en enseñar mi código.

Por último, por si hay alguien de diseño Front por aquí, aquí está el CSS que aún lo estoy retocando para hacer el tamaño de la fuente también responsive.

.button {
  display: inline-block;
  width: 48%;
  height: 50%;
  border: none;
  background-color: #4CAF50;
  color: white;
  padding: 14px 28px;
  font-size: 16px;
  cursor: pointer;
  text-align: center;
}

.start {
    background-color: #4CAF50; /* Green */
}

.stop {
    background-color: #f00; /* red */
}

.disabled {
    background-color: #808080; /* gray */
    cursor: not-allowed;
}

Publicando la web

Cuando he habilitado el servicio de Static website en la cuenta de almacenamiento, se me ha creado de forma automática un contenedor de tipo Blob llamado $web. Dentro de este blob subo los tres fichero ya sea desde el portal o, mejor y recomendable, desde el Azure Storage Explorer.

Lo único que tengo que tener cuidado es que el fichero de inicio se llame exactamente como lo he configurado en la Static website. Y, fíjate en la captura, yo no estoy subiendo el fichero 404.html aunque debiera hacerlo.

Blob con los tres ficheros de la publicación

Con este poquito código y una poquita de configuración desde el portal, lo que he conseguido es un pequeñísimo panel de encendido y apagado de mi VM, al que puedo acceder desde mi móvil, la web o cualquier navegador… y que me cuesta nada al mes.

Realmente lo importante de toda esta arquitectura es que ahora tengo las bases para seguir ampliando este panel para controlar – por ejemplo- mis cuentas de estudiantes, y abarcar la gestión y gobernanza de los cada vez más y más complejos recursos que utilizo en mi día a día.

Espero que sea de ayuda.

 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.