docker-graphql initial commit

This commit is contained in:
Sérgio Ramos 2017-04-27 22:47:32 +01:00
parent e48a42559f
commit 4e73cc4ea6
25 changed files with 4584 additions and 0 deletions

1
.gitignore vendored
View File

@ -150,6 +150,7 @@ $RECYCLE.BIN/
*.postcss.js
/cloudapi-graphql/credentials.json
/docker-graphql/config.json
tap-xunit
/ui/dist

27
docker-graphql/.eslintrc Normal file
View File

@ -0,0 +1,27 @@
{
"extends": [
"eslint:recommended",
"prettier"
],
"plugins": [
"prettier"
],
"rules": {
"no-console": 0,
"prettier/prettier": ["error", {
"useTabs": false,
"printWidth": 80,
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"parser": "flow",
"semi": true
}]
},
"env": {
"es6": true,
"node": true
}
}

50
docker-graphql/.gitignore vendored Normal file
View File

@ -0,0 +1,50 @@
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Vim files:
*.sw*
# Mac OS dirty files
.DS_Store

View File

@ -0,0 +1 @@
FROM quay.io/yldio/alpine-node-containerpilot:6.9.4-3

54
docker-graphql/Makefile Normal file
View File

@ -0,0 +1,54 @@
NAME := $(lastword $(subst /, ,$(CURDIR)))
bindir := $(shell yarn bin)
AVA := $(bindir)/ava
NYC := $(bindir)/nyc
.PHONY: install
install:
yarn install --prefer-offline
.PHONY: install-production
install-production:
yarn install --production --pure-lockfile --prefer-offline
.PHONY: clean
clean:
@rm -rf node_modules
.PHONY: test
test:
$(AVA) $(TEST_ARGS)
XUNIT_DIR := ${CIRCLE_TEST_REPORTS}/tap-xunit
XUNIT := $(bindir)/tap-xunit
XUNIT_OUTPUT := >> ${CIRCLE_TEST_REPORTS}/tap-xunit/xunit-$(NAME)
.PHONY: test-ci
test-ci:
mkdir -p $(XUNIT_DIR)
$(NYC) $(AVA) -t | $(XUNIT) $(XUNIT_OUTPUT).xml
.PHONY: start
start:
yarn run start
.PHONY: build
build:
docker build -t quay.io/yldio/joyent-dashboard-$(NAME):$(CIRCLE_BRANCH) .
.PHONY: push
push:
docker push quay.io/yldio/joyent-dashboard-$(NAME)
.PHONY: lint
lint:
$(bindir)/eslint .
.PHONY: lint-ci
lint-ci:
mkdir -p $(XUNIT_DIR)
-$(bindir)/eslint . --format tap | $(XUNIT) $(XUNIT_OUTPUT)-lint.xml
.PHONY: licence-check
licence-check:
../node_modules/.bin/license-to-fail ../licence.js

1
docker-graphql/README.md Normal file
View File

@ -0,0 +1 @@
WIP

View File

@ -0,0 +1,38 @@
{
"consul": "{{ .CONSUL }}:8500",
"services": [{
"name": "joyent-portal-docker-graphql",
"port": 5000,
"health": "/usr/bin/curl -o /dev/null --fail -s http://localhost:4000/graphql",
"poll": 3,
"ttl": 10
}],
"telemetry": {
"port": 9090,
"sensors": [{
"name": "graphql_memory_percent",
"help": "percentage of memory used",
"type": "gauge",
"poll": 5,
"check": ["/bin/sensors", "memory"]
}, {
"name": "graphql_cpu_load",
"help": "cpu load",
"type": "gauge",
"poll": 5,
"check": ["/bin/sensors", "cpu"]
}, {
"name": "graphql_disk_capacity",
"help": "disk capacity",
"type": "gauge",
"poll": 60,
"check": ["/bin/sensors", "diskcapacity"]
}, {
"name": "graphql_disk_usage",
"help": "disk usage",
"type": "gauge",
"poll": 60,
"check": ["/bin/sensors", "diskusage"]
}]
}
}

View File

