Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds a secondary form to project:create for template, catalog, and initialize options #831

Open
wants to merge 17 commits into
base: development
Choose a base branch
from
Open
Changes from 5 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
9381f8e
update handling flag for catalog passing and initialization within th…
shawnawsu Aug 5, 2019
65a5027
handling values passed in via the flag for a template location
shawnawsu Aug 5, 2019
9da78e2
switched out all the options for fields to allow consoleForm to work …
shawnawsu Aug 5, 2019
95817f8
possible solution using a secondary form
shawnawsu Aug 6, 2019
c783520
cleaning up
shawnawsu Aug 6, 2019
fca2eef
moving catalog to end of create subscription for backwards compatibility
shawnawsu Aug 30, 2019
6b3dca3
some of the updates requested by Patrick still working on cleaning up…
shawnawsu Sep 3, 2019
422d38d
error handling around the initialize flag if required information is …
shawnawsu Sep 3, 2019
16b8b3c
function name change per patricks feedback
shawnawsu Sep 3, 2019
4002301
some additional checking to make sure things dont error out for no r…
shawnawsu Sep 3, 2019
9a53654
cleaning up after a change per what Patrick noticed and making a smal…
shawnawsu Sep 4, 2019
11f3652
plans and regions first looking to setup options api for a listing
shawnawsu Sep 6, 2019
69bab98
removing a print
shawnawsu Sep 11, 2019
d25b5b8
removing the empty catalog option still not sure if we need a error m…
shawnawsu Sep 16, 2019
60f0d6b
Merge branch 'setup-options-plan-region-lists' into project-create-se…
shawnawsu Sep 16, 2019
22e4abb
merging in PR 852 and adding error checking on the yaml that is passe…
shawnawsu Sep 16, 2019
3b39002
cleaning the file up a little
shawnawsu Sep 16, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 147 additions & 15 deletions src/Command/Project/ProjectCreateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,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(<<<EOF
Use this command to create a new project.
Expand Down Expand Up @@ -60,9 +63,24 @@ protected function execute(InputInterface $input, OutputInterface $output)

$options = $this->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));
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved
$this->template_form->configureInputDefinition($this->getDefinition());
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved
$template_options = $this->template_form->resolveOptions($input, $output, $questionHelper);

}


$estimate = $this->api()
->getClient()
->getSubscriptionEstimate($options['plan'], $options['storage'], $options['environments'], 1);

$costConfirm = sprintf(
'The estimated monthly cost of this project is: <comment>%s</comment>',
$estimate['total']
Expand All @@ -78,8 +96,17 @@ protected function execute(InputInterface $input, OutputInterface $output)
return 1;
}

// Grab the url of the yaml file.
if (!empty($template_options['catalog_url'])) {
pjcdawkins marked this conversation as resolved.
Show resolved Hide resolved
$options['catalog'] = $template_options['catalog_url'];
pjcdawkins marked this conversation as resolved.
Show resolved Hide resolved
}
else if (!empty($template_options['catalog_url'])) {
pjcdawkins marked this conversation as resolved.
Show resolved Hide resolved
$options['catalog'] = $template_options['template_url'];
}
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved

$subscription = $this->api()->getClient()
->createSubscription(
$options['catalog'],
$options['region'],
$options['plan'],
$options['title'],
Expand Down Expand Up @@ -129,7 +156,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('<error>The project failed to activate on time</error>');
Expand All @@ -146,14 +172,30 @@ protected function execute(InputInterface $input, OutputInterface $output)
return 1;
}

$this->stdErr->writeln("The project is now ready!");
if ($template_options['initialize']) {
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved
// Use the existing initialize command.
$project = $this->selectProject($subscription->project_id);
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved
$environment = $this->api()->getEnvironment('master', $project, null, true);
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved
$environment->initialize($subscription->project_options['initialize']['profile'], $subscription->project_options['initialize']['repository']);
pjcdawkins marked this conversation as resolved.
Show resolved Hide resolved
$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: <info>{$subscription->project_options[initialize][repository] }</info>");
}
$this->stdErr->writeln(" Region: <info>{$subscription->project_region}</info>");
$this->stdErr->writeln(" Project ID: <info>{$subscription->project_id}</info>");
$this->stdErr->writeln(" Project title: <info>{$subscription->project_title}</info>");
$this->stdErr->writeln(" URL: <info>{$subscription->project_ui}</info>");


return 0;
}

Expand Down Expand Up @@ -216,29 +258,57 @@ 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)
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved
{
if ($runtime) {
$catalog = [];
foreach ($this->api()->getClient()->getCatalog()->getData() as $item) {
pjcdawkins marked this conversation as resolved.
Show resolved Hide resolved
if ($item['info'] && $item['template']) {
$catalog[$item['template']] = $item['info']['name'];
}
}
$catalog['empty'] = 'Empty Project';
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved
} 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()
{
return [
'title' => new Field('Project title', [
$fields = [];
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved

$fields['title'] = new Field('Project title', [
'optionName' => 'title',
'description' => 'The initial project title',
'questionLine' => '',
'default' => 'Untitled Project',
]),
'region' => new OptionsField('Region', [
]);
$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(),
Expand All @@ -247,23 +317,85 @@ 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;
}

/**
* 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', [
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved
'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', [
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved
'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?',
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved
'questionLine' => 'Initialize this environment?',
shawnawsu marked this conversation as resolved.
Show resolved Hide resolved
]);

return $fields;
}

/**
Expand Down