Skip to content

Commit

Permalink
feat: Update to latest Openshift Rest Client (#293)
Browse files Browse the repository at this point in the history
BREAKING CHANGE:  Slight Refactor

* Updating the Openshift Rest Client to 2.1.0, which has a new API

* Removing strictSSL and tryServiceAccount flags since the updated openshift rest client doesn't need them.

* Removes the openshift config loader, which is no longer used
  • Loading branch information
lholmquist committed Apr 5, 2019
1 parent eaf0046 commit e73db9c
Show file tree
Hide file tree
Showing 40 changed files with 2,755 additions and 2,204 deletions.
12 changes: 0 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,9 @@ Outputs the current version of nodeshift
#### projectLocation
Changes the default location of where to look for your project. Defaults to your current working directory(CWD)

#### strictSSL
This option is passed through to the [Openshift Rest Client](https://www.npmjs.com/package/openshift-rest-client) for SSL use. To allow using a self-signed cert, set to false

#### configLocation
This option is passed through to the [Openshift Config Loader](https://www.npmjs.com/package/openshift-config-loader). Defaults to the `~/.kube/config`

#### tryServiceAccount
This option is passed through to the [Openshift Config Loader](https://www.npmjs.com/package/openshift-config-loader). Set to false to by-pass service account lookup or use the KUBERNETES_AUTH_TRYSERVICEACCOUNT environment variable

#### imageTag
Specify the tag of the docker image to use for the deployed application. defaults to latest. These version tags corespond to the docker hub tags of the [nodeshift s2i images](https://hub.docker.com/r/nodeshift/centos7-s2i-nodejs/tags/)

Expand Down Expand Up @@ -203,12 +197,6 @@ Shows the below help
Options:
--version Show version number [boolean]
--projectLocation change the default location of the project [string]
--strictSSL setting to pass to the Openshift Rest Client. Set to
false if using a self-sign cert
--tryServiceAccount setting to pass to the Openshift Config Loader.
Set to false to by-pass service account lookup
or use the KUBERNETES_AUTH_TRYSERVICEACCOUNT
environment variable
--imageTag The tag of the docker image to use for the deployed
application. [string] [default: "latest"]
--quiet supress INFO and TRACE lines from output logs
Expand Down
10 changes: 0 additions & 10 deletions bin/nodeshift
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,10 @@ yargs
describe: 'change the default location of the project',
type: 'string'
})
.options('strictSSL', {
describe: 'setting to pass to the Openshift Rest Client. Set to false if using a self-sign cert'
})
.option('configLocation', {
describe: 'change the default location of the config',
type: 'string'
})
.options('tryServiceAccount', {
describe: `setting to pass to the Openshift Config Loader. Set to false to by-pass service account lookup
or use the KUBERNETES_AUTH_TRYSERVICEACCOUNT environment variable
`
})
.options('dockerImage', {
describe: 'the s2i image to use, defaults to nodeshift/centos7-s2i-nodejs',
type: 'string'
Expand Down Expand Up @@ -163,8 +155,6 @@ function createOptions (argv) {
options.removeAll = argv.removeAll;
options.namespace = argv.namespace;
options.expose = argv.expose;
options.strictSSL = argv.strictSSL !== 'false';
options.tryServiceAccount = argv.tryServiceAccount !== 'false';
options.configLocation = argv.configLocation;

// Check for the --build.env array
Expand Down
10 changes: 0 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ const cli = require('./bin/cli');
@param {object} [options] -
@param {string} [options.projectLocation] - the location(directory) of your projects package.json. Defaults to `process.cwd`
@param {boolean} [options.strictSSL] - Set to false to allow self-signed Certs
@param {boolean} [options.tryServiceAccount] - Set to false to by-pass service account lookup
@param {boolean} [options.expose] - Set to true to create a default Route and expose the default service. defaults to false
@param {object} [options.namespace] -
@param {string} [options.namespace.displayName] - flag to specify the project namespace display name to build/deploy into. Overwrites any namespace settings in your OpenShift or Kubernetes configuration files
Expand Down Expand Up @@ -44,8 +42,6 @@ function deploy (options = {}) {
@param {object} [options] -
@param {string} [options.projectLocation] - the location(directory) of your projects package.json. Defaults to `process.cwd`
@param {boolean} [options.strictSSL] - Set to false to allow self-signed Certs
@param {boolean} [options.tryServiceAccount] - Set to false to by-pass service account lookup
@param {boolean} [options.expose] - Set to true to create a default Route and expose the default service. defaults to false
@param {object} [options.namespace] -
@param {string} [options.namespace.displayName] - flag to specify the project namespace display name to build/deploy into. Overwrites any namespace settings in your OpenShift or Kubernetes configuration files
Expand All @@ -68,8 +64,6 @@ function resource (options = {}) {
@param {object} [options] -
@param {string} [options.projectLocation] - the location(directory) of your projects package.json. Defaults to `process.cwd`
@param {boolean} [options.strictSSL] - Set to false to allow self-signed Certs
@param {boolean} [options.tryServiceAccount] - Set to false to by-pass service account lookup
@param {boolean} [options.expose] - Set to true to create a default Route and expose the default service. defaults to false
@param {object} [options.namespace] -
@param {string} [options.namespace.displayName] - flag to specify the project namespace display name to build/deploy into. Overwrites any namespace settings in your OpenShift or Kubernetes configuration files
Expand All @@ -96,8 +90,6 @@ function applyResource (options = {}) {
@param {object} [options] -
@param {string} [options.projectLocation] - the location(directory) of your projects package.json. Defaults to `process.cwd`
@param {boolean} [options.strictSSL] - Set to false to allow self-signed Certs
@param {boolean} [options.tryServiceAccount] - Set to false to by-pass service account lookup
@param {object} [options.namespace] -
@param {string} [options.namespace.displayName] - flag to specify the project namespace display name to build/deploy into. Overwrites any namespace settings in your OpenShift or Kubernetes configuration files
@param {boolean} [options.namespace.remove] - flag to remove the user created namespace. Only applicable for the undeploy command. Must be used with namespace.name
Expand All @@ -124,8 +116,6 @@ function undeploy (options = {}) {
@param {object} [options] -
@param {string} [options.projectLocation] - the location(directory) of your projects package.json. Defaults to `process.cwd`
@param {boolean} [options.strictSSL] - Set to false to allow self-signed Certs
@param {boolean} [options.tryServiceAccount] - Set to false to by-pass service account lookup
@param {object} [options.namespace] -
@param {string} [options.namespace.displayName] - flag to specify the project namespace display name to build/deploy into. Overwrites any namespace settings in your OpenShift or Kubernetes configuration files
@param {boolean} [options.namespace.create] - flag to create the namespace if it does not exist. Only applicable for the build and deploy command. Must be used with namespace.name
Expand Down
22 changes: 13 additions & 9 deletions lib/binary-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@
const watchBuildLog = require('./build-watcher');
const logger = require('./common-log')();
const { wait } = require('./helpers');
const fs = require('fs');

module.exports = async (config, archiveLocation) => {
// Upload the .tar file
logger.info(`uploading binary archive ${archiveLocation}`);
const response = await config.openshiftRestClient
.buildconfigs
.instantiateBinary(config.buildName, { dockerArchive: archiveLocation });
// const response = await dorequest(config, archiveLocation);
const binaryResponse = await config.openshiftRestClient.apis.build.v1.ns(config.namespace.name).buildconfigs(config.buildName).instantiatebinary.post({ body: fs.createReadStream(archiveLocation), json: false });
const response = JSON.parse(binaryResponse.body);
// const response = await config.openshiftRestClient
// .buildconfigs
// .instantiateBinary(config.buildName, { dockerArchive: archiveLocation });
logger.info('binary upload complete');

// Trigger watch of build
Expand All @@ -42,16 +46,16 @@ module.exports = async (config, archiveLocation) => {
const timeout = (i + 1) * 200;
await wait(timeout);

const buildStatus = await config.openshiftRestClient.builds.find(response.metadata.name);
if (buildStatus.status.phase === 'Complete') {
logger.info(`build ${buildStatus.metadata.name} complete`);
const buildStatus = await config.openshiftRestClient.apis.build.v1.ns(config.namespace.name).builds(response.metadata.name).get();
if (buildStatus.body.status.phase === 'Complete') {
logger.info(`build ${buildStatus.body.metadata.name} complete`);
await buildLogWatcher;
return buildStatus;
}

if (buildStatus.status.phase === 'Failed') {
logger.error('build failed with message:', buildStatus.status.message);
throw new Error(buildStatus.status.message);
if (buildStatus.body.status.phase === 'Failed') {
logger.error('build failed with message:', buildStatus.body.status.message);
throw new Error(buildStatus.body.status.message);
}
}
};
26 changes: 13 additions & 13 deletions lib/build-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,15 @@

'use strict';

// https://docs.openshift.com/online/rest_api/openshift_v1.html#v1-buildconfig

const objectMetadata = require('./definitions/object-metadata');
const buildConfigSpec = require('./definitions/build-config-spec');
const buildConfigStatus = require('./definitions/build-config-status');
const logger = require('./common-log')();
const { awaitRequest } = require('./helpers');

const baseBuildConfig = {
apiVersion: 'v1', // Not Required
kind: 'BuildConfig' // Not Required
'kind': 'BuildConfig',
'apiVersion': 'build.openshift.io/v1'
};

function createBuildConfig (config, options) {
Expand All @@ -36,7 +35,7 @@ function createBuildConfig (config, options) {
// Add new metadata
buildConfig.metadata = objectMetadata({
name: config.buildName,
namespace: config.context.namespace,
namespace: config.namespace.name,
labels: {
project: config.projectName,
version: config.projectVersion
Expand All @@ -58,8 +57,7 @@ async function removeBuildsAndBuildConfig (config) {
logger.info(`Deleteing build configuration ${buildName}`);
// First get the list of builds with the labelselector
// https://URL/oapi/v1/namespaces/NAMESPACE/builds?labelSelector=openshift.io/build-config.name=BUILD_NAME
const buildList = await config.openshiftRestClient.builds.findAll({ qs: { labelSelector: `openshift.io/build-config.name=${buildName}` } });

const buildList = await config.openshiftRestClient.apis.build.v1.ns(config.namespace.name).builds.get({ qs: { labelSelector: `openshift.io/build-config.name=${buildName}` } });
// Some default remove Body Options for the rest client, maybe at some point, these will be exposed to the user
const removeOptions = {
body: {
Expand All @@ -69,20 +67,22 @@ async function removeBuildsAndBuildConfig (config) {
};

// Delete the builds that it finds
for (const items of buildList.items) {
for (const items of buildList.body.items) {
logger.info(`Deleteing build ${items.metadata.name}`);
await config.openshiftRestClient.builds.remove(items.metadata.name, removeOptions);
await awaitRequest(config.openshiftRestClient.apis.build.v1.ns(config.namespace.name).builds(items.metadata.name).delete({ body: removeOptions }));
}
// delete build config
return config.openshiftRestClient.buildconfigs.remove(buildName, removeOptions);
return awaitRequest(config.openshiftRestClient.apis.build.v1.ns(config.namespace.name).buildconfigs(buildName).delete({ body: removeOptions }));
}

async function createOrUpdateBuildConfig (config) {
// Check for a BuildConfig, create or update if necessary
const buildName = config.buildName;
const imageStreamName = config.projectName;
const outputImageStreamTag = `${imageStreamName}:latest`; // TODO: base on a tag
const buildConfig = await config.openshiftRestClient.buildconfigs.find(buildName);
// The new code under the openshift rest client, returns an error when getting a 404, so we need to catch it and check the status code
// I wonder if it is better to find all buildConfigs, then do a Array.find on the returned item list
const buildConfig = await awaitRequest(config.openshiftRestClient.apis.build.v1.ns(config.namespace.name).buildconfigs(buildName).get());

config.build = config.build || {};

Expand All @@ -97,7 +97,7 @@ async function createOrUpdateBuildConfig (config) {
dockerImage: config.dockerImage,
buildEnv: config.build.env
});
return config.openshiftRestClient.buildconfigs.create(newBuildConfig);
return config.openshiftRestClient.apis.build.v1.ns(config.namespace.name).buildconfigs.post({ body: newBuildConfig });
}

// There is a buildConfig, check our "recreate" option if we need to delete and re-create
Expand All @@ -114,7 +114,7 @@ async function createOrUpdateBuildConfig (config) {
dockerImage: config.dockerImage,
buildEnv: config.build.env
});
return config.openshiftRestClient.buildconfigs.create(newBuildConfig);
return config.openshiftRestClient.apis.build.v1.ns(config.namespace.name).buildconfigs.post({ body: newBuildConfig });
}

logger.info(`using existing build configuration ${buildName}`);
Expand Down
46 changes: 15 additions & 31 deletions lib/build-watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,19 @@

'use strict';

const request = require('request');
const logger = require('./common-log')();
const { wait } = require('./helpers');
// https://192.168.99.100:8443/api/v1/namespaces/node-demo-1/pods/wfswarm-rest-http-s2i-5-build/log?pretty=false&follow=true';

function podLogEndpoint (config, build) {
return new Promise((resolve, reject) => {
const req = {
url: `${config.openshiftRestClient.kubeUrl}/namespaces/${config.context.namespace}/pods/${build}-build/log`,
auth: {
bearer: config.user.token
},
strictSSL: config.strictSSL
};

request(req, (err, resp, body) => {
if (err) return reject(err);
async function podLogEndpoint (config, build) {
let response;
try {
response = await config.openshiftRestClient.api.v1.ns(config.namespace.name).pods(`${build}-build`).log.get();
} catch (err) {
response = err;
}

return resolve(resp);
});
});
return response;
}

async function pingEndpoint (config, build) {
Expand All @@ -61,21 +53,13 @@ module.exports = async function watchBuildLog (config, build) {
await pingEndpoint(config, build);
// Then do the follow endpoint

return new Promise((resolve, reject) => {
const req = {
url: `${config.openshiftRestClient.kubeUrl}/namespaces/${config.context.namespace}/pods/${build}-build/log?pretty=false&follow=true`,
auth: {
bearer: config.user.token
},
strictSSL: config.strictSSL
};
const response = config.openshiftRestClient.api.v1.ns(config.namespace.name).pods(`${build}-build`).log.getStream({ qs: { follow: true, pretty: false } });

request.get(req).on('data', (chunk) => {
logger.trace(chunk.toString('utf8').trim());
}).on('end', () => {
return resolve();
}).on('error', (err) => {
return reject(err);
});
response.on('data', (chunk) => {
logger.trace(chunk.toString('utf8').trim());
}).on('end', () => {
return Promise.resolve();
}).on('error', (err) => {
return Promise.reject(err);
});
};
7 changes: 4 additions & 3 deletions lib/config-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@
'use strict';

const log = require('./common-log')();
const { awaitRequest } = require('./helpers');

module.exports = async function getConfigMap (config, configMapResource) {
// First check to see if we already have a route created
let configMap = await config.openshiftRestClient.configmaps.find(configMapResource.metadata.name);
let configMap = await awaitRequest(config.openshiftRestClient.api.v1.ns(config.namespace.name).configmaps(configMapResource.metadata.name).get());
if (configMap.code === 404) {
// There isn't a configMap yet, so we need to create one
log.info(`creating new configMap ${configMapResource.metadata.name}`);
configMap = await config.openshiftRestClient.configmaps.create(configMapResource);
configMap = await awaitRequest(config.openshiftRestClient.api.v1.ns(config.namespace.name).configmaps.post({ body: configMapResource }));
} else {
log.info(`using existing configMap ${configMap.metadata.name}`);
log.info(`using existing configMap ${configMap.body.metadata.name}`);
}
return configMap;
};
2 changes: 1 addition & 1 deletion lib/definitions/deployment-config-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ module.exports = (resource, config) => {
containerNames: [config.projectName],
from: {
kind: 'ImageStreamTag',
namespace: config.context.namespace,
namespace: config.namespace.name,
name: `${config.projectName}:latest`
}
}
Expand Down
18 changes: 9 additions & 9 deletions lib/deployment-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,18 @@

// https://docs.openshift.com/online/rest_api/openshift_v1.html#v1-deploymentconfig
const logger = require('./common-log')();
const { awaitRequest } = require('./helpers');

async function deploy (config, deploymentConfigResource) {
// First check to see if we already have a deployment config created
const deployment = await config.openshiftRestClient.deploymentconfigs.find(deploymentConfigResource.metadata.name);
const deployment = await awaitRequest(config.openshiftRestClient.apis['apps.openshift.io'].v1.ns(config.namespace.name).deploymentconfigs(deploymentConfigResource.metadata.name).get());
// If no deploymentconfig, create one
if (deployment.code === 404) {
logger.info(`creating deployment configuration ${deploymentConfigResource.metadata.name}`);
return config.openshiftRestClient.deploymentconfigs.create(deploymentConfigResource);
return config.openshiftRestClient.apis['apps.openshift.io'].v1.ns(config.namespace.name).deploymentconfigs.post({ body: deploymentConfigResource });
}

logger.info(`using existing deployment configuration ${deployment.metadata.name}`);
logger.info(`using existing deployment configuration ${deployment.body.metadata.name}`);
return deployment;
}

Expand All @@ -50,22 +51,21 @@ async function undeploy (config, deploymentConfigResource) {

// then delete the deploymentconfig
logger.info(`Deleteing Deployment Config ${deploymentConfigResource.metadata.name}`);
response.deploymentConfig = await config.openshiftRestClient.deploymentconfigs.remove(deploymentConfigResource.metadata.name, removeOptionsDeploymentConfig);
response.deploymentConfig = await awaitRequest(config.openshiftRestClient.apis['apps.openshift.io'].v1.ns(config.namespace.name).deploymentconfigs(deploymentConfigResource.metadata.name).delete({ body: removeOptionsDeploymentConfig }));
// Get the list of replication controllers
const rcList = await config.openshiftRestClient.replicationcontrollers.findAll({ qs: { labelSelector: `openshift.io/deployment-config.name=${config.projectName}` } });

const rcList = await config.openshiftRestClient.api.v1.ns(config.namespace.name).replicationcontrollers.get({ qs: { labelSelector: `openshift.io/deployment-config.name=${config.projectName}` } });
const removeOptionsReplicationControllers = {
body: {
orphanDependents: false,
gracePeriodSeconds: undefined
}
};
// Delete the builds that it finds
for (const items of rcList.items) {
for (const items of rcList.body.items) {
logger.info(`Deleteing replication controller ${items.metadata.name}`);
response.replicationControllers.push(
await config.openshiftRestClient.replicationcontrollers.remove(
items.metadata.name, removeOptionsReplicationControllers));
await awaitRequest(config.openshiftRestClient.api.v1.ns(config.namespace.name).replicationcontrollers(items.metadata.name).delete({ body: removeOptionsReplicationControllers }))
);
}
return response;
}
Expand Down

0 comments on commit e73db9c

Please sign in to comment.