text:
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ** This file is automatically generated by gapic-generator-typescript. **
// ** https://github.com/googleapis/gapic-generator-typescript **
// ** All changes to this file may be overwritten. **

/* global window */
import type * as gax from 'google-gax';
import type {
  Callback,
  CallOptions,
  Descriptors,
  ClientOptions,
  GrpcClientOptions,
  LROperation,
  PaginationCallback,
  GaxCall,
} from 'google-gax';
import {Transform} from 'stream';
import * as protos from '../../protos/protos';
import jsonProtos = require('../../protos/protos.json');
/**
 * Client JSON configuration object, loaded from
 * `src/v1/environments_client_config.json`.
 * This file defines retry strategy and timeouts for all API methods in this library.
 */
import * as gapicConfig from './environments_client_config.json';
const version = require('../../../package.json').version;

/**
 *  Managed Apache Airflow Environments.
 * @class
 * @memberof v1
 */
export class EnvironmentsClient {
  private _terminated = false;
  private _opts: ClientOptions;
  private _providedCustomServicePath: boolean;
  private _gaxModule: typeof gax | typeof gax.fallback;
  private _gaxGrpc: gax.GrpcClient | gax.fallback.GrpcClient;
  private _protos: {};
  private _defaults: {[method: string]: gax.CallSettings};
  auth: gax.GoogleAuth;
  descriptors: Descriptors = {
    page: {},
    stream: {},
    longrunning: {},
    batching: {},
  };
  warn: (code: string, message: string, warnType?: string) => void;
  innerApiCalls: {[name: string]: Function};
  pathTemplates: {[name: string]: gax.PathTemplate};
  operationsClient: gax.OperationsClient;
  environmentsStub?: Promise<{[name: string]: Function}>;

  /**
   * Construct an instance of EnvironmentsClient.
   *
   * @param {object} [options] - The configuration object.
   * The options accepted by the constructor are described in detail
   * in [this document](https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md#creating-the-client-instance).
   * The common options are:
   * @param {object} [options.credentials] - Credentials object.
   * @param {string} [options.credentials.client_email]
   * @param {string} [options.credentials.private_key]
   * @param {string} [options.email] - Account email address. Required when
   *     using a .pem or .p12 keyFilename.
   * @param {string} [options.keyFilename] - Full path to the a .json, .pem, or
   *     .p12 key downloaded from the Google Developers Console. If you provide
   *     a path to a JSON file, the projectId option below is not necessary.
   *     NOTE: .pem and .p12 require you to specify options.email as well.
   * @param {number} [options.port] - The port on which to connect to
   *     the remote host.
   * @param {string} [options.projectId] - The project ID from the Google
   *     Developer's Console, e.g. 'grape-spaceship-123'. We will also check
   *     the environment variable GCLOUD_PROJECT for your project ID. If your
   *     app is running in an environment which supports
   *     {@link https://developers.google.com/identity/protocols/application-default-credentials Application Default Credentials},
   *     your project ID will be detected automatically.
   * @param {string} [options.apiEndpoint] - The domain name of the
   *     API remote host.
   * @param {gax.ClientConfig} [options.clientConfig] - Client configuration override.
   *     Follows the structure of {@link gapicConfig}.
   * @param {boolean | "rest"} [options.fallback] - Use HTTP fallback mode.
   *     Pass "rest" to use HTTP/1.1 REST API instead of gRPC.
   *     For more information, please check the
   *     {@link https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md#http11-rest-api-mode documentation}.
   * @param {gax} [gaxInstance]: loaded instance of `google-gax`. Useful if you
   *     need to avoid loading the default gRPC version and want to use the fallback
   *     HTTP implementation. Load only fallback version and pass it to the constructor:
   *     ```
   *     const gax = require('google-gax/build/src/fallback'); // avoids loading google-gax with gRPC
   *     const client = new EnvironmentsClient({fallback: 'rest'}, gax);
   *     ```
   */
  constructor(
    opts?: ClientOptions,
    gaxInstance?: typeof gax | typeof gax.fallback
  ) {
    // Ensure that options include all the required fields.
    const staticMembers = this.constructor as typeof EnvironmentsClient;
    const servicePath =
      opts?.servicePath || opts?.apiEndpoint || staticMembers.servicePath;
    this._providedCustomServicePath = !!(
      opts?.servicePath || opts?.apiEndpoint
    );
    const port = opts?.port || staticMembers.port;
    const clientConfig = opts?.clientConfig ?? {};
    const fallback =
      opts?.fallback ??
      (typeof window !== 'undefined' && typeof window?.fetch === 'function');
    opts = Object.assign({servicePath, port, clientConfig, fallback}, opts);

    // If scopes are unset in options and we're connecting to a non-default endpoint, set scopes just in case.
    if (servicePath !== staticMembers.servicePath && !('scopes' in opts)) {
      opts['scopes'] = staticMembers.scopes;
    }

    // Load google-gax module synchronously if needed
    if (!gaxInstance) {
      gaxInstance = require('google-gax') as typeof gax;
    }

    // Choose either gRPC or proto-over-HTTP implementation of google-gax.
    this._gaxModule = opts.fallback ? gaxInstance.fallback : gaxInstance;

    // Create a `gaxGrpc` object, with any grpc-specific options sent to the client.
    this._gaxGrpc = new this._gaxModule.GrpcClient(opts);

    // Save options to use in initialize() method.
    this._opts = opts;

    // Save the auth object to the client, for use by other methods.
    this.auth = this._gaxGrpc.auth as gax.GoogleAuth;

    // Set useJWTAccessWithScope on the auth object.
    this.auth.useJWTAccessWithScope = true;

    // Set defaultServicePath on the auth object.
    this.auth.defaultServicePath = staticMembers.servicePath;

    // Set the default scopes in auth client if needed.
    if (servicePath === staticMembers.servicePath) {
      this.auth.defaultScopes = staticMembers.scopes;
    }

    // Determine the client header string.
    const clientHeader = [`gax/${this._gaxModule.version}`, `gapic/${version}`];
    if (typeof process !== 'undefined' && 'versions' in process) {
      clientHeader.push(`gl-node/${process.versions.node}`);
    } else {
      clientHeader.push(`gl-web/${this._gaxModule.version}`);
    }
    if (!opts.fallback) {
      clientHeader.push(`grpc/${this._gaxGrpc.grpcVersion}`);
    } else if (opts.fallback === 'rest') {
      clientHeader.push(`rest/${this._gaxGrpc.grpcVersion}`);
    }
    if (opts.libName && opts.libVersion) {
      clientHeader.push(`${opts.libName}/${opts.libVersion}`);
    }
    // Load the applicable protos.
    this._protos = this._gaxGrpc.loadProtoJSON(jsonProtos);

    // This API contains "path templates"; forward-slash-separated
    // identifiers to uniquely identify resources within the API.
    // Create useful helper objects for these.
    this.pathTemplates = {
      environmentPathTemplate: new this._gaxModule.PathTemplate(
        'projects/{project}/locations/{location}/environments/{environment}'
      ),
    };

    // Some of the methods on this service return "paged" results,
    // (e.g. 50 results at a time, with tokens to get subsequent
    // pages). Denote the keys used for pagination and results.
    this.descriptors.page = {
      listEnvironments: new this._gaxModule.PageDescriptor(
        'pageToken',
        'nextPageToken',
        'environments'
      ),
    };

    const protoFilesRoot = this._gaxModule.protobuf.Root.fromJSON(jsonProtos);
    // This API contains "long-running operations", which return a
    // an Operation object that allows for tracking of the operation,
    // rather than holding a request open.
    const lroOptions: GrpcClientOptions = {
      auth: this.auth,
      grpc: 'grpc' in this._gaxGrpc ? this._gaxGrpc.grpc : undefined,
    };
    if (opts.fallback === 'rest') {
      lroOptions.protoJson = protoFilesRoot;
      lroOptions.httpRules = [
        {
          selector: 'google.longrunning.Operations.DeleteOperation',
          delete: '/v1/{name=projects/*/locations/*/operations/*}',
        },
        {
          selector: 'google.longrunning.Operations.GetOperation',
          get: '/v1/{name=projects/*/locations/*/operations/*}',
        },
        {
          selector: 'google.longrunning.Operations.ListOperations',
          get: '/v1/{name=projects/*/locations/*}/operations',
        },
      ];
    }
    this.operationsClient = this._gaxModule
      .lro(lroOptions)
      .operationsClient(opts);
    const createEnvironmentResponse = protoFilesRoot.lookup(
      '.google.cloud.orchestration.airflow.service.v1.Environment'
    ) as gax.protobuf.Type;
    const createEnvironmentMetadata = protoFilesRoot.lookup(
      '.google.cloud.orchestration.airflow.service.v1.OperationMetadata'
    ) as gax.protobuf.Type;
    const updateEnvironmentResponse = protoFilesRoot.lookup(
      '.google.cloud.orchestration.airflow.service.v1.Environment'
    ) as gax.protobuf.Type;
    const updateEnvironmentMetadata = protoFilesRoot.lookup(
      '.google.cloud.orchestration.airflow.service.v1.OperationMetadata'
    ) as gax.protobuf.Type;
    const deleteEnvironmentResponse = protoFilesRoot.lookup(
      '.google.protobuf.Empty'
    ) as gax.protobuf.Type;
    const deleteEnvironmentMetadata = protoFilesRoot.lookup(
      '.google.cloud.orchestration.airflow.service.v1.OperationMetadata'
    ) as gax.protobuf.Type;

    this.descriptors.longrunning = {
      createEnvironment: new this._gaxModule.LongrunningDescriptor(
        this.operationsClient,
        createEnvironmentResponse.decode.bind(createEnvironmentResponse),
        createEnvironmentMetadata.decode.bind(createEnvironmentMetadata)
      ),
      updateEnvironment: new this._gaxModule.LongrunningDescriptor(
        this.operationsClient,
        updateEnvironmentResponse.decode.bind(updateEnvironmentResponse),
        updateEnvironmentMetadata.decode.bind(updateEnvironmentMetadata)
      ),
      deleteEnvironment: new this._gaxModule.LongrunningDescriptor(
        this.operationsClient,
        deleteEnvironmentResponse.decode.bind(deleteEnvironmentResponse),
        deleteEnvironmentMetadata.decode.bind(deleteEnvironmentMetadata)
      ),
    };

    // Put together the default options sent with requests.
    this._defaults = this._gaxGrpc.constructSettings(
      'google.cloud.orchestration.airflow.service.v1.Environments',
      gapicConfig as gax.ClientConfig,
      opts.clientConfig || {},
      {'x-goog-api-client': clientHeader.join(' ')}
    );

    // Set up a dictionary of "inner API calls"; the core implementation
    // of calling the API is handled in `google-gax`, with this code
    // merely providing the destination and request information.
    this.innerApiCalls = {};

    // Add a warn function to the client constructor so it can be easily tested.
    this.warn = this._gaxModule.warn;
  }

