Gustavo Adolfo Arellano

Find sorted media

problemas a resolver, Técnicos Comments Off on Find sorted media
Sep 082020
import java.util.Arrays;

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int [] iArr = addAll(nums1, nums2);
        Arrays.sort(iArr);
        int mid = iArr.length/2;
        return (iArr.length %2 == 0)?(iArr[mid-1] + iArr[mid])/2.0:iArr[mid];
    }
    private int[] addAll(int[] nums1, int[] nums2) {
        int len = nums1.length + nums2.length;
        int[] result = new int[len];
        for(int i=0; i< nums1.length; i++) {
            result[i] = nums1[i];
        }
        for(int i=0; i< nums2.length; i++) {
            result[i+nums1.length] = nums2[i];
        }
        return result;
    }
}

Problema #4

problemas a resolver Comments Off on Problema #4
Aug 232020
// Super fast reverse words algorithm
// It only takes 2 ms to do the process ...
public class Solution {
    public String reverseWords(String ss) {
        return ok(ss.trim());
    }
    public String ok(String ss) {
        String[] words = ss.split(" ");
        StringBuilder r = new StringBuilder();
        for(int i=words.length-1; i>=0; i--) {
            if(words[i].length()<1) continue;
            r.append(words[i]);
            if(i>0) r.append(" ");
        }
        return r.toString();
    }
}

Problema #3

problemas a resolver Comments Off on Problema #3
Aug 232020
package mytest;

public class SinglyLinkedList<T> {
    private Node<T> head;

    /**
     * Imprime esta lista ligada con un formato 
     * específico delimitado por símbolos '--->'
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        Node<T> current = head;
        while (current != null) {
            sb.append(current).append("-->");
            current = current.next;
        }
        // to remove --> from last node:
        if (sb.length() >= 3) {
            sb.delete(sb.length() - 3, sb.length());
        }
        return sb.toString();
    }

    /**
     * Crea una lista ligada de objetos de topo 'Node' con alguna
     * letra (seleccionada del conjunto 'ABCDEFghijk') como el 
     * contenido de cada nodo.
     */
    private static SinglyLinkedList<String> createList() {
        String source = "ABCDEFghijk";
        SinglyLinkedList<String> linkedlist = new SinglyLinkedList<>();
        for (int i = 0; i < source.length(); i++)
            linkedlist.append(source.charAt(i) + "");
        return linkedlist;
    }

    /**
     * Agrega a una lista ligada un elemento al final de ella
     */
    public void append(T data) {
        if (head == null) {
            head = new Node<T>(data);
        } else {
            tail().next = new Node<T>(data);
        }
    }

    /**
     * Auxiliar del método 'append'. Regresa el último elemento de una lista
     */
    private Node<T> tail() {
        Node<T> tail = head;
        while (tail.next != null)  tail = tail.next;
        return tail;
    }

    /**
     * AQUI DEBES ADIVINAR QUÉ HACE ESTE MÉTODO LLAMADO 'misterioso'
     * PERO TAMBIÉN DEBES DECIR PORQUE LO HACE Y EXPLICAR SU ALGORITMO.
     */
    private Node<T> misterioso(Node<T> tavo) {
        if (tavo.next == null) return tavo;
        Node<T> gus = misterioso(tavo.next);
        tavo.next.next = tavo;
        tavo.next = null;
        return gus;
    }

    public void adivina() {
        head = misterioso(head);
    }

    /**
     * Definición de la clase privada 'Node'
     */
    private static class Node<T> {
        private Node<T> next;
        private T data;
        
        public Node(T data) {
            this.data = data;
        }
        public String toString() {
            return data.toString();
        }
    }

    /**
     * Ejecuta el programa
     */
    public static void main(String args[]) {
        SinglyLinkedList<String> linkedlist = createList();
        System.out.println("linked list before adivina : " + linkedlist);
        
        linkedlist.adivina();
        System.out.println("linked list after adivina " + linkedlist);
    }

}

Problema #2

problemas a resolver Comments Off on Problema #2
Aug 232020

We stack glasses in a pyramid, where the first row has 1 glass, the second row has 2 glasses, and so on until the 100th row.  Each glass holds one cup (250ml) of champagne.

Then, some champagne is poured in the first glass at the top.  When the top most glass is full, any excess liquid poured will fall equally to the glass immediately to the left and right of it.  When those glasses become full, any excess champagne will fall equally to the left and right of those glasses, and so on.  (A glass at the bottom row has it’s excess champagne fall on the floor.)

For example, after one cup of champagne is poured, the top most glass is full.  After two cups of champagne are poured, the two glasses on the second row are half full.  After three cups of champagne are poured, those two cups become full – there are 3 full glasses total now.  After four cups of champagne are poured, the third row has the middle glass half full, and the two outside glasses are a quarter full, as pictured below.

