-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from nteract/run-minio-on-circleci
set up minio on circle
- Loading branch information
Showing
13 changed files
with
394 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
const path = require("path"); | ||
const fs = require("fs"); | ||
|
||
const _ = require("lodash"); | ||
|
||
const s3 = require("./s3"); | ||
const { JupyterServer } = require("./jupyter"); | ||
|
||
const { sleep } = require("./sleep"); | ||
|
||
// Catch all rogue promise rejections to fail CI | ||
process.on("unhandledRejection", error => { | ||
console.log("unhandledRejection", error.message); | ||
console.error(error.stack); | ||
process.exit(2); | ||
}); | ||
|
||
console.log("running bookstore integration tests"); | ||
|
||
const main = async () => { | ||
const bucketName = "bookstore"; | ||
|
||
const jupyterServer = new JupyterServer(); | ||
await jupyterServer.start(); | ||
|
||
const s3Config = { | ||
endPoint: "127.0.0.1", | ||
port: 9000, | ||
useSSL: false, | ||
accessKey: "ONLY_ON_CIRCLE", | ||
secretKey: "CAN_WE_DO_THIS" | ||
}; | ||
|
||
// Instantiate the minio client with the endpoint | ||
// and access keys as shown below. | ||
var s3Client = new s3.Client(s3Config); | ||
|
||
await s3Client.makeBucket(bucketName); | ||
|
||
console.log(`Created bucket ${bucketName}`); | ||
|
||
const originalNotebook = { | ||
cells: [ | ||
{ | ||
cell_type: "code", | ||
execution_count: null, | ||
metadata: {}, | ||
outputs: [], | ||
source: ["import this"] | ||
} | ||
], | ||
metadata: { | ||
kernelspec: { | ||
display_name: "Python 3", | ||
language: "python", | ||
name: "python3" | ||
}, | ||
language_info: { | ||
codemirror_mode: { | ||
name: "ipython", | ||
version: 3 | ||
}, | ||
file_extension: ".py", | ||
mimetype: "text/x-python", | ||
name: "python", | ||
nbconvert_exporter: "python", | ||
pygments_lexer: "ipython3", | ||
version: "3.7.0" | ||
} | ||
}, | ||
nbformat: 4, | ||
nbformat_minor: 2 | ||
}; | ||
|
||
jupyterServer.writeNotebook("ci-local-writeout.ipynb", originalNotebook); | ||
|
||
// Wait for minio to have the notebook | ||
// Future iterations of this script should poll to get the notebook | ||
await sleep(1000); | ||
|
||
jupyterServer.shutdown(); | ||
|
||
/***** Check notebook from S3 *****/ | ||
const rawNotebook = await s3Client.getObject( | ||
bucketName, | ||
"ci-workspace/ci-local-writeout.ipynb" | ||
); | ||
|
||
const notebook = JSON.parse(rawNotebook); | ||
|
||
if (!_.isEqual(notebook, originalNotebook)) { | ||
console.error("original"); | ||
console.error(originalNotebook); | ||
console.error("from s3"); | ||
console.error(notebook); | ||
throw new Error("Notebook on S3 does not match what we sent"); | ||
} | ||
|
||
console.log("Notebook on S3 matches what we sent"); | ||
|
||
/***** Check notebook from Disk *****/ | ||
const diskNotebook = await new Promise((resolve, reject) => | ||
fs.readFile( | ||
path.join(__dirname, "ci-local-writeout.ipynb"), | ||
(err, data) => { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
resolve(JSON.parse(data)); | ||
} | ||
} | ||
) | ||
); | ||
|
||
if (!_.isEqual(diskNotebook, originalNotebook)) { | ||
console.error("original"); | ||
console.error(originalNotebook); | ||
console.error("from disk"); | ||
console.error(diskNotebook); | ||
throw new Error("Notebook on Disk does not match what we sent"); | ||
} | ||
|
||
console.log("📚 Bookstore Integration Complete 📚"); | ||
}; | ||
|
||
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
const child_process = require("child_process"); | ||
const { genToken } = require("./token"); | ||
const { sleep } = require("./sleep"); | ||
|
||
// "Polyfill" XMLHttpRequest for rxjs' ajax to use | ||
global.XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; | ||
const { ajax } = require("rxjs/ajax"); | ||
|
||
class JupyterServer { | ||
constructor(config = {}) { | ||
this.port = config.port || 9988; | ||
this.ip = config.ip || "127.0.0.1"; | ||
this.scheme = config.scheme || "http"; | ||
this.token = null; | ||
|
||
// Launch the server from the directory of this script by default | ||
this.cwd = config.cwd || __dirname; | ||
|
||
this.process = null; | ||
this.up = false; | ||
} | ||
|
||
async start() { | ||
if (!this.token) { | ||
this.token = await genToken(); | ||
} | ||
|
||
this.process = child_process.spawn( | ||
"jupyter", | ||
[ | ||
"notebook", | ||
"--no-browser", | ||
`--NotebookApp.token=${this.token}`, | ||
`--NotebookApp.disable_check_xsrf=True`, | ||
`--port=${this.port}`, | ||
`--ip=${this.ip}` | ||
], | ||
{ cwd: this.cwd } | ||
); | ||
|
||
////// Refactor me later, streams are a bit messy with async await | ||
////// Let's use spawn-rx in the future and make some clean rxjs with timeouts | ||
this.process.stdout.on("data", data => { | ||
const s = data.toString(); | ||
console.log(s); | ||
}); | ||
this.process.stderr.on("data", data => { | ||
const s = data.toString(); | ||
|
||
console.error(s); | ||
if (s.includes("Jupyter Notebook is running at")) { | ||
this.up = true; | ||
} | ||
}); | ||
this.process.stdout.on("end", data => | ||
console.log("jupyter server terminated") | ||
); | ||
|
||
await sleep(3000); | ||
|
||
if (!this.up) { | ||
console.log("jupyter has not come up after 3 seconds, waiting 3 more"); | ||
await sleep(3000); | ||
|
||
if (!this.up) { | ||
throw new Error("jupyter has not come up after 6 seconds, bailing"); | ||
} | ||
} | ||
} | ||
|
||
async writeNotebook(path, notebook) { | ||
// Once https://github.com/nteract/nteract/pull/3651 is merged, we can use | ||
// rx-jupyter for writing a notebook to the contents API | ||
const xhr = await ajax({ | ||
url: `${this.endpoint}/api/contents/${path}`, | ||
responseType: "json", | ||
createXHR: () => new XMLHttpRequest(), | ||
method: "PUT", | ||
body: { | ||
type: "notebook", | ||
content: notebook | ||
}, | ||
headers: { | ||
"Content-Type": "application/json", | ||
Authorization: `token ${this.token}` | ||
} | ||
}).toPromise(); | ||
|
||
return xhr; | ||
} | ||
|
||
shutdown() { | ||
this.process.kill(); | ||
} | ||
|
||
get endpoint() { | ||
return `${this.scheme}://${this.ip}:${this.port}`; | ||
} | ||
} | ||
|
||
module.exports = { | ||
JupyterServer | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
from bookstore import BookstoreContentsArchiver, BookstoreSettings | ||
|
||
# jupyter config | ||
# At ~/.jupyter/jupyter_notebook_config.py for user installs | ||
# At __ for system installs | ||
c = get_config() | ||
|
||
c.NotebookApp.contents_manager_class = BookstoreContentsArchiver | ||
|
||
c.BookstoreSettings.workspace_prefix = "ci-workspace" | ||
|
||
# If using minio for development | ||
c.BookstoreSettings.s3_endpoint_url = "http://127.0.0.1:9000" | ||
c.BookstoreSettings.s3_bucket = "bookstore" | ||
|
||
# Straight out of `circleci/config.yml` | ||
c.BookstoreSettings.s3_access_key_id = "ONLY_ON_CIRCLE" | ||
c.BookstoreSettings.s3_secret_access_key = "CAN_WE_DO_THIS" |
Oops, something went wrong.