  /**
   * Initialize the client.
   * Performs asynchronous operations (such as authentication) and prepares the client.
   * This function will be called automatically when any class method is called for the
   * first time, but if you need to initialize it before calling an actual method,
   * feel free to call initialize() directly.
   *
   * You can await on this method if you want to make sure the client is initialized.
   *
   * @returns {Promise} A promise that resolves to an authenticated service stub.
   */
  initialize() {
    // If the client stub promise is already initialized, return immediately.
    if (this.environmentsStub) {
      return this.environmentsStub;
    }

    // Put together the "service stub" for
    // google.cloud.orchestration.airflow.service.v1.Environments.
    this.environmentsStub = this._gaxGrpc.createStub(
      this._opts.fallback
        ? (this._protos as protobuf.Root).lookupService(
            'google.cloud.orchestration.airflow.service.v1.Environments'
          )
        : // eslint-disable-next-line @typescript-eslint/no-explicit-any
          (this._protos as any).google.cloud.orchestration.airflow.service.v1
            .Environments,
      this._opts,
      this._providedCustomServicePath
    ) as Promise<{[method: string]: Function}>;

    // Iterate over each of the methods that the service provides
    // and create an API call method for each.
    const environmentsStubMethods = [
      'createEnvironment',
      'getEnvironment',
      'listEnvironments',
      'updateEnvironment',
      'deleteEnvironment',
    ];
    for (const methodName of environmentsStubMethods) {
      const callPromise = this.environmentsStub.then(
        stub =>
          (...args: Array<{}>) => {
            if (this._terminated) {
              return Promise.reject('The client has already been closed.');
            }
            const func = stub[methodName];
            return func.apply(stub, args);
          },
        (err: Error | null | undefined) => () => {
          throw err;
        }
      );

      const descriptor =
        this.descriptors.page[methodName] ||
        this.descriptors.longrunning[methodName] ||
        undefined;
      const apiCall = this._gaxModule.createApiCall(
        callPromise,
        this._defaults[methodName],
        descriptor,
        this._opts.fallback
      );

      this.innerApiCalls[methodName] = apiCall;
    }

    return this.environmentsStub;
  }

  /**
   * The DNS address for this API service.
   * @returns {string} The DNS address for this service.
   */
  static get servicePath() {
    return 'composer.googleapis.com';
  }

  /**
   * The DNS address for this API service - same as servicePath(),
   * exists for compatibility reasons.
   * @returns {string} The DNS address for this service.
   */
  static get apiEndpoint() {
    return 'composer.googleapis.com';
  }

  /**
   * The port for this API service.
   * @returns {number} The default port for this service.
   */
  static get port() {
    return 443;
  }

  /**
   * The scopes needed to make gRPC calls for every method defined
   * in this service.
   * @returns {string[]} List of default scopes.
   */
  static get scopes() {
    return ['https://www.googleapis.com/auth/cloud-platform'];
  }

  getProjectId(): Promise<string>;
  getProjectId(callback: Callback<string, undefined, undefined>): void;
  /**
   * Return the project ID used by this class.
   * @returns {Promise} A promise that resolves to string containing the project ID.
   */
  getProjectId(
    callback?: Callback<string, undefined, undefined>
  ): Promise<string> | void {
    if (callback) {
      this.auth.getProjectId(callback);
      return;
    }
    return this.auth.getProjectId();
  }

  // -------------------
  // -- Service calls --
  // -------------------
  /**
   * Get an existing environment.
   *
   * @param {Object} request
   *   The request object that will be sent.
   * @param {string} request.name
   *   The resource name of the environment to get, in the form:
   *   "projects/{projectId}/locations/{locationId}/environments/{environmentId}"
   * @param {object} [options]
   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
   * @returns {Promise} - The promise which resolves to an array.
   *   The first element of the array is an object representing [Environment]{@link google.cloud.orchestration.airflow.service.v1.Environment}.
   *   Please see the
   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
   *   for more details and examples.
   * @example <caption>include:samples/generated/v1/environments.get_environment.js</caption>
   * region_tag:composer_v1_generated_Environments_GetEnvironment_async
   */
  getEnvironment(
    request?: protos.google.cloud.orchestration.airflow.service.v1.IGetEnvironmentRequest,
    options?: CallOptions
  ): Promise<
    [
      protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
      (
        | protos.google.cloud.orchestration.airflow.service.v1.IGetEnvironmentRequest
        | undefined
      ),
      {} | undefined
    ]
  >;
  getEnvironment(
    request: protos.google.cloud.orchestration.airflow.service.v1.IGetEnvironmentRequest,
    options: CallOptions,
    callback: Callback<
      protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
      | protos.google.cloud.orchestration.airflow.service.v1.IGetEnvironmentRequest
      | null
      | undefined,
      {} | null | undefined
    >
  ): void;
  getEnvironment(
    request: protos.google.cloud.orchestration.airflow.service.v1.IGetEnvironmentRequest,
    callback: Callback<
      protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
      | protos.google.cloud.orchestration.airflow.service.v1.IGetEnvironmentRequest
      | null
      | undefined,
      {} | null | undefined
    >
  ): void;
  getEnvironment(
    request?: protos.google.cloud.orchestration.airflow.service.v1.IGetEnvironmentRequest,
    optionsOrCallback?:
      | CallOptions
      | Callback<
          protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
          | protos.google.cloud.orchestration.airflow.service.v1.IGetEnvironmentRequest
          | null
          | undefined,
          {} | null | undefined
        >,
    callback?: Callback<
      protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
      | protos.google.cloud.orchestration.airflow.service.v1.IGetEnvironmentRequest
      | null
      | undefined,
      {} | null | undefined
    >
  ): Promise<
    [
      protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
      (
        | protos.google.cloud.orchestration.airflow.service.v1.IGetEnvironmentRequest
        | undefined
      ),
      {} | undefined
    ]
  > | void {
    request = request || {};
    let options: CallOptions;
    if (typeof optionsOrCallback === 'function' && callback === undefined) {
      callback = optionsOrCallback;
      options = {};
    } else {
      options = optionsOrCallback as CallOptions;
    }
    options = options || {};
    options.otherArgs = options.otherArgs || {};
    options.otherArgs.headers = options.otherArgs.headers || {};
    options.otherArgs.headers['x-goog-request-params'] =
      this._gaxModule.routingHeader.fromParams({
        name: request.name ?? '',
      });
    this.initialize();
    return this.innerApiCalls.getEnvironment(request, options, callback);
  }