La solución a este problema es simple y elegante. Obviamente recursiva. Te pido a ti, lector, que primero intentes solucionar el problema por ti mismo y como último recurso que veas la solución que adjunto justo aquí abajo:

class Solution {
    public double champagneTower(int poured, int query_row, int query_glass) {
        return Math.min(1, input(poured, query_row+1, query_glass+1));
    }
    
    private double input(int p, int r, int c) {
        if(r*c==1) return p;
        if(c<=0 || c>r) return 0;
        double izq = Math.max(0, (input(p, r-1, c-1)-1)/2);
        double der = Math.max(0, (input(p, r-1, c)-1)/2);
        return (izq + der);
    }
}

Problema #1

problemas a resolver Comments Off on Problema #1
Aug 232020
/*
Given an array of integers and an integer k, the method 'findPairs' finds
the number of unique 'k-diff' pairs in the array. 

Please note that a 'k-diff' pair is defined as an integer pair (i, j), where
i and j are both numbers in the array and their absolute difference is k.
*/
public class Solution2 {
    public static int findPairs(int[] nums, int k) {
        // your code here ...
    }
}

Se adjuntan pruebas unitarias para este ejercicio

package mytest;

import static org.junit.Assert.assertTrue;
import org.junit.Test;

public class CasosPrueba {
    
