diff --git a/README.md b/README.md index 8af627e..882b9cc 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ Here’s a typical workflow when you want to break your Property Manager configu * Do you need any new supporting processes? For example, if different teams are involved, how will you manage ownership of the different templates? -1. Import an existing property by running the `akamai property-manager import` command. This creates a local instance of your configuration. You can also create a new property if needed. +1. Import an existing property by running the `akamai property-manager import --network --propver ` command. This creates a local instance of your configuration. You can also create a new property if needed. 1. Verify that the `/config-snippets` folder contains a separate JSON-based configuration snippet for each rule in your property configuration.
In this folder, the `main.json` file ties all the snippets together. It lists the available snippets and contains the local permissions for each snippet. @@ -215,7 +215,7 @@ Create your local client side snippets to let different teams own different part 1. Determine how to handle any [custom user variables](#using-property-manager-user-variables). -1. Run the `akamai property-manager import` command to create a local instance of your Property Manager configuration. +1. Run the `akamai property-manager import --network --propver ` command to create a local instance of your Property Manager configuration. 1. In your project directory structure, navigate to the new `config-snippets` folder.
This folder contains a separate JSON-based configuration snippet for each rule in your property configuration. @@ -480,7 +480,7 @@ Here are some ways you can use the Property Manager CLI to meet your business ne If you also use the Property Manager UI, make sure your client side files are in sync with the latest property version on the network. -To retrieve all updates from the latest property version, run this command: `akamai property-manager update-local -p `.
The `update-local` command overrides any locally-saved configuration version with the latest active property version. +To retrieve all updates from the latest or specific property version, run this command: `akamai property-manager update-local -p --network --propver `.
The `update-local` command overrides any locally-saved configuration version with the latest or specified property version. ## Retrieve a specific rule from Property Manager diff --git a/docs/cli_pm_commands_help.md b/docs/cli_pm_commands_help.md index 6cb5684..b67571e 100644 --- a/docs/cli_pm_commands_help.md +++ b/docs/cli_pm_commands_help.md @@ -131,6 +131,9 @@ Creates a local version of an existing property. Options: -p, --property Property name. Optional if default property was set using the set-default command. + -n, --network Network, either 'production' or 'staging'. You + can shorten 'production' to 'prod' or 'p' and + 'staging' to 'stage' or 's'. --dry-run Verify the result of your command syntax before running it. Displays the JSON generated by the command as currently @@ -155,6 +158,9 @@ Update local property with the latest from the Property Manager API (PAPI). Options: -p, --property Property name. Optional if default property was set using the set-default command. + -n, --network Network, either 'production' or 'staging'. You + can shorten 'production' to 'prod' or 'p' and + 'staging' to 'stage' or 's'. --dry-run Verify the result of your command syntax before running it. Displays the JSON generated by the command as currently diff --git a/src/papi.js b/src/papi.js index 82d6620..114213a 100644 --- a/src/papi.js +++ b/src/papi.js @@ -70,8 +70,13 @@ class PAPI { return this.openClient.post(url, postBody); } - latestPropertyVersion(propertyId) { - let url = `/papi/v1/properties/${propertyId}/versions/latest`; + latestPropertyVersion(propertyId, network) { + let url; + if (network) { + url = `/papi/v1/properties/${propertyId}/versions/latest?activatedOn=${network}`; + } else { + url = `/papi/v1/properties/${propertyId}/versions/latest`; + } return this.openClient.get(url); } diff --git a/src/pm/devops_property_manager.js b/src/pm/devops_property_manager.js index dd5f85f..ff7514d 100644 --- a/src/pm/devops_property_manager.js +++ b/src/pm/devops_property_manager.js @@ -127,8 +127,9 @@ class DevopsPropertyManager extends Devops { "property_does_not_exist_on_server", createPropertyInfo.propertyName); } createPropertyInfo.propertyId = helpers.parsePropertyId(results.versions.items[0].propertyId); - let propertyInfo = await project.getPropertyInfo(createPropertyInfo.propertyId); + let propertyInfo = await project.getPropertyInfo(createPropertyInfo.propertyId, createPropertyInfo.propertyVersion, createPropertyInfo.network); + project.propertyVersion = propertyInfo.propertyVersion; createPropertyInfo.propertyVersion = propertyInfo.propertyVersion; logger.info(`Attempting to load rule tree for property id: ${createPropertyInfo.propertyId} and version: ${createPropertyInfo.propertyVersion}`); let ruleTree = await project.getPropertyRuleTree(createPropertyInfo.propertyId, createPropertyInfo.propertyVersion); @@ -171,9 +172,9 @@ class DevopsPropertyManager extends Devops { } envInfo.propertyId = helpers.parsePropertyId(results.versions.items[0].propertyId); } - let propertyInfo = await project.getPropertyInfo(envInfo.propertyId); - + let propertyInfo = await project.getPropertyInfo(envInfo.propertyId, createPropertyInfo.propertyVersion, createPropertyInfo.network); + project.propertyVersion = propertyInfo.propertyVersion ruleTree = await project.getPropertyRuleTree(envInfo.propertyId, propertyInfo.propertyVersion); let projectInfo = project.getProjectInfo(); let isSecure = ruleTree.rules.options.is_secure; diff --git a/src/pm/property_manager_cli.js b/src/pm/property_manager_cli.js index 36fdbd1..0e27720 100644 --- a/src/pm/property_manager_cli.js +++ b/src/pm/property_manager_cli.js @@ -613,13 +613,22 @@ Are you sure you want to deactivate the property '${propertyName}' on network '$ const importProperty = async function(devops, options) { let propertyName = options.property; + let propertyVersion = parseInt(options.propver, 10); + let network; if (!propertyName || _.isBoolean(propertyName)) { throw new errors.DependencyError("Missing property option! Use akamai property-manager import -p ...", "missing_property_name"); } + + if (options.network) { + network = commonCli.checkNetworkName(options); + } + consoleLogger.info(`Importing and creating local files for ${propertyName} from Property Manager...`); let createPropertyInfo = { - propertyName + propertyName, + propertyVersion, + network }; let variableMode = helpers.allowedModes[1]; @@ -635,7 +644,7 @@ Are you sure you want to deactivate the property '${propertyName}' on network '$ consoleLogger.info("update property info: ", helpers.jsonStringify(createPropertyInfo)); } else { let project = await devops.importProperty(createPropertyInfo); - consoleLogger.info(`Imported ${project.getName()}. The latest version is: v${project.loadEnvironmentInfo().latestVersionInfo.propertyVersion}`); + consoleLogger.info(`Imported ${project.getName()}. The local version is: v${project.propertyVersion}`); } }; @@ -664,6 +673,12 @@ Are you sure you want to DELETE the property '${options.property}'?`, const update = async function(devops, options) { let runPull = options.forceUpdate; let projectName = devops.extractProjectName(options); + let propertyVersion = parseInt(options.propver, 10); + let network; + + if (options.network) { + network = commonCli.checkNetworkName(options); + } if (!runPull) { var questions = [{ @@ -683,9 +698,12 @@ Are you sure you want to DELETE the property '${options.property}'?`, throw new errors.ArgumentError(`Invalid variable mode option selected. Valid modes are ${printAllowedModesUpdateOrImport()}`, "invalid_variable_mode"); } + let createPropertyInfo = { projectName, - variableMode + variableMode, + propertyVersion, + network }; let dryRun = options.dryRun || false; @@ -696,7 +714,7 @@ Are you sure you want to DELETE the property '${options.property}'?`, } else { consoleLogger.info(`Updating and overwriting local files for ${projectName} from PAPI...`); let project = await devops.updateProperty(createPropertyInfo); - consoleLogger.info(`Updated ${project.getName()} to the latest: v${project.loadEnvironmentInfo().latestVersionInfo.propertyVersion}`); + consoleLogger.info(`Updated ${projectName}. The local version is: v${project.propertyVersion}`); } } @@ -1073,6 +1091,8 @@ Are you sure you want to DELETE the property '${options.property}'?`, commander .command("update-local", "Update local property with the latest version from the Property Manager API.") .option('-p, --property ', 'Property name. Optional if default property was set using the set-default command.') + .option('--propver ', "Optional. The property version to activate. Uses latest version if not specified.", helpers.parsePropertyVersion) + .option('-n, --network ', "Optional. Network, either 'production' or 'staging'. You can shorten 'production' to " + "'prod' or 'p' and 'staging' to 'stage' or 's'.") .option('--dry-run', 'Verify the result of your command syntax before running it. Displays the JSON generated by the command as currently written.') .option('--force-update', 'WARNING: This option bypasses the confirmation prompt and automatically overwrites your local files.') .option('--variable-mode ', `Choose how this command pulls in variables. Allowed values are ${printAllowedModesUpdateOrImport()}. Default functionality is no-var.`) @@ -1088,6 +1108,8 @@ Are you sure you want to DELETE the property '${options.property}'?`, commander .command("import", "Import an existing property from Property Manager.") .option('-p, --property ', 'Property name. Optional if default property was set using the set-default command.') + .option('--propver ', "Optional. The property version to activate. Uses latest version if not specified.", helpers.parsePropertyVersion) + .option('-n, --network ', "Optional. Network, either 'production' or 'staging'. You can shorten 'production' to " + "'prod' or 'p' and 'staging' to 'stage' or 's'.") .option('--dry-run', 'Verify the result of your command syntax before running it. Displays the JSON generated by the command as currently written.') .option('--variable-mode ', `Choose how to pull in variables. Allowed values are ${printAllowedModesUpdateOrImport()}. By default, variables aren't imported (no-var).`) .alias("i") diff --git a/src/project.js b/src/project.js index e21b21a..2147ab7 100644 --- a/src/project.js +++ b/src/project.js @@ -348,14 +348,15 @@ class Project { /** * @param propertyId * @param version + * @param network * @return {Promise.<*>} */ - async getPropertyInfo(propertyId, version) { + async getPropertyInfo(propertyId, version, network) { let papi = this.dependencies.getPAPI(); let versionInfo; if (!_.isNumber(version)) { - versionInfo = await papi.latestPropertyVersion(propertyId); + versionInfo = await papi.latestPropertyVersion(propertyId, network); } else { versionInfo = await papi.getPropertyVersion(propertyId, version); } diff --git a/tests/snippets/snippets_cli_test.js b/tests/snippets/snippets_cli_test.js index b26fce5..b6aeb47 100644 --- a/tests/snippets/snippets_cli_test.js +++ b/tests/snippets/snippets_cli_test.js @@ -645,6 +645,12 @@ describe('Snippets CLI PULL command', function () { td.when(project.loadEnvironmentInfo()).thenReturn({ latestVersionInfo : { propertyVersion : 9 + }, + activeIn_STAGING_Info : { + propertyVersion : 8 + }, + activeIn_PRODUCTION_Info : { + propertyVersion : 5 } }); @@ -701,6 +707,32 @@ describe('Snippets CLI PULL command', function () { assert.equal(errorCatcher.error, 'Error: Can\'t read default property name from snippetsSettings.json and no property name provided per -p option'); }); }); + + it('update local output -with network', function () { + let createDevOpsFun = function (deps) { + let newDeps = { + devopsHome + }; + Object.assign(deps, newDeps); + + let devOps = createDevOps(deps); + devOps.updateProperty = function(){ + return project; + }; + return devOps; + }; + + let cliArgs = createCommand("update-local", "-p", "testproject.com", "--force-update", "-n", "stg"); + let testConsole = new TestConsole(); + return mainTester(errorReporter => { + main(cliArgs, {}, createDevOpsFun, errorReporter, testConsole); + }, errorCatcher => { + assert.equal(errorCatcher, null); + assert.equal(testConsole.logs.length, 2); + let output = testConsole.logs.join("\n"); + assert.equal(output, 'Updating and overwriting local files for testproject.com from PAPI...\nUpdated testproject.com to the latest: v9'); + }); + }); }); describe('Snippets CLI search tests', function () {