  /**
   * Create a new environment.
   *
   * @param {Object} request
   *   The request object that will be sent.
   * @param {string} request.parent
   *   The parent must be of the form
   *   "projects/{projectId}/locations/{locationId}".
   * @param {google.cloud.orchestration.airflow.service.v1.Environment} request.environment
   *   The environment to create.
   * @param {object} [options]
   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
   * @returns {Promise} - The promise which resolves to an array.
   *   The first element of the array is an object representing
   *   a long running operation. Its `promise()` method returns a promise
   *   you can `await` for.
   *   Please see the
   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#long-running-operations)
   *   for more details and examples.
   * @example <caption>include:samples/generated/v1/environments.create_environment.js</caption>
   * region_tag:composer_v1_generated_Environments_CreateEnvironment_async
   */
  createEnvironment(
    request?: protos.google.cloud.orchestration.airflow.service.v1.ICreateEnvironmentRequest,
    options?: CallOptions
  ): Promise<
    [
      LROperation<
        protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | undefined,
      {} | undefined
    ]
  >;
  createEnvironment(
    request: protos.google.cloud.orchestration.airflow.service.v1.ICreateEnvironmentRequest,
    options: CallOptions,
    callback: Callback<
      LROperation<
        protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | null | undefined,
      {} | null | undefined
    >
  ): void;
  createEnvironment(
    request: protos.google.cloud.orchestration.airflow.service.v1.ICreateEnvironmentRequest,
    callback: Callback<
      LROperation<
        protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | null | undefined,
      {} | null | undefined
    >
  ): void;
  createEnvironment(
    request?: protos.google.cloud.orchestration.airflow.service.v1.ICreateEnvironmentRequest,
    optionsOrCallback?:
      | CallOptions
      | Callback<
          LROperation<
            protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
            protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
          >,
          protos.google.longrunning.IOperation | null | undefined,
          {} | null | undefined
        >,
    callback?: Callback<
      LROperation<
        protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | null | undefined,
      {} | null | undefined
    >
  ): Promise<
    [
      LROperation<
        protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | undefined,
      {} | undefined
    ]
  > | void {
    request = request || {};
    let options: CallOptions;
    if (typeof optionsOrCallback === 'function' && callback === undefined) {
      callback = optionsOrCallback;
      options = {};
    } else {
      options = optionsOrCallback as CallOptions;
    }
    options = options || {};
    options.otherArgs = options.otherArgs || {};
    options.otherArgs.headers = options.otherArgs.headers || {};
    options.otherArgs.headers['x-goog-request-params'] =
      this._gaxModule.routingHeader.fromParams({
        parent: request.parent ?? '',
      });
    this.initialize();
    return this.innerApiCalls.createEnvironment(request, options, callback);
  }
  /**
   * Check the status of the long running operation returned by `createEnvironment()`.
   * @param {String} name
   *   The operation name that will be passed.
   * @returns {Promise} - The promise which resolves to an object.
   *   The decoded operation object has result and metadata field to get information from.
   *   Please see the
   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#long-running-operations)
   *   for more details and examples.
   * @example <caption>include:samples/generated/v1/environments.create_environment.js</caption>
   * region_tag:composer_v1_generated_Environments_CreateEnvironment_async
   */
  async checkCreateEnvironmentProgress(
    name: string
  ): Promise<
    LROperation<
      protos.google.cloud.orchestration.airflow.service.v1.Environment,
      protos.google.cloud.orchestration.airflow.service.v1.OperationMetadata
    >
  > {
    const request =
      new this._gaxModule.operationsProtos.google.longrunning.GetOperationRequest(
        {name}
      );
    const [operation] = await this.operationsClient.getOperation(request);
    const decodeOperation = new this._gaxModule.Operation(
      operation,
      this.descriptors.longrunning.createEnvironment,
      this._gaxModule.createDefaultBackoffSettings()
    );
    return decodeOperation as LROperation<
      protos.google.cloud.orchestration.airflow.service.v1.Environment,
      protos.google.cloud.orchestration.airflow.service.v1.OperationMetadata
    >;
  }
  /**
   * Update an environment.
   *
   * @param {Object} request
   *   The request object that will be sent.
   * @param {string} request.name
   *   The relative resource name of the environment to update, in the form:
   *   "projects/{projectId}/locations/{locationId}/environments/{environmentId}"
   * @param {google.cloud.orchestration.airflow.service.v1.Environment} request.environment
   *   A patch environment. Fields specified by the `updateMask` will be copied
   *   from the patch environment into the environment under update.
   * @param {google.protobuf.FieldMask} request.updateMask
   *   Required. A comma-separated list of paths, relative to `Environment`, of
   *   fields to update.
   *   For example, to set the version of scikit-learn to install in the
   *   environment to 0.19.0 and to remove an existing installation of
   *   numpy, the `updateMask` parameter would include the following two
   *   `paths` values: "config.softwareConfig.pypiPackages.scikit-learn" and
   *   "config.softwareConfig.pypiPackages.numpy". The included patch
   *   environment would specify the scikit-learn version as follows:
   *
   *       {
   *         "config":{
   *           "softwareConfig":{
   *             "pypiPackages":{
   *               "scikit-learn":"==0.19.0"
   *             }
   *           }
   *         }
   *       }
   *
   *   Note that in the above example, any existing PyPI packages
   *   other than scikit-learn and numpy will be unaffected.
   *
   *   Only one update type may be included in a single request's `updateMask`.
   *   For example, one cannot update both the PyPI packages and
   *   labels in the same request. However, it is possible to update multiple
   *   members of a map field simultaneously in the same request. For example,
   *   to set the labels "label1" and "label2" while clearing "label3" (assuming
   *   it already exists), one can
   *   provide the paths "labels.label1", "labels.label2", and "labels.label3"
   *   and populate the patch environment as follows:
   *
   *       {
   *         "labels":{
   *           "label1":"new-label1-value"
   *           "label2":"new-label2-value"
   *         }
   *       }
   *
   *   Note that in the above example, any existing labels that are not
   *   included in the `updateMask` will be unaffected.
   *
   *   It is also possible to replace an entire map field by providing the
   *   map field's path in the `updateMask`. The new value of the field will
   *   be that which is provided in the patch environment. For example, to
   *   delete all pre-existing user-specified PyPI packages and
   *   install botocore at version 1.7.14, the `updateMask` would contain
   *   the path "config.softwareConfig.pypiPackages", and
   *   the patch environment would be the following:
   *
   *       {
   *         "config":{
   *           "softwareConfig":{
   *             "pypiPackages":{
   *               "botocore":"==1.7.14"
   *             }
   *           }
   *         }
   *       }
   *
   *   **Note:** Only the following fields can be updated:
   *
   *   * `config.softwareConfig.pypiPackages`
   *       * Replace all custom custom PyPI packages. If a replacement
   *         package map is not included in `environment`, all custom
   *         PyPI packages are cleared. It is an error to provide both
   *         this mask and a mask specifying an individual package.
   *   * `config.softwareConfig.pypiPackages.`packagename
   *       * Update the custom PyPI package *packagename*,
   *         preserving other packages. To delete the package, include it in
   *         `updateMask`, and omit the mapping for it in
   *         `environment.config.softwareConfig.pypiPackages`. It is an error
   *         to provide both a mask of this form and the
   *         `config.softwareConfig.pypiPackages` mask.
   *   * `labels`
   *       * Replace all environment labels. If a replacement labels map is not
   *         included in `environment`, all labels are cleared. It is an error to
   *         provide both this mask and a mask specifying one or more individual
   *         labels.
   *   * `labels.`labelName
   *       * Set the label named *labelName*, while preserving other
   *         labels. To delete the label, include it in `updateMask` and omit its
   *         mapping in `environment.labels`. It is an error to provide both a
   *         mask of this form and the `labels` mask.
   *   * `config.nodeCount`
   *       * Horizontally scale the number of nodes in the environment. An integer
   *         greater than or equal to 3 must be provided in the `config.nodeCount`
   *         field.
   *   * `config.webServerNetworkAccessControl`
   *       * Replace the environment's current `WebServerNetworkAccessControl`.
   *   * `config.databaseConfig`
   *       * Replace the environment's current `DatabaseConfig`.
   *   * `config.webServerConfig`
   *       * Replace the environment's current `WebServerConfig`.
   *   * `config.softwareConfig.airflowConfigOverrides`
   *       * Replace all Apache Airflow config overrides. If a replacement config
   *         overrides map is not included in `environment`, all config overrides
   *         are cleared.
   *         It is an error to provide both this mask and a mask specifying one or
   *         more individual config overrides.
   *   * `config.softwareConfig.airflowConfigOverrides.`section-name
   *       * Override the Apache Airflow config property *name* in the
   *         section named *section*, preserving other properties. To
   *         delete the property override, include it in `updateMask` and omit its
   *         mapping in
   *         `environment.config.softwareConfig.airflowConfigOverrides`.
   *         It is an error to provide both a mask of this form and the
   *         `config.softwareConfig.airflowConfigOverrides` mask.
   *   * `config.softwareConfig.envVariables`
   *       * Replace all environment variables. If a replacement environment
   *         variable map is not included in `environment`, all custom environment
   *         variables  are cleared.
   *         It is an error to provide both this mask and a mask specifying one or
   *         more individual environment variables.
   * @param {object} [options]
   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
   * @returns {Promise} - The promise which resolves to an array.
   *   The first element of the array is an object representing
   *   a long running operation. Its `promise()` method returns a promise
   *   you can `await` for.
   *   Please see the
   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#long-running-operations)
   *   for more details and examples.
   * @example <caption>include:samples/generated/v1/environments.update_environment.js</caption>
   * region_tag:composer_v1_generated_Environments_UpdateEnvironment_async
   */
  updateEnvironment(
    request?: protos.google.cloud.orchestration.airflow.service.v1.IUpdateEnvironmentRequest,
    options?: CallOptions
  ): Promise<
    [
      LROperation<
        protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | undefined,
      {} | undefined
    ]
  >;
  updateEnvironment(
    request: protos.google.cloud.orchestration.airflow.service.v1.IUpdateEnvironmentRequest,
    options: CallOptions,
    callback: Callback<
      LROperation<
        protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | null | undefined,
      {} | null | undefined
    >
  ): void;
  updateEnvironment(
    request: protos.google.cloud.orchestration.airflow.service.v1.IUpdateEnvironmentRequest,
    callback: Callback<
      LROperation<
        protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | null | undefined,
      {} | null | undefined
    >
  ): void;
  updateEnvironment(
    request?: protos.google.cloud.orchestration.airflow.service.v1.IUpdateEnvironmentRequest,
    optionsOrCallback?:
      | CallOptions
      | Callback<
          LROperation<
            protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
            protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
          >,
          protos.google.longrunning.IOperation | null | undefined,
          {} | null | undefined
        >,
    callback?: Callback<
      LROperation<
        protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | null | undefined,
      {} | null | undefined
    >
  ): Promise<
    [
      LROperation<
        protos.google.cloud.orchestration.airflow.service.v1.IEnvironment,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | undefined,
      {} | undefined
    ]
  > | void {
    request = request || {};
    let options: CallOptions;
    if (typeof optionsOrCallback === 'function' && callback === undefined) {
      callback = optionsOrCallback;
      options = {};
    } else {
      options = optionsOrCallback as CallOptions;
    }
    options = options || {};
    options.otherArgs = options.otherArgs || {};
    options.otherArgs.headers = options.otherArgs.headers || {};
    options.otherArgs.headers['x-goog-request-params'] =
      this._gaxModule.routingHeader.fromParams({
        name: request.name ?? '',
      });
    this.initialize();
    return this.innerApiCalls.updateEnvironment(request, options, callback);
  }
  /**
   * Check the status of the long running operation returned by `updateEnvironment()`.
   * @param {String} name
   *   The operation name that will be passed.
   * @returns {Promise} - The promise which resolves to an object.
   *   The decoded operation object has result and metadata field to get information from.
   *   Please see the
   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#long-running-operations)
   *   for more details and examples.
   * @example <caption>include:samples/generated/v1/environments.update_environment.js</caption>
   * region_tag:composer_v1_generated_Environments_UpdateEnvironment_async
   */
  async checkUpdateEnvironmentProgress(
    name: string
  ): Promise<
    LROperation<
      protos.google.cloud.orchestration.airflow.service.v1.Environment,
      protos.google.cloud.orchestration.airflow.service.v1.OperationMetadata
    >
  > {
    const request =
      new this._gaxModule.operationsProtos.google.longrunning.GetOperationRequest(
        {name}
      );
    const [operation] = await this.operationsClient.getOperation(request);
    const decodeOperation = new this._gaxModule.Operation(
      operation,
      this.descriptors.longrunning.updateEnvironment,
      this._gaxModule.createDefaultBackoffSettings()
    );
    return decodeOperation as LROperation<
      protos.google.cloud.orchestration.airflow.service.v1.Environment,
      protos.google.cloud.orchestration.airflow.service.v1.OperationMetadata
    >;
  }
  /**
   * Delete an environment.
   *
   * @param {Object} request
   *   The request object that will be sent.
   * @param {string} request.name
   *   The environment to delete, in the form:
   *   "projects/{projectId}/locations/{locationId}/environments/{environmentId}"
   * @param {object} [options]
   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
   * @returns {Promise} - The promise which resolves to an array.
   *   The first element of the array is an object representing
   *   a long running operation. Its `promise()` method returns a promise
   *   you can `await` for.
   *   Please see the
   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#long-running-operations)
   *   for more details and examples.
   * @example <caption>include:samples/generated/v1/environments.delete_environment.js</caption>
   * region_tag:composer_v1_generated_Environments_DeleteEnvironment_async
   */
  deleteEnvironment(
    request?: protos.google.cloud.orchestration.airflow.service.v1.IDeleteEnvironmentRequest,
    options?: CallOptions
  ): Promise<
    [
      LROperation<
        protos.google.protobuf.IEmpty,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | undefined,
      {} | undefined
    ]
  >;
  deleteEnvironment(
    request: protos.google.cloud.orchestration.airflow.service.v1.IDeleteEnvironmentRequest,
    options: CallOptions,
    callback: Callback<
      LROperation<
        protos.google.protobuf.IEmpty,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | null | undefined,
      {} | null | undefined
    >
  ): void;
  deleteEnvironment(
    request: protos.google.cloud.orchestration.airflow.service.v1.IDeleteEnvironmentRequest,
    callback: Callback<
      LROperation<
        protos.google.protobuf.IEmpty,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | null | undefined,
      {} | null | undefined
    >
  ): void;
  deleteEnvironment(
    request?: protos.google.cloud.orchestration.airflow.service.v1.IDeleteEnvironmentRequest,
    optionsOrCallback?:
      | CallOptions
      | Callback<
          LROperation<
            protos.google.protobuf.IEmpty,
            protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
          >,
          protos.google.longrunning.IOperation | null | undefined,
          {} | null | undefined
        >,
    callback?: Callback<
      LROperation<
        protos.google.protobuf.IEmpty,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | null | undefined,
      {} | null | undefined
    >
  ): Promise<
    [
      LROperation<
        protos.google.protobuf.IEmpty,
        protos.google.cloud.orchestration.airflow.service.v1.IOperationMetadata
      >,
      protos.google.longrunning.IOperation | undefined,
      {} | undefined
    ]
  > | void {
    request = request || {};
    let options: CallOptions;
    if (typeof optionsOrCallback === 'function' && callback === undefined) {
      callback = optionsOrCallback;
      options = {};
    } else {
      options = optionsOrCallback as CallOptions;
    }
    options = options || {};
    options.otherArgs = options.otherArgs || {};
    options.otherArgs.headers = options.otherArgs.headers || {};
    options.otherArgs.headers['x-goog-request-params'] =
      this._gaxModule.routingHeader.fromParams({
        name: request.name ?? '',
      });
    this.initialize();
    return this.innerApiCalls.deleteEnvironment(request, options, callback);
  }
  /**
   * Check the status of the long running operation returned by `deleteEnvironment()`.
   * @param {String} name
   *   The operation name that will be passed.
   * @returns {Promise} - The promise which resolves to an object.
   *   The decoded operation object has result and metadata field to get information from.
   *   Please see the
   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#long-running-operations)
   *   for more details and examples.
   * @example <caption>include:samples/generated/v1/environments.delete_environment.js</caption>
   * region_tag:composer_v1_generated_Environments_DeleteEnvironment_async
   */
  async checkDeleteEnvironmentProgress(
    name: string
  ): Promise<
    LROperation<
      protos.google.protobuf.Empty,
      protos.google.cloud.orchestration.airflow.service.v1.OperationMetadata
    >
  > {
    const request =
      new this._gaxModule.operationsProtos.google.longrunning.GetOperationRequest(
        {name}
      );
    const [operation] = await this.operationsClient.getOperation(request);
    const decodeOperation = new this._gaxModule.Operation(
      operation,
      this.descriptors.longrunning.deleteEnvironment,
      this._gaxModule.createDefaultBackoffSettings()
    );
    return decodeOperation as LROperation<
      protos.google.protobuf.Empty,
      protos.google.cloud.orchestration.airflow.service.v1.OperationMetadata
    >;
  }
  /**
   * List environments.
   *
   * @param {Object} request
   *   The request object that will be sent.
   * @param {string} request.parent
   *   List environments in the given project and location, in the form:
   *   "projects/{projectId}/locations/{locationId}"
   * @param {number} request.pageSize
   *   The maximum number of environments to return.
   * @param {string} request.pageToken
   *   The next_page_token value returned from a previous List request, if any.
   * @param {object} [options]
   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
   * @returns {Promise} - The promise which resolves to an array.
   *   The first element of the array is Array of [Environment]{@link google.cloud.orchestration.airflow.service.v1.Environment}.
   *   The client library will perform auto-pagination by default: it will call the API as many
   *   times as needed and will merge results from all the pages into this array.
   *   Note that it can affect your quota.
   *   We recommend using `listEnvironmentsAsync()`
   *   method described below for async iteration which you can stop as needed.
   *   Please see the
   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#auto-pagination)
   *   for more details and examples.
   */
  listEnvironments(
    request?: protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsRequest,
    options?: CallOptions
  ): Promise<
    [
      protos.google.cloud.orchestration.airflow.service.v1.IEnvironment[],
      protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsRequest | null,
      protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsResponse
    ]
  >;
  listEnvironments(
    request: protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsRequest,
    options: CallOptions,
    callback: PaginationCallback<
      protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsRequest,
      | protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsResponse
      | null
      | undefined,
      protos.google.cloud.orchestration.airflow.service.v1.IEnvironment
    >
  ): void;
  listEnvironments(
    request: protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsRequest,
    callback: PaginationCallback<
      protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsRequest,
      | protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsResponse
      | null
      | undefined,
      protos.google.cloud.orchestration.airflow.service.v1.IEnvironment
    >
  ): void;
  listEnvironments(
    request?: protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsRequest,
    optionsOrCallback?:
      | CallOptions
      | PaginationCallback<
          protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsRequest,
          | protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsResponse
          | null
          | undefined,
          protos.google.cloud.orchestration.airflow.service.v1.IEnvironment
        >,
    callback?: PaginationCallback<
      protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsRequest,
      | protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsResponse
      | null
      | undefined,
      protos.google.cloud.orchestration.airflow.service.v1.IEnvironment
    >
  ): Promise<
    [
      protos.google.cloud.orchestration.airflow.service.v1.IEnvironment[],
      protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsRequest | null,
      protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsResponse
    ]
  > | void {
    request = request || {};
    let options: CallOptions;
    if (typeof optionsOrCallback === 'function' && callback === undefined) {
      callback = optionsOrCallback;
      options = {};
    } else {
      options = optionsOrCallback as CallOptions;
    }
    options = options || {};
    options.otherArgs = options.otherArgs || {};
    options.otherArgs.headers = options.otherArgs.headers || {};
    options.otherArgs.headers['x-goog-request-params'] =
      this._gaxModule.routingHeader.fromParams({
        parent: request.parent ?? '',
      });
    this.initialize();
    return this.innerApiCalls.listEnvironments(request, options, callback);
  }

