func alignApps(reApps, deApps []specv1.AppInfo) []specv1.AppInfo {
	if len(reApps) == 0 || len(deApps) == 0 {
		return reApps
	}
	as := map[string]specv1.AppInfo{}
	for _, a := range reApps {
		as[a.Name] = a
	}
	var res []specv1.AppInfo
	for _, a := range deApps {
		if r, ok := as[a.Name]; ok {
			res = append(res, r)
			delete(as, a.Name)
		}
	}
	for _, a := range as {
		res = append(res, a)
	}
	return res
}
ensuring apps have same order in report and desire list
package engine
import (
	"fmt"
	specv1 "github.com/baetyl/baetyl-go/v2/spec/v1"
)
func checkService(infos []specv1.AppInfo, apps map[string]specv1.Application, stats map[string]specv1.AppStats, update map[string]specv1.AppInfo) {
	svcs := make(map[string][]string)
	for _, info := range infos {
		app, ok := apps[info.Name]
		if !ok {
			continue
		}
		for _, svc := range app.Services {
			svcs[svc.Name] = append(svcs[svc.Name], app.Name)
		}
	}
	del := make(map[string]struct{})
	var first string
	for sName, aNames := range svcs {
		if len(aNames) <= 1 {
			continue
		}
		first = ""
		for _, aName := range aNames {
			if first == "" {
				first = aName
			}
			if _, ok := stats[aName]; ok {
				first = aName
				break
			}
		}
		for _, aName := range aNames {
			if aName == first {
				continue
			}
			stat, ok := stats[aName]
			if !ok {
				stat = specv1.AppStats{
					AppInfo:       specv1.AppInfo{Name: aName, Version: apps[aName].Version},
					Status:        specv1.Unknown,
					InstanceStats: map[string]specv1.InstanceStats{},
				}
			}
			iStat, ok := stat.InstanceStats[sName]
			if !ok {
				iStat = specv1.InstanceStats{ServiceName: sName, Status: specv1.Unknown}
			}
			iStat.Cause += fmt.Sprintf("service [%s] in application [%s] collide with application [%s]", sName, aName, first)
			stat.InstanceStats[sName] = iStat
			stats[aName] = stat
			del[aName] = struct{}{}
		}
	}
	for n := range del {
		delete(update, n)
		delete(apps, n)
	}
}
func checkPort(infos []specv1.AppInfo, apps map[string]specv1.Application, stats map[string]specv1.AppStats, update map[string]specv1.AppInfo) {
	ports := make(map[int32][]string)
	svcs := make(map[string]string)
	del := make(map[string]struct{})
	for _, info := range infos {
		app, ok := apps[info.Name]
		if !ok {
			continue
		}
		for _, svc := range app.Services {
			svcs[svc.Name] = app.Name
			for _, p := range svc.Ports {
				if p.HostPort == 0 {
					continue
				}
				if svc.Replica > 1 {
					stat, ok := stats[app.Name]
					if !ok {
						stat = specv1.AppStats{
							AppInfo:       specv1.AppInfo{Name: app.Name, Version: app.Version},
							Status:        specv1.Unknown,
							InstanceStats: map[string]specv1.InstanceStats{},
						}
					}
					iStat, ok := stat.InstanceStats[svc.Name]
					if !ok {
						iStat = specv1.InstanceStats{ServiceName: svc.Name, Status: specv1.Unknown}
					}
					iStat.Cause += fmt.Sprintf("service [%s] with relica > 1 can not configure host port", svc.Name)
					stat.InstanceStats[svc.Name] = iStat
					stats[app.Name] = stat
					del[app.Name] = struct{}{}
				} else {
					ports[p.HostPort] = append(ports[p.HostPort], svc.Name)
				}
			}
		}
	}
	var first string
	for p, sNames := range ports {
		if len(sNames) <= 1 {
			continue
		}
		first = ""
		for _, sName := range sNames {
			aName := svcs[sName]
			if first == "" {
				first = sName
			}
			if stat, ok := stats[aName]; ok {
				if _, ok := stat.InstanceStats[sName]; ok {
					first = sName
					break
				}
			}
		}
		for _, sName := range sNames {
			if sName == first {
				continue
			}
			aName := svcs[sName]
			stat, ok := stats[aName]
			if !ok {
				stat = specv1.AppStats{
					AppInfo:       specv1.AppInfo{Name: aName, Version: apps[aName].Version},
					Status:        specv1.Unknown,
					InstanceStats: map[string]specv1.InstanceStats{},
				}
			}
			iStat, ok := stat.InstanceStats[sName]
			if !ok {
				iStat = specv1.InstanceStats{ServiceName: sName, Status: specv1.Unknown}
			}
			iStat.Cause += fmt.Sprintf("port [%d] in service [%s] collide with service [%s]", p, sName, first)
			stat.InstanceStats[sName] = iStat
			stats[aName] = stat
			del[aName] = struct{}{}
		}
	}
	for n := range del {
		delete(update, n)
		delete(apps, n)
	}
}
func makeKey(kind specv1.Kind, name, ver string) string {
	if name == "" || ver == "" {
		return ""
	}
	return string(kind) + "-" + name + "-" + ver
}