Context("Synchronous operations", func() {
		BeforeEach(func() {
			broker = NewServiceBroker(
				random_name.CATSRandomName("BRKR"),
				assets.NewAssets().ServiceBroker,
				TestSetup,
			)
			broker.Push(Config)
			broker.Configure()
			broker.Create()
			broker.PublicizePlans()
		})

		AfterEach(func() {
			app_helpers.AppReport(broker.Name, Config.DefaultTimeoutDuration())

			broker.Destroy()
		})

		Context("just service instances", func() {
			var instanceName string
			AfterEach(func() {
				if instanceName != "" {
					Expect(cf.Cf("delete-service", instanceName, "-f").Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
				}
			})

			It("can create a service instance", func() {
				tags := "['tag1', 'tag2']"
				type Params struct{ Param1 string }
	return false, AppUsageEvent{}
}

var _ = Describe("Application Lifecycle", func() {
	var appName string

	BeforeEach(func() {
		appName = generator.PrefixedRandomName("CATS-APP-")

		Expect(cf.Cf("push", appName, "--no-start", "-b", config.RubyBuildpackName, "-m", DEFAULT_MEMORY_LIMIT, "-p", assets.NewAssets().Dora, "-d", config.AppsDomain).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		app_helpers.SetBackend(appName)
		Expect(cf.Cf("start", appName).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))
	})

	AfterEach(func() {
		app_helpers.AppReport(appName, DEFAULT_TIMEOUT)

		Expect(cf.Cf("delete", appName, "-f", "-r").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})

	Describe("pushing", func() {
		It("makes the app reachable via its bound route", func() {
			Eventually(func() string {
				return helpers.CurlAppRoot(appName)
			}, DEFAULT_TIMEOUT).Should(ContainSubstring("Hi, I'm Dora!"))
		})

		Describe("Context path", func() {
			var app2 string
			var path = "/imposter_dora"
						acls = cf.Cf("service-access", "-e", broker.Service.Name).Wait(DEFAULT_TIMEOUT)
						Expect(acls).To(Exit(0))
						output = acls.Out.Contents()
						Expect(output).To(ContainSubstring(broker.Service.Name))

						expectedOutput := fmt.Sprintf(accessOutput, broker.Service.Name, globallyPublicPlan.Name, "none")
						Expect(output).To(MatchRegexp(expectedOutput))
						expectedOutput = fmt.Sprintf(accessOutput, broker.Service.Name, orgPublicPlan.Name, "none")
						Expect(output).To(MatchRegexp(expectedOutput))
					})
				})
			})
		})

		AfterEach(func() {
			app_helpers.AppReport(broker.Name, DEFAULT_TIMEOUT)

			broker.Destroy()
		})
	})

	Describe("private brokers", func() {
		BeforeEach(func() {
			broker = NewServiceBroker(
				generator.PrefixedRandomName("prbr-"),
				assets.NewAssets().ServiceBroker,
				context,
			)
			cf.TargetSpace(context.RegularUserContext(), context.ShortTimeout())
			broker.Push()
			broker.Configure()
			Expect(cf.Cf("create-shared-domain", domainName).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))
		})

		appNameDora = generator.PrefixedRandomName("CATS-APP-")
		Expect(cf.Cf("push", appNameDora, "--no-start", "-b", config.RubyBuildpackName, "-m", DEFAULT_MEMORY_LIMIT, "-p", assets.NewAssets().Dora, "-d", config.AppsDomain).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		app_helpers.SetBackend(appNameDora)
		Expect(cf.Cf("start", appNameDora).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))

		appNameSimple = generator.PrefixedRandomName("CATS-APP-")
		Expect(cf.Cf("push", appNameSimple, "--no-start", "-b", config.RubyBuildpackName, "-m", DEFAULT_MEMORY_LIMIT, "-p", assets.NewAssets().HelloWorld, "-d", config.AppsDomain).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		app_helpers.SetBackend(appNameSimple)
		Expect(cf.Cf("start", appNameSimple).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))
	})

	AfterEach(func() {
		app_helpers.AppReport(appNameDora, DEFAULT_TIMEOUT)
		app_helpers.AppReport(appNameSimple, DEFAULT_TIMEOUT)

		cf.AsUser(context.AdminUserContext(), DEFAULT_TIMEOUT, func() {
			Expect(cf.Cf("target", "-o", orgName).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
			Expect(cf.Cf("delete-shared-domain", domainName, "-f").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		})

		Expect(cf.Cf("delete", appNameDora, "-f", "-r").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		Expect(cf.Cf("delete", appNameSimple, "-f", "-r").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})

	Describe("Adding a wildcard route to a domain", func() {
		It("completes successfully", func() {
			wildCardRoute := "*"
			regularRoute := "bar"
		domain   string
	)

	BeforeEach(func() {
		app1 = PushApp(helloRoutingAsset, config.RubyBuildpackName)
		app2 = PushApp(helloRoutingAsset, config.RubyBuildpackName)
		app3 = PushApp(helloRoutingAsset, config.RubyBuildpackName)

		domain = app1

		MapRouteToApp(domain, app2Path, app2)
		MapRouteToApp(domain, app3Path, app3)
	})

	AfterEach(func() {
		app_helpers.AppReport(app1, DEFAULT_TIMEOUT)
		app_helpers.AppReport(app2, DEFAULT_TIMEOUT)
		app_helpers.AppReport(app3, DEFAULT_TIMEOUT)

		DeleteApp(app1)
		DeleteApp(app2)
		DeleteApp(app3)
	})

	Context("when another app has a route with a context path", func() {
		It("routes to app with context path", func() {
			Eventually(func() string {
				return helpers.CurlAppRoot(domain)
			}, DEFAULT_TIMEOUT).Should(ContainSubstring(app1))

			Eventually(func() string {
)

var _ = AppsDescribe("Uploading and Downloading droplets", func() {
	var helloWorldAppName string
	var out bytes.Buffer

	BeforeEach(func() {
		helloWorldAppName = random_name.CATSRandomName("APP")

		Expect(cf.Cf("push", helloWorldAppName, "--no-start", "-b", Config.GetRubyBuildpackName(), "-m", DEFAULT_MEMORY_LIMIT, "-p", assets.NewAssets().HelloWorld, "-d", Config.GetAppsDomain()).Wait(Config.CfPushTimeoutDuration())).To(Exit(0))
		app_helpers.SetBackend(helloWorldAppName)
		Expect(cf.Cf("start", helloWorldAppName).Wait(Config.CfPushTimeoutDuration())).To(Exit(0))
	})

	AfterEach(func() {
		app_helpers.AppReport(helloWorldAppName, Config.DefaultTimeoutDuration())

		Expect(cf.Cf("delete", helloWorldAppName, "-f", "-r").Wait(Config.DefaultTimeoutDuration())).To(Exit(0))
	})

	It("Users can manage droplet bits for an app", func() {
		By("Downloading the droplet for the app")

		guid := cf.Cf("app", helloWorldAppName, "--guid").Wait(Config.DefaultTimeoutDuration()).Out.Contents()
		appGuid := strings.TrimSpace(string(guid))

		tmpdir, err := ioutil.TempDir(os.TempDir(), "droplet-download")
		Expect(err).ToNot(HaveOccurred())

		app_droplet_path := path.Join(tmpdir, helloWorldAppName)
			Eventually(cf.Cf("push", listenerAppName, "--no-start", "--health-check-type", "port", "-b", Config.GetGoBuildpackName(), "-m", DEFAULT_MEMORY_LIMIT, "-p", assets.NewAssets().SyslogDrainListener, "-d", Config.GetAppsDomain(), "-f", assets.NewAssets().SyslogDrainListener+"/manifest.yml"), Config.DefaultTimeoutDuration()).Should(Exit(0), "Failed to push app")
			Eventually(cf.Cf("push", logWriterAppName, "--no-start", "-b", Config.GetRubyBuildpackName(), "-m", DEFAULT_MEMORY_LIMIT, "-p", assets.NewAssets().RubySimple, "-d", Config.GetAppsDomain()), Config.DefaultTimeoutDuration()).Should(Exit(0), "Failed to push app")

			app_helpers.SetBackend(listenerAppName)
			app_helpers.SetBackend(logWriterAppName)

			Expect(cf.Cf("start", listenerAppName).Wait(Config.CfPushTimeoutDuration())).To(Exit(0))
			Expect(cf.Cf("start", logWriterAppName).Wait(Config.CfPushTimeoutDuration())).To(Exit(0))
		})

		AfterEach(func() {
			logs.Kill()
			close(interrupt)

			app_helpers.AppReport(logWriterAppName, Config.DefaultTimeoutDuration())
			app_helpers.AppReport(listenerAppName, Config.DefaultTimeoutDuration())

			Eventually(cf.Cf("delete", logWriterAppName, "-f", "-r"), Config.DefaultTimeoutDuration()).Should(Exit(0), "Failed to delete app")
			Eventually(cf.Cf("delete", listenerAppName, "-f", "-r"), Config.DefaultTimeoutDuration()).Should(Exit(0), "Failed to delete app")
			if serviceName != "" {
				Eventually(cf.Cf("delete-service", serviceName, "-f"), Config.DefaultTimeoutDuration()).Should(Exit(0), "Failed to delete service")
			}

			Eventually(cf.Cf("delete-orphaned-routes", "-f"), Config.CfPushTimeoutDuration()).Should(Exit(0), "Failed to delete orphaned routes")
		})

		It("forwards app messages to registered syslog drains", func() {
			syslogDrainURL := "syslog://" + getSyslogDrainAddress(listenerAppName)

			Eventually(cf.Cf("cups", serviceName, "-l", syslogDrainURL), Config.DefaultTimeoutDuration()).Should(Exit(0), "Failed to create syslog drain service")
			"--no-start",
			"-b", config.RubyBuildpackName,
			"-m", DEFAULT_MEMORY_LIMIT,
			"-p", assets.NewAssets().Golang,
			"-d", config.AppsDomain,
		).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		Expect(cf.Cf("push", helloWorldAppName,
			"--no-start",
			"-m", DEFAULT_MEMORY_LIMIT,
			"-p", assets.NewAssets().HelloWorld,
			"-d", config.AppsDomain,
		).Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})

	AfterEach(func() {
		app_helpers.AppReport(golangAppName, DEFAULT_TIMEOUT)
		app_helpers.AppReport(helloWorldAppName, DEFAULT_TIMEOUT)

		Expect(cf.Cf("delete", golangAppName, "-f", "-r").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
		Expect(cf.Cf("delete", helloWorldAppName, "-f", "-r").Wait(DEFAULT_TIMEOUT)).To(Exit(0))
	})

	It("Copies over the package from the source app to the destination app", func() {
		app_helpers.SetBackend(golangAppName)
		Expect(cf.Cf("copy-source", helloWorldAppName, golangAppName).Wait(CF_PUSH_TIMEOUT)).To(Exit(0))

		Eventually(func() string {
			return helpers.CurlAppRoot(golangAppName)
		}, DEFAULT_TIMEOUT).Should(ContainSubstring("Hello, world!"))
	})
})
		BeforeEach(func() {
			clientAppName = random_name.CATSRandomName("APP")
			pushApp(clientAppName, Config.GetRubyBuildpackName())
			Expect(cf.Cf("start", clientAppName).Wait(Config.CfPushTimeoutDuration())).To(Exit(0))

			By("Asserting default running security group configuration for traffic between containers")
			doraCurlResponse := testAppConnectivity(clientAppName, privateHost, privatePort)
			Expect(doraCurlResponse.ReturnCode).NotTo(Equal(0), "Expected default running security groups not to allow internal communication between app containers. Configure your running security groups to not allow traffic on internal networks, or disable this test by setting 'include_security_groups' to 'false' in '"+os.Getenv("CONFIG")+"'.")

			By("Asserting default running security group configuration from a running container to an external destination")
			doraCurlResponse = testAppConnectivity(clientAppName, "www.google.com", 80)
			Expect(doraCurlResponse.ReturnCode).To(Equal(0), "Expected default running security groups to allow external traffic from app containers. Configure your running security groups to not allow traffic on internal networks, or disable this test by setting 'include_security_groups' to 'false' in '"+os.Getenv("CONFIG")+"'.")
		})

		AfterEach(func() {
			app_helpers.AppReport(serverAppName, Config.DefaultTimeoutDuration())
			Expect(cf.Cf("delete", serverAppName, "-f", "-r").Wait(Config.CfPushTimeoutDuration())).To(Exit(0))

			app_helpers.AppReport(clientAppName, Config.DefaultTimeoutDuration())
			Expect(cf.Cf("delete", clientAppName, "-f", "-r").Wait(Config.CfPushTimeoutDuration())).To(Exit(0))

			deleteSecurityGroup(securityGroupName)
		})

		It("allows ip traffic between containers after applying a security group and blocks it when the security group is removed", func() {
			if Config.GetIncludeContainerNetworking() {
				Skip("Skipping this test because Config.ContainerNetworking is set to 'true'.")
			}

			containerIp, containerPort := getAppContainerIpAndPort(serverAppName)
			securityGroupName = createSecurityGroup(