Browse Source

Added Neutron Service

This neutron service follows the same pattern as the glance service,
and provides both version negotiation and endpoint discovery.

Change-Id: Ia2f59213eedf6d7acbb02789ee921c13ff391d09
Corentin Ardeois 2 years ago
parent
commit
b033ad652e
6 changed files with 260 additions and 1 deletions
  1. 2
    1
      configure-devstack.js
  2. 1
    0
      src/index.js
  3. 56
    0
      src/neutron.js
  4. 83
    0
      test/functional/neutronTest.js
  5. 64
    0
      test/unit/helpers/data/neutron.js
  6. 54
    0
      test/unit/neutronTest.js

+ 2
- 1
configure-devstack.js View File

@@ -7,7 +7,8 @@ function getDevstackConfig() {
7 7
   const karmaConfig = karma.parseConfig(path.resolve('./karma.conf.js'));
8 8
 
9 9
   return getCorsConfig('$KEYSTONE_CONF', karmaConfig) +
10
-    getCorsConfig('$GLANCE_API_CONF', karmaConfig);
10
+    getCorsConfig('$GLANCE_API_CONF', karmaConfig) +
11
+    getCorsConfig('$NEUTRON_CONF', karmaConfig);
11 12
 
12 13
 }
13 14
 

+ 1
- 0
src/index.js View File

@@ -1,2 +1,3 @@
1 1
 export {default as Keystone} from './keystone';
2 2
 export {default as Glance} from './glance';
3
+export {default as Neutron} from './neutron';

+ 56
- 0
src/neutron.js View File

@@ -0,0 +1,56 @@
1
+/*
2
+ * Copyright (c) 2016 Internap.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
+ * use this file except in compliance with the License. You may obtain a copy
6
+ * of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
13
+ * the License for the specific language governing permissions and limitations
14
+ * under the License.
15
+ */
16
+import AbstractService from './util/abstractService';
17
+
18
+/**
19
+ * A list of all supported versions. Please keep this array sorted by most recent.
20
+ *
21
+ * @type {Array}
22
+ * @ignore
23
+ */
24
+const supportedNeutronVersions = [
25
+  'v2.0'
26
+];
27
+
28
+export default class Neutron extends AbstractService {
29
+
30
+  /**
31
+   * This class provides direct, idempotent, low-level access to the Neutron API of a specific
32
+   * cloud. The constructor requires that you provide a specific neutron interface endpoint
33
+   * descriptor, as received from keystone's catalog list.
34
+   *
35
+   * @example
36
+   * {
37
+   *   region_id: "RegionOne",
38
+   *   url: "http://127.0.0.1:9696",
39
+   *   region: "RegionOne",
40
+   *   interface: "admin",
41
+   *   id: "4f08823e667345478b6e40fab8373c0f"
42
+   * }
43
+   * @param {{}} endpointConfig The configuration element for a specific glance endpoint.
44
+   */
45
+  constructor(endpointConfig) {
46
+    // Sanity checks.
47
+    if (!endpointConfig || !endpointConfig.url) {
48
+      throw new Error('An endpoint configuration is required.');
49
+    }
50
+    // Clone the config, so that this instance is immutable
51
+    // at runtime (no modifying the config after the fact).
52
+    endpointConfig = Object.assign({}, endpointConfig);
53
+
54
+    super(endpointConfig.url, supportedNeutronVersions);
55
+  }
56
+}

+ 83
- 0
test/functional/neutronTest.js View File

@@ -0,0 +1,83 @@
1
+/*
2
+ * Copyright (c) 2016 Internap.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
+ * use this file except in compliance with the License. You may obtain a copy
6
+ * of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
13
+ * the License for the specific language governing permissions and limitations
14
+ * under the License.
15
+ */
16
+
17
+import config from "./helpers/cloudsConfig";
18
+import Version from '../../src/util/version';
19
+import Neutron from "../../src/neutron";
20
+import Keystone from "../../src/keystone";
21
+import log from 'loglevel';
22
+
23
+log.setLevel("DEBUG");
24
+
25
+describe("neutron", () => {
26
+  // Create a keystone instance and extract the neutron API endpoint.
27
+  let devstackConfig = config.clouds.devstack;
28
+  let keystone = new Keystone(devstackConfig);
29
+  let tokenPromise = keystone.tokenIssue();
30
+
31
+  let configPromise = tokenPromise
32
+    .then((token) => keystone.catalogList(token))
33
+    .then((catalog) => catalog.find((entry) => entry.name === 'neutron'))
34
+    .then((entry) => entry.endpoints.find((endpoint) => endpoint.interface === 'public'));
35
+
36
+  describe("versions()", () => {
37
+    it("should return a list of all versions available on this clouds' neutron", (done) => {
38
+      configPromise
39
+        .then((config) => new Neutron(config))
40
+        .then((neutron) => neutron.versions())
41
+        .then((versions) => {
42
+          // Quick sanity check.
43
+          expect(versions.length > 0).toBeTruthy();
44
+          done();
45
+        })
46
+        .catch((error) => done.fail(error));
47
+    });
48
+  });
49
+
50
+  describe("version()", () => {
51
+
52
+    const supportedApiVersions = [
53
+      new Version('network 2.0')
54
+    ];
55
+
56
+    /**
57
+     * This test acts as a canary, to inform the SDK developers that the Neutron API
58
+     * has changed in a significant way.
59
+     */
60
+    it("should return a supported version.", (done) => {
61
+      configPromise
62
+        .then((config) => new Neutron(config))
63
+        .then((neutron) => neutron.version())
64
+        .then((version) => {
65
+
66
+          // Quick sanity check.
67
+          const apiVersion = new Version('network', version.id);
68
+
69
+          for (let i = 0; i < supportedApiVersions.length; i++) {
70
+            let supportedVersion = supportedApiVersions[i];
71
+            if (apiVersion.equals(supportedVersion)) {
72
+              done();
73
+              return;
74
+            }
75
+          }
76
+          fail("Current devstack neutron version is not supported.");
77
+          done();
78
+        })
79
+        .catch((error) => done.fail(error));
80
+    });
81
+  });
82
+
83
+});

