ronantakizawa/codereview-bench huggingface dataset:
Repository: traefik/traefik
File: pkg/middlewares/ipallowlist/ip_allowlist.go (Go)

Code before:
	}

	logger.Debugf("Setting up IPAllowLister with sourceRange: %s", config.SourceRange)

	return &ipAllowLister{
		strategy:    strategy,
		allowLister: checker,
		next:        next,
		name:        name,
	}, nil
}

func (al *ipAllowLister) GetTracingInformation() (string, ext.SpanKindEnum) {
	return al.name, tracing.SpanKindNoneEnum
}

func (al *ipAllowLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	ctx := middlewares.GetLoggerCtx(req.Context(), al.name, typeName)
	logger := log.FromContext(ctx)

	clientIP := al.strategy.GetIP(req)
	err := al.allowLister.IsAuthorized(clientIP)
	if err != nil {
		msg := fmt.Sprintf("Rejecting IP %s: %v", clientIP, err)
		logger.Debug(msg)
		tracing.SetErrorWithEvent(req, msg) //nolint: govet
		reject(ctx, rw)
		return
	}
	logger.Debugf("Accepting IP %s", clientIP)

	al.next.ServeHTTP(rw, req)
}

func reject(ctx context.Context, rw http.ResponseWriter) {
	statusCode := http.StatusForbidden

	rw.WriteHeader(statusCode)
	_, err := rw.Write([]byte(http.StatusText(statusCode)))
	if err != nil {
		log.FromContext(ctx).Error(err)
	}
}


Review comment (suggestion):
```suggestion
		tracing.SetErrorWithEvent(req, msg)
```

Code after:
	}

	logger.Debugf("Setting up IPAllowLister with sourceRange: %s", config.SourceRange)

	return &ipAllowLister{
		strategy:    strategy,
		allowLister: checker,
		next:        next,
		name:        name,
	}, nil
}

func (al *ipAllowLister) GetTracingInformation() (string, ext.SpanKindEnum) {
	return al.name, tracing.SpanKindNoneEnum
}

func (al *ipAllowLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	ctx := middlewares.GetLoggerCtx(req.Context(), al.name, typeName)
	logger := log.FromContext(ctx)

	clientIP := al.strategy.GetIP(req)
	err := al.allowLister.IsAuthorized(clientIP)
	if err != nil {
		logger.Debugf("Rejecting IP %s: %v", clientIP, err)
		tracing.SetErrorWithEvent(req, "Rejecting IP %s: %v", clientIP, err)
		reject(ctx, rw)
		return
	}
	logger.Debugf("Accepting IP %s", clientIP)

	al.next.ServeHTTP(rw, req)
}

func reject(ctx context.Context, rw http.ResponseWriter) {
	statusCode := http.StatusForbidden

	rw.WriteHeader(statusCode)
	_, err := rw.Write([]byte(http.StatusText(statusCode)))
	if err != nil {
		log.FromContext(ctx).Error(err)
	}
}
Repository: traefik/traefik
File: pkg/middlewares/accesslog/logger.go (Go)

