@skyramp/skyramp 0.4.31 → 1.0.0-sha.b2dfe11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,93 +1,24 @@
1
- # skyramp
2
-
3
- `skyramp` is an npm module that provides utility functions for leveraging [skyramp CLI](https://skyramp.dev/docs/commands/skyramp/) commands. The `skyramp` module provides functionalities to create and apply mock configurations for both gRPC and REST APIs. It also offers features for testing and asserting scenarios in various test environments. The module exports the following classes: `RestEndpoint`, `GrpcEndpoint`, `Scenario`, and `SkyrampClient`.
1
+ # Skyramp
2
+ Skyramp is an npm module that provides utility functions for leveraging [skyramp CLI](https://skyramp.dev/docs/commands/skyramp/) commands.
4
3
 
5
4
  ## Installation
6
5
  To install Skyramp, simply run the following command in your terminal:
7
- ```bash
6
+ ```
8
7
  npm install skyramp
9
8
  ```
10
9
 
11
10
  ## Usage
12
11
  Once you've installed Skyramp, you can import it into your project like this:
13
12
 
14
- ```bash
15
- const { GrpcEndpoint, RestEndpoint, SkyrampClient, Scenario } = require('skyramp');
16
- ```
17
-
18
- ### SkyrampClient
19
- The `SkyrampClient` class is the main entry point to interact with the skyramp module. It allows you to apply configurations, start test scenarios, and deploy and delete workers. First, you must set up the `SkyrampClient` with a kubernetes cluster.
20
-
21
- **Example: Provision Local Cluster with Skyramp**
22
- ```bash
23
- const skyrampClient = new SkyrampClient();
24
- skyrampClient.applyLocal().then(function() {
25
- // Local cluster provisioned
26
- }).catch(function(error) {
27
- // Error occurred during provisioning
28
- });
29
- ```
30
- Once you have a `SkyrampClient` instance configured with a kubernetes cluster, you can deploy the Skyramp Worker in-cluster, for applying mocks and running tests.
31
- **Example: Deploy Skyramp Worker**
32
- ```bash
33
- skyrampClient.deployWorker('my-namespace').then(function() {
34
- // Worker deployed successfully
35
- }).catch(function(error) {
36
- // Error occurred during deployment
37
- });
38
- ```
39
-
40
- ### RestEndpoint
41
- The `RestEndpoint` class represents a REST API endpoint and provides methods to configure mock responses to apply them to the `SkyrampClient`.
42
-
43
- **Example: Create REST Mock Configuration**
44
- ```bash
45
- restEndpoint = new RestEndpoint('artists', 'artists-GET', 50050, 'api/openapi/artists.yaml');
46
- restEndpoint.mockMethodFromFile('artists-GET', 'files/rest-values.yaml');
47
- skyrampClient.mockerApply('my-namespace', restEndpoint).then(function() {
48
- // Mock applied successfully
49
- }).catch(function(error) {
50
- // Error occurred during mock application
51
- });
52
13
  ```
53
-
54
- ### GrpcEndpoint
55
- The `GrpcEndpoint` class represents a gRPC API endpoint and provides methods to configure mock responses to apply them to the `SkyrampClient`.
56
-
57
- **Example: Create gRPC Mock Configuration**
58
- ```bash
59
- grpcEndpoint = new GrpcEndpoint('routeguide', 'RouteGuide', 50051, 'api/pb/routeguide.proto');
60
- grpcEndpoint.mockMethodFromFile('GetFeature', 'files/grpc-response.yaml');
61
- skyrampClient.mockerApply('my-namespace', grpcEndpoint).then(function() {
62
- // Mock applied successfully
63
- }).catch(function(error) {
64
- // Error occurred during mock application
65
- });
66
- ```
67
-
68
- ### Scenario
69
- The `Scenario` class allows you to define test scenarios by specifying a series of API requests and assertions to be made. Once a `Scenario` is created, you can start it using the `SkyrampClient` instance.
70
-
71
- **Example: Test Assert Scenario (REST)**
72
- ```bash
73
- scenario = new Scenario('rest-test')
74
- step1 = scenario.addRequest(restEndpoint, 'artists-GET');
75
- step2 = scenario.addAssertEqual(`${step1}.res.items[0].artist_name`, 'abc');
76
- skyrampClient.testerStart('test-worker', scenario).then(function() {
77
- // Test scenario started
78
- }).catch(function(error) {
79
- // Error occurred during the test scenario
80
- });
14
+ const skyramp = require('skyramp');
81
15
  ```
82
16
 
83
- **Example: Test Assert Scenario (gRPC)**
84
- ```bash
85
- scenario = new Scenario('routeguide-assert-test')
86
- step1 = scenario.addRequestFromFile(grpcEndpoint, 'GetFeature', 'files/grpc-request.yaml');
87
- step2 = scenario.addAssertEqual(`${step1}.res.name`, 'test-feature');
88
- skyrampClient.testerStart('test-worker', scenario).then(function() {
89
- // Test scenario started
90
- }).catch(function(error) {
91
- // Error occurred during the test scenario
92
- });
93
- ```
17
+ Skyramp currently exports the following six functions:
18
+ - `runConfigApplyLocal`: create a new local test cluster
19
+ - `runAddKubeconfig`: specify kubeconfig for a pre-provisioned workload cluster
20
+ - `runConfigRemoveLocal`: remove a local test cluster
21
+ - `runConfigRemove`: remove a test cluster
22
+ - `runMockerCreate`: generate Mocker configurations
23
+ - `runMockerDeploy`: update Mocker configurations and source schema files
24
+ - `runTesterStart`: starts a skyramp test specified in the test description file
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@skyramp/skyramp",
3
- "version": "0.4.31",
3
+ "version": "1.0.0-sha.b2dfe11",
4
4
  "description": "module for leveraging skyramp cli functionality",
5
5
  "scripts": {
6
- "pack": "npm pack"
6
+ "pack": "npm pack",
7
+ "publish-npm": "npm publish --access private --ignore-scripts --@skyramp:skyramp='https://registry.npmjs.org'"
7
8
  },
8
9
  "files": [
9
10
  "lib/**",
@@ -14,10 +15,10 @@
14
15
  ],
15
16
  "main": "src/index.js",
16
17
  "author": "",
17
- "license": "MIT",
18
+ "license": "ISC",
18
19
  "dependencies": {
19
20
  "fs": "^0.0.1-security",
20
21
  "js-yaml": "^4.1.0",
21
- "koffi": "^2.5.3"
22
+ "koffi": "^2.3.20"
22
23
  }
23
24
  }
@@ -1,6 +1,6 @@
1
1
  export declare class Endpoint {
2
2
  constructor(endpointData: string);
3
- mockMethod(methodName: string, mockObject: string, dynamic?: boolean): void;
3
+ mockMethod(methodName: string, mockData: string, dynamic?: boolean): void;
4
4
  mockMethodFromFile(methodName: string, fileName: string): void;
5
5
  writeMockConfigurationToFile(kubernetesService: string): Promise<void>;
6
6
  }
@@ -1,6 +1,7 @@
1
1
  const lib = require('../lib');
2
- const { getYamlBytes, readDataFromFile } = require('../utils');
2
+ const yaml = require('js-yaml');
3
3
  const writeMockDescriptionWrapper = lib.func('writeMockDescriptionWrapper', 'string', ['string', 'string']);
4
+ const { readDataFromFile } = require('../utils');
4
5
 
5
6
  class Endpoint {
6
7
  constructor(endpointData) {
@@ -22,7 +23,7 @@ class Endpoint {
22
23
  }
23
24
  }
24
25
 
25
- mockMethod(methodName, mockObject, dynamic=false) {
26
+ mockMethod(methodName, mockData, dynamic=false) {
26
27
  for (const method of this.endpoint.methods) {
27
28
  if (method.name === methodName || method.type === methodName) {
28
29
  const responseName = method.responseValue;
@@ -30,10 +31,10 @@ class Endpoint {
30
31
  for (const responseValue of this.responseValues) {
31
32
  if (responseValue.name === responseName) {
32
33
  if (dynamic) {
33
- responseValue.javascriptPath = mockObject;
34
+ responseValue.javascriptPath = mockData;
34
35
  delete responseValue.blob;
35
36
  } else {
36
- responseValue.blob = mockObject.responseValue.blob;
37
+ responseValue.blob = mockData;
37
38
  delete responseValue.javascriptPath;
38
39
  }
39
40
  return;
@@ -45,23 +46,27 @@ class Endpoint {
45
46
  }
46
47
 
47
48
  mockMethodFromFile(methodName, fileName) {
48
- const [jsonData, dynamic] = readDataFromFile(fileName);
49
- return this.mockMethod(methodName, jsonData, dynamic);
49
+ const [jsonString, dynamic] = readDataFromFile(fileName);
50
+ return this.mockMethod(methodName, jsonString, dynamic);
50
51
  }
51
52
 
52
53
  writeMockConfigurationToFile(kubernetesService) {
53
- const yamlContent = getYamlBytes(this.mockDescription);
54
- return new Promise((resolve, reject) => {
55
- writeMockDescriptionWrapper.async(yamlContent, kubernetesService, (err, res) => {
56
- if (err) {
57
- reject(err);
58
- } else if (res) {
59
- reject(new Error(res));
60
- } else {
61
- resolve();
62
- }
54
+ try {
55
+ const yamlContent = yaml.dump(this.mockDescription);
56
+ return new Promise((resolve, reject) => {
57
+ writeMockDescriptionWrapper.async(yamlContent, kubernetesService, (err, res) => {
58
+ if (err) {
59
+ reject(err);
60
+ } else if (res) {
61
+ reject(new Error(res));
62
+ } else {
63
+ resolve();
64
+ }
65
+ });
63
66
  });
64
- });
67
+ } catch (error) {
68
+ throw new Error('Error converting to YAML bytes:', error);
69
+ }
65
70
  }
66
71
  }
67
72
 
@@ -1,17 +1,10 @@
1
1
  import { Endpoint } from './Endpoint';
2
- import { Scenario } from './Scenario';
3
2
  export declare class SkyrampClient {
4
- constructor(kubeconfigPath?: string, clusterName?: string, context?: string);
3
+ constructor(kubeconfigPath?: string, clusterName?: string, context?: string, ingress?: string);
5
4
  applyLocal(): Promise<void>;
6
5
  addKubeconfig(context: string, clusterName: string, kubeconfigPath: string): Promise<void>;
7
6
  removeCluster(clusterName?: string): Promise<void>;
8
7
  removeLocal(): Promise<void>;
9
8
  removeClusterFromConfig(clusterName: string): Promise<void>;
10
- mockerApply(namespace: string, address: string, endpoint: Endpoint): Promise<void>;
11
-
12
- mockerApplyFromFile(namespace: string, address: string, filePath: string): Promise<void>;
13
- applyMockDescription(namespace: string, address: string, mockYamlContent: string): Promise<void>;
14
- testerStart(namespace: string, address: string, scenario: Scenario): Promise<void>;
15
- testerStartFromFile(namespace: string, address: string, filePath: string): Promise<void>;
16
- runTesterStart(namespace: string, address: string, testYamlContent: string, generateReport: boolean): Promise<void>;
9
+ apply(namespace: string, endpoint: Endpoint): Promise<void>;
17
10
  }
@@ -1,5 +1,6 @@
1
1
  const lib = require('../lib');
2
- const { createTestDescriptionFromScenario, getYamlBytes, readDataFromFile } = require('../utils');
2
+ const yaml = require('js-yaml');
3
+
3
4
  const applyLocalWrapper = lib.func('applyLocalWrapper', 'string', []);
4
5
  const addKubeconfigWrapper = lib.func('addKubeconfigWrapper', 'string', ['string', 'bool', 'string', 'string']);
5
6
  const deleteSkyrampWorkerWrapper = lib.func('deleteSkyrampWorkerWrapper', 'string', ['string'])
@@ -7,14 +8,14 @@ const deploySkyrampWorkerWrapper = lib.func('deploySkyrampWorkerWrapper', 'strin
7
8
  const getKubeConfigPath = lib.func('getKubeConfigPath', 'string', []);
8
9
  const removeLocalWrapper = lib.func('removeLocalWrapper', 'string', []);
9
10
  const removeClusterFromConfigWrapper = lib.func('removeClusterFromConfigWrapper', 'string', ['string']);
10
- const runTesterStartWrapper = lib.func('runTesterStartWrapper', 'string', ['string', 'string', 'string', 'bool']);
11
- const applyMockDescriptionWrapper = lib.func('applyMockDescriptionWrapper', 'string', ['string', 'string', 'string']);
11
+ const applyMockDescriptionWrapper = lib.func('applyMockDescriptionWrapper', 'string', ['string', 'string']);
12
12
 
13
13
  class SkyrampClient {
14
- constructor(kubeconfigPath, clusterName, context) {
14
+ constructor(kubeconfigPath, clusterName, context, ingress) {
15
15
  this.workerNamespaces = [];
16
- if (kubeconfigPath || clusterName || context) {
17
- this.addKubeconfig(clusterName, context, kubeconfigPath);
16
+ this.mockedEndpoints = [];
17
+ if (kubeconfigPath || clusterName || context || ingress) {
18
+ this.addKubeconfig(clusterName, context, ingress, kubeconfigPath);
18
19
  }
19
20
  }
20
21
 
@@ -128,73 +129,25 @@ class SkyrampClient {
128
129
  });
129
130
  }
130
131
 
131
- async mockerApply(namespace, address, endpoint) {
132
- try {
133
- const yamlContent = getYamlBytes(endpoint.mockDescription);
134
- await this.applyMockDescription(namespace, address, yamlContent);
135
- } catch (err) {
136
- throw err;
137
- }
138
- }
139
-
140
- // NPM only: for VS code extension use
141
- async mockerApplyFromFile(namespace, address, filepath) {
132
+ async apply(namespace, endpoint) {
142
133
  try {
143
- const yamlContent = getYamlBytes(readDataFromFile(filepath)[0]);
144
- await this.applyMockDescription(namespace, address, yamlContent);
145
- } catch (err) {
146
- throw err;
147
- }
148
- }
149
-
150
- async applyMockDescription(namespace, address, yamlContent) {
151
- return new Promise((resolve, reject) => {
152
- applyMockDescriptionWrapper.async(namespace, address, yamlContent, (err, res) => {
153
- if (err) {
154
- reject(err);
155
- } else if (res) {
156
- reject(new Error(res));
157
- } else {
158
- resolve();
159
- }
134
+ const yamlContent = yaml.dump(endpoint.mockDescription);
135
+ return new Promise((resolve, reject) => {
136
+ applyMockDescriptionWrapper.async(namespace, yamlContent, (err, res) => {
137
+ if (err) {
138
+ reject(err);
139
+ } else if (res) {
140
+ reject(new Error(res));
141
+ } else {
142
+ resolve();
143
+ this.mockedEndpoints.push(endpoint);
144
+ }
145
+ });
160
146
  });
161
- });
162
- }
163
-
164
- async testerStart(namespace, address, scenario) {
165
- try {
166
- const testDescription = createTestDescriptionFromScenario(scenario);
167
- const testYamlContent = getYamlBytes(testDescription);
168
- await this.runTesterStart(namespace, address, testYamlContent, false);
169
- } catch (err) {
170
- throw err;
171
- }
172
- }
173
-
174
- // NPM only: for VS code extension use
175
- async testerStartFromFile(namespace, address, filepath) {
176
- try {
177
- const testDescription = readDataFromFile(filepath)[0]
178
- const testYamlContent = getYamlBytes(testDescription);
179
- await this.runTesterStart(namespace, address, testYamlContent, true);
180
147
  } catch (err) {
181
- throw err;
148
+ throw new Error('Error converting to YAML bytes:', err);
182
149
  }
183
150
  }
184
-
185
- async runTesterStart(namespace, address, testYamlContent, generateReport) {
186
- return new Promise((resolve, reject) => {
187
- runTesterStartWrapper.async(namespace, address, testYamlContent, generateReport, (err, res) => {
188
- if (err) {
189
- reject(err);
190
- } else if (res) {
191
- reject(new Error(res));
192
- } else {
193
- resolve();
194
- }
195
- });
196
- });
197
- }
198
151
  }
199
152
 
200
153
  module.exports = SkyrampClient;
package/src/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export * from './classes/Endpoint';
2
2
  export * from './classes/GrpcEndpoint';
3
3
  export * from './classes/RestEndpoint';
4
- export * from './classes/Scenario';
5
4
  export * from './classes/SkyrampClient';
6
5
  export * from './utils';
package/src/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  const SkyrampClient = require('./classes/SkyrampClient');
2
2
  const GrpcEndpoint = require('./classes/GrpcEndpoint');
3
3
  const RestEndpoint = require('./classes/RestEndpoint');
4
- const Scenario = require('./classes/Scenario');
4
+ const { runTesterStart } = require('./utils');
5
5
 
6
6
  module.exports = {
7
7
  SkyrampClient,
8
8
  GrpcEndpoint,
9
9
  RestEndpoint,
10
- Scenario
10
+ runTesterStart
11
11
  }
package/src/utils.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ declare function runTesterStart(namespace: string, testDescription: string): Promise<void>;
2
+
3
+ export {
4
+ runTesterStart
5
+ };
package/src/utils.js CHANGED
@@ -1,33 +1,22 @@
1
1
  const fs = require('fs');
2
+ const lib = require('./lib');
2
3
  const path = require('path');
3
4
  const yaml = require('js-yaml');
4
5
 
5
- function getYamlBytes(jsonObject) {
6
- try {
7
- const yamlContent = yaml.dump(jsonObject, {lineWidth: 100});
8
- return yamlContent;
9
- } catch (error) {
10
- throw new Error('Error converting to YAML bytes:', error);
11
- }
12
- }
6
+ runTesterStartWrapper = lib.func('runTesterStartWrapper', 'string', ['string', 'string']);
13
7
 
14
- function createTestDescriptionFromScenario(scenario) {
15
- return {
16
- test: {
17
- name: scenario.name,
18
- testPattern: [{
19
- startAt: 1,
20
- scenario: scenario.name
21
- }]
22
- },
23
- services: scenario.services,
24
- endpoints: scenario.endpoints,
25
- scenarios: [{
26
- name: scenario.name,
27
- steps: scenario.steps
28
- }],
29
- requests: scenario.requests
30
- };
8
+ async function runTesterStart(namespace, testDescription) {
9
+ return new Promise((resolve, reject) => {
10
+ runTesterStartWrapper.async(namespace, testDescription, (err, res) => {
11
+ if (err) {
12
+ reject(err);
13
+ } else if (res) {
14
+ reject(new Error(res));
15
+ } else {
16
+ resolve();
17
+ }
18
+ });
19
+ });
31
20
  }
32
21
 
33
22
  function readDataFromFile(filename) {
@@ -45,14 +34,14 @@ function readDataFromFile(filename) {
45
34
  } else {
46
35
  throw new Error('Unsupported file format. Only .json, .yaml, and .js files are supported.');
47
36
  }
48
- return [jsonData, false];
37
+ const jsonString = JSON.stringify(jsonData, null, 2)
38
+ return [jsonString, false];
49
39
  } catch(error) {
50
40
  throw new Error('Error reading or parsing file: ', error);
51
41
  }
52
42
  }
53
43
 
54
44
  module.exports = {
55
- createTestDescriptionFromScenario,
56
- getYamlBytes,
45
+ runTesterStart,
57
46
  readDataFromFile
58
47
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 Skyramp
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,8 +0,0 @@
1
- export declare class Scenario {
2
- constructor(name: string);
3
- addRequest(endpoint: any, methodName: string, requestObject?: string, dynamic?: boolean): string;
4
- addRequestFromFile(endpoint: any, methodName: string, requestFile: string): string;
5
- buildRequestsFromEndpoint(endpoint: any): void;
6
- addAssertEqual(value1: string, value2: string): string;
7
- writeTestConfigurationToFile(): Promise<void>;
8
- }
@@ -1,80 +0,0 @@
1
- const lib = require('../lib');
2
- const { createTestDescriptionFromScenario, getYamlBytes, readDataFromFile } = require('../utils');
3
- const buildRequestsWrapper = lib.func('buildRequestsWrapper', 'string', ['string']);
4
- const writeTestDescriptionWrapper = lib.func('writeTestDescriptionWrapper', 'string', ['string', 'string']);
5
-
6
- class Scenario {
7
- constructor(name) {
8
- this.name = name;
9
- this.steps = [];
10
- this.services = [];
11
- this.endpoints = [];
12
- this.requests = [];
13
- }
14
-
15
- addRequest(endpoint, methodName, requestObject=undefined, dynamic=false) {
16
- this.buildRequestsFromEndpoint(endpoint);
17
- for (const request of this.requests) {
18
- if (request.method === methodName) {
19
- if (dynamic) {
20
- request.requestValue.javascriptPath = requestObject;
21
- delete request.requestValue.blob;
22
- } else if (requestObject !== undefined) {
23
- request.requestValue = requestObject.requestValue;
24
- }
25
- this.steps.push({ request: request.name });
26
- return request.name;
27
- }
28
- }
29
- throw new Error(`Method ${methodName} not found`);
30
- }
31
-
32
- addRequestFromFile(endpoint, methodName, requestFile) {
33
- const [jsonData, dynamic] = readDataFromFile(requestFile);
34
- return this.addRequest(endpoint, methodName, jsonData, dynamic);
35
- }
36
-
37
- buildRequestsFromEndpoint(endpoint) {
38
- if (this.endpoints.indexOf(endpoint.endpoint) !== -1) {
39
- return;
40
- }
41
- const processedMethods = endpoint.endpoint.methods.map(method => {
42
- const { responseValue, proxy, ...rest } = method;
43
- return rest;
44
- });
45
- this.services.push(...endpoint.services);
46
- this.endpoints.push({ ...endpoint.endpoint, methods: processedMethods });
47
- const yamlContent = getYamlBytes(endpoint.mockDescription);
48
- const response = buildRequestsWrapper(yamlContent);
49
- try {
50
- const requests = JSON.parse(response);
51
- this.requests.push(requests[0]);
52
- } catch (error) {
53
- throw new Error(response);
54
- }
55
- }
56
-
57
- addAssertEqual(value1, value2) {
58
- const assertion = `requests.${value1} == "${value2}"`;
59
- this.steps.push({ asserts: assertion });
60
- return assertion;
61
- }
62
-
63
- writeTestConfigurationToFile() {
64
- const testDescription = createTestDescriptionFromScenario(this);
65
- const yamlContent = getYamlBytes(testDescription);
66
- return new Promise((resolve, reject) => {
67
- writeTestDescriptionWrapper.async(yamlContent, this.name, (err, res) => {
68
- if (err) {
69
- reject(err);
70
- } else if (res) {
71
- reject(new Error(res));
72
- } else {
73
- resolve();
74
- }
75
- });
76
- });
77
- }
78
- }
79
-
80
- module.exports = Scenario;