func (c *ClusterTx) ContainerList(filter ContainerFilter) ([]Container, error) {
	// Result slice.
	objects := make([]Container, 0)

	// Check which filter criteria are active.
	criteria := map[string]interface{}{}
	if filter.Project != "" {
		criteria["Project"] = filter.Project
	}
	if filter.Name != "" {
		criteria["Name"] = filter.Name
	}
	if filter.Node != "" {
		criteria["Node"] = filter.Node
	}
	if filter.Parent != "" {
		criteria["Parent"] = filter.Parent
	}
	if filter.Type != -1 {
		criteria["Type"] = filter.Type
	}

	// Pick the prepared statement and arguments to use based on active criteria.
	var stmt *sql.Stmt
	var args []interface{}

	if criteria["Project"] != nil && criteria["Name"] != nil && criteria["Type"] != nil {
		stmt = c.stmt(containerObjectsByProjectAndNameAndType)
		args = []interface{}{
			filter.Project,
			filter.Name,
			filter.Type,
		}
	} else if criteria["Project"] != nil && criteria["Type"] != nil && criteria["Parent"] != nil {
		stmt = c.stmt(containerObjectsByProjectAndTypeAndParent)
		args = []interface{}{
			filter.Project,
			filter.Type,
			len(filter.Parent) + 1,
			filter.Parent + "/",
		}
	} else if criteria["Project"] != nil && criteria["Node"] != nil && criteria["Type"] != nil {
		stmt = c.stmt(containerObjectsByProjectAndNodeAndType)
		args = []interface{}{
			filter.Project,
			filter.Node,
			filter.Type,
		}
	} else if criteria["Node"] != nil && criteria["Type"] != nil {
		stmt = c.stmt(containerObjectsByNodeAndType)
		args = []interface{}{
			filter.Node,
			filter.Type,
		}
	} else if criteria["Project"] != nil && criteria["Type"] != nil {
		stmt = c.stmt(containerObjectsByProjectAndType)
		args = []interface{}{
			filter.Project,
			filter.Type,
		}
	} else if criteria["Project"] != nil && criteria["Name"] != nil {
		stmt = c.stmt(containerObjectsByProjectAndName)
		args = []interface{}{
			filter.Project,
			filter.Name,
		}
	} else if criteria["Type"] != nil {
		stmt = c.stmt(containerObjectsByType)
		args = []interface{}{
			filter.Type,
		}
	} else {
		stmt = c.stmt(containerObjects)
		args = []interface{}{}
	}

	// Dest function for scanning a row.
	dest := func(i int) []interface{} {
		objects = append(objects, Container{})
		return []interface{}{
			&objects[i].ID,
			&objects[i].Project,
			&objects[i].Name,
			&objects[i].Node,
			&objects[i].Type,
			&objects[i].Architecture,
			&objects[i].Ephemeral,
			&objects[i].CreationDate,
			&objects[i].Stateful,
			&objects[i].LastUseDate,
			&objects[i].Description,
			&objects[i].ExpiryDate,
		}
	}

	// Select.
	err := query.SelectObjects(stmt, dest, args...)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to fetch containers")
	}

	// Fill field Config.
	configObjects, err := c.ContainerConfigRef(filter)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to fetch field Config")
	}

	for i := range objects {
		_, ok := configObjects[objects[i].Project]
		if !ok {
			subIndex := map[string]map[string]string{}
			configObjects[objects[i].Project] = subIndex
		}

		value := configObjects[objects[i].Project][objects[i].Name]
		if value == nil {
			value = map[string]string{}
		}
		objects[i].Config = value
	}

	// Fill field Devices.
	devicesObjects, err := c.ContainerDevicesRef(filter)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to fetch field Devices")
	}

	for i := range objects {
		_, ok := devicesObjects[objects[i].Project]
		if !ok {
			subIndex := map[string]map[string]map[string]string{}
			devicesObjects[objects[i].Project] = subIndex
		}

		value := devicesObjects[objects[i].Project][objects[i].Name]
		if value == nil {
			value = map[string]map[string]string{}
		}
		objects[i].Devices = value
	}

	// Fill field Profiles.
	profilesObjects, err := c.ContainerProfilesRef(filter)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to fetch field Profiles")
	}

	for i := range objects {
		_, ok := profilesObjects[objects[i].Project]
		if !ok {
			subIndex := map[string][]string{}
			profilesObjects[objects[i].Project] = subIndex
		}

		value := profilesObjects[objects[i].Project][objects[i].Name]
		if value == nil {
			value = []string{}
		}
		objects[i].Profiles = value
	}

	return objects, nil
}
func (c *ClusterTx) ContainerList(filter ContainerFilter) ([]Container, error) {
	// Result slice.
	objects := make([]Container, 0)

	// Check which filter criteria are active.
	criteria := map[string]interface{}{}
	if filter.Project != "" {
		criteria["Project"] = filter.Project
	}
	if filter.Name != "" {
		criteria["Name"] = filter.Name
	}
	if filter.Node != "" {
		criteria["Node"] = filter.Node
	}
	if filter.Parent != "" {
		criteria["Parent"] = filter.Parent
	}
	if filter.Type != -1 {
		criteria["Type"] = filter.Type
	}

	// Pick the prepared statement and arguments to use based on active criteria.
	var stmt *sql.Stmt
	var args []interface{}

	if criteria["Project"] != nil && criteria["Name"] != nil && criteria["Type"] != nil {
		stmt = c.stmt(containerObjectsByProjectAndNameAndType)
		args = []interface{}{
			filter.Project,
			filter.Name,
			filter.Type,
		}
	} else if criteria["Project"] != nil && criteria["Type"] != nil && criteria["Parent"] != nil {
		stmt = c.stmt(containerObjectsByProjectAndTypeAndParent)
		args = []interface{}{
			filter.Project,
			filter.Type,
			len(filter.Parent) + 1,
			filter.Parent + "/",
		}
	} else if criteria["Project"] != nil && criteria["Node"] != nil && criteria["Type"] != nil {
		stmt = c.stmt(containerObjectsByProjectAndNodeAndType)
		args = []interface{}{
			filter.Project,
			filter.Node,
			filter.Type,
		}
	} else if criteria["Node"] != nil && criteria["Type"] != nil {
		stmt = c.stmt(containerObjectsByNodeAndType)
		args = []interface{}{
			filter.Node,
			filter.Type,
		}
	} else if criteria["Project"] != nil && criteria["Type"] != nil {
		stmt = c.stmt(containerObjectsByProjectAndType)
		args = []interface{}{
			filter.Project,
			filter.Type,
		}
	} else if criteria["Project"] != nil && criteria["Name"] != nil {
		stmt = c.stmt(containerObjectsByProjectAndName)
		args = []interface{}{
			filter.Project,
			filter.Name,
		}
	} else if criteria["Type"] != nil {
		stmt = c.stmt(containerObjectsByType)
		args = []interface{}{
			filter.Type,
		}
	} else {
		stmt = c.stmt(containerObjects)
		args = []interface{}{}
	}

	// Dest function for scanning a row.
	dest := func(i int) []interface{} {
		objects = append(objects, Container{})
		return []interface{}{
			&objects[i].ID,
			&objects[i].Project,
			&objects[i].Name,
			&objects[i].Node,
			&objects[i].Type,
			&objects[i].Architecture,
			&objects[i].Ephemeral,
			&objects[i].CreationDate,
			&objects[i].Stateful,
			&objects[i].LastUseDate,
			&objects[i].Description,
			&objects[i].ExpiryDate,
		}
	}

	// Select.
	err := query.SelectObjects(stmt, dest, args...)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to fetch containers")
	}

	// Fill field Config.
	configObjects, err := c.ContainerConfigRef(filter)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to fetch field Config")
	}

	for i := range objects {
		_, ok := configObjects[objects[i].Project]
		if !ok {
			subIndex := map[string]map[string]string{}
			configObjects[objects[i].Project] = subIndex
		}

		value := configObjects[objects[i].Project][objects[i].Name]
		if value == nil {
			value = map[string]string{}
		}
		objects[i].Config = value
	}

	// Fill field Devices.
	devicesObjects, err := c.ContainerDevicesRef(filter)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to fetch field Devices")
	}

	for i := range objects {
		_, ok := devicesObjects[objects[i].Project]
		if !ok {
			subIndex := map[string]map[string]map[string]string{}
			devicesObjects[objects[i].Project] = subIndex
		}

		value := devicesObjects[objects[i].Project][objects[i].Name]
		if value == nil {
			value = map[string]map[string]string{}
		}
		objects[i].Devices = value
	}

	// Fill field Profiles.
	profilesObjects, err := c.ContainerProfilesRef(filter)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to fetch field Profiles")
	}

	for i := range objects {
		_, ok := profilesObjects[objects[i].Project]
		if !ok {
			subIndex := map[string][]string{}
			profilesObjects[objects[i].Project] = subIndex
		}

		value := profilesObjects[objects[i].Project][objects[i].Name]
		if value == nil {
			value = []string{}
		}
		objects[i].Profiles = value
	}

	return objects, nil
}
// ContainerList returns all available containers.