Code before:
			return nil, fmt.Errorf("error opening access log file: %w", err)
		}
		file = f
	}
	logHandlerChan := make(chan handlerParams, config.BufferingSize)

	var formatter logrus.Formatter

	switch config.Format {
	case CommonFormat:
		formatter = new(CommonLogFormatter)
	case JSONFormat:
		formatter = new(logrus.JSONFormatter)
	default:
		log.WithoutContext().Errorf("unsupported access log format: %q, defaulting to common format instead.", config.Format)
		formatter = new(CommonLogFormatter)
	}

	logger := &logrus.Logger{
		Out:       file,
		Formatter: formatter,
		Hooks:     make(logrus.LevelHooks),
		Level:     logrus.InfoLevel,
	}

	// Transform field and header names in config to a canonical form,
	// to enable case-insensitive lookup.
	if config.Fields != nil {
		if len(config.Fields.Names) > 0 {
			fields := map[string]string{}

			for h, v := range config.Fields.Names {
				fields[strings.ToLower(h)] = v
			}

			config.Fields.Names = fields
		}

		if config.Fields.Headers != nil && len(config.Fields.Headers.Names) > 0 {
			fields := map[string]string{}

			for h, v := range config.Fields.Headers.Names {
				fields[textproto.CanonicalMIMEHeaderKey(h)] = v
			}

			config.Fields.Headers.Names = fields
		}
	}

	logHandler := &Handler{
		config:         config,

Review comment (security):
```suggestion
	// Transforms header names to a canonical form, to be used as is without further transformations,
	// and transforms field names in lower case, to enable case-insensitive lookup.
```

Code after:
			return nil, fmt.Errorf("error opening access log file: %w", err)
		}
		file = f
	}
	logHandlerChan := make(chan handlerParams, config.BufferingSize)

	var formatter logrus.Formatter

	switch config.Format {
	case CommonFormat:
		formatter = new(CommonLogFormatter)
	case JSONFormat:
		formatter = new(logrus.JSONFormatter)
	default:
		log.WithoutContext().Errorf("unsupported access log format: %q, defaulting to common format instead.", config.Format)
		formatter = new(CommonLogFormatter)
	}

	logger := &logrus.Logger{
		Out:       file,
		Formatter: formatter,
		Hooks:     make(logrus.LevelHooks),
		Level:     logrus.InfoLevel,
	}

	// Transform header names to a canonical form, to be used as is without further transformations,
	// and transform field names to lower case, to enable case-insensitive lookup.
	if config.Fields != nil {
		if len(config.Fields.Names) > 0 {
			fields := map[string]string{}

			for h, v := range config.Fields.Names {
				fields[strings.ToLower(h)] = v
			}

			config.Fields.Names = fields
		}

		if config.Fields.Headers != nil && len(config.Fields.Headers.Names) > 0 {
			fields := map[string]string{}

			for h, v := range config.Fields.Headers.Names {
				fields[textproto.CanonicalMIMEHeaderKey(h)] = v
			}

			config.Fields.Headers.Names = fields
		}
	}

	logHandler := &Handler{
		config:         config,
Repository: traefik/traefik
File: pkg/server/service/loadbalancer/wrr/wrr.go (Go)

Code before:
var errNoAvailableServer = errors.New("no available server")

func (b *Balancer) nextServer() (*namedHandler, error) {
	b.handlersMu.Lock()
	defer b.handlersMu.Unlock()

	if len(b.handlers) == 0 || len(b.status) == 0 {
		return nil, errNoAvailableServer
	}

	var handler *namedHandler
	for {
		// Pick handler with closest deadline.
		handler = heap.Pop(b).(*namedHandler)

		// curDeadline should be handler's deadline so that new added entry would have a fair competition environment with the old ones.
		b.curDeadline = handler.deadline
		handler.deadline += 1 / handler.weight

		heap.Push(b, handler)
		if _, ok := b.status[handler.name]; ok {
			if _, ok := b.fenced[handler.name]; !ok {
				// do not select a fenced handler
				break
			}
		}
	}

	log.Debug().Msgf("Service selected by WRR: %s", handler.name)
	return handler, nil
}

func (b *Balancer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if b.stickyCookie != nil {
		cookie, err := req.Cookie(b.stickyCookie.name)

		if err != nil && !errors.Is(err, http.ErrNoCookie) {
			log.Warn().Err(err).Msg("Error while reading cookie")
		}

		if err == nil && cookie != nil {
			b.handlersMu.RLock()
			handler, ok := b.handlerMap[cookie.Value]
			b.handlersMu.RUnlock()

			if ok && handler != nil {
				b.handlersMu.RLock()
				_, isHealthy := b.status[handler.name]
				b.handlersMu.RUnlock()
				if isHealthy {
					handler.ServeHTTP(w, req)

Review comment (suggestion):
Unless I missed something, there seems to be an issue here. If all handlers are fenced, the for loop will hang indefinitely. I suppose we need to ensure that there is at least one handler referenced in status that is not fenced.

Code after:
	b.updaters = append(b.updaters, fn)
	return nil
}

var errNoAvailableServer = errors.New("no available server")

func (b *Balancer) nextServer() (*namedHandler, error) {
	b.handlersMu.Lock()
	defer b.handlersMu.Unlock()

	if len(b.handlers) == 0 || len(b.status) == 0 || len(b.fenced) == len(b.handlers) {
		return nil, errNoAvailableServer
	}

	var handler *namedHandler
	for {
		// Pick handler with closest deadline.
		handler = heap.Pop(b).(*namedHandler)

		// curDeadline should be handler's deadline so that new added entry would have a fair competition environment with the old ones.
		b.curDeadline = handler.deadline
		handler.deadline += 1 / handler.weight

		heap.Push(b, handler)
		if _, ok := b.status[handler.name]; ok {
			if _, ok := b.fenced[handler.name]; !ok {
				// do not select a fenced handler.
				break
			}
		}
	}

	log.Debug().Msgf("Service selected by WRR: %s", handler.name)
	return handler, nil
}

func (b *Balancer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if b.stickyCookie != nil {
		cookie, err := req.Cookie(b.stickyCookie.name)

		if err != nil && !errors.Is(err, http.ErrNoCookie) {
			log.Warn().Err(err).Msg("Error while reading cookie")
		}

		if err == nil && cookie != nil {
			b.handlersMu.RLock()
			handler, ok := b.handlerMap[cookie.Value]
			b.handlersMu.RUnlock()

			if ok && handler != nil {
				b.handlersMu.RLock()
Repository: traefik/traefik
File: pkg/provider/kubernetes/ingress/kubernetes_test.go (Go)

Code before:
			path:        "/",
			requestPath: "/aaa/ccc",
			match:       true,
		},
		{
			path:        "/aaa",
			requestPath: "/aaa/ccc",
			match:       true,
		},
		{
			path:        "/...",
			requestPath: "/aaa",
			match:       false,
		},
		{
			path:        "/...",
			requestPath: "/.../",
			match:       true,
		},
	}

	for i, tt := range tests {
		t.Run(fmt.Sprintf("Prefix match case #%d", i), func(t *testing.T) {
			re := regexp.MustCompile(buildPrefixMatchRegex(tt.path))
			assert.Equalf(t, tt.match, re.MatchString(tt.requestPath), "Kubernetes prefix matching path=%s, requestPath=%s incorrect", tt.path, tt.requestPath)
		})
	}
}


Review comment (bug):
```suggestion
		t.Run(fmt.Sprintf("Prefix match case #%d", i), func(t *testing.T) {
		        t.Parallel()
		        
			re := regexp.MustCompile(buildPrefixMatchRegex(tt.path))
			assert.Equalf(t, tt.match, re.MatchString(tt.requestPath), "Kubernetes prefix matching path=%s, requestPath=%s incorrect", tt.path, tt.requestPath)
		})
```

Code after:
		},
		{
			path:        "/aaa",
			requestPath: "/aaa/ccc",
			match:       true,
		},
		{
			path:        "/...",
			requestPath: "/aaa",
			match:       false,
		},
		{
			path:        "/...",
			requestPath: "/.../",
			match:       true,
		},
	}

	for _, tt := range tests {
		t.Run(fmt.Sprintf("Prefix match case %s", tt.path), func(t *testing.T) {
			t.Parallel()

			handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
			muxer, err := traefikhttp.NewMuxer()
			require.NoError(t, err)

			rule := buildStrictPrefixMatchingRule(tt.path)
			err = muxer.AddRoute(rule, "", 0, handler)
			require.NoError(t, err)

			w := httptest.NewRecorder()
			req := httptest.NewRequest(http.MethodGet, tt.requestPath, http.NoBody)
			muxer.ServeHTTP(w, req)

			if tt.match {
				assert.Equal(t, http.StatusOK, w.Code)
			} else {
				assert.Equal(t, http.StatusNotFound, w.Code)
			}
		})
	}
}
Repository: traefik/traefik
File: pkg/api/dashboard/dashboard.go (Go)

Code before:
	"strings"
	"text/template"

	"github.com/gorilla/mux"
	"github.com/rs/zerolog/log"
	"github.com/traefik/traefik/v3/webui"
)

type indexTemplateData struct {
	APIUrl string
}

// Handler expose dashboard routes.
type Handler struct {
	BasePath string

	assets fs.FS // optional assets, to override the webui.FS default
}

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	assets := h.assets
	if assets == nil {
		assets = webui.FS
	}

	// allow iframes from our domains only
	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src
	w.Header().Set("Content-Security-Policy", "frame-src 'self' https://traefik.io https://*.traefik.io;")

	// The content type must be guessed by the file server.
	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
	w.Header().Del("Content-Type")

	if r.URL.Path == "/" {
		indexTemplate, err := template.ParseFS(assets, "index.html")
		if err != nil {
			log.Error().Err(err).Msg("Unable to parse index template")
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
			return
		}

		apiPath := strings.TrimSuffix(h.BasePath, "/") + "/api/"
		if err = indexTemplate.Execute(w, indexTemplateData{APIUrl: apiPath}); err != nil {
			log.Error().Err(err).Msg("Unable to render index template")
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
			return
		}

		return
	}


Review comment (suggestion):
```suggestion
	// allow iframes from traefik domains only
```

Code after:
	"text/template"

	"github.com/gorilla/mux"
	"github.com/rs/zerolog/log"
	"github.com/traefik/traefik/v3/webui"
)

type indexTemplateData struct {
	APIUrl string
}

// Handler expose dashboard routes.
type Handler struct {
	BasePath string

	assets fs.FS // optional assets, to override the webui.FS default
}

func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	assets := h.assets
	if assets == nil {
		assets = webui.FS
	}

	// allow iframes from traefik domains only
	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src
	w.Header().Set("Content-Security-Policy", "frame-src 'self' https://traefik.io https://*.traefik.io;")

	// The content type must be guessed by the file server.
	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
	w.Header().Del("Content-Type")

	if r.RequestURI == "/" {
		indexTemplate, err := template.ParseFS(assets, "index.html")
		if err != nil {
			log.Error().Err(err).Msg("Unable to parse index template")
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
			return
		}

		apiPath := strings.TrimSuffix(h.BasePath, "/") + "/api/"
		if err = indexTemplate.Execute(w, indexTemplateData{APIUrl: apiPath}); err != nil {
			log.Error().Err(err).Msg("Unable to render index template")
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
			return
		}

		return
	}

	http.FileServerFS(assets).ServeHTTP(w, r)
Repository: traefik/traefik
File: pkg/provider/kubernetes/gateway/tlsroute.go (Go)

Code before:
	}

	lb := &dynamic.TCPServersLoadBalancer{}

	for _, ba := range backendAddresses {
		lb.Servers = append(lb.Servers, dynamic.TCPServer{
			// TODO determine whether the servers needs TLS, from the port?
			Address: net.JoinHostPort(ba.IP, strconv.Itoa(int(ba.Port))),
		})
	}
	return lb, nil
}