    @Test
    public void calc2() {
        int k6=9;
        int[] a6 = {25, 53, 96, 30, -57, 32, 3, 33, 83, 81, -35, -92, 34, 79, 75, 71, -14, 58, -43, 91};
        int r6 = Solution2.findPairs(a6, k6);
        assertTrue(r6==1);

        int k7=52;
        int[] a7 = {88, 6, -24, 35, -29, 25, 13, 15, 29, 70, 45, 40, 32, 40, -27, -48, 46, 62};
        int r7 = Solution2.findPairs(a7, k7);
        assertTrue(r7==1);

        int k9=39;
        int[] a9 = {18, -82, -99, 14, 17, 53, 63, 80, 41, 0, 22, -14, 61, 76};
        int r9 = Solution2.findPairs(a9, k9);
        assertTrue(r9==3);

        int k10=23;
        int[] a10 = {-60, 6, -58, 96, 56, 22, 9, 26, -81, 11, -76, 91, 69, 10, 1, 72, 61, 51, -87};
        int r10 = Solution2.findPairs(a10, k10);
        assertTrue(r10==1);

        int k11=31;
        int[] a11 = {55, -14, 40, 61, 91, 51, -70, 52, -69, 70, -48, 12, 91, -77, 20, -30, 67, 35, -45, -81, 46, 84, 11};
        int r11 = Solution2.findPairs(a11, k11);
        assertTrue(r11==2);

        int k14=17;
        int[] a14 = {25, -85, 18, 96, 19, 83, 73, 90, 80, 2, 54, 5, 68, 19, 64, 26, 88, 71, 89, 24, 39};
        int r14 = Solution2.findPairs(a14, k14);
        assertTrue(r14==4);

        int k15=28;
        int[] a15 = {-24, 25, -32, 89, 25, 83, 30, 71, 41, 61, 6, 39, 33, 91, -3, 33, 94, 53, 45, 12, 17, -28, 55, 66};
        int r15 = Solution2.findPairs(a15, k15);
        assertTrue(r15==7);

        int k16=42;
        int[] a16 = {80, 48, 88, 7, -97, 20, 22, -48, -86, 62, 30, 9, 0, 43, 37, 15, 44, 68, -37, 74};
        int r16 = Solution2.findPairs(a16, k16);
        assertTrue(r16==1);

        int k20=52;
        int[] a20 = {19, -45, 17, 41, -46, -97, 45, 23, 79, -24, 73, 76, 91, 87, 6, 71, 13, 62, 70, 14};
        int r20 = Solution2.findPairs(a20, k20);
        assertTrue(r20==3);

        int k27=35;
        int[] a27 = {17, 76, 93, 75, -6, 26, 30, 51, 18, -98, 25, 24, 50, 44, 51, 60, -26, 1, 52, 50, 39};
        int r27 = Solution2.findPairs(a27, k27);
        assertTrue(r27==2);

        int k28=47;
        int[] a28 = {49, 2, 91, 24};
        int r28 = Solution2.findPairs(a28, k28);
        assertTrue(r28==1);

        int k30=42;
        int[] a30 = {25, 21, 30, 97, 31, -27, 74, 69, 56, 50, 30, 85, 39, 71, 81, 45};
        int r30 = Solution2.findPairs(a30, k30);
        assertTrue(r30==1);

        int k32=12;
        int[] a32 = {63, 80, 40, 3, 31, 68, -61, -38};
        int r32 = Solution2.findPairs(a32, k32);
        assertTrue(r32==1);

        int k34=12;
        int[] a34 = {9, 25, 62, 43, 68, 91, 80, -1, 9, 38, 24, 40, -65};
        int r34 = Solution2.findPairs(a34, k34);
        assertTrue(r34==1);

        int k36=5;
        int[] a36 = {58, -83, 90, 24, 13, 54, -48, 45, 40, -75, 85, 74, 64, 18};
        int r36 = Solution2.findPairs(a36, k36);
        assertTrue(r36==3);

        int k37=53;
        int[] a37 = {48, 98, 51, 15, 88, -90, -3, -15, 2, 15, 67, 8, -92, 81, -47, -36, -85, 55, 40, 57};
        int r37 = Solution2.findPairs(a37, k37);
        assertTrue(r37==1);

        int k38=42;
        int[] a38 = {24, -81, 78, -44, 56, 34, 81, -25, 25, 67, 44, 91, 2, 69, 65, -8, -40, -93, 22};
        int r38 = Solution2.findPairs(a38, k38);
        assertTrue(r38==4);

        int k39=41;
        int[] a39 = {8, 14, -41, 32, 36, 71, -52, 50, 86, 0, -51, 60, -62, 90, 1, 44};
        int r39 = Solution2.findPairs(a39, k39);
        assertTrue(r39==1);

        int k41=14;
        int[] a41 = {95, 39, 73, 80, -90, 45, -47, 24, 19, 42, 53, 54, 70, 92, 52, 23, 68, 67, 86, 89, 16, 56, 13};
        int r41 = Solution2.findPairs(a41, k41);
        assertTrue(r41==5);

        int k42=30;
        int[] a42 = {50, -82, -19, 78, 51, -63, 22, 96, -67, -81, -57, 92, 28, 56, 20, 45, 59, 21, 4, 19, 18, 50, -64, 38};
        int r42 = Solution2.findPairs(a42, k42);
        assertTrue(r42==2);

        int k50=13;
        int[] a50 = {70, 74, -46, 36, -73, 65, 50, 48, 38, -19, 80, 12, 87, 41, 6, -69, 20, 86, 85, 15};
        int r50 = Solution2.findPairs(a50, k50);
        assertTrue(r50==1);

        int k51=10;
        int[] a51 = {1, 83, 55, 62, 65, 19, -12, 67, -78, 90, 52};
        int r51 = Solution2.findPairs(a51, k51);
        assertTrue(r51==2);

        int k54=6;
        int[] a54 = {94, 22, 97, -22, 49, 20, -80, 29, 20, 71, -48, 52, 4, 64, 34, 98, 43, -20, 26, 14, 25, 62, 80, -72};
        int r54 = Solution2.findPairs(a54, k54);
        assertTrue(r54==3);

        int k60=8;
        int[] a60 = {24, 76, 56, 74, 1, 70, 33, 35, 16, 59, 83, -30, -9, 7, 93, 46, 2};
        int r60 = Solution2.findPairs(a60, k60);
        assertTrue(r60==1);

        int k62=20;
        int[] a62 = {87, 75, 66, 14, 95, 15, -13, 81, 50, 14, 72, 88, 70, 74, 1, 92, 84, -88, 27, -18, -22, -24, 71, -56};
        int r62 = Solution2.findPairs(a62, k62);
        assertTrue(r62==3);

        int k63=29;
        int[] a63 = {-54, 43, 40, 68, -53, 77, -83, 80, 85, 88, 51, -99, 55, 73, -8, -39, 75, 85, 63, 43, 87, 44};
        int r63 = Solution2.findPairs(a63, k63);
        assertTrue(r63==3);

        int k65=28;
        int[] a65 = {81, 70, 4, 45, 14, -97, 67, -20, 13, 85, -16, 20, 95, 60, 64, 72};
        int r65 = Solution2.findPairs(a65, k65);
        assertTrue(r65==1);

        int k66=30;
        int[] a66 = {89, 78, 94, 18, 33, 17, 62, 30, 47, -5, 97, 2, 20, -16, 52, 61, 38, 56, 5, 3, 91};
        int r66 = Solution2.findPairs(a66, k66);
        assertTrue(r66==3);

        int k70=49;
        int[] a70 = {73, 60, -30, 60, 58, 23, 9, 92, 89};
        int r70 = Solution2.findPairs(a70, k70);
        assertTrue(r70==1);

        int k71=20;
        int[] a71 = {-20, 58, 91, 80, 0, 63, 92, 37, 12, -99, -58, 44, 73, -28, 87, 41, 61, 37, 77, 66, 65};
        int r71 = Solution2.findPairs(a71, k71);
        assertTrue(r71==2);

        int k72=13;
        int[] a72 = {-50, 84, 56, 46, 12, 51, 59, -86, 57, 26, 79, -26, 65, 81, 9, 20, 46, 71, 8, 13, 24, -63};
        int r72 = Solution2.findPairs(a72, k72);
        assertTrue(r72==4);

        int k75=18;
        int[] a75 = {53, 5, 71, 76, 18, 62, 81, 0, 27, 84, -61, -35, 64, 55, 63, 3, 64};
        int r75 = Solution2.findPairs(a75, k75);
        assertTrue(r75==3);

        int k77=41;
        int[] a77 = {11, 3, 71, 18, 44, 98, 89, 82, 55, 41, 89, 72};
        int r77 = Solution2.findPairs(a77, k77);
        assertTrue(r77==2);

        int k78=52;
        int[] a78 = {73, 1, 83, 22, 24, 45, 5, 66, 20, -22, 12, 68, 23, 73, -17, 30, 31, -9, -31};
        int r78 = Solution2.findPairs(a78, k78);
        assertTrue(r78==2);

        int k79=43;
        int[] a79 = {85, 83, 65, -13, 14, 49, 57, 43, -40, -14};
        int r79 = Solution2.findPairs(a79, k79);
        assertTrue(r79==1);

        int k80=19;
        int[] a80 = {59, 40, 98, -85, -33, 99, 52, 13, 75, 28, 94, 64, 25, -28, 64, 4, 0, 11, 20, 66, 18};
        int r80 = Solution2.findPairs(a80, k80);
        assertTrue(r80==2);

        int k82=21;
        int[] a82 = {60, 4, 42, 50, 15, 77, 36};
        int r82 = Solution2.findPairs(a82, k82);
        assertTrue(r82==1);

        int k83=22;
        int[] a83 = {-89, -43, 15, 82, -37, -59, 37, -82, 59, 70, 11, 21, 80, 82, 71, 60, 23, 43, 78, 1};
        int r83 = Solution2.findPairs(a83, k83);
        assertTrue(r83==6);

        int k85=35;
        int[] a85 = {-71, 0, 33, 16, 10, 2, 92, -76, 79, 24, 57, -41, 13, 41, 65, 90, 18, 75};
        int r85 = Solution2.findPairs(a85, k85);
        assertTrue(r85==2);

        int k86=20;
        int[] a86 = {99, 15, 61, 79, 55, 81, -15};
        int r86 = Solution2.findPairs(a86, k86);
        assertTrue(r86==2);

        int k87=14;
        int[] a87 = {6, 70, 46, 69, 42, -76, -20, -99, -98, -72, 98, 44, 33, 53, 83, 20, 13, -47, 49, -27, 11, 84, 48, 38};
        int r87 = Solution2.findPairs(a87, k87);
        assertTrue(r87==4);

        int k88=7;
        int[] a88 = {38, 13, 94, 11, 65, 0, 68, 35, 26, 36, -56, 68, 61, 75, 12, 99, 32, 74, -42, 20};
        int r88 = Solution2.findPairs(a88, k88);
        assertTrue(r88==3);

        int k90=30;
        int[] a90 = {75, 30, 15, 85, 51, -55, -71, 77, -97, -69, 78, 42, 81, -48, 2, -63, -14, 59, 64, 99, -18};
        int r90 = Solution2.findPairs(a90, k90);
        assertTrue(r90==2);

        int k95=48;
        int[] a95 = {12, -80, 20, 33, 8, 76, 23, 63, 87, 21, 35, 20, 6, 99, 84, 30, 28, 94, 54, 91, 93, 34, 56, 95};
        int r95 = Solution2.findPairs(a95, k95);
        assertTrue(r95==3);

        int k96=23;
        int[] a96 = {14, 72, 36, 81, 39, -34, 28, 61, 41, 92, 29, 59, 79, 72, 54, 64, 10};
        int r96 = Solution2.findPairs(a96, k96);
        assertTrue(r96==2);

        int k97=25;
        int[] a97 = {21, 87, 82, 30, 60, 73, -14, 68, 82, 14, 43, 41, -83, -54, -56, 83};
        int r97 = Solution2.findPairs(a97, k97);
        assertTrue(r97==1);
    }

}

