1package deployment
2
3import (
4	"time"
5
6	biblobstore "github.com/cloudfoundry/bosh-cli/blobstore"
7	bicloud "github.com/cloudfoundry/bosh-cli/cloud"
8	bidisk "github.com/cloudfoundry/bosh-cli/deployment/disk"
9	biinstance "github.com/cloudfoundry/bosh-cli/deployment/instance"
10	bideplmanifest "github.com/cloudfoundry/bosh-cli/deployment/manifest"
11	bivm "github.com/cloudfoundry/bosh-cli/deployment/vm"
12	biinstallmanifest "github.com/cloudfoundry/bosh-cli/installation/manifest"
13	bistemcell "github.com/cloudfoundry/bosh-cli/stemcell"
14	biui "github.com/cloudfoundry/bosh-cli/ui"
15	bosherr "github.com/cloudfoundry/bosh-utils/errors"
16	boshlog "github.com/cloudfoundry/bosh-utils/logger"
17)
18
19type Deployer interface {
20	Deploy(
21		bicloud.Cloud,
22		bideplmanifest.Manifest,
23		bistemcell.CloudStemcell,
24		biinstallmanifest.Registry,
25		bivm.Manager,
26		biblobstore.Blobstore,
27		bool,
28		biui.Stage,
29	) (Deployment, error)
30}
31
32type deployer struct {
33	vmManagerFactory       bivm.ManagerFactory
34	instanceManagerFactory biinstance.ManagerFactory
35	deploymentFactory      Factory
36	logger                 boshlog.Logger
37	logTag                 string
38}
39
40func NewDeployer(
41	vmManagerFactory bivm.ManagerFactory,
42	instanceManagerFactory biinstance.ManagerFactory,
43	deploymentFactory Factory,
44	logger boshlog.Logger,
45) Deployer {
46	return &deployer{
47		vmManagerFactory:       vmManagerFactory,
48		instanceManagerFactory: instanceManagerFactory,
49		deploymentFactory:      deploymentFactory,
50		logger:                 logger,
51		logTag:                 "deployer",
52	}
53}
54
55func (d *deployer) Deploy(
56	cloud bicloud.Cloud,
57	deploymentManifest bideplmanifest.Manifest,
58	cloudStemcell bistemcell.CloudStemcell,
59	registryConfig biinstallmanifest.Registry,
60	vmManager bivm.Manager,
61	blobstore biblobstore.Blobstore,
62	skipDrain bool,
63	deployStage biui.Stage,
64) (Deployment, error) {
65	instanceManager := d.instanceManagerFactory.NewManager(cloud, vmManager, blobstore)
66
67	pingTimeout := 10 * time.Second
68	pingDelay := 500 * time.Millisecond
69	if err := instanceManager.DeleteAll(pingTimeout, pingDelay, skipDrain, deployStage); err != nil {
70		return nil, err
71	}
72
73	instances, disks, err := d.createAllInstances(deploymentManifest, instanceManager, cloudStemcell, registryConfig, deployStage)
74	if err != nil {
75		return nil, err
76	}
77
78	stemcells := []bistemcell.CloudStemcell{cloudStemcell}
79	return d.deploymentFactory.NewDeployment(instances, disks, stemcells), nil
80}
81
82func (d *deployer) createAllInstances(
83	deploymentManifest bideplmanifest.Manifest,
84	instanceManager biinstance.Manager,
85	cloudStemcell bistemcell.CloudStemcell,
86	registryConfig biinstallmanifest.Registry,
87	deployStage biui.Stage,
88) ([]biinstance.Instance, []bidisk.Disk, error) {
89	instances := []biinstance.Instance{}
90	disks := []bidisk.Disk{}
91
92	if len(deploymentManifest.Jobs) != 1 {
93		return instances, disks, bosherr.Errorf("There must only be one job, found %d", len(deploymentManifest.Jobs))
94	}
95
96	for _, jobSpec := range deploymentManifest.Jobs {
97		if jobSpec.Instances != 1 {
98			return instances, disks, bosherr.Errorf("Job '%s' must have only one instance, found %d", jobSpec.Name, jobSpec.Instances)
99		}
100		for instanceID := 0; instanceID < jobSpec.Instances; instanceID++ {
101			instance, instanceDisks, err := instanceManager.Create(jobSpec.Name, instanceID, deploymentManifest, cloudStemcell, registryConfig, deployStage)
102			if err != nil {
103				return instances, disks, bosherr.WrapErrorf(err, "Creating instance '%s/%d'", jobSpec.Name, instanceID)
104			}
105			instances = append(instances, instance)
106			disks = append(disks, instanceDisks...)
107
108			err = instance.UpdateJobs(deploymentManifest, deployStage)
109			if err != nil {
110				return instances, disks, err
111			}
112		}
113	}
114
115	return instances, disks, nil
116}
117