From de53b906e805a46717c1538bfff98c8d6afd91f0 Mon Sep 17 00:00:00 2001 From: Thomas Anderson <127358482+zc-devs@users.noreply.github.com> Date: Thu, 2 Nov 2023 06:12:41 +0300 Subject: [PATCH] Add ports into pipeline backend step model (#2656) Closes #2655. [Pipeline](https://woodpecker-ci.org/docs/next/usage/services#complete-pipeline-example): ```yaml services: database: image: mysql environment: - MYSQL_DATABASE=test - MYSQL_ROOT_PASSWORD=example ports: - 3306 steps: get-version: image: ubuntu commands: - ( apt update && apt dist-upgrade -y && apt install -y mysql-client 2>&1 )> /dev/null - sleep 60s # need to wait for mysql-server init - echo 'SHOW VARIABLES LIKE "version"' | mysql -uroot -hdatabase test -pexample ``` Service: ```yaml apiVersion: v1 kind: Service metadata: name: wp-01hdq6gbkw1mn6k1655fs3rntf-0-services-0 namespace: woodpecker-runtime ... selfLink: >- /api/v1/namespaces/woodpecker-runtime/services/wp-01hdq6gbkw1mn6k1655fs3rntf-0-services-0 status: loadBalancer: {} spec: ports: - protocol: TCP port: 3306 targetPort: 3306 selector: step: database clusterIP: 10.43.180.120 clusterIPs: - 10.43.180.120 type: ClusterIP sessionAffinity: None ipFamilies: - IPv4 ipFamilyPolicy: SingleStack internalTrafficPolicy: Cluster ``` --- pipeline/backend/kubernetes/kubernetes.go | 8 ++------ pipeline/backend/kubernetes/service.go | 15 ++++----------- pipeline/backend/kubernetes/service_test.go | 2 +- pipeline/backend/types/step.go | 1 + pipeline/frontend/yaml/compiler/convert.go | 6 ++++++ pipeline/frontend/yaml/types/container.go | 1 + pipeline/frontend/yaml/types/container_test.go | 3 +++ 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/pipeline/backend/kubernetes/kubernetes.go b/pipeline/backend/kubernetes/kubernetes.go index 38906a768..fd00f518e 100644 --- a/pipeline/backend/kubernetes/kubernetes.go +++ b/pipeline/backend/kubernetes/kubernetes.go @@ -164,9 +164,7 @@ func (e *kube) SetupWorkflow(ctx context.Context, conf *types.Config, taskUUID s return err } log.Trace().Str("pod-name", stepName).Msgf("Creating service: %s", step.Name) - // TODO: support ports setting - // svc, err := Service(e.config.Namespace, step.Name, stepName, step.Ports) - svc, err := Service(e.config.Namespace, step.Name, stepName, []string{}) + svc, err := Service(e.config.Namespace, step.Name, step.Alias, step.Ports) if err != nil { return err } @@ -393,9 +391,7 @@ func (e *kube) DestroyWorkflow(_ context.Context, conf *types.Config, taskUUID s if stage.Alias == "services" { for _, step := range stage.Steps { log.Trace().Msgf("Deleting service: %s", step.Name) - // TODO: support ports setting - // svc, err := Service(e.config.Namespace, step.Name, step.Alias, step.Ports) - svc, err := Service(e.config.Namespace, step.Name, step.Alias, []string{}) + svc, err := Service(e.config.Namespace, step.Name, step.Alias, step.Ports) if err != nil { return err } diff --git a/pipeline/backend/kubernetes/service.go b/pipeline/backend/kubernetes/service.go index 224bc7c6c..2fee9496a 100644 --- a/pipeline/backend/kubernetes/service.go +++ b/pipeline/backend/kubernetes/service.go @@ -15,24 +15,17 @@ package kubernetes import ( - "fmt" - "strconv" - v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" ) -func Service(namespace, name, podName string, ports []string) (*v1.Service, error) { +func Service(namespace, name, podName string, ports []uint16) (*v1.Service, error) { var svcPorts []v1.ServicePort - for _, p := range ports { - i, err := strconv.Atoi(p) - if err != nil { - return nil, fmt.Errorf("Could not parse service port %s as integer", p) - } + for _, port := range ports { svcPorts = append(svcPorts, v1.ServicePort{ - Port: int32(i), - TargetPort: intstr.IntOrString{IntVal: int32(i)}, + Port: int32(port), + TargetPort: intstr.IntOrString{IntVal: int32(port)}, }) } diff --git a/pipeline/backend/kubernetes/service_test.go b/pipeline/backend/kubernetes/service_test.go index 2d0441d3b..16d718102 100644 --- a/pipeline/backend/kubernetes/service_test.go +++ b/pipeline/backend/kubernetes/service_test.go @@ -54,7 +54,7 @@ func TestService(t *testing.T) { } }` - s, _ := Service("foo", "bar", "baz", []string{"1", "2", "3"}) + s, _ := Service("foo", "bar", "baz", []uint16{1, 2, 3}) j, err := json.Marshal(s) assert.NoError(t, err) assert.JSONEq(t, expected, string(j)) diff --git a/pipeline/backend/types/step.go b/pipeline/backend/types/step.go index a491051fb..71bd5a66d 100644 --- a/pipeline/backend/types/step.go +++ b/pipeline/backend/types/step.go @@ -48,6 +48,7 @@ type Step struct { NetworkMode string `json:"network_mode,omitempty"` IpcMode string `json:"ipc_mode,omitempty"` Sysctls map[string]string `json:"sysctls,omitempty"` + Ports []uint16 `json:"ports,omitempty"` BackendOptions BackendOptions `json:"backend_options,omitempty"` } diff --git a/pipeline/frontend/yaml/compiler/convert.go b/pipeline/frontend/yaml/compiler/convert.go index 9ee729075..53e85f0d9 100644 --- a/pipeline/frontend/yaml/compiler/convert.go +++ b/pipeline/frontend/yaml/compiler/convert.go @@ -164,6 +164,11 @@ func (c *Compiler) createProcess(name string, container *yaml_types.Container, s cpuSet = c.reslimit.CPUSet } + var ports []uint16 + for _, port := range container.Ports { + ports = append(ports, uint16(port)) + } + // at least one constraint contain status success, or all constraints have no status set onSuccess := container.When.IncludesStatusSuccess() // at least one constraint must include the status failure. @@ -206,6 +211,7 @@ func (c *Compiler) createProcess(name string, container *yaml_types.Container, s Failure: failure, NetworkMode: networkMode, IpcMode: ipcMode, + Ports: ports, BackendOptions: backendOptions, } } diff --git a/pipeline/frontend/yaml/types/container.go b/pipeline/frontend/yaml/types/container.go index 945816f80..eca9bd5a0 100644 --- a/pipeline/frontend/yaml/types/container.go +++ b/pipeline/frontend/yaml/types/container.go @@ -47,6 +47,7 @@ type ( Settings map[string]interface{} `yaml:"settings"` Volumes Volumes `yaml:"volumes,omitempty"` When constraint.When `yaml:"when,omitempty"` + Ports []base.StringOrInt `yaml:"ports,omitempty"` // Docker Specific Privileged bool `yaml:"privileged,omitempty"` diff --git a/pipeline/frontend/yaml/types/container_test.go b/pipeline/frontend/yaml/types/container_test.go index 46f51b2d7..89d6e09f2 100644 --- a/pipeline/frontend/yaml/types/container_test.go +++ b/pipeline/frontend/yaml/types/container_test.go @@ -68,6 +68,8 @@ when: settings: foo: bar baz: false +ports: + - 8080 `) func TestUnmarshalContainer(t *testing.T) { @@ -126,6 +128,7 @@ func TestUnmarshalContainer(t *testing.T) { "foo": "bar", "baz": false, }, + Ports: []base.StringOrInt{8080}, } got := Container{} err := yaml.Unmarshal(containerYaml, &got)