  /**
   * Equivalent to `method.name.toCamelCase()`, but returns a NodeJS Stream object.
   * @param {Object} request
   *   The request object that will be sent.
   * @param {string} request.parent
   *   List environments in the given project and location, in the form:
   *   "projects/{projectId}/locations/{locationId}"
   * @param {number} request.pageSize
   *   The maximum number of environments to return.
   * @param {string} request.pageToken
   *   The next_page_token value returned from a previous List request, if any.
   * @param {object} [options]
   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
   * @returns {Stream}
   *   An object stream which emits an object representing [Environment]{@link google.cloud.orchestration.airflow.service.v1.Environment} on 'data' event.
   *   The client library will perform auto-pagination by default: it will call the API as many
   *   times as needed. Note that it can affect your quota.
   *   We recommend using `listEnvironmentsAsync()`
   *   method described below for async iteration which you can stop as needed.
   *   Please see the
   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#auto-pagination)
   *   for more details and examples.
   */
  listEnvironmentsStream(
    request?: protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsRequest,
    options?: CallOptions
  ): Transform {
    request = request || {};
    options = options || {};
    options.otherArgs = options.otherArgs || {};
    options.otherArgs.headers = options.otherArgs.headers || {};
    options.otherArgs.headers['x-goog-request-params'] =
      this._gaxModule.routingHeader.fromParams({
        parent: request.parent ?? '',
      });
    const defaultCallSettings = this._defaults['listEnvironments'];
    const callSettings = defaultCallSettings.merge(options);
    this.initialize();
    return this.descriptors.page.listEnvironments.createStream(
      this.innerApiCalls.listEnvironments as GaxCall,
      request,
      callSettings
    );
  }

  /**
   * Equivalent to `listEnvironments`, but returns an iterable object.
   *
   * `for`-`await`-`of` syntax is used with the iterable to get response elements on-demand.
   * @param {Object} request
   *   The request object that will be sent.
   * @param {string} request.parent
   *   List environments in the given project and location, in the form:
   *   "projects/{projectId}/locations/{locationId}"
   * @param {number} request.pageSize
   *   The maximum number of environments to return.
   * @param {string} request.pageToken
   *   The next_page_token value returned from a previous List request, if any.
   * @param {object} [options]
   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
   * @returns {Object}
   *   An iterable Object that allows [async iteration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols).
   *   When you iterate the returned iterable, each element will be an object representing
   *   [Environment]{@link google.cloud.orchestration.airflow.service.v1.Environment}. The API will be called under the hood as needed, once per the page,
   *   so you can stop the iteration when you don't need more results.
   *   Please see the
   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#auto-pagination)
   *   for more details and examples.
   * @example <caption>include:samples/generated/v1/environments.list_environments.js</caption>
   * region_tag:composer_v1_generated_Environments_ListEnvironments_async
   */
  listEnvironmentsAsync(
    request?: protos.google.cloud.orchestration.airflow.service.v1.IListEnvironmentsRequest,
    options?: CallOptions
  ): AsyncIterable<protos.google.cloud.orchestration.airflow.service.v1.IEnvironment> {
    request = request || {};
    options = options || {};
    options.otherArgs = options.otherArgs || {};
    options.otherArgs.headers = options.otherArgs.headers || {};
    options.otherArgs.headers['x-goog-request-params'] =
      this._gaxModule.routingHeader.fromParams({
        parent: request.parent ?? '',
      });
    const defaultCallSettings = this._defaults['listEnvironments'];
    const callSettings = defaultCallSettings.merge(options);
    this.initialize();
    return this.descriptors.page.listEnvironments.asyncIterate(
      this.innerApiCalls['listEnvironments'] as GaxCall,
      request as {},
      callSettings
    ) as AsyncIterable<protos.google.cloud.orchestration.airflow.service.v1.IEnvironment>;
  }
  // --------------------
  // -- Path templates --
  // --------------------

  /**
   * Return a fully-qualified environment resource name string.
   *
   * @param {string} project
   * @param {string} location
   * @param {string} environment
   * @returns {string} Resource name string.
   */
  environmentPath(project: string, location: string, environment: string) {
    return this.pathTemplates.environmentPathTemplate.render({
      project: project,
      location: location,
      environment: environment,
    });
  }

