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: api.cluster.reroute.go
    path of file: ./repos/corteza/extra/server-discovery/vendor/github.com/elastic/go-elasticsearch/v7/esapi
    
    the code of the file until where you have to start completion: // Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V. licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
//
// Code generated from specification version 7.12.0: DO NOT EDIT

package esapi

import (
	"context"
	"io"
	"net/http"
	"strconv"
	"strings"
	"time"
)

func newClusterRerouteFunc(t Transport) ClusterReroute {
	return func(o ...func(*ClusterRerouteRequest)) (*Response, error) {
		var r = ClusterRerouteRequest{}
		for _, f := range o {
			f(&r)
		}
		return r.Do(r.ctx, t)
	}
}

// ----- API Definition -------------------------------------------------------

// ClusterReroute allows to manually change the allocation of individual shards in the cluster.
//
// See full documentation at https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-reroute.html.
//
type ClusterReroute func(o ...func(*ClusterRerouteRequest)) (*Response, error)

// ClusterRerouteRequest configures the Cluster Reroute API request.
//
type ClusterRerouteRequest struct {
	Body io.Reader

	DryRun        *bool
	Explain       *bool
	MasterTimeout time.Duration
	Metric        []string
	RetryFailed   *bool
	Timeout       time.Duration

	Pretty     bool
	Human      bool
	ErrorTrace bool
	FilterPath []string

	Header http.Header

	ctx con
    
func (r ClusterRerouteRequest) Do(ctx context.Context, transport Transport) (*Response, error) {
	var (
		method string
		path   strings.Builder
		params map[string]string
	)

	method = "POST"

	path.Grow(len("/_cluster/reroute"))
	path.WriteString("/_cluster/reroute")

	params = make(map[string]string)

	if r.DryRun != nil {
		params["dry_run"] = strconv.FormatBool(*r.DryRun)
	}

	if r.Explain != nil {
		params["explain"] = strconv.FormatBool(*r.Explain)
	}

	if r.MasterTimeout != 0 {
		params["master_timeout"] = formatDuration(r.MasterTimeout)
	}

	if len(r.Metric) > 0 {
		params["metric"] = strings.Join(r.Metric, ",")
	}

	if r.RetryFailed != nil {
		params["retry_failed"] = strconv.FormatBool(*r.RetryFailed)
	}

	if r.Timeout != 0 {
		params["timeout"] = formatDuration(r.Timeout)
	}

	if r.Pretty {
		params["pretty"] = "true"
	}

	if r.Human {
		params["human"] = "true"
	}

	if r.ErrorTrace {
		params["error_trace"] = "true"
	}

	if len(r.FilterPath) > 0 {
		params["filter_path"] = strings.Join(r.FilterPath, ",")
	}

	req, err := newRequest(method, path.String(), r.Body)
	if err != nil {
		return nil, err
	}

	if len(params) > 0 {
		q := req.URL.Query()
		for k, v := range params {
			q.Set(k, v)
		}
		req.URL.RawQuery = q.Encode()
	}

	if r.Body != nil {
		req.Header[headerContentType] = headerContentTypeJSON
	}

	if len(r.Header) > 0 {
		if len(req.Header) == 0 {
			req.Header = r.Header
		} else {
			for k, vv := range r.Header {
				for _, v := range vv {
					req.Header.Add(k, v)
				}
			}
		}
	}

	if ctx != nil {
		req = req.WithContext(ctx)
	}

	res, err := transport.Perform(req)
	if err != nil {
		return nil, err
	}

	response := Response{
		StatusCode: res.StatusCode,
		Body:       res.Body,
		Header:     res.Header,
	}

	return &response, nil
}