Last active
January 17, 2025 16:37
-
-
Save dylanmartin/72fe50b82c9a185b6cbf80775d669d80 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
const axios = require('axios'); | |
const gql = require('graphql-tag'); | |
const fs = require('fs') | |
const path = require('path'); | |
const apiUrl = "https://coinstac.rs.gsu.edu/api"; // Base API URL | |
// ----------------------------- | |
// Authentication | |
// ----------------------------- | |
/** | |
* Authenticate and retrieve a token. | |
*/ | |
async function getToken(username, password) { | |
try { | |
const response = await axios.post(`${apiUrl}/authenticate`, { username, password }); | |
return response.data.id_token; | |
} catch (error) { | |
console.error("Authentication failed:", error); | |
return null; | |
} | |
} | |
// ----------------------------- | |
// GraphQL Helper Functions | |
// ----------------------------- | |
/** | |
* Execute a GraphQL mutation. | |
*/ | |
async function callGraphQLMutation(mutation, variables = {}, token) { | |
try { | |
const response = await axios.post( | |
`${apiUrl}/graphql`, | |
{ query: mutation, variables }, | |
{ headers: { Authorization: `Bearer ${token}` } } | |
); | |
return response.data; | |
} catch (error) { | |
console.error("GraphQL mutation error:", error); | |
return null; | |
} | |
} | |
/** | |
* Execute a GraphQL query. | |
*/ | |
async function callGraphQLQuery(query, token) { | |
try { | |
const response = await axios.post( | |
`${apiUrl}/graphql`, | |
{ query: query }, | |
{ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` } } | |
); | |
if (response.data.errors) { | |
console.error("GraphQL query errors:", response.data.errors); | |
return null; | |
} | |
return response.data.data; | |
} catch (error) { | |
console.error("GraphQL query error:", error); | |
return null; | |
} | |
} | |
// ----------------------------- | |
// Queries and Mutations | |
// ----------------------------- | |
const generateHeadlessClientApiKeyMutation = ` | |
mutation($headlessClientId: ID!) { | |
generateHeadlessClientApiKey(headlessClientId: $headlessClientId) | |
} | |
`; | |
const fetchAllHeadlessClientsQuery = ` | |
query { | |
fetchAllHeadlessClients { | |
id | |
name | |
computationWhitelist | |
owners | |
hasApiKey | |
} | |
} | |
`; | |
const createHeadlessClientMutation = ` | |
mutation($data: HeadlessClientInput!) { | |
createHeadlessClient(data: $data) { | |
id | |
name | |
hasApiKey | |
} | |
} | |
`; | |
const deleteHeadlessClientMutation = ` | |
mutation($headlessClientId: ID!) { | |
deleteHeadlessClient(headlessClientId: $headlessClientId) { | |
id | |
name | |
} | |
} | |
`; | |
const updateHeadlessClientMutation = ` | |
mutation($headlessClientId: ID!, $data: HeadlessClientInput!) { | |
updateHeadlessClient(headlessClientId: $headlessClientId, data: $data) { | |
id | |
name | |
computationWhitelist | |
owners | |
hasApiKey | |
} | |
} | |
`; | |
// ----------------------------- | |
// Business Logic Functions | |
// ----------------------------- | |
/** | |
* Fetch all headless clients. | |
*/ | |
async function getHeadlessClients(token) { | |
const response = await callGraphQLQuery(fetchAllHeadlessClientsQuery, token); | |
return response ? response.fetchAllHeadlessClients : []; | |
} | |
/** | |
* Generate an API key for a headless client. | |
*/ | |
async function generateApiKey(token, clientId) { | |
const variables = { headlessClientId: clientId }; | |
const data = await callGraphQLMutation(generateHeadlessClientApiKeyMutation, variables, token); | |
return data?.data?.generateHeadlessClientApiKey || null; | |
} | |
/** | |
* Create headless client entities for multiple datasets. | |
*/ | |
async function getComputationWhitelistFromFile(datasetName) { | |
try { | |
const fileName = `${datasetName}.json`; | |
const filePath = path.join(__dirname, 'headlessClientEntityDocs', fileName); | |
// Check if the file exists | |
if (!fs.existsSync(filePath)) { | |
console.warn(`File not found for dataset: ${datasetName}`); | |
return null; | |
} | |
// Read and parse the file | |
const fileContent = await fs.promises.readFile(filePath, 'utf-8'); | |
const jsonData = JSON.parse(fileContent); | |
// Return the "computationWhitelist" key if it exists | |
if (jsonData.computationWhitelist) { | |
return jsonData.computationWhitelist; | |
} else { | |
console.warn(`"computationWhitelist" key not found in file: ${fileName}`); | |
return null; | |
} | |
} catch (error) { | |
console.error(`Error while retrieving computation whitelist for dataset: ${datasetName}`); | |
console.error(error.message); | |
console.error(error.stack); | |
return null; | |
} | |
} | |
async function createHeadlessClientEntities({ prefix, datasetNames, token }) { | |
return Promise.all(datasetNames.map(async datasetName => { | |
const computationWhitelist = await getComputationWhitelistFromFile(datasetName); | |
const newClientName = `${prefix}-${datasetName}`; | |
const variables = { | |
data: { | |
name: newClientName, | |
computationWhitelist: computationWhitelist || [], | |
owners: null, // Adjust ownership structure if needed | |
}, | |
}; | |
try { | |
const response = await callGraphQLMutation(createHeadlessClientMutation, variables, token); | |
if (response?.data?.createHeadlessClient) { | |
console.log(`Created headless client: ${response.data.createHeadlessClient.name}`); | |
return response.data.createHeadlessClient; | |
} else { | |
console.error(`Failed to create headless client for dataset: ${datasetName}`); | |
console.error(`GraphQL response errors: ${JSON.stringify(response?.errors, null, 2)}`); | |
console.error(`Variables: ${JSON.stringify(variables, null, 2)}`); | |
return null; | |
} | |
} catch (error) { | |
console.error(`Exception occurred while creating headless client for dataset: ${datasetName}`); | |
console.error(`Error: ${error.message}`); | |
console.error(`Stack trace: ${error.stack}`); | |
console.error(`Variables: ${JSON.stringify(variables, null, 2)}`); | |
return null; | |
} | |
})); | |
} | |
/** | |
* Generate configuration for clients matching a prefix. | |
*/ | |
async function createHeadlessClientConfig({ prefix, token }) { | |
const allHeadlessClients = await getHeadlessClients(token); | |
const filteredClients = allHeadlessClients.filter(client => client.name.includes(prefix)); | |
return Promise.all(filteredClients.map(async client => { | |
const apiKey = await generateApiKey(token, client.id); | |
return { id: client.id, name: client.name, apiKey }; | |
})); | |
} | |
/** | |
* Delete headless client entities matching a prefix. | |
*/ | |
async function deleteHeadlessClientEntities({ prefix, token }) { | |
const allHeadlessClients = await getHeadlessClients(token); | |
const filteredClients = allHeadlessClients.filter(client => client.name.includes(prefix)); | |
return Promise.all(filteredClients.map(async client => { | |
const variables = { headlessClientId: client.id }; | |
const response = await callGraphQLMutation(deleteHeadlessClientMutation, variables, token); | |
if (response?.data?.deleteHeadlessClient) { | |
console.log(`Deleted headless client: ${response.data.deleteHeadlessClient.name}`); | |
} else { | |
console.error(`Failed to delete headless client with ID: ${client.id}`); | |
} | |
})); | |
} | |
/** | |
* Delete all headless clients whose names start with a given prefix. | |
* @param {string} prefix - The prefix to match client names. | |
* @param {string} token - Authentication token. | |
*/ | |
async function deleteHeadlessClientsByPrefix(prefix, token) { | |
try { | |
// Fetch all headless clients | |
const allHeadlessClients = await getHeadlessClients(token); | |
// Filter clients matching the prefix | |
const clientsToDelete = allHeadlessClients.filter(client => client.name.startsWith(prefix)); | |
if (clientsToDelete.length === 0) { | |
console.log(`No headless clients found with prefix: ${prefix}`); | |
return; | |
} | |
console.log(`Found ${clientsToDelete.length} clients to delete with prefix: ${prefix}`); | |
// Delete each matching client | |
await Promise.all(clientsToDelete.map(async client => { | |
const variables = { headlessClientId: client.id }; | |
const response = await callGraphQLMutation(deleteHeadlessClientMutation, variables, token); | |
if (response?.data?.deleteHeadlessClient) { | |
console.log(`Deleted headless client: ${response.data.deleteHeadlessClient.name}`); | |
} else { | |
console.error(`Failed to delete headless client: ${client.name} (ID: ${client.id})`); | |
if (response?.errors) { | |
console.error(`GraphQL errors: ${JSON.stringify(response.errors, null, 2)}`); | |
} | |
} | |
})); | |
console.log(`Completed deletion of clients with prefix: ${prefix}`); | |
} catch (error) { | |
console.error(`Error during deletion of clients with prefix: ${prefix}`); | |
console.error(`Error details: ${error.message}`); | |
console.error(`Stack trace: ${error.stack}`); | |
} | |
} | |
async function updateHeadlessClient(token, clientId, updateData) { | |
const variables = { | |
headlessClientId: clientId, | |
data: updateData, | |
}; | |
try { | |
const response = await callGraphQLMutation(updateHeadlessClientMutation, variables, token); | |
if (response?.data?.updateHeadlessClient) { | |
console.log(`Updated headless client: ${response.data.updateHeadlessClient.name}`); | |
return response.data.updateHeadlessClient; | |
} else { | |
console.error(`Failed to update headless client with ID: ${clientId}`); | |
console.error(`GraphQL response errors: ${JSON.stringify(response?.errors, null, 2)}`); | |
return null; | |
} | |
} catch (error) { | |
console.error(`Exception occurred while updating headless client with ID: ${clientId}`); | |
console.error(`Error: ${error.message}`); | |
console.error(`Stack trace: ${error.stack}`); | |
return null; | |
} | |
} | |
async function saveAllHeadlessClientConfigurations(token) { | |
try { | |
// Fetch all headless clients | |
const allHeadlessClients = await getHeadlessClients(token); | |
if (!allHeadlessClients || allHeadlessClients.length === 0) { | |
console.log("No headless clients found."); | |
return; | |
} | |
// Iterate through each headless client | |
await Promise.all( | |
allHeadlessClients.map(async (client) => { | |
const clientConfig = { | |
id: client.id, | |
name: client.name, | |
computationWhitelist: client.computationWhitelist || [], | |
owners: client.owners || [], | |
hasApiKey: client.hasApiKey, | |
}; | |
// // Generate API key if it doesn't exist | |
// if (!client.hasApiKey) { | |
// const apiKey = await generateApiKey(token, client.id); | |
// if (apiKey) { | |
// clientConfig.apiKey = apiKey; | |
// } else { | |
// console.error(`Failed to generate API key for client: ${client.name}`); | |
// } | |
// } | |
// Save the configuration to a file | |
const fileName = `${client.name}.json`; | |
await fs.promises.writeFile(fileName, JSON.stringify(clientConfig, null, 2)); | |
console.log(`Configuration for client "${client.name}" saved to file: ${fileName}`); | |
}) | |
); | |
console.log("All client configurations have been saved."); | |
} catch (error) { | |
console.error("Error while saving headless client configurations:", error.message); | |
console.error(error.stack); | |
} | |
} | |
// ----------------------------- | |
// Main Execution | |
// ----------------------------- | |
(async () => { | |
const USERNAME = ""; | |
const PASSWORD = ""; | |
const token = await getToken(USERNAME, PASSWORD); | |
if (!token) { | |
console.error("Failed to authenticate. Exiting."); | |
return; | |
} | |
const datasetNames = [ | |
"CMI-GICA vault", | |
"CMI-HealthyBrain-Freesurfer_regression_vault", | |
"CMI-HealthyBrain-VBM_regression_vault", | |
"Substance-Use-Freesurfer_regression_vault", | |
"Substance-Use-VBM_regression_vault", | |
"SUBSTANCEUSE-GICA vault", | |
"TReNDS-COBRE-Freesurfer_regression_vault", | |
"TReNDS-COBRE-GICA vault", | |
"TReNDS-COBRE-VBM regression vault", | |
]; | |
const numberOfVaultServers = 1; | |
for (let i = 0; i < numberOfVaultServers; i++) { | |
const prefix = `VAULT-TEST-${i+1}`; | |
console.log(`Creating clients for prefix: ${prefix}`); | |
await createHeadlessClientEntities({ prefix, datasetNames, token }); | |
console.log(`Generating configuration for prefix: ${prefix}`); | |
const vaultConfig = await createHeadlessClientConfig({ prefix, token }); | |
const filePath = `vault_config-${prefix}.json`; | |
await fs.promises.writeFile(filePath, JSON.stringify(vaultConfig, null, 2)); | |
console.log(`Vault Config saved to ${filePath}`); | |
} | |
// await deleteHeadlessClientsByPrefix("test-ec2", token); | |
// await saveAllHeadlessClientConfigurations(token); | |
})(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment