Mostrando entradas con la etiqueta URL. Mostrar todas las entradas
Mostrando entradas con la etiqueta URL. Mostrar todas las entradas

miércoles, 21 de marzo de 2018

Trabajando con VMware Cloud en AWS, con REST-API y Python

Introducción

Últimamente hemos estado jugando mucho con la REST-API para VMware Cloud en AWS por una variedad de razones.

Esto nos ha dado una buena visión de muchos casos de uso donde el acceso programático sería preferible al "señalar y hacer clic" de la Interfaz Gráfica de Usuario (GUI por sus siglas en inglés).

Es muy común que aprovechemos el lenguaje Python para llamar a la REST-API, ya que es un lenguaje extremadamente fácil y flexible para empezar.

Es una configuración rápida y normalmente no necesitamos instalar ningún módulo adicional. El módulo "Solicitudes", que es el módulo más común utilizado para interactuar con "endpoints" http(s), se incluye en Python de forma predeterminada.

Como nota al margen, VMware tiene un SDK de Python (y también Java) para interactuar directamente con la API, sin utilizar REST. Podemos consultarlo aquí si deseamos obtener un poco más de Pythonic con sus aventuras en la API.

¡Comencemos!

Introducción: cómo extraer su clave OAuth

Para comenzar, necesitará una cuenta activa de VMware Cloud Services. Con una cuenta activa, desplegamos una clave OAuth que nos permitirá autenticar la API programáticamente.

Esta clave es efectivamente sus credenciales para el medio ambiente, por lo que probablemente debería proteger esto con su vida. Vamos a "exportar" esta clave en Linux para que no tengamos que colocar la clave de forma estática en nuestro código.

Para obtener nuestra clave de OAuth, inicie sesión en la url https://console.cloud.vmware.com y seleccione su nombre en la parte superior derecha, en el menú desplegable, seleccionaremos “OAuth Refresh Token”.


Después de esto, seleccionaremos "Token nuevo" o "Crear un nuevo token" en la página "OAuth Refresh Token".


Recuerde lo que mencionamos antes, este es un código MUY importante. Guárdemoslo de manera segura, guardémoslo con prudencia. ¡Ahora que tenemos este "token", podemos comenzar a bucear en el servicio!

Construyendo Nuestras Llamadas para REST

Estos ejemplos se realizarán en Python 3.6 para Ubuntu en Windows. Sí, usaremos el shell de Linux en Windows. Utilizaremos algunos F String aquí, así que es una buena idea saber lo que hacemos. Son una forma práctica de hacer que nuestro código sea un poco más limpio.

En Linux, podemos usar el comando de exportación para almacenar variables en la memoria y llamarlas dentro de Python, usando el módulo del sistema operativo.

El beneficio de esto es que no se almacenan a largo plazo en un archivo estático en algún lugar donde la gente puede leerlos, y cuando el comando ejecutado en el "shell" termina, ¡ya no está! En este caso, exportaremos oauthkey = 'yourkeydigitshere' y luego lanzaremos nuestro "shell" de Python.

NOTA: Las cadenas F se agregaron en Python 3.6, por lo que si no está ejecutando eso, querrá asignar las variables estáticamente y concatenarlas según sea necesario.

import requests 
import os 

oauth = os.environ['oauthkey']
baseurl = 'https://console.cloud.vmware.com/csp/gateway'
uri = '/am/api/auth/api-tokens/authorize'
headers = {'Content-Type':'application/json'}
payload = {'refresh_token': oauth}
r = requests.post(f'{baseurl}{uri}', headers = headers, params = payload)
print(r.status_code)

Dando un paso atrás para explicar qué está pasando aquí:
  • Importamos el módulo de solicitudes para trabajar con nuestros puntos finales API e importamos el módulo os para que interactúe con las variables de entorno. Ambos módulos tienen capacidades extensas fuera de lo que acabo de mencionar, pero esto es para lo que los usamos en esta publicación
  • Configuramos el mapa de variables "oauth" a la variable de entorno que establecemos fuera de python utilizando el método "os.environ"
  • Establecemos "baseurl" como una variable, específicamente como la URL raíz o "root" con la que vamos a trabajar.
  • Configuramos la variable uri como el punto final API al que intentamos llamar, en este caso, estamos llamando al punto final API para la autorización del "token".
  • Comenzamos a construir nuestros encabezados y nuestros parámetros. Para nuestra variable de encabezados, establecemos nuestro tipo de contenido que se espera para 'application/json'.

    Realmente no NECESITAMOS hacer esto; pero establecer un tipo de contenido es la mejor práctica cuando se trabaja con la API. También establecemos que nuestra carga útil "body" sea un objeto JSON que contenga nuestra clave "OAuth", también conocida como "token de actualización" en la nube de VMware.
  • Finalmente, imprimimos el código de estado de la devolución, para saber si entramos. Esperamos un código de estado de respuesta "200". AnythingElse == 'bad'.
