You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: workload_common.go
    path of file: ./repos/rancher/pkg/controllers/managementagent/workload
    
    the code of the file until where you have to start completion: package workload

import (
	"context"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"

	"github.com/rancher/norman/types/convert"
	appsv1 "github.com/rancher/rancher/pkg/generated/norman/apps/v1"
	batchv1 "github.com/rancher/rancher/pkg/generated/norman/batch/v1"
	v1 "github.com/rancher/rancher/pkg/generated/norman/core/v1"
	"github.com/rancher/rancher/pkg/types/config"
	k8sappv1 "k8s.io/api/apps/v1"
	corebatchv1 "k8s.io/api/batch/v1"
	corev1 "k8s.io/api/core/v1"
	apierrors
    
func generateServicesFromPortsAnnotation(workload *Workload) ([]Service, error) {
	var services []Service
	val, ok := workload.TemplateSpec.Annotations[PortsAnnotation]
	if !ok {
		return services, nil
	}
	var portList [][]ContainerPort
	err := json.Unmarshal([]byte(val), &portList)
	if err != nil {
		return services, err
	}

	svcTypeToPort := map[corev1.ServiceType][]ContainerPort{}
	for _, l := range portList {
		for _, port := range l {
			if port.Kind == "HostPort" {
				continue
			}
			svcType := corev1.ServiceType(port.Kind)
			svcTypeToPort[svcType] = append(svcTypeToPort[svcType], port)
		}
	}

	for svcType, ports := range svcTypeToPort {
		servicePorts := map[string][]corev1.ServicePort{}
		for _, p := range ports {
			var nodePort int32
			var clusterIPPort int32
			if svcType == corev1.ServiceTypeNodePort {
				nodePort = int32(p.SourcePort)
				clusterIPPort = p.ContainerPort
			} else {
				if p.SourcePort == 0 {
					clusterIPPort = p.ContainerPort
				} else {
					clusterIPPort = int32(p.SourcePort)
				}
			}
			servicePort := corev1.ServicePort{
				Port:       clusterIPPort,
				TargetPort: intstr.Parse(strconv.FormatInt(int64(p.ContainerPort), 10)),
				NodePort:   nodePort,
				Protocol:   corev1.Protocol(p.Protocol),
				Name:       p.Name,
			}
			dnsName := p.DNSName
			if dnsName == "" {
				dnsName = workload.Name
			}
			servicePorts[dnsName] = append(servicePorts[dnsName], servicePort)
		}
		// append default port as sky dns won't work w/o at least one port being set
		if len(servicePorts) == 0 {
			servicePort := corev1.ServicePort{
				Port:       42,
				TargetPort: intstr.Parse(strconv.FormatInt(42, 10)),
				Protocol:   corev1.Protocol(corev1.ProtocolTCP),
				Name:       "default",
			}
			servicePorts[workload.Name] = append(servicePorts[workload.Name], servicePort)
		}

		for dnsName, servicePorts := range servicePorts {
			services = append(services, Service{
				Type:         svcType,
				ServicePorts: servicePorts,
				Name:         dnsName,
			})
		}

	}

	return services, nil
}