From 9381f8e094ca1eee66525cb35c778fe394856405 Mon Sep 17 00:00:00 2001 From: Shawna Date: Mon, 5 Aug 2019 05:49:39 -0400 Subject: [PATCH 1/6] update handling flag for catalog passing and initialization within the creation step --- src/Command/Project/ProjectCreateCommand.php | 104 +++++++++++++++---- 1 file changed, 86 insertions(+), 18 deletions(-) diff --git a/src/Command/Project/ProjectCreateCommand.php b/src/Command/Project/ProjectCreateCommand.php index ad4df76b9c..6a40e50a7b 100644 --- a/src/Command/Project/ProjectCreateCommand.php +++ b/src/Command/Project/ProjectCreateCommand.php @@ -27,11 +27,14 @@ protected function configure() ->setAliases(['create']) ->setDescription('Create a new project'); - $this->form = Form::fromArray($this->getFields()); - $this->form->configureInputDefinition($this->getDefinition()); $this->addOption('check-timeout', null, InputOption::VALUE_REQUIRED, 'The API timeout while checking the project status', 30) - ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'The total timeout for all API checks (0 to disable the timeout)', 900); + ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'The total timeout for all API checks (0 to disable the timeout)', 900) + ->addOption('template', null, InputOption::VALUE_NONE, 'Choose a template on which to build your project.') + ->addOption('initialize', null, InputOption::VALUE_NONE, 'Initialize the project after it has been created.') + ->addOption('current-repo', null, InputOption::VALUE_NONE, 'Automatically set remote after creation.') + ->addOption('region', null, InputOption::VALUE_REQUIRED, 'The region to assign the project to.'); + $this->setHelp(<<form = Form::fromArray($this->getFields($input->getOption('template'))); + $this->form->configureInputDefinition($this->getDefinition()); + /** @var \Platformsh\Cli\Service\QuestionHelper $questionHelper */ $questionHelper = $this->getService('question_helper'); @@ -63,6 +69,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $estimate = $this->api() ->getClient() ->getSubscriptionEstimate($options['plan'], $options['storage'], $options['environments'], 1); + $costConfirm = sprintf( 'The estimated monthly cost of this project is: %s', $estimate['total'] @@ -77,9 +84,15 @@ protected function execute(InputInterface $input, OutputInterface $output) if (!$questionHelper->confirm($costConfirm)) { return 1; } + + // Handle if no template is chosen look for a default one for the user. + if (empty($options['catalog'])) { + $options['catalog'] == NULL; + } $subscription = $this->api()->getClient() ->createSubscription( + $options['catalog'], $options['region'], $options['plan'], $options['title'], @@ -129,7 +142,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $timedOut = $totalTimeout ? time() - $start > $totalTimeout : false; } $this->stdErr->writeln(''); - if (!$subscription->isActive()) { if ($timedOut) { $this->stdErr->writeln('The project failed to activate on time'); @@ -146,14 +158,30 @@ protected function execute(InputInterface $input, OutputInterface $output) return 1; } - $this->stdErr->writeln("The project is now ready!"); + if ($input->getOption('initialize')) { + // Use the existing initialize command. + $project = $this->selectProject($subscription->project_id); + $environment = $this->api()->getEnvironment('master', $project, null, true); + $environment->initialize($subscription->project_options['initialize']['profile'], $subscription->project_options['initialize']['repository']); + $this->api()->clearEnvironmentsCache($environment->project); + $this->stdErr->writeln("The project has been initialized and is ready!"); + } + else { + $this->stdErr->writeln("The project is now ready!"); + } + $output->writeln($subscription->project_id); $this->stdErr->writeln(''); + if (!empty($subscription->project_options['initialize'])) { + $this->stdErr->writeln(" Template: {$subscription->project_options[initialize][repository] }"); + } $this->stdErr->writeln(" Region: {$subscription->project_region}"); $this->stdErr->writeln(" Project ID: {$subscription->project_id}"); $this->stdErr->writeln(" Project title: {$subscription->project_title}"); $this->stdErr->writeln(" URL: {$subscription->project_ui}"); + + return 0; } @@ -216,29 +244,68 @@ protected function getAvailableRegions($runtime = false) return $regions; } + /** + * Return the catalog. + * + * The default list is in the config `service.catalog`. This is + * replaced at runtime by an API call. + * + * @param bool $runtime + * + * @return array + */ + protected function getAvailableCatalog($runtime = false) + { + if ($runtime) { + $catalog = []; + foreach ($this->api()->getClient()->getCatalog()->getData() as $item) { + if ($item['info'] && $item['template']) { + $catalog[$item['template']] = $item['info']['name']; + } + } + $catalog['empty'] = 'Empty Project'; + } else { + $catalog = (array) $this->config()->get('service.catalog'); + } + + return $catalog; + } + /** * Returns a list of ConsoleForm form fields for this command. * * @return Field[] */ - protected function getFields() + protected function getFields($template) { - return [ - 'title' => new Field('Project title', [ + $fields = []; + + $fields['title'] = new Field('Project title', [ 'optionName' => 'title', 'description' => 'The initial project title', 'questionLine' => '', 'default' => 'Untitled Project', - ]), - 'region' => new OptionsField('Region', [ + ]); + if ($template) { + $fields['catalog'] = new OptionsField('Base Template', [ + 'optionName' => 'catalog', + 'description' => 'The template from which to create your project or your own blank project.', + 'options' => $this->getAvailableCatalog(), + 'asChoice' => FALSE, + 'optionsCallback' => function () { + return $this->getAvailableCatalog(true); + }, + ]); + } + $fields['region'] = new OptionsField('Region', [ 'optionName' => 'region', 'description' => 'The region where the project will be hosted', 'options' => $this->getAvailableRegions(), 'optionsCallback' => function () { return $this->getAvailableRegions(true); }, - ]), - 'plan' => new OptionsField('Plan', [ + ]); + $fields['plan'] = new OptionsField('Plan', [ 'optionName' => 'plan', 'description' => 'The subscription plan', 'options' => $this->getAvailablePlans(), @@ -247,23 +314,24 @@ protected function getFields() }, 'default' => in_array('development', $this->getAvailablePlans()) ? 'development' : null, 'allowOther' => true, - ]), - 'environments' => new Field('Environments', [ + ]); + $fields['environments'] = new Field('Environments', [ 'optionName' => 'environments', 'description' => 'The number of environments', 'default' => 3, 'validator' => function ($value) { return is_numeric($value) && $value > 0 && $value < 50; }, - ]), - 'storage' => new Field('Storage', [ + ]); + $fields['storage'] = new Field('Storage', [ 'description' => 'The amount of storage per environment, in GiB', 'default' => 5, 'validator' => function ($value) { return is_numeric($value) && $value > 0 && $value < 1024; }, - ]), - ]; + ]); + + return $fields; } /** From 65a50279c4181b513eaecf4b7930b89efaceb0ed Mon Sep 17 00:00:00 2001 From: Shawna Date: Mon, 5 Aug 2019 08:03:58 -0400 Subject: [PATCH 2/6] handling values passed in via the flag for a template location --- src/Command/Project/ProjectCreateCommand.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Command/Project/ProjectCreateCommand.php b/src/Command/Project/ProjectCreateCommand.php index 6a40e50a7b..994233ef5e 100644 --- a/src/Command/Project/ProjectCreateCommand.php +++ b/src/Command/Project/ProjectCreateCommand.php @@ -30,7 +30,7 @@ protected function configure() $this->addOption('check-timeout', null, InputOption::VALUE_REQUIRED, 'The API timeout while checking the project status', 30) ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'The total timeout for all API checks (0 to disable the timeout)', 900) - ->addOption('template', null, InputOption::VALUE_NONE, 'Choose a template on which to build your project.') + ->addOption('template', null, InputOption::VALUE_OPTIONAL, 'Provide a template url or choose a template from the provided list on which to build your project.', false) ->addOption('initialize', null, InputOption::VALUE_NONE, 'Initialize the project after it has been created.') ->addOption('current-repo', null, InputOption::VALUE_NONE, 'Automatically set remote after creation.') ->addOption('region', null, InputOption::VALUE_REQUIRED, 'The region to assign the project to.'); @@ -58,7 +58,14 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->form = Form::fromArray($this->getFields($input->getOption('template'))); + // Process the template field to determine if it's a url or just the flag. + //@todo How do we want to handle bad urls? + $catalog = false; + if ($input->getOption('template') !== false && empty(parse_url($input->getOption('template'), PHP_URL_PATH))) { + $catalog = true; + } + + $this->form = Form::fromArray($this->getFields($catalog)); $this->form->configureInputDefinition($this->getDefinition()); /** @var \Platformsh\Cli\Service\QuestionHelper $questionHelper */ @@ -86,7 +93,10 @@ protected function execute(InputInterface $input, OutputInterface $output) } // Handle if no template is chosen look for a default one for the user. - if (empty($options['catalog'])) { + if ($catalog === false && !empty(parse_url($input->getOption('template'), PHP_URL_PATH))) { + $options['catalog'] = $input->getOption('template'); + } + else { $options['catalog'] == NULL; } From 9da78e2b9452e1ef41851738fb9220f4a65b90fe Mon Sep 17 00:00:00 2001 From: Shawna Date: Mon, 5 Aug 2019 14:45:43 -0400 Subject: [PATCH 3/6] switched out all the options for fields to allow consoleForm to work in all its glory --- src/Command/Project/ProjectCreateCommand.php | 86 +++++++++++++------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/src/Command/Project/ProjectCreateCommand.php b/src/Command/Project/ProjectCreateCommand.php index 994233ef5e..6a5fad6954 100644 --- a/src/Command/Project/ProjectCreateCommand.php +++ b/src/Command/Project/ProjectCreateCommand.php @@ -7,6 +7,8 @@ use Platformsh\Cli\Console\Bot; use Platformsh\ConsoleForm\Field\Field; use Platformsh\ConsoleForm\Field\OptionsField; +use Platformsh\ConsoleForm\Field\BooleanField; +use Platformsh\ConsoleForm\Field\UrlField; use Platformsh\ConsoleForm\Form; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -27,14 +29,11 @@ protected function configure() ->setAliases(['create']) ->setDescription('Create a new project'); + $this->form = Form::fromArray($this->getFields()); + $this->form->configureInputDefinition($this->getDefinition()); $this->addOption('check-timeout', null, InputOption::VALUE_REQUIRED, 'The API timeout while checking the project status', 30) - ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'The total timeout for all API checks (0 to disable the timeout)', 900) - ->addOption('template', null, InputOption::VALUE_OPTIONAL, 'Provide a template url or choose a template from the provided list on which to build your project.', false) - ->addOption('initialize', null, InputOption::VALUE_NONE, 'Initialize the project after it has been created.') - ->addOption('current-repo', null, InputOption::VALUE_NONE, 'Automatically set remote after creation.') - ->addOption('region', null, InputOption::VALUE_REQUIRED, 'The region to assign the project to.'); - + ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'The total timeout for all API checks (0 to disable the timeout)', 900); $this->setHelp(<<getOption('template') !== false && empty(parse_url($input->getOption('template'), PHP_URL_PATH))) { - $catalog = true; - } - - $this->form = Form::fromArray($this->getFields($catalog)); - $this->form->configureInputDefinition($this->getDefinition()); - /** @var \Platformsh\Cli\Service\QuestionHelper $questionHelper */ $questionHelper = $this->getService('question_helper'); @@ -91,15 +80,15 @@ protected function execute(InputInterface $input, OutputInterface $output) if (!$questionHelper->confirm($costConfirm)) { return 1; } - - // Handle if no template is chosen look for a default one for the user. - if ($catalog === false && !empty(parse_url($input->getOption('template'), PHP_URL_PATH))) { - $options['catalog'] = $input->getOption('template'); + + // Grab the url of the yaml file. + if (!empty($options['catalog_url'])) { + $options['catalog'] = $options['catalog_url']; } - else { - $options['catalog'] == NULL; + else if (!empty($options['catalog_url'])) { + $options['catalog'] = $options['template_url']; } - + $subscription = $this->api()->getClient() ->createSubscription( $options['catalog'], @@ -168,7 +157,7 @@ protected function execute(InputInterface $input, OutputInterface $output) return 1; } - if ($input->getOption('initialize')) { + if ($options['initialize']) { // Use the existing initialize command. $project = $this->selectProject($subscription->project_id); $environment = $this->api()->getEnvironment('master', $project, null, true); @@ -286,7 +275,7 @@ protected function getAvailableCatalog($runtime = false) * * @return Field[] */ - protected function getFields($template) + protected function getFields() { $fields = []; @@ -296,17 +285,41 @@ protected function getFields($template) 'questionLine' => '', 'default' => 'Untitled Project', ]); - if ($template) { - $fields['catalog'] = new OptionsField('Base Template', [ - 'optionName' => 'catalog', + + $fields['template_option'] = new OptionsField('Template Options', [ + 'optionName' => 'template_option', + 'options' => [ + 'Provide your own template url.', + 'Choose a template from the catalog.', + 'No template at this time.', + ], + 'description' => 'Choose a template, provide a url or choose not to use one.', + 'includeAsOption' => false, + ]); + $fields['catalog_url'] = new OptionsField('Catalog', [ + 'optionName' => 'catalog_url', + 'conditions' => [ + 'template_option' => [ + 'Choose a template from the catalog.' + ], + ], 'description' => 'The template from which to create your project or your own blank project.', 'options' => $this->getAvailableCatalog(), 'asChoice' => FALSE, 'optionsCallback' => function () { return $this->getAvailableCatalog(true); - }, - ]); - } + }, + ]); + $fields['template_url'] = new UrlField('Template URL', [ + 'optionName' => 'template_url', + 'conditions' => [ + 'template_option' => [ + 'Provide your own template url.' + ], + ], + 'description' => 'The template url', + 'questionLine' => 'What is the URL of the template?', + ]); $fields['region'] = new OptionsField('Region', [ 'optionName' => 'region', 'description' => 'The region where the project will be hosted', @@ -340,6 +353,17 @@ protected function getFields($template) return is_numeric($value) && $value > 0 && $value < 1024; }, ]); + $fields['initialize'] = new BooleanField('Initialize', [ + 'optionName' => 'initialized', + 'conditions' => [ + 'template_option' => [ + 'Provide your own template url.', + 'Choose a template from the catalog.', + ], + ], + 'description' => 'Initialize this environment?', + 'questionLine' => 'Initialize this environment?', + ]); return $fields; } From 95817f8463b6f1b3d2ebcbdd26402fe25084700f Mon Sep 17 00:00:00 2001 From: Shawna Date: Tue, 6 Aug 2019 07:31:43 -0400 Subject: [PATCH 4/6] possible solution using a secondary form --- src/Command/Project/ProjectCreateCommand.php | 172 ++++++++++++++----- 1 file changed, 125 insertions(+), 47 deletions(-) diff --git a/src/Command/Project/ProjectCreateCommand.php b/src/Command/Project/ProjectCreateCommand.php index 6a5fad6954..81148389ef 100644 --- a/src/Command/Project/ProjectCreateCommand.php +++ b/src/Command/Project/ProjectCreateCommand.php @@ -33,7 +33,8 @@ protected function configure() $this->form->configureInputDefinition($this->getDefinition()); $this->addOption('check-timeout', null, InputOption::VALUE_REQUIRED, 'The API timeout while checking the project status', 30) - ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'The total timeout for all API checks (0 to disable the timeout)', 900); + ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'The total timeout for all API checks (0 to disable the timeout)', 900) + ->addOption('template', null, InputOption::VALUE_OPTIONAL, 'Choose a starting template or provide a url of one.', false); $this->setHelp(<<form->resolveOptions($input, $output, $questionHelper); + if ($input->getOption('template') !== false) { + if (empty(parse_url($input->getOption('template'), PHP_URL_PATH))) { + $temp_provided = true; + } + else { + $temp_provided = false; + } + $this->template_form = Form::fromArray($this->getTemplateFields($temp_provided)); + $this->template_form->configureInputDefinition($this->getDefinition()); + $template_options = $this->template_form->resolveOptions($input, $output, $questionHelper); + + } + + $estimate = $this->api() ->getClient() ->getSubscriptionEstimate($options['plan'], $options['storage'], $options['environments'], 1); @@ -82,11 +97,11 @@ protected function execute(InputInterface $input, OutputInterface $output) } // Grab the url of the yaml file. - if (!empty($options['catalog_url'])) { - $options['catalog'] = $options['catalog_url']; + if (!empty($template_options['catalog_url'])) { + $options['catalog'] = $template_options['catalog_url']; } - else if (!empty($options['catalog_url'])) { - $options['catalog'] = $options['template_url']; + else if (!empty($template_options['catalog_url'])) { + $options['catalog'] = $template_options['template_url']; } $subscription = $this->api()->getClient() @@ -157,7 +172,7 @@ protected function execute(InputInterface $input, OutputInterface $output) return 1; } - if ($options['initialize']) { + if ($template_options['initialize']) { // Use the existing initialize command. $project = $this->selectProject($subscription->project_id); $environment = $this->api()->getEnvironment('master', $project, null, true); @@ -286,40 +301,40 @@ protected function getFields() 'default' => 'Untitled Project', ]); - $fields['template_option'] = new OptionsField('Template Options', [ - 'optionName' => 'template_option', - 'options' => [ - 'Provide your own template url.', - 'Choose a template from the catalog.', - 'No template at this time.', - ], - 'description' => 'Choose a template, provide a url or choose not to use one.', - 'includeAsOption' => false, - ]); - $fields['catalog_url'] = new OptionsField('Catalog', [ - 'optionName' => 'catalog_url', - 'conditions' => [ - 'template_option' => [ - 'Choose a template from the catalog.' - ], - ], - 'description' => 'The template from which to create your project or your own blank project.', - 'options' => $this->getAvailableCatalog(), - 'asChoice' => FALSE, - 'optionsCallback' => function () { - return $this->getAvailableCatalog(true); - }, - ]); - $fields['template_url'] = new UrlField('Template URL', [ - 'optionName' => 'template_url', - 'conditions' => [ - 'template_option' => [ - 'Provide your own template url.' - ], - ], - 'description' => 'The template url', - 'questionLine' => 'What is the URL of the template?', - ]); + // $fields['template_option'] = new OptionsField('Template Options', [ + // 'optionName' => 'template_option', + // 'options' => [ + // 'Provide your own template url.', + // 'Choose a template from the catalog.', + // 'No template at this time.', + // ], + // 'description' => 'Choose a template, provide a url or choose not to use one.', + // 'includeAsOption' => false, + // ]); + // $fields['catalog_url'] = new OptionsField('Catalog', [ + // 'optionName' => 'catalog_url', + // 'conditions' => [ + // 'template_option' => [ + // 'Choose a template from the catalog.' + // ], + // ], + // 'description' => 'The template from which to create your project or your own blank project.', + // 'options' => $this->getAvailableCatalog(), + // 'asChoice' => FALSE, + // 'optionsCallback' => function () { + // return $this->getAvailableCatalog(true); + // }, + // ]); + // $fields['template_url'] = new UrlField('Template URL', [ + // 'optionName' => 'template_url', + // 'conditions' => [ + // 'template_option' => [ + // 'Provide your own template url.' + // ], + // ], + // 'description' => 'The template url', + // 'questionLine' => 'What is the URL of the template?', + // ]); $fields['region'] = new OptionsField('Region', [ 'optionName' => 'region', 'description' => 'The region where the project will be hosted', @@ -353,17 +368,80 @@ protected function getFields() return is_numeric($value) && $value > 0 && $value < 1024; }, ]); - $fields['initialize'] = new BooleanField('Initialize', [ - 'optionName' => 'initialized', - 'conditions' => [ - 'template_option' => [ + // $fields['initialize'] = new BooleanField('Initialize', [ + // 'optionName' => 'initialized', + // 'conditions' => [ + // 'template_option' => [ + // 'Provide your own template url.', + // 'Choose a template from the catalog.', + // ], + // ], + // 'description' => 'Initialize this environment?', + // 'questionLine' => 'Initialize this environment?', + // ]); + + return $fields; + } + + /** + * Returns a list of ConsoleForm form fields for this command. + * + * @return Field[] + */ + protected function getTemplateFields($url_provided) + { + $fields = []; + + if (!$url_provided) { + $fields['template_option'] = new OptionsField('Template Options', [ + 'optionName' => 'template_option', + 'options' => [ 'Provide your own template url.', 'Choose a template from the catalog.', + 'No template at this time.', + ], + 'description' => 'Choose a template, provide a url or choose not to use one.', + 'includeAsOption' => false, + ]); + + $fields['catalog_url'] = new OptionsField('Catalog', [ + 'optionName' => 'catalog_url', + 'conditions' => [ + 'template_option' => [ + 'Choose a template from the catalog.' ], ], - 'description' => 'Initialize this environment?', - 'questionLine' => 'Initialize this environment?', - ]); + 'description' => 'The template from which to create your project or your own blank project.', + 'options' => $this->getAvailableCatalog(), + 'asChoice' => FALSE, + 'optionsCallback' => function () { + return $this->getAvailableCatalog(true); + }, + ]); + + $fields['template_url'] = new UrlField('Template URL', [ + 'optionName' => 'template_url', + 'conditions' => [ + 'template_option' => [ + 'Provide your own template url.' + ], + ], + 'description' => 'The template url', + 'questionLine' => 'What is the URL of the template?', + ]); + } + + $fields['initialize'] = new BooleanField('Initialize', [ + 'optionName' => 'initialized', + 'conditions' => [ + 'template_option' => [ + 'Provide your own template url.', + 'Choose a template from the catalog.', + ], + ], + 'description' => 'Initialize this environment?', + 'questionLine' => 'Initialize this environment?', + ]); return $fields; } From 721af73b31bae8db8a8b7a7ca11009433a941b14 Mon Sep 17 00:00:00 2001 From: Shawna Date: Tue, 6 Aug 2019 08:59:43 -0400 Subject: [PATCH 5/6] new createconsoleform to override parent class behavior in resolveoptions --- src/Command/Project/CreateConsoleForm.php | 60 +++++++ src/Command/Project/ProjectCreateCommand.php | 160 +++---------------- 2 files changed, 86 insertions(+), 134 deletions(-) create mode 100644 src/Command/Project/CreateConsoleForm.php diff --git a/src/Command/Project/CreateConsoleForm.php b/src/Command/Project/CreateConsoleForm.php new file mode 100644 index 0000000000..e09a8f51f8 --- /dev/null +++ b/src/Command/Project/CreateConsoleForm.php @@ -0,0 +1,60 @@ +getErrorOutput() : $output; + foreach ($this->fields as $key => $field) { + $field->onChange($values); + + //Check for the catalog flag. + if ($field->getOptionName() == 'catalog_url' && $input->getOption('catalog')!==true) { + continue; + } + //Check if the field should be initialized. + if ($field->getOptionName() == 'initialize' && + ($input->getOption('catalog')!==true || $input->getOption('template')!==true)) { + continue; + } + + if (!$this->includeField($field, $values)) { + continue; + } + + // Get the value from the command-line options. + $value = $field->getValueFromInput($input, false); + if ($value !== null) { + $field->validate($value); + } elseif ($input->isInteractive()) { + // Get the value interactively. + $value = $helper->ask($input, $stdErr, $field->getAsQuestion()); + $stdErr->writeln(''); + } elseif ($field->isRequired()) { + throw new MissingValueException('--' . $field->getOptionName() . ' is required'); + } + + self::setNestedArrayValue( + $values, + $field->getValueKeys() ?: [$key], + $field->getFinalValue($value), + true + ); + } + + return $values; + } +} diff --git a/src/Command/Project/ProjectCreateCommand.php b/src/Command/Project/ProjectCreateCommand.php index 81148389ef..742d942809 100644 --- a/src/Command/Project/ProjectCreateCommand.php +++ b/src/Command/Project/ProjectCreateCommand.php @@ -8,8 +8,7 @@ use Platformsh\ConsoleForm\Field\Field; use Platformsh\ConsoleForm\Field\OptionsField; use Platformsh\ConsoleForm\Field\BooleanField; -use Platformsh\ConsoleForm\Field\UrlField; -use Platformsh\ConsoleForm\Form; +use Platformsh\Cli\Command\Project\CreateConsoleForm; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -29,12 +28,15 @@ protected function configure() ->setAliases(['create']) ->setDescription('Create a new project'); - $this->form = Form::fromArray($this->getFields()); + $this->form = CreateConsoleForm::fromArray($this->getFields()); $this->form->configureInputDefinition($this->getDefinition()); $this->addOption('check-timeout', null, InputOption::VALUE_REQUIRED, 'The API timeout while checking the project status', 30) ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'The total timeout for all API checks (0 to disable the timeout)', 900) - ->addOption('template', null, InputOption::VALUE_OPTIONAL, 'Choose a starting template or provide a url of one.', false); + ->addOption('template', null, InputOption::VALUE_REQUIRED, 'Choose a starting template or provide a url of one.') + ->addOption('catalog', null, InputOption::VALUE_NONE, 'Choose a template from the catalog') + ->addOption('initialize', null, InputOption::VALUE_NONE, 'Initialize the project after it has been created.'); + $this->setHelp(<<form->resolveOptions($input, $output, $questionHelper); - if ($input->getOption('template') !== false) { - if (empty(parse_url($input->getOption('template'), PHP_URL_PATH))) { - $temp_provided = true; - } - else { - $temp_provided = false; - } - $this->template_form = Form::fromArray($this->getTemplateFields($temp_provided)); - $this->template_form->configureInputDefinition($this->getDefinition()); - $template_options = $this->template_form->resolveOptions($input, $output, $questionHelper); - - } - - $estimate = $this->api() ->getClient() ->getSubscriptionEstimate($options['plan'], $options['storage'], $options['environments'], 1); @@ -95,15 +83,14 @@ protected function execute(InputInterface $input, OutputInterface $output) if (!$questionHelper->confirm($costConfirm)) { return 1; } - - // Grab the url of the yaml file. - if (!empty($template_options['catalog_url'])) { - $options['catalog'] = $template_options['catalog_url']; + if (!empty($options['catalog_url'])) { + $options['catalog'] = $options['catalog_url']; } - else if (!empty($template_options['catalog_url'])) { - $options['catalog'] = $template_options['template_url']; + else if (!empty($input->getOption('template'))) { + $options['catalog'] = $input->getOption('template'); } + $subscription = $this->api()->getClient() ->createSubscription( $options['catalog'], @@ -172,7 +159,7 @@ protected function execute(InputInterface $input, OutputInterface $output) return 1; } - if ($template_options['initialize']) { + if ($options['initialize']) { // Use the existing initialize command. $project = $this->selectProject($subscription->project_id); $environment = $this->api()->getEnvironment('master', $project, null, true); @@ -300,41 +287,15 @@ protected function getFields() 'questionLine' => '', 'default' => 'Untitled Project', ]); - - // $fields['template_option'] = new OptionsField('Template Options', [ - // 'optionName' => 'template_option', - // 'options' => [ - // 'Provide your own template url.', - // 'Choose a template from the catalog.', - // 'No template at this time.', - // ], - // 'description' => 'Choose a template, provide a url or choose not to use one.', - // 'includeAsOption' => false, - // ]); - // $fields['catalog_url'] = new OptionsField('Catalog', [ - // 'optionName' => 'catalog_url', - // 'conditions' => [ - // 'template_option' => [ - // 'Choose a template from the catalog.' - // ], - // ], - // 'description' => 'The template from which to create your project or your own blank project.', - // 'options' => $this->getAvailableCatalog(), - // 'asChoice' => FALSE, - // 'optionsCallback' => function () { - // return $this->getAvailableCatalog(true); - // }, - // ]); - // $fields['template_url'] = new UrlField('Template URL', [ - // 'optionName' => 'template_url', - // 'conditions' => [ - // 'template_option' => [ - // 'Provide your own template url.' - // ], - // ], - // 'description' => 'The template url', - // 'questionLine' => 'What is the URL of the template?', - // ]); + $fields['catalog_url'] = new OptionsField('Catalog', [ + 'optionName' => 'catalog_url', + 'description' => 'The template from which to create your project or your own blank project.', + 'options' => $this->getAvailableCatalog(), + 'asChoice' => FALSE, + 'optionsCallback' => function () { + return $this->getAvailableCatalog(true); + }, + ]); $fields['region'] = new OptionsField('Region', [ 'optionName' => 'region', 'description' => 'The region where the project will be hosted', @@ -368,80 +329,11 @@ protected function getFields() return is_numeric($value) && $value > 0 && $value < 1024; }, ]); - // $fields['initialize'] = new BooleanField('Initialize', [ - // 'optionName' => 'initialized', - // 'conditions' => [ - // 'template_option' => [ - // 'Provide your own template url.', - // 'Choose a template from the catalog.', - // ], - // ], - // 'description' => 'Initialize this environment?', - // 'questionLine' => 'Initialize this environment?', - // ]); - - return $fields; - } - - /** - * Returns a list of ConsoleForm form fields for this command. - * - * @return Field[] - */ - protected function getTemplateFields($url_provided) - { - $fields = []; - - if (!$url_provided) { - $fields['template_option'] = new OptionsField('Template Options', [ - 'optionName' => 'template_option', - 'options' => [ - 'Provide your own template url.', - 'Choose a template from the catalog.', - 'No template at this time.', - ], - 'description' => 'Choose a template, provide a url or choose not to use one.', - 'includeAsOption' => false, - ]); - - $fields['catalog_url'] = new OptionsField('Catalog', [ - 'optionName' => 'catalog_url', - 'conditions' => [ - 'template_option' => [ - 'Choose a template from the catalog.' - ], - ], - 'description' => 'The template from which to create your project or your own blank project.', - 'options' => $this->getAvailableCatalog(), - 'asChoice' => FALSE, - 'optionsCallback' => function () { - return $this->getAvailableCatalog(true); - }, - ]); - - $fields['template_url'] = new UrlField('Template URL', [ - 'optionName' => 'template_url', - 'conditions' => [ - 'template_option' => [ - 'Provide your own template url.' - ], - ], - 'description' => 'The template url', - 'questionLine' => 'What is the URL of the template?', - ]); - } - - $fields['initialize'] = new BooleanField('Initialize', [ - 'optionName' => 'initialized', - 'conditions' => [ - 'template_option' => [ - 'Provide your own template url.', - 'Choose a template from the catalog.', - ], - ], - 'description' => 'Initialize this environment?', - 'questionLine' => 'Initialize this environment?', - ]); + $fields['initialize'] = new BooleanField('Initialize', [ + 'optionName' => 'initialized', + 'description' => 'Initialize this environment?', + 'questionLine' => 'Initialize this environment?', + ]); return $fields; } From d2517d3442a7bb99cb3cdecefb2d24e7632c42a3 Mon Sep 17 00:00:00 2001 From: Shawna Date: Wed, 7 Aug 2019 08:29:48 -0400 Subject: [PATCH 6/6] made some error checking tweaks and added some help text --- config.yaml | 4 ++++ src/Command/Project/CreateConsoleForm.php | 19 +++++++++++++------ src/Command/Project/ProjectCreateCommand.php | 13 +++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/config.yaml b/config.yaml index 7a94c96b95..89c27da28d 100644 --- a/config.yaml +++ b/config.yaml @@ -80,6 +80,10 @@ service: - standard - medium - large + catalog: + - https://github.com/platformsh/template-builder/blob/master/templates/akeneo/.platform.template.yaml + - https://github.com/platformsh/template-builder/blob/master/templates/beego/.platform.template.yaml + - https://github.com/platformsh/template-builder/blob/master/templates/django1/.platform.template.yaml # Configuration relating to API calls. # This can be overridden in the user config file. diff --git a/src/Command/Project/CreateConsoleForm.php b/src/Command/Project/CreateConsoleForm.php index e09a8f51f8..2b3e492797 100644 --- a/src/Command/Project/CreateConsoleForm.php +++ b/src/Command/Project/CreateConsoleForm.php @@ -18,19 +18,26 @@ public function resolveOptions(InputInterface $input, OutputInterface $output, Q { $values = []; $stdErr = $output instanceof ConsoleOutput ? $output->getErrorOutput() : $output; + print_r('catalog: ' . $input->getOption('catalog')); + print_r('template: ' . $input->getOption('template')); foreach ($this->fields as $key => $field) { $field->onChange($values); - //Check for the catalog flag. + // Check for the catalog flag. if ($field->getOptionName() == 'catalog_url' && $input->getOption('catalog')!==true) { continue; } - //Check if the field should be initialized. - if ($field->getOptionName() == 'initialize' && - ($input->getOption('catalog')!==true || $input->getOption('template')!==true)) { - continue; + // Check if the initialize field should be shown. + if ($field->getOptionName() == 'initialized') { + // Do not show if the neither catalog or template flags are present. + if ($input->getOption('catalog')==false && $input->getOption('template')==false) { + continue; + } + // Do not show is the initialize flag is present. + if ($input->getOption('initialize')==true) { + continue; + } } - if (!$this->includeField($field, $values)) { continue; } diff --git a/src/Command/Project/ProjectCreateCommand.php b/src/Command/Project/ProjectCreateCommand.php index 742d942809..1c5a1008ea 100644 --- a/src/Command/Project/ProjectCreateCommand.php +++ b/src/Command/Project/ProjectCreateCommand.php @@ -60,6 +60,15 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + if ($input->getOption('initialize')==true && + ($input->getOption('catalog')==false && + $input->getOption('template')==false)) { + + $this->stdErr->writeln("Projects cannot be initialized without a template file. +If you would like to use the --initialize option please provide a template file by utilizing +the --template or --catalog options. For more information on this command please type project:create --help."); + return 0; + } /** @var \Platformsh\Cli\Service\QuestionHelper $questionHelper */ $questionHelper = $this->getService('question_helper'); @@ -160,6 +169,10 @@ protected function execute(InputInterface $input, OutputInterface $output) } if ($options['initialize']) { + // Check that the profile and repository are present and initializable. + if (empty($subscription->project_options['initialize']['repository'])) { + $this->stdErr->writeln("The project has been created but cannot be initialized because the project repository is empty."); + } // Use the existing initialize command. $project = $this->selectProject($subscription->project_id); $environment = $this->api()->getEnvironment('master', $project, null, true);