Infraestructura de Integración Continua

Configuración, LINUX, Técnicos Comments Off on Infraestructura de Integración Continua
May 112020

Este post está dedicado a proveer instrucciones detalladas acerca de la manera en la que se debe crear una infraestructura de integración continua usando herramientas como GitLab, Jenkins, Nexus, Sonar, Swagger editor, Rancher, H2 y Keycloak. Todo lo anterior sobre AWS, pero con la asociación de nombres de dominio adecuados (subdominios) y su correspondiente SSL.

Requisitos básicos

A lo largo de este post se hará uso extensivo de conceptos, herramientas y tecnologías muy particulares que son enumeradas a continuación:

  1. Cuenta de un “Registar” como GoDaddy o Akky
  2. Cuenta AWS con privilegios para EC2 y Route53
  3. Cuenta con algún proveedor de certificados SSL
  4. Nuestra estación de trabajo deberá tener instalado el cliente de consola de aws también conocido como awscli y deberá estar configurado para que las credenciales de acceso estén creadas y disponibles para su uso

Esto último, aws cli, es posible que sea instalado en Ubuntu (probado en la versión 18.04) simplemente ejecutando el comando:

sudo apt install awscli

Posteriormente, se debreá configurar el cliente con las crdenciales requeridas. esto se puede hacer mediante:

