cf-node-client
momo auto_awesome BUY CLAUDE KIT WITH 20% OFF coffee BUY ME COFFEE

Source: model/cloudcontroller/CloudController.js

"use strict";

const CloudControllerBase = require("./CloudControllerBase");

/**
 * Entry point for the Cloud Foundry Controller.
 * Supports both CF API v2 and v3 with automatic version routing.
 * {@link https://github.com/cloudfoundry/cloud_controller_ng}
 *
 * @class
 */
class CloudController extends CloudControllerBase {

    /**
     * @param {String} [endPoint] - Cloud Controller API endpoint URL
     * @param {Object} [options={}] - Options (same as CloudControllerBase)
     */
    constructor(endPoint, options = {}) {
        super(endPoint, options);
    }

    /**
     * Get information from Cloud Controller.
     *
     * v2: {@link http://apidocs.cloudfoundry.org/214/info/get_info.html}
     * v3: Uses the root endpoint (/) — CF v3 has no /v3/info.
     *     The response is **normalized** so that `authorization_endpoint`
     *     and `token_endpoint` are always present at the top level,
     *     keeping backward compatibility with existing consumer code.
     *
     * @return {Promise} Resolves with JSON info (always contains
     *                   `authorization_endpoint` and `token_endpoint`)
     */
    getInfo() {
        if (this.isUsingV3()) {
            // CF v3: root endpoint "/" returns { links: { uaa: {href}, login: {href}, … } }
            const options = {
                method: "GET",
                url: `${this.API_URL}/`,
                headers: { Accept: "application/json" }
            };
            return this.REST.request(options, this.HttpStatus.OK, true)
                .then(function (result) {
                    // Normalize: add v2-style fields for backward compatibility
                    if (result && result.links) {
                        if (result.links.login && result.links.login.href) {
                            result.authorization_endpoint = result.links.login.href;
                        } else if (result.links.uaa && result.links.uaa.href) {
                            result.authorization_endpoint = result.links.uaa.href;
                        }
                        if (result.links.uaa && result.links.uaa.href) {
                            result.token_endpoint = result.links.uaa.href;
                        }
                    }
                    return result;
                });
        }
        const options = {
            method: "GET",
            url: `${this.API_URL}/v2/info`
        };
        return this.REST.request(options, this.HttpStatus.OK, true);
    }

    /**
     * Get the UAA authorization endpoint URL from Cloud Controller info.
     * Works with both v2 and v3 — abstracts away the response shape difference.
     *
     * @return {Promise<String>} Resolves with the authorization endpoint URL
     * @throws {Error} If authorization endpoint is not found in the info response
     */
    getAuthorizationEndpoint() {
        return this.getInfo().then(function (info) {
            const endpoint = info.authorization_endpoint;
            if (!endpoint) {
                throw new Error(
                    "Could not determine authorization_endpoint from CF info response. " +
                    "Ensure the Cloud Controller is reachable and returns valid info."
                );
            }
            return endpoint;
        });
    }

    /**
     * Get all feature flags
     * v2: {@link http://apidocs.cloudfoundry.org/214/feature_flags/get_all_feature_flags.html}
     * v3: {@link https://v3-apidocs.cloudfoundry.org/#list-feature-flags}
     *
     * @return {Promise} Resolves with JSON feature flags list
     */
    getFeaturedFlags() {
        const token = this.getAuthorizationHeader();
        if (this.isUsingV3()) {
            return this.REST.requestV3("GET", `${this.API_URL}/v3/feature_flags`, token);
        }
        const options = {
            method: "GET",
            url: `${this.API_URL}/v2/config/feature_flags`,
            headers: { Authorization: token }
        };
        return this.REST.request(options, this.HttpStatus.OK, true);
    }

    /**
     * Get a specific feature flag
     * v2: {@link http://apidocs.cloudfoundry.org/214/feature_flags/get_the_diego_docker_feature_flag.html}
     * v3: {@link https://v3-apidocs.cloudfoundry.org/#get-a-feature-flag}
     *
     * @param  {String} flag - Feature flag name
     * @return {Promise} Resolves with JSON feature flag
     */
    getFeaturedFlag(flag) {
        const token = this.getAuthorizationHeader();
        if (this.isUsingV3()) {
            return this.REST.requestV3("GET", `${this.API_URL}/v3/feature_flags/${flag}`, token);
        }
        const options = {
            method: "GET",
            url: `${this.API_URL}/v2/config/feature_flags/${flag}`,
            headers: { Authorization: token }
        };
        return this.REST.request(options, this.HttpStatus.OK, true);
    }

    /**
     * Enable / set a feature flag
     * v2: {@link http://apidocs.cloudfoundry.org/214/feature_flags/set_a_feature_flag.html}
     * v3: {@link https://v3-apidocs.cloudfoundry.org/#update-a-feature-flag}
     *
     * @param {String} flag - Feature flag name
     * @param {Object} [flagOptions] - v3 body (e.g. { enabled: true })
     * @return {Promise} Resolves with JSON response
     */
    setFeaturedFlag(flag, flagOptions) {
        const token = this.getAuthorizationHeader();
        if (this.isUsingV3()) {
            return this.REST.requestV3("PATCH", `${this.API_URL}/v3/feature_flags/${flag}`, token, flagOptions);
        }
        const options = {
            method: "PUT",
            url: `${this.API_URL}/v2/config/feature_flags/${flag}`,
            headers: { Authorization: token }
        };
        return this.REST.request(options, this.HttpStatus.OK, true);
    }

}

module.exports = CloudController;