func hostSNIRule(hostnames []gatev1.Hostname) (string, int) {
	var priority int

	rules := make([]string, 0, len(hostnames))
	uniqHostnames := map[gatev1.Hostname]struct{}{}

	for _, hostname := range hostnames {
		if len(hostname) == 0 {
			continue
		}

		if priority < len(hostname) {
			priority = len(hostname)
		}

		if _, exists := uniqHostnames[hostname]; exists {
			continue
		}

		host := string(hostname)
		uniqHostnames[hostname] = struct{}{}

		wildcard := strings.Count(host, "*")
		if wildcard == 0 {
			rules = append(rules, fmt.Sprintf("HostSNI(`%s`)", host))
			continue
		}

		host = strings.Replace(regexp.QuoteMeta(host), `\*\.`, `[a-z0-9-\.]+\.`, 1)
		rules = append(rules, fmt.Sprintf("HostSNIRegexp(`^%s$`)", host))
	}

	if len(hostnames) == 0 || len(rules) == 0 {
		return "HostSNI(`*`)", 0
	}

	return strings.Join(rules, " || "), priority
}

Review comment (suggestion):
@augustozanellato I have one last suggestion.
This is nit picking, but the case of one character subdomain that will have the same priority as the wildcard one.
Applying minus one in case of a wildcard should do the trick.