aws configure

Durante la configuración se pedirán los siguientes datos:

  1. AWS Access Key ID
  2. AWS Secret Access Key ID
  3. Región (Yo uso: “us-east-1”)
  4. Formato (ENTER = FORMATO POR DEFAULT)

NOTA IMPORTANTE: Los valores de (1) y (2) son generados por un administrador de AWS, mediante el uso de la interfaz gráfica de AWS en la sección de seguridad. Son únicos y son revocables en cualquier momento. Sin estos datos será muy complejo continuar con este Tutorial. Es extremadamente recomendable obtenerlos en este punto antes de continuar con esta lectura.

Pasos previos a la creación de la Infraestructura

Antes de poder generar la Infraestructura de integración continua será necesario gestionar los siguiente:

I Compra de dominio

Un “Registrar” es una compañía (como GoDaddy o como Akky) que vende nombres de dominio que se encuentren disponibles. Generalmente es posible comprar un dominio “.com” o un dominio “.org” disponible por unos 10 dólares al año o menos. Hay dominios mas caros, como los dominios “.io” o los dominios “.tv” que cuestan unos 50 dólares al año.

Los dominios con nombres cortos ya han sido comprados y si se desea negociar su transferencia o venta, ésta puede llegar a costar miles de dólares. Un ejemplo es “Tesla” que fue vendido al fabricante de autos eléctricos por 75,000 dólares.

Una vez que el dominio ha sido adquirido, el “Registrar” enviará al comprador una serie de datos e instrucciones al correo que éste último indicó al momento del registro o compra del dominio. La operación completa toma al rededor de 10 minutos.

Es MUY recomendable que el correo que se indica para la compra del dominio en cuestión sea un correo dedicado para sólo este fin. En este sentido, conviene crear un correo gratuito (gmail, outlook, hotmail, yahoo o cualquier otro) y usarlo sólo para este propósito. De esta manera, si algún día decidimos vender el dominio, la transferencia será mucho mas fácil y directa.

Nota importante

II Creación de una Zona en AWS Route53

AWS Ofrece una interfaz para la gestión de dominios, sub dominios y registros A, AAA, CNAME, TXT, etc de los nombes de dominio que hayamos adquirido con un registrar. Esto es posible a través de la interfaz llamada Route53.

En el momento en el que damos de alta en Route53 un nombre de dominio que hayamos adquirido con algún “Registrar”, podremos observar que se generan cuatro cadenas de texto asociadas a los “name servers” (servidores de nombre) que AWS crea de manera automática. Se deberá tomar nota de esas cuatro cadenas ya que serán usadas en el siguiente paso.

III Alta de Name Servers en el “Registrar”

Con la información generada por AWS Route53 en referencia a las 4 cadenas de texto asociadas a los “Name Servers”, se deberá ingresar a la interfaz del “Registrar” y solicitar la redirección de los DNS’s que tiene (generalmente apuntados a servidores de nombre de si mismo) pero ahora ingresando la nueva información.

En un siguiente paso se verificará que si esto se hizo correctamente, ya que no es posible hacerlo de manera inmediata, pues este cambio generalmente toma una o dos horas en hacerse efectivo.

Mientras tanto, se deberán realizar otras actividades que se explican a continuación.

IV Generación de una IP estática, permanente y homologada

Durante este proceso, será requerida una única IP estática y homologada que será nuestra puerta de acceso a todos los servicios de nuestra infraestructura de integración continua.

La generación de una IP homologada es posible ya sea gracias a la interfaz de EC2 que provee AWS en la sección de “Elastic IP” o bien mediante la ejecución de un sencillo script para aws cli:

aws ec2 allocate-address \
    --domain vpc \
    --network-border-group us-east-1

Que nos genera la siguiente respuesta de EJEMPLO:

{
    "PublicIp": "70.224.234.241",
    "AllocationId": "eipalloc-02463d08ceEXAMPLE",
    "PublicIpv4Pool": "amazon",
    "NetworkBorderGroup": "us-east-1",
    "Domain": "vpc"
}

Evidentemente, esta respuesta será diferente cada vez que el primer comando sea invocado. El dato que nos interesa es el IP generado. En este ejemplo es “70.224.234.241”. Se deberá tomar nota de tal IP ya que será empleado en el siguiente paso.

También es MUY importante anotar el “AllocationId” asociado a esta IP, ya que será requerido al momento de asignar esta IP a una instancia de EC2, cosa que haremos hacia el final de este tutorial.

V Generación de subdominios

