diff --git a/example/create-recipe.json b/example/create-recipe.json index 9db9302a8..062d8ccf2 100644 --- a/example/create-recipe.json +++ b/example/create-recipe.json @@ -2,6 +2,10 @@ "sandbox": { "clonable": true, "properties": [ + { + "rulesPath": "papi-rules-1.json", + "hostname": "www.example.com" + }, { "property": "447903:2" } diff --git a/schemas/recipe.json b/schemas/recipe.json index 5a0a6fdef..c0aa92e8e 100644 --- a/schemas/recipe.json +++ b/schemas/recipe.json @@ -48,24 +48,7 @@ "property": { "type": "string" } - }, - "oneOf": [ - { - "required": [ - "rulesPath" - ] - }, - { - "required": [ - "property" - ] - }, - { - "required": [ - "hostname" - ] - } - ] + } }, "minItems": 1 } diff --git a/src/cli-main.ts b/src/cli-main.ts index b7c62256b..11caa37a2 100644 --- a/src/cli-main.ts +++ b/src/cli-main.ts @@ -464,12 +464,13 @@ async function addPropertyFromRules(sandboxId: string, papiFilePath: string, hos return await cliUtils.spinner(sandboxSvc.addPropertyFromRules(sandboxId, hostnames, papiJson), `adding sandbox property to ${sandboxId}`); } -async function createFromRules(papiFilePath: string, hostnames: Array, isClonable: boolean, name: string, cpcode: number) { +async function createFromRules(papiFilePath: string, propForRules: string, hostnames: Array, isClonable: boolean, name: string, cpcode: number) { if (!fs.existsSync(papiFilePath)) { logAndExit(`file: ${papiFilePath} does not exist`); } const papiJson = getJsonFromFile(papiFilePath); - return await cliUtils.spinner(sandboxSvc.createFromRules(papiJson, hostnames, name, isClonable, cpcode), "creating new sandbox"); + const propertySpecObjMsg = `${JSON.stringify(propForRules)}`; + return await cliUtils.spinner(sandboxSvc.createFromRules(papiJson, propForRules, hostnames, name, isClonable, cpcode), "creating new sandbox"); } function parsePropertySpecifier(propertySpecifier) { @@ -547,8 +548,20 @@ async function createFromPropertiesRecipe(recipe, cpcode) { const properties = sandboxRecipe.properties; const firstProp = properties[0]; + let propForRules; + if (firstProp.rulesPath) { + console.log(`Found rules in properties.. Finding property to base the sandbox to be created..`); + + if (firstProp.property) { + propForRules = parsePropertySpecifier(firstProp.property); + } + else if (firstProp.hostname){ + propForRules = firstProp.hostname; + } + } + console.log(`creating sandbox & property 1 from recipe`); - const r = await cliUtils.spinner(createRecipeSandboxAndProperty(firstProp, sandboxRecipe, cpcode)); + const r = await cliUtils.spinner(createRecipeSandboxAndProperty(firstProp, propForRules, sandboxRecipe, cpcode)); for (var i = 1; i < properties.length; i++) { try { @@ -590,23 +603,34 @@ function validateAndBuildRecipe(recipeFilePath, name, clonable): any { const sandboxRecipe = recipe.sandbox; sandboxRecipe.clonable = clonable || sandboxRecipe.clonable; sandboxRecipe.name = name || sandboxRecipe.name; + var idx = 0; + if (sandboxRecipe.properties) { sandboxRecipe.properties.forEach(p => { if (p.rulesPath) { + if(!oneOf(p.property, p.hostname)) { + logAndExit(`Error with property ${idx}. Either property or hostname must be specified to base the created sandbox on when a rulesPath is specified.`); + } p.rulesPath = resolveRulesPath(recipeFilePath, p.rulesPath); } + idx++; }); - var idx = 0; + + idx = 0; sandboxRecipe.properties.forEach(p => { - if (!oneOf(p.rulesPath, p.property, p.hostname)) { - logAndExit(`Error with property ${idx}. Please specify only one of: rulesPath, property, or hostname`); + if (!oneOf(p.property, p.hostname)) { + logAndExit(`Error with property ${idx}. Please specify only one of: property or hostname`); } if (p.rulesPath && !fs.existsSync(p.rulesPath)) { logAndExit(`Error with property ${idx} could not load file at path: ${p.rulesPath}`); } - if (p.rulesPath && (!p.requestHostnames || p.requestHostnames.length === 0)) { - logAndExit(`Error with property ${idx}. Must specify requestHostnames array when using rulesPath`); - } + + // requestHostnames is no longer required when specifying rules, the hostnames can be obtained from the createFromProperty specified + // However, providing requestHostnames will override those hostnames. + + /* if (p.rulesPath && (!p.requestHostnames || p.requestHostnames.length === 0)) { + logAndExit(`Error with property ${idx}. Must specify requestHostnames array when using rulesPath`); + }*/ idx++; }); } @@ -691,13 +715,13 @@ function createRecipeProperty(rp, sandboxId) { } } -function createRecipeSandboxAndProperty(rp, recipe, cpcode) { +function createRecipeSandboxAndProperty(rp, propertyForRules, recipe, cpcode) { if (rp.property) { return createFromProperty(rp.property, rp.requestHostnames, recipe.clonable, recipe.name, cpcode); } else if (rp.hostname) { return createFromHostname(rp.hostname, rp.requestHostnames, recipe.clonable, recipe.name, cpcode); } else if (rp.rulesPath) { - return createFromRules(rp.rulesPath, rp.requestHostnames, recipe.clonable, recipe.name, cpcode); + return createFromRules(rp.rulesPath, propertyForRules, rp.requestHostnames, recipe.clonable, recipe.name, cpcode); } else { logAndExit("critical error with recipe property. rulesPath or property needs to be defined."); } @@ -726,7 +750,7 @@ function isNonEmptyString(obj) { program .command('create') .description('create a new sandbox') - .option('-r, --rules ', 'papi json file') + .option('-r, --rules ', 'papi json file. a property or hostname must also be specified to base the created sandbox on') .option('-p, --property ', 'property to use. if no version is specified the latest will be used.') .option('-o, --hostname ', 'the hostname of your akamai property (e.g. www.example.com)') .option('-c, --clonable ', 'make this sandbox clonable') @@ -752,22 +776,44 @@ program const propertySpecifier = options.property; const hostnameSpecifier = options.hostname; + let propForRules; //validation if (!isNonEmptyString(name)) { logAndExit(`You must provide a name for your sandbox`); } - if (!oneOf(propertySpecifier, papiFilePath, hostnameSpecifier)) { - logAndExit(`Exactly one of the following must be specified: --property, --rules, --hostname. Please pick only one of those arguments.`) + + // if --rules is specified, then either --property or --hostname must be specified + if (papiFilePath) { + if(!oneOf(propertySpecifier, hostnameSpecifier)) { + logAndExit(`Either --property or --hostname must be specified to base the created sandbox on when --rules is specified.`); + } + if(propertySpecifier) { + propForRules = parsePropertySpecifier(propertySpecifier); + } + else { + propForRules = hostnameSpecifier; + } } - if (!hostnamesCsv && papiFilePath) { - logAndExit('--requesthostnames must be specified when specifying --rules'); + // if hostnames are accepted with --rules then leave this below logic as it is + // else add logic when --rules and --hostname is detected as invalid + if (!oneOf(propertySpecifier, hostnameSpecifier)) { + logAndExit(`Exactly one of the following must be specified : --property, --hostname. Please pick only one of those arguments.`) } + + + // requestHostnames is no longer required when specifying --rules, the hostnames can be obtained from the createFromProperty specified + // However, providing requestHostnames will override those hostnames. + + /* if (!hostnamesCsv && papiFilePath) { + logAndExit('--requesthostnames must be specified when specifying --rules'); + }*/ + const hostnames = hostnamesCsv ? parseHostnameCsv(hostnamesCsv) : undefined; var r = null; if (papiFilePath) { - r = await createFromRules(papiFilePath, hostnames, isClonable, name, cpcode); + r = await createFromRules(papiFilePath, propForRules, hostnames, isClonable, name, cpcode); } else if (propertySpecifier) { r = await createFromProperty(propertySpecifier, hostnames, isClonable, name, cpcode); } else if (hostnameSpecifier) { diff --git a/src/service/sandbox-svc.ts b/src/service/sandbox-svc.ts index 0d184535a..ccd4b703f 100644 --- a/src/service/sandbox-svc.ts +++ b/src/service/sandbox-svc.ts @@ -104,14 +104,18 @@ export function updateSandbox(sandbox) { return putJson(`${SANDBOX_API_BASE}/sandboxes/${sandbox.sandboxId}`, sandbox).then(r => r.body); } -export function createFromRules(papiRules, requestHostnames, name, isClonable, cpcode) { +export function createFromRules(papiRules, fromPropertyObj, requestHostnames, name, isClonable, cpcode) { var bodyObj = { name: name, - requestHostnames: requestHostnames, createFromRules: papiRules, + createFromProperty: fromPropertyObj, isClonable: isClonable }; + if (requestHostnames) { + bodyObj['requestHostnames'] = requestHostnames; + } + if(cpcode) { bodyObj['cpcode'] = cpcode; }