  /**
   * Parse the project from Environment resource.
   *
   * @param {string} environmentName
   *   A fully-qualified path representing Environment resource.
   * @returns {string} A string representing the project.
   */
  matchProjectFromEnvironmentName(environmentName: string) {
    return this.pathTemplates.environmentPathTemplate.match(environmentName)
      .project;
  }

  /**
   * Parse the location from Environment resource.
   *
   * @param {string} environmentName
   *   A fully-qualified path representing Environment resource.
   * @returns {string} A string representing the location.
   */
  matchLocationFromEnvironmentName(environmentName: string) {
    return this.pathTemplates.environmentPathTemplate.match(environmentName)
      .location;
  }

  /**
   * Parse the environment from Environment resource.
   *
   * @param {string} environmentName
   *   A fully-qualified path representing Environment resource.
   * @returns {string} A string representing the environment.
   */
  matchEnvironmentFromEnvironmentName(environmentName: string) {
    return this.pathTemplates.environmentPathTemplate.match(environmentName)
      .environment;
  }

  /**
   * Terminate the gRPC channel and close the client.
   *
   * The client will no longer be usable and all future behavior is undefined.
   * @returns {Promise} A promise that resolves when the client is closed.
   */
  close(): Promise<void> {
    if (this.environmentsStub && !this._terminated) {
      return this.environmentsStub.then(stub => {
        this._terminated = true;
        stub.close();
        this.operationsClient.close();
      });
    }
    return Promise.resolve();
  }
}


text:
/*
*  ApplyFEMCurrentSource.cc:  Builds the RHS of the FE matrix for voltage sources
*
*  Written by:
*   David Weinstein, University of Utah, May 1999
*   Alexei Samsonov, March 2001
*   Frank B. Sachse, February 2006
*/

#include <Modules/Legacy/FiniteElements/ApplyFEMCurrentSource.h>
#include <Core/Datatypes/Matrix.h>
#include <Core/Datatypes/DenseColumnMatrix.h>
#include <Core/Datatypes/SparseRowMatrix.h>
#include <Core/Datatypes/MatrixTypeConversions.h>
#include <Core/Datatypes/Legacy/Field/Field.h>
#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/Legacy/Field/VMesh.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <Core/Logging/Log.h>

using namespace SCIRun;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun::Core::Logging;
using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Modules::FiniteElements;

namespace detail
{
  class ApplyFEMCurrentSourceImpl
  {
  public:
    explicit ApplyFEMCurrentSourceImpl(LegacyLoggerInterface* log) : log_(log) {}

    bool execute_dipole(FieldHandle field,
      FieldHandle source,
      DenseColumnMatrixHandle& rhs,
      SparseRowMatrixHandle& weights);

    bool execute_sources_and_sinks(FieldHandle field,
      FieldHandle source,
      VMesh::index_type sourceNode,
      VMesh::index_type sinkNode,
      DenseColumnMatrixHandle& rhs,
      MatrixHandle mapping);

    static bool ud_pair_less(const std::pair<index_type, double> &a,
      const std::pair<index_type, double> &b)
    {
      return a.first < b.first;
    }

  private:
    LegacyLoggerInterface* log_;
  };
}

MODULE_INFO_DEF(ApplyFEMCurrentSource, FiniteElements, SCIRun)
const AlgorithmParameterName ApplyFEMCurrentSource::SourceNode("SourceNode");
const AlgorithmParameterName ApplyFEMCurrentSource::SinkNode("SinkNode");
const AlgorithmParameterName ApplyFEMCurrentSource::ModelType("ModelType");

ApplyFEMCurrentSource::ApplyFEMCurrentSource() : Module(staticInfo_)
{
  INITIALIZE_PORT(Mesh);
  INITIALIZE_PORT(Sources);
  INITIALIZE_PORT(Mapping);
  INITIALIZE_PORT(Input_RHS);
  INITIALIZE_PORT(Output_RHS);
  INITIALIZE_PORT(Output_Weights);
}

void ApplyFEMCurrentSource::setStateDefaults()
{
  auto state = get_state();
  state->setValue(SourceNode, 0);
  state->setValue(SinkNode, 1);
  state->setValue(ModelType, std::string("dipole"));
}

bool detail::ApplyFEMCurrentSourceImpl::execute_dipole(FieldHandle field,
  FieldHandle source,
  DenseColumnMatrixHandle& rhs,
  SparseRowMatrixHandle& weights)
{
  if (!field)
  {
    log_->error("No input field");
    return (false);
  }

  if (!source)
  {
    log_->error("No source field");
    return (false);
  }

  VMesh* mesh = field->vmesh();

  mesh->synchronize(Mesh::ELEM_LOCATE_E);
  VMesh::Node::size_type nsize = mesh->num_nodes();
  VMesh::Elem::size_type sz    = mesh->num_elems();

  VMesh::Node::array_type nodes;

  mesh->size(sz);

  // Create new RHS matrix
  if (!rhs)
  {
    rhs.reset(new DenseColumnMatrix(nsize));
    rhs->setZero();
  }
  else
  {
    rhs.reset(rhs->clone());
  }

  FieldInformation fi(source);
  if (!fi.is_vector())
  {
    log_->error("Source field does not contain vectors");
    return (false);
  }

  if (!(fi.is_constantdata()) && !(fi.is_lineardata()))
  {
    log_->error("Source field needs to have vectors at the nodes or elements");
    return (false);
  }

  VMesh*  smesh = source->vmesh();
  VField* sfield = source->vfield();

  VField::size_type num_svalues = sfield->num_values();
  VMesh::Elem::index_type loc;
  VMesh::coords_type coords;
  Vector dir;
  double Ji[9];
  StackVector<double,3> grad;
  std::vector<double> dweights;
  std::vector<std::pair<index_type, double> > weightsVec;

  double* rhs_data = rhs->data();

  for (VField::index_type idx=0; idx < num_svalues; idx++)
  {
    // Position of the dipole.
    Point pos;
    if (sfield->basis_order() == 0) smesh->get_center(pos,VMesh::Elem::index_type(idx));
    else smesh->get_center(pos,VMesh::Node::index_type(idx));

    sfield->get_value(dir,idx);

    if (mesh->locate(loc, coords, pos))
    {
      LOG_DEBUG("Source pos=" << pos << " dir=" << dir << " found in elem " << loc <<std::endl);

      if (fabs(dir.x()) > 0.000001)
      {
        weightsVec.push_back(std::make_pair(loc*3+0, dir.x()));
      }
      if (fabs(dir.y()) > 0.000001)
      {
        weightsVec.push_back(std::make_pair(loc*3+1, dir.y()));
      }
      if (fabs(dir.z()) > 0.000001)
      {
        weightsVec.push_back(std::make_pair(loc*3+2, dir.z()));
      }

      mesh->inverse_jacobian(coords,loc,Ji);
      mesh->get_derivate_weights(coords,dweights,1);
      mesh->get_nodes(nodes,loc);
      int numnodes = nodes.size();

      int dim = mesh->dimensionality();

      if (dim == 3)
      {
        for(int i=0; i<numnodes; i++)
        {
          grad[0] = dweights[i]*Ji[0]+dweights[i+numnodes]*Ji[1]+dweights[i+2*numnodes]*Ji[2];
          grad[1] = dweights[i]*Ji[3]+dweights[i+numnodes]*Ji[4]+dweights[i+2*numnodes]*Ji[5];
          grad[2] = dweights[i]*Ji[6]+dweights[i+numnodes]*Ji[7]+dweights[i+2*numnodes]*Ji[8];

          rhs_data[nodes[i]] += grad[0]*dir.x() + grad[1]*dir.y() + grad[2]*dir.z();
        }
      }
      else if (dim == 2)
      {
        for(int i=0; i<numnodes; i++)
        {
          grad[0] = dweights[i]*Ji[0]+dweights[i+numnodes]*Ji[1];
          grad[1] = dweights[i]*Ji[3]+dweights[i+numnodes]*Ji[4];
          grad[2] = dweights[i]*Ji[6]+dweights[i+numnodes]*Ji[7];

          rhs_data[nodes[i]] += grad[0]*dir.x() + grad[1]*dir.y() + grad[2]*dir.z();
        }
      }
      else if (dim == 1)
      {
        for(int i=0; i<numnodes; i++)
        {
          grad[0] = dweights[i]*Ji[0];
          grad[1] = dweights[i]*Ji[3];
          grad[2] = dweights[i]*Ji[6];
          rhs_data[nodes[i]] += grad[0]*dir.x() + grad[1]*dir.y() + grad[2]*dir.z();
        }
      }

    }
    else
    {
      log_->error("Dipole not located within mesh");
      return (false);
    }
  }

#ifdef SCIRUN4_CODE_TO_BE_ENABLED_LATER
  SparseRowMatrix::Data sparseData(2, weights.size());
  const SparseRowMatrix::Rows& rr = sparseData.rows();
  const SparseRowMatrix::Columns& cc = sparseData.columns();
  const SparseRowMatrix::Storage& dd = sparseData.data();

  rr[0] = 0; rr[1] = static_cast<index_type>(weights.size());

  std::sort(weights.begin(), weights.end(), ud_pair_less);

  for (size_t i=0; i < weights.size(); i++)
  {
    cc[i] = weights[i].first;
    dd[i] = weights[i].second;
  }

  hWeights = new SparseRowMatrix(1, 3*sz, sparseData, static_cast<size_type>(weights.size()));

  return hWeights != nullptr;
#endif
  return true;
}

