2023-08-07 19:13:26 +00:00
// Copyright 2022 Woodpecker Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2022-09-05 04:01:14 +00:00
package kubernetes
import (
2023-12-19 03:53:52 +00:00
"context"
2023-12-19 01:38:18 +00:00
"fmt"
2023-12-19 03:53:52 +00:00
"github.com/rs/zerolog/log"
"go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types"
2022-09-05 04:01:14 +00:00
v1 "k8s.io/api/core/v1"
2023-12-19 03:53:52 +00:00
"k8s.io/apimachinery/pkg/api/errors"
2022-09-05 04:01:14 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)
2023-12-19 03:53:52 +00:00
func mkService ( namespace , name string , ports [ ] uint16 , selector map [ string ] string ) ( * v1 . Service , error ) {
log . Trace ( ) . Str ( "name" , name ) . Interface ( "selector" , selector ) . Interface ( "ports" , ports ) . Msg ( "Creating service" )
2022-09-05 04:01:14 +00:00
var svcPorts [ ] v1 . ServicePort
2023-11-02 03:12:41 +00:00
for _ , port := range ports {
2022-09-05 04:01:14 +00:00
svcPorts = append ( svcPorts , v1 . ServicePort {
2023-12-19 01:38:18 +00:00
Name : fmt . Sprintf ( "port-%d" , port ) ,
2023-11-02 03:12:41 +00:00
Port : int32 ( port ) ,
TargetPort : intstr . IntOrString { IntVal : int32 ( port ) } ,
2022-09-05 04:01:14 +00:00
} )
}
return & v1 . Service {
ObjectMeta : metav1 . ObjectMeta {
2023-12-19 03:53:52 +00:00
Name : name ,
2022-09-05 04:01:14 +00:00
Namespace : namespace ,
} ,
Spec : v1 . ServiceSpec {
2023-12-19 03:53:52 +00:00
Type : v1 . ServiceTypeClusterIP ,
Selector : selector ,
Ports : svcPorts ,
2022-09-05 04:01:14 +00:00
} ,
} , nil
}
2023-12-19 03:53:52 +00:00
func serviceName ( step * types . Step ) ( string , error ) {
return dnsName ( step . Name )
}
func startService ( ctx context . Context , engine * kube , step * types . Step ) ( * v1 . Service , error ) {
name , err := serviceName ( step )
if err != nil {
return nil , err
}
podName , err := podName ( step )
if err != nil {
return nil , err
}
selector := map [ string ] string {
StepLabel : podName ,
}
svc , err := mkService ( engine . config . Namespace , name , step . Ports , selector )
if err != nil {
return nil , err
}
return engine . client . CoreV1 ( ) . Services ( engine . config . Namespace ) . Create ( ctx , svc , metav1 . CreateOptions { } )
}
func stopService ( ctx context . Context , engine * kube , step * types . Step , deleteOpts metav1 . DeleteOptions ) error {
svcName , err := serviceName ( step )
if err != nil {
return err
}
log . Trace ( ) . Str ( "name" , svcName ) . Msg ( "Deleting service" )
err = engine . client . CoreV1 ( ) . Services ( engine . config . Namespace ) . Delete ( ctx , svcName , deleteOpts )
if errors . IsNotFound ( err ) {
// Don't abort on 404 errors from k8s, they most likely mean that the pod hasn't been created yet, usually because pipeline was canceled before running all steps.
log . Trace ( ) . Err ( err ) . Msgf ( "Unable to delete service %s" , svcName )
return nil
}
return err
}