Code after:
	}

	lb := &dynamic.TCPServersLoadBalancer{}

	for _, ba := range backendAddresses {
		lb.Servers = append(lb.Servers, dynamic.TCPServer{
			// TODO determine whether the servers needs TLS, from the port?
			Address: net.JoinHostPort(ba.IP, strconv.Itoa(int(ba.Port))),
		})
	}
	return lb, nil
}

func hostSNIRule(hostnames []gatev1.Hostname) (string, int) {
	var priority int

	rules := make([]string, 0, len(hostnames))
	uniqHostnames := map[gatev1.Hostname]struct{}{}

	for _, hostname := range hostnames {
		if len(hostname) == 0 {
			continue
		}

		host := string(hostname)
		wildcard := strings.Count(host, "*")

		thisPriority := len(hostname) - wildcard

		if priority < thisPriority {
			priority = thisPriority
		}

		if _, exists := uniqHostnames[hostname]; exists {
			continue
		}

		uniqHostnames[hostname] = struct{}{}

		if wildcard == 0 {
			rules = append(rules, fmt.Sprintf("HostSNI(`%s`)", host))
			continue
		}

		host = strings.Replace(regexp.QuoteMeta(host), `\*\.`, `[a-z0-9-\.]+\.`, 1)
		rules = append(rules, fmt.Sprintf("HostSNIRegexp(`^%s$`)", host))
	}

	if len(hostnames) == 0 || len(rules) == 0 {
		return "HostSNI(`*`)", 0
	}
Repository: traefik/traefik
File: pkg/middlewares/customerrors/custom_errors.go (Go)

Code before:
	"go.opentelemetry.io/otel/trace"
)