bool detail::ApplyFEMCurrentSourceImpl::execute_sources_and_sinks(FieldHandle field,
  FieldHandle source,
  VMesh::index_type sourceNode,
  VMesh::index_type sinkNode,
  DenseColumnMatrixHandle& rhs,
  MatrixHandle mapping)
{
  if (!field)
  {
    log_->error("No input field");
    return (false);
  }

  VMesh* mesh = field->vmesh();
  VMesh::Node::size_type nsize = mesh->num_nodes();

  // Create new RHS matrix
  if (!rhs)
  {
    rhs.reset(new DenseColumnMatrix(nsize));
    rhs->setZero();
  }
  else
  {
    rhs.reset(rhs->clone());
  }

  mesh->synchronize(Mesh::ELEM_LOCATE_E);

  // if we have an Mapping matrix and a Source field and all types are good,
  // hCurField will be valid after this block

  if (mapping && source)
  {
    FieldInformation fi(source);

    if (!(fi.is_scalar()))
    {
      log_->error("Can only use a field with scalar values as source when using an Mapping matrix and a Source field -- this mode is for specifying current densities");
      return (false);
    }

    if (source->vfield()->num_values() != mapping->nrows())
    {
      log_->error("Source field and Mapping matrix size mismatch.");
      return (false);
    }
    if (static_cast<unsigned int>(nsize) != static_cast<unsigned int>(mapping->ncols()))
    {
      log_->error("Mesh field and Mapping matrix size mismatch.");
      return (false);
    }
  }

  // if we have don't have a Mapping matrix, use the source/sink indices
  // directly as volume nodes

  // if we do have a Mapping matrix, but we don't have a Source field,
  // then the source/sink indices refer to the PointCloud, so use the
  // Mapping matrix to get their corresponding volume node indices.

  // if we have a Mapping matrix AND a Source field, then ignore the
  // source/sink indices.  The Mapping matrix defines how the PointCloud
  //  nodes map to volume mesh nodes, and the Source field gives a
  // scalar quantity (current density) for each source.

  double* rhs_data = rhs->data();

  if (!mapping || !matrixIs::sparse(mapping))
  {
    if (sourceNode >= nsize || sinkNode >= nsize)
    {
      log_->error("SourceNode or SinkNode was out of mesh range.");
      return (false);
    }
    rhs_data[sourceNode] += -1.0;
    rhs_data[sinkNode] += 1.0;

    return (true);
  }

  SparseRowMatrixHandle sparseMapping = castMatrix::toSparse(mapping);

  if (!source)
  {
    if (sourceNode < mapping->nrows() &&
      sinkNode < mapping->nrows())
    {
      index_type *cc;
      double *vv;
      index_type ccsize;
      sparseMapping->getRowNonzerosNoCopy(sourceNode, ccsize, cc, vv);
      sourceNode = cc?cc[0]:0;
      sparseMapping->getRowNonzerosNoCopy(sinkNode, ccsize, cc, vv);
      sinkNode = cc?cc[0]:0;
    }
    else
    {
      log_->error("SourceNode or SinkNode was out of mapping range.");
      return (false);
    }
    rhs_data[sourceNode] += -1.0;
    rhs_data[sinkNode] += 1.0;

    return(true);
  }

  VField* pfield = source->vfield();
  VMesh* pmesh = source->vmesh();
  VMesh::size_type num_nodes = pmesh->num_nodes();

  for (VMesh::index_type idx=0; idx < num_nodes; idx++)
  {
    double currentDensity;
    pfield->get_value(currentDensity, idx);

    index_type *cc;
    double *vv;
    index_type ccsize;

    sparseMapping->getRowNonzerosNoCopy(idx, ccsize, cc, vv);

    for (size_type j=0; j < ccsize; j++)
    {
      rhs_data[cc?cc[j]:j] += vv[j] * currentDensity;
    }
  }

  return (true);
}

void ApplyFEMCurrentSource::execute()
{
  auto state = get_state();
  auto modelType = state->getValue(ModelType).toString();
  bool dipole = (modelType == "dipole");

  auto field = getRequiredInput(Mesh);
  auto sourceOption = getOptionalInput(Sources);

  SparseRowMatrixHandle weights;
  DenseColumnMatrixHandle RHS;
  auto RHSoption = getOptionalInput(Input_RHS);
  if (RHSoption)
    RHS = castMatrix::toColumn(*RHSoption);

  if (needToExecute())
  {
    detail::ApplyFEMCurrentSourceImpl impl(this);
    if (dipole)
    {
      if (!impl.execute_dipole(field, sourceOption.get_value_or(nullptr), RHS, weights))
        return;
    }
    else
    {
      auto mapping = getOptionalInput(Mapping);
      if(!impl.execute_sources_and_sinks(field,
        sourceOption.get_value_or(nullptr),
        state->getValue(SourceNode).toInt(),
        state->getValue(SinkNode).toInt(),
        RHS, mapping.get_value_or(nullptr)))
        return;
    }

    sendOutput(Output_RHS, RHS);
#ifdef SCIRUN4_CODE_TO_BE_ENABLED_LATER
    if (weights)
      sendOutput(Output_Weights, weights);
#endif
  }
}

redpajama_set_name: RedPajamaGithub


text:
import os

import fixtures
from tempest.lib.common.utils import data_utils

from openstackclient.tests.functional import base

BASIC_LIST_HEADERS = ['ID', 'Name']
SYSTEM_CLOUD = os.environ.get('OS_SYSTEM_CLOUD', 'devstack-system-admin')

