Skip to content

Commit

Permalink
Merge pull request #211 from ystia/feature/GH-131-bootstrap-yorc
Browse files Browse the repository at this point in the history
Feature/gh 131 bootstrap yorc
  • Loading branch information
laurentganne authored Dec 6, 2018
2 parents 556640a + d451443 commit 807af37
Show file tree
Hide file tree
Showing 120 changed files with 13,008 additions and 169 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ work
**/debug.test
**/debug
build/consul
build/*.zip
/doc/_build/*
/doc/.doctrees
/dist
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

* The orchestrator requires now at least Ansible 2.7.2 (upgrade from 2.6.3 introduced in [GH-194](https://github.com/ystia/yorc/issues/194))

### FEATURES

* Allow to bootstrap a full stack Alien4Cloud/Yorc setup using yorc CLI ([GH-131](https://github.com/ystia/yorc/issues/131))

### BUG FIXES

* ConnectTo relationship not working for kubernetes topologies ([GH-212](https://github.com/ystia/yorc/issues/212))
Expand Down
20 changes: 16 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,30 @@ VERSION:=$(shell grep "yorc_version" versions.yaml | awk '{print $$2}')
BUILD_TAG:=$(shell echo `expr match "$(BUILD_ARGS)" '-tags \([A-Za-z0-9]*\)'`)
VERSION:=$(if $(BUILD_TAG),$(VERSION)+$(BUILD_TAG),$(VERSION))
COMMIT_HASH=$(shell git rev-parse HEAD)
ANSIBLE_VERSION=$(shell grep "ansible_version" versions.yaml | awk '{print $$2}')
CONSUL_VERSION=$(shell grep "consul_version" versions.yaml | awk '{print $$2}')
TERRAFORM_VERSION=$(shell grep "terraform_version" versions.yaml | awk '{print $$2}')
TF_CONSUL_PLUGIN_VERSION=$(shell grep "tf_consul_plugin_version" versions.yaml | awk '{print $$2}')
TF_AWS_PLUGIN_VERSION=$(shell grep "tf_aws_plugin_version" versions.yaml | awk '{print $$2}')
TF_OPENSTACK_PLUGIN_VERSION=$(shell grep "tf_openstack_plugin_version" versions.yaml | awk '{print $$2}')
TF_GOOGLE_PLUGIN_VERSION=$(shell grep "tf_google_plugin_version" versions.yaml | awk '{print $$2}')
YORC_VERSION=$(shell grep "yorc_version" versions.yaml | awk '{print $$2}')
build: test
@echo "--> Running go build"
@CGO_ENABLED=0 go build $(BUILD_ARGS) -ldflags "-X github.com/ystia/yorc/commands.version=v$(VERSION) -X github.com/ystia/yorc/commands.gitCommit=$(COMMIT_HASH) \
-X github.com/ystia/yorc/commands.tfConsulPluginVersion=$(TF_CONSUL_PLUGIN_VERSION) \
-X github.com/ystia/yorc/commands.tfAWSPluginVersion=$(TF_AWS_PLUGIN_VERSION) \
-X github.com/ystia/yorc/commands.tfOpenStackPluginVersion=$(TF_OPENSTACK_PLUGIN_VERSION) \
-X github.com/ystia/yorc/commands.tfGooglePluginVersion=$(TF_GOOGLE_PLUGIN_VERSION)"
-X github.com/ystia/yorc/commands.TfConsulPluginVersion=$(TF_CONSUL_PLUGIN_VERSION) \
-X github.com/ystia/yorc/commands.TfAWSPluginVersion=$(TF_AWS_PLUGIN_VERSION) \
-X github.com/ystia/yorc/commands.TfOpenStackPluginVersion=$(TF_OPENSTACK_PLUGIN_VERSION) \
-X github.com/ystia/yorc/commands.TfGooglePluginVersion=$(TF_GOOGLE_PLUGIN_VERSION) \
-X github.com/ystia/yorc/commands/bootstrap.ansibleVersion=$(ANSIBLE_VERSION) \
-X github.com/ystia/yorc/commands/bootstrap.consulVersion=$(CONSUL_VERSION) \
-X github.com/ystia/yorc/commands/bootstrap.terraformVersion=$(TERRAFORM_VERSION) \
-X github.com/ystia/yorc/commands/bootstrap.yorcVersion=$(YORC_VERSION)"
@rm -f ./build/bootstrapResources.zip
@cd ./commands && zip -q -r ../build/bootstrapResources.zip ./bootstrap/resources/*
@cat ./build/bootstrapResources.zip >> ./yorc
@zip -A ./yorc > /dev/null
generate: checks
@go generate ./...
Expand Down
178 changes: 178 additions & 0 deletions commands/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
// Copyright 2018 Bull S.A.S. Atos Technologies - Bull, Rue Jean Jaures, B.P.68, 78340, Les Clayes-sous-Bois, France.
//
// 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
//
// http://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.

package bootstrap

import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/ystia/yorc/commands"
)

// Variables with an uknown values are initialized in the root Makefile
var (
alien4cloudVersion = getAlien4CloudVersionFromTOSCATypes()
ansibleVersion = "unknown"
consulVersion = "unknown"
terraformVersion = "unknown"
yorcVersion = "unknown"
)

func init() {

// bootstrapViper is the viper configuration for bootstrap command and its children
bootstrapViper = viper.New()

// bootstrapCmd is the bootstrap base command
bootstrapCmd = &cobra.Command{
Use: "bootstrap",
Aliases: []string{"boot", "b"},
Short: "Installs Yorc and its dependencies",
Long: `Installs Yorc and its dependencies on a given infrastructure`,
SilenceErrors: true,
Run: func(cmd *cobra.Command, args []string) {
err := bootstrap()
if err != nil {
fmt.Println("Bootstrap error", err)
}
},
}

commands.RootCmd.AddCommand(bootstrapCmd)
bootstrapCmd.PersistentFlags().StringVarP(&infrastructureType,
"infrastructure", "i", "", "Define the type of infrastructure where to deploy Yorc: google, openstack, aws, hostspool")
viper.BindPFlag("infrastructure", bootstrapCmd.PersistentFlags().Lookup("infrastructure"))
bootstrapCmd.PersistentFlags().StringVarP(&deploymentType,
"deployment_type", "d", "single_node", "Define deployment type: single_node or HA")
viper.BindPFlag("deployment_type", bootstrapCmd.PersistentFlags().Lookup("deployment_type"))
bootstrapCmd.PersistentFlags().StringVarP(&followType,
"follow", "f", "steps", "Follow bootstrap deployment steps, logs, or none")
viper.BindPFlag("follow", bootstrapCmd.PersistentFlags().Lookup("follow"))
bootstrapCmd.PersistentFlags().StringVarP(&inputsPath,
"values", "v", "", "Path to file containing input values")
bootstrapCmd.PersistentFlags().BoolVarP(&reviewInputs, "review", "r", false,
"Review and update input values before starting the bootstrap")
viper.BindPFlag("review", bootstrapCmd.PersistentFlags().Lookup("review"))
bootstrapCmd.PersistentFlags().StringVarP(&resourcesZipFilePath,
"resources_zip", "z", "", "Path to bootstrap resources zip file")
viper.BindPFlag("resources_zip", bootstrapCmd.PersistentFlags().Lookup("resources_zip"))
bootstrapCmd.PersistentFlags().StringVarP(&workingDirectoryPath,
"working_directory", "w", "work", "Working directory where to place deployment files")
viper.BindPFlag("working_directory", bootstrapCmd.PersistentFlags().Lookup("working_directory"))

viper.SetEnvPrefix(commands.EnvironmentVariablePrefix)
viper.AutomaticEnv() // read in environment variables that match
viper.BindEnv("infrastructure")
viper.BindEnv("deployment_type")
viper.BindEnv("follow")
viper.BindEnv("review")
viper.BindEnv("resources_zip")
viper.BindEnv("working_directory")

// Adding extra parameters for bootstrap configuration values
args := os.Args
setBootstrapExtraParams(args, bootstrapCmd)

cleanCmd := &cobra.Command{
Use: "cleanup",
Short: "Cleans local setup",
Long: `Cleans local setup, without undeploying the bootstrapped Yorc.`,
RunE: func(cmd *cobra.Command, args []string) error {
return cleanBootstrapSetup(workingDirectoryPath)
},
}
bootstrapCmd.AddCommand(cleanCmd)

// Adding flags related to the infrastructure
commands.InitExtraFlags(args, bootstrapCmd)

// When review is set through an environment variable
// it has to be converted as a boolean or it is not taken into account
// correctly
reviewInputs = viper.GetBool("review")

}

var bootstrapCmd *cobra.Command
var bootstrapViper *viper.Viper
var infrastructureType string
var deploymentType string
var followType string
var reviewInputs bool
var resourcesZipFilePath string
var workingDirectoryPath string
var inputsPath string

func bootstrap() error {

infrastructureType = strings.ToLower(infrastructureType)
deploymentType = strings.ToLower(deploymentType)

// Resources, like the topology zip, will be created in a directory under
//the working directory
resourcesDir := filepath.Join(workingDirectoryPath, "bootstrapResources")
if err := os.RemoveAll(resourcesDir); err != nil {
return err
}

// First extract resources files
if err := extractResources(resourcesZipFilePath, resourcesDir); err != nil {
return err
}

// Read config if any
viper.SetConfigName("config.yorc") // name of config file (without extension)
viper.AddConfigPath(workingDirectoryPath)
viper.ReadInConfig()

configuration := commands.GetConfig()

// Initializing parameters from environment variables, CLI options
// input file, and asking for user input if needed
if err := initializeInputs(inputsPath, resourcesDir, configuration); err != nil {
return err
}

// Create a topology from resources provided in the resources directory
topologyDir := filepath.Join(resourcesDir, "topology")
if err := createTopology(topologyDir); err != nil {
return err
}

// Now that the topology is ready, it needs a local Yorc server able to
// deploy it
if err := setupYorcServer(workingDirectoryPath); err != nil {
return err
}

// A local Yorc server is running, using it to deploy the topology
deploymentID, errDeploy := deployTopology(workingDirectoryPath, topologyDir)

if errDeploy != nil {
return errDeploy
}

if err := followDeployment(deploymentID, followType); err != nil {
return err
}

// err = tearDownYorcServer(workingDirectoryPath)
return nil
}
99 changes: 99 additions & 0 deletions commands/bootstrap/deployment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright 2018 Bull S.A.S. Atos Technologies - Bull, Rue Jean Jaures, B.P.68, 78340, Les Clayes-sous-Bois, France.
//
// 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
//
// http://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.

package bootstrap

import (
"fmt"
"io"
"os"
"path/filepath"
"time"

"github.com/ystia/yorc/commands/deployments"
"github.com/ystia/yorc/helper/ziputil"
)

// deployTopology deploys a topology provided under deploymentDir.
// Return the the ID of the deployment
func deployTopology(workdDir, deploymentDir string) (string, error) {

// Download Alien4Cloud whose zip is expected to be provided in the
// deployment
// First downloading it in the work dir if not yet there
// like other extenrla downloadable dependencies
url := inputValues.Alien4cloud.DownloadURL
if _, err := download(url, workdDir); err != nil {
return "", err
}

// Copying this file now to the deployment dir
_, filename := filepath.Split(url)
srcPath := filepath.Join(workdDir, filename)
dstPath := filepath.Join(deploymentDir, filename)
src, err := os.Open(srcPath)
if err != nil {
return "", err
}
dst, err := os.Create(dstPath)
if err != nil {
return "", err
}
defer dst.Close()
if _, err := io.Copy(dst, src); err != nil {
return "", err
}

// Create the deployment archive
fmt.Println("Creating the deployment archive")
csarZip, err := ziputil.ZipPath(deploymentDir)
if err != nil {
return "", err
}

t := time.Now()
deploymentID := fmt.Sprintf("bootstrap-%d-%02d-%02d--%02d-%02d-%02d",
t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second())
client, err := getYorcClient()
if err != nil {
return "", err
}

fmt.Println("Deploying...")
_, err = deployments.SubmitCSAR(csarZip, client, deploymentID)
if err != nil {
return "", err
}
return deploymentID, err
}

// followDeployment follows deployments steps or deploymnet logs
// until the deployment is finished
func followDeployment(deploymentID, followType string) error {

client, err := getYorcClient()
if err != nil {
return err
}

if followType == "steps" {
err = deployments.DisplayInfo(client, deploymentID, false, true, 3*time.Second)
} else if followType == "logs" {
deployments.StreamsLogs(client, deploymentID, true, true, false)
} else {
fmt.Printf("Deployment %s submitted", deploymentID)
}

return err
}
Loading

0 comments on commit 807af37

Please sign in to comment.