func NewManifest(config Config, iaasConfig iaas.Config) (Manifest, error) {
	config = NewConfigWithDefaults(config)

	releases := []core.Release{
		{
			Name:    "etcd",
			Version: "latest",
		},
	}

	cidr, err := core.ParseCIDRBlock(config.IPRange)
	if err != nil {
		return Manifest{}, err
	}

	etcdNetwork1 := core.Network{
		Name: "etcd1",
		Subnets: []core.NetworkSubnet{{
			CloudProperties: iaasConfig.NetworkSubnet(cidr.String()),
			Gateway:         cidr.GetFirstIP().Add(1).String(),
			Range:           cidr.String(),
			Reserved:        []string{cidr.Range(2, 3), cidr.GetLastIP().String()},
			Static:          []string{cidr.Range(4, cidr.CIDRSize-5)},
		}},
		Type: "manual",
	}

	compilation := core.Compilation{
		Network:             etcdNetwork1.Name,
		ReuseCompilationVMs: true,
		Workers:             3,
		CloudProperties:     iaasConfig.Compilation("us-east-1a"),
	}

	update := core.Update{
		Canaries:        1,
		CanaryWatchTime: "1000-180000",
		MaxInFlight:     1,
		Serial:          true,
		UpdateWatchTime: "1000-180000",
	}

	stemcell := core.ResourcePoolStemcell{
		Name:    iaasConfig.Stemcell(),
		Version: "latest",
	}

	z1ResourcePool := core.ResourcePool{
		Name:            "etcd_z1",
		Network:         etcdNetwork1.Name,
		Stemcell:        stemcell,
		CloudProperties: iaasConfig.ResourcePool(etcdNetwork1.Subnets[0].Range),
	}

	staticIPs, err := etcdNetwork1.StaticIPsFromRange(24)
	if err != nil {
		return Manifest{}, err
	}

	etcdZ1JobTemplates := []core.JobTemplate{
		{
			Name:    "etcd",
			Release: "etcd",
		},
	}

	etcdZ1Job := core.Job{
		Name:      "etcd_z1",
		Instances: 1,
		Networks: []core.JobNetwork{{
			Name:      etcdNetwork1.Name,
			StaticIPs: []string{staticIPs[0]},
		}},
		PersistentDisk: 1024,
		ResourcePool:   z1ResourcePool.Name,
		Templates:      etcdZ1JobTemplates,
	}

	if config.IPTablesAgent {
		etcdZ1Job.Templates = append(etcdZ1Job.Templates, core.JobTemplate{
			Name:    "iptables_agent",
			Release: "etcd",
		})
	}

	testconsumerZ1Job := core.Job{
		Name:      "testconsumer_z1",
		Instances: 1,
		Networks: []core.JobNetwork{{
			Name:      etcdNetwork1.Name,
			StaticIPs: []string{staticIPs[8]},
		}},
		PersistentDisk: 1024,
		ResourcePool:   z1ResourcePool.Name,
		Templates: []core.JobTemplate{
			{
				Name:    "etcd_testconsumer",
				Release: "etcd",
			},
		},
	}

	globalProperties := Properties{
		Etcd: &PropertiesEtcd{
			Cluster: []PropertiesEtcdCluster{{
				Instances: 1,
				Name:      "etcd_z1",
			}},
			Machines:                        etcdZ1Job.Networks[0].StaticIPs,
			PeerRequireSSL:                  false,
			RequireSSL:                      false,
			HeartbeatIntervalInMilliseconds: 50,
		},
		EtcdTestConsumer: &PropertiesEtcdTestConsumer{
			Etcd: PropertiesEtcdTestConsumerEtcd{
				Machines: etcdZ1Job.Networks[0].StaticIPs,
			},
		},
	}

	if config.TurbulenceHost != "" {
		globalProperties.TurbulenceAgent = &core.PropertiesTurbulenceAgent{
			API: core.PropertiesTurbulenceAgentAPI{
				Host:     config.TurbulenceHost,
				Password: turbulence.DefaultPassword,
				CACert:   turbulence.APICACert,
			},
		}

		etcdZ1Job.Templates = append(etcdZ1Job.Templates, core.JobTemplate{
			Name:    "turbulence_agent",
			Release: "turbulence",
		})

		releases = append(releases, core.Release{
			Name:    "turbulence",
			Version: "latest",
		})
	}

	return Manifest{
		DirectorUUID: config.DirectorUUID,
		Name:         config.Name,
		Compilation:  compilation,
		Jobs: []core.Job{
			etcdZ1Job,
			testconsumerZ1Job,
		},
		Networks: []core.Network{
			etcdNetwork1,
		},
		Properties: globalProperties,
		Releases:   releases,
		ResourcePools: []core.ResourcePool{
			z1ResourcePool,
		},
		Update: update,
	}, nil
}
package core_test

import (
	"github.com/pivotal-cf-experimental/destiny/core"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Job", func() {
	Describe("HasTemplate", func() {
		It("returns true if the job has the template", func() {
			job := core.Job{
				Templates: []core.JobTemplate{
					{
						Name:    "some-template-name",
						Release: "some-template-release",
					},
				},
			}

			Expect(job.HasTemplate("some-template-name", "some-template-release")).To(BeTrue())
		})

		It("returns false if the job does not have the template", func() {
			job := core.Job{
				Templates: []core.JobTemplate{
					{
						Name:    "some-other-template-name",
						Release: "some-other-template-release",
					},
				},