¿Cómo sabemos qué URL usar para la autenticación? En la versión más reciente de VMware Cloud en AWS, el equipo lanzó Developer Center, una interfaz de usuario completa construida en torno a las integraciones de la API.


Desde esta vista, podemos navegar al menú "Operaciones de autenticación" y usar esto para ver detalles sobre las diversas llamadas posibles al servicio de autenticación.


Una gran ayuda para Alan Renouf y su equipo por obtener esta función: es una gran ayuda para aquellos de nosotros que estamos tratando de trabajar con VMware Cloud Services desde una perspectiva de la API.

Cuando se ejecuta nuestro "script", con nuestra clave OAuth correctamente aplicada; deberíamos obtener ese código de respuesta 200 sin ningún problema.

Si imprimimos (r.json ()) en este caso, veremos nuestro retorno de token de acceso, junto con el tiempo que tarda en caducar, el tipo de token y algunos valores relacionados con el permiso. Nos hemos autenticado.

Python Shell

¿Cómo podemos mejorar esto? ¿No podemos verificar una falla antes de imprimir? Además, esto funciona bien como un guión, pero ¿y si quisiéramos construir algo un poco extensible? ¿O reutilizar este código en todo nuestro programa? ¿Tiene sentido para nosotros?

Mejorando nuestro inicio de sesión API - Declaraciones y funciones "if"

Podemos realizar comprobaciones proactivas usando una declaración if para verificar y ver "if" la respuesta es lo que queremos que sea.

Como se puede imaginar, para los no adoctrinados, usar una declaración if es muy parecido a decir "si algo es ESTO, haz ALGO, de lo contrario, podemos hacer ESO". En este caso, la actualización es bastante simple.

Podemos agregar el siguiente bloque a nuestro código para hacer que verifique durante el proceso de inicio de sesión, y devolver un error si no puede iniciar sesión correctamente.

if r.status_code != 200:
    print(f'Unsuccessful Login Attempt. Error code {r.status_code}')
else:
    print('Login successful. ') 

Esto es muy fácil de leer, y un ejemplo extremadamente común de una declaración "if" en Python con la REST API. Si el código de estado que se devuelve cuando se ejecuta "r" es algo distinto a 200, imprima el error y díganos el código. De lo contrario, imprima que el inicio de sesión fue exitoso.

Además, la mejor práctica generalmente dice que la creación de funciones es bueno cuando se trata de código. Esto nos permitirá ejecutar un comando simple, como "iniciar sesión", mientras le damos un valor para iniciar sesión correctamente y devolver nuestras credenciales de autenticación.

La mejor parte de esto es que podemos configurar el formato de la respuesta devuelta para que esté en un formato que podamos incluir en OTRAS llamadas a la API.

def login():
    key = os.environ['oauthkey']
    baseurl = 'https://console.cloud.vmware.com/csp/gateway'
    uri = '/am/api/auth/api-tokens/authorize'
    headers = {'Content-Type':'application/json'}
    payload = {'refresh_token': key}
    r = requests.post(f'{baseurl}{uri}', headers = headers, params = payload)
    if r.status_code != 200:
        print(f'Unsuccessful Login Attmept. Error code {r.status_code}')
    else:
        print('Login successful. ')
        auth_json = r.json()['access_token']
        auth_Header = {'Content-Type':'application/json','csp-auth-token':auth_json}
        return auth_Header

El gran problema aquí es ser consciente de nuestro espacio. Python requiere consistencia en esto. Podemos ver que hacemos un simple def login() para comenzar las cosas. Esto declara nuestra función.

A continuación, implementamos el mismo código que nuestro script anterior, con la adición de nuestra verificación de respuesta de estado. Una vez que nuestra verificación se aprueba exitosamente (200 respuestas), imprimimos que el inicio de sesión fue exitoso y construimos nuestro encabezado de autenticación.

Para construir esto, sacamos la clave "access_token" del JSON de la respuesta y la construimos en un nuevo objeto de encabezado llamado "auth_Header", donde establecemos nuestra clave "content-type" y "csp-auth-token". La declaración de devolución al final "devuelve" este encabezado cuando la llamada se realiza correctamente.

Llamando a VMware Cloud vía la AWS REST API

Ahora que tenemos una función de inicio de sesión definida, podemos ser aún más creativos con nuestra llamada a la API. La URL base anterior que usamos es para la API de VMware Cloud Services.

Uno de los componentes principales de esto es el servicio de autenticación. Lo que NO incluye son los Servicios de nube individuales, como la oferta de "VMware Cloud on AWS". Para eso, necesitamos usar una URL DIFERENTE.

Hemos abstraído la mayoría del código de inicio de sesión ahora, lo que acortará drásticamente nuestras próximas llamadas. Probemos uno simple para enumerar todas las organizaciones a las que pertenece la cuenta de usuario de VMwware Cloud Services.

Si miramos el centro de desarrolladores, en el menú "Organizaciones", podemos ver el URI que debemos llamar para extraer los datos de "Org".


Una cosa que no está documentada actualmente en el Centro de desarrolladores, es que la URL base para VMware Cloud en AWS es "https://vmc.vmware.com/vmc/api".

