Esempio n. 1
0
func (container *Container) updateNetworkSettings(n libnetwork.Network) error {
	if container.NetworkSettings == nil {
		container.NetworkSettings = &network.Settings{Networks: []string{}}
	}
	settings := container.NetworkSettings

	for _, s := range settings.Networks {
		sn, err := container.daemon.FindNetwork(s)
		if err != nil {
			continue
		}

		if sn.Name() == n.Name() {
			// Avoid duplicate config
			return nil
		}
		if !runconfig.NetworkMode(sn.Type()).IsPrivate() ||
			!runconfig.NetworkMode(n.Type()).IsPrivate() {
			return runconfig.ErrConflictSharedNetwork
		}
		if runconfig.NetworkMode(sn.Name()).IsNone() ||
			runconfig.NetworkMode(n.Name()).IsNone() {
			return runconfig.ErrConflictNoNetwork
		}
	}
	settings.Networks = append(settings.Networks, n.Name())

	return nil
}
Esempio n. 2
0
func (daemon *Daemon) updateNetworkSettings(container *Container, n libnetwork.Network) error {
	if container.NetworkSettings == nil {
		container.NetworkSettings = &network.Settings{Networks: make(map[string]*network.EndpointSettings)}
	}

	if !container.hostConfig.NetworkMode.IsHost() && runconfig.NetworkMode(n.Type()).IsHost() {
		return runconfig.ErrConflictHostNetwork
	}

	for s := range container.NetworkSettings.Networks {
		sn, err := daemon.FindNetwork(s)
		if err != nil {
			continue
		}

		if sn.Name() == n.Name() {
			// Avoid duplicate config
			return nil
		}
		if !runconfig.NetworkMode(sn.Type()).IsPrivate() ||
			!runconfig.NetworkMode(n.Type()).IsPrivate() {
			return runconfig.ErrConflictSharedNetwork
		}
		if runconfig.NetworkMode(sn.Name()).IsNone() ||
			runconfig.NetworkMode(n.Name()).IsNone() {
			return runconfig.ErrConflictNoNetwork
		}
	}
	container.NetworkSettings.Networks[n.Name()] = new(network.EndpointSettings)

	return nil
}
func UtilCreateNetworkMode(c *check.C, networkMode string) {
	config := map[string]interface{}{
		"Image":      "busybox",
		"HostConfig": map[string]interface{}{"NetworkMode": networkMode},
	}

	status, body, err := sockRequest("POST", "/containers/create", config)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusCreated)

	var container types.ContainerCreateResponse
	if err := json.Unmarshal(body, &container); err != nil {
		c.Fatal(err)
	}

	status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusOK)

	var containerJSON types.ContainerJSON
	if err := json.Unmarshal(body, &containerJSON); err != nil {
		c.Fatal(err)
	}

	if containerJSON.HostConfig.NetworkMode != runconfig.NetworkMode(networkMode) {
		c.Fatalf("Mismatched NetworkMode, Expected %s, Actual: %s ", networkMode, containerJSON.HostConfig.NetworkMode)
	}
}
Esempio n. 4
0
func (container *Container) initializeNetworking() error {
	var err error

	// Make sure NetworkMode has an acceptable value before
	// initializing networking.
	if container.hostConfig.NetworkMode == runconfig.NetworkMode("") {
		container.hostConfig.NetworkMode = runconfig.NetworkMode("bridge")
	}

	if container.hostConfig.NetworkMode.IsContainer() {
		// we need to get the hosts files from the container to join
		nc, err := container.getNetworkedContainer()
		if err != nil {
			return err
		}
		container.HostnamePath = nc.HostnamePath
		container.HostsPath = nc.HostsPath
		container.ResolvConfPath = nc.ResolvConfPath
		container.Config.Hostname = nc.Config.Hostname
		container.Config.Domainname = nc.Config.Domainname
		return nil
	}

	if container.daemon.config.DisableNetwork {
		container.Config.NetworkDisabled = true
	}

	if container.hostConfig.NetworkMode.IsHost() {
		container.Config.Hostname, err = os.Hostname()
		if err != nil {
			return err
		}

		parts := strings.SplitN(container.Config.Hostname, ".", 2)
		if len(parts) > 1 {
			container.Config.Hostname = parts[0]
			container.Config.Domainname = parts[1]
		}

	}

	if err := container.AllocateNetwork(); err != nil {
		return err
	}

	return container.buildHostnameFile()
}
Esempio n. 5
0
func setupNetworking(netMode string, launchConfig *rancherClient.LaunchConfig) {
	if netMode == "" {
		launchConfig.NetworkMode = "managed"
	} else if runconfig.NetworkMode(netMode).IsContainer() {
		launchConfig.NetworkMode = "container"
		launchConfig.NetworkLaunchConfig = strings.TrimPrefix(netMode, "container:")
	} else {
		launchConfig.NetworkMode = netMode
	}
}
// DisconnectFromNetwork disconnects container from network n.
func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network) error {
	if !container.Running {
		return derr.ErrorCodeNotRunning.WithArgs(container.ID)
	}

	if container.HostConfig.NetworkMode.IsHost() && runconfig.NetworkMode(n.Type()).IsHost() {
		return runconfig.ErrConflictHostNetwork
	}

	return disconnectFromNetwork(container, n)
}
func (daemon *Daemon) updateEndpointNetworkSettings(container *container.Container, n libnetwork.Network, ep libnetwork.Endpoint) error {
	if err := container.BuildEndpointInfo(n, ep); err != nil {
		return err
	}

	if container.HostConfig.NetworkMode == runconfig.NetworkMode("bridge") {
		container.NetworkSettings.Bridge = daemon.configStore.Bridge.Iface
	}

	return nil
}
Esempio n. 8
0
func (container *Container) updateEndpointNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error {
	networkSettings, err := container.buildEndpointInfo(n, ep, container.NetworkSettings)
	if err != nil {
		return err
	}

	if container.hostConfig.NetworkMode == runconfig.NetworkMode("bridge") {
		networkSettings.Bridge = container.daemon.configStore.Bridge.Iface
	}

	return nil
}
Esempio n. 9
0
func createLaunchConfig(r *RancherService, name string, serviceConfig *project.ServiceConfig) (rancherClient.LaunchConfig, error) {
	var result rancherClient.LaunchConfig

	rancherConfig := r.context.RancherConfig[name]

	schemasUrl := strings.SplitN(r.Context().Client.Schemas.Links["self"], "/schemas", 2)[0]
	scriptsUrl := schemasUrl + "/scripts/transform"

	config, hostConfig, err := docker.Convert(serviceConfig)
	if err != nil {
		return result, err
	}

	dockerContainer := &ContainerInspect{
		Config:     config,
		HostConfig: hostConfig,
	}

	dockerContainer.HostConfig.NetworkMode = runconfig.NetworkMode("")
	dockerContainer.Name = "/" + name

	err = r.Context().Client.Post(scriptsUrl, dockerContainer, &result)
	if err != nil {
		return result, err
	}

	setupNetworking(serviceConfig.Net, &result)
	setupVolumesFrom(serviceConfig.VolumesFrom, &result)

	err = setupBuild(r, name, &result, serviceConfig)

	if result.Labels == nil {
		result.Labels = map[string]interface{}{}
	}

	result.Kind = rancherConfig.Type
	result.Vcpu = rancherConfig.Vcpu
	result.Userdata = rancherConfig.Userdata
	result.MemoryMb = rancherConfig.Memory
	result.Disks = []interface{}{}
	for _, i := range rancherConfig.Disks {
		result.Disks = append(result.Disks, i)
	}

	if strings.EqualFold(result.Kind, "virtual_machine") || strings.EqualFold(result.Kind, "virtualmachine") {
		result.Kind = "virtualMachine"
	}

	return result, err
}
Esempio n. 10
0
func createNetwork(controller libnetwork.NetworkController, dnet string, driver string) (libnetwork.Network, error) {
	createOptions := []libnetwork.NetworkOption{}
	genericOption := options.Generic{}

	// Bridge driver is special due to legacy reasons
	if runconfig.NetworkMode(driver).IsBridge() {
		genericOption[netlabel.GenericData] = map[string]string{
			bridge.BridgeName: dnet,
		}
		networkOption := libnetwork.NetworkOptionGeneric(genericOption)
		createOptions = append(createOptions, networkOption)
	}

	return controller.NewNetwork(driver, dnet, createOptions...)
}
Esempio n. 11
0
func (container *Container) allocateNetwork() error {
	mode := container.hostConfig.NetworkMode
	controller := container.daemon.netController
	if container.Config.NetworkDisabled || mode.IsContainer() {
		return nil
	}

	networkDriver := string(mode)
	service := container.Config.PublishService
	networkName := mode.NetworkName()
	if mode.IsDefault() {
		if service != "" {
			service, networkName, networkDriver = parseService(controller, service)
		} else {
			networkName = controller.Config().Daemon.DefaultNetwork
			networkDriver = controller.Config().Daemon.DefaultDriver
		}
	} else if service != "" {
		return derr.ErrorCodeNetworkConflict
	}

	if runconfig.NetworkMode(networkDriver).IsBridge() && container.daemon.configStore.DisableBridge {
		container.Config.NetworkDisabled = true
		return nil
	}

	if service == "" {
		// dot character "." has a special meaning to support SERVICE[.NETWORK] format.
		// For backward compatibility, replacing "." with "-", instead of failing
		service = strings.Replace(container.Name, ".", "-", -1)
		// Service names dont like "/" in them. removing it instead of failing for backward compatibility
		service = strings.Replace(service, "/", "", -1)
	}

	if container.secondaryNetworkRequired(networkDriver) {
		// Configure Bridge as secondary network for port binding purposes
		if err := container.configureNetwork("bridge", service, "bridge", false); err != nil {
			return err
		}
	}

	if err := container.configureNetwork(networkName, service, networkDriver, mode.IsDefault()); err != nil {
		return err
	}

	return container.writeHostConfig()
}
Esempio n. 12
0
// DisconnectFromNetwork disconnects a container from a network
func (container *Container) DisconnectFromNetwork(n libnetwork.Network) error {
	if !container.Running {
		return derr.ErrorCodeNotRunning.WithArgs(container.ID)
	}

	if container.hostConfig.NetworkMode.IsHost() && runconfig.NetworkMode(n.Type()).IsHost() {
		return runconfig.ErrConflictHostNetwork
	}

	if err := container.disconnectFromNetwork(n); err != nil {
		return err
	}

	if err := container.toDiskLocking(); err != nil {
		return fmt.Errorf("Error saving container to disk: %v", err)
	}
	return nil
}
Esempio n. 13
0
func createLaunchConfig(r *RancherService, serviceConfig *project.ServiceConfig) (rancherClient.LaunchConfig, error) {
	var result rancherClient.LaunchConfig

	schemasUrl := strings.SplitN(r.Context().Client.Schemas.Links["self"], "/schemas", 2)[0]
	scriptsUrl := schemasUrl + "/scripts/transform"

	config, hostConfig, err := docker.Convert(serviceConfig)
	if err != nil {
		return result, err
	}

	dockerContainer := &ContainerInspect{
		Config:     config,
		HostConfig: hostConfig,
	}

	dockerContainer.HostConfig.NetworkMode = runconfig.NetworkMode("")

	if serviceConfig.Name != "" {
		dockerContainer.Name = "/" + serviceConfig.Name
	} else {
		dockerContainer.Name = "/" + r.name
	}

	err = r.Context().Client.Post(scriptsUrl, dockerContainer, &result)
	if err != nil {
		return result, err
	}

	result.HealthCheck = r.HealthCheck()

	setupNetworking(serviceConfig.Net, &result)
	setupVolumesFrom(serviceConfig.VolumesFrom, &result)

	err = r.setupBuild(&result, serviceConfig)

	if result.Labels == nil {
		result.Labels = map[string]interface{}{}
	}

	return result, err
}
Esempio n. 14
0
func (container *Container) updateEndpointNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error {
	networkSettings := &network.Settings{NetworkID: n.ID(), EndpointID: ep.ID()}

	networkSettings, err := container.buildPortMapInfo(ep, networkSettings)
	if err != nil {
		return err
	}

	networkSettings, err = container.buildEndpointInfo(ep, networkSettings)
	if err != nil {
		return err
	}

	if container.hostConfig.NetworkMode == runconfig.NetworkMode("bridge") {
		networkSettings.Bridge = container.daemon.configStore.Bridge.Iface
	}

	container.NetworkSettings = networkSettings
	return nil
}
Esempio n. 15
0
func UtilCreateNetworkMode(c *check.C, networkMode string) {
	config := map[string]interface{}{
		"Image":      "busybox",
		"HostConfig": map[string]interface{}{"NetworkMode": networkMode},
	}

	status, body, err := sockRequest("POST", "/containers/create", config)
	c.Assert(err, checker.IsNil)
	c.Assert(status, checker.Equals, http.StatusCreated)

	var container types.ContainerCreateResponse
	c.Assert(json.Unmarshal(body, &container), checker.IsNil)

	status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
	c.Assert(err, checker.IsNil)
	c.Assert(status, checker.Equals, http.StatusOK)

	var containerJSON types.ContainerJSON
	c.Assert(json.Unmarshal(body, &containerJSON), checker.IsNil)
	c.Assert(containerJSON.HostConfig.NetworkMode, checker.Equals, runconfig.NetworkMode(networkMode), check.Commentf("Mismatched NetworkMode"))
}
Esempio n. 16
0
func (daemon *Daemon) connectToNetwork(container *Container, idOrName string, updateSettings bool) (err error) {
	if container.hostConfig.NetworkMode.IsContainer() {
		return runconfig.ErrConflictSharedNetwork
	}

	if runconfig.NetworkMode(idOrName).IsBridge() &&
		daemon.configStore.DisableBridge {
		container.Config.NetworkDisabled = true
		return nil
	}

	controller := daemon.netController

	n, err := daemon.FindNetwork(idOrName)
	if err != nil {
		return err
	}

	if updateSettings {
		if err := daemon.updateNetworkSettings(container, n); err != nil {
			return err
		}
	}

	ep, err := container.getEndpointInNetwork(n)
	if err == nil {
		return fmt.Errorf("container already connected to network %s", idOrName)
	}

	if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok {
		return err
	}

	createOptions, err := container.buildCreateEndpointOptions(n)
	if err != nil {
		return err
	}

	endpointName := strings.TrimPrefix(container.Name, "/")
	ep, err = n.CreateEndpoint(endpointName, createOptions...)
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			if e := ep.Delete(); e != nil {
				logrus.Warnf("Could not rollback container connection to network %s", idOrName)
			}
		}
	}()

	if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil {
		return err
	}

	sb := daemon.getNetworkSandbox(container)
	if sb == nil {
		options, err := daemon.buildSandboxOptions(container, n)
		if err != nil {
			return err
		}
		sb, err = controller.NewSandbox(container.ID, options...)
		if err != nil {
			return err
		}

		container.updateSandboxNetworkSettings(sb)
	}

	if err := ep.Join(sb); err != nil {
		return err
	}

	if err := container.updateJoinInfo(n, ep); err != nil {
		return derr.ErrorCodeJoinInfo.WithArgs(err)
	}

	return nil
}
Esempio n. 17
0
func Convert(c *project.ServiceConfig) (*runconfig.Config, *runconfig.HostConfig, error) {
	vs := Filter(c.Volumes, isVolume)

	volumes := make(map[string]struct{}, len(vs))
	for _, v := range vs {
		volumes[v] = struct{}{}
	}

	ports, binding, err := nat.ParsePortSpecs(c.Ports)
	if err != nil {
		return nil, nil, err
	}
	restart, err := runconfig.ParseRestartPolicy(c.Restart)
	if err != nil {
		return nil, nil, err
	}

	if exposedPorts, _, err := nat.ParsePortSpecs(c.Expose); err != nil {
		return nil, nil, err
	} else {
		for k, v := range exposedPorts {
			ports[k] = v
		}
	}

	deviceMappings, err := parseDevices(c.Devices)
	if err != nil {
		return nil, nil, err
	}

	config := &runconfig.Config{
		Entrypoint:   runconfig.NewEntrypoint(c.Entrypoint.Slice()...),
		Hostname:     c.Hostname,
		Domainname:   c.DomainName,
		User:         c.User,
		Env:          c.Environment.Slice(),
		Cmd:          runconfig.NewCommand(c.Command.Slice()...),
		Image:        c.Image,
		Labels:       c.Labels.MapParts(),
		ExposedPorts: ports,
		Tty:          c.Tty,
		OpenStdin:    c.StdinOpen,
		WorkingDir:   c.WorkingDir,
		VolumeDriver: c.VolumeDriver,
		Volumes:      volumes,
	}
	host_config := &runconfig.HostConfig{
		VolumesFrom: c.VolumesFrom,
		CapAdd:      runconfig.NewCapList(c.CapAdd),
		CapDrop:     runconfig.NewCapList(c.CapDrop),
		CpuShares:   c.CpuShares,
		CpusetCpus:  c.CpuSet,
		ExtraHosts:  c.ExtraHosts,
		Privileged:  c.Privileged,
		Binds:       Filter(c.Volumes, isBind),
		Devices:     deviceMappings,
		Dns:         c.Dns.Slice(),
		DnsSearch:   c.DnsSearch.Slice(),
		LogConfig: runconfig.LogConfig{
			Type:   c.LogDriver,
			Config: c.LogOpt,
		},
		Memory:         c.MemLimit,
		MemorySwap:     c.MemSwapLimit,
		NetworkMode:    runconfig.NetworkMode(c.Net),
		ReadonlyRootfs: c.ReadOnly,
		PidMode:        runconfig.PidMode(c.Pid),
		UTSMode:        runconfig.UTSMode(c.Uts),
		IpcMode:        runconfig.IpcMode(c.Ipc),
		PortBindings:   binding,
		RestartPolicy:  restart,
		SecurityOpt:    c.SecurityOpt,
	}

	return config, host_config, nil
}
Esempio n. 18
0
func (container *Container) AllocateNetwork() error {
	mode := container.hostConfig.NetworkMode
	controller := container.daemon.netController
	if container.Config.NetworkDisabled || mode.IsContainer() {
		return nil
	}

	parts := strings.Split(string(mode), ":")

	switch {
	case len(parts) == 0:
		return nil
	case len(parts) == 1:
	case len(parts) == 2:
	default:
		return errors.New("networkname:ip not specified")
	}

	mode = runconfig.NetworkMode(parts[0])
	var networkName string
	var networkByName = false
	n, err := controller.NetworkByName(String(mode))
	if err == nil {
		networkName = string(mode)
		networkByName = true
	} else {
		networkName = mode.NetworkName
	}

	networkDriver := string(mode)
	service := container.Config.PublishService
	networkName := mode.NetworkName()
	if !networkByName && mode.IsDefault() {
		if service != "" {
			service, networkName, networkDriver = parseService(controller, service)
		} else {
			networkName = controller.Config().Daemon.DefaultNetwork
			networkDriver = controller.Config().Daemon.DefaultDriver
		}
	} else if service != "" {
		return fmt.Errorf("conflicting options: publishing a service and network mode")
	}

	if runconfig.NetworkMode(networkDriver).IsBridge() && container.daemon.config.DisableBridge {
		container.Config.NetworkDisabled = true
		return nil
	}

	if service == "" {
		// dot character "." has a special meaning to support SERVICE[.NETWORK] format.
		// For backward compatibility, replacing "." with "-", instead of failing
		service = strings.Replace(container.Name, ".", "-", -1)
		// Service names dont like "/" in them. removing it instead of failing for backward compatibility
		service = strings.Replace(service, "/", "", -1)
	}

	if !networkByName {
		n, err = controller.NetworkByName(networkName)
	}

	if container.secondaryNetworkRequired(networkDriver) {
		// Configure Bridge as secondary network for port binding purposes
		if err := container.configureNetwork("bridge", service, "bridge", false); err != nil {
			return err
		}
	}

	if err := container.configureNetwork(networkName, service, networkDriver, mode.IsDefault()); err != nil {
		return err
	}

	return container.WriteHostConfig()
}
Esempio n. 19
0
func Convert(c *project.ServiceConfig) (*runconfig.Config, *runconfig.HostConfig, error) {
	vs := Filter(c.Volumes, isVolume)

	volumes := make(map[string]struct{}, len(vs))
	for _, v := range vs {
		volumes[v] = struct{}{}
	}

	cmd, _ := shlex.Split(c.Command)
	entrypoint, _ := shlex.Split(c.Entrypoint)
	ports, binding, err := nat.ParsePortSpecs(c.Ports)
	if err != nil {
		return nil, nil, err
	}
	restart, err := runconfig.ParseRestartPolicy(c.Restart)
	if err != nil {
		return nil, nil, err
	}
	dns := c.Dns.Slice()
	dnssearch := c.DnsSearch.Slice()
	labels := c.Labels.MapParts()

	if len(c.Expose) > 0 {
		exposedPorts, _, err := nat.ParsePortSpecs(c.Expose)
		ports = exposedPorts
		if err != nil {
			return nil, nil, err
		}
	}

	config := &runconfig.Config{
		Entrypoint:   runconfig.NewEntrypoint(entrypoint...),
		Hostname:     c.Hostname,
		Domainname:   c.DomainName,
		User:         c.User,
		Env:          c.Environment.Slice(),
		Cmd:          runconfig.NewCommand(cmd...),
		Image:        c.Image,
		Labels:       labels,
		ExposedPorts: ports,
		Tty:          c.Tty,
		OpenStdin:    c.StdinOpen,
		WorkingDir:   c.WorkingDir,
		Volumes:      volumes,
	}
	host_config := &runconfig.HostConfig{
		VolumesFrom: c.VolumesFrom,
		CapAdd:      c.CapAdd,
		CapDrop:     c.CapDrop,
		CpuShares:   c.CpuShares,
		Privileged:  c.Privileged,
		Binds:       Filter(c.Volumes, isBind),
		Dns:         dns,
		DnsSearch:   dnssearch,
		LogConfig: runconfig.LogConfig{
			Type: c.LogDriver,
		},
		Memory:         c.MemLimit,
		NetworkMode:    runconfig.NetworkMode(c.Net),
		ReadonlyRootfs: c.ReadOnly,
		PidMode:        runconfig.PidMode(c.Pid),
		IpcMode:        runconfig.IpcMode(c.Ipc),
		PortBindings:   binding,
		RestartPolicy:  restart,
	}

	return config, host_config, nil
}
Esempio n. 20
0
func (container *Container) connectToNetwork(idOrName string, updateSettings bool) error {
	if container.hostConfig.NetworkMode.IsContainer() {
		return runconfig.ErrConflictSharedNetwork
	}

	if runconfig.NetworkMode(idOrName).IsBridge() &&
		container.daemon.configStore.DisableBridge {
		container.Config.NetworkDisabled = true
		return nil
	}

	controller := container.daemon.netController

	n, err := container.daemon.FindNetwork(idOrName)
	if err != nil {
		return err
	}

	if updateSettings {
		if err := container.updateNetworkSettings(n); err != nil {
			return err
		}
	}

	ep, err := container.getEndpointInNetwork(n)
	if err != nil {
		if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok {
			return err
		}

		createOptions, err := container.buildCreateEndpointOptions()
		if err != nil {
			return err
		}

		endpointName := strings.TrimPrefix(container.Name, "/")
		ep, err = n.CreateEndpoint(endpointName, createOptions...)
		if err != nil {
			return err
		}
	}

	if err := container.updateEndpointNetworkSettings(n, ep); err != nil {
		return err
	}

	var sb libnetwork.Sandbox
	controller.WalkSandboxes(func(s libnetwork.Sandbox) bool {
		if s.ContainerID() == container.ID {
			sb = s
			return true
		}
		return false
	})
	if sb == nil {
		options, err := container.buildSandboxOptions(n)
		if err != nil {
			return err
		}
		sb, err = controller.NewSandbox(container.ID, options...)
		if err != nil {
			return err
		}
	}

	container.updateSandboxNetworkSettings(sb)

	if err := ep.Join(sb); err != nil {
		return err
	}

	if err := container.updateJoinInfo(ep); err != nil {
		return derr.ErrorCodeJoinInfo.WithArgs(err)
	}

	return nil
}