class IdentityTests(base.TestCase):
    """Functional tests for Identity commands. """

    DOMAIN_FIELDS = ['description', 'enabled', 'id', 'name']
    GROUP_FIELDS = ['description', 'domain_id', 'id', 'name']
    TOKEN_FIELDS = ['expires', 'id', 'project_id', 'user_id']
    USER_FIELDS = ['email', 'enabled', 'id', 'name', 'name',
                   'domain_id', 'default_project_id', 'description',
                   'password_expires_at']
    PROJECT_FIELDS = ['description', 'id', 'domain_id', 'is_domain',
                      'enabled', 'name', 'parent_id']
    ROLE_FIELDS = ['id', 'name', 'domain_id']
    SERVICE_FIELDS = ['id', 'enabled', 'name', 'type', 'description']
    REGION_FIELDS = ['description', 'enabled', 'parent_region', 'region']
    ENDPOINT_FIELDS = ['id', 'region', 'region_id', 'service_id',
                       'service_name', 'service_type', 'enabled',
                       'interface', 'url']

    REGION_LIST_HEADERS = ['Region', 'Parent Region', 'Description']
    ENDPOINT_LIST_HEADERS = ['ID', 'Region', 'Service Name', 'Service Type',
                             'Enabled', 'Interface', 'URL']
    ENDPOINT_LIST_PROJECT_HEADERS = ['ID', 'Name']

    IDENTITY_PROVIDER_FIELDS = ['description', 'enabled', 'id', 'remote_ids',
                                'domain_id']
    IDENTITY_PROVIDER_LIST_HEADERS = ['ID', 'Enabled', 'Description']

    SERVICE_PROVIDER_FIELDS = ['auth_url', 'description', 'enabled',
                               'id', 'relay_state_prefix', 'sp_url']
    SERVICE_PROVIDER_LIST_HEADERS = ['ID', 'Enabled', 'Description',
                                     'Auth URL']
    IMPLIED_ROLE_LIST_HEADERS = ['Prior Role ID', 'Prior Role Name',
                                 'Implied Role ID', 'Implied Role Name']
    REGISTERED_LIMIT_FIELDS = ['id', 'service_id', 'resource_name',
                               'default_limit', 'description', 'region_id']
    REGISTERED_LIMIT_LIST_HEADERS = ['ID', 'Service ID', 'Resource Name',
                                     'Default Limit', 'Description',
                                     'Region ID']
    LIMIT_FIELDS = ['id', 'project_id', 'service_id', 'resource_name',
                    'resource_limit', 'description', 'region_id']
    LIMIT_LIST_HEADERS = ['ID', 'Project ID', 'Service ID', 'Resource Name',
                          'Resource Limit', 'Description', 'Region ID']

    @classmethod
    def setUpClass(cls):
        super(IdentityTests, cls).setUpClass()
        # create dummy domain
        cls.domain_name = data_utils.rand_name('TestDomain')
        cls.domain_description = data_utils.rand_name('description')
        cls.openstack(
            '--os-identity-api-version 3 '
            'domain create '
            '--description %(description)s '
            '--enable '
            '%(name)s' % {'description': cls.domain_description,
                          'name': cls.domain_name})

        # create dummy project
        cls.project_name = data_utils.rand_name('TestProject')
        cls.project_description = data_utils.rand_name('description')
        cls.openstack(
            '--os-identity-api-version 3 '
            'project create '
            '--domain %(domain)s '
            '--description %(description)s '
            '--enable '
            '%(name)s' % {'domain': cls.domain_name,
                          'description': cls.project_description,
                          'name': cls.project_name})

    @classmethod
    def tearDownClass(cls):
        try:
            # delete dummy project
            cls.openstack('--os-identity-api-version 3 '
                          'project delete %s' % cls.project_name)
            # disable and delete dummy domain
            cls.openstack('--os-identity-api-version 3 '
                          'domain set --disable %s' % cls.domain_name)
            cls.openstack('--os-identity-api-version 3 '
                          'domain delete %s' % cls.domain_name)
        finally:
            super(IdentityTests, cls).tearDownClass()

    def setUp(self):
        super(IdentityTests, self).setUp()
        # prepare v3 env
        ver_fixture = fixtures.EnvironmentVariable(
            'OS_IDENTITY_API_VERSION', '3')
        self.useFixture(ver_fixture)
        auth_url = os.environ.get('OS_AUTH_URL')
        if auth_url:
            auth_url_fixture = fixtures.EnvironmentVariable(
                'OS_AUTH_URL', auth_url.replace('v2.0', 'v3')
            )
            self.useFixture(auth_url_fixture)

    def _create_dummy_user(self, add_clean_up=True):
        username = data_utils.rand_name('TestUser')
        password = data_utils.rand_name('password')
        email = data_utils.rand_name() + '@example.com'
        description = data_utils.rand_name('description')
        raw_output = self.openstack(
            'user create '
            '--domain %(domain)s '
            '--project %(project)s '
            '--project-domain %(project_domain)s '
            '--password %(password)s '
            '--email %(email)s '
            '--description %(description)s '
            '--enable '
            '%(name)s' % {'domain': self.domain_name,
                          'project': self.project_name,
                          'project_domain': self.domain_name,
                          'email': email,
                          'password': password,
                          'description': description,
                          'name': username})
        if add_clean_up:
            self.addCleanup(
                self.openstack,
                'user delete %s' % self.parse_show_as_object(raw_output)['id'])
        items = self.parse_show(raw_output)
        self.assert_show_fields(items, self.USER_FIELDS)
        return username

    def _create_dummy_role(self, add_clean_up=True):
        role_name = data_utils.rand_name('TestRole')
        raw_output = self.openstack('role create %s' % role_name)
        role = self.parse_show_as_object(raw_output)
        if add_clean_up:
            self.addCleanup(
                self.openstack,
                'role delete %s' % role['id'])
        items = self.parse_show(raw_output)
        self.assert_show_fields(items, self.ROLE_FIELDS)
        self.assertEqual(role_name, role['name'])
        return role_name

    def _create_dummy_implied_role(self, add_clean_up=True):
        role_name = self._create_dummy_role(add_clean_up)
        implied_role_name = self._create_dummy_role(add_clean_up)
        self.openstack(
            'implied role create '
            '--implied-role %(implied_role)s '
            '%(role)s' % {'implied_role': implied_role_name,
                          'role': role_name})

        return implied_role_name, role_name

    def _create_dummy_group(self, add_clean_up=True):
        group_name = data_utils.rand_name('TestGroup')
        description = data_utils.rand_name('description')
        raw_output = self.openstack(
            'group create '
            '--domain %(domain)s '
            '--description %(description)s '
            '%(name)s' % {'domain': self.domain_name,
                          'description': description,
                          'name': group_name})
        if add_clean_up:
            self.addCleanup(
                self.openstack,
                'group delete '
                '--domain %(domain)s '
                '%(name)s' % {'domain': self.domain_name,
                              'name': group_name})
        items = self.parse_show(raw_output)
        self.assert_show_fields(items, self.GROUP_FIELDS)
        return group_name

    def _create_dummy_domain(self, add_clean_up=True):
        domain_name = data_utils.rand_name('TestDomain')
        domain_description = data_utils.rand_name('description')
        self.openstack(
            'domain create '
            '--description %(description)s '
            '--enable %(name)s' % {'description': domain_description,
                                   'name': domain_name})
        if add_clean_up:
            self.addCleanup(
                self.openstack,
                'domain delete %s' % domain_name
            )
            self.addCleanup(
                self.openstack,
                'domain set --disable %s' % domain_name
            )
        return domain_name

    def _create_dummy_project(self, add_clean_up=True):
        project_name = data_utils.rand_name('TestProject')
        project_description = data_utils.rand_name('description')
        self.openstack(
            'project create '
            '--domain %(domain)s '
            '--description %(description)s '
            '--enable %(name)s' % {'domain': self.domain_name,
                                   'description': project_description,
                                   'name': project_name})
        if add_clean_up:
            self.addCleanup(
                self.openstack,
                'project delete '
                '--domain %(domain)s '
                '%(name)s' % {'domain': self.domain_name,
                              'name': project_name})
        return project_name

    def _create_dummy_region(self, parent_region=None, add_clean_up=True):
        region_id = data_utils.rand_name('TestRegion')
        description = data_utils.rand_name('description')
        parent_region_arg = ''
        if parent_region is not None:
            parent_region_arg = '--parent-region %s' % parent_region
        raw_output = self.openstack(
            'region create '
            '%(parent_region_arg)s '
            '--description %(description)s '
            '%(id)s' % {'parent_region_arg': parent_region_arg,
                        'description': description,
                        'id': region_id})
        if add_clean_up:
            self.addCleanup(self.openstack,
                            'region delete %s' % region_id)
        items = self.parse_show(raw_output)
        self.assert_show_fields(items, self.REGION_FIELDS)
        return region_id

    def _create_dummy_service(self, add_clean_up=True):
        service_name = data_utils.rand_name('TestService')
        description = data_utils.rand_name('description')
        type_name = data_utils.rand_name('TestType')
        raw_output = self.openstack(
            'service create '
            '--name %(name)s '
            '--description %(description)s '
            '--enable '
            '%(type)s' % {'name': service_name,
                          'description': description,
                          'type': type_name})
        if add_clean_up:
            service = self.parse_show_as_object(raw_output)
            self.addCleanup(self.openstack,
                            'service delete %s' % service['id'])
        items = self.parse_show(raw_output)
        self.assert_show_fields(items, self.SERVICE_FIELDS)
        return service_name

    def _create_dummy_endpoint(self, interface='public', add_clean_up=True):
        region_id = self._create_dummy_region()
        service_name = self._create_dummy_service()
        endpoint_url = data_utils.rand_url()
        raw_output = self.openstack(
            'endpoint create '
            '--region %(region)s '
            '--enable '
            '%(service)s '
            '%(interface)s '
            '%(url)s' % {'region': region_id,
                         'service': service_name,
                         'interface': interface,
                         'url': endpoint_url})
        endpoint = self.parse_show_as_object(raw_output)
        if add_clean_up:
            self.addCleanup(
                self.openstack,
                'endpoint delete %s' % endpoint['id'])
        items = self.parse_show(raw_output)
        self.assert_show_fields(items, self.ENDPOINT_FIELDS)
        return endpoint['id']

    def _create_dummy_idp(self, add_clean_up=True):
        identity_provider = data_utils.rand_name('IdentityProvider')
        description = data_utils.rand_name('description')
        raw_output = self.openstack(
            'identity provider create '
            ' %(name)s '
            '--description %(description)s '
            '--enable ' % {'name': identity_provider,
                           'description': description})
        if add_clean_up:
            self.addCleanup(
                self.openstack,
                'identity provider delete %s' % identity_provider)
        items = self.parse_show(raw_output)
        self.assert_show_fields(items, self.IDENTITY_PROVIDER_FIELDS)
        return identity_provider

    def _create_dummy_sp(self, add_clean_up=True):
        service_provider = data_utils.rand_name('ServiceProvider')
        description = data_utils.rand_name('description')
        raw_output = self.openstack(
            'service provider create '
            ' %(name)s '
            '--description %(description)s '
            '--auth-url https://sp.example.com:35357 '
            '--service-provider-url https://sp.example.com:5000 '
            '--enable ' % {'name': service_provider,
                           'description': description})
        if add_clean_up:
            self.addCleanup(
                self.openstack,
                'service provider delete %s' % service_provider)
        items = self.parse_show(raw_output)
        self.assert_show_fields(items, self.SERVICE_PROVIDER_FIELDS)
        return service_provider

    def _create_dummy_registered_limit(self, add_clean_up=True):
        service_name = self._create_dummy_service()
        resource_name = data_utils.rand_name('resource_name')
        params = {
            'service_name': service_name,
            'default_limit': 10,
            'resource_name': resource_name
        }
        raw_output = self.openstack(
            'registered limit create'
            ' --service %(service_name)s'
            ' --default-limit %(default_limit)s'
            ' %(resource_name)s' % params,
            cloud=SYSTEM_CLOUD
        )
        items = self.parse_show(raw_output)
        registered_limit_id = self._extract_value_from_items('id', items)

        if add_clean_up:
            self.addCleanup(
                self.openstack,
                'registered limit delete %s' % registered_limit_id,
                cloud=SYSTEM_CLOUD
            )

        self.assert_show_fields(items, self.REGISTERED_LIMIT_FIELDS)
        return registered_limit_id

    def _extract_value_from_items(self, key, items):
        for d in items:
            for k, v in d.items():
                if k == key:
                    return v

    def _create_dummy_limit(self, add_clean_up=True):
        registered_limit_id = self._create_dummy_registered_limit()

        raw_output = self.openstack(
            'registered limit show %s' % registered_limit_id,
            cloud=SYSTEM_CLOUD
        )
        items = self.parse_show(raw_output)
        resource_name = self._extract_value_from_items('resource_name', items)
        service_id = self._extract_value_from_items('service_id', items)
        resource_limit = 15

        project_name = self._create_dummy_project()
        raw_output = self.openstack('project show %s' % project_name)
        items = self.parse_show(raw_output)
        project_id = self._extract_value_from_items('id', items)

        params = {
            'project_id': project_id,
            'service_id': service_id,
            'resource_name': resource_name,
            'resource_limit': resource_limit
        }

        raw_output = self.openstack(
            'limit create'
            ' --project %(project_id)s'
            ' --service %(service_id)s'
            ' --resource-limit %(resource_limit)s'
            ' %(resource_name)s' % params,
            cloud=SYSTEM_CLOUD
        )
        items = self.parse_show(raw_output)
        limit_id = self._extract_value_from_items('id', items)

        if add_clean_up:
            self.addCleanup(
                self.openstack, 'limit delete %s' % limit_id,
                cloud=SYSTEM_CLOUD
            )

        self.assert_show_fields(items, self.LIMIT_FIELDS)
        return limit_id


text:
. ./scripts/planetlab/pl-common.sh

# TOPOLOGY
DCS[0]=${EC2_PROD_EU_MICRO[0]}
DCSEQ[0]=${EC2_PROD_EU_MICRO[0]}

#DCS[1]=${EC2_PROD_EU_MICRO[1]}
#DCSEQ[1]=${EC2_PROD_EU_MICRO[1]}

DC_CLIENTS=("${PLANETLAB_NODES[@]}")

MACHINES="${DCS[*]} ${DCSEQ[*]} ${DC_CLIENTS[*]}"
INIT_DB_DC=${DCS[0]}
INIT_DB_CLIENT=${DC_CLIENTS[0]}

# INPUT DATA PARAMS
INPUT_USERS=1500
INPUT_ACTIVE_USERS=10
INPUT_USER_FRIENDS=25
INPUT_USER_BIASED_OPS=9
INPUT_USER_RANDOM_OPS=1
INPUT_USER_OPS_GROUPS=500
FILE_USERS=input/users.txt
FILE_CMDS_PREFIX=input/commands.txt

# BENCHMARK PARAMS
NOTIFICATIONS=false
ISOLATION=REPEATABLE_READS
CACHING=CACHED
CACHE_EVICTION_TIME_MS=5000 #120000
ASYNC_COMMIT=false
THINK_TIME_MS=0
MAX_CONCURRENT_SESSIONS_PER_JVM=5