Como puede ver en el centro de desarrolladores, debemos adjuntar "/orgs" a la URL base. Para llamar a esta API, también debemos incluir nuestro encabezado de autenticación en la llamada real. Con nuestra función de inicio de sesión anterior que creamos, esto hace las cosas mucho más simples.

auth_header = login()
orgList = requests.get('https://vmc.vmware.com/vmc/api/orgs', headers = auth_header)
print(orgList.status_code)

¡Éxito! Cuando ejecutamos este código, podemos ver que nuestro código de estado devuelto es 200.

Authentication Login

VMware Cloud on AWS API devuelve JSON, por lo que es muy fácil de analizar con Python. Podemos movernos a través del JSON devuelto utilizando un bucle simple para proporcionarnos el nombre y la ID de organización para cada uno de los objetos.

La identificación de la organización es necesaria para llamadas que profundizan en VMware Cloud en AWS, por lo que es importante.

auth_header = login()
orgList = requests.get('https://vmc.vmware.com/vmc/api/orgs', headers = auth_header)
for org in orgList.json():
    print("Org Name: " + org['display_name'])
    print("Org ID: " + org['id'])

Aquí hemos introducido un bucle "for", como mencionamos anteriormente. Básicamente, estamos diciendo "para cada organización en el objeto JSON devuelto por el "orglist", imprima datos desde allí".

Analizamos nuestro JSON, llamando a las claves específicas adjuntas a nuestro bucle "for". Cuando activamos la llamada, usando todo lo que hemos construido hasta ahora, se nos devuelve el siguiente contenido:


"OBTENER" nuestros SDDC's

Para nuestro concepto final, vamos a tomar los datos que hemos llamado anteriormente y devolver los datos de un solo SDDC. Podemos ver en la respuesta que nos devolvieron 2 Organizaciones de nuestra llamada anterior.

Vamos a trabajar con la segunda organización en esa lista. Es un poco engañoso si nunca antes se ha trabajado con un lenguaje de scripting o de codificación, pero "1" en realidad se refiere al segundo elemento de la matriz (siendo 0 el primero). Juguemos con nuestro código un poco más:

auth_header = login()
orgList = requests.get('https://vmc.vmware.com/vmc/api/orgs', headers = auth_header)
orgID = orgList.json()[1]['id']
print(orgID)

Cuando ejecutamos este bloque, podemos confirmar que nuestro "OrgID" se devuelve como se esperaba. Para poder "OBTENER (GET)" y SDDC, debemos volver al centro de desarrolladores para comprender el URI de la API a la que debemos llamar.


Hay un montón de opciones en el menú SDDC, pero finalmente solo queremos el "URI SDDCS" principal. Podemos ver en la llamada que necesitamos alimentar el ID de la organización en el URI de la API. Qué bueno que hayamos establecido cómo hacerlo en la sección anterio. Ya que estamos seguros de que esta llamada a la API va a funcionar, también incluiremos

auth_header = login()
orgList = requests.get('https://vmc.vmware.com/vmc/api/orgs', headers = auth_header)
orgID = orgList.json()[1]['id']
sddcList = requests.get(f'https://vmc.vmware.com/vmc/api/orgs/{orgID}/sddcs', headers = auth_header)
if sddcList.status_code != 200:
    print('API Error')
else:
    for sddc in sddcList.json():
        print("SDDC Name: " + sddc['name'])
        print("SDDC Create Date: " + sddc['created'])
        print("SDDC Provider: " + sddc['provider'])
        print("SDDC Region: " + sddc['resource_config']['region'])

Que largo camino hemos recorrido; y ahora estamos al final. Con estas modificaciones en nuestro script, podemos analizar el resultado del SDDC y obtener algunos datos básicos sobre el clúster SDDC que se ha creado.

Usamos el concepto de "f-string" del que hablamos anteriormente para alimentar en nuestro OrgID a la API "GET" de SDDC. Una vez que recuperamos el valor, analizamos el JSON y extraemos la información relevante que queríamos.

Aquí usamos un bucle "for", pero finalmente solo hay un SDDC en el objeto, por lo que solo se imprime una vez. Sin embargo, si tuviéramos varios SDDC, imprimiría todos:


Éxito. Finalmente hemos llegado a nuestro clúster de vCenter real que vive en AWS y podemos devolver datos desde él.

Conclusión

Aquí se cubren muchos conceptos avanzados, pero podemos ver que es muy fácil llegar a un lugar en el que extraemos datos relevantes de nuestra infraestructura. Hasta ahora nos hemos centrado exclusivamente en las llamadas a la API "GET", pero también hay "PUT", "POST" y "DELETE" que aún no hemos tocado.

¿Imagine crear una función de envío que agregue hosts o los elimine a través de "FaaS"? ¿Se imagina hacerlo en Lambda o vRealize Automation? Imagine desplegar nuevos centros de datos cuando entraste en un nuevo proyecto. Hay muchas opciones con las que podemos jugar.