fix release for graphite

This commit is contained in:
Jonathan Shook 2020-09-22 12:04:50 -05:00
parent 75d6450341
commit b144849c77
7 changed files with 539 additions and 2 deletions

View File

@ -1,2 +1 @@
- a35042b3 updated docsys nuxt resources
- 1a7dfcf8 updated guidebook static content
- 75d64503 (HEAD -> main, origin/main) Fix for graphite reporter regression

View File

@ -0,0 +1,258 @@
<template>
<v-container>
<v-row>
Workload details
</v-row>
<v-row>
<v-text-field
outlined
label="Workload name"
v-model="workloadName"
></v-text-field>
</v-row>
<v-row>
<v-textarea
outlined
label="Create Table Statement"
v-model="createTableDef"
v-on:blur="parseStatement()"
></v-textarea>
</v-row>
<v-row>
<v-btn :title="save_title" v-if="parseSuccess" v-on:click="saveWorkloadToWorkspace()">{{
save_button
}}
</v-btn>
<v-btn :title="dl_title" v-if="parseSuccess" v-on:click="downloadWorkload()">{{ dl_button }}</v-btn>
<v-btn :title="example1" v-if="!parseSuccess" v-on:click="loadExample1()">Load example1.cql</v-btn>
</v-row>
</v-container>
<!-- <v-col cols="12">-->
<!-- </v-col>-->
<!-- </v-card>-->
</template>
<script>
import antlr4 from "antlr4";
import {saveAs} from "file-saver";
import yamlDumper from "js-yaml";
import CQL3Parser from '@/antlr/CQL3Parser.js';
import CQL3Lexer from '@/antlr/CQL3Lexer.js';
import defaultYaml from 'assets/default.yaml';
import basictypes from 'assets/basictypes.yaml';
export default {
data(context) {
let data = {
createTableDef: "",
workloadName: "",
parseSuccess: false,
blob: null,
};
return data;
},
computed: {
save_button: function () {
return "Save to workspace '" + this.$store.getters["workspaces/getWorkspace"] + "'";
},
dl_button: function () {
return "Download as " + this.filename;
},
dl_title: function () {
return "Click to download the workload as '" + this.filename + "'";
},
filename: function () {
return this.workloadName + ".yaml";
},
save_title: function () {
return "Click to save this workload in the '" + this.workspace + "' workspace, or change the workspace in the app bar first.\n"
},
},
methods: {
loadExample1() {
this.$data.createTableDef="create table a.b (\n a text,\n b text,\n primary key(a,b))\n";
this.$data.workloadName="example1";
this.parseStatement();
},
async parseStatement() {
console.log(this.$data.createTableDef);
const input = this.$data.createTableDef;
const chars = new antlr4.InputStream(input);
const lexer = new CQL3Lexer.CQL3Lexer(chars);
lexer.strictMode = false; // do not use js strictMode
const tokens = new antlr4.CommonTokenStream(lexer);
const parser = new CQL3Parser.CQL3Parser(tokens);
const context = parser.create_table_stmt();
try {
const keyspaceName = context.table_name().keyspace_name().getChild(0).getText()
const tableName = context.table_name().table_name_noks().getChild(0).getText()
const columnDefinitions = context.column_definitions().column_definition();
let columns = [];
let partitionKeys = [];
let clusteringKeys = [];
columnDefinitions.forEach(columnDef => {
if (columnDef.column_name() != null) {
columns.push({
"name": columnDef.column_name().getText(),
"type": columnDef.column_type().getText()
})
} else {
const primaryKeyContext = columnDef.primary_key()
if (primaryKeyContext.partition_key() != null) {
const partitionKeysContext = primaryKeyContext.partition_key().column_name();
partitionKeysContext.map((partitionKey, i) => {
const partitionKeyName = partitionKey.getText()
const col = {
"name": partitionKeyName,
"type": columns.filter(x => x.name == partitionKeyName)[0].type
}
partitionKeys.push(col)
})
}
if (primaryKeyContext.clustering_column().length != 0) {
const clusteringKeysContext = primaryKeyContext.clustering_column();
clusteringKeysContext.map((clusteringKey, i) => {
const clusteringKeyName = clusteringKey.getText()
const col = {
"name": clusteringKeyName,
"type": columns.filter(x => x.name == clusteringKeyName)[0].type
}
clusteringKeys.push(col)
})
}
}
})
columns = columns.filter(col => {
return partitionKeys.filter(pk => pk.name == col.name).length == 0 && clusteringKeys.filter(cc => cc.name == col.name).length == 0
})
const allColumns = [].concat(columns, partitionKeys, clusteringKeys)
this.$data.tableName = tableName;
this.$data.keyspaceName = keyspaceName;
this.$data.columns = columns;
this.$data.clusteringKeys = clusteringKeys;
this.$data.partitionKeys = partitionKeys;
this.$data.allColumns = allColumns;
console.log(this.$data)
console.log(defaultYaml)
// schema and bindings
let createTableStatement = "CREATE TABLE IF NOT EXISTS <<keyspace:" + keyspaceName + ">>." + tableName + " (\n";
console.log(basictypes)
defaultYaml.bindings = {}
allColumns.forEach(column => {
let recipe = basictypes.bindings[column.type + "val"];
if (recipe == undefined) {
const chars = new antlr4.InputStream(column.type);
const lexer = new CQL3Lexer.CQL3Lexer(chars);
lexer.strictMode = false; // do not use js strictMode
const tokens = new antlr4.CommonTokenStream(lexer);
const parser = new CQL3Parser.CQL3Parser(tokens);
const typeContext = parser.column_type();
const collectionTypeContext = typeContext.data_type().collection_type();
const collectionType = collectionTypeContext.children[0].getText();
if (collectionType.toLowerCase() == "set") {
const type = collectionTypeContext.children[2].getText();
recipe = "Set(HashRange(1,<<set-count-" + column.name + ":5>>)," + basictypes.bindings[type + "val"] + ") -> java.util.Set"
} else if (collectionType.toLowerCase() == "list") {
const type = collectionTypeContext.children[2].getText();
recipe = "List(HashRange(1,<<list-count-" + column.name + ":5>>)," + basictypes.bindings[type + "val"] + ") -> java.util.List"
} else if (collectionType.toLowerCase() == "map") {
const type1 = collectionTypeContext.children[2].getText();
const type2 = collectionTypeContext.children[4].getText();
recipe = "Map(HashRange(1,<<map-count-" + column.name + ":5>>)," + basictypes.bindings[type1 + "val"] + "," + basictypes.bindings[type2 + "val"] + ") -> java.util.Map"
} else {
alert("Could not generate recipe for type: " + column.type + " for column: " + column.name)
}
}
defaultYaml.bindings[column.name] = recipe
createTableStatement = createTableStatement + column.name + " " + column.type + ",\n";
})
let pk = "PRIMARY KEY (("
pk = pk + partitionKeys.map(x => x.name).reduce((x, acc) => acc = acc + "," + x)
pk = pk + ")"
if (clusteringKeys.length > 0) {
pk = pk + "," + clusteringKeys.map(x => x.name).reduce((x, acc) => acc = acc + "," + x)
}
pk = pk + ")"
createTableStatement = createTableStatement + pk + "\n);"
defaultYaml.blocks[0].statements[0] = {"create-table": createTableStatement}
//rampup
let insertStatement = "INSERT INTO <<keyspace:" + keyspaceName + ">>." + tableName + " (\n";
insertStatement = insertStatement + allColumns.map(x => x.name).reduce((x, acc) => acc = acc + ",\n" + x) + "\n) VALUES (\n";
insertStatement = insertStatement + allColumns.map(x => "{" + x.name + "}").reduce((x, acc) => acc = acc + ",\n" + x) + "\n);"
defaultYaml.blocks[1].statements[0] = {"insert-rampup": insertStatement}
//main-write
defaultYaml.blocks[2].statements[0] = {"insert-main": insertStatement}
//main-read-partition
let readPartitionStatement = "SELECT * from <<keyspace:" + keyspaceName + ">>." + tableName + " WHERE ";
readPartitionStatement = readPartitionStatement + partitionKeys.map(x => x.name + "={" + x.name + "}").reduce((x, acc) => acc = acc + " AND " + x);
let readRowStatement = readPartitionStatement + ";";
if (clusteringKeys.length > 0) {
readPartitionStatement = readPartitionStatement + " AND " + clusteringKeys.map(x => x.name + "={" + x.name + "}").reduce((x, acc) => acc = acc + " AND " + x);
}
readPartitionStatement = readPartitionStatement + ";";
defaultYaml.blocks[3].statements[0] = {"read-partition": readPartitionStatement}
//main-read-row
defaultYaml.blocks[4].statements[0] = {"read-row": readRowStatement}
defaultYaml.description = this.$data.workloadName
const yamlOutputText = yamlDumper.dump(defaultYaml)
this.blob = new Blob([yamlOutputText], {type: "text/plain;charset=utf-8"});
this.parseSuccess = true;
} catch (e) {
console.log("blur, invalid create table def")
console.log(e)
}
},
downloadWorkload() {
saveAs(this.blob, this.$data.filename);
},
saveWorkloadToWorkspace() {
let workspace =this.$store.getters["workspaces/getWorkspace"];
this.$store.dispatch("workspaces/putFile", {
workspace: workspace,
filename: this.filename,
content: this.blob
})
}
},
created() {
this.$store.dispatch('service_status/loadEndpoints')
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,116 @@
<template>
<v-container>
<!-- OpenAPI Selection -->
<v-row>
<v-select
v-if="mode==='selecting'"
label="Use OpenAPI YAML"
v-model="yamloptions"
:items="yamlfiles_in_workspace"
>
<template v-slot:append-item>
<v-list-item>
<v-btn @click="mode='importing'">import</v-btn>
</v-list-item>
</template>
</v-select>
</v-row>
<div v-if="mode==='importing'">
<v-row>
<v-text-field
outlined
label="OpenAPI YAML URL"
@input="nameImport()"
v-model="import_url"></v-text-field>
</v-row>
<v-row v-if="import_as">
<v-text-field outlined
label="import as name"
v-model="import_as"></v-text-field>
</v-row>
<v-row>
<v-btn
@click="loadExample1()"
v-if="!this.import_url"
title="load https://gist.githubusercontent.com/jshook/529e1b3f80e6283459c55ae56255bbc5/raw/c0d2ac9853099b57ca6d2209661f332a3953ab02/stargate.yaml"
>Load stargate.yaml
</v-btn>
<v-btn
v-if="this.import_url && this.import_url.match('^http')"
@click="importToWorkspace()"
>Save to Workspace
</v-btn>
</v-row>
</div>
</v-container>
</template>
<script>
export default {
name: "openapi",
data() {
return {
openapifiles: [],
mode: 'selecting',
import_url: null,
yamloptions: null,
import_as: null,
example_url: "https://gist.githubusercontent.com/jshook/529e1b3f80e6283459c55ae56255bbc5/raw/c0d2ac9853099b57ca6d2209661f332a3953ab02/stargate.yaml"
}
},
computed: {
yamlfiles_in_workspace: {
get() {
let wsfiles = this.$store.getters["workspaces/getMatchingFiles"]
}
},
workspace: function () {
return this.$store.getters["workspaces/getWorkspace"]
}
},
methods: {
refreshOpenApiFiles() {
let wsfiles = this.$store.dispatch("workspaces/listWorkspaceFiles",
{
wsname: this.workspace,
contains: '^openapi: 3.*'
})
console.log("wsfiles:" + JSON.stringify(wsfiles,null,2))
// this.openapifiles=wsfiles.ls.map(f => f.name)
},
loadExample1() {
this.import_url = this.example_url
this.nameImport();
},
nameImport() {
let parts = this.import_url.split("/");
this.import_as = parts[parts.length - 1]
},
importToWorkspace() {
this.$store.dispatch("workspaces/importUrlToWorkspace",
{
workspace: this.workspace,
import_url: this.import_url,
import_as: this.import_as
}
)
this.refreshOpenApiFiles()
this.mode = 'selecting'
}
},
mounted() {
this.refreshOpenApiFiles()
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,128 @@
<template>
<v-app>
<main-app-bar></main-app-bar>
<!-- <workspace-selector @changed="seenChange(workspace)"></workspace-selector>-->
<!-- <v-btn title="start a new workspace" @click="startNewWorkspace()">-->
<!-- <v-icon>mdi-folder-plus-outline</v-icon>-->
<!-- </v-btn>-->
<!-- <v-btn icon title="upload a workspace zip file">-->
<!-- <v-icon>mdi-folder-upload</v-icon>-->
<!-- </v-btn>-->
<!-- <v-btn icon title="download workspaces.zip">-->
<!-- <v-icon>mdi-briefcase-download</v-icon>-->
<!-- </v-btn>-->
<!-- <v-btn icon title="upload workspaces.zip">-->
<!-- <v-icon>mdi-briefcase-upload</v-icon>-->
<!-- </v-btn>-->
<v-content justify-start align-start class="d-inline-block pa-4 ma-10">
<div class="row no-gutters">
<v-card min-width="300" max-width="300" max-height="400" raised elevation="5" v-for="(cardspace,w) in workspaces" :key="w"
class="pa-4 ma-4">
<v-row>
<v-card-title title="workspace name">{{ cardspace.name }}</v-card-title>
<v-icon v-if="workspace === cardspace.name">mdi-check-bold</v-icon>
</v-row>
<v-card-subtitle title="last change">{{ abbrev(cardspace.summary.last_changed_filename) }}</v-card-subtitle>
<v-divider></v-divider>
<v-list align-start>
<v-simple-table>
<tbody>
<tr>
<td>Bytes</td>
<td>{{ cardspace.summary.total_bytes }}</td>
</tr>
<tr>
<td>Files</td>
<td>{{ cardspace.summary.total_files }}</td>
</tr>
</tbody>
</v-simple-table>
<v-divider></v-divider>
<v-list-item>
<v-btn title="view details of workspace">
<v-icon>mdi-magnify</v-icon>
</v-btn>
<v-spacer></v-spacer>
<v-btn title="download zipped workspace">
<v-icon>mdi-folder-download</v-icon>
</v-btn>
<v-spacer></v-spacer>
<v-btn title="purge workspace">
<v-icon @click="purgeWorkspace(cardspace.name)">mdi-trash-can</v-icon>
</v-btn>
</v-list-item>
</v-list>
</v-card>
</div>
</v-content>
</v-app>
</template>
<script>
import WorkspaceSelector from "@/components/WorkspaceSelector";
import {mapActions, mapGetters, mapMutations} from "vuex";
import AppSelector from "@/components/AppSelector";
import MainAppBar from "@/components/MainAppBar";
export default {
name: "workspaces.vue",
components: {
MainAppBar,
AppSelector,
WorkspaceSelector
},
data(context) {
let data = {};
return data;
},
computed: {
workspace: {
get() {
return this.$store.getters["workspaces/getWorkspace"]
},
set(val) {
this.$store.dispatch("workspaces/setWorkspace", val)
}
},
workspaces: {
get() {
return this.$store.getters["workspaces/getWorkspaces"]
},
set(val) {
this.$store.dispatch("workspaces/setWorkspaces", val)
}
},
},
methods: {
abbrev(name) {
return name;
},
purgeWorkspace: function (ws) {
// console.log("purging " + ws);
this.$store.dispatch('workspaces/purgeWorkspace', ws);
// this.$store.dispatch("workspaces/setWorkspace")
this.$forceUpdate();
},
},
created() {
this.$store.dispatch('workspaces/initWorkspaces', "workspace panel load");
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,36 @@
import endpoints from "@/js/endpoints";
export const state = () => ({
pathops: []
});
export const getters = {
getPathOps: (state, getters) => {
return state.pathops;
}
}
export const mutations = {
setPathOps: (state,pathops) => {
state.pathops=pathops
}
}
export const actions = {
async loadPaths(context, opts) {
let reason = opts.reason;
let workspace = opts.workspace;
let filepath = (opts.filepath ? opts.filepath : "stargate.yaml")
if (!reason || !workspace || !filepath) {
throw "reason, workspace, filepath are all required in opts: " + JSON.stringify(opts,null,2);
}
await this.$axios.$get(endpoints.url(document, context, "/services/openapi/paths?filepath=" + filepath))
.then(res => {
context.commit('setPathOps', res)
})
.catch((e) => {
console.error("axios/nuxt scenarios async error:", e);
})
},
}