async function serviceQuestions()

in provider-utils/awscloudformation/service-walkthroughs/vod-push.js [16:314]


async function serviceQuestions(context, options, defaultValuesFilename, resourceName) {
  const { amplify } = context;
  const projectMeta = context.amplify.getProjectMeta();
  const projectDetails = context.amplify.getProjectDetails();
  const defaultLocation = path.resolve(`${__dirname}/../default-values/${defaultValuesFilename}`);
  const defaults = JSON.parse(fs.readFileSync(`${defaultLocation}`));
  const targetDir = amplify.pathManager.getBackendDirPath();
  const props = {};
  let oldValues = {};
  let nameDict = {};
  let aws;

  const { payload } = context.parameters.options;
  const args = payload ? JSON.parse(payload) : {};

  const nameProject = [
    {
      type: question.resourceName.type,
      name: question.resourceName.key,
      message: question.resourceName.question,
      validate: amplify.inputValidation(question.resourceName),
      default: question.resourceName.default,
      when(answers) {
        return headlessMode.autoAnswer({
          context,
          answers,
          key: question.resourceName.key,
          value: args.resourceName ? args.resourceName : question.resourceName.default,
        });
      },
    }];

  if (resourceName) {
    nameDict.resourceName = resourceName;
    props.shared = nameDict;
    // TODO: find a way of using default values from new question
    try {
      oldValues = JSON.parse(fs.readFileSync(`${targetDir}/video/${resourceName}/props.json`));
      Object.assign(defaults, oldValues);
    } catch (err) {
      // Do nothing
    }
    props.shared.bucketInput = defaults.shared.bucketInput;
    props.shared.bucketOutput = defaults.shared.bucketOutput;
  } else {
    nameDict = await inquirer.prompt(nameProject);
    props.shared = nameDict;
    const uuid = Math.random().toString(36).substring(2, 6)
                + Math.random().toString(36).substring(2, 6);
    props.shared.bucketInput = `${nameDict.resourceName.toLowerCase()}-${projectDetails.localEnvInfo.envName}-input-${uuid}`.slice(0, 63);
    props.shared.bucketOutput = `${nameDict.resourceName.toLowerCase()}-${projectDetails.localEnvInfo.envName}-output-${uuid}`.slice(0, 63);
  }

  props.shared.bucket = projectMeta.providers.awscloudformation.DeploymentBucketName;

  if (!fs.existsSync(`${targetDir}/video/${props.shared.resourceName}/`)) {
    fs.mkdirSync(`${targetDir}/video/${props.shared.resourceName}/`, { recursive: true });
  }

  props.template = {};

  const pluginDir = path.join(`${__dirname}/..`);
  const templates = fs.readdirSync(`${pluginDir}/templates/`);
  const availableTemplates = [];

  templates.forEach((filepath) => {
    const templateInfo = JSON.parse(fs.readFileSync(`${pluginDir}/templates/${filepath}`));
    availableTemplates.push({
      name: templateInfo.Description,
      value: filepath,
    });
  });

  props.template.type = {};

  availableTemplates.push({
    name: 'Bring your own template',
    value: 'advanced',
  });
  const templateQuestion = [
    {
      type: question.encodingTemplate.type,
      name: question.encodingTemplate.key,
      message: question.encodingTemplate.question,
      choices: availableTemplates,
      default: question.encodingTemplate.default,
      when(answers) {
        return headlessMode.autoAnswer({
          context,
          answers,
          key: question.encodingTemplate.key,
          value: args.encodingTemplate ? args.encodingTemplate : availableTemplates[0].value,
        });
      },
    },
  ];
  const template = await inquirer.prompt(templateQuestion);

  const outputRendition = [];

  if (template.encodingTemplate === 'advanced') {
    let jobTemplate = {};
    while (!('JobTemplate' in jobTemplate)) {
      const provider = getAWSConfig(context, options);
      aws = await provider.getConfiguredAWSClient(context);
      let mcClient = new aws.MediaConvert();
      const encodingTemplateName = [
        {
          type: question.encodingTemplateName.type,
          name: question.encodingTemplateName.key,
          message: question.encodingTemplateName.question,
          validate: amplify.inputValidation(question.encodingTemplateName),
        },
      ];
      try {
        const endpoints = await mcClient.describeEndpoints().promise();
        aws.config.mediaconvert = { endpoint: endpoints.Endpoints[0].Url };
        // Override so config applies
        mcClient = new aws.MediaConvert();
      } catch (e) {
        context.print.error(e.message);
      }
      const advTemplate = await inquirer.prompt(encodingTemplateName);
      props.template.name = advTemplate.encodingTemplateName;
      const params = {
        Name: props.template.name,
      };

      try {
        jobTemplate = await mcClient.getJobTemplate(params).promise();
        // Regex: Replaces System- if found at the beginning of the name with ''
        jobTemplate.JobTemplate.Name = jobTemplate.JobTemplate.Name.replace(/^(System-)/, '');
        delete jobTemplate.JobTemplate.Arn;
        delete jobTemplate.JobTemplate.CreatedAt;
        delete jobTemplate.JobTemplate.LastUpdated;
        delete jobTemplate.JobTemplate.Type;
        delete jobTemplate.JobTemplate.StatusUpdateInterval;
        delete jobTemplate.JobTemplate.Priority;
        fs.outputFileSync(`${targetDir}/video/${props.shared.resourceName}/mediaconvert-job-temp.json`, JSON.stringify(jobTemplate.JobTemplate, null, 4));
      } catch (e) {
        context.print.error(e.message);
      }

      // determine the outputRendition of the template (HLS or DASH)
      const currentTemplate = jobTemplate.JobTemplate;

      for (let counter = 0; counter < currentTemplate.Settings.OutputGroups.length; counter++) {
        if (currentTemplate.Settings.OutputGroups[0].OutputGroupSettings.Type.includes('DASH')) {
          outputRendition.push('DASH');
        } else if (currentTemplate.Settings.OutputGroups[0].OutputGroupSettings.Type.includes('HLS')) {
          outputRendition.push('HLS');
        }
      }

      props.template.type = outputRendition;
    }
  } else {
    props.template.name = template.encodingTemplate;

    const currentTemplate = JSON.parse(fs.readFileSync(`${pluginDir}/templates/${template.encodingTemplate}`, { encoding: 'utf8', flag: 'r' }));

    for (let counter = 0; counter < currentTemplate.Settings.OutputGroups.length; counter++) {
      if (currentTemplate.Settings.OutputGroups[counter].OutputGroupSettings.Type.includes('DASH')) {
        outputRendition.push('DASH');
      } else if (currentTemplate.Settings.OutputGroups[counter].OutputGroupSettings.Type.includes('HLS')) {
        outputRendition.push('HLS');
      }
    }

    props.template.type = outputRendition;

    fs.copySync(`${pluginDir}/templates/${template.encodingTemplate}`, `${targetDir}/video/${props.shared.resourceName}/mediaconvert-job-temp.json`);
  }
  const snsQuestion = [
    {
      type: question.createSnsTopic.type,
      name: question.createSnsTopic.key,
      message: question.createSnsTopic.question,
      when(answers) {
        return headlessMode.autoAnswer({
          context,
          answers,
          key: question.createSnsTopic.key,
          value: args.createSnsTopic
            ? args.createSnsTopic
            : defaults.snsTopic[question.createSnsTopic.key],
        });
      },
    },
  ];
  const sns = await inquirer.prompt(snsQuestion);
  props.sns = {};
  props.sns.createTopic = sns.createSnsTopic;
  if (sns.createSnsTopic) {
    const snsFunctionQuestion = [
      {
        type: question.enableSnsFunction.type,
        name: question.enableSnsFunction.key,
        message: question.enableSnsFunction.question,
        when(answers) {
          return headlessMode.autoAnswer({
            context,
            answers,
            key: question.enableSnsFunction.key,
            value: args.enableSnsFunction
              ? args.enableSnsFunction
              : defaults.snsTopic[question.enableSnsFunction.key],
          });
        },
      },
    ];
    const snsFunction = await inquirer.prompt(snsFunctionQuestion);
    props.sns.snsFunction = snsFunction.enableSnsFunction;
  }
  // prompt for cdn
  props.contentDeliveryNetwork = {};
  const cdnEnable = [
    {
      type: question.enableCDN.type,
      name: question.enableCDN.key,
      message: question.enableCDN.question,
      validate: amplify.inputValidation(question.enableCDN),
      default: defaults.contentDeliveryNetwork[question.enableCDN.key],
      when(answers) {
        return headlessMode.autoAnswer({
          context,
          answers,
          key: question.enableCDN.key,
          value: args.enableCDN
            ? args.enableCDN
            : defaults.contentDeliveryNetwork[question.enableCDN.key],
        });
      },
    }];

  const cdnResponse = await inquirer.prompt(cdnEnable);

  if (cdnResponse.enableCDN === true) {
    const contentDeliveryNetwork = await createCDN(context, props, options, aws, oldValues);
    props.contentDeliveryNetwork = contentDeliveryNetwork;
  }

  props.contentDeliveryNetwork.enableDistribution = cdnResponse.enableCDN;

  const cmsEnable = [
    {
      type: question.enableCMS.type,
      name: question.enableCMS.key,
      message: question.enableCMS.question,
      validate: amplify.inputValidation(question.enableCMS),
      default: defaults.contentManagementSystem[question.enableCMS.key],
      when(answers) {
        return headlessMode.autoAnswer({
          context,
          answers,
          key: question.enableCMS.key,
          value: args.enableCMS ? args.enableCMS : false,
        });
      },
    }];

  const cmsResponse = await inquirer.prompt(cmsEnable);

  props.parameters = {
    authRoleName: {
      Ref: 'AuthRoleName',
    },
  };

  if (cmsResponse.enableCMS) {
    let apiName = getAPIName(context);
    if (apiName === '') {
      context.print.warning('Video On Demand only supports GraphQL right now.');
      context.print.warning('If you want to only use API for CMS then choose the default ToDo and don\'t edit it until later.');
      const apiPlugin = amplify.getPluginInstance(context, 'api');
      context.input.command = 'add';
      await apiPlugin.executeAmplifyCommand(context);
      apiName = getAPIName(context);
    } else {
      context.print.info(`Using ${apiName} to manage API`);
    }

    await createCMS(context, apiName, props);
    props.parameters.GraphQLAPIId = {
      'Fn::GetAtt': [
        `api${apiName}`,
        'Outputs.GraphQLAPIIdOutput',
      ],
    };
    props.parameters.GraphQLEndpoint = {
      'Fn::GetAtt': [
        `api${apiName}`,
        'Outputs.GraphQLAPIEndpointOutput',
      ],
    };
  }

  return props;
}