func (d *Deletor) Delete(
	interfaceName string,
	containerNSPath string,
	sandboxName string,
	vxlanDeviceName string,
) error {
	containerNS, err := d.NamespaceOpener.OpenPath(containerNSPath)
	if err != nil {
		return fmt.Errorf("open container netns: %s", err)
	}

	err = d.Executor.Execute(
		commands.All(
			commands.InNamespace{
				Namespace: containerNS,
				Command: commands.DeleteLink{
					LinkName: interfaceName,
				},
			},

			commands.CleanupSandbox{
				SandboxName:     sandboxName,
				VxlanDeviceName: vxlanDeviceName,
			},
		),
	)
	if err != nil {
		return err
	}

	return nil
}
func (b *CommandBuilder) IdempotentlySetupBridge(
	vxlanName, sandboxLinkName, bridgeName string,
	sandboxNS namespace.Namespace,
	ipamResult *types.Result,
) executor.Command {
	return commands.InNamespace{
		Namespace: sandboxNS,
		Command: commands.All(
			commands.SetLinkUp{
				LinkName: sandboxLinkName,
			},
			commands.Unless{
				Condition: conditions.LinkExists{
					Name: bridgeName,
				},
				Command: commands.All(
					commands.CreateBridge{
						Name: bridgeName,
					},
					commands.AddAddress{
						InterfaceName: bridgeName,
						Address: net.IPNet{
							IP:   ipamResult.IP4.Gateway,
							Mask: ipamResult.IP4.IP.Mask,
						},
					},
					commands.SetLinkUp{
						LinkName: bridgeName,
					},
					commands.SetLinkMaster{
						Master: bridgeName,
						Slave:  commands.DNS_INTERFACE_NAME,
					},
				),
			},
			commands.SetLinkMaster{
				Master: bridgeName,
				Slave:  vxlanName,
			},
			commands.SetLinkMaster{
				Master: bridgeName,
				Slave:  sandboxLinkName,
			},
		),
	}
}
func (b *CommandBuilder) AddRoutes(interfaceName string, ipConfig *types.IPConfig) executor.Command {
	var routeCommands []executor.Command
	for _, route := range ipConfig.Routes {
		routeCommand := commands.AddRoute{
			Interface:   interfaceName,
			Destination: route.Dst,
			Gateway:     route.GW,
		}

		if routeCommand.Gateway == nil {
			routeCommand.Gateway = ipConfig.Gateway
		}

		routeCommands = append(routeCommands, routeCommand)
	}

	return commands.All(routeCommands...)
}
func (b *CommandBuilder) IdempotentlyCreateVxlan(
	vxlanName string,
	sandboxName string,
	sandboxNS namespace.Namespace,
) executor.Command {

	return commands.All(
		commands.InNamespace{
			Namespace: sandboxNS,
			Command: commands.SetLinkUp{
				LinkName: vxlanName,
			},
		},
		commands.StartMonitor{
			HostNamespace: b.HostNamespace,
			Watcher:       b.MissWatcher,
			SandboxName:   sandboxName,
			VxlanLinkName: vxlanName,
		},
	)
}
func (b *CommandBuilder) IdempotentlyCreateSandbox(sandboxName, vxlanName string, vni int, dnsAddress string) executor.Command {
	return commands.Unless{
		Condition: conditions.SandboxExists{
			Name: sandboxName,
		},
		Command: commands.All(
			commands.CreateSandbox{
				Name: sandboxName,
			},
			commands.CreateVxlan{
				Name: vxlanName,
				VNI:  vni,
			},
			commands.MoveLink{
				Name:        vxlanName,
				SandboxName: sandboxName,
			},
			commands.StartDNSServer{
				SandboxName:   sandboxName,
				ListenAddress: dnsAddress,
			},
		),
	}
}
		})
	})

	It("should construct the correct command sequence", func() {
		err := deletor.Delete("some-interface-name", "/path/to/container/namespace", "sandbox-name", "some-vxlan")
		Expect(err).NotTo(HaveOccurred())

		Expect(executor.ExecuteCallCount()).To(Equal(1))
		Expect(executor.ExecuteArgsForCall(0)).To(Equal(
			commands.All(
				commands.InNamespace{
					Namespace: containerNS,
					Command: commands.DeleteLink{
						LinkName: "some-interface-name",
					},
				},

				commands.CleanupSandbox{
					SandboxName:     "sandbox-name",
					VxlanDeviceName: "some-vxlan",
				},
			),
		))
	})

	Context("when executing fails", func() {
		BeforeEach(func() {
			executor.ExecuteReturns(errors.New("boom"))
		})

		It("should return the error", func() {
func (c *Creator) Setup(config CreatorConfig) (models.Container, error) {
	vxlanName := fmt.Sprintf("vxlan%d", config.VNI)
	sandboxName := fmt.Sprintf("vni-%d", config.VNI)
	bridgeName := fmt.Sprintf("vxlanbr%d", config.VNI)

	containerNS, err := c.NamespaceOpener.OpenPath(config.ContainerNsPath)
	if err != nil {
		return models.Container{}, fmt.Errorf("open container netns: %s", err)
	}

	sandboxLinkName := NameSandboxLink(config.ContainerID)

	var routeCommands = c.CommandBuilder.AddRoutes(config.InterfaceName, config.IPAMResult.IP4)

	err = c.Executor.Execute(c.CommandBuilder.IdempotentlyCreateSandbox(sandboxName, vxlanName, config.VNI, c.DNSAddress))
	if err != nil {
		return models.Container{}, fmt.Errorf("executing command: create sandbox: %s", err)
	}

	sandbox, err := c.SandboxRepo.Get(sandboxName)
	if err != nil {
		return models.Container{}, fmt.Errorf("get sandbox: %s", err)
	}
	sandbox.Lock()
	defer sandbox.Unlock()

	sandboxNS := sandbox.Namespace()
	err = c.Executor.Execute(
		commands.All(
			c.CommandBuilder.IdempotentlyCreateVxlan(vxlanName, sandboxName, sandboxNS),
			c.CommandBuilder.SetupVeth(containerNS, sandboxLinkName, config.InterfaceName, config.IPAMResult.IP4.IP, sandboxName, routeCommands),
			c.CommandBuilder.IdempotentlySetupBridge(vxlanName, sandboxLinkName, bridgeName, sandboxNS, config.IPAMResult),
		),
	)
	if err != nil {
		return models.Container{}, err
	}

	getHardwareAddressCommand := &commands.GetHardwareAddress{
		LinkName: config.InterfaceName,
	}

	command := commands.InNamespace{
		Namespace: containerNS,
		Command:   getHardwareAddressCommand,
	}
	err = c.Executor.Execute(command)
	if err != nil {
		return models.Container{}, err
	}

	return models.Container{
		ID:          config.ContainerID,
		MAC:         getHardwareAddressCommand.Result.String(),
		IP:          config.IPAMResult.IP4.IP.IP.String(),
		NetworkID:   config.NetworkID,
		HostIP:      c.HostIP.String(),
		SandboxName: sandboxName,
		App:         config.App,
	}, nil
}
			command3 *fakes.Command
			all      executor.Command
		)

		BeforeEach(func() {
			context = &fakes.Context{}

			command1 = &fakes.Command{}
			command2 = &fakes.Command{}
			command3 = &fakes.Command{}

			command1.StringReturns("some-command 1")
			command2.StringReturns("some-command 2")
			command3.StringReturns("some-command 3")

			all = commands.All(command1, command2, command3)
		})

		Describe("Execute", func() {
			It("creates a command wrapper that executes all commands", func() {
				err := all.Execute(context)
				Expect(err).NotTo(HaveOccurred())

				Expect(command1.ExecuteCallCount()).To(Equal(1))
				Expect(command1.ExecuteArgsForCall(0)).To(Equal(context))

				Expect(command2.ExecuteCallCount()).To(Equal(1))
				Expect(command2.ExecuteArgsForCall(0)).To(Equal(context))

				Expect(command3.ExecuteCallCount()).To(Equal(1))
				Expect(command3.ExecuteArgsForCall(0)).To(Equal(context))
			cmd := b.IdempotentlyCreateSandbox("some-sandbox-name", "some-vxlan-name", 99, "some-dns-address")

			Expect(cmd).To(Equal(
				commands.Unless{
					Condition: conditions.SandboxExists{
						Name: "some-sandbox-name",
					},
					Command: commands.All(
						commands.CreateSandbox{
							Name: "some-sandbox-name",
						},
						commands.CreateVxlan{
							Name: "some-vxlan-name",
							VNI:  99,
						},
						commands.MoveLink{
							Name:        "some-vxlan-name",
							SandboxName: "some-sandbox-name",
						},
						commands.StartDNSServer{
							SandboxName:   "some-sandbox-name",
							ListenAddress: "some-dns-address",
						},
					),
				}))
		})
	})

	Describe("IdempotentlyCreateVxlan", func() {
		var sandboxNS *fakes.Namespace