UNPKG

@netzreich/openstack-clients

Version:

Openstack Client generated via OpenAPI Spec via openapi-generator

266 lines (240 loc) 9.01 kB
import * as Compute from "./compute"; import * as Network from "./network"; import * as Identity from "./identity"; import { BaseAPI } from "./identity/base"; import { Logger, LoggerInterface } from "./logger"; import { time } from "console"; import { AxiosError } from "axios"; type ComputeType = ReturnType<typeof Compute.ExtensionsApiFactory> & ReturnType<typeof Compute.OsSimpleTenantUsageApiFactory> & ReturnType<typeof Compute.ServersApiFactory> & ReturnType<typeof Compute.FlavorsApiFactory> & ReturnType<typeof Compute.ImagesApiFactory> & ReturnType<typeof Compute.OsKeypairsApiFactory>; type NetworkType = ReturnType<typeof Network.NetworksApiFactory> & ReturnType<typeof Network.SubnetsApiFactory> & ReturnType<typeof Network.PortsApiFactory> & ReturnType<typeof Network.SecurityGroupsApiFactory> & ReturnType<typeof Network.SecurityGroupRulesApiFactory> & ReturnType<typeof Network.FloatingipPoolsApiFactory> & ReturnType<typeof Network.QosApiFactory> & ReturnType<typeof Network.RoutersApiFactory>; type IdentityType = ReturnType<typeof Identity.AuthApiFactory> & ReturnType<typeof Identity.RolesApiFactory> & ReturnType<typeof Identity.UsersApiFactory> & ReturnType<typeof Identity.ProjectsApiFactory> & ReturnType<typeof Identity.DomainsApiFactory> & ReturnType<typeof Identity.ServicesApiFactory> & ReturnType<typeof Identity.EndpointsApiFactory> & ReturnType<typeof Identity.GroupsApiFactory> & ReturnType<typeof Identity.RoleAssignmentsApiFactory>; function removeVersionFromPath(path: string = ""): string { // Regex zum Entfernen der Version und des letzten Slashes return path.replace(/\/v[\d.]+$/, ""); } export default class OpenStack { public Compute: ComputeType; public Identity: IdentityType; public Network: NetworkType; private configuration: Identity.Configuration; private _token?: string; private _catalog?: Identity.AuthCatalogGetResponseCatalogInner[]; private expires_at?: Date; private _retry: ReturnType<typeof setTimeout> | undefined; public isAuthenticated = false; firsTime = true; constructor( configuration: Identity.Configuration, private _auth: Identity.AuthTokensPostRequest, private logger: LoggerInterface = new Logger() ) { this.Identity = { ...Identity.AuthApiFactory(configuration), ...Identity.RolesApiFactory(configuration), ...Identity.RoleAssignmentsApiFactory(configuration), ...Identity.UsersApiFactory(configuration), ...Identity.ProjectsApiFactory(configuration), ...Identity.DomainsApiFactory(configuration), ...Identity.ServicesApiFactory(configuration), ...Identity.EndpointsApiFactory(configuration), ...Identity.GroupsApiFactory(configuration), }; this.configuration = configuration; this.Compute = { ...Compute.ExtensionsApiFactory(configuration), ...Compute.OsSimpleTenantUsageApiFactory(configuration), ...Compute.ServersApiFactory(configuration), ...Compute.FlavorsApiFactory(configuration), ...Compute.ImagesApiFactory(configuration), ...Compute.OsKeypairsApiFactory(configuration), }; this.Network = { ...Network.NetworksApiFactory(configuration), ...Network.SubnetsApiFactory(configuration), ...Network.PortsApiFactory(configuration), ...Network.SecurityGroupsApiFactory(configuration), ...Network.SecurityGroupRulesApiFactory(configuration), ...Network.FloatingipPoolsApiFactory(configuration), ...Network.QosApiFactory(configuration), ...Network.RoutersApiFactory(configuration), }; setInterval(() => { if (this.isTokenExpired()) { this.authenticate(this._auth, false, 1000).catch((e) => { this.logger.error(e.message) }); } }, 1000 * 10); } private async _authenticate( credentials: Identity.AuthTokensPostRequest = this._auth, timeout = 1000 ) { const authResponse = await this.Identity.authTokensPost(credentials, { timeout, // fail fast and retry instead }); const token = authResponse.headers["x-subject-token"]; this._token = token; const catalog = authResponse.data.token?.catalog; if (!catalog) { this.logger.error("No catalog found in response"); throw new Error("No catalog found in response"); } if (authResponse.data.token?.expires_at) { this.logger.log( "New Token expires at: ", authResponse.data.token.expires_at ); this.expires_at = new Date(authResponse.data.token.expires_at); } if (authResponse.data.token?.expires_at === null) { // null means token never expires this.expires_at = new Date( new Date().setFullYear(new Date().getFullYear() + 100) ); } this._catalog = catalog; this.initializeApis(catalog); this.isAuthenticated = true; return authResponse; } isTokenExpired(): boolean { if ( this._token && this.expires_at && !(this.expires_at.getTime() < new Date().getTime()) ) { return false; } return true; } public async authenticate( credentials: Identity.AuthTokensPostRequest = this._auth, retryOnError = true, retryInterval = 60 * 1000, timeout = 1000 ): Promise<Identity.AuthTokensPostResponse | void> { try { if (this.isTokenExpired()) { this.logger.log("Token expired - authenticating"); return this._authenticate(credentials, timeout) .then((resp) => resp.data) .catch((e) => { this.logger.error(e.message) return Promise.reject(e); }); } return void 0; } catch (e: any) { this.isAuthenticated = false; this._token = undefined; this.expires_at = undefined; this.logger.error(`Failed to authenticate: ${e.message}`); if (retryOnError) { this.logger.log(`Retrying every 10s`); } throw e; } } public switchEndpointInterface(interfaceName: string) { if (!this._catalog) { this.logger.error("No catalog found in response"); throw new Error("No catalog found in response"); } this.initializeApis(this._catalog, interfaceName); } private initializeApis( catalog: Identity.AuthCatalogGetResponseCatalogInner[], entrypointInterface: string = "public" ) { this.initializeApi("compute", catalog, entrypointInterface); this.initializeApi("network", catalog, entrypointInterface); this.initializeApi("identity", catalog, entrypointInterface); } private initializeApi( type: string, catalog: Identity.AuthCatalogGetResponseCatalogInner[], entrypointInterface: string = "public" ) { const service = catalog.find((entry) => entry.type === type); if (!service || !service.endpoints) { this.logger.error(`No ${type} service found in catalog`); throw new Error(`No ${type} service found in catalog`); } const endpoint = service.endpoints.find( (endpoint) => endpoint.interface === entrypointInterface ); if (!endpoint || !endpoint.url) { this.logger.error( `No ${entrypointInterface} endpoint found in ${type} service` ); throw new Error( `No ${entrypointInterface} endpoint found in compute service` ); } const parsedUrl = new URL(endpoint.url); const config = new Identity.Configuration({ ...this.configuration, }); config.basePath = `${parsedUrl.protocol}//${ parsedUrl.host }${removeVersionFromPath(parsedUrl.pathname)}`; config.baseOptions.headers["X-Auth-Token"] = this._token; if (type === "compute") { this.Compute = { ...Compute.ExtensionsApiFactory(config), ...Compute.OsSimpleTenantUsageApiFactory(config), ...Compute.ServersApiFactory(config), ...Compute.FlavorsApiFactory(config), ...Compute.ImagesApiFactory(config), ...Compute.OsKeypairsApiFactory(config), }; } if (type === "network") { this.Network = { ...Network.NetworksApiFactory(config), ...Network.SubnetsApiFactory(config), ...Network.PortsApiFactory(config), ...Network.SecurityGroupsApiFactory(config), ...Network.SecurityGroupRulesApiFactory(config), ...Network.FloatingipPoolsApiFactory(config), ...Network.QosApiFactory(config), ...Network.RoutersApiFactory(config), }; } if (type === "identity") { this.Identity = { ...Identity.AuthApiFactory(config), ...Identity.RolesApiFactory(config), ...Identity.UsersApiFactory(config), ...Identity.RoleAssignmentsApiFactory(config), ...Identity.ProjectsApiFactory(config), ...Identity.DomainsApiFactory(config), ...Identity.ServicesApiFactory(config), ...Identity.EndpointsApiFactory(config), ...Identity.GroupsApiFactory(config), }; } } } export { Compute, Network, Identity };