mirror of
https://github.com/apple/foundationdb.git
synced 2025-05-14 01:42:37 +08:00
185 lines
5.6 KiB
Go
185 lines
5.6 KiB
Go
// config.go
|
|
//
|
|
// This source file is part of the FoundationDB open source project
|
|
//
|
|
// Copyright 2021 Apple Inc. and the FoundationDB project 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.
|
|
//
|
|
|
|
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// ProcessConfiguration models the configuration for starting a FoundationDB
|
|
// process.
|
|
type ProcessConfiguration struct {
|
|
// Version provides the version of FoundationDB the process should run.
|
|
Version string `json:"version"`
|
|
|
|
// RunServers defines whether we should run the server processes.
|
|
// This defaults to true, but you can set it to false to prevent starting
|
|
// new fdbserver processes.
|
|
RunServers *bool `json:"runServers,omitempty"`
|
|
|
|
// BinaryPath provides the path to the binary to launch.
|
|
BinaryPath string `json:"-"`
|
|
|
|
// Arguments provides the arguments to the process.
|
|
Arguments []Argument `json:"arguments,omitempty"`
|
|
}
|
|
|
|
// Argument defines an argument to the process.
|
|
type Argument struct {
|
|
// ArgumentType determines how the value is generated.
|
|
ArgumentType ArgumentType `json:"type,omitempty"`
|
|
|
|
// Value provides the value for a Literal type argument.
|
|
Value string `json:"value,omitempty"`
|
|
|
|
// Values provides the sub-values for a Concatenate type argument.
|
|
Values []Argument `json:"values,omitempty"`
|
|
|
|
// Source provides the name of the environment variable to use for an
|
|
// Environment type argument.
|
|
Source string `json:"source,omitempty"`
|
|
|
|
// Multiplier provides a multiplier for the process number for ProcessNumber
|
|
// type arguments.
|
|
Multiplier int `json:"multiplier,omitempty"`
|
|
|
|
// Offset provides an offset to add to the process number for ProcessNumber
|
|
// type arguments.
|
|
Offset int `json:"offset,omitempty"`
|
|
|
|
// IPFamily provides the family to use for IPList type arguments.
|
|
IPFamily int `json:"ipFamily,omitempty"`
|
|
}
|
|
|
|
// ArgumentType defines the types for arguments.
|
|
type ArgumentType string
|
|
|
|
const (
|
|
// LiteralArgumentType defines an argument with a literal string value.
|
|
LiteralArgumentType ArgumentType = "Literal"
|
|
|
|
// ConcatenateArgumentType defines an argument composed of other arguments.
|
|
ConcatenateArgumentType = "Concatenate"
|
|
|
|
// EnvironmentArgumentType defines an argument that is pulled from an
|
|
// environment variable.
|
|
EnvironmentArgumentType = "Environment"
|
|
|
|
// ProcessNumberArgumentType defines an argument that is calculated using
|
|
// the number of the process in the process list.
|
|
ProcessNumberArgumentType = "ProcessNumber"
|
|
|
|
// IPListArgumentType defines an argument that is a comma-separated list of
|
|
// IP addresses, provided through an environment variable.
|
|
IPListArgumentType = "IPList"
|
|
)
|
|
|
|
// GenerateArgument processes an argument and generates its string
|
|
// representation.
|
|
func (argument Argument) GenerateArgument(processNumber int, env map[string]string) (string, error) {
|
|
switch argument.ArgumentType {
|
|
case "":
|
|
fallthrough
|
|
case LiteralArgumentType:
|
|
return argument.Value, nil
|
|
case ConcatenateArgumentType:
|
|
concatenated := ""
|
|
for _, childArgument := range argument.Values {
|
|
childValue, err := childArgument.GenerateArgument(processNumber, env)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
concatenated += childValue
|
|
}
|
|
return concatenated, nil
|
|
case ProcessNumberArgumentType:
|
|
number := processNumber
|
|
if argument.Multiplier != 0 {
|
|
number = number * argument.Multiplier
|
|
}
|
|
number = number + argument.Offset
|
|
return strconv.Itoa(number), nil
|
|
case EnvironmentArgumentType, IPListArgumentType:
|
|
return argument.LookupEnv(env)
|
|
default:
|
|
return "", fmt.Errorf("unsupported argument type %s", argument.ArgumentType)
|
|
}
|
|
}
|
|
|
|
// LookupEnv looks up the value for an argument from the environment.
|
|
func (argument Argument) LookupEnv(env map[string]string) (string, error) {
|
|
var value string
|
|
var present bool
|
|
if env != nil {
|
|
value, present = env[argument.Source]
|
|
}
|
|
if !present {
|
|
value, present = os.LookupEnv(argument.Source)
|
|
}
|
|
if !present {
|
|
return "", fmt.Errorf("missing environment variable %s", argument.Source)
|
|
}
|
|
|
|
if argument.ArgumentType == IPListArgumentType {
|
|
ips := strings.Split(value, ",")
|
|
for _, ipString := range ips {
|
|
ip := net.ParseIP(ipString)
|
|
if ip == nil {
|
|
continue
|
|
}
|
|
switch argument.IPFamily {
|
|
case 4:
|
|
if ip.To4() != nil {
|
|
return ipString, nil
|
|
}
|
|
case 6:
|
|
if ip.To16() != nil && ip.To4() == nil {
|
|
return ipString, nil
|
|
}
|
|
default:
|
|
return "", fmt.Errorf("unsupported IP family %d", argument.IPFamily)
|
|
}
|
|
}
|
|
return "", fmt.Errorf("could not find IP with family %d", argument.IPFamily)
|
|
}
|
|
return value, nil
|
|
}
|
|
|
|
// GenerateArguments interprets the arguments in the process configuration and
|
|
// generates a command invocation.
|
|
func (configuration *ProcessConfiguration) GenerateArguments(processNumber int, env map[string]string) ([]string, error) {
|
|
results := make([]string, 0, len(configuration.Arguments)+1)
|
|
if configuration.BinaryPath != "" {
|
|
results = append(results, configuration.BinaryPath)
|
|
}
|
|
for _, argument := range configuration.Arguments {
|
|
result, err := argument.GenerateArgument(processNumber, env)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
results = append(results, result)
|
|
}
|
|
return results, nil
|
|
}
|