La generación de subdominios se realiza en la interfaz de Route53 que provee AWS y básicamente requiere de cuatro datos:

  1. Nombre del subdominio (es el conjunto de segmentos que van al inicio de nuestro nombre de dominio, como www, ftp o estructuras mas compplejas como srv01.ci, uno.dos.tres, etc)
  2. Tipo de registro, que en nuestro caso será siempre “A”, salvo un único caso que se discutirá próximamente (registro TXT)
  3. Dirección IP, que en nuestro caso es la IP estática, homologada generada en el punto IV
  4. TTL que es un número y en nuestro caso siempre será: 60 (“Time To live” representa el número de segundos de refresco)

También es posible usar el cliente consola de AWS para dar de alta tales subdominios. Si se desea realizar de esta forma, l referencia puede ser consultada en esta liga: https://docs.aws.amazon.com/cli/latest/reference/route53/index.html

Por otro lado, “en caso” de que se tenga la posibilidad de usar el sdk de aws, entonces la generación de varios dominios se puede “automatizar” con el siguiente segmento de código java que contiene sólo dos métodos:

    
    public CreateZoneSubdomains(String hostedZoneId, String domain, String ip) {
        String dns = Tools.getScriptTextPlain("zone-names.txt");
        String[] names = dns.split(" ");
        changeRecordSetTypeA(hostedZoneId, domain, ip);
        for(String name : names) {
            if(name.trim().length()>0) {
                changeRecordSetTypeA(hostedZoneId, name.trim() + ".ci."+domain, ip);
            }
        }
    }

    public ChangeResourceRecordSetsResult changeRecordSetTypeA(
            String hostedZoneId, String subdomain, String ip) {
        @SuppressWarnings("deprecation")
        AmazonRoute53Client route53Client = new AmazonRoute53Client();
   
        GetHostedZoneResult hostedZoneResult = route53Client.getHostedZone(
            new GetHostedZoneRequest(hostedZoneId));
        HostedZone hostedZone = hostedZoneResult.getHostedZone();
    
        ResourceRecordSet resourceRecordSet = new ResourceRecordSet()
            .withName(subdomain)
            .withType(RRType.A)
            .withTTL(60L)
            .withResourceRecords(new ResourceRecord().withValue(ip));
    
        ChangeResourceRecordSetsRequest request = new ChangeResourceRecordSetsRequest()
            .withHostedZoneId(hostedZone.getId())
            .withChangeBatch(new ChangeBatch()
                    .withChanges(new Change()
                            .withAction(ChangeAction.CREATE)
                            .withResourceRecordSet(resourceRecordSet)
                     )
             );
        Tools.prn("Se ha creado el subdominio: [%s] en el ip: [%s]\n", subdomain, ip);
        return route53Client.changeResourceRecordSets(request);
     }

VI Solicitud de certificados SSL

Con la información de propiedad de nombre de dominio es posible realizar la compra de certificados SSL. Para este caso, será INDISPENSABLE solicitar un certificado de tipo WILDCARD. Esto nos permitirá usarlo en cualquier subdominio del dominio asociado. Es recomendable que se pida del tipo “green”. Estos certificados, después de pagados los podemos empezar a usar de manera inmediata. El proceso completo de compra y descarga, posterior a la compra no toma mas de 10 minutos y los proveedores que ofrecen estos servicios son variados: Verisign, Commodo, CheapSSL, etc. Un certificado WILDCARD “green” de Verisign puede costar unos 50 usd al año, aproximadamente.

Próximamente tales certificados serán requeridos en la configuración del servidor Nginx, ya que habrá que indicar su trayectoria en un apartado similar al siguiente:

ssl_certificate     /some/path/fullchain.pem;
ssl_certificate_key /some/path/privkey.pem;

fullchain.pem is a concatenation of cert.pem and chain.pem in one file. In most servers you’ll specify this file as the certificate, so the entire chain will be send at once.

Fuente: Super Goose

En caso de que en un futuro se desee emplear otro servidor web, como Apache, por ejemplo, quizá sea necesario generar mas archivos asociados al SSL y si el vendedor no los generó ni envió de manera previa, la herramienta (libre) openssl quizá nos podría ser de utilidad para tal efecto.

En el momento de solicitar la generación de los archivos asociados al certificado SSL, es posible que el proveedor de certificados (por ejemplo, Verisign) nos pida crear un registro TXT en Route53. Sería un procedimiento prácticamente igual al que hicimos para la creación manual de subdominios en Route53, pero en vez de usar “A” sería “TXT”.

VII Creación del servidor de “Front”

En esta sección se creará un servidor EC2 al cual le asignaremos en su momento, la IP estática que nos entregó AWS y que responderá (via un servidor nginx) adecuadamente ante cada petición de nombre de dominio hacia tal IP.