@ -0,0 +1,30 @@
{
"name": "docker-graphql",
"private": true,
"license": "MPL-2.0",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"lint": "eslint src --fix",
"start": "node src/index.js",
"test": "make test"
},
"dependencies": {
"dockerode": "^2.4.3",
"dotenv": "^4.0.0",
"express": "^4.15.2",
"express-graphql": "^0.6.4",
"graphql": "^0.9.3",
"pascal-case": "^2.0.1",
"upper-case": "^1.1.3"
},
"devDependencies": {
"ava": "^0.19.1",
"eslint": "^3.19.0",
"eslint-config-prettier": "^1.7.0",
"eslint-plugin-prettier": "^2.0.1",
"nyc": "^10.2.0",
"prettier": "^1.2.2",
"tap-xunit": "^1.7.0"
}
}

View File

@ -0,0 +1,16 @@
const Docker = require('dockerode');
const url = require('url');
const path = require('path');
const fs = require('fs');
const config = require('../config');
const location = url.parse(config.host);
module.exports = new Docker({
host: location.hostname,
port: Number(location.port),
ca: fs.readFileSync(path.join(config.cert, 'ca.pem')),
cert: fs.readFileSync(path.join(config.cert, 'cert.pem')),
key: fs.readFileSync(path.join(config.cert, 'key.pem')),
version: 'v1.24'
});

View File

@ -0,0 +1,28 @@
const client = require('./client');
// https://docs.docker.com/engine/api/v1.24/#list-containers
module.exports.list = () => client.listContainers();
module.exports.create = () => null;
module.exports.inspect = () => null;
module.exports.ps = () => null;
module.exports.logs = () => null;
module.exports.stats = () => null;
module.exports.changes = () => null;
module.exports['export'] = () => null;
module.exports.resize = () => null;
module.exports.start = () => null;
module.exports.stop = () => null;
module.exports.restart = () => null;
module.exports.kill = () => null;
module.exports.update = () => null;
module.exports.rename = () => null;
module.exports.pause = () => null;
module.exports.unpause = () => null;
module.exports.attach = () => null;
module.exports.wait = () => null;
module.exports.remove = () => null;
module.exports.archive = () => null;
module.exports.pause = () => null;
module.exports.exec = () => null;
module.exports.pause = () => null;

View File

@ -0,0 +1,3 @@
module.exports = {
containers: require('./containers')
};

View File

@ -0,0 +1,47 @@
const json = (() => {
try {
const res = require('dotenv').config({
path: '../.env',
silent: true
});
if (res.error) {
throw res.error;
}
} catch (err) {
try {
return require('../config.json');
} catch (err) {
return {};
}
}
return {};
})();
module.exports = {
cert: (
process.env.DOCKER_CERT_PATH ||
json.DOCKER_CERT_PATH ||
json.cert ||
''
),
host: (
process.env.DOCKER_HOST ||
json.DOCKER_HOST ||
json.host ||
''
),
tls_verify: (
process.env.DOCKER_TLS_VERIFY ||
json.DOCKER_TLS_VERIFY ||
json.tls_verify ||
''
),
timeout: (
process.env.DOCKER_CLIENT_TIMEOUT ||
json.DOCKER_CLIENT_TIMEOUT ||
json.timeout ||
''
)
};

View File

@ -0,0 +1,8 @@
const graphqlHTTP = require('express-graphql');
const schema = require('./schema');
module.exports = graphqlHTTP(() => ({
schema: schema,
graphiql: true,
pretty: true
}));

View File

@ -0,0 +1,14 @@
const express = require('express');
const app = express();
app.use('/graphql', require('./endpoint'));
const server = app.listen(4010, err => {
if (err) {
console.error(err);
throw err;
}
console.log(`Listening at http://0.0.0.0:${server.address().port}/graphql`);
});

View File

@ -0,0 +1,9 @@
const graphql = require('graphql');
const mutation = require('./mutations');
const query = require('./queries');
const { GraphQLSchema } = graphql;
module.exports = new GraphQLSchema({
query
});

View File

@ -0,0 +1,17 @@
const { GraphQLObjectType } = require('graphql');
module.exports = new GraphQLObjectType({
name: 'RootMutationType',
fields: {}
// fields: Object.assign(
// // require('./account'),
// // require('./keys'),
// // require('./users'),
// // require('./roles'),
// // require('./policies'),
// // require('./machines'),
// // require('./images'),
// // require('./firewall-rules'),
// // require('./snapshots')
// )
});

View File

