BeforeEach(func() {
		var err error
		address = fmt.Sprintf("127.0.0.1:%d", 4001+GinkgoParallelNode())
		sandboxRepoDir, err = ioutil.TempDir("", "sandbox")
		Expect(err).NotTo(HaveOccurred())

		logger = lagertest.NewTestLogger("test")
		threadLocker := &ossupport.OSLocker{}

		// sandboxRepo, err = namespace.NewRepository(logger, sandboxRepoDir, threadLocker)
		// Expect(err).NotTo(HaveOccurred())

		containerRepoDir, err := ioutil.TempDir("", "containers")
		Expect(err).NotTo(HaveOccurred())

		containerRepo, err = namespace.NewRepository(logger, containerRepoDir, threadLocker)
		Expect(err).NotTo(HaveOccurred())

		guid, err := uuid.NewV4()
		Expect(err).NotTo(HaveOccurred())

		containerNamespace, err = containerRepo.Create(guid.String())
		Expect(err).NotTo(HaveOccurred())

		configFilePath = writeConfigFile(config.Daemon{
			ListenHost:        "127.0.0.1",
			ListenPort:        4001 + GinkgoParallelNode(),
			LocalSubnet:       "192.168.1.0/16",
			OverlayNetwork:    "192.168.0.0/16",
			SandboxDir:        sandboxRepoDir,
			Database:          testDatabase.DBConfig(),
var _ = Describe("Repository", func() {
	var (
		repo         namespace.Repository
		logger       *lagertest.TestLogger
		threadLocker *fakes.OSThreadLocker
		dir          string
	)

	BeforeEach(func() {
		var err error
		dir, err = ioutil.TempDir("", "path")
		Expect(err).NotTo(HaveOccurred())

		logger = lagertest.NewTestLogger("test")
		threadLocker = &fakes.OSThreadLocker{}
		repo, err = namespace.NewRepository(logger, dir, threadLocker)
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		os.RemoveAll(dir)
	})

	Describe("PathOf", func() {
		It("returns the full path of a namespace in the repository", func() {
			Expect(repo.PathOf("some-namespace")).To(Equal(filepath.Join(dir, "some-namespace")))
		})
	})

	Describe("Destroy", func() {
		It("removes the namespace bind mount and file and logs the operation", func() {
func main() {
	var configFilePath string
	const configFileFlag = "configFile"

	cf_lager.AddFlags(flag.CommandLine)
	flag.StringVar(&configFilePath, configFileFlag, "", "")
	flag.Parse()

	conf, err := config.ParseConfigFile(configFilePath)
	if err != nil {
		log.Fatalf("parsing config: %s", err)
	}

	subnet := conf.LocalSubnet
	overlay := conf.OverlayNetwork

	if !overlay.Contains(subnet.IP) {
		log.Fatalf("overlay network does not contain local subnet")
	}

	retriableConnector := db.RetriableConnector{
		Connector:     db.GetConnectionPool,
		Sleeper:       db.SleeperFunc(time.Sleep),
		RetryInterval: 3 * time.Second,
		MaxRetries:    10,
	}

	databaseURL := conf.DatabaseURL
	dbConnectionPool, err := retriableConnector.GetConnectionPool(databaseURL)
	if err != nil {
		log.Fatalf("db connect: %s", err)
	}

	dataStore, err := store.New(dbConnectionPool)
	if err != nil {
		log.Fatalf("failed to construct datastore: %s", err)
	}

	logger, reconfigurableSink := cf_lager.New("ducatid")

	configFactory := &ipam.ConfigFactory{
		Config: types.IPConfig{
			IP: *subnet,
		},
	}

	ipAllocator := ipam.New(
		&ipam.StoreFactory{},
		&sync.Mutex{},
		configFactory,
		&sync.Mutex{},
	)

	rataHandlers := rata.Handlers{}

	addressManager := &ip.AddressManager{Netlinker: nl.Netlink}
	routeManager := &ip.RouteManager{Netlinker: nl.Netlink}
	linkFactory := &links.Factory{Netlinker: nl.Netlink}
	osThreadLocker := &ossupport.OSLocker{}

	sandboxNamespaceRepo, err := namespace.NewRepository(logger, conf.SandboxRepoDir, osThreadLocker)
	if err != nil {
		log.Fatalf("unable to make repo: %s", err) // not tested
	}

	namespaceOpener := &namespace.PathOpener{
		Logger:       logger,
		ThreadLocker: osThreadLocker,
	}

	subscriber := &subscriber.Subscriber{
		Logger:    logger.Session("subscriber"),
		Netlinker: nl.Netlink,
	}
	resolver := &watcher.Resolver{
		Logger: logger,
		Store:  dataStore,
	}
	arpInserter := &neigh.ARPInserter{
		Logger:    logger,
		Netlinker: nl.Netlink,
	}
	missWatcher := watcher.New(
		logger,
		subscriber,
		&sync.Mutex{},
		resolver,
		arpInserter,
	)
	networkMapper := &network.FixedNetworkMapper{DefaultNetworkID: "default"}

	reloader := &reloader.Reloader{
		Watcher: missWatcher,
	}

	sandboxRepo := &sandbox.Repository{
		Logger:         logger.Session("sandbox-repository"),
		Locker:         &sync.Mutex{},
		NamespaceRepo:  sandboxNamespaceRepo,
		Invoker:        sandbox.InvokeFunc(ifrit.Invoke),
		LinkFactory:    linkFactory,
		Watcher:        missWatcher,
		SandboxFactory: sandbox.NewSandboxFunc(sandbox.New),
		Sandboxes:      map[string]sandbox.Sandbox{},
	}

	hostNamespace, err := namespaceOpener.OpenPath("/proc/self/ns/net")
	if err != nil {
		log.Fatalf("unable to open host namespace: %s", err) // not tested
	}
	commandBuilder := &container.CommandBuilder{
		MissWatcher:   missWatcher,
		HostNamespace: hostNamespace,
	}
	dnsFactory := &executor.DNSFactory{
		Logger:           logger,
		ExternalServer:   fmt.Sprintf("%s:%d", conf.ExternalDNSServer, 53),
		Suffix:           conf.Suffix,
		DucatiAPI:        "http://" + conf.ListenAddress,
		DecoratorFactory: executor.WriterDecoratorFactoryFunc(executor.NamespaceDecoratorFactory),
	}
	executor := executor.New(
		logger,
		addressManager,
		routeManager,
		linkFactory,
		sandboxNamespaceRepo,
		sandboxRepo,
		executor.ListenUDPFunc(net.ListenUDP),
		dnsFactory,
	)
	creator := &container.Creator{
		Executor:        executor,
		SandboxRepo:     sandboxRepo,
		Watcher:         missWatcher,
		CommandBuilder:  commandBuilder,
		DNSAddress:      fmt.Sprintf("%s:%d", conf.OverlayDNSAddress, 53),
		HostIP:          conf.HostAddress,
		NamespaceOpener: namespaceOpener,
	}
	deletor := &container.Deletor{
		Executor:        executor,
		NamespaceOpener: namespaceOpener,
	}

	addController := &cni.AddController{
		IPAllocator:   ipAllocator,
		NetworkMapper: networkMapper,
		Creator:       creator,
		Datastore:     dataStore,
	}

	delController := &cni.DelController{
		Datastore:     dataStore,
		Deletor:       deletor,
		IPAllocator:   ipAllocator,
		NetworkMapper: networkMapper,
	}

	marshaler := marshal.MarshalFunc(json.Marshal)
	unmarshaler := marshal.UnmarshalFunc(json.Unmarshal)

	rataHandlers["get_container"] = &handlers.GetContainer{
		Marshaler: marshaler,
		Logger:    logger,
		Datastore: dataStore,
	}

	rataHandlers["networks_list_containers"] = &handlers.NetworksListContainers{
		Marshaler: marshaler,
		Logger:    logger,
		Datastore: dataStore,
	}

	rataHandlers["list_containers"] = &handlers.ListContainers{
		Marshaler: marshaler,
		Logger:    logger,
		Datastore: dataStore,
	}

	rataHandlers["cni_add"] = &handlers.CNIAdd{
		Logger:      logger,
		Marshaler:   marshaler,
		Unmarshaler: unmarshaler,
		Controller:  addController,
	}

	rataHandlers["cni_del"] = &handlers.CNIDel{
		Logger:      logger,
		Marshaler:   marshaler,
		Unmarshaler: unmarshaler,
		Controller:  delController,
	}

	routes := rata.Routes{
		{Name: "get_container", Method: "GET", Path: "/containers/:container_id"},
		{Name: "networks_list_containers", Method: "GET", Path: "/networks/:network_id"},
		{Name: "list_containers", Method: "GET", Path: "/containers"},
		{Name: "cni_add", Method: "POST", Path: "/cni/add"},
		{Name: "cni_del", Method: "POST", Path: "/cni/del"},
	}

	rataRouter, err := rata.NewRouter(routes, rataHandlers)
	if err != nil {
		log.Fatalf("unable to create rata Router: %s", err) // not tested
	}

	err = sandboxRepo.Load(conf.SandboxRepoDir)
	if err != nil {
		log.Fatalf("unable to load sandboxRepo: %s", err)
	}

	err = sandboxRepo.ForEach(reloader)
	if err != nil {
		log.Fatalf("unable to restart monitors: %s", err)
	}

	httpServer := http_server.New(conf.ListenAddress, rataRouter)

	members := grouper.Members{
		{"http_server", httpServer},
	}

	if conf.DebugAddress != "" {
		members = append(grouper.Members{
			{"debug-server", cf_debug_server.Runner(conf.DebugAddress, reconfigurableSink)},
		}, members...)
	}

	group := grouper.NewOrdered(os.Interrupt, members)

	monitor := ifrit.Invoke(sigmon.New(group))

	err = <-monitor.Wait()
	if err != nil {
		log.Fatalf("daemon terminated: %s", err)
	}
}
		var err error
		repoDir, err = ioutil.TempDir("", "ns-repo")
		Expect(err).NotTo(HaveOccurred())

		logger = lagertest.NewTestLogger("test")
		threadLocker = &fakes.OSThreadLocker{}
	})

	AfterEach(func() {
		err := os.RemoveAll(repoDir)
		Expect(err).NotTo(HaveOccurred())
	})

	Describe("NewRepository", func() {
		It("returns a repository", func() {
			repo, err := namespace.NewRepository(logger, repoDir, threadLocker)
			Expect(err).NotTo(HaveOccurred())
			Expect(repo).NotTo(BeNil())
		})

		Context("when the target directory does not exist", func() {
			BeforeEach(func() {
				err := os.RemoveAll(repoDir)
				Expect(err).NotTo(HaveOccurred())
			})

			It("creates the directory", func() {
				_, err := namespace.NewRepository(logger, repoDir, threadLocker)
				Expect(err).NotTo(HaveOccurred())

				info, err := os.Stat(repoDir)