Para este efecto, se requerirá de tener los siguientes recursos ya creados:

  1. Grupo de seguridad con puertos abiertos: 22, 80, 443, 1521, 5005 para el CIDR: 0.0.0.0./0
  2. Grupo de seguridad con puertos abiertos: 0-65535 para el CIDR: 171.31.0.0/16
  3. Keypair de acceso ssh para el servidor de Front (vale la pena crear este recurso en la interfaz de EC2)
  4. La IP estática y homologada generada en pasos previos (requeriremos el “id” asociado a esta IP. Si no lo anotamos cuando se creó, podemos recuperarlo en la interfaz de EC2)
  5. Archivo de Pre-Configuración e instalación de Software inicial.

Se recuerda que todas las operaciones, configuraciones y ajustes descritos en este documento, pueden ser gestionados directamente desde la interfaz de AWS, pero que también es posible usar la interfaz de linea de comandos “aws cli” para el mismo efecto. Dicho lo anterior, para la mayoría de solicitudes se mostrará el código asociado a ejecutar desde la interfaz de comandos “aws cli”.

El siguiente código nos permite crear un grupo de seguridad con las carecterísticas que se mencionan en párragos anteriores:

aws ec2 create-security-group \
--group-name my-sg-any-name \
--description "My security group description" \
--vpc-id vpc-4b8d0531

Obtendremos la siguiente respuesta:

{
    "GroupId": "sg-0824778f9d1e68ac1"
}

Con el “ID” obtenido, podremos agregar “reglas” a tal grupo. En este caso, la regla es la apertura del rango de puertos del 3389 al 4123, que serán accesibles sólo desde el rango de IP’s 172.31.0.0/16

aws ec2 authorize-security-group-ingress \
--group-id sg-0824778f9d1e68ac1 \
--protocol tcp \
--port 3389-4123 \
--cidr 172.31.0.0/16

Con 256×256 direcciones capacez de conectar con ese rango de puertos de la vpc existente de la región. El rango de IP’s fué calculado usando la herramienta en la siguiente liga: http://www.subnet-calculator.com/cidr.php

La bandera “–port” soporta un rango de puertos (como el que se usó) o un simple número, como 22, por ejemplo.

En este punto se deberá crear un “Keypair” y la mejor manera de hacer esto es via la interfaz de EC2. Para este ejemplo, el nombre del “Keypair” será “frontKey”

Nota importante !!!

Para crear una instancia de EC2, se deberá usar este código:

aws ec2 run-instances \
--image-id ami-085925f297f89fce1 \
--count 1 \
--instance-type t2.small \
--key-name frontKey \
--security-group-ids sg-058aa6ea0649c0f92 \
--user-data file://script_00.txt \
--block-device-mappings "[{\"DeviceName\":\"/dev/sda1\",\"Ebs\":{\"VolumeSize\":20,\"DeleteOnTermination\":false}}]"

Con lo anterior, se solicita la creación de una (–count=1) instancia de EC2 de Ubuntu 18_04 (ami-085925f297f89fce1), con 1 CPU y 2 Gigas de memoria RAM (t2.small), 20 Gb de disco SSD, con llave de acceso “frontKey”, en elgrupo de seguridad dado (sg-058aa6ea0649c0f92) y ejecutando la serie de comandos descritos en el archivo “script_00.txt”

El contenido del archivo “script_00.txt” es el siguiente:

#!/bin/bash

sh -c "echo 'LC_ALL=en_US.UTF-8\\nLANG=en_US.UTF-8' >> /etc/environment"

apt update
apt install -y docker-ce
apt install -y docker-compose
apt install -y s3fs
apt install -y sshfs

gpasswd -a ubuntu docker

mkdir -p /home/ubuntu/{.ssh,services,shared-s3,shared-ssh}
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDjybz2kqMxcryhVVOCRWPlBt9//gDTcQECrleQZyO2F1diR+7ANZ7iHFB1+ZdDRv6qi45aL7EaNDAtIxAJp4IxSYAiQeycdUfoiTX/HYkQWj5+13Zc0Rw+SARFJ9KnRZM8Al2olEOfqnCUxBkTj24sozfeSViAi+CfzANL/TlS1lfvbF/icbRgDqvXeqqqdOMxFf6rWYJG5nqIirfa6EpOWjsEnjLSWAyZCfuV/A6wk0fosSBQnzs/K6f8aSe2AZtDX7RRYQELeW7i2J2KS9DqpptMRRD1ysRBKp9qxqS7SKBEFVOMsUVLHRPbJcpdDc0SHLu7j/7sv3JGXJPyja2b" >> /home/ubuntu/.ssh/authorized_keys

wget --no-check-certificate 'https://cutt.ly/gzvViBW' -O /home/ubuntu/bridge.tar.gz

tar xzvf /home/ubuntu/bridge.tar.gz -C /home/ubuntu
chown -R ubuntu:ubuntu /home/ubuntu timedatectl set-timezone America/Mexico_City

