function getComposerExpandedYaml()

in ui-modules/utils/quick-launch/quick-launch.js [283:357]


        function getComposerExpandedYaml(validate) {
            const planText = $scope.app.plan.data || "{}";
            let result = {};

            // this is set if we're able to parse the plan's text definition, and then:
            // - we've had to override a field from the plan's text definition, because a value is set _and_ different; or
            // - the plan's text definition is indented or JSON rather than YAML (not outdented yaml)
            // and in either case we use the result _object_ ...
            // unless we didn't actually change anything, in which case this is ignored
            let cannotUsePlanText = false;

            if (validate) {
                result = yaml.safeLoad(planText);
                if (typeof result !== 'object') {
                    throw "The plan is not a YAML map, but of type "+(typeof result);
                }
                if (!result.services) {
                    throw "The plan does not have any services.";
                }
                cannotUsePlanText = Object.keys(result).some(property =>
                    // plan is not outdented yaml, can't use its text mode
                    !planText.startsWith(property) && !planText.includes('\n'+property+':')
                );
            }

            let newApp = {};

            let newName = $scope.model.name || $scope.app.displayName;
            if (newName && newName != result.name) {
                newApp.name = newName;
                if (result.name) {
                    delete result.name;
                    cannotUsePlanText = true;
                }
            }

            let newLocation = $scope.model.location;
            if (newLocation && newLocation != result.location) {
                newApp.location = newLocation;
                if (result.location) {
                    delete result.location;
                    cannotUsePlanText = true;
                }
            }

            let newConfig = $scope.entityToDeploy[BROOKLYN_CONFIG];
            if (newConfig) {
                if (result[BROOKLYN_CONFIG]) {
                    let oldConfig = result[BROOKLYN_CONFIG];
                    let mergedConfig = angular.copy(oldConfig);
                    for (const [k,v] of Object.entries(newConfig) ) {
                        if (mergedConfig[k] != v) {
                            cannotUsePlanText = true;
                            mergedConfig[k] = v;
                        }
                    }
                    if (cannotUsePlanText) {
                        newApp[BROOKLYN_CONFIG] = mergedConfig;
                        delete result[BROOKLYN_CONFIG];
                    }
                } else {
                    newApp[BROOKLYN_CONFIG] = newConfig;
                }
            }

            // prefer to use the actual yaml input, but if it's not possible
            let tryMergeByConcatenate = Object.keys(newApp).length
                ? yaml.safeDump(newApp, {skipInvalid: true}) + `\n${(validate && cannotUsePlanText) ? yaml.safeDump(result) : planText}`
                : planText;
            if (validate) {
                // don't think there's any way we'd wind up with invalid yaml but check to be sure
                yaml.safeLoad(tryMergeByConcatenate);
            }
            return tryMergeByConcatenate;
        }