@ -0,0 +1,55 @@
const graphql = require('graphql');
const DynamicObjectType = require('../types/dynamic-object');
const ContainerType = require('../types/container');
const api = require('../../api');
const { GraphQLInt, GraphQLList, GraphQLString, GraphQLID, GraphQLBoolean } = graphql;
module.exports = {
type: new GraphQLList(ContainerType),
args: {
all: {
type: GraphQLBoolean,
description: 'Show all containers. Only running containers are shown by default (i.e., this defaults to false)',
resolve: root => !!root.all
},
limit: {
type: GraphQLInt,
description: 'Show `limit` last created containers, include non-running ones'
},
since: {
type: GraphQLID,
description: 'Show only containers created since `id`, include non-running ones'
},
before: {
type: GraphQLID,
description: 'Show only containers created before `id`, include non-running ones'
},
size: {
type: GraphQLBoolean,
description: 'Show the containers sizes'
},
filters: {
type: DynamicObjectType,
description: 'Filters to process on the containers list'
}
},
resolve(root, args) {
const { list, inspect } = api.containers;
return list(args);
//
// const { after, first } = args;
//
// const newArgs = Object.assign(args, {
// limit: first,
// offset: after
// });
//
// return args.id
// ? get({
// id: args.id
// }).then(machine => [machine])
// : list(newArgs);
}
};

View File

@ -0,0 +1,8 @@
const { GraphQLObjectType } = require('graphql');
module.exports = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
containers: require('./containers')
}
});

View File

@ -0,0 +1,49 @@
const DynamicObjectType = require('./dynamic-object');
const fromPascalCase = require('./from-pascal-case');
const PortType = require('./port');
const {
GraphQLString,
GraphQLObjectType,
GraphQLInt,
GraphQLList,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'ContainerType',
fields: {
id: {
type: GraphQLID,
resolve: fromPascalCase
},
created: {
type: GraphQLInt,
resolve: fromPascalCase
},
command: {
type: GraphQLString,
resolve: fromPascalCase
},
names: {
type: new GraphQLList(GraphQLString),
resolve: fromPascalCase
},
status: {
type: GraphQLString,
resolve: fromPascalCase
},
image: {
type: GraphQLString,
resolve: fromPascalCase
},
labels: {
type: DynamicObjectType,
resolve: fromPascalCase
},
ports: {
type: new GraphQLList(PortType),
resolve: fromPascalCase
}
}
});

View File

@ -0,0 +1,41 @@
const { GraphQLScalarType, Kind } = require('graphql');
const kinds = {
[Kind.STRING]: ast => {
return ast.value;
},
[Kind.BOOLEAN]: ast => {
return kinds[Kind.STRING](ast);
},
[Kind.INT]: ast => {
return Number(ast.value);
},
[Kind.FLOAT]: ast => {
return kinds[Kind.INT](ast);
},
[Kind.OBJECT]: ast => {
const value = Object.create(null);
ast.fields.forEach(field => {
value[field.name.value] = parseLiteral(field.value);
});
return value;
},
[Kind.LIST]: ast => {
return ast.values.map(parseLiteral);
}
};
// https://github.com/taion/graphql-type-json/blob/master/src/index.js
const parseLiteral = ast => {
const kind = kinds[ast.kind];
return kind ? kinds[ast.kind](ast) : null;
};
// from http://stackoverflow.com/a/34229603
module.exports = new GraphQLScalarType({
name: 'DynamicObjectType',
serialize: v => v,
parseValue: v => v,
parseLiteral: parseLiteral
});

View File

@ -0,0 +1,4 @@
const pascalCase = require('pascal-case');
const upperCase = require('upper-case');
module.exports = (root, ctx, req, { fieldName }) => root[pascalCase(fieldName)] || root[upperCase(fieldName)];

View File

@ -0,0 +1,25 @@
const { GraphQLString, GraphQLObjectType, GraphQLInt } = require('graphql');
const DynamicObjectType = require('./dynamic-object');
const fromPascalCase = require('./from-pascal-case');
module.exports = new GraphQLObjectType({
name: 'PortType',
fields: {
ip: {
type: GraphQLString,
resolve: fromPascalCase
},
privatePort: {
type: GraphQLInt,
resolve: fromPascalCase
},
publicPort: {
type: GraphQLInt,
resolve: fromPascalCase
},
type: {
type: GraphQLString,
resolve: fromPascalCase
}
}
});

View File

View File

@ -0,0 +1,7 @@
// TODO: REMOVE, JUST FOR AN EXAMPLE
const test = require('ava');
test('foo', t => {
t.pass();
});

4051
docker-graphql/yarn.lock Normal file

File diff suppressed because it is too large Load Diff