// Compile time validation that the response recorder implements http interfaces correctly.
var (
	_ middlewares.Stateful = &codeModifier{}
	_ middlewares.Stateful = &codeCatcher{}
)

const typeName = "CustomError"

type serviceBuilder interface {
	BuildHTTP(ctx context.Context, serviceName string) (http.Handler, error)
}

// customErrors is a middleware that provides the custom error pages.
type customErrors struct {
	name           string
	next           http.Handler
	backendHandler http.Handler
	httpCodeRanges types.HTTPCodeRanges
	backendQuery   string
	rewriteStatus  []rewriteStatusObj
}

type rewriteStatusObj struct {
	fromCodes types.HTTPCodeRanges
	toCode    int
}

// New creates a new custom error pages middleware.
func New(ctx context.Context, next http.Handler, config dynamic.ErrorPage, serviceBuilder serviceBuilder, name string) (http.Handler, error) {
	middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware")

	httpCodeRanges, err := types.NewHTTPCodeRanges(config.Status)
	if err != nil {
		return nil, err
	}

	backend, err := serviceBuilder.BuildHTTP(ctx, config.Service)
	if err != nil {
		return nil, err
	}

	// Parse RewriteStatus codes
	rewriteStatus := make([]rewriteStatusObj, 0, len(config.RewriteStatus))
	for k, v := range config.RewriteStatus {
		ranges, err := types.NewHTTPCodeRanges([]string{k})
		if err != nil {
			return nil, err
		}

Review comment (suggestion):
I think `rewriteStatusObj` could be renamed to `statusRewrite` for simplicity and better readability. Since it represents a single status rewrite rule, it feels more intuitive.

Code after:
	"go.opentelemetry.io/otel/trace"
)

// Compile time validation that the response recorder implements http interfaces correctly.
var (
	_ middlewares.Stateful = &codeModifier{}
	_ middlewares.Stateful = &codeCatcher{}
)

const typeName = "CustomError"

type serviceBuilder interface {
	BuildHTTP(ctx context.Context, serviceName string) (http.Handler, error)
}

// customErrors is a middleware that provides the custom error pages.
type customErrors struct {
	name           string
	next           http.Handler
	backendHandler http.Handler
	httpCodeRanges types.HTTPCodeRanges
	backendQuery   string
	statusRewrites []statusRewrite
}

type statusRewrite struct {
	fromCodes types.HTTPCodeRanges
	toCode    int
}

// New creates a new custom error pages middleware.
func New(ctx context.Context, next http.Handler, config dynamic.ErrorPage, serviceBuilder serviceBuilder, name string) (http.Handler, error) {
	middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware")

	httpCodeRanges, err := types.NewHTTPCodeRanges(config.Status)
	if err != nil {
		return nil, err
	}

	backend, err := serviceBuilder.BuildHTTP(ctx, config.Service)
	if err != nil {
		return nil, err
	}

	// Parse StatusRewrites
	statusRewrites := make([]statusRewrite, 0, len(config.StatusRewrites))
	for k, v := range config.StatusRewrites {
		ranges, err := types.NewHTTPCodeRanges([]string{k})
		if err != nil {
			return nil, err
		}
Repository: traefik/traefik
File: script/code-gen.sh (Shell)

Code before:
#!/usr/bin/env bash

set -e -o pipefail

export PROJECT_MODULE="github.com/traefik/traefik"
export MODULE_VERSION="v2"
KUBE_VERSION=v0.30.10
CURRENT_DIR="$(pwd)"

go install "k8s.io/code-generator/cmd/deepcopy-gen@${KUBE_VERSION}"
go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.16.1

CODEGEN_PKG="$(go env GOPATH)/pkg/mod/k8s.io/code-generator@${KUBE_VERSION}"
# shellcheck disable=SC1091 # Cannot check source of this file
source "${CODEGEN_PKG}/kube_codegen.sh"

echo "# Generating kubernetes code ..."
kube::codegen::gen_helpers \
  --boilerplate "$(dirname "${BASH_SOURCE[0]}")/boilerplate.go.tmpl" \
  "${CURRENT_DIR}"

kube::codegen::gen_client \
    --with-watch \
    --output-dir "${CURRENT_DIR}/pkg/provider/kubernetes/crd/generated" \
    --output-pkg "${PROJECT_MODULE}/${MODULE_VERSION}/pkg/provider/kubernetes/crd/generated" \
    --boilerplate "$(dirname "${BASH_SOURCE[0]}")/boilerplate.go.tmpl" \
    "${CURRENT_DIR}/pkg/provider/kubernetes/crd"

echo "# Generating the CRD definitions for the documentation ..."
controller-gen crd:crdVersions=v1 \
    paths={./pkg/provider/kubernetes/crd/traefikio/v1alpha1/...,./pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/...} \

Review comment (suggestion):
If I am not mistaken those variables do not need to be exported, wdyt?

```suggestion
PROJECT_MODULE="github.com/traefik/traefik"
MODULE_VERSION="v2"
```

Code after:
#!/usr/bin/env bash

set -e -o pipefail

PROJECT_MODULE="github.com/traefik/traefik"
MODULE_VERSION="v2"
KUBE_VERSION=v0.30.10
CURRENT_DIR="$(pwd)"

go install "k8s.io/code-generator/cmd/deepcopy-gen@${KUBE_VERSION}"
go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.16.1

CODEGEN_PKG="$(go env GOPATH)/pkg/mod/k8s.io/code-generator@${KUBE_VERSION}"
# shellcheck disable=SC1091 # Cannot check source of this file
source "${CODEGEN_PKG}/kube_codegen.sh"

echo "# Generating Traefik clientset and deepcopy code ..."
kube::codegen::gen_helpers \
  --boilerplate "$(dirname "${BASH_SOURCE[0]}")/boilerplate.go.tmpl" \
  "${CURRENT_DIR}"

kube::codegen::gen_client \
    --with-watch \
    --output-dir "${CURRENT_DIR}/pkg/provider/kubernetes/crd/generated" \
    --output-pkg "${PROJECT_MODULE}/${MODULE_VERSION}/pkg/provider/kubernetes/crd/generated" \
    --boilerplate "$(dirname "${BASH_SOURCE[0]}")/boilerplate.go.tmpl" \
    "${CURRENT_DIR}/pkg/provider/kubernetes/crd"

echo "# Generating the CRD definitions for the documentation ..."
controller-gen crd:crdVersions=v1 \
    paths={./pkg/provider/kubernetes/crd/traefikio/v1alpha1/...,./pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/...} \