Una vez que la instancia de EC2 está en estado operacional, se deberá asignar la IP estática homologada a tal instancia. Como siempre, esto puede ser realizado via la interfaz gráfica de AWS en la sección de EC2 (elastic IP) o bien via la ejecución del siguiente comando:

aws ec2 associate-address \
--instance-id i-0b263919b6498b123 \
--allocation-id eipalloc-64d5890a

Con lo anterior, hemos asociado el “id” de una dirección ip estática al “id” de una instancia EC2.

En este punto, ya es posible usar la llave privada de “frontKey” que generamos en la interfaz gráfica de AWS (módulo EC2) para acceder al servidor de front con la ip estática que acabamos de asociar y hasta lo podemos hecer con alguno de los nombres de dominio que hemos asociado a esa IP al inicio de este Tutorial. La forma de acceder se la siguiente:

ssh -i frontKey.pem -o "StrictHostKeyChecking no" ubuntu@server.com.mx

Una vez dentro…

1. correr el script de search & replace para el nombre del dominio
2. colocar los certificados en una ruta adecuada
3. correr el script para la generación del keystore de java
4. correr el script de arranque de Nginx
5. verificar que se llega a los dominios indicados

listo !!!! To be continue…

Mediterráneo... Un regalo de Serrat

General, Personal Comments Off on Mediterráneo… Un regalo de Serrat
Apr 042020

Quizás porque mi niñez
Sigue jugando en tu playa
Y escondido tras las cañas
Duerme mi primer amor,
Llevo tu luz y tu olor
Por dondequiera que vaya,
Y amontonado en tu arena
Guardo amor, juegos y penas.
Yo, que en la piel tengo el sabor
Amargo del llanto eterno
Que han vertido en ti cien pueblos
De algeciras a estambul
Para que pintes de azul
Sus largas noches de invierno.
A fuerza de desventuras,
Tu alma es profunda y oscura.
A tus atardeceres rojos
Se acostumbraron mis ojos
Como el recodo al camino.
Soy cantor, soy embustero,
Me gusta el juego y el vino,
Tengo alma de marinero.
Qué le voy a hacer, si yo
Nací en el mediterráneo.
Y te acercas, y te vas
Después de besar mi aldea.
Jugando con la marea
Te vas, pensando en volver.
Eres como una mujer
Perfumadita de brea
Que se añora y que se quiere
Que se conoce y se teme.
Ay, si un día para mi mal
Viene a buscarme la parca.
Empujad al mar mi barca
Con un levante otoñal
Y dejad que el temporal
Desguace sus alas blancas.
Y a mí enterradme sin duelo
Entre la playa y el cielo…
En la ladera de un monte,
Más alto que el horizonte.
Quiero tener buena vista.
Mi cuerpo será camino,
Le daré verde a los pinos
Y amarillo a la genista.
Cerca del Mar porque yo
Nací en el mediterráneo.

Code formatter... que bien se ve !!!

Configuración, General, Personal, Técnicos Comments Off on Code formatter… que bien se ve !!!
Mar 272020
var arreglo = [2,3,20,10,1,23];
arreglo.sort(function (a,b){
   return a-b
});

function ok() {
  console.log(arreglo);
}

Se ve genial, no?


Este es otro estilo
Y es mas compacto..

Y… este es el tercer estilo:

echo "usage: wherein <dir> <file-pattern> <string>"

for i in $(find $1 -name $2);
    do 
      if grep -i $3 "$i"; 
        then echo "$i"; 
      fi; 
done;

Gallito

General, Personal Comments Off on Gallito
Mar 272020

Yo, Gustavo

General, Personal, Técnicos Comments Off on Yo, Gustavo
Mar 182020

Técnicamente se hacer muy pocas cosas y tardo un poco en aprender cosas nuevas, pero las pocas cosas que sé hacer y que he tardado en aprender las sé hacer muy bien:

1. Puedo levantar una infraestructura de CI/CD de principio a fin con sus respectivos certificados SSL (Green) para cada servicio y mecanismos de backup y restauración en una infraestructura AWS. Se incuye GitLab, Jenkins, Nexus (+ registry Docker privado), SonarQube, OpenGrok y Rancher (front gráfico de Kubernetes)

2. Puedo desarrollar aplicativos Rest/Springboot/MyBatis/VueJs completamente Dockerizados, basados en una arquitectura de microservicios y listos para despliegue en una infraestructura de H.A. que también puedo preparar.

3. Puedo integrar al 100% una sub infraestructura de autorización y autenticación en Keycloak.

3. Conozco y practico el Agilismo y soy capaz de formar equipos de alto desempeño muy productivos y muy felices de hacer su trabajo.

4. Me gusta mucho transmitir conocimiento y mis alumnos, a lo largo de los años, dicen que lo hago muy bien.

¿A quién le gustaría contratarme?

Sólo cobro 5,000 usd al mes.

Abrazos,
Gus

© 2020 Goose Workshop Suffusion theme by Sayontan Sinha