DC_NUMBER=${#DCS[@]}
CLIENTS_NUMBER=${#DC_CLIENTS[@]}

echo "DCS: " $DC_NUMBER "CLIENTS: " $CLIENTS_NUMBER

echo "==== KILLING EXISTING SERVERS AND CLIENTS ===="
. scripts/planetlab/pl-kill.sh $MACHINES
echo "==== DONE ===="

sleep 10

ant -buildfile smd-jar-build.xml

if [ ! -f "$JAR" ]; then
echo "file $JAR not found" && exit 1
fi

# DEPLOY STUFF?
DEPLOY=true

# run_swift_client_initdb <client> <server> <users_file>
run_swift_client_initdb() {
	client=$1
	server=$2
	input_file=$3
	swift_app_cmd swift.application.social.SwiftSocialBenchmark init $server users.txt
	run_cmd $client $CMD
}

# run_swift_client_bg <client> <server> <cmds_file>
run_swift_client_bg() {
	client=$1
	server=$2
	input_file=$3
	swift_app_cmd_nostdout -Xmx256m -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.port=7777 -Djava.rmi.server.hostname=$client swift.application.social.SwiftSocialBenchmark run $server commands.txt $ISOLATION $CACHING $CACHE_EVICTION_TIME_MS $NOTIFICATIONS $ASYNC_COMMIT $THINK_TIME_MS $MAX_CONCURRENT_SESSIONS_PER_JVM
	run_cmd_bg $client $CMD
}

#echo "==== PREPROCESSING INPUT PARAMETERS ===="
#if [ "${!DCS[*]}" != "${!DC_CLIENTS[*]}" ]; then
#	echo "Error: DCs configuration does not match clients configuration"
#	exit 1
#fi

echo "==== GENERATING INPUT DATA - GENERATING USERS DB ===="
mkdir -p input/
scripts/planetlab/create_users.py 0 $INPUT_USERS $FILE_USERS
echo "==== GENERATING INPUT DATA - GENERATING COMMANDS ===="
scripts/planetlab/gen_commands_local.py $FILE_USERS $INPUT_USER_FRIENDS $INPUT_USER_BIASED_OPS $INPUT_USER_RANDOM_OPS $INPUT_USER_OPS_GROUPS $CLIENTS_NUMBER $INPUT_ACTIVE_USERS $FILE_CMDS_PREFIX

echo "==== DEPLOYING SWIFTCLOUD BINARIES ===="
if [ -n "$DEPLOY" ]; then
	deploy_swift_on_many $MACHINES
	echo "==== COPYING DB OF USERS ===="
	copy_to_bg $FILE_USERS $INIT_DB_CLIENT users.txt
	copy_pids="$!"
	echo "==== SCATTERING WORKLOAD DEFINITIONS TO THE CLIENTS ===="
	i=0
	for client in ${DC_CLIENTS[*]}; do
		copy_to_bg $FILE_CMDS_PREFIX-$i $client commands.txt
#		copy_pids="$copy_pids $!"
		i=$(($i+1))
	done
	echo "==== AWAITING TRANSFERS COMPLETION ===="
	echo "PIDS:" + $copy_pids
#	wait $copy_pids
fi

echo "==== STARTING SEQUENCERS AND DC SERVERS ===="
scripts/planetlab/pl-start-servers-ds-seq.sh
servers_start DCS DCSEQ

echo "==== WAITING A BIT BEFORE INITIALIZING DATABASE ===="
sleep 30

echo "==== INITIALIZING DATABASE ===="
echo "CLIENT" + $INIT_DB_CLIENT, "SERVER" + $INIT_DB_DC
run_swift_client_initdb $INIT_DB_CLIENT $INIT_DB_DC users.txt

echo "==== WAITING A BIT BEFORE STARTING REAL CLIENTS ===="
sleep 30

echo "DCS: " $DC_NUMBER "CLIENTS: " $CLIENTS_NUMBER

client_pids=""

#for i in ${!DCS[*]}; do
#	echo "==== STARTING CLIENTS CONNECTING to DC$i ===="
#	for client in ${DC_CLIENTS[$i]}; do
#		run_swift_client_bg "$client" "${DCS[$i]}"
#		client_pids="$client_pids $!"
#	done
#done

i=0;
for client in ${DC_CLIENTS[*]}; do
	j=$(($i % $DC_NUMBER))
	CLIENT_DC=${DCS[$j]}
	echo "==== STARTING CLIENT Nº $i @ $client CONNECTING TO $CLIENT_DC ===="
		run_swift_client_bg "$client" "$CLIENT_DC"
		client_pids="$client_pids $!"
		i=$(($i+1))
done

echo "==== RUNNING... ===="
wait $client_pids

echo "==== KILLING SERVERS AND CLIENTS ===="
scripts/planetlab/pl-kill.sh $MACHINES

echo "==== COLLECTING CLIENT LOGS AS RESULTS ===="
output_prefix=results/result-social-$ISOLATION-$CACHING-$NOTIFICATIONS-$CACHE_EVICTION_TIME_MS-$ASYNC_COMMIT-$THINK_TIME_MS.log
for client in ${DC_CLIENTS[*]}; do
	copy_from $client stdout.txt $output_prefix.$client
done


text:
class Subdomain
  def self.matches?(request)
    case request.subdomain
    when 'www', '', nil
      false
    else
      true
    end
  end
end


text:
@implementation MATwitterAccountUpdateDeliveryDevice

@end


text:
package com.centurylink.mdw.workflow.activity.process;

import com.centurylink.mdw.activity.types.FinishActivity;
import com.centurylink.mdw.annotations.Activity;
import com.centurylink.mdw.model.event.EventType;
import com.centurylink.mdw.util.log.StandardLogger.LogLevel;
import com.centurylink.mdw.util.timer.Tracked;
import com.centurylink.mdw.workflow.activity.DefaultActivityImpl;

/**
 * Base class for all the ProcessFinish Controlled Activity
 * This class will be extended by the custom ProcessFinish activity
 */
@Tracked(LogLevel.TRACE)
@Activity(value="Process Stop", category=FinishActivity.class, icon="shape:stop",
        pagelet="com.centurylink.mdw.base/processFinish.pagelet")
public class ProcessFinishActivity extends DefaultActivityImpl implements FinishActivity {

    private static final String ATTRIBUTE_COMPLETION_CODE = "CompletionCode";
    private static final String ATTRIBUTE_TERMINATION_ACTION = "TerminationAction";
    private static final String ATTRIBUTE_NO_NOTIFY = "DoNotNotifyCaller";

//    private static final String ATTRVALUE_DEFAULT = "Default";
    private static final String ATTRVALUE_COMPLETE_PROCESS = "Complete Process";
    private static final String ATTRVALUE_CANCEL_PROCESS = "Cancel Process";

    /**
     * Default constructor with params
     */
    public ProcessFinishActivity(){
        super();
    }

    public String getProcessCompletionCode() {
        String av = this.getAttributeValue(ATTRIBUTE_TERMINATION_ACTION);
        if (av==null) return null;
        if (av.equals(ATTRVALUE_COMPLETE_PROCESS)) {
            av = this.getAttributeValue(ATTRIBUTE_COMPLETION_CODE);
            return EventType.EVENTNAME_FINISH + (av==null?"":(":" + av));
        } else if (av.equals(ATTRVALUE_CANCEL_PROCESS)) {
            return EventType.EVENTNAME_ABORT + ":process";
        } else return null;
    }

    public boolean doNotNotifyCaller() {
        return "true".equalsIgnoreCase(this.getAttributeValue(ATTRIBUTE_NO_NOTIFY));
    }

}


text:
using hyperdex::pending_atomic;

pending_atomic :: pending_atomic(uint64_t id,
                                 hyperdex_client_returncode* status)
    : pending(id, status)
    , m_state(INITIALIZED)
{
}

pending_atomic :: ~pending_atomic() throw ()
{
}

bool
pending_atomic :: can_yield()
{
    assert(m_state == RECV || m_state == YIELDED);
    return m_state == RECV;
}

bool
pending_atomic :: yield(hyperdex_client_returncode* status, e::error* err)
{
    *status = HYPERDEX_CLIENT_SUCCESS;
    *err = e::error();
    m_state = YIELDED;
    return true;
}

void
pending_atomic :: handle_sent_to(const server_id&,
                                 const virtual_server_id&)
{
    assert(m_state == INITIALIZED);
    m_state = SENT;
}

void
pending_atomic :: handle_failure(const server_id& si,
                                 const virtual_server_id& vsi)
{
    assert(m_state == SENT);
    m_state = RECV;
    PENDING_ERROR(RECONFIGURE) << "reconfiguration affecting "
                               << vsi << "/" << si;
}

bool
pending_atomic :: handle_message(client*,
                                 const server_id& si,
                                 const virtual_server_id& vsi,
                                 network_msgtype mt,
                                 std::auto_ptr<e::buffer> msg,
                                 e::unpacker up,
                                 hyperdex_client_returncode* status,
                                 e::error* err)
{
    m_state = RECV;
    *status = HYPERDEX_CLIENT_SUCCESS;
    *err = e::error();

    if (mt != RESP_ATOMIC)
    {
        PENDING_ERROR(SERVERERROR) << "server " << vsi << " responded to ATOMIC with " << mt;
        return true;
    }

    uint16_t response;
    up = up >> response;

    if (up.error())
    {
        PENDING_ERROR(SERVERERROR) << "communication error: server "
                                   << vsi << " sent corrupt message="
                                   << msg->as_slice().hex()
                                   << " in response to an ATOMIC";
        return true;
    }

    switch (static_cast<network_returncode>(response))
    {
        case NET_SUCCESS:
            set_status(HYPERDEX_CLIENT_SUCCESS);
            set_error(e::error());
            return true;
        case NET_NOTFOUND:
            set_status(HYPERDEX_CLIENT_NOTFOUND);
            set_error(e::error());
            return true;
        case NET_CMPFAIL:
            set_status(HYPERDEX_CLIENT_CMPFAIL);
            set_error(e::error());
            return true;
        case NET_BADDIMSPEC:
            PENDING_ERROR(SERVERERROR) << "server " << si
                                       << " reports that our request was invalid;"
                                       << " check its log for details";
            return true;
        case NET_NOTUS:
            PENDING_ERROR(RECONFIGURE) << "server " << si
                                       << " reports that it is no longer reponsible"
                                       << " for the requested object";
            return true;
        case NET_OVERFLOW:
            PENDING_ERROR(OVERFLOW) << "server " << si
                                    << " reports that the operation would"
                                    << " cause a number overflow";
            return true;
        case NET_READONLY:
            PENDING_ERROR(READONLY) << "cluster is in read-only mode";
            return true;
        case NET_SERVERERROR:
            PENDING_ERROR(SERVERERROR) << "server " << si
                                       << " reports a server error;"
                                       << " check its log for details";
            return true;
        case NET_UNAUTHORIZED:
            PENDING_ERROR(UNAUTHORIZED) << "server " << si
                                        << " denied the request because it is unauthorized";
            return true;
        default:
            PENDING_ERROR(SERVERERROR) << "server " << si
                                       << " returned non-sensical returncode "
                                       << response;
            return true;
    }
}


text:
title: Deploy
---

# Deploy Guides

> TODO: Add How-Tos for deployment on different servers