Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support extra flags for mysqld_exporter #629

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
12 changes: 8 additions & 4 deletions deploy/crds/planetscale.com_vitessclusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1992,6 +1992,10 @@ spec:
type: object
mysqldExporter:
properties:
extraFlags:
additionalProperties:
type: string
type: object
stankevich marked this conversation as resolved.
Show resolved Hide resolved
resources:
properties:
claims:
Expand Down Expand Up @@ -2025,8 +2029,6 @@ spec:
x-kubernetes-int-or-string: true
type: object
type: object
required:
- resources
type: object
name:
default: ""
Expand Down Expand Up @@ -2433,6 +2435,10 @@ spec:
type: object
mysqldExporter:
properties:
extraFlags:
additionalProperties:
type: string
type: object
resources:
properties:
claims:
Expand Down Expand Up @@ -2466,8 +2472,6 @@ spec:
x-kubernetes-int-or-string: true
type: object
type: object
required:
- resources
type: object
name:
default: ""
Expand Down
12 changes: 8 additions & 4 deletions deploy/crds/planetscale.com_vitesskeyspaces.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,10 @@ spec:
type: object
mysqldExporter:
properties:
extraFlags:
additionalProperties:
type: string
type: object
resources:
properties:
claims:
Expand Down Expand Up @@ -583,8 +587,6 @@ spec:
x-kubernetes-int-or-string: true
type: object
type: object
required:
- resources
type: object
name:
default: ""
Expand Down Expand Up @@ -991,6 +993,10 @@ spec:
type: object
mysqldExporter:
properties:
extraFlags:
additionalProperties:
type: string
type: object
resources:
properties:
claims:
Expand Down Expand Up @@ -1024,8 +1030,6 @@ spec:
x-kubernetes-int-or-string: true
type: object
type: object
required:
- resources
type: object
name:
default: ""
Expand Down
6 changes: 4 additions & 2 deletions deploy/crds/planetscale.com_vitessshards.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,10 @@ spec:
type: object
mysqldExporter:
properties:
extraFlags:
additionalProperties:
type: string
type: object
resources:
properties:
claims:
Expand Down Expand Up @@ -566,8 +570,6 @@ spec:
x-kubernetes-int-or-string: true
type: object
type: object
required:
- resources
type: object
name:
default: ""
Expand Down
16 changes: 16 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,22 @@ EtcdLockserverStatus
<tbody>
<tr>
<td>
<code>extraFlags</code><br>
<em>
map[string]string
</em>
</td>
<td>
<p>ExtraFlags can optionally be used to override default flags set by the
operator, or pass additional flags to mysqld_exporter. All entries must be
key-value string pairs of the form &ldquo;flag&rdquo;: &ldquo;value&rdquo;. The flag name should
not have any prefix (just &ldquo;flag&rdquo;, not &ldquo;-flag&rdquo;). To set a boolean flag,
set the string value to either &ldquo;true&rdquo; or &ldquo;false&rdquo;; the flag will be
automatically converted to the format expected by mysqld_exporter.</p>
</td>
</tr>
<tr>
<td>
<code>resources</code><br>
<em>
<a href="https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#resourcerequirements-v1-core">
Expand Down
16 changes: 16 additions & 0 deletions docs/api/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1538,6 +1538,22 @@ <h3 id="planetscale.com/v2.MysqldExporterSpec">MysqldExporterSpec
<tbody>
<tr>
<td>
<code>extraFlags</code><br>
<em>
map[string]string
</em>
</td>
<td>
<p>ExtraFlags can optionally be used to override default flags set by the
operator, or pass additional flags to mysqld_exporter. All entries must be
key-value string pairs of the form &ldquo;flag&rdquo;: &ldquo;value&rdquo;. The flag name should
not have any prefix (just &ldquo;flag&rdquo;, not &ldquo;-flag&rdquo;). To set a boolean flag,
set the string value to either &ldquo;true&rdquo; or &ldquo;false&rdquo;; the flag will be
automatically converted to the format expected by mysqld_exporter.</p>
</td>
</tr>
<tr>
<td>
<code>resources</code><br>
<em>
<a href="https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#resourcerequirements-v1-core">
Expand Down
10 changes: 9 additions & 1 deletion pkg/apis/planetscale/v2/vitessshard_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,16 @@ type MysqldSpec struct {

// MysqldExporterSpec configures the local MySQL exporter within a tablet.
type MysqldExporterSpec struct {
// ExtraFlags can optionally be used to override default flags set by the
// operator, or pass additional flags to mysqld_exporter. All entries must be
// key-value string pairs of the form "flag": "value". The flag name should
// not have any prefix (just "flag", not "-flag"). To set a boolean flag,
// set the string value to either "true" or "false"; the flag will be
// automatically converted to the format expected by mysqld_exporter.
ExtraFlags map[string]string `json:"extraFlags,omitempty"`

// Resources specify the compute resources to allocate for just the MySQL Exporter.
Resources corev1.ResourceRequirements `json:"resources"`
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
}

// VitessTabletPoolType represents the tablet types for which it makes sense
Expand Down
7 changes: 7 additions & 0 deletions pkg/apis/planetscale/v2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions pkg/operator/vitess/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package vitess
import (
"fmt"
"sort"
"strings"
)

// Flags represents values for flags to be passed to Vitess binaries.
Expand Down Expand Up @@ -61,6 +62,44 @@ func (f Flags) FormatArgs() []string {
return args
}

// FormatArgsConvertBoolean returns the flags as a flattened list of
// command-line args with boolean values formatted as `--flag` or `--no-flag`.
// This format is used by some tools, like mysqld_exporter.
// Method is based on FormatArgs().
func (f Flags) FormatArgsConvertBoolean() []string {
// Sort flag names so the ordering is deterministic,
// which is important when diffing object specs.
// This also makes it easier for humans to find things.
keys := make([]string, 0, len(f))
for key := range f {
keys = append(keys, key)
}
sort.Strings(keys)

// Make formatted args list.
args := make([]string, 0, len(f))
for _, key := range keys {
// These args are passed to the command as a string array,
// so we don't need to worry about quotes or escaping.
//
// We use two dashes (--) even though the standard flag parser
// accepts either one or two dashes, because some wrappers like
// pflags require two dashes.
//
// All boolean values are formatted as `--flag` or `--no-flag`.
value := f[key].(string)
switch value := strings.ToLower(value); value {
case "true":
args = append(args, fmt.Sprintf("--%v", key))
case "false":
args = append(args, fmt.Sprintf("--no-%v", key))
default:
args = append(args, fmt.Sprintf("--%v=%v", key, value))
}
}
return args
}

// Merge sets the given flags, overwriting duplicates.
func (f Flags) Merge(flags Flags) Flags {
for key, value := range flags {
Expand Down
165 changes: 165 additions & 0 deletions pkg/operator/vitess/flags_test.go
stankevich marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
Copyright 2024 PlanetScale Inc.

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 vitess

import (
"testing"

"github.com/stretchr/testify/assert"
)

// TestFormatArgs tests the FormatArgs method of the Flags type.
func TestFormatArgs(t *testing.T) {
tests := []struct {
name string
flags Flags
want []string
}{
{
name: "empty flags",
flags: Flags{},
want: []string{},
},
{
name: "single flag",
flags: Flags{
"flag1": "value1",
},
want: []string{"--flag1=value1"},
},
{
name: "multiple flags",
flags: Flags{
"flag2": "value2",
"flag3": "value3",
},
want: []string{"--flag2=value2", "--flag3=value3"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.flags.FormatArgs()
assert.Equal(t, tt.want, got)
})
}
}

// TestFormatArgsConvertBoolean tests the FormatArgsConvertBoolean method of the Flags type.
func TestFormatArgsConvertBoolean(t *testing.T) {
tests := []struct {
name string
flags Flags
want []string
}{
{
name: "empty flags",
flags: Flags{},
want: []string{},
},
{
name: "boolean flag true",
flags: Flags{
"flag1": "true",
},
want: []string{"--flag1"},
},
{
name: "boolean flag false",
flags: Flags{
"flag2": "false",
},
want: []string{"--no-flag2"},
},
{
name: "non-boolean flag",
flags: Flags{
"flag3": "value3",
},
want: []string{"--flag3=value3"},
},
{
name: "multiple flags",
flags: Flags{
"flag4": "true",
"flag5": "false",
"flag6": "value6",
},
want: []string{"--flag4", "--no-flag5", "--flag6=value6"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.flags.FormatArgsConvertBoolean()
assert.Equal(t, tt.want, got)
})
}
}

// TestMerge tests the Merge method of the Flags type.
func TestMerge(t *testing.T) {
tests := []struct {
name string
flags Flags
merge Flags
result Flags
}{
{
name: "merge empty flags",
flags: Flags{
"flag1": "value1",
},
merge: Flags{},
result: Flags{
"flag1": "value1",
},
},
{
name: "merge non-empty flags",
flags: Flags{
"flag1": "value1",
},
merge: Flags{
"flag2": "value2",
},
result: Flags{
"flag1": "value1",
"flag2": "value2",
},
},
{
name: "merge duplicate flags",
flags: Flags{
"flag1": "value1",
},
merge: Flags{
"flag1": "value2",
},
result: Flags{
"flag1": "value2",
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.flags.Merge(tt.merge)
assert.Equal(t, tt.result, got)
})
}
}
Loading
Loading