github.com/kyma-project/kyma-environment-broker@v0.0.1/testing/e2e/skr/kyma-environment-broker/client.js (about)

     1  const axios = require('axios');
     2  const fs = require('fs');
     3  const {debug, getEnvOrThrow} = require('../utils');
     4  const {OAuthCredentials, OAuthToken} = require('../lib/oauth');
     5  
     6  const SCOPES = ['broker:write'];
     7  const KYMA_SERVICE_ID = '47c9dcbf-ff30-448e-ab36-d3bad66ba281';
     8  const trialPlanID = '7d55d31d-35ae-4438-bf13-6ffdfa107d9f';
     9  
    10  class KEBConfig {
    11    static fromEnv() {
    12      return new KEBConfig(
    13          getEnvOrThrow('KEB_HOST'),
    14          OAuthCredentials.fromEnv('KEB_CLIENT_ID', 'KEB_CLIENT_SECRET'),
    15          getEnvOrThrow('KEB_GLOBALACCOUNT_ID'),
    16          getEnvOrThrow('KEB_SUBACCOUNT_ID'),
    17          getEnvOrThrow('KEB_USER_ID'),
    18          getEnvOrThrow('KEB_PLAN_ID'),
    19          process.env.KEB_REGION,
    20          process.env.KEB_PLATFORM_REGION,
    21          process.env.KEB_TOKEN_URL,
    22      );
    23    }
    24  
    25    constructor(host, credentials, globalAccountID, subaccountID, userID, planID, region, platformRegion, tokenUrl) {
    26      this.host = host;
    27      this.credentials = credentials;
    28      this.globalAccountID = globalAccountID;
    29      this.subaccountID = subaccountID;
    30      this.userID = userID;
    31      this.planID = planID;
    32      this.region = region;
    33      this.platformRegion = platformRegion;
    34      this.tokenUrl = tokenUrl;
    35    }
    36  }
    37  
    38  class KEBClient {
    39    constructor(config) {
    40      let tokenUrl = `https://oauth2.${config.host}/oauth2/token`;
    41      if (config.tokenUrl) {
    42        tokenUrl = config.tokenUrl;
    43      }
    44      this.token = new OAuthToken(tokenUrl, config.credentials);
    45      this.host = config.host;
    46      this.globalAccountID = config.globalAccountID;
    47      this.subaccountID = config.subaccountID;
    48      this.userID = config.userID;
    49      this.planID = config.planID;
    50      this.region = config.region;
    51      this.platformRegion = config.platformRegion;
    52    }
    53  
    54    async buildRequest(payload, endpoint, verb) {
    55      const token = await this.token.getToken(SCOPES);
    56      const platformRegion = this.getPlatformRegion();
    57      const url = `https://kyma-env-broker.${this.host}/oauth/${platformRegion}v2/${endpoint}`;
    58      const headers = {
    59        'X-Broker-API-Version': 2.14,
    60        'Authorization': `Bearer ${token}`,
    61        'Content-Type': 'application/json',
    62      };
    63      const request = {
    64        url: url,
    65        method: verb,
    66        headers: headers,
    67        data: payload,
    68      };
    69      return request;
    70    }
    71  
    72    async buildRequestWithoutToken(payload, endpoint, verb) {
    73      const url = `https://kyma-env-broker.${this.host}/${endpoint}`;
    74      const headers = {
    75        'X-Broker-API-Version': 2.14,
    76        'Content-Type': 'application/json',
    77      };
    78      const request = {
    79        url: url,
    80        method: verb,
    81        headers: headers,
    82        data: payload,
    83      };
    84      return request;
    85    }
    86  
    87    async callKEB(payload, endpoint, verb) {
    88      const config = await this.buildRequest(payload, endpoint, verb);
    89  
    90      try {
    91        const resp = await axios.request(config);
    92        if (resp.data.errors) {
    93          throw new Error(resp.data);
    94        }
    95        return resp.data;
    96      } catch (err) {
    97        const msg = 'Error calling KEB';
    98        if (err.response) {
    99          throw new Error(`${msg}: ${err.response.status} ${err.response.statusText}`);
   100        } else {
   101          throw new Error(`${msg}: ${err.toString()}`);
   102        }
   103      }
   104    }
   105  
   106    async callKEBWithoutToken(payload, endpoint, verb) {
   107      const config = await this.buildRequestWithoutToken(payload, endpoint, verb);
   108      try {
   109        const resp = await axios.request(config);
   110        if (!(resp.status === 403 || resp.status === 401)) {
   111          throw new Error(`Unexpected status: ${resp.status}`);
   112        }
   113      } catch (err) {
   114        const msg = 'Error calling KEB';
   115        if (err.response) {
   116          if (!(err.response.status === 403 || err.response.status === 401)) {
   117            throw new Error(`${msg}: ${err.response.status} ${err.response.statusText}`);
   118          }
   119        } else {
   120          throw new Error(`${msg}: ${err.toString()}`);
   121        }
   122      }
   123    }
   124  
   125    async getSKR(instanceID) {
   126      const endpoint = `service_instances/${instanceID}`;
   127      try {
   128        return await this.callKEB({}, endpoint, 'get');
   129      } catch (err) {
   130        throw new Error(`error while getting SKR: ${err.toString()}`);
   131      }
   132    }
   133  
   134    async getCatalog() {
   135      const endpoint = `catalog`;
   136      try {
   137        return await this.callKEB({}, endpoint, 'get');
   138      } catch (err) {
   139        throw new Error(`error while getting catalog: ${err.toString()}`);
   140      }
   141    }
   142  
   143    buildPayload(name, instanceID, platformCreds, btpOperatorCreds, customParams) {
   144      const payload = {
   145        service_id: KYMA_SERVICE_ID,
   146        plan_id: this.planID,
   147        context: {
   148          globalaccount_id: this.globalAccountID,
   149          subaccount_id: this.subaccountID,
   150          user_id: this.userID,
   151        },
   152        parameters: {
   153          name: name,
   154          // Trial plan doesn't require region
   155          ...(this.planID === trialPlanID ? {} : {region: this.region}),
   156          ...customParams,
   157        },
   158      };
   159  
   160      if (platformCreds && btpOperatorCreds) {
   161        payload.context['sm_platform_credentials'] = {
   162          credentials: {
   163            basic: {
   164              username: platformCreds.credentials.username,
   165              password: platformCreds.credentials.password,
   166            },
   167          },
   168          url: btpOperatorCreds.smURL,
   169        };
   170      } else if (btpOperatorCreds) {
   171        payload.context['sm_operator_credentials'] = {
   172          clientid: btpOperatorCreds.clientid,
   173          clientsecret: btpOperatorCreds.clientsecret,
   174          sm_url: btpOperatorCreds.smURL,
   175          url: btpOperatorCreds.url,
   176        };
   177      }
   178      return payload;
   179    }
   180  
   181    async provisionSKR(name, instanceID, platformCreds, btpOperatorCreds, customParams) {
   182      const payload = this.buildPayload(name, instanceID, platformCreds, btpOperatorCreds, customParams);
   183  
   184      const endpoint = `service_instances/${instanceID}`;
   185      try {
   186        return await this.callKEB(payload, endpoint, 'put');
   187      } catch (err) {
   188        throw new Error(`error while provisioning SKR: ${err.toString()}`);
   189      }
   190    }
   191  
   192    async updateSKR(instanceID, customParams, btpOperatorCreds, isMigration) {
   193      const payload = {
   194        service_id: KYMA_SERVICE_ID,
   195        context: {
   196          globalaccount_id: this.globalAccountID,
   197          isMigration: isMigration,
   198        },
   199        parameters: {
   200          ...customParams,
   201        },
   202      };
   203  
   204      if (btpOperatorCreds) {
   205        payload.context['sm_operator_credentials'] = {
   206          clientid: btpOperatorCreds.clientId,
   207          clientsecret: btpOperatorCreds.clientSecret,
   208          sm_url: btpOperatorCreds.smURL,
   209          url: btpOperatorCreds.url,
   210        };
   211      }
   212  
   213      const endpoint = `service_instances/${instanceID}?accepts_incomplete=true`;
   214      try {
   215        return await this.callKEB(payload, endpoint, 'patch');
   216      } catch (err) {
   217        throw new Error(`error while updating SKR: ${err.toString()}`);
   218      }
   219    }
   220  
   221    async getOperation(instanceID, operationID) {
   222      const endpoint = `service_instances/${instanceID}/last_operation?operation=${operationID}`;
   223      try {
   224        return await this.callKEB({}, endpoint, 'get');
   225      } catch (err) {
   226        debug(err.toString());
   227        return new Error(`error while checking SKR State: ${err.toString()}`);
   228      }
   229    }
   230  
   231    async deprovisionSKR(instanceID) {
   232      const endpoint = `service_instances/${instanceID}?service_id=${KYMA_SERVICE_ID}&plan_id=${this.planID}`;
   233      try {
   234        return await this.callKEB(null, endpoint, 'delete');
   235      } catch (err) {
   236        return new Error(`error while deprovisioning SKR: ${err.toString()}`);
   237      }
   238    }
   239  
   240    async downloadKubeconfig(instanceID) {
   241      const downloadUrl = `https://kyma-env-broker.${this.host}/kubeconfig/${instanceID}`;
   242      debug(`Downloading kubeconfig from: ${downloadUrl}`);
   243      return new Promise(async (resolve, reject) => {
   244        const writeStream = fs
   245            .createWriteStream('./shoot-kubeconfig.yaml')
   246            .on('error', function(err) {
   247              reject(err);
   248            })
   249            .on('finish', function() {
   250              writeStream.close();
   251              fs.readFile('./shoot-kubeconfig.yaml', 'utf8', (err, data) => {
   252                fs.unlinkSync('./shoot-kubeconfig.yaml');
   253                resolve(data);
   254              });
   255            });
   256  
   257        try {
   258          const resp = await axios.request({
   259            method: 'get',
   260            url: downloadUrl,
   261            responseType: 'stream',
   262          });
   263          if (resp.data.errors) {
   264            throw new Error(resp.data);
   265          }
   266          resp.data.pipe(writeStream);
   267        } catch (err) {
   268          debug(err.data);
   269          fs.unlinkSync('./shoot-kubeconfig.yaml');
   270          reject(err);
   271        }
   272      });
   273    }
   274  
   275    getPlatformRegion() {
   276      if (this.platformRegion && this.platformRegion != '') {
   277        return `${this.platformRegion}/`;
   278      }
   279      return '';
   280    }
   281  }
   282  
   283  module.exports = {
   284    KEBConfig,
   285    KEBClient,
   286  };