+ 64
- 0
test/unit/helpers/data/neutron.js View File

@@ -0,0 +1,64 @@
1
+/*
2
+ * Copyright (c) 2016 Internap.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
+ * use this file except in compliance with the License. You may obtain a copy
6
+ * of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
13
+ * the License for the specific language governing permissions and limitations
14
+ * under the License.
15
+ */
16
+
17
+/**
18
+ * This file contains test data for fetchMock, to simplify bootstrapping of unit tests for
19
+ * neutron. Most of these are functions, as FetchMock does not perform a safe clone of the
20
+ * instances, and may accidentally modify them at runtime.
21
+ */
22
+
23
+/**
24
+ * Mock cloud configuration that matches our test data below. This is not a clouds.yaml
25
+ * format but a subsection of service endpoint return by keystone's catalog.
26
+ */
27
+const neutronConfig = {
28
+  region_id: "RegionOne",
29
+  url: "http://192.168.99.99:9696/",
30
+  region: "RegionOne",
31
+  interface: "public",
32
+  id: "0b8b5f0f14904136ab5a4f83f27ec49a"
33
+};
34
+
35
+/**
36
+ * Build a new FetchMock configuration for the root endpoint.
37
+ *
38
+ * @returns {{}} A full FetchMock configuration for Neutron's Root Resource.
39
+ */
40
+function rootResponse() {
41
+  return {
42
+    method: 'GET',
43
+    matcher: 'http://192.168.99.99:9696/',
44
+    response: {
45
+      versions: [
46
+        {
47
+          status: 'CURRENT',
48
+          id: 'v2.0',
49
+          links: [
50
+            {
51
+              href: 'http://192.168.99.99:9696/v2.0',
52
+              rel: 'self'
53
+            }
54
+          ]
55
+        }
56
+      ]
57
+    }
58
+  };
59
+}
60
+
61
+export {
62
+  neutronConfig as config,
63
+  rootResponse as root
64
+};

+ 54
- 0
test/unit/neutronTest.js View File

@@ -0,0 +1,54 @@
1
+/*
2
+ * Copyright (c) 2016 Internap.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
+ * use this file except in compliance with the License. You may obtain a copy
6
+ * of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
13
+ * the License for the specific language governing permissions and limitations
14
+ * under the License.
15
+ */
16
+
17
+import Neutron from '../../src/neutron.js';
18
+import * as mockData from './helpers/data/neutron';
19
+import fetchMock from 'fetch-mock';
20
+
21
+describe('neutron', () => {
22
+
23
+  afterEach(fetchMock.restore);
24
+
25
+  it('should export a class', () => {
26
+    const neutron = new Neutron(mockData.config);
27
+    expect(neutron).toBeDefined();
28
+  });
29
+
30
+  it('should throw an error for an empty config', () => {
31
+    try {
32
+      const neutron = new Neutron();
33
+      neutron.versions();
34
+    } catch (e) {
35
+      expect(e.message).toEqual('An endpoint configuration is required.');
36
+    }
37
+  });
38
+
39
+  describe("versions()", () => {
40
+    it("Should return a list of all versions available on this clouds' NEUTRON", (done) => {
41
+      const neutron = new Neutron(mockData.config);
42
+
43
+      fetchMock.mock(mockData.root());
44
+
45
+      neutron.versions()
46
+        .then((versions) => {
47
+          // Quick sanity check.
48
+          expect(versions.length).toBe(1);
49
+          done();
50
+        })
51
+        .catch((error) => done.fail(error));
52
+    });
53
+  });
54
+});

Loading…
Cancel
Save