func parseDuration(str string) (time.Duration, error) {
	matches := durationRegex.FindStringSubmatch(str)
	if len(matches) == 0 {
		return 0, errors.New("Invalid duration, must be ISO8601 format")
	}
	years := parseDurationPart(matches[1], time.Hour*24*365)
	months := parseDurationPart(matches[2], time.Hour*24*30)
	days := parseDurationPart(matches[3], time.Hour*24)
	hours := parseDurationPart(matches[4], time.Hour)
	minutes := parseDurationPart(matches[5], time.Second*60)
	seconds := parseDurationPart(matches[6], time.Second)
	return time.Duration(years + months + days + hours + minutes + seconds), nil
}
ParseDuration converts a ISO8601 duration into a time.Duration
package gcppca
import (
	"context"
	"errors"
	"fmt"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"
	"github.com/hashicorp/vault/sdk/framework"
	"github.com/hashicorp/vault/sdk/logical"
)
func withFieldValidator(f framework.OperationFunc) framework.OperationFunc {
	return func(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
		if err := validateFields(req, d); err != nil {
			return nil, logical.CodedError(400, err.Error())
		}
		return f(ctx, req, d)
	}
}
func validateFields(req *logical.Request, data *framework.FieldData) error {
	var unknownFields []string
	for k := range req.Data {
		if _, ok := data.Schema[k]; !ok {
			unknownFields = append(unknownFields, k)
		}
	}
	switch len(unknownFields) {
	case 0:
		return nil
	case 1:
		return fmt.Errorf("unknown field: %s", unknownFields[0])
	default:
		sort.Strings(unknownFields)
		return fmt.Errorf("unknown fields: %s", strings.Join(unknownFields, ","))
	}
}
func errMissingFields(f ...string) error {
	return logical.CodedError(400, fmt.Sprintf(
		"missing required field(s): %q", f))
}
var durationRegex = regexp.MustCompile(`P([\d\.]+Y)?([\d\.]+M)?([\d\.]+D)?T?([\d\.]+H)?([\d\.]+M)?([\d\.]+?S)?`)