feat: replace bootkube with Talos-managed control plane

Control plane components are running as static pods managed by the
kubelets.

Whole subsystem is managed via resources/controllers from os-runtime.

Many supporting changes/refactoring to enable new code paths.

Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
This commit is contained in:
Andrey Smirnov 2021-01-19 15:45:50 +03:00 committed by talos-bot
parent a2b6939c21
commit 0aaf8fa968
81 changed files with 5951 additions and 1648 deletions

View File

@ -93,6 +93,8 @@ COPY ./api/cluster/cluster.proto /api/cluster/cluster.proto
RUN protoc -I/api -I/api/vendor/ --go_out=plugins=grpc,paths=source_relative:/api cluster/cluster.proto
COPY ./api/resource/resource.proto /api/resource/resource.proto
RUN protoc -I/api -I/api/vendor/ --go_out=plugins=grpc,paths=source_relative:/api resource/resource.proto
COPY ./api/inspect/inspect.proto /api/inspect/inspect.proto
RUN protoc -I/api -I/api/vendor/ --go_out=plugins=grpc,paths=source_relative:/api inspect/inspect.proto
# Gofumports generated files to adjust import order
RUN gofumports -w -local github.com/talos-systems/talos /api/
@ -112,6 +114,7 @@ COPY --from=generate-build /api/network/*.pb.go /pkg/machinery/api/network/
COPY --from=generate-build /api/cluster/*.pb.go /pkg/machinery/api/cluster/
COPY --from=generate-build /api/storage/*.pb.go /pkg/machinery/api/storage/
COPY --from=generate-build /api/resource/*.pb.go /pkg/machinery/api/resource/
COPY --from=generate-build /api/inspect/*.pb.go /pkg/machinery/api/inspect/
COPY --from=generate-build /pkg/machinery/config/types/v1alpha1/*_doc.go /pkg/machinery/config/types/v1alpha1/
# The base target provides a container that can be used to build all Talos
@ -268,27 +271,6 @@ RUN printf "FROM scratch\nCOPY ./routerd /routerd\nENTRYPOINT [\"/routerd\"]" >
RUN --security=insecure img build --tag ${USERNAME}/routerd:${TAG} --output type=docker,dest=/routerd.tar --no-console .
# The bootkube target builds the bootkube image.
FROM base AS bootkube-build
ARG SHA
ARG TAG
ARG PKGS
ARG EXTRAS
ARG VERSION_PKG="github.com/talos-systems/talos/pkg/version"
WORKDIR /src/internal/app/bootkube
RUN --mount=type=cache,target=/.cache/go-build go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Server -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X ${VERSION_PKG}.PkgsVersion=${PKGS} -X ${VERSION_PKG}.ExtrasVersion=${EXTRAS}" -o /bootkube
RUN chmod +x /bootkube
FROM base AS bootkube-image
ARG TAG
ARG USERNAME
COPY --from=bootkube-build /bootkube /scratch/bootkube
WORKDIR /scratch
RUN printf "FROM scratch\nCOPY ./bootkube /bootkube\nENTRYPOINT [\"/bootkube\"]" > Dockerfile
RUN --security=insecure img build --tag ${USERNAME}/bootkube:${TAG} --output type=docker,dest=/bootkube.tar --no-console .
# The talosctl targets build the talosctl binaries.
FROM base AS talosctl-linux-amd64-build
@ -392,7 +374,6 @@ COPY --from=pkg-kmod /usr/lib/libkmod.* /rootfs/lib/
COPY --from=pkg-kernel /lib/modules /rootfs/lib/modules
COPY --from=machined /machined /rootfs/sbin/init
COPY --from=apid-image /apid.tar /rootfs/usr/images/
COPY --from=bootkube-image /bootkube.tar /rootfs/usr/images/
COPY --from=timed-image /timed.tar /rootfs/usr/images/
COPY --from=trustd-image /trustd.tar /rootfs/usr/images/
COPY --from=networkd-image /networkd.tar /rootfs/usr/images/
@ -645,6 +626,7 @@ RUN protoc \
-I/protos \
-I/protos/common \
-I/protos/health \
-I/protos/inspect \
-I/protos/machine \
-I/protos/network \
-I/protos/resource \
@ -656,6 +638,7 @@ RUN protoc \
--doc_out=/tmp \
/protos/common/*.proto \
/protos/health/*.proto \
/protos/inspect/*.proto \
/protos/machine/*.proto \
/protos/network/*.proto \
/protos/resource/*.proto \

42
api/inspect/inspect.proto Normal file
View File

@ -0,0 +1,42 @@
syntax = "proto3";
package inspect;
option go_package = "github.com/talos-systems/talos/pkg/machinery/api/inspect";
option java_multiple_files = true;
option java_outer_classname = "InspectApi";
option java_package = "com.inspect.api";
import "google/protobuf/empty.proto";
import "common/common.proto";
// The inspect service definition.
//
// InspectService provides auxilary API to inspect OS internals.
service InspectService {
rpc ControllerRuntimeDependencies(google.protobuf.Empty) returns (ControllerRuntimeDependenciesResponse);
}
// The ControllerRuntimeDependency message contains the graph of controller-resource dependencies.
message ControllerRuntimeDependency {
common.Metadata metadata = 1;
repeated ControllerDependencyEdge edges = 2;
}
message ControllerRuntimeDependenciesResponse { repeated ControllerRuntimeDependency messages = 1; }
enum DependencyEdgeType {
MANAGES = 0;
STRONG = 1;
WEAK = 2;
}
message ControllerDependencyEdge {
string controller_name = 1;
DependencyEdgeType edge_type = 2;
string resource_namespace = 3;
string resource_type = 4;
string resource_id = 5;
}

View File

@ -126,6 +126,7 @@ message ServiceStateEvent {
};
Action action = 2;
string message = 3;
ServiceHealth health = 4;
};
message EventsRequest {

View File

@ -9,8 +9,7 @@ import (
"github.com/spf13/cobra"
"github.com/talos-systems/talos/internal/app/bootkube/images"
imagespkg "github.com/talos-systems/talos/pkg/images"
"github.com/talos-systems/talos/pkg/images"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1"
)
@ -44,8 +43,8 @@ var imagesCmd = &cobra.Command{
fmt.Printf("%s\n", images.KubeScheduler)
fmt.Printf("%s\n", images.KubeProxy)
fmt.Printf("%s\n", images.Kubelet)
fmt.Printf("%s\n", images.PodCheckpointer)
fmt.Printf("%s\n", imagespkg.DefaultInstallerImage)
fmt.Printf("%s\n", images.Installer)
fmt.Printf("%s\n", images.Pause)
return nil
},

View File

@ -0,0 +1,185 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package talos
import (
"context"
"fmt"
"io"
"os"
"github.com/emicklei/dot"
"github.com/spf13/cobra"
"github.com/talos-systems/os-runtime/pkg/resource"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/talos-systems/talos/cmd/talosctl/pkg/talos/helpers"
"github.com/talos-systems/talos/pkg/cli"
"github.com/talos-systems/talos/pkg/machinery/api/inspect"
"github.com/talos-systems/talos/pkg/machinery/client"
)
// inspectCmd represents the inspect command.
var inspectCmd = &cobra.Command{
Use: "inspect",
Short: "Inspect internals of Talos",
Long: ``,
}
var inspectDependenciesCmdFlags struct {
withResources bool
}
// inspectDependenciesCmd represents the inspect dependencies command.
var inspectDependenciesCmd = &cobra.Command{
Use: "dependencies",
Short: "Inspect controller-resource dependencies as graphviz graph.",
Long: `Inspect controller-resource dependencies as graphviz graph.
Pipe the output of the command through the "dot" program (part of graphviz package)
to render the graph:
talosctl inspect dependencies | dot -Tpng > graph.png
`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return WithClient(func(ctx context.Context, c *client.Client) error {
if err := helpers.FailIfMultiNodes(ctx, "inspect dependencies"); err != nil {
return err
}
resp, err := c.Inspect.ControllerRuntimeDependencies(ctx)
if err != nil {
if resp == nil {
return fmt.Errorf("error getting controller runtime dependencies: %s", err)
}
cli.Warning("%s", err)
}
graph := dot.NewGraph(dot.Directed)
resourceTypeID := func(edge *inspect.ControllerDependencyEdge) string {
return fmt.Sprintf("%s:%s", edge.GetResourceNamespace(), edge.GetResourceType())
}
resourceID := func(r resource.Resource) string {
return r.Metadata().ID()
}
if inspectDependenciesCmdFlags.withResources {
resources := map[string][]resource.Resource{}
for _, msg := range resp.GetMessages() {
for _, edge := range msg.GetEdges() {
resourceType := resourceTypeID(edge)
if _, ok := resources[resourceType]; ok {
continue
}
listClient, err := c.Resources.List(ctx, edge.GetResourceNamespace(), edge.GetResourceType())
if err != nil {
return fmt.Errorf("error listing resources: %w", err)
}
for {
resp, err := listClient.Recv()
if err != nil {
if err == io.EOF || status.Code(err) == codes.Canceled {
break
}
return fmt.Errorf("error listing resources: %w", err)
}
if resp.Resource != nil {
resources[resourceType] = append(resources[resourceType], resp.Resource)
}
}
}
}
for _, msg := range resp.GetMessages() {
for _, edge := range msg.GetEdges() {
graph.Node(edge.ControllerName).Box()
}
}
for resourceType, resourceList := range resources {
cluster := graph.Subgraph(resourceType, dot.ClusterOption{})
for _, resource := range resourceList {
cluster.Node(resourceID(resource)).
Attr("shape", "note").
Attr("fillcolor", "azure2").
Attr("style", "filled")
}
}
for _, msg := range resp.GetMessages() {
for _, edge := range msg.GetEdges() {
for _, resource := range resources[resourceTypeID(edge)] {
if edge.GetResourceId() != "" && resource.Metadata().ID() != edge.GetResourceId() {
continue
}
switch edge.GetEdgeType() {
case inspect.DependencyEdgeType_MANAGES:
graph.Edge(graph.Node(edge.ControllerName), graph.Subgraph(resourceTypeID(edge)).Node(resourceID(resource))).Solid()
case inspect.DependencyEdgeType_STRONG:
graph.Edge(graph.Subgraph(resourceTypeID(edge)).Node(resourceID(resource)), graph.Node(edge.ControllerName)).Solid()
case inspect.DependencyEdgeType_WEAK:
graph.Edge(graph.Subgraph(resourceTypeID(edge)).Node(resourceID(resource)), graph.Node(edge.ControllerName)).Dotted()
}
}
}
}
} else {
for _, msg := range resp.GetMessages() {
for _, edge := range msg.GetEdges() {
graph.Node(edge.ControllerName).Box()
graph.Node(resourceTypeID(edge)).
Attr("shape", "note").
Attr("fillcolor", "azure2").
Attr("style", "filled")
}
}
for _, msg := range resp.GetMessages() {
for _, edge := range msg.GetEdges() {
idLabels := []string{}
if edge.GetResourceId() != "" {
idLabels = append(idLabels, edge.GetResourceId())
}
switch edge.GetEdgeType() {
case inspect.DependencyEdgeType_MANAGES:
graph.Edge(graph.Node(edge.ControllerName), graph.Node(resourceTypeID(edge))).Bold()
case inspect.DependencyEdgeType_STRONG:
graph.Edge(graph.Node(resourceTypeID(edge)), graph.Node(edge.ControllerName), idLabels...).Solid()
case inspect.DependencyEdgeType_WEAK:
graph.Edge(graph.Node(resourceTypeID(edge)), graph.Node(edge.ControllerName), idLabels...).Dotted()
}
}
}
}
graph.Write(os.Stdout)
return nil
})
},
}
func init() {
addCommand(inspectCmd)
inspectCmd.AddCommand(inspectDependenciesCmd)
inspectDependenciesCmd.Flags().BoolVar(&inspectDependenciesCmdFlags.withResources, "with-resources", false, "display live resource information with dependencies")
}

22
go.mod
View File

@ -9,6 +9,7 @@ replace (
)
require (
github.com/AlekSi/pointer v1.1.0
github.com/BurntSushi/toml v0.3.1
github.com/Microsoft/hcsshim v0.8.10 // indirect
github.com/Microsoft/hcsshim/test v0.0.0-20201124231931-de74fe8b94ae // indirect
@ -24,10 +25,15 @@ require (
github.com/containernetworking/cni v0.8.0
github.com/containernetworking/plugins v0.8.7
github.com/coreos/go-iptables v0.4.5
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
github.com/docker/distribution v2.7.1+incompatible
github.com/docker/docker v1.13.1
github.com/docker/go-connections v0.4.0
github.com/dustin/go-humanize v1.0.0
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484 // indirect
github.com/elazarl/goproxy/ext v0.0.0-20191011121108-aa519ddbe484 // indirect
github.com/emicklei/dot v0.15.0
github.com/emicklei/go-restful v2.11.1+incompatible // indirect
github.com/fatih/color v1.10.0
github.com/firecracker-microvm/firecracker-go-sdk v0.22.0
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa
@ -37,11 +43,11 @@ require (
github.com/golang/protobuf v1.4.3
github.com/google/uuid v1.1.2
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
github.com/grpc-ecosystem/grpc-gateway v1.11.3 // indirect
github.com/hashicorp/go-getter v1.5.1
github.com/hashicorp/go-multierror v1.1.0
github.com/insomniacslk/dhcp v0.0.0-20201112113307-4de412bc85d8
github.com/jsimonetti/rtnetlink v0.0.0-20201125080424-8bebea019a6c
github.com/kubernetes-sigs/bootkube v0.14.1-0.20200817205730-0b4482256ca1
github.com/mattn/go-isatty v0.0.12
github.com/mdlayher/genetlink v1.0.0
github.com/mdlayher/netlink v1.1.1
@ -55,24 +61,24 @@ require (
github.com/ryanuber/columnize v2.1.2+incompatible
github.com/smira/go-xz v0.0.0-20201019130106-9921ed7a9935
github.com/spf13/cobra v1.1.1
github.com/stretchr/testify v1.6.1
github.com/stretchr/testify v1.7.0
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
github.com/talos-systems/bootkube-plugin v0.0.0-20201223175004-aee474d8d060
github.com/talos-systems/crypto v0.2.1-0.20201203131813-e0dd56ac4745
github.com/talos-systems/crypto v0.2.1-0.20210125160556-cf75519cab82
github.com/talos-systems/go-blockdevice v0.1.1-0.20201218174450-f2728a581972
github.com/talos-systems/go-loadbalancer v0.1.0
github.com/talos-systems/go-procfs v0.0.0-20210108152626-8cbc42d3dc24
github.com/talos-systems/go-retry v0.2.0
github.com/talos-systems/go-smbios v0.0.0-20200807005123-80196199691e
github.com/talos-systems/grpc-proxy v0.2.0
github.com/talos-systems/net v0.2.0
github.com/talos-systems/os-runtime v0.0.0-20210119124441-98acf0d2d332
github.com/talos-systems/net v0.2.1-0.20210121122956-005a94f8b36b
github.com/talos-systems/os-runtime v0.0.0-20210126185717-734f1e1cee9e
github.com/talos-systems/talos/pkg/machinery v0.0.0-20200818212414-6a7cc0264819
github.com/u-root/u-root v7.0.0+incompatible
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect
github.com/vmware-tanzu/sonobuoy v0.19.0
github.com/vmware/vmw-guestinfo v0.0.0-20200218095840-687661b8bd8e
go.etcd.io/etcd v0.5.0-alpha.5.0.20201125193152-8a03d2e9614b
go.uber.org/zap v1.14.1 // indirect
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 // indirect
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
@ -86,11 +92,11 @@ require (
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
gopkg.in/freddierice/go-losetup.v1 v1.0.0-20170407175016-fc9adea44124
gopkg.in/fsnotify.v1 v1.4.7
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
honnef.co/go/tools v0.0.1-2020.1.6 // indirect
k8s.io/api v0.20.2
k8s.io/apimachinery v0.20.2
k8s.io/apiserver v0.20.2
k8s.io/apiserver v0.20.2 // indirect
k8s.io/client-go v0.20.2
k8s.io/cri-api v0.20.2
k8s.io/kubelet v0.20.2

122
go.sum
View File

@ -7,14 +7,12 @@ cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6A
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.47.0/go.mod h1:5p3Ky/7f3N10VBkhuR5LFtddroTiMyjZV/Kj5qOQFxU=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.2.0/go.mod h1:Cqg1qaK3wRdys8sKlow0jIBVFwSTiHoFx5um4ujCpyE=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0 h1:xE3CPsOgttP4ACBePh79zTKALtXwn/Edhcr16R5hMWU=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@ -27,7 +25,6 @@ cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+
cloud.google.com/go/pubsub v1.2.0 h1:Lpy6hKgdcl7a3WGSfJIFmxmcdjSpP6OmBEfcOv1Y680=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.2.1/go.mod h1:kpwTAahUQmhyVVGgLWQh2GdyPDZSA3UJDjMm/fDV2oQ=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0 h1:UDpwYIwla4jHGzZJaEJYx1tOejbgSoNqsAfHAUYe2r8=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
@ -40,12 +37,10 @@ github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.1/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.2/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.11.1 h1:eVvIXUKiTgv++6YnWb42DUA1YL7qDugnKP0HljexdnQ=
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.6.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0=
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
@ -79,7 +74,6 @@ github.com/Microsoft/hcsshim v0.8.10/go.mod h1:g5uw8EV2mAlzqe94tfNBNdr89fnbD/n3H
github.com/Microsoft/hcsshim/test v0.0.0-20201124231931-de74fe8b94ae h1:O4x+p9kPOz8k0zIZauAgoq9zRAGD1nShUxjlVH/rBK4=
github.com/Microsoft/hcsshim/test v0.0.0-20201124231931-de74fe8b94ae/go.mod h1:IrOsC3sbIiki4idDR4z1Plxm8vAUM5dKN/HEVkRU0GI=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
@ -124,7 +118,6 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
@ -137,6 +130,8 @@ github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0Bsq
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae h1:2Zmk+8cNvAGuY8AyvZuWpUdpQUAXwfom4ReVMe/CTIo=
github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
github.com/cenkalti/backoff/v4 v4.1.0 h1:c8LkOFQTzuO0WBM/ae5HdGQuZPfPxp7lqBRwQRm4fSc=
github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@ -192,9 +187,7 @@ github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ
github.com/containernetworking/plugins v0.8.7 h1:bU7QieuAp+sACI2vCzESJ3FoT860urYP+lThyZkb/2M=
github.com/containernetworking/plugins v0.8.7/go.mod h1:R7lXeZaBzpfqapcAbHRW8/CYwm0dHzbz0XEjofx0uB0=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38=
@ -211,7 +204,6 @@ github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+
github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg=
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
@ -226,7 +218,6 @@ github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1S
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -241,7 +232,6 @@ github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyG
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible h1:dvc1KSkIYTVjZgHf/CTC2diTYC8PzhaA5sFISRfNVrE=
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo=
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
@ -260,7 +250,6 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484 h1:pEtiCjIXx3RvGjlUJuCNxNOw0MNblyR9Wi+vJGBFh+8=
@ -268,8 +257,11 @@ github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/El
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/elazarl/goproxy/ext v0.0.0-20191011121108-aa519ddbe484 h1:aBgSK7SOjFeL1wfzfbIb/pkPpfRr6EP7b1Af4o/xkpU=
github.com/elazarl/goproxy/ext v0.0.0-20191011121108-aa519ddbe484/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/emicklei/dot v0.15.0 h1:XDBW0Xco1QNyRb33cqLe10cT04yMWL1XpCZfa98Q6Og=
github.com/emicklei/dot v0.15.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.11.1+incompatible h1:CjKsv3uWcCMvySPQYKxO8XX3f9zD4FeZRsW4G0B4ffE=
github.com/emicklei/go-restful v2.11.1+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -347,7 +339,6 @@ github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI=
github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk=
github.com/go-openapi/loads v0.19.5 h1:jZVYWawIQiA1NBnHla28ktg6hrcfTHsCE+3QLVRBIls=
github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY=
github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
@ -362,7 +353,6 @@ github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsd
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
github.com/go-openapi/spec v0.19.8 h1:qAdZLh1r6QF/hI/gTq+TJTvsQUodZsM7KLqkAJdiJNg=
github.com/go-openapi/spec v0.19.8/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
@ -385,7 +375,6 @@ github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfT
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo=
github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-openapi/validate v0.19.10/go.mod h1:RKEZTUWDkxKQxN2jDT7ZnZi2bhZlbNMAuKvKB+IaGx8=
github.com/go-openapi/validate v0.19.11 h1:8lCr0b9lNWKjVjW/hSZZvltUy+bULl7vbnCTsOzlhPo=
github.com/go-openapi/validate v0.19.11/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0waH08tGe6kAQ4=
@ -435,7 +424,6 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -472,7 +460,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -480,7 +467,6 @@ github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPg
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191105193234-27840fff0d09/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@ -495,13 +481,10 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v0.2.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v0.6.0 h1:Xb2lcqZtml1XjgYZxbeayEemq7ASbeTp09m36gQFpEU=
github.com/gophercloud/gophercloud v0.6.0/go.mod h1:GICNByuaEBibcjmjvI7QvYJSZEbGkcYwAR7EZK2WMqM=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
@ -510,16 +493,11 @@ github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE=
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0=
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
@ -562,8 +540,6 @@ github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
@ -598,7 +574,6 @@ github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqo
github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg=
github.com/jsimonetti/rtnetlink v0.0.0-20201125080424-8bebea019a6c h1:SIKkaHgrNzRnHEB3QtUR3VUwy9+QpnTwhZ9GYBC0QyU=
github.com/jsimonetti/rtnetlink v0.0.0-20201125080424-8bebea019a6c/go.mod h1:cR77jAZG3Y3bsb8hF6fHJbFoyFukLFOkQ98S0pQz3xw=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@ -624,13 +599,9 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kubernetes-sigs/bootkube v0.14.1-0.20200416193108-93ff8fc5e457/go.mod h1:CIpoNLW4Lm9zNVFRgqQIylnbZi/x9TnulTEA8edC0O4=
github.com/kubernetes-sigs/bootkube v0.14.1-0.20200817205730-0b4482256ca1 h1:kjwCNY83bnHUNR6XijS2HDxuXqIp+W8lwk17N2RXlKI=
github.com/kubernetes-sigs/bootkube v0.14.1-0.20200817205730-0b4482256ca1/go.mod h1:tgR06vqFs3qxPEkOFmiMDy9UbQ0PMcee/FK6dOyiHFs=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
@ -702,7 +673,6 @@ github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/f
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
@ -722,14 +692,11 @@ github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:v
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
@ -753,7 +720,6 @@ github.com/opencontainers/selinux v1.6.0 h1:+bIAS/Za3q5FTwWym4fTB0vObnfCf3G/NC7K
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v0.0.0-20150603214016-ca53cad383ca/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
@ -767,7 +733,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
@ -776,7 +741,6 @@ github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@ -789,7 +753,6 @@ github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7q
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@ -797,7 +760,6 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
@ -811,11 +773,9 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-charset v0.0.0-20190617161244-0dc95cdf6f31/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.5.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
@ -861,7 +821,6 @@ github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.0-20170515075120-4cdb38c072b8/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
@ -885,7 +844,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -893,15 +851,15 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.0/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/talos-systems/bootkube-plugin v0.0.0-20201223175004-aee474d8d060 h1:mPJ7w+edz0xQhhZ9Qp1iF7w5vcj7owK2ExmS8usDsFA=
github.com/talos-systems/bootkube-plugin v0.0.0-20201223175004-aee474d8d060/go.mod h1:AbdJAgHK5rJNDPUN3msPTfQJSR9b4DKb5xNN07uG8/Y=
github.com/talos-systems/crypto v0.2.1-0.20201203131813-e0dd56ac4745 h1:Smw6ebFiEiwrkaOD2hEYYb+xkIhQTMZNq3WVYKLszB8=
github.com/talos-systems/crypto v0.2.1-0.20201203131813-e0dd56ac4745/go.mod h1:KwqG+jANKU1FNQIapmioHQ5fkovY1DJkAqMenjYBGh0=
github.com/talos-systems/crypto v0.2.1-0.20210125160556-cf75519cab82 h1:5TsM3o/yJJF6kakHyPee88D0yWNNDNKZJ2NCX9MFsKk=
github.com/talos-systems/crypto v0.2.1-0.20210125160556-cf75519cab82/go.mod h1:OXCK52Q0dzm88YRG4VdTBdidkPUtqrCxCyW7bUs4DAw=
github.com/talos-systems/go-blockdevice v0.1.1-0.20201218174450-f2728a581972 h1:/yEPl6h6+pK9XIfQEiZ989GDuw6dCUBeinzUcCu6dyY=
github.com/talos-systems/go-blockdevice v0.1.1-0.20201218174450-f2728a581972/go.mod h1:efEE9wjtgxiovqsZAV39xlOd/AOI/0sLuZqb5jEgeqo=
github.com/talos-systems/go-loadbalancer v0.1.0 h1:MQFONvSjoleU8RrKq1O1Z8CyTCJGd4SLqdAHDlR6o9s=
@ -915,10 +873,10 @@ github.com/talos-systems/go-smbios v0.0.0-20200807005123-80196199691e h1:uCp8BfH
github.com/talos-systems/go-smbios v0.0.0-20200807005123-80196199691e/go.mod h1:HxhrzAoTZ7ed5Z5VvtCvnCIrOxyXDS7V2B5hCetAMW8=
github.com/talos-systems/grpc-proxy v0.2.0 h1:DN75bLfaW4xfhq0r0mwFRnfGhSB+HPhK1LNzuMEs9Pw=
github.com/talos-systems/grpc-proxy v0.2.0/go.mod h1:sm97Vc/z2cok3pu6ruNeszQej4KDxFrDgfWs4C1mtC4=
github.com/talos-systems/net v0.2.0 h1:QJ2ofYboG1Zjew9b+3RAjtLIfL0mIONGuc6/LyO68MM=
github.com/talos-systems/net v0.2.0/go.mod h1:VreSAyRmxMtqussAHSKMKkJQa1YwBTSVfkmE4Jydam4=
github.com/talos-systems/os-runtime v0.0.0-20210119124441-98acf0d2d332 h1:Ib5HAIpv8GjAfdKSzcPfvUPN2mbzYwsre61Sogjt/kk=
github.com/talos-systems/os-runtime v0.0.0-20210119124441-98acf0d2d332/go.mod h1:pQ8E1nmr8SODM9TD9HXH5HlzgyfyeCO8yug4x6fDKlQ=
github.com/talos-systems/net v0.2.1-0.20210121122956-005a94f8b36b h1:y3mBkTJdW7cUn+ff53TZN0yyWCpjS6XrVmlx+vx9pwA=
github.com/talos-systems/net v0.2.1-0.20210121122956-005a94f8b36b/go.mod h1:VreSAyRmxMtqussAHSKMKkJQa1YwBTSVfkmE4Jydam4=
github.com/talos-systems/os-runtime v0.0.0-20210126185717-734f1e1cee9e h1:HrAdgwnXhVr9LlWjpc+kejkLVUpTRKbNTAJe7H+kRXM=
github.com/talos-systems/os-runtime v0.0.0-20210126185717-734f1e1cee9e/go.mod h1:+E9CUVoYpReh0nhOEvFpy7pwLiyq0700WF03I06giyk=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@ -927,9 +885,7 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1
github.com/u-root/u-root v7.0.0+incompatible h1:u+KSS04pSxJGI5E7WE4Bs9+Zd75QjFv+REkjy/aoAc8=
github.com/u-root/u-root v7.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
@ -967,16 +923,13 @@ github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPS
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
go.etcd.io/etcd v0.5.0-alpha.5.0.20201125193152-8a03d2e9614b h1:PLwvCoe5rvpuo9Un6/hlNRMAfOMVb7zBsOOeKAjV81g=
go.etcd.io/etcd v0.5.0-alpha.5.0.20201125193152-8a03d2e9614b/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
go.mongodb.org/mongo-driver v1.3.4 h1:zs/dKNwX0gYUtzwrN9lLiR15hCO0nDwQj5xXx+vjCdE=
go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
@ -1014,7 +967,6 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191108234033-bd318be0434a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@ -1024,10 +976,7 @@ golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE=
golang.org/x/exp v0.0.0-20191024150812-c286b889502e/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
@ -1037,7 +986,6 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -1051,7 +999,6 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20191031020345-0945064e013a/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
@ -1083,13 +1030,11 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191109021931-daa7c04131f5/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -1151,7 +1096,6 @@ golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1160,7 +1104,6 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191110163157-d32e6e3b99c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1235,18 +1178,11 @@ golang.org/x/tools v0.0.0-20190624190245-7f2218787638/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190909214602-067311248421/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191010171213-8abd42400456/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191028194131-d78a1f2664a0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191105231337-689d0f08e67a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191111154804-8cb0d02132ec/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@ -1303,8 +1239,6 @@ google.golang.org/genproto v0.0.0-20190626174449-989357319d63/go.mod h1:z3L6/3dT
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191028173616-919d9bdd9fe6/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
@ -1362,7 +1296,6 @@ gopkg.in/freddierice/go-losetup.v1 v1.0.0-20170407175016-fc9adea44124/go.mod h1:
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
@ -1384,6 +1317,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E=
@ -1399,71 +1334,44 @@ honnef.co/go/tools v0.0.1-2020.1.6 h1:W18jzjh8mfPez+AwGLxmOImucz/IFjpNlrKVnaj2YV
honnef.co/go/tools v0.0.1-2020.1.6/go.mod h1:pyyisuGw24ruLjrr1ddx39WE0y9OooInRzEYLhQB2YY=
inet.af/tcpproxy v0.0.0-20200125044825-b6bb9b5b8252 h1:gmJCKidOfjKDUHF1jjke+I+2iQIyE3HNNxu2OKO/FUI=
inet.af/tcpproxy v0.0.0-20200125044825-b6bb9b5b8252/go.mod h1:zq+R+tLcdHugi7Jt+FtIQY6m6wtX34lr2CdQVH2fhW0=
k8s.io/api v0.0.0-20191016110408-35e52d86657a/go.mod h1:/L5qH+AD540e7Cetbui1tuJeXdmNhO8jM6VkXeDdDhQ=
k8s.io/api v0.0.0-20191109101513-0171b7c15da1/go.mod h1:VJq7+38rpM4TSUbRiZX4P5UVAKK2UQpNQLZClkFQkpE=
k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
k8s.io/api v0.18.5/go.mod h1:tN+e/2nbdGKOAH55NMV8oGrMG+3uRlA9GaRfvnCCSNk=
k8s.io/api v0.20.2 h1:y/HR22XDZY3pniu9hIFDLpUCPq2w5eQ6aV/VFQ7uJMw=
k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8=
k8s.io/apiextensions-apiserver v0.0.0-20190202013456-d4288ab64945/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE=
k8s.io/apiextensions-apiserver v0.18.2 h1:I4v3/jAuQC+89L3Z7dDgAiN4EOjN6sbm6iBqQwHTah8=
k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ=
k8s.io/apimachinery v0.0.0-20191109100837-dffb012825f2/go.mod h1:+6CX7hP4aLfX2sb91JYDMIp0VqDSog2kZu0BHe+lP+s=
k8s.io/apimachinery v0.0.0-20191111054156-6eb29fdf75dc/go.mod h1:+6CX7hP4aLfX2sb91JYDMIp0VqDSog2kZu0BHe+lP+s=
k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
k8s.io/apimachinery v0.18.5/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
k8s.io/apimachinery v0.20.2 h1:hFx6Sbt1oG0n6DZ+g4bFt5f6BoMkOjKWsQFu077M3Vg=
k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
k8s.io/apiserver v0.20.2 h1:lGno2t3gcZnLtzsKH4oG0xA9/4GTiBzMO1DGp+K+Bak=
k8s.io/apiserver v0.20.2/go.mod h1:2nKd93WyMhZx4Hp3RfgH2K5PhwyTrprrkWYnI7id7jA=
k8s.io/client-go v0.0.0-20191016111102-bec269661e48/go.mod h1:hrwktSwYGI4JK+TJA3dMaFyyvHVi/aLarVHpbs8bgCU=
k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU=
k8s.io/client-go v0.18.5/go.mod h1:EsiD+7Fx+bRckKWZXnAXRKKetm1WuzPagH4iOSC8x58=
k8s.io/client-go v0.20.2 h1:uuf+iIAbfnCSw8IGAv/Rg0giM+2bOzHLOsbbrwrdhNQ=
k8s.io/client-go v0.20.2/go.mod h1:kH5brqWqp7HDxUFKoEgiI4v8G1xzbe9giaCenUWJzgE=
k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM=
k8s.io/component-base v0.20.2 h1:LMmu5I0pLtwjpp5009KLuMGFqSc2S2isGw8t1hpYKLE=
k8s.io/component-base v0.20.2/go.mod h1:pzFtCiwe/ASD0iV7ySMu8SYVJjCapNM9bjvk7ptpKh0=
k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM=
k8s.io/cri-api v0.20.2 h1:GPwBRUF2dQvf7ZaXVUmHbmyYRDlxDuCBSfn/2wpccQk=
k8s.io/cri-api v0.20.2/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20191108084044-e500ee069b5c/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
k8s.io/kubelet v0.20.2 h1:TbOqhr5pN6GsGy798WnwiBAw1JIyZ5H4rugKf1q2jNw=
k8s.io/kubelet v0.20.2/go.mod h1:i441hnZtH2wUiDNqpXVZYaNCqEOBd2sM7x2mV0n7dJs=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20191030222137-2b95a09bc58d/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/structured-merge-diff v1.0.0 h1:JI5bQQfabPDe8cSuK/lFMm2xB3faNkWyXyxT69FVmS8=
sigs.k8s.io/structured-merge-diff v1.0.0/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8=

View File

@ -1,276 +0,0 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package main
import (
"context"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"strings"
"github.com/hashicorp/go-getter"
"github.com/hashicorp/go-multierror"
"github.com/kubernetes-sigs/bootkube/pkg/tlsutil"
"github.com/talos-systems/bootkube-plugin/pkg/asset"
tnet "github.com/talos-systems/net"
"github.com/talos-systems/talos/internal/app/bootkube/images"
"github.com/talos-systems/talos/pkg/machinery/config"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// nolint: gocyclo
func generateAssets(config config.Provider) (err error) {
// Ensure assets directory does not exist / is left over from a failed install
if err = os.RemoveAll(constants.AssetsDirectory); err != nil {
// Ignore if the directory does not exist
if !errors.Is(err, os.ErrNotExist) {
return err
}
}
peerCrt, err := ioutil.ReadFile(constants.KubernetesEtcdPeerCert)
if err != nil {
return err
}
block, _ := pem.Decode(peerCrt)
if block == nil {
return errors.New("failed to decode peer certificate")
}
peer, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return fmt.Errorf("failed to parse client certificate: %w", err)
}
caCrt, err := ioutil.ReadFile(constants.KubernetesEtcdCACert)
if err != nil {
return err
}
block, _ = pem.Decode(caCrt)
if block == nil {
return errors.New("failed to decode CA certificate")
}
ca, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return fmt.Errorf("failed to parse etcd CA certificate: %w", err)
}
peerKey, err := ioutil.ReadFile(constants.KubernetesEtcdPeerKey)
if err != nil {
return err
}
block, _ = pem.Decode(peerKey)
if block == nil {
return errors.New("failed to peer key")
}
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return fmt.Errorf("failed to parse client key: %w", err)
}
etcdServer, err := url.Parse("https://127.0.0.1:2379")
if err != nil {
return err
}
podCIDRs, err := splitCIDRs(config.Cluster().Network().PodCIDR())
if err != nil {
return fmt.Errorf("failed to process Pod CIDRs: %w", err)
}
serviceCIDRs, err := splitCIDRs(config.Cluster().Network().ServiceCIDR())
if err != nil {
return fmt.Errorf("failed to process Service CIDRs: %w", err)
}
urls := []string{config.Cluster().Endpoint().Hostname()}
urls = append(urls, config.Cluster().CertSANs()...)
altNames := altNamesFromURLs(urls)
k8sCA, err := config.Cluster().CA().GetCert()
if err != nil {
return fmt.Errorf("failed to get Kubernetes CA certificate: %w", err)
}
k8sKey, err := config.Cluster().CA().GetRSAKey()
if err != nil {
return fmt.Errorf("failed to parse Kubernetes key: %w", err)
}
apiServiceIPs, err := nthIPInCIDRSet(serviceCIDRs, 1)
if err != nil {
return fmt.Errorf("failed to calculate API service IP: %w", err)
}
dnsServiceIPs, err := nthIPInCIDRSet(serviceCIDRs, 10)
if err != nil {
return fmt.Errorf("failed to calculate DNS service IP: %w", err)
}
images := images.List(config)
conf := asset.Config{
ClusterName: config.Cluster().Name(),
APIServerExtraArgs: config.Cluster().APIServer().ExtraArgs(),
ControllerManagerExtraArgs: config.Cluster().ControllerManager().ExtraArgs(),
ProxyMode: config.Cluster().Proxy().Mode(),
ProxyExtraArgs: config.Cluster().Proxy().ExtraArgs(),
SchedulerExtraArgs: config.Cluster().Scheduler().ExtraArgs(),
CACert: k8sCA,
CAPrivKey: k8sKey,
EtcdCACert: ca,
EtcdClientCert: peer,
EtcdClientKey: key,
EtcdServers: []*url.URL{etcdServer},
EtcdUseTLS: true,
ControlPlaneEndpoint: config.Cluster().Endpoint(),
LocalAPIServerPort: config.Cluster().LocalAPIServerPort(),
APIServiceIPs: apiServiceIPs,
DNSServiceIPs: dnsServiceIPs,
PodCIDRs: podCIDRs,
ServiceCIDRs: serviceCIDRs,
NetworkProvider: config.Cluster().Network().CNI().Name(),
AltNames: altNames,
Images: images,
BootstrapSecretsSubdir: "/assets/tls",
BootstrapTokenID: config.Cluster().Token().ID(),
BootstrapTokenSecret: config.Cluster().Token().Secret(),
AESCBCEncryptionSecret: config.Cluster().AESCBCEncryptionSecret(),
ClusterDomain: config.Cluster().Network().DNSDomain(),
}
if err = asset.Render(constants.AssetsDirectory, conf); err != nil {
return err
}
// If "custom" is the CNI, we expect the user to supply one or more urls that point to CNI yamls
if config.Cluster().Network().CNI().Name() == constants.CustomCNI {
if err = fetchManifests(config.Cluster().Network().CNI().URLs(), map[string]string{}); err != nil {
return err
}
}
if len(config.Cluster().ExtraManifestURLs()) > 0 {
if err = fetchManifests(config.Cluster().ExtraManifestURLs(), config.Cluster().ExtraManifestHeaderMap()); err != nil {
return err
}
}
return nil
}
func altNamesFromURLs(urls []string) *tlsutil.AltNames {
var an tlsutil.AltNames
for _, u := range urls {
ip := net.ParseIP(u)
if ip != nil {
an.IPs = append(an.IPs, ip)
continue
}
an.DNSNames = append(an.DNSNames, u)
}
return &an
}
// fetchManifests will lay down manifests in the provided urls to the bootkube assets directory.
func fetchManifests(urls []string, headers map[string]string) error {
ctx := context.Background()
var result *multierror.Error
for _, url := range urls {
fileName := path.Base(url)
pwd, err := os.Getwd()
if err != nil {
result = multierror.Append(result, err)
continue
}
// Disable netrc since we don't have getent installed, and most likely
// never will.
httpGetter := &getter.HttpGetter{
Netrc: false,
Client: http.DefaultClient,
}
httpGetter.Header = make(http.Header)
for k, v := range headers {
httpGetter.Header.Add(k, v)
}
getter.Getters["http"] = httpGetter
getter.Getters["https"] = httpGetter
// We will squirrel all user-supplied manifests into a `zzz-talos` directory.
// Bootkube applies manifests alphabetically, so pushing these into a subdir with this name
// allows us to ensure they're the last things that get applied and things like PSPs and whatnot are present
client := &getter.Client{
Ctx: ctx,
Src: url,
Dst: filepath.Join(constants.AssetsDirectory, "manifests", "zzz-talos", fileName),
Pwd: pwd,
Mode: getter.ClientModeFile,
Options: []getter.ClientOption{},
}
fmt.Printf("Downloading manifest: %q -> %q", client.Src, client.Dst)
if err = client.Get(); err != nil {
result = multierror.Append(result, fmt.Errorf("error fetching manifest by URL %q: %w", url, err))
continue
}
}
return result.ErrorOrNil()
}
func splitCIDRs(cidrList string) (out []*net.IPNet, err error) {
for _, podCIDR := range strings.Split(cidrList, ",") {
_, cidr, err := net.ParseCIDR(podCIDR)
if err != nil {
return nil, fmt.Errorf("failed to parse %q as a CIDR: %w", podCIDR, err)
}
out = append(out, cidr)
}
return out, nil
}
func nthIPInCIDRSet(cidrList []*net.IPNet, offset int) (out []net.IP, err error) {
for _, cidr := range cidrList {
ip, err := tnet.NthIPInNetwork(cidr, offset)
if err != nil {
return nil, fmt.Errorf("failed to calculate offset %d from CIDR %q: %w", offset, cidr, err)
}
out = append(out, ip)
}
return out, nil
}

View File

@ -1,137 +0,0 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package main
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"github.com/hashicorp/go-multierror"
"github.com/kubernetes-sigs/bootkube/pkg/bootkube"
"github.com/kubernetes-sigs/bootkube/pkg/util"
"github.com/talos-systems/talos/pkg/machinery/config/configloader"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
var (
strict *bool
recover *bool
recoverSource *string
)
func init() {
log.SetFlags(log.Lshortfile | log.Ldate | log.Lmicroseconds | log.Ltime)
strict = flag.Bool("strict", true, "require all manifests to cleanly apply")
recover = flag.Bool("recover", false, "run recovery instead of generate")
recoverSource = flag.String("recover-source", "ETCD", "recovery source to use")
flag.Parse()
}
//nolint: gocyclo
func run() error {
util.InitLogs()
defer util.FlushLogs()
config, err := configloader.NewFromStdin()
if err != nil {
return err
}
if *recover {
if err = recoverAssets(config); err != nil {
return fmt.Errorf("error recovering assets: %w", err)
}
} else {
if err = generateAssets(config); err != nil {
return fmt.Errorf("error generating assets: %w", err)
}
}
if err = os.MkdirAll(constants.ManifestsDirectory, 0o644); err != nil {
return err
}
// cleanup manifests which might have been left from previous bootkube run
cleanupManifests("bootkube-*") //nolint: errcheck
cleanupManifests("kube-system-pod-checkpointer-*") //nolint: errcheck
defaultRequiredPods := []string{
"kube-system/pod-checkpointer",
"kube-system/kube-apiserver",
"kube-system/kube-scheduler",
"kube-system/kube-controller-manager",
}
cfg := bootkube.Config{
AssetDir: constants.AssetsDirectory,
PodManifestPath: constants.ManifestsDirectory,
Strict: *strict,
RequiredPods: defaultRequiredPods,
}
bk, err := bootkube.NewBootkube(cfg)
if err != nil {
return err
}
failed := true
defer func() {
// We want to cleanup the manifests directory only if bootkube fails.
if failed {
if err = os.RemoveAll(constants.ManifestsDirectory); err != nil {
log.Printf("failed to cleanup manifests dir %s", constants.ManifestsDirectory)
}
}
if err = os.RemoveAll(constants.AssetsDirectory); err != nil {
log.Printf("failed to cleanup bootkube assets dir %s", constants.AssetsDirectory)
}
if err = cleanupManifests("bootstrap-*"); err != nil {
log.Printf("%s", err)
}
}()
if err = bk.Run(); err != nil {
return err
}
failed = false
return nil
}
func cleanupManifests(wildcard string) error {
bootstrapWildcard := filepath.Join(constants.ManifestsDirectory, wildcard)
bootstrapFiles, err := filepath.Glob(bootstrapWildcard)
if err != nil {
return fmt.Errorf("error finding bootstrap files in manifests dir %s", constants.ManifestsDirectory)
}
var multiErr *multierror.Error
for _, bootstrapFile := range bootstrapFiles {
if err = os.Remove(bootstrapFile); err != nil {
multiErr = multierror.Append(multiErr, fmt.Errorf("error deleting bootstrap file in manifests dir: %s", err))
}
}
return multiErr.ErrorOrNil()
}
func main() {
if err := run(); err != nil {
log.Fatalf("bootkube failed: %s", err)
}
}

View File

@ -1,111 +0,0 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package main
import (
"bytes"
"context"
"crypto/aes"
"encoding/base64"
"errors"
"fmt"
"os"
"github.com/kubernetes-sigs/bootkube/pkg/recovery"
k8saes "k8s.io/apiserver/pkg/storage/value/encrypt/aes"
"github.com/talos-systems/talos/internal/pkg/etcd"
machineapi "github.com/talos-systems/talos/pkg/machinery/api/machine"
"github.com/talos-systems/talos/pkg/machinery/config"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
//nolint: gocyclo
func recoverAssets(config config.Provider) error {
// Ensure assets directory does not exist / is left over from a failed install
if err := os.RemoveAll(constants.AssetsDirectory); err != nil {
// Ignore if the directory does not exist
if !errors.Is(err, os.ErrNotExist) {
return err
}
}
var (
backend recovery.Backend
err error
)
switch *recoverSource {
case machineapi.RecoverRequest_ETCD.String():
var client *etcd.Client
client, err = etcd.NewClient([]string{"127.0.0.1:2379"})
if err != nil {
return err
}
var transform recovery.TransformerFromStorage
transform, err = aesTransformer(config.Cluster())
if err != nil {
return err
}
backend = recovery.NewEtcdBackendWithTransformer(client.Client, "/registry", transform)
case machineapi.RecoverRequest_APISERVER.String():
backend, err = recovery.NewAPIServerBackend(constants.RecoveryKubeconfig)
if err != nil {
return err
}
}
as, err := recovery.Recover(context.Background(), backend, constants.RecoveryKubeconfig)
if err != nil {
return err
}
if err = os.MkdirAll(constants.AssetsDirectory, 0o600); err != nil {
return err
}
if err = as.WriteFiles(constants.AssetsDirectory); err != nil {
return fmt.Errorf("failed to write recovered assets: %w", err)
}
return nil
}
func aesTransformer(clusterConfig config.ClusterConfig) (recovery.TransformerFromStorage, error) {
key, err := base64.StdEncoding.DecodeString(clusterConfig.AESCBCEncryptionSecret())
if err != nil {
return nil, err
}
cipher, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
transformer := k8saes.NewCBCTransformer(cipher)
return func(value []byte) ([]byte, error) {
const (
aesCBCTransformerPrefixV1 = "k8s:enc:aescbc:v1:"
aesCBCKeyName = "key1:"
aesCBCPrefix = aesCBCTransformerPrefixV1 + aesCBCKeyName
)
if !bytes.HasPrefix(value, []byte(aesCBCPrefix)) {
return value, nil
}
value = value[len(aesCBCPrefix):]
value, _, e := transformer.TransformFromStorage(value, nil)
return value, e
}, nil
}

View File

@ -0,0 +1,62 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package runtime
import (
"context"
"fmt"
"github.com/golang/protobuf/ptypes/empty"
"github.com/talos-systems/os-runtime/pkg/controller"
inspectapi "github.com/talos-systems/talos/pkg/machinery/api/inspect"
)
// InspectServer implements InspectService API.
type InspectServer struct {
server *Server
}
// ControllerRuntimeDependencies implements inspect.InspectService interface.
func (s *InspectServer) ControllerRuntimeDependencies(ctx context.Context, in *empty.Empty) (*inspectapi.ControllerRuntimeDependenciesResponse, error) {
graph, err := s.server.Controller.V1Alpha2().DependencyGraph()
if err != nil {
return nil, fmt.Errorf("error fetching dependency graph: %w", err)
}
edges := make([]*inspectapi.ControllerDependencyEdge, 0, len(graph.Edges))
for i := range graph.Edges {
var edgeType inspectapi.DependencyEdgeType
switch graph.Edges[i].EdgeType {
case controller.EdgeManages:
edgeType = inspectapi.DependencyEdgeType_MANAGES
case controller.EdgeDependsStrong:
edgeType = inspectapi.DependencyEdgeType_STRONG
case controller.EdgeDependsWeak:
edgeType = inspectapi.DependencyEdgeType_WEAK
}
edges = append(edges, &inspectapi.ControllerDependencyEdge{
ControllerName: graph.Edges[i].ControllerName,
EdgeType: edgeType,
ResourceNamespace: graph.Edges[i].ResourceNamespace,
ResourceType: graph.Edges[i].ResourceType,
ResourceId: graph.Edges[i].ResourceID,
})
}
return &inspectapi.ControllerRuntimeDependenciesResponse{
Messages: []*inspectapi.ControllerRuntimeDependency{
{
Edges: edges,
},
},
}, nil
}

View File

@ -57,6 +57,7 @@ import (
"github.com/talos-systems/talos/pkg/chunker/stream"
"github.com/talos-systems/talos/pkg/machinery/api/cluster"
"github.com/talos-systems/talos/pkg/machinery/api/common"
"github.com/talos-systems/talos/pkg/machinery/api/inspect"
"github.com/talos-systems/talos/pkg/machinery/api/machine"
"github.com/talos-systems/talos/pkg/machinery/api/resource"
"github.com/talos-systems/talos/pkg/machinery/config"
@ -98,6 +99,7 @@ func (s *Server) Register(obj *grpc.Server) {
machine.RegisterMachineServiceServer(obj, s)
cluster.RegisterClusterServiceServer(obj, s)
resource.RegisterResourceServiceServer(obj, &ResourceServer{server: s})
inspect.RegisterInspectServiceServer(obj, &InspectServer{server: s})
}
// ApplyConfiguration implements machine.MachineService.
@ -530,25 +532,7 @@ func (s *Server) Recover(ctx context.Context, in *machine.RecoverRequest) (reply
return nil, fmt.Errorf("recover can only be performed on a control plane node")
}
go func() {
if err := s.Controller.Run(runtime.SequenceRecover, in); err != nil {
log.Println("recover failed:", err)
if err != runtime.ErrLocked {
// NB: We stop the gRPC server since a failed sequence triggers a
// reboot.
s.server.GracefulStop()
}
}
}()
reply = &machine.RecoverResponse{
Messages: []*machine.Recover{
{},
},
}
return reply, nil
return nil, fmt.Errorf("recover is not supported since Talos 0.9, use apply-config to update control plane configuration")
}
// ServiceList returns list of the registered services and their status.
@ -1638,7 +1622,7 @@ func (s *Server) EtcdMemberList(ctx context.Context, in *machine.EtcdMemberListR
var client *etcd.Client
if in.QueryLocal {
client, err = etcd.NewClient([]string{"127.0.0.1:2379"})
client, err = etcd.NewLocalClient()
} else {
client, err = etcd.NewClientFromControlPlaneIPs(ctx, s.Controller.Runtime().Config().Cluster().CA(), s.Controller.Runtime().Config().Cluster().Endpoint())
}

View File

@ -0,0 +1,6 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Package config provides controllers which manage config resources.
package config

View File

@ -0,0 +1,237 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package config
import (
"context"
"fmt"
"log"
"strings"
"github.com/AlekSi/pointer"
talosnet "github.com/talos-systems/net"
"github.com/talos-systems/os-runtime/pkg/controller"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/state"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/config"
"github.com/talos-systems/talos/pkg/images"
talosconfig "github.com/talos-systems/talos/pkg/machinery/config"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// K8sControlPlaneController manages config.K8sControlPlane based on configuration.
type K8sControlPlaneController struct {
}
// Name implements controller.Controller interface.
func (ctrl *K8sControlPlaneController) Name() string {
return "config.K8sControlPlaneController"
}
// ManagedResources implements controller.Controller interface.
func (ctrl *K8sControlPlaneController) ManagedResources() (resource.Namespace, resource.Type) {
return config.NamespaceName, config.K8sControlPlaneType
}
// Run implements controller.Controller interface.
//
//nolint: gocyclo
func (ctrl *K8sControlPlaneController) Run(ctx context.Context, r controller.Runtime, logger *log.Logger) error {
if err := r.UpdateDependencies([]controller.Dependency{
{
Namespace: config.NamespaceName,
Type: config.V1Alpha1Type,
ID: pointer.ToString(config.V1Alpha1ID),
Kind: controller.DependencyWeak,
},
{
Namespace: config.NamespaceName,
Type: config.MachineTypeType,
ID: pointer.ToString(config.MachineTypeID),
Kind: controller.DependencyWeak,
},
}); err != nil {
return fmt.Errorf("error setting up dependencies: %w", err)
}
for {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}
cfg, err := r.Get(ctx, resource.NewMetadata(config.NamespaceName, config.V1Alpha1Type, config.V1Alpha1ID, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
if err = ctrl.teardownAll(ctx, r, logger); err != nil {
return fmt.Errorf("error destroying resources: %w", err)
}
continue
}
return fmt.Errorf("error getting config: %w", err)
}
cfgProvider := cfg.(*config.V1Alpha1).Config()
machineTypeRes, err := r.Get(ctx, resource.NewMetadata(config.NamespaceName, config.MachineTypeType, config.MachineTypeID, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
continue
}
return fmt.Errorf("error getting machine type: %w", err)
}
machineType := machineTypeRes.(*config.MachineType).MachineType()
if machineType != machine.TypeControlPlane && machineType != machine.TypeInit {
if err = ctrl.teardownAll(ctx, r, logger); err != nil {
return fmt.Errorf("error destroying resources: %w", err)
}
continue
}
for _, f := range []func(context.Context, controller.Runtime, *log.Logger, talosconfig.Provider) error{
ctrl.manageAPIServerConfig,
ctrl.manageControllerManagerConfig,
ctrl.manageSchedulerConfig,
ctrl.manageManifestsConfig,
ctrl.manageExtraManifestsConfig,
} {
if err = f(ctx, r, logger, cfgProvider); err != nil {
return fmt.Errorf("error updating objects: %w", err)
}
}
}
}
func (ctrl *K8sControlPlaneController) manageAPIServerConfig(ctx context.Context, r controller.Runtime, logger *log.Logger, cfgProvider talosconfig.Provider) error {
return r.Update(ctx, config.NewK8sControlPlaneAPIServer(), func(r resource.Resource) error {
r.(*config.K8sControlPlane).SetAPIServer(config.K8sControlPlaneAPIServerSpec{
Image: cfgProvider.Cluster().APIServer().Image(),
CloudProvider: "", // TODO: add cloud provider to config one day
ControlPlaneEndpoint: cfgProvider.Cluster().Endpoint().String(),
EtcdServers: []string{"https://127.0.0.1:2379"},
LocalPort: cfgProvider.Cluster().LocalAPIServerPort(),
ServiceCIDR: cfgProvider.Cluster().Network().ServiceCIDR(),
ExtraArgs: cfgProvider.Cluster().APIServer().ExtraArgs(),
})
return nil
})
}
func (ctrl *K8sControlPlaneController) manageControllerManagerConfig(ctx context.Context, r controller.Runtime, logger *log.Logger, cfgProvider talosconfig.Provider) error {
return r.Update(ctx, config.NewK8sControlPlaneControllerManager(), func(r resource.Resource) error {
r.(*config.K8sControlPlane).SetControllerManager(config.K8sControlPlaneControllerManagerSpec{
Image: cfgProvider.Cluster().ControllerManager().Image(),
CloudProvider: "", // TODO: add cloud provider to config one day
PodCIDR: cfgProvider.Cluster().Network().PodCIDR(),
ServiceCIDR: cfgProvider.Cluster().Network().ServiceCIDR(),
ExtraArgs: cfgProvider.Cluster().ControllerManager().ExtraArgs(),
})
return nil
})
}
func (ctrl *K8sControlPlaneController) manageSchedulerConfig(ctx context.Context, r controller.Runtime, logger *log.Logger, cfgProvider talosconfig.Provider) error {
return r.Update(ctx, config.NewK8sControlPlaneScheduler(), func(r resource.Resource) error {
r.(*config.K8sControlPlane).SetScheduler(config.K8sControlPlaneSchedulerSpec{
Image: cfgProvider.Cluster().Scheduler().Image(),
ExtraArgs: cfgProvider.Cluster().Scheduler().ExtraArgs(),
})
return nil
})
}
func (ctrl *K8sControlPlaneController) manageManifestsConfig(ctx context.Context, r controller.Runtime, logger *log.Logger, cfgProvider talosconfig.Provider) error {
dnsServiceIPs, err := cfgProvider.Cluster().Network().DNSServiceIPs()
if err != nil {
return fmt.Errorf("error calculating DNS service IPs: %w", err)
}
dnsServiceIP := ""
dnsServiceIPv6 := ""
if len(dnsServiceIPs) == 1 {
dnsServiceIP = dnsServiceIPs[0].String()
} else {
for _, ip := range dnsServiceIPs {
if dnsServiceIP == "" && ip.To4().Equal(ip) {
dnsServiceIP = ip.String()
}
if dnsServiceIPv6 == "" && talosnet.IsNonLocalIPv6(ip) {
dnsServiceIPv6 = ip.String()
}
}
}
return r.Update(ctx, config.NewK8sManifests(), func(r resource.Resource) error {
images := images.List(cfgProvider)
r.(*config.K8sControlPlane).SetManifests(config.K8sManifestsSpec{
Server: cfgProvider.Cluster().Endpoint().String(),
ClusterDomain: cfgProvider.Cluster().Network().DNSDomain(),
PodCIDRs: cfgProvider.Cluster().Network().PodCIDR(),
FirstPodCIDR: strings.Split(cfgProvider.Cluster().Network().PodCIDR(), ",")[0],
ProxyImage: cfgProvider.Cluster().Proxy().Image(),
ProxyMode: cfgProvider.Cluster().Proxy().Mode(),
ProxyExtraArgs: cfgProvider.Cluster().Proxy().ExtraArgs(),
CoreDNSImage: cfgProvider.Cluster().CoreDNS().Image(),
DNSServiceIP: dnsServiceIP,
DNSServiceIPv6: dnsServiceIPv6,
FlannelEnabled: cfgProvider.Cluster().Network().CNI().Name() != constants.CustomCNI,
FlannelImage: images.Flannel,
FlannelCNIImage: images.FlannelCNI,
})
return nil
})
}
func (ctrl *K8sControlPlaneController) manageExtraManifestsConfig(ctx context.Context, r controller.Runtime, logger *log.Logger, cfgProvider talosconfig.Provider) error {
return r.Update(ctx, config.NewK8sExtraManifests(), func(r resource.Resource) error {
spec := config.K8sExtraManifestsSpec{}
if cfgProvider.Cluster().Network().CNI().Name() == constants.CustomCNI {
for _, url := range cfgProvider.Cluster().Network().CNI().URLs() {
spec.ExtraManifests = append(spec.ExtraManifests, config.ExtraManifest{
URL: url,
Priority: "05", // push CNI to the top
})
}
}
for _, url := range cfgProvider.Cluster().ExtraManifestURLs() {
spec.ExtraManifests = append(spec.ExtraManifests, config.ExtraManifest{
URL: url,
Priority: "99", // make sure extra manifests come last, when PSP is already created
ExtraHeaders: cfgProvider.Cluster().ExtraManifestHeaderMap(),
})
}
r.(*config.K8sControlPlane).SetExtraManifests(spec)
return nil
})
}
func (ctrl *K8sControlPlaneController) teardownAll(ctx context.Context, r controller.Runtime, logger *log.Logger) error {
return nil
}

View File

@ -0,0 +1,74 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package config
import (
"context"
"fmt"
"log"
"github.com/AlekSi/pointer"
"github.com/talos-systems/os-runtime/pkg/controller"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/state"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/config"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine"
)
// MachineTypeController manages config.MachineType based on configuration.
type MachineTypeController struct {
}
// Name implements controller.Controller interface.
func (ctrl *MachineTypeController) Name() string {
return "config.MachineTypeController"
}
// ManagedResources implements controller.Controller interface.
func (ctrl *MachineTypeController) ManagedResources() (resource.Namespace, resource.Type) {
return config.NamespaceName, config.MachineTypeType
}
// Run implements controller.Controller interface.
func (ctrl *MachineTypeController) Run(ctx context.Context, r controller.Runtime, logger *log.Logger) error {
if err := r.UpdateDependencies([]controller.Dependency{
{
Namespace: config.NamespaceName,
Type: config.V1Alpha1Type,
ID: pointer.ToString(config.V1Alpha1ID),
Kind: controller.DependencyWeak,
},
}); err != nil {
return fmt.Errorf("error setting up dependencies: %w", err)
}
for {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}
var machineType machine.Type
cfg, err := r.Get(ctx, resource.NewMetadata(config.NamespaceName, config.V1Alpha1Type, config.V1Alpha1ID, resource.VersionUndefined))
if err != nil {
if !state.IsNotFoundError(err) {
return fmt.Errorf("error getting config: %w", err)
}
} else {
machineType = cfg.(*config.V1Alpha1).Config().Machine().Type()
}
if err = r.Update(ctx, config.NewMachineType(), func(r resource.Resource) error {
r.(*config.MachineType).SetMachineType(machineType)
return nil
}); err != nil {
return fmt.Errorf("error updating objects: %w", err)
}
}
}

View File

@ -0,0 +1,410 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package k8s
import (
"context"
"fmt"
"log"
"path/filepath"
"strings"
"github.com/AlekSi/pointer"
"github.com/talos-systems/os-runtime/pkg/controller"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/state"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/config"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/k8s"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// ControlPlaneStaticPodController manages k8s.StaticPod based on control plane configuration.
type ControlPlaneStaticPodController struct{}
// Name implements controller.Controller interface.
func (ctrl *ControlPlaneStaticPodController) Name() string {
return "k8s.ControlPlaneStaticPodController"
}
// ManagedResources implements controller.Controller interface.
func (ctrl *ControlPlaneStaticPodController) ManagedResources() (resource.Namespace, resource.Type) {
return k8s.ControlPlaneNamespaceName, k8s.StaticPodType
}
// Run implements controller.Controller interface.
//
//nolint: gocyclo
func (ctrl *ControlPlaneStaticPodController) Run(ctx context.Context, r controller.Runtime, logger *log.Logger) error {
if err := r.UpdateDependencies([]controller.Dependency{
{
Namespace: config.NamespaceName,
Type: config.K8sControlPlaneType,
Kind: controller.DependencyWeak,
},
{
Namespace: k8s.ControlPlaneNamespaceName,
Type: k8s.SecretsStatusType,
ID: pointer.ToString(k8s.StaticPodSecretsStaticPodID),
Kind: controller.DependencyWeak,
},
}); err != nil {
return fmt.Errorf("error setting up dependencies: %w", err)
}
for {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}
secretsStatusResource, err := r.Get(ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.SecretsStatusType, k8s.StaticPodSecretsStaticPodID, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
if err = ctrl.teardownAll(ctx, r); err != nil {
return fmt.Errorf("error tearing down: %w", err)
}
continue
}
return err
}
secretsVersion := secretsStatusResource.(*k8s.SecretsStatus).Status().Version
for _, pod := range []struct {
f func(context.Context, controller.Runtime, *log.Logger, *config.K8sControlPlane, string) error
id resource.ID
}{
{
f: ctrl.manageAPIServer,
id: config.K8sControlPlaneAPIServerID,
},
{
f: ctrl.manageControllerManager,
id: config.K8sControlPlaneControllerManagerID,
},
{
f: ctrl.manageScheduler,
id: config.K8sControlPlaneSchedulerID,
},
} {
res, err := r.Get(ctx, resource.NewMetadata(config.NamespaceName, config.K8sControlPlaneType, pod.id, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
continue
}
return fmt.Errorf("error getting control plane config: %w", err)
}
if err = pod.f(ctx, r, logger, res.(*config.K8sControlPlane), secretsVersion); err != nil {
return fmt.Errorf("error updating static pod for %q: %w", pod.id, err)
}
}
}
}
func (ctrl *ControlPlaneStaticPodController) teardownAll(ctx context.Context, r controller.Runtime) error {
list, err := r.List(ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.StaticPodType, "", resource.VersionUndefined))
if err != nil {
return err
}
// TODO: change this to proper teardown sequence
for _, res := range list.Items {
if err = r.Destroy(ctx, res.Metadata()); err != nil {
return err
}
}
return nil
}
func (ctrl *ControlPlaneStaticPodController) manageAPIServer(ctx context.Context, r controller.Runtime, logger *log.Logger, configResource *config.K8sControlPlane, secretsVersion string) error {
cfg := configResource.APIServer()
args := []string{
"/go-runner",
"/usr/local/bin/kube-apiserver",
"--enable-admission-plugins=PodSecurityPolicy,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeClaimResize,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,Priority,NodeRestriction", //nolint: lll
"--advertise-address=$(POD_IP)",
"--allow-privileged=true",
fmt.Sprintf("--api-audiences=%s", cfg.ControlPlaneEndpoint),
"--authorization-mode=Node,RBAC",
"--bind-address=0.0.0.0",
fmt.Sprintf("--client-ca-file=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "ca.crt")),
fmt.Sprintf("--requestheader-client-ca-file=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "aggregator-ca.crt")),
"--requestheader-allowed-names=front-proxy-client",
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
"--requestheader-group-headers=X-Remote-Group",
"--requestheader-username-headers=X-Remote-User",
fmt.Sprintf("--proxy-client-cert-file=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "front-proxy-client.crt")),
fmt.Sprintf("--proxy-client-key-file=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "front-proxy-client.key")),
fmt.Sprintf("--cloud-provider=%s", cfg.CloudProvider),
"--enable-bootstrap-token-auth=true",
"--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256", //nolint: lll
fmt.Sprintf("--encryption-provider-config=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "encryptionconfig.yaml")),
fmt.Sprintf("--audit-policy-file=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "auditpolicy.yaml")),
"--audit-log-path=-",
"--audit-log-maxage=30",
"--audit-log-maxbackup=3",
"--audit-log-maxsize=50",
"--profiling=false",
fmt.Sprintf("--etcd-cafile=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "etcd-client-ca.crt")),
fmt.Sprintf("--etcd-certfile=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "etcd-client.crt")),
fmt.Sprintf("--etcd-keyfile=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "etcd-client.key")),
fmt.Sprintf("--etcd-servers=%s", strings.Join(cfg.EtcdServers, ",")),
"--insecure-port=0",
fmt.Sprintf("--kubelet-client-certificate=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "apiserver-kubelet-client.crt")),
fmt.Sprintf("--kubelet-client-key=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "apiserver-kubelet-client.key")),
fmt.Sprintf("--secure-port=%d", cfg.LocalPort),
fmt.Sprintf("--service-account-issuer=%s", cfg.ControlPlaneEndpoint),
fmt.Sprintf("--service-account-key-file=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "service-account.pub")),
fmt.Sprintf("--service-account-signing-key-file=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "service-account.key")),
fmt.Sprintf("--service-cluster-ip-range=%s", cfg.ServiceCIDR),
fmt.Sprintf("--tls-cert-file=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "apiserver.crt")),
fmt.Sprintf("--tls-private-key-file=%s", filepath.Join(constants.KubernetesAPIServerSecretsDir, "apiserver.key")),
"--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname",
}
for k, v := range cfg.ExtraArgs {
args = append(args, fmt.Sprintf("--%s=%s", k, v))
}
return r.Update(ctx, k8s.NewStaticPod(k8s.ControlPlaneNamespaceName, "kube-apiserver", nil), func(r resource.Resource) error {
r.(*k8s.StaticPod).SetPod(&v1.Pod{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: "kube-apiserver",
Namespace: "kube-system",
Labels: map[string]string{
"tier": "control-plane",
"k8s-app": "kube-apiserver",
"secrets-version": secretsVersion,
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "kube-apiserver",
Image: cfg.Image,
Command: args,
Env: []v1.EnvVar{
{
Name: "POD_IP",
ValueFrom: &v1.EnvVarSource{
FieldRef: &v1.ObjectFieldSelector{
FieldPath: "status.podIP",
},
},
},
},
VolumeMounts: []v1.VolumeMount{
{
Name: "secrets",
MountPath: constants.KubernetesAPIServerSecretsDir,
ReadOnly: true,
},
},
},
},
HostNetwork: true,
SecurityContext: &v1.PodSecurityContext{
RunAsNonRoot: pointer.ToBool(true),
RunAsUser: pointer.ToInt64(constants.KubernetesRunUser),
},
Volumes: []v1.Volume{
{
Name: "secrets",
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{
Path: constants.KubernetesAPIServerSecretsDir,
},
},
},
},
},
})
return nil
})
}
func (ctrl *ControlPlaneStaticPodController) manageControllerManager(ctx context.Context, r controller.Runtime,
logger *log.Logger, configResource *config.K8sControlPlane, secretsVersion string) error {
cfg := configResource.ControllerManager()
args := []string{
"/go-runner",
"/usr/local/bin/kube-controller-manager",
"--allocate-node-cidrs=true",
fmt.Sprintf("--cloud-provider=%s", cfg.CloudProvider),
fmt.Sprintf("--cluster-cidr=%s", cfg.PodCIDR),
fmt.Sprintf("--service-cluster-ip-range=%s", cfg.ServiceCIDR),
fmt.Sprintf("--cluster-signing-cert-file=%s", filepath.Join(constants.KubernetesControllerManagerSecretsDir, "ca.crt")),
fmt.Sprintf("--cluster-signing-key-file=%s", filepath.Join(constants.KubernetesControllerManagerSecretsDir, "ca.key")),
"--configure-cloud-routes=false",
fmt.Sprintf("--kubeconfig=%s", filepath.Join(constants.KubernetesControllerManagerSecretsDir, "kubeconfig")),
"--leader-elect=true",
fmt.Sprintf("--root-ca-file=%s", filepath.Join(constants.KubernetesControllerManagerSecretsDir, "ca.crt")),
fmt.Sprintf("--service-account-private-key-file=%s", filepath.Join(constants.KubernetesControllerManagerSecretsDir, "service-account.key")),
"--profiling=false",
}
for k, v := range cfg.ExtraArgs {
args = append(args, fmt.Sprintf("--%s=%s", k, v))
}
//nolint: dupl
return r.Update(ctx, k8s.NewStaticPod(k8s.ControlPlaneNamespaceName, "kube-controller-manager", nil), func(r resource.Resource) error {
r.(*k8s.StaticPod).SetPod(&v1.Pod{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: "kube-controller-manager",
Namespace: "kube-system",
Labels: map[string]string{
"tier": "control-plane",
"k8s-app": "kube-controller-manager",
"secrets-version": secretsVersion,
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "kube-controller-manager",
Image: cfg.Image,
Command: args,
VolumeMounts: []v1.VolumeMount{
{
Name: "secrets",
MountPath: constants.KubernetesControllerManagerSecretsDir,
ReadOnly: true,
},
},
LivenessProbe: &v1.Probe{
Handler: v1.Handler{
HTTPGet: &v1.HTTPGetAction{
Path: "/healthz",
Port: intstr.FromInt(10252),
},
},
InitialDelaySeconds: 15,
TimeoutSeconds: 15,
},
},
},
HostNetwork: true,
SecurityContext: &v1.PodSecurityContext{
RunAsNonRoot: pointer.ToBool(true),
RunAsUser: pointer.ToInt64(constants.KubernetesRunUser),
},
Volumes: []v1.Volume{
{
Name: "secrets",
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{
Path: constants.KubernetesControllerManagerSecretsDir,
},
},
},
},
},
})
return nil
})
}
func (ctrl *ControlPlaneStaticPodController) manageScheduler(ctx context.Context, r controller.Runtime,
logger *log.Logger, configResource *config.K8sControlPlane, secretsVersion string) error {
cfg := configResource.Scheduler()
args := []string{
"/go-runner",
"/usr/local/bin/kube-scheduler",
fmt.Sprintf("--kubeconfig=%s", filepath.Join(constants.KubernetesSchedulerSecretsDir, "kubeconfig")),
"--leader-elect=true",
"--profiling=false",
}
for k, v := range cfg.ExtraArgs {
args = append(args, fmt.Sprintf("--%s=%s", k, v))
}
//nolint: dupl
return r.Update(ctx, k8s.NewStaticPod(k8s.ControlPlaneNamespaceName, "kube-scheduler", nil), func(r resource.Resource) error {
r.(*k8s.StaticPod).SetPod(&v1.Pod{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: "kube-scheduler",
Namespace: "kube-system",
Labels: map[string]string{
"tier": "control-plane",
"k8s-app": "kube-scheduler",
"secrets-version": secretsVersion,
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "kube-scheduler",
Image: cfg.Image,
Command: args,
VolumeMounts: []v1.VolumeMount{
{
Name: "secrets",
MountPath: constants.KubernetesSchedulerSecretsDir,
ReadOnly: true,
},
},
LivenessProbe: &v1.Probe{
Handler: v1.Handler{
HTTPGet: &v1.HTTPGetAction{
Path: "/healthz",
Port: intstr.FromInt(10251),
},
},
InitialDelaySeconds: 15,
TimeoutSeconds: 15,
},
},
},
HostNetwork: true,
SecurityContext: &v1.PodSecurityContext{
RunAsNonRoot: pointer.ToBool(true),
RunAsUser: pointer.ToInt64(constants.KubernetesRunUser),
},
Volumes: []v1.Volume{
{
Name: "secrets",
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{
Path: constants.KubernetesSchedulerSecretsDir,
},
},
},
},
},
})
return nil
})
}

View File

@ -0,0 +1,215 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package k8s
import (
"context"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"github.com/AlekSi/pointer"
"github.com/hashicorp/go-getter"
"github.com/hashicorp/go-multierror"
"github.com/talos-systems/os-runtime/pkg/controller"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/state"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/config"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/k8s"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/v1alpha1"
)
// ExtraManifestController renders manifests based on templates and config/secrets.
type ExtraManifestController struct{}
// Name implements controller.Controller interface.
func (ctrl *ExtraManifestController) Name() string {
return "k8s.ExtraManifestController"
}
// ManagedResources implements controller.Controller interface.
func (ctrl *ExtraManifestController) ManagedResources() (resource.Namespace, resource.Type) {
return k8s.ExtraNamespaceName, k8s.ManifestType
}
// Run implements controller.Controller interface.
//
//nolint: gocyclo
func (ctrl *ExtraManifestController) Run(ctx context.Context, r controller.Runtime, logger *log.Logger) error {
if err := r.UpdateDependencies([]controller.Dependency{
{
Namespace: config.NamespaceName,
Type: config.K8sControlPlaneType,
ID: pointer.ToString(config.K8sExtraManifestsID),
Kind: controller.DependencyWeak,
},
{
Namespace: v1alpha1.NamespaceName,
Type: v1alpha1.ServiceType,
ID: pointer.ToString("networkd"),
Kind: controller.DependencyWeak,
},
}); err != nil {
return fmt.Errorf("error setting up dependencies: %w", err)
}
for {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}
// wait for networkd to be healthy as networking is required to download extra manifests
networkdResource, err := r.Get(ctx, resource.NewMetadata(v1alpha1.NamespaceName, v1alpha1.ServiceType, "networkd", resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
continue
}
return err
}
if !networkdResource.(*v1alpha1.Service).Healthy() {
continue
}
configResource, err := r.Get(ctx, resource.NewMetadata(config.NamespaceName, config.K8sControlPlaneType, config.K8sExtraManifestsID, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
if err = ctrl.teardownAll(ctx, r); err != nil {
return fmt.Errorf("error tearing down: %w", err)
}
continue
}
return err
}
config := configResource.(*config.K8sControlPlane).ExtraManifests()
var multiErr *multierror.Error
presentManifests := map[resource.ID]struct{}{}
for _, manifest := range config.ExtraManifests {
var id resource.ID
id, err = ctrl.download(ctx, r, logger, manifest)
if err != nil {
multiErr = multierror.Append(multiErr, err)
}
presentManifests[id] = struct{}{}
}
if multiErr.ErrorOrNil() != nil {
return multiErr.ErrorOrNil()
}
allManifests, err := r.List(ctx, resource.NewMetadata(k8s.ExtraNamespaceName, k8s.ManifestType, "", resource.VersionUndefined))
if err != nil {
return fmt.Errorf("error listing extra manifests: %w", err)
}
for _, manifest := range allManifests.Items {
if _, exists := presentManifests[manifest.Metadata().ID()]; !exists {
if err = r.Destroy(ctx, manifest.Metadata()); err != nil {
return fmt.Errorf("error cleaning up extra manifest: %w", err)
}
}
}
}
}
func (ctrl *ExtraManifestController) download(ctx context.Context, r controller.Runtime, logger *log.Logger, manifest config.ExtraManifest) (id resource.ID, err error) {
id = fmt.Sprintf("%s-%s", manifest.Priority, manifest.URL)
var tmpDir string
tmpDir, err = ioutil.TempDir("", "talos")
if err != nil {
return
}
defer os.RemoveAll(tmpDir) //nolint: errcheck
fileName := filepath.Base(manifest.URL)
// I wish we never used go-getter package, as it doesn't allow downloading into memory.
// But there's not much we can do about it right now, as it supports lots of magic
// users might rely upon now.
// Disable netrc since we don't have getent installed, and most likely
// never will.
httpGetter := &getter.HttpGetter{
Netrc: false,
Client: http.DefaultClient,
}
httpGetter.Header = make(http.Header)
for k, v := range manifest.ExtraHeaders {
httpGetter.Header.Add(k, v)
}
getter.Getters["http"] = httpGetter
getter.Getters["https"] = httpGetter
client := &getter.Client{
Ctx: ctx,
Src: manifest.URL,
Dst: filepath.Join(tmpDir, fileName),
Pwd: tmpDir,
Mode: getter.ClientModeFile,
Options: []getter.ClientOption{},
}
if err = client.Get(); err != nil {
err = fmt.Errorf("error downloading %q: %w", manifest.URL, err)
return
}
logger.Printf("downloaded manifest %q", manifest.URL)
var contents []byte
contents, err = ioutil.ReadFile(client.Dst)
if err != nil {
return
}
if err = r.Update(ctx, k8s.NewManifest(k8s.ExtraNamespaceName, id),
func(r resource.Resource) error {
return r.(*k8s.Manifest).SetYAML(contents)
}); err != nil {
err = fmt.Errorf("error updating manifests: %w", err)
return
}
return id, nil
}
func (ctrl *ExtraManifestController) teardownAll(ctx context.Context, r controller.Runtime) error {
manifests, err := r.List(ctx, resource.NewMetadata(k8s.ExtraNamespaceName, k8s.ManifestType, "", resource.VersionUndefined))
if err != nil {
return fmt.Errorf("error listing extra manifests: %w", err)
}
for _, manifest := range manifests.Items {
if err = r.Destroy(ctx, manifest.Metadata()); err != nil {
return fmt.Errorf("error destroying extra manifest: %w", err)
}
}
return nil
}

View File

@ -0,0 +1,16 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Package k8s provides controllers which manage Kubernetes resources.
package k8s
import (
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)
func init() {
// ugly hack, but it doesn't look like there's better API
// cut out error handler which logs error to standard logger
utilruntime.ErrorHandlers = utilruntime.ErrorHandlers[len(utilruntime.ErrorHandlers)-1:]
}

View File

@ -0,0 +1,287 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package k8s
import (
"bytes"
"context"
"crypto/tls"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"time"
"github.com/AlekSi/pointer"
"github.com/talos-systems/os-runtime/pkg/controller"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/state"
"gopkg.in/yaml.v3"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/k8s"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/secrets"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/v1alpha1"
"github.com/talos-systems/talos/pkg/kubernetes/kubelet"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// KubeletStaticPodController renders static pod definitions and manages k8s.StaticPodStatus.
type KubeletStaticPodController struct{}
// Name implements controller.Controller interface.
func (ctrl *KubeletStaticPodController) Name() string {
return "k8s.KubeletStaticPodController"
}
// ManagedResources implements controller.Controller interface.
func (ctrl *KubeletStaticPodController) ManagedResources() (resource.Namespace, resource.Type) {
return k8s.ControlPlaneNamespaceName, k8s.StaticPodStatusType
}
// Run implements controller.Controller interface.
//
//nolint: gocyclo
func (ctrl *KubeletStaticPodController) Run(ctx context.Context, r controller.Runtime, logger *log.Logger) error {
if err := r.UpdateDependencies([]controller.Dependency{
{
Namespace: k8s.ControlPlaneNamespaceName,
Type: k8s.StaticPodType,
Kind: controller.DependencyStrong,
},
{
Namespace: v1alpha1.NamespaceName,
Type: v1alpha1.ServiceType,
ID: pointer.ToString("kubelet"),
Kind: controller.DependencyWeak,
},
{
Namespace: secrets.NamespaceName,
Type: secrets.KubernetesType,
ID: pointer.ToString(secrets.KubernetesID),
Kind: controller.DependencyWeak,
},
{
Namespace: v1alpha1.NamespaceName,
Type: v1alpha1.BootstrapStatusType,
ID: pointer.ToString(v1alpha1.BootstrapStatusID),
Kind: controller.DependencyWeak,
},
}); err != nil {
return fmt.Errorf("error setting up dependencies: %w", err)
}
var kubeletClient *kubelet.Client
refreshTicker := time.NewTicker(15 * time.Second) // refresh kubelet pods status every 15 seconds
defer refreshTicker.Stop()
for {
select {
case <-ctx.Done():
return nil
case <-refreshTicker.C:
if kubeletClient != nil {
if err := ctrl.refreshPodStatus(ctx, r, kubeletClient); err != nil {
return fmt.Errorf("error refreshing pod status: %w", err)
}
}
continue
case <-r.EventCh():
}
kubeletResource, err := r.Get(ctx, resource.NewMetadata(v1alpha1.NamespaceName, v1alpha1.ServiceType, "kubelet", resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
kubeletClient = nil
if err = ctrl.teardownStatuses(ctx, r); err != nil {
return fmt.Errorf("error tearing down: %w", err)
}
continue
}
return err
}
if !kubeletResource.(*v1alpha1.Service).Running() {
kubeletClient = nil
if err = ctrl.teardownStatuses(ctx, r); err != nil {
return fmt.Errorf("error tearing down: %w", err)
}
continue
}
secretsResources, err := r.Get(ctx, resource.NewMetadata(secrets.NamespaceName, secrets.KubernetesType, secrets.KubernetesID, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
continue
}
return err
}
secrets := secretsResources.(*secrets.Kubernetes).Secrets()
bootstrapStatus, err := r.Get(ctx, v1alpha1.NewBootstrapStatus().Metadata())
if err != nil {
if state.IsNotFoundError(err) {
continue
}
return err
}
if bootstrapStatus.(*v1alpha1.BootstrapStatus).Status().SelfHostedControlPlane {
logger.Print("skipped as running self-hosted control plane")
continue
}
kubeletClientCert, err := tls.X509KeyPair(secrets.APIServerKubeletClient.Crt, secrets.APIServerKubeletClient.Key)
if err != nil {
return fmt.Errorf("error loading apiserver kubelet client cert: %w", err)
}
kubeletClient, err = kubelet.NewClient(kubeletClientCert)
if err != nil {
return fmt.Errorf("error building kubelet client: %w", err)
}
staticPods, err := r.List(ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.StaticPodType, "", resource.VersionUndefined))
if err != nil {
return fmt.Errorf("error listing static pods: %w", err)
}
for _, staticPod := range staticPods.Items {
switch staticPod.Metadata().Phase() {
case resource.PhaseRunning:
if err = ctrl.runPod(ctx, r, logger, staticPod.(*k8s.StaticPod)); err != nil {
return fmt.Errorf("error running pod: %w", err)
}
case resource.PhaseTearingDown:
if err = ctrl.teardownPod(logger, staticPod.(*k8s.StaticPod)); err != nil {
return fmt.Errorf("error tearing down pod: %w", err)
}
}
}
}
}
func (ctrl *KubeletStaticPodController) runPod(ctx context.Context, r controller.Runtime, logger *log.Logger, staticPod *k8s.StaticPod) error {
staticPodStatus := k8s.NewStaticPodStatus(staticPod.Metadata().Namespace(), staticPod.Metadata().ID())
if err := r.AddFinalizer(ctx, staticPod.Metadata(), staticPodStatus.String()); err != nil {
return err
}
renderedPod, err := yaml.Marshal(staticPod.Spec())
if err != nil {
return nil
}
podPath := filepath.Join(constants.ManifestsDirectory, fmt.Sprintf("%s.yaml", staticPod.Metadata().ID()))
existingPod, err := ioutil.ReadFile(podPath)
if err != nil {
if !os.IsNotExist(err) {
return err
}
}
if bytes.Equal(renderedPod, existingPod) {
return nil
}
logger.Printf("writing static pod %q", podPath)
return ioutil.WriteFile(podPath, renderedPod, 0o600)
}
func (ctrl *KubeletStaticPodController) teardownPod(logger *log.Logger, staticPod *k8s.StaticPod) error {
podPath := filepath.Join(constants.ManifestsDirectory, fmt.Sprintf("%s.yaml", staticPod.Metadata().ID()))
_, err := os.Stat(podPath)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return fmt.Errorf("error checking static pod status: %w", err)
}
logger.Printf("removing static pod %q", podPath)
if err = os.Remove(podPath); err != nil {
return fmt.Errorf("error removing static pod %q: %w", podPath, err)
}
return nil
}
func (ctrl *KubeletStaticPodController) teardownStatuses(ctx context.Context, r controller.Runtime) error {
statuses, err := r.List(ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.StaticPodStatusType, "", resource.VersionUndefined))
if err != nil {
return fmt.Errorf("error listing pod statuses: %w", err)
}
for _, status := range statuses.Items {
// TODO: proper teardown sequence?
if err = r.Destroy(ctx, status.Metadata()); err != nil {
return fmt.Errorf("error destroying stale pod status: %w", err)
}
}
return nil
}
func (ctrl *KubeletStaticPodController) refreshPodStatus(ctx context.Context, r controller.Runtime, kubeletClient *kubelet.Client) error {
podList, err := kubeletClient.Pods(ctx)
if err != nil {
return fmt.Errorf("error fetching pod status: %w", err)
}
podsSeen := map[string]struct{}{}
for _, pod := range podList.Items {
if pod.OwnerReferences != nil {
continue
}
pod := pod
statusID := fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)
podsSeen[statusID] = struct{}{}
if err = r.Update(ctx, k8s.NewStaticPodStatus(k8s.ControlPlaneNamespaceName, statusID), func(r resource.Resource) error {
r.(*k8s.StaticPodStatus).SetStatus(&pod.Status)
return nil
}); err != nil {
return fmt.Errorf("error updating pod status: %w", err)
}
}
statuses, err := r.List(ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.StaticPodStatusType, "", resource.VersionUndefined))
if err != nil {
return fmt.Errorf("error listing pod statuses: %w", err)
}
for _, status := range statuses.Items {
if _, exists := podsSeen[status.Metadata().ID()]; !exists {
// TODO: proper teardown sequence?
if err = r.Destroy(ctx, status.Metadata()); err != nil {
return fmt.Errorf("error destroying stale pod status: %w", err)
}
}
}
return nil
}

View File

@ -0,0 +1,218 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package k8s
import (
"bytes"
"context"
"fmt"
"html/template"
"log"
"github.com/AlekSi/pointer"
"github.com/talos-systems/os-runtime/pkg/controller"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/state"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/config"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/k8s"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/secrets"
)
// ManifestController renders manifests based on templates and config/secrets.
type ManifestController struct{}
// Name implements controller.Controller interface.
func (ctrl *ManifestController) Name() string {
return "k8s.ManifestController"
}
// ManagedResources implements controller.Controller interface.
func (ctrl *ManifestController) ManagedResources() (resource.Namespace, resource.Type) {
return k8s.ControlPlaneNamespaceName, k8s.ManifestType
}
// Run implements controller.Controller interface.
//
//nolint: gocyclo
func (ctrl *ManifestController) Run(ctx context.Context, r controller.Runtime, logger *log.Logger) error {
if err := r.UpdateDependencies([]controller.Dependency{
{
Namespace: config.NamespaceName,
Type: config.K8sControlPlaneType,
ID: pointer.ToString(config.K8sManifestsID),
Kind: controller.DependencyWeak,
},
{
Namespace: secrets.NamespaceName,
Type: secrets.KubernetesType,
ID: pointer.ToString(secrets.KubernetesID),
Kind: controller.DependencyWeak,
},
}); err != nil {
return fmt.Errorf("error setting up dependencies: %w", err)
}
for {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}
configResource, err := r.Get(ctx, resource.NewMetadata(config.NamespaceName, config.K8sControlPlaneType, config.K8sManifestsID, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
if err = ctrl.teardownAll(ctx, r); err != nil {
return fmt.Errorf("error tearing down: %w", err)
}
continue
}
return err
}
config := configResource.(*config.K8sControlPlane).Manifests()
secretsResources, err := r.Get(ctx, resource.NewMetadata(secrets.NamespaceName, secrets.KubernetesType, secrets.KubernetesID, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
if err = ctrl.teardownAll(ctx, r); err != nil {
return fmt.Errorf("error tearing down: %w", err)
}
continue
}
return err
}
secrets := secretsResources.(*secrets.Kubernetes).Secrets()
renderedManifests, err := ctrl.render(config, *secrets)
if err != nil {
return err
}
for _, renderedManifest := range renderedManifests {
renderedManifest := renderedManifest
if err = r.Update(ctx, k8s.NewManifest(k8s.ControlPlaneNamespaceName, renderedManifest.name),
func(r resource.Resource) error {
return r.(*k8s.Manifest).SetYAML(renderedManifest.data)
}); err != nil {
return fmt.Errorf("error updating manifests: %w", err)
}
}
// remove any manifests which weren't rendered
manifests, err := r.List(ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.ManifestType, "", resource.VersionUndefined))
if err != nil {
return fmt.Errorf("error listing manifests: %w", err)
}
manifestsToDelete := map[string]struct{}{}
for _, manifest := range manifests.Items {
manifestsToDelete[manifest.Metadata().ID()] = struct{}{}
}
for _, renderedManifest := range renderedManifests {
delete(manifestsToDelete, renderedManifest.name)
}
for id := range manifestsToDelete {
if err = r.Destroy(ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.ManifestType, id, resource.VersionUndefined)); err != nil {
return fmt.Errorf("error cleaning up manifests: %w", err)
}
}
}
}
type renderedManifest struct {
name string
data []byte
}
func (ctrl *ManifestController) render(cfg config.K8sManifestsSpec, scrt secrets.KubernetesSpec) ([]renderedManifest, error) {
templateConfig := struct {
config.K8sManifestsSpec
Secrets secrets.KubernetesSpec
}{
K8sManifestsSpec: cfg,
Secrets: scrt,
}
type manifestDesc struct {
name string
template []byte
}
defaultManifests := []manifestDesc{
{"00-kubelet-bootstrapping-token", kubeletBootstrappingToken},
{"01-csr-node-bootstrap", csrNodeBootstrapTemplate},
{"01-csr-approver-role-binding", csrApproverRoleBindingTemplate},
{"01-csr-renewal-role-binding", csrRenewalRoleBindingTemplate},
{"02-kube-system-sa-role-binding", kubeSystemSARoleBindingTemplate},
{"03-default-pod-security-policy", podSecurityPolicy},
{"10-kube-proxy", kubeProxyTemplate},
{"11-kube-config-in-cluster", kubeConfigInClusterTemplate},
{"11-core-dns", coreDNSTemplate},
{"11-core-dns-svc", coreDNSSvcTemplate},
}
if cfg.DNSServiceIPv6 != "" {
defaultManifests = append(defaultManifests,
[]manifestDesc{
{"11-core-dns-v6-svc", coreDNSv6SvcTemplate},
}...,
)
}
if cfg.FlannelEnabled {
defaultManifests = append(defaultManifests,
[]manifestDesc{
{"05-flannel", flannelTemplate},
}...,
)
}
manifests := make([]renderedManifest, len(defaultManifests))
for i := range defaultManifests {
tmpl, err := template.New(defaultManifests[i].name).Parse(string(defaultManifests[i].template))
if err != nil {
return nil, fmt.Errorf("error parsing manifest template %q: %w", defaultManifests[i].name, err)
}
var buf bytes.Buffer
if err = tmpl.Execute(&buf, &templateConfig); err != nil {
return nil, fmt.Errorf("error executing template %q: %w", defaultManifests[i].name, err)
}
manifests[i].name = defaultManifests[i].name
manifests[i].data = buf.Bytes()
}
return manifests, nil
}
func (ctrl *ManifestController) teardownAll(ctx context.Context, r controller.Runtime) error {
manifests, err := r.List(ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.ManifestType, "", resource.VersionUndefined))
if err != nil {
return fmt.Errorf("error listing manifests: %w", err)
}
for _, manifest := range manifests.Items {
if err = r.Destroy(ctx, manifest.Metadata()); err != nil {
return fmt.Errorf("error destroying manifest: %w", err)
}
}
return nil
}

View File

@ -0,0 +1,305 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package k8s
import (
"context"
"fmt"
"log"
"sort"
"github.com/AlekSi/pointer"
"github.com/talos-systems/os-runtime/pkg/controller"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/state"
"go.etcd.io/etcd/clientv3/concurrency"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/discovery"
memory "k8s.io/client-go/discovery/cached"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest"
"k8s.io/client-go/restmapper"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/k8s"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/secrets"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/v1alpha1"
"github.com/talos-systems/talos/internal/pkg/etcd"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// ManifestApplyController applies manifests via control plane endpoint.
type ManifestApplyController struct{}
// Name implements controller.Controller interface.
func (ctrl *ManifestApplyController) Name() string {
return "k8s.ManifestApplyController"
}
// ManagedResources implements controller.Controller interface.
func (ctrl *ManifestApplyController) ManagedResources() (resource.Namespace, resource.Type) {
return k8s.ControlPlaneNamespaceName, k8s.ManifestStatusType
}
// Run implements controller.Controller interface.
//
//nolint: gocyclo
func (ctrl *ManifestApplyController) Run(ctx context.Context, r controller.Runtime, logger *log.Logger) error {
if err := r.UpdateDependencies([]controller.Dependency{
{
Namespace: secrets.NamespaceName,
Type: secrets.KubernetesType,
ID: pointer.ToString(secrets.KubernetesID),
Kind: controller.DependencyWeak,
},
{
Namespace: k8s.ControlPlaneNamespaceName,
Type: k8s.ManifestType,
Kind: controller.DependencyWeak,
},
{
Namespace: k8s.ExtraNamespaceName,
Type: k8s.ManifestType,
Kind: controller.DependencyWeak,
},
{
Namespace: v1alpha1.NamespaceName,
Type: v1alpha1.BootstrapStatusType,
ID: pointer.ToString(v1alpha1.BootstrapStatusID),
Kind: controller.DependencyWeak,
},
}); err != nil {
return fmt.Errorf("error setting up dependencies: %w", err)
}
for {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}
secretsResources, err := r.Get(ctx, resource.NewMetadata(secrets.NamespaceName, secrets.KubernetesType, secrets.KubernetesID, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
continue
}
return err
}
secrets := secretsResources.(*secrets.Kubernetes).Secrets()
bootstrapStatus, err := r.Get(ctx, v1alpha1.NewBootstrapStatus().Metadata())
if err != nil {
if state.IsNotFoundError(err) {
continue
}
return err
}
if bootstrapStatus.(*v1alpha1.BootstrapStatus).Status().SelfHostedControlPlane {
logger.Print("skipped as running self-hosted control plane")
continue
}
manifests, err := r.List(ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.ManifestType, "", resource.VersionUndefined))
if err != nil {
return fmt.Errorf("error listing manifests: %w", err)
}
extraManifests, err := r.List(ctx, resource.NewMetadata(k8s.ExtraNamespaceName, k8s.ManifestType, "", resource.VersionUndefined))
if err != nil {
return fmt.Errorf("error listing extra manifests: %w", err)
}
manifests.Items = append(manifests.Items, extraManifests.Items...)
sort.Slice(manifests.Items, func(i, j int) bool {
return manifests.Items[i].Metadata().ID() < manifests.Items[j].Metadata().ID()
})
if len(manifests.Items) > 0 {
var (
kubeconfig *rest.Config
dc *discovery.DiscoveryClient
dyn dynamic.Interface
)
kubeconfig, err = clientcmd.BuildConfigFromKubeconfigGetter("", func() (*clientcmdapi.Config, error) {
return clientcmd.Load([]byte(secrets.AdminKubeconfig))
})
if err != nil {
return fmt.Errorf("error loading kubeconfig: %w", err)
}
dc, err = discovery.NewDiscoveryClientForConfig(kubeconfig)
if err != nil {
return fmt.Errorf("error building discovery client: %w", err)
}
mapper := restmapper.NewDeferredDiscoveryRESTMapper(memory.NewMemCacheClient(dc))
dyn, err = dynamic.NewForConfig(kubeconfig)
if err != nil {
return fmt.Errorf("error building dynamic client: %w", err)
}
if err = ctrl.etcdLock(ctx, logger, func() error {
return ctrl.apply(ctx, logger, mapper, dyn, manifests)
}); err != nil {
return err
}
}
if err = r.Update(ctx, k8s.NewManifestStatus(k8s.ControlPlaneNamespaceName), func(r resource.Resource) error {
status := r.(*k8s.ManifestStatus).Status()
status.ManifestsApplied = make([]string, 0, len(manifests.Items))
for _, manifest := range manifests.Items {
status.ManifestsApplied = append(status.ManifestsApplied, manifest.Metadata().ID())
}
return nil
}); err != nil {
return fmt.Errorf("error updating manifest status: %w", err)
}
}
}
func (ctrl *ManifestApplyController) etcdLock(ctx context.Context, logger *log.Logger, f func() error) error {
etcdClient, err := etcd.NewLocalClient()
if err != nil {
return fmt.Errorf("error creating etcd client: %w", err)
}
defer etcdClient.Close() //nolint: errcheck
session, err := concurrency.NewSession(etcdClient.Client)
if err != nil {
return fmt.Errorf("error creating etcd session: %w", err)
}
defer session.Close() //nolint: errcheck
mutex := concurrency.NewMutex(session, constants.EtcdTalosManifestApplyMutex)
logger.Printf("waiting for mutex")
if err := mutex.Lock(ctx); err != nil {
return fmt.Errorf("error acquiring mutex: %w", err)
}
logger.Printf("mutex acquired")
defer mutex.Unlock(ctx) //nolint: errcheck
return f()
}
//nolint: gocyclo
func (ctrl *ManifestApplyController) apply(ctx context.Context, logger *log.Logger, mapper *restmapper.DeferredDiscoveryRESTMapper, dyn dynamic.Interface, manifests resource.List) error {
// flatten list of objects to be applied
objects := make([]*unstructured.Unstructured, 0, len(manifests.Items))
for _, manifest := range manifests.Items {
objects = append(objects, manifest.(*k8s.Manifest).Objects()...)
}
// sort the list so that namespaces come first, followed by CRDs and everything else after that
sort.SliceStable(objects, func(i, j int) bool {
objL := objects[i]
objR := objects[j]
gvkL := objL.GroupVersionKind()
gvkR := objR.GroupVersionKind()
if isNamespace(gvkL) {
if !isNamespace(gvkR) {
return true
}
return objL.GetName() < objR.GetName()
}
if isNamespace(gvkR) {
return false
}
if isCRD(gvkL) {
if !isCRD(gvkR) {
return true
}
return objL.GetName() < objR.GetName()
}
if isCRD(gvkR) {
return false
}
return false
})
for _, obj := range objects {
gvk := obj.GroupVersionKind()
objName := fmt.Sprintf("%s/%s/%s/%s", gvk.Group, gvk.Version, gvk.Kind, obj.GetName())
mapping, err := mapper.RESTMapping(obj.GroupVersionKind().GroupKind(), obj.GroupVersionKind().Version)
if err != nil {
return fmt.Errorf("error creating mapping for object %s: %w", objName, err)
}
var dr dynamic.ResourceInterface
if mapping.Scope.Name() == meta.RESTScopeNameNamespace {
// namespaced resources should specify the namespace
dr = dyn.Resource(mapping.Resource).Namespace(obj.GetNamespace())
} else {
// for cluster-wide resources
dr = dyn.Resource(mapping.Resource)
}
_, err = dr.Get(ctx, obj.GetName(), metav1.GetOptions{})
if err == nil {
// already exists
continue
}
if !apierrors.IsNotFound(err) {
return fmt.Errorf("error checking resource existence: %w", err)
}
_, err = dr.Create(ctx, obj, metav1.CreateOptions{
FieldManager: "talos",
})
if err != nil {
if apierrors.IsAlreadyExists(err) {
// later on we might want to do something here, e.g. do server-side apply, for now do nothing
} else {
return fmt.Errorf("error creating %s: %w", objName, err)
}
} else {
logger.Printf("created %s", objName)
}
}
return nil
}
func isNamespace(gvk schema.GroupVersionKind) bool {
return gvk.Kind == "Namespace" && gvk.Version == "v1"
}
func isCRD(gvk schema.GroupVersionKind) bool {
return gvk.Kind == "CustomResourceDefinition" && gvk.Group == "apiextensions.k8s.io"
}

View File

@ -0,0 +1,250 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package k8s
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
stdlibtemplate "text/template"
"github.com/talos-systems/crypto/x509"
"github.com/talos-systems/os-runtime/pkg/controller"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/state"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/k8s"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/secrets"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// RenderSecretsStaticPodController manages k8s.SecretsReady and renders secrets from secrets.Kubernetes.
type RenderSecretsStaticPodController struct{}
// Name implements controller.Controller interface.
func (ctrl *RenderSecretsStaticPodController) Name() string {
return "k8s.RenderSecretsStaticPodController"
}
// ManagedResources implements controller.Controller interface.
func (ctrl *RenderSecretsStaticPodController) ManagedResources() (resource.Namespace, resource.Type) {
return k8s.ControlPlaneNamespaceName, k8s.SecretsStatusType
}
// Run implements controller.Controller interface.
//
//nolint: gocyclo
func (ctrl *RenderSecretsStaticPodController) Run(ctx context.Context, r controller.Runtime, logger *log.Logger) error {
if err := r.UpdateDependencies([]controller.Dependency{
{
Namespace: secrets.NamespaceName,
Type: secrets.KubernetesType,
Kind: controller.DependencyWeak,
},
}); err != nil {
return fmt.Errorf("error setting up dependencies: %w", err)
}
for {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}
secretsRes, err := r.Get(ctx, resource.NewMetadata(secrets.NamespaceName, secrets.KubernetesType, secrets.KubernetesID, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
continue
}
return fmt.Errorf("error getting secrets resource: %w", err)
}
secrets := secretsRes.(*secrets.Kubernetes).Secrets()
serviceAccountKey, err := secrets.ServiceAccount.GetRSAKey()
if err != nil {
return fmt.Errorf("error parsing service account key: %w", err)
}
type secret struct {
getter func() *x509.PEMEncodedCertificateAndKey
certFilename string
keyFilename string
}
type template struct {
filename string
template []byte
}
for _, pod := range []struct {
name string
directory string
secrets []secret
templates []template
}{
{
name: "kube-apiserver",
directory: constants.KubernetesAPIServerSecretsDir,
secrets: []secret{
{
getter: func() *x509.PEMEncodedCertificateAndKey { return secrets.EtcdCA },
certFilename: "etcd-client-ca.crt",
},
{
getter: func() *x509.PEMEncodedCertificateAndKey { return secrets.EtcdPeer },
certFilename: "etcd-client.crt",
keyFilename: "etcd-client.key",
},
{
getter: func() *x509.PEMEncodedCertificateAndKey { return secrets.CA },
certFilename: "ca.crt",
},
{
getter: func() *x509.PEMEncodedCertificateAndKey { return secrets.APIServer },
certFilename: "apiserver.crt",
keyFilename: "apiserver.key",
},
{
getter: func() *x509.PEMEncodedCertificateAndKey { return secrets.APIServerKubeletClient },
certFilename: "apiserver-kubelet-client.crt",
keyFilename: "apiserver-kubelet-client.key",
},
{
getter: func() *x509.PEMEncodedCertificateAndKey {
return &x509.PEMEncodedCertificateAndKey{
Crt: serviceAccountKey.PublicKeyPEM,
Key: serviceAccountKey.KeyPEM,
}
},
certFilename: "service-account.pub",
keyFilename: "service-account.key",
},
{
getter: func() *x509.PEMEncodedCertificateAndKey { return secrets.AggregatorCA },
certFilename: "aggregator-ca.crt",
},
{
getter: func() *x509.PEMEncodedCertificateAndKey { return secrets.FrontProxy },
certFilename: "front-proxy-client.crt",
keyFilename: "front-proxy-client.key",
},
},
templates: []template{
{
filename: "encryptionconfig.yaml",
template: kubeSystemEncryptionConfigTemplate,
},
{
filename: "auditpolicy.yaml",
template: kubeSystemAuditPolicyTemplate,
},
},
},
{
name: "kube-controller-manager",
directory: constants.KubernetesControllerManagerSecretsDir,
secrets: []secret{
{
getter: func() *x509.PEMEncodedCertificateAndKey { return secrets.CA },
certFilename: "ca.crt",
keyFilename: "ca.key",
},
{
getter: func() *x509.PEMEncodedCertificateAndKey {
return &x509.PEMEncodedCertificateAndKey{
Crt: serviceAccountKey.PublicKeyPEM,
Key: serviceAccountKey.KeyPEM,
}
},
keyFilename: "service-account.key",
},
},
templates: []template{
{
filename: "kubeconfig",
template: []byte("{{ .AdminKubeconfig }}"),
},
},
},
{
name: "kube-scheduler",
directory: constants.KubernetesSchedulerSecretsDir,
templates: []template{
{
filename: "kubeconfig",
template: []byte("{{ .AdminKubeconfig }}"),
},
},
},
} {
if err = os.MkdirAll(pod.directory, 0o755); err != nil {
return fmt.Errorf("error creating secrets directory for %q: %w", pod.name, err)
}
for _, secret := range pod.secrets {
certAndKey := secret.getter()
if secret.certFilename != "" {
if err = ioutil.WriteFile(filepath.Join(pod.directory, secret.certFilename), certAndKey.Crt, 0o400); err != nil {
return fmt.Errorf("error writing certificate %q for %q: %w", secret.certFilename, pod.name, err)
}
if err = os.Chown(filepath.Join(pod.directory, secret.certFilename), constants.KubernetesRunUser, -1); err != nil {
return fmt.Errorf("error chowning %q for %q: %w", secret.certFilename, pod.name, err)
}
}
if secret.keyFilename != "" {
if err = ioutil.WriteFile(filepath.Join(pod.directory, secret.keyFilename), certAndKey.Key, 0o400); err != nil {
return fmt.Errorf("error writing key %q for %q: %w", secret.keyFilename, pod.name, err)
}
if err = os.Chown(filepath.Join(pod.directory, secret.keyFilename), constants.KubernetesRunUser, -1); err != nil {
return fmt.Errorf("error chowning %q for %q: %w", secret.keyFilename, pod.name, err)
}
}
}
for _, templ := range pod.templates {
var t *stdlibtemplate.Template
t, err = stdlibtemplate.New(templ.filename).Parse(string(templ.template))
if err != nil {
return fmt.Errorf("error parsing template %q: %w", templ.filename, err)
}
var buf bytes.Buffer
if err = t.Execute(&buf, secrets); err != nil {
return fmt.Errorf("error executing template %q: %w", templ.filename, err)
}
if err = ioutil.WriteFile(filepath.Join(pod.directory, templ.filename), buf.Bytes(), 0o400); err != nil {
return fmt.Errorf("error writing template %q for %q: %w", templ.filename, pod.name, err)
}
if err = os.Chown(filepath.Join(pod.directory, templ.filename), constants.KubernetesRunUser, -1); err != nil {
return fmt.Errorf("error chowning %q for %q: %w", templ.filename, pod.name, err)
}
}
}
if err = r.Update(ctx, k8s.NewSecretsStatus(k8s.ControlPlaneNamespaceName, k8s.StaticPodSecretsStaticPodID), func(r resource.Resource) error {
r.(*k8s.SecretsStatus).Status().Ready = true
r.(*k8s.SecretsStatus).Status().Version = secretsRes.Metadata().Version().String()
return nil
}); err != nil {
return err
}
}
}

View File

@ -0,0 +1,701 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package k8s
// kube-apiserver configuration:
var kubeSystemEncryptionConfigTemplate = []byte(`apiVersion: v1
kind: EncryptionConfig
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: {{ .AESCBCEncryptionSecret }}
- identity: {}
`)
var kubeSystemAuditPolicyTemplate = []byte(`apiVersion: audit.k8s.io/v1beta1
kind: Policy
rules:
- level: Metadata
`)
// manifests injected into kube-apiserver
var kubeletBootstrappingToken = []byte(`apiVersion: v1
kind: Secret
metadata:
name: bootstrap-token-{{ .Secrets.BootstrapTokenID }}
namespace: kube-system
type: bootstrap.kubernetes.io/token
stringData:
token-id: "{{ .Secrets.BootstrapTokenID }}"
token-secret: "{{ .Secrets.BootstrapTokenSecret }}"
usage-bootstrap-authentication: "true"
`)
// csrNodeBootstrapTemplate lets bootstrapping tokens and nodes request CSRs.
var csrNodeBootstrapTemplate = []byte(`kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: system-bootstrap-node-bootstrapper
subjects:
- kind: Group
name: system:bootstrappers
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system:nodes
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: system:node-bootstrapper
apiGroup: rbac.authorization.k8s.io
`)
// csrApproverRoleBindingTemplate instructs the csrapprover controller to
// automatically approve CSRs made by bootstrapping tokens for client
// credentials.
//
// This binding should be removed to disable CSR auto-approval.
var csrApproverRoleBindingTemplate = []byte(`kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: system-bootstrap-approve-node-client-csr
subjects:
- kind: Group
name: system:bootstrappers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: system:certificates.k8s.io:certificatesigningrequests:nodeclient
apiGroup: rbac.authorization.k8s.io
`)
// csrRenewalRoleBindingTemplate instructs the csrapprover controller to
// automatically approve all CSRs made by nodes to renew their client
// certificates.
//
// This binding should be altered in the future to hold a list of node
// names instead of targeting `system:nodes` so we can revoke invidivual
// node's ability to renew its certs.
var csrRenewalRoleBindingTemplate = []byte(`kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: system-bootstrap-node-renewal
subjects:
- kind: Group
name: system:nodes
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient
apiGroup: rbac.authorization.k8s.io
`)
var kubeSystemSARoleBindingTemplate = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:default-sa
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
`)
var kubeProxyTemplate = []byte(`apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-proxy
namespace: kube-system
labels:
tier: node
k8s-app: kube-proxy
spec:
selector:
matchLabels:
tier: node
k8s-app: kube-proxy
template:
metadata:
labels:
tier: node
k8s-app: kube-proxy
spec:
containers:
- name: kube-proxy
image: {{ .ProxyImage }}
command:
- /usr/local/bin/kube-proxy
- --cluster-cidr={{ .PodCIDRs }}
- --hostname-override=$(NODE_NAME)
- --kubeconfig=/etc/kubernetes/kubeconfig
- --proxy-mode={{ .ProxyMode }}
- --conntrack-max-per-core=0
{{- range $k, $v := .ProxyExtraArgs }}
- --{{ $k }}={{ $v }}
{{- end }}
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
securityContext:
privileged: true
volumeMounts:
- mountPath: /lib/modules
name: lib-modules
readOnly: true
- mountPath: /etc/ssl/certs
name: ssl-certs-host
readOnly: true
- name: kubeconfig
mountPath: /etc/kubernetes
readOnly: true
hostNetwork: true
serviceAccountName: kube-proxy
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists
volumes:
- name: lib-modules
hostPath:
path: /lib/modules
- name: ssl-certs-host
hostPath:
path: /etc/ssl/certs
- name: kubeconfig
configMap:
name: kubeconfig-in-cluster
updateStrategy:
rollingUpdate:
maxUnavailable: 1
type: RollingUpdate
---
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: kube-system
name: kube-proxy
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kube-proxy
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:node-proxier # Automatically created system role.
subjects:
- kind: ServiceAccount
name: kube-proxy
namespace: kube-system
`)
// kubeConfigInCluster instructs clients to use their service account token,
// but unlike an in-cluster client doesn't rely on the `KUBERNETES_SERVICE_PORT`
// and `KUBERNETES_PORT` to determine the API servers address.
//
// This kubeconfig is used by bootstrapping pods that might not have access to
// these env vars, such as kube-proxy, which sets up the API server endpoint
// (chicken and egg), and the checkpointer, which needs to run as a static pod
// even if the API server isn't available.
var kubeConfigInClusterTemplate = []byte(`apiVersion: v1
kind: ConfigMap
metadata:
name: kubeconfig-in-cluster
namespace: kube-system
data:
kubeconfig: |
apiVersion: v1
clusters:
- name: local
cluster:
server: {{ .Server }}
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
users:
- name: service-account
user:
# Use service account token
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
contexts:
- context:
cluster: local
user: service-account
`)
var coreDNSTemplate = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:coredns
labels:
kubernetes.io/bootstrapping: rbac-defaults
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:coredns
subjects:
- kind: ServiceAccount
name: coredns
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:coredns
labels:
kubernetes.io/bootstrapping: rbac-defaults
rules:
- apiGroups: [""]
resources:
- endpoints
- services
- pods
- namespaces
verbs:
- list
- watch
- apiGroups: [""]
resources:
- nodes
verbs:
- get
---
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
log . {
class error
}
kubernetes {{ .ClusterDomain }} in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: coredns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/name: "CoreDNS"
kubernetes.io/cluster-service: "true"
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
selector:
matchLabels:
k8s-app: kube-dns
template:
metadata:
labels:
k8s-app: kube-dns
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: k8s-app
operator: In
values:
- kube-dns
topologyKey: kubernetes.io/hostname
serviceAccountName: coredns
priorityClassName: system-cluster-critical
tolerations:
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
containers:
- name: coredns
image: {{ .CoreDNSImage }}
imagePullPolicy: IfNotPresent
resources:
limits:
memory: 170Mi
requests:
cpu: 100m
memory: 70Mi
args: [ "-conf", "/etc/coredns/Corefile" ]
volumeMounts:
- name: config-volume
mountPath: /etc/coredns
readOnly: true
ports:
- name: dns
protocol: UDP
containerPort: 53
- name: dns-tcp
protocol: TCP
containerPort: 53
- name: metrics
protocol: TCP
containerPort: 9153
livenessProbe:
httpGet:
path: /health
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /ready
port: 8181
scheme: HTTP
securityContext:
allowPrivilegeEscalation: false
capabilities:
add:
- NET_BIND_SERVICE
drop:
- all
readOnlyRootFilesystem: true
dnsPolicy: Default
volumes:
- name: config-volume
configMap:
name: coredns
items:
- key: Corefile
path: Corefile
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: coredns
namespace: kube-system
labels:
kubernetes.io/cluster-service: "true"
`)
var coreDNSSvcTemplate = []byte(`apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9153"
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "CoreDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: {{ .DNSServiceIP }}
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
`)
var coreDNSv6SvcTemplate = []byte(`apiVersion: v1
kind: Service
metadata:
name: kube-dnsv6
namespace: kube-system
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9153"
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "CoreDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: {{ .DNSServiceIPv6 }}
ipFamily: IPv6
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
`)
var flannelTemplate = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: flannel
rules:
- apiGroups: ['extensions']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames: ['psp.flannel.unprivileged']
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- ""
resources:
- nodes
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: flannel
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: flannel
subjects:
- kind: ServiceAccount
name: flannel
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: flannel
namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-flannel-cfg
namespace: kube-system
labels:
tier: node
k8s-app: flannel
data:
cni-conf.json: |
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json: |
{
"Network": "{{ .FirstPodCIDR }}",
"Backend": {
"Type": "vxlan",
"Port": 4789
}
}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-flannel
namespace: kube-system
labels:
tier: node
k8s-app: flannel
spec:
selector:
matchLabels:
tier: node
k8s-app: flannel
template:
metadata:
labels:
tier: node
k8s-app: flannel
spec:
serviceAccountName: flannel
initContainers:
- name: install-config
image: {{ .FlannelImage }}
command:
- cp
args:
- -f
- /etc/kube-flannel/cni-conf.json
- /etc/cni/net.d/10-flannel.conflist
volumeMounts:
- name: cni
mountPath: /etc/cni/net.d
- name: flannel-cfg
mountPath: /etc/kube-flannel/
- name: install-cni
image: {{ .FlannelCNIImage }}
command: ["/install-cni.sh"]
volumeMounts:
- name: host-cni-bin
mountPath: /host/opt/cni/bin/
containers:
- name: kube-flannel
image: {{ .FlannelImage }}
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
securityContext:
privileged: true
capabilities:
add: ["NET_ADMIN", "NET_RAW"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
volumeMounts:
- name: run
mountPath: /run/flannel
- name: flannel-cfg
mountPath: /etc/kube-flannel/
hostNetwork: true
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists
volumes:
- name: run
hostPath:
path: /run/flannel
- name: cni
hostPath:
path: /etc/cni/net.d
- name: flannel-cfg
configMap:
name: kube-flannel-cfg
- name: host-cni-bin
hostPath:
path: /opt/cni/bin
updateStrategy:
rollingUpdate:
maxUnavailable: 1
type: RollingUpdate
`)
// podSecurityPolicy is the default PSP.
var podSecurityPolicy = []byte(`kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: psp:privileged
rules:
- apiGroups: ['policy']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames:
- privileged
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: psp:privileged
roleRef:
kind: ClusterRole
name: psp:privileged
apiGroup: rbac.authorization.k8s.io
subjects:
# Authorize all service accounts in a namespace:
- kind: Group
apiGroup: rbac.authorization.k8s.io
name: system:serviceaccounts
# Authorize all authenticated users in a namespace:
- kind: Group
apiGroup: rbac.authorization.k8s.io
name: system:authenticated
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: privileged
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
spec:
fsGroup:
rule: RunAsAny
privileged: true
runAsUser:
rule: RunAsAny
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
volumes:
- '*'
allowedCapabilities:
- '*'
hostPID: true
hostIPC: true
hostNetwork: true
hostPorts:
- min: 1
max: 65536
`)

View File

@ -0,0 +1,286 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package secrets
import (
"bytes"
"context"
"fmt"
"log"
"net"
"time"
"github.com/AlekSi/pointer"
"github.com/talos-systems/crypto/x509"
"github.com/talos-systems/os-runtime/pkg/controller"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/state"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/config"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/secrets"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/v1alpha1"
"github.com/talos-systems/talos/internal/pkg/etcd"
"github.com/talos-systems/talos/internal/pkg/kubeconfig"
talosconfig "github.com/talos-systems/talos/pkg/machinery/config"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// KubernetesController manages secrets.Kubernetes based on configuration.
type KubernetesController struct {
}
// Name implements controller.Controller interface.
func (ctrl *KubernetesController) Name() string {
return "secrets.KubernetesController"
}
// ManagedResources implements controller.Controller interface.
func (ctrl *KubernetesController) ManagedResources() (resource.Namespace, resource.Type) {
return secrets.NamespaceName, secrets.KubernetesType
}
// Run implements controller.Controller interface.
//
//nolint: gocyclo
func (ctrl *KubernetesController) Run(ctx context.Context, r controller.Runtime, logger *log.Logger) error {
if err := r.UpdateDependencies([]controller.Dependency{
{ // TODO: should render config for kubernetes secrets controller
Namespace: config.NamespaceName,
Type: config.V1Alpha1Type,
ID: pointer.ToString(config.V1Alpha1ID),
Kind: controller.DependencyWeak,
},
{
Namespace: v1alpha1.NamespaceName,
Type: v1alpha1.ServiceType,
ID: pointer.ToString("networkd"),
Kind: controller.DependencyWeak,
},
{
Namespace: config.NamespaceName,
Type: config.MachineTypeType,
ID: pointer.ToString(config.MachineTypeID),
Kind: controller.DependencyWeak,
},
}); err != nil {
return fmt.Errorf("error setting up dependencies: %w", err)
}
for {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}
cfg, err := r.Get(ctx, resource.NewMetadata(config.NamespaceName, config.V1Alpha1Type, config.V1Alpha1ID, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
if err = ctrl.teardownAll(ctx, r); err != nil {
return fmt.Errorf("error destroying static pods: %w", err)
}
continue
}
return fmt.Errorf("error getting config: %w", err)
}
cfgProvider := cfg.(*config.V1Alpha1).Config()
machineTypeRes, err := r.Get(ctx, resource.NewMetadata(config.NamespaceName, config.MachineTypeType, config.MachineTypeID, resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
continue
}
return fmt.Errorf("error getting machine type: %w", err)
}
machineType := machineTypeRes.(*config.MachineType).MachineType()
if machineType != machine.TypeControlPlane && machineType != machine.TypeInit {
if err = ctrl.teardownAll(ctx, r); err != nil {
return fmt.Errorf("error destroying static pods: %w", err)
}
continue
}
// wait for networkd to be healthy as it might change IPs/hostname
networkdResource, err := r.Get(ctx, resource.NewMetadata(v1alpha1.NamespaceName, v1alpha1.ServiceType, "networkd", resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
continue
}
return err
}
if !networkdResource.(*v1alpha1.Service).Healthy() {
continue
}
if err = r.Update(ctx, secrets.NewKubernetes(), func(r resource.Resource) error {
k8sSecrets := r.(*secrets.Kubernetes) //nolint: errcheck
return ctrl.updateSecrets(cfgProvider, k8sSecrets)
}); err != nil {
return err
}
}
}
//nolint: gocyclo
func (ctrl *KubernetesController) updateSecrets(cfgProvider talosconfig.Provider, k8sSecrets *secrets.Kubernetes) error {
k8sSecrets.Secrets().EtcdCA = cfgProvider.Cluster().Etcd().CA()
if k8sSecrets.Secrets().EtcdCA == nil {
return fmt.Errorf("missing cluster.etcdCA secret")
}
k8sSecrets.Secrets().AggregatorCA = cfgProvider.Cluster().AggregatorCA()
if k8sSecrets.Secrets().AggregatorCA == nil {
return fmt.Errorf("missing cluster.aggregatorCA secret")
}
k8sSecrets.Secrets().CA = cfgProvider.Cluster().CA()
if k8sSecrets.Secrets().CA == nil {
return fmt.Errorf("missing cluster.CA secret")
}
var err error
k8sSecrets.Secrets().EtcdPeer, err = etcd.GeneratePeerCert(cfgProvider.Cluster().Etcd().CA())
if err != nil {
return err
}
urls := []string{cfgProvider.Cluster().Endpoint().Hostname()}
urls = append(urls, cfgProvider.Cluster().CertSANs()...)
altNames := altNamesFromURLs(urls)
apiServiceIPs, err := cfgProvider.Cluster().Network().APIServerIPs()
if err != nil {
return fmt.Errorf("failed to calculate API service IP: %w", err)
}
altNames.IPs = append(altNames.IPs, apiServiceIPs...)
// Add kubernetes default svc with cluster domain to AltNames
altNames.DNSNames = append(altNames.DNSNames,
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc."+cfgProvider.Cluster().Network().DNSDomain(),
)
ca, err := x509.NewCertificateAuthorityFromCertificateAndKey(k8sSecrets.Secrets().CA, x509.RSA(true))
if err != nil {
return fmt.Errorf("failed to parse CA certificate: %w", err)
}
apiServer, err := x509.NewKeyPair(ca,
x509.RSA(true),
x509.IPAddresses(altNames.IPs),
x509.DNSNames(altNames.DNSNames),
x509.CommonName("kube-apiserver"),
x509.Organization("kube-master"),
x509.NotAfter(time.Now().Add(constants.KubernetesDefaultCertificateValidityDuration)),
)
if err != nil {
return fmt.Errorf("failed to generate api-server cert: %w", err)
}
k8sSecrets.Secrets().APIServer = x509.NewCertificateAndKeyFromKeyPair(apiServer)
apiServerKubeletClient, err := x509.NewKeyPair(ca,
x509.RSA(true),
x509.CommonName(constants.KubernetesAdminCertCommonName),
x509.Organization(constants.KubernetesAdminCertOrganization),
x509.NotAfter(time.Now().Add(constants.KubernetesDefaultCertificateValidityDuration)),
)
if err != nil {
return fmt.Errorf("failed to generate api-server cert: %w", err)
}
k8sSecrets.Secrets().APIServerKubeletClient = x509.NewCertificateAndKeyFromKeyPair(apiServerKubeletClient)
k8sSecrets.Secrets().ServiceAccount = cfgProvider.Cluster().ServiceAccount()
aggregatorCA, err := x509.NewCertificateAuthorityFromCertificateAndKey(k8sSecrets.Secrets().AggregatorCA, x509.RSA(true))
if err != nil {
return fmt.Errorf("failed to parse aggregator CA: %w", err)
}
frontProxy, err := x509.NewKeyPair(aggregatorCA,
x509.RSA(true),
x509.CommonName("front-proxy-client"),
x509.NotAfter(time.Now().Add(constants.KubernetesDefaultCertificateValidityDuration)),
)
if err != nil {
return fmt.Errorf("failed to generate aggregator cert: %w", err)
}
k8sSecrets.Secrets().FrontProxy = x509.NewCertificateAndKeyFromKeyPair(frontProxy)
k8sSecrets.Secrets().AESCBCEncryptionSecret = cfgProvider.Cluster().AESCBCEncryptionSecret()
var buf bytes.Buffer
if err = kubeconfig.GenerateAdmin(cfgProvider.Cluster(), &buf); err != nil {
return fmt.Errorf("failed to generate admin kubeconfig: %w", err)
}
k8sSecrets.Secrets().AdminKubeconfig = buf.String()
k8sSecrets.Secrets().BootstrapTokenID = cfgProvider.Cluster().Token().ID()
k8sSecrets.Secrets().BootstrapTokenSecret = cfgProvider.Cluster().Token().Secret()
return nil
}
func (ctrl *KubernetesController) teardownAll(ctx context.Context, r controller.Runtime) error {
list, err := r.List(ctx, resource.NewMetadata(secrets.NamespaceName, secrets.KubernetesType, "", resource.VersionUndefined))
if err != nil {
return err
}
// TODO: change this to proper teardown sequence
for _, res := range list.Items {
if err = r.Destroy(ctx, res.Metadata()); err != nil {
return err
}
}
return nil
}
// AltNames defines certificate alternative names.
type AltNames struct {
IPs []net.IP
DNSNames []string
}
func altNamesFromURLs(urls []string) *AltNames {
var an AltNames
for _, u := range urls {
ip := net.ParseIP(u)
if ip != nil {
an.IPs = append(an.IPs, ip)
continue
}
an.DNSNames = append(an.DNSNames, u)
}
return &an
}

View File

@ -0,0 +1,6 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Package secrets provides controllers which manage secret resources.
package secrets

View File

@ -0,0 +1,128 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package v1alpha1
import (
"context"
"fmt"
"log"
"github.com/AlekSi/pointer"
"github.com/talos-systems/os-runtime/pkg/controller"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/state"
"go.etcd.io/etcd/clientv3"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/v1alpha1"
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
"github.com/talos-systems/talos/internal/pkg/etcd"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// BootstrapStatusController manages v1alpha1.Service based on services subsystem state.
type BootstrapStatusController struct {
V1Alpha1Events runtime.Watcher
}
// Name implements controller.Controller interface.
func (ctrl *BootstrapStatusController) Name() string {
return "v1alpha1.BootstrapStatusController"
}
// ManagedResources implements controller.Controller interface.
func (ctrl *BootstrapStatusController) ManagedResources() (resource.Namespace, resource.Type) {
return v1alpha1.NamespaceName, v1alpha1.BootstrapStatusType
}
// Run implements controller.Controller interface.
//
//nolint: gocyclo
func (ctrl *BootstrapStatusController) Run(ctx context.Context, r controller.Runtime, logger *log.Logger) error {
if err := r.UpdateDependencies([]controller.Dependency{
{
Namespace: v1alpha1.NamespaceName,
Type: v1alpha1.ServiceType,
ID: pointer.ToString("etcd"),
Kind: controller.DependencyWeak,
},
}); err != nil {
return fmt.Errorf("error setting up dependencies: %w", err)
}
for {
select {
case <-ctx.Done():
return nil
case <-r.EventCh():
}
// wait for etcd to be healthy as controller reads the key
etcdResource, err := r.Get(ctx, resource.NewMetadata(v1alpha1.NamespaceName, v1alpha1.ServiceType, "etcd", resource.VersionUndefined))
if err != nil {
if state.IsNotFoundError(err) {
continue
}
return err
}
if !etcdResource.(*v1alpha1.Service).Healthy() {
continue
}
if err = ctrl.readInitialized(ctx, r, logger); err != nil {
return err
}
}
}
func (ctrl *BootstrapStatusController) readInitialized(ctx context.Context, r controller.Runtime, logger *log.Logger) error {
etcdClient, err := etcd.NewLocalClient()
if err != nil {
return fmt.Errorf("error creating etcd client: %w", err)
}
defer etcdClient.Close() //nolint: errcheck
ctx, cancel := context.WithCancel(ctx)
defer cancel()
ctx = clientv3.WithRequireLeader(ctx)
// InitializedKey was created by Talos < 0.9 after successful bootstrap run (bootkube)
// this key can only be removed by Talos 0.9, so if key is not found, controller returns
watchCh := etcdClient.Watch(ctx, constants.InitializedKey)
resp, err := etcdClient.Get(ctx, constants.InitializedKey)
if err != nil {
return fmt.Errorf("error getting key: %w", err)
}
if resp.Count == 0 || string(resp.Kvs[0].Value) != "true" {
logger.Printf("bootkube initialized status not found")
return r.Update(ctx, v1alpha1.NewBootstrapStatus(), func(r resource.Resource) error {
r.(*v1alpha1.BootstrapStatus).Status().SelfHostedControlPlane = false
return nil
})
}
logger.Printf("found bootkube initialized status in etcd")
if err = r.Update(ctx, v1alpha1.NewBootstrapStatus(), func(r resource.Resource) error {
r.(*v1alpha1.BootstrapStatus).Status().SelfHostedControlPlane = true
return nil
}); err != nil {
return err
}
// wait for key change or any other event in etcd
<-watchCh
return nil
}

View File

@ -65,7 +65,10 @@ func (ctrl *ServiceController) Run(ctx context.Context, r controller.Runtime, lo
switch msg.Action { //nolint: exhaustive
case machine.ServiceStateEvent_RUNNING:
if err := r.Update(ctx, service, func(r resource.Resource) error {
r.(*v1alpha1.Service).SetRunning(true)
svc := r.(*v1alpha1.Service) //nolint: errcheck
svc.SetRunning(true)
svc.SetHealthy(msg.GetHealth().GetHealthy() && !msg.GetHealth().GetUnknown())
return nil
}); err != nil {

View File

@ -0,0 +1,238 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package config
import (
"fmt"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/resource/core"
)
// K8sControlPlaneType is type of K8sControlPlane resource.
const K8sControlPlaneType = resource.Type("config/k8sControlPlane")
// K8sControlPlaneAPIServerID is an ID of kube-apiserver config.
const K8sControlPlaneAPIServerID = resource.ID("kube-apiserver")
// K8sControlPlaneControllerManagerID is an ID of kube-controller-manager config.
const K8sControlPlaneControllerManagerID = resource.ID("kube-controller-manager")
// K8sControlPlaneSchedulerID is an ID of kube-scheduler config.
const K8sControlPlaneSchedulerID = resource.ID("kube-scheduler")
// K8sManifestsID is an ID of manifests config.
const K8sManifestsID = resource.ID("manifests")
// K8sExtraManifestsID is an ID of extra manifests config.
const K8sExtraManifestsID = resource.ID("extra-manifests")
// K8sControlPlane describes machine type.
type K8sControlPlane struct {
md resource.Metadata
// spec stores values of different types depending on ID
spec interface{}
}
// K8sControlPlaneAPIServerSpec is configuration for kube-apiserver.
type K8sControlPlaneAPIServerSpec struct {
Image string `yaml:"image"`
CloudProvider string `yaml:"cloudProvider"`
ControlPlaneEndpoint string `yaml:"controlPlaneEndpoint"`
EtcdServers []string `yaml:"etcdServers"`
LocalPort int `yaml:"localPort"`
ServiceCIDR string `yaml:"serviceCIDR"`
ExtraArgs map[string]string `yaml:"extraArgs"`
}
// K8sControlPlaneControllerManagerSpec is configuration for kube-controller-manager.
type K8sControlPlaneControllerManagerSpec struct {
Image string `yaml:"image"`
CloudProvider string `yaml:"cloudProvider"`
PodCIDR string `yaml:"podCIDR"`
ServiceCIDR string `yaml:"serviceCIDR"`
ExtraArgs map[string]string `yaml:"extraArgs"`
}
// K8sControlPlaneSchedulerSpec is configuration for kube-scheduler.
type K8sControlPlaneSchedulerSpec struct {
Image string `yaml:"image"`
ExtraArgs map[string]string `yaml:"extraArgs"`
}
// K8sManifestsSpec is configuration for manifests.
type K8sManifestsSpec struct {
Server string `yaml:"string"`
ClusterDomain string `yaml:"clusterDomain"`
PodCIDRs string `yaml:"podCIDRs"`
FirstPodCIDR string `yaml:"firstPodCIDR"`
ProxyImage string `yaml:"proxyImage"`
ProxyMode string `yaml:"proxyMode"`
ProxyExtraArgs map[string]string `yaml:"proxyExtraArgs"`
CoreDNSImage string `yaml:"coreDNSImage"`
DNSServiceIP string `yaml:"dnsServiceIP"`
DNSServiceIPv6 string `yaml:"dnsServiceIPv6"`
FlannelEnabled bool `yaml:"flannelEnabled"`
FlannelImage string `yaml:"flannelImage"`
FlannelCNIImage string `yaml:"flannelCNIImage"`
}
// ExtraManifest defines a single extra manifest to download.
type ExtraManifest struct {
URL string `yaml:"url"`
Priority string `yaml:"priority"`
ExtraHeaders map[string]string `yaml:"extraHeaders"`
}
// K8sExtraManifestsSpec is a configuration for extra manifests.
type K8sExtraManifestsSpec struct {
ExtraManifests []ExtraManifest `yaml:"extraManifests"`
}
// NewK8sControlPlaneAPIServer initializes a K8sControlPlane resource.
func NewK8sControlPlaneAPIServer() *K8sControlPlane {
r := &K8sControlPlane{
md: resource.NewMetadata(NamespaceName, K8sControlPlaneType, K8sControlPlaneAPIServerID, resource.VersionUndefined),
spec: K8sControlPlaneAPIServerSpec{},
}
r.md.BumpVersion()
return r
}
// NewK8sControlPlaneControllerManager initializes a K8sControlPlane resource.
func NewK8sControlPlaneControllerManager() *K8sControlPlane {
r := &K8sControlPlane{
md: resource.NewMetadata(NamespaceName, K8sControlPlaneType, K8sControlPlaneControllerManagerID, resource.VersionUndefined),
spec: K8sControlPlaneControllerManagerSpec{},
}
r.md.BumpVersion()
return r
}
// NewK8sControlPlaneScheduler initializes a K8sControlPlane resource.
func NewK8sControlPlaneScheduler() *K8sControlPlane {
r := &K8sControlPlane{
md: resource.NewMetadata(NamespaceName, K8sControlPlaneType, K8sControlPlaneSchedulerID, resource.VersionUndefined),
spec: K8sControlPlaneSchedulerSpec{},
}
r.md.BumpVersion()
return r
}
// NewK8sManifests initializes a K8sControlPlane resource.
func NewK8sManifests() *K8sControlPlane {
r := &K8sControlPlane{
md: resource.NewMetadata(NamespaceName, K8sControlPlaneType, K8sManifestsID, resource.VersionUndefined),
spec: K8sManifestsSpec{},
}
r.md.BumpVersion()
return r
}
// NewK8sExtraManifests initializes a K8sControlPlane resource.
func NewK8sExtraManifests() *K8sControlPlane {
r := &K8sControlPlane{
md: resource.NewMetadata(NamespaceName, K8sControlPlaneType, K8sExtraManifestsID, resource.VersionUndefined),
spec: K8sExtraManifestsSpec{},
}
r.md.BumpVersion()
return r
}
// Metadata implements resource.Resource.
func (r *K8sControlPlane) Metadata() *resource.Metadata {
return &r.md
}
// Spec implements resource.Resource.
func (r *K8sControlPlane) Spec() interface{} {
return r.spec
}
func (r *K8sControlPlane) String() string {
return fmt.Sprintf("config.K8sControlPlane(%q)", r.md.ID())
}
// DeepCopy implements resource.Resource.
func (r *K8sControlPlane) DeepCopy() resource.Resource {
return &K8sControlPlane{
md: r.md,
spec: r.spec,
}
}
// ResourceDefinition implements core.ResourceDefinitionProvider interface.
func (r *K8sControlPlane) ResourceDefinition() core.ResourceDefinitionSpec {
return core.ResourceDefinitionSpec{
Type: K8sControlPlaneType,
Aliases: []resource.Type{"controlPlane"},
DefaultNamespace: NamespaceName,
}
}
// APIServer returns K8sControlPlaneApiServerSpec.
func (r *K8sControlPlane) APIServer() K8sControlPlaneAPIServerSpec {
return r.spec.(K8sControlPlaneAPIServerSpec)
}
// SetAPIServer sets K8sControlPlaneApiServerSpec.
func (r *K8sControlPlane) SetAPIServer(spec K8sControlPlaneAPIServerSpec) {
r.spec = spec
}
// ControllerManager returns K8sControlPlaneControllerManagerSpec.
func (r *K8sControlPlane) ControllerManager() K8sControlPlaneControllerManagerSpec {
return r.spec.(K8sControlPlaneControllerManagerSpec)
}
// SetControllerManager sets K8sControlPlaneControllerManagerSpec.
func (r *K8sControlPlane) SetControllerManager(spec K8sControlPlaneControllerManagerSpec) {
r.spec = spec
}
// Scheduler returns K8sControlPlaneSchedulerSpec.
func (r *K8sControlPlane) Scheduler() K8sControlPlaneSchedulerSpec {
return r.spec.(K8sControlPlaneSchedulerSpec)
}
// SetScheduler sets K8sControlPlaneSchedulerSpec.
func (r *K8sControlPlane) SetScheduler(spec K8sControlPlaneSchedulerSpec) {
r.spec = spec
}
// Manifests returns K8sManifestsSpec.
func (r *K8sControlPlane) Manifests() K8sManifestsSpec {
return r.spec.(K8sManifestsSpec)
}
// SetManifests sets K8sManifestsSpec.
func (r *K8sControlPlane) SetManifests(spec K8sManifestsSpec) {
r.spec = spec
}
// ExtraManifests returns K8sExtraManifestsSpec.
func (r *K8sControlPlane) ExtraManifests() K8sExtraManifestsSpec {
return r.spec.(K8sExtraManifestsSpec)
}
// SetExtraManifests sets K8sManifestsSpec.
func (r *K8sControlPlane) SetExtraManifests(spec K8sExtraManifestsSpec) {
r.spec = spec
}

View File

@ -0,0 +1,87 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package config
import (
"fmt"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/resource/core"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine"
)
// MachineTypeType is type of MachineType resource.
const MachineTypeType = resource.Type("config/machineType")
// MachineTypeID is singleton resource ID.
const MachineTypeID = resource.ID("machine-type")
// MachineType describes machine type.
type MachineType struct {
md resource.Metadata
spec machineTypeSpec
}
type machineTypeSpec struct {
machine.Type
}
func (spec machineTypeSpec) MarshalYAML() (interface{}, error) {
return spec.Type.String(), nil
}
// NewMachineType initializes a MachineType resource.
func NewMachineType() *MachineType {
r := &MachineType{
md: resource.NewMetadata(NamespaceName, MachineTypeType, MachineTypeID, resource.VersionUndefined),
spec: machineTypeSpec{},
}
r.md.BumpVersion()
return r
}
// Metadata implements resource.Resource.
func (r *MachineType) Metadata() *resource.Metadata {
return &r.md
}
// Spec implements resource.Resource.
func (r *MachineType) Spec() interface{} {
return r.spec
}
func (r *MachineType) String() string {
return fmt.Sprintf("config.MachineType(%q)", r.md.ID())
}
// DeepCopy implements resource.Resource.
func (r *MachineType) DeepCopy() resource.Resource {
return &MachineType{
md: r.md,
spec: r.spec,
}
}
// ResourceDefinition implements core.ResourceDefinitionProvider interface.
func (r *MachineType) ResourceDefinition() core.ResourceDefinitionSpec {
return core.ResourceDefinitionSpec{
Type: MachineTypeType,
Aliases: []resource.Type{"machineType"},
DefaultNamespace: NamespaceName,
}
}
// MachineType returns machine.Type.
func (r *MachineType) MachineType() machine.Type {
return r.spec.Type
}
// SetMachineType sets machine.Type.
func (r *MachineType) SetMachineType(typ machine.Type) {
r.spec.Type = typ
}

View File

@ -0,0 +1,14 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Package k8s provides resources which interface with Kubernetes.
package k8s
import "github.com/talos-systems/os-runtime/pkg/resource"
// ControlPlaneNamespaceName contains resources supporting Kubernetes control plane.
const ControlPlaneNamespaceName resource.Namespace = "k8s/controlplane"
// ExtraNamespaceName contains extra resources related to Kubernnetes configuration.
const ExtraNamespaceName resource.Namespace = "k8s/extra"

View File

@ -0,0 +1,134 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package k8s
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/resource/core"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/yaml"
)
// ManifestType is type of Manifest resource.
const ManifestType = resource.Type("k8s/manifest")
// Manifest resource holds definition of kubelet static pod.
type Manifest struct {
md resource.Metadata
spec *manifestSpec
}
type manifestSpec struct {
Items []*unstructured.Unstructured
}
func (spec *manifestSpec) MarshalYAML() (interface{}, error) {
result := make([]map[string]interface{}, 0, len(spec.Items))
for _, obj := range spec.Items {
result = append(result, obj.Object)
}
return result, nil
}
// NewManifest initializes an empty Manifest resource.
func NewManifest(namespace resource.Namespace, id resource.ID) *Manifest {
r := &Manifest{
md: resource.NewMetadata(namespace, ManifestType, id, resource.VersionUndefined),
spec: &manifestSpec{},
}
r.md.BumpVersion()
return r
}
// Metadata implements resource.Resource.
func (r *Manifest) Metadata() *resource.Metadata {
return &r.md
}
// Spec implements resource.Resource.
func (r *Manifest) Spec() interface{} {
return r.spec
}
func (r *Manifest) String() string {
return fmt.Sprintf("k8s.Manifest(%q)", r.md.ID())
}
// DeepCopy implements resource.Resource.
func (r *Manifest) DeepCopy() resource.Resource {
spec := &manifestSpec{
Items: make([]*unstructured.Unstructured, len(r.spec.Items)),
}
for i := range r.spec.Items {
spec.Items[i] = r.spec.Items[i].DeepCopy()
}
return &Manifest{
md: r.md,
spec: spec,
}
}
// ResourceDefinition implements core.ResourceDefinitionProvider interface.
func (r *Manifest) ResourceDefinition() core.ResourceDefinitionSpec {
return core.ResourceDefinitionSpec{
Type: ManifestType,
Aliases: []resource.Type{"manifest", "manifests"},
DefaultNamespace: ControlPlaneNamespaceName,
}
}
// SetYAML parses manifest from YAML.
func (r *Manifest) SetYAML(yamlBytes []byte) error {
reader := yaml.NewYAMLReader(bufio.NewReader(bytes.NewReader(yamlBytes)))
for {
yamlManifest, err := reader.Read()
if err != nil {
if err == io.EOF {
break
}
return err
}
yamlManifest = bytes.TrimSpace(yamlManifest)
if len(yamlManifest) == 0 {
continue
}
jsonManifest, err := yaml.ToJSON(yamlManifest)
if err != nil {
return fmt.Errorf("error converting manifest to JSON: %w", err)
}
obj := new(unstructured.Unstructured)
if err = json.Unmarshal(jsonManifest, obj); err != nil {
return fmt.Errorf("error loading JSON manifest into unstructured: %w", err)
}
r.spec.Items = append(r.spec.Items, obj)
}
return nil
}
// Objects returns list of unstrustured object.
func (r *Manifest) Objects() []*unstructured.Unstructured {
return r.spec.Items
}

View File

@ -0,0 +1,77 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package k8s
import (
"fmt"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/resource/core"
)
// ManifestStatusType is type of ManifestStatus resource.
const ManifestStatusType = resource.Type("k8s/manifestStatus")
// ManifestStatusID is a singleton resource ID.
const ManifestStatusID = resource.ID("manifests")
// ManifestStatus resource holds definition of kubelet static pod.
type ManifestStatus struct {
md resource.Metadata
spec ManifestStatusSpec
}
// ManifestStatusSpec describes manifest application status.
type ManifestStatusSpec struct {
ManifestsApplied []string `yaml:"manifestsApplied"`
}
// NewManifestStatus initializes an empty ManifestStatus resource.
func NewManifestStatus(namespace resource.Namespace) *ManifestStatus {
r := &ManifestStatus{
md: resource.NewMetadata(namespace, ManifestStatusType, ManifestStatusID, resource.VersionUndefined),
spec: ManifestStatusSpec{},
}
r.md.BumpVersion()
return r
}
// Metadata implements resource.Resource.
func (r *ManifestStatus) Metadata() *resource.Metadata {
return &r.md
}
// Spec implements resource.Resource.
func (r *ManifestStatus) Spec() interface{} {
return r.spec
}
func (r *ManifestStatus) String() string {
return fmt.Sprintf("k8s.ManifestStatus(%q)", r.md.ID())
}
// DeepCopy implements resource.Resource.
func (r *ManifestStatus) DeepCopy() resource.Resource {
return &ManifestStatus{
md: r.md,
spec: r.spec,
}
}
// Status returns ManifestStatusSpec.
func (r *ManifestStatus) Status() *ManifestStatusSpec {
return &r.spec
}
// ResourceDefinition implements core.ResourceDefinitionProvider interface.
func (r *ManifestStatus) ResourceDefinition() core.ResourceDefinitionSpec {
return core.ResourceDefinitionSpec{
Type: ManifestStatusType,
Aliases: []resource.Type{"manifestStatus", "manifestStatuses"},
DefaultNamespace: ControlPlaneNamespaceName,
}
}

View File

@ -0,0 +1,78 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package k8s
import (
"fmt"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/resource/core"
)
// SecretsStatusType is type of SecretsStatus resource.
const SecretsStatusType = resource.Type("k8s/secretsStatus")
// StaticPodSecretsStaticPodID is resource ID for SecretStatus resource for static pods.
const StaticPodSecretsStaticPodID = resource.ID("staticPods")
// SecretsStatus resource holds definition of rendered secrets.
type SecretsStatus struct {
md resource.Metadata
spec SecretsStatusSpec
}
// SecretsStatusSpec describes status of rendered secrets.
type SecretsStatusSpec struct {
Ready bool `yaml:"ready"`
Version string `yaml:"version"`
}
// NewSecretsStatus initializes a SecretsStatus resource.
func NewSecretsStatus(namespace resource.Namespace, id resource.ID) *SecretsStatus {
r := &SecretsStatus{
md: resource.NewMetadata(namespace, SecretsStatusType, id, resource.VersionUndefined),
spec: SecretsStatusSpec{},
}
r.md.BumpVersion()
return r
}
// Metadata implements resource.Resource.
func (r *SecretsStatus) Metadata() *resource.Metadata {
return &r.md
}
// Spec implements resource.Resource.
func (r *SecretsStatus) Spec() interface{} {
return r.spec
}
func (r *SecretsStatus) String() string {
return fmt.Sprintf("k8s.SecretsStatus(%q)", r.md.ID())
}
// DeepCopy implements resource.Resource.
func (r *SecretsStatus) DeepCopy() resource.Resource {
return &SecretsStatus{
md: r.md,
spec: r.spec,
}
}
// ResourceDefinition implements core.ResourceDefinitionProvider interface.
func (r *SecretsStatus) ResourceDefinition() core.ResourceDefinitionSpec {
return core.ResourceDefinitionSpec{
Type: SecretsStatusType,
Aliases: []resource.Type{"secretStatus"},
DefaultNamespace: ControlPlaneNamespaceName,
}
}
// Status sets pod status.
func (r *SecretsStatus) Status() *SecretsStatusSpec {
return &r.spec
}

View File

@ -0,0 +1,92 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package k8s
import (
"encoding/json"
"fmt"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/resource/core"
v1 "k8s.io/api/core/v1"
)
// StaticPodType is type of StaticPod resource.
const StaticPodType = resource.Type("k8s/staticPod")
// StaticPod resource holds definition of kubelet static pod.
type StaticPod struct {
md resource.Metadata
spec *staticPodSpec
}
type staticPodSpec struct {
*v1.Pod
}
func (spec *staticPodSpec) MarshalYAML() (interface{}, error) {
jsonSerialized, err := json.Marshal(spec.Pod)
if err != nil {
return nil, err
}
var obj interface{}
err = json.Unmarshal(jsonSerialized, &obj)
return obj, err
}
// NewStaticPod initializes a StaticPod resource.
func NewStaticPod(namespace resource.Namespace, id resource.ID, spec *v1.Pod) *StaticPod {
r := &StaticPod{
md: resource.NewMetadata(namespace, StaticPodType, id, resource.VersionUndefined),
spec: &staticPodSpec{
Pod: spec,
},
}
r.md.BumpVersion()
return r
}
// Metadata implements resource.Resource.
func (r *StaticPod) Metadata() *resource.Metadata {
return &r.md
}
// Spec implements resource.Resource.
func (r *StaticPod) Spec() interface{} {
return r.spec
}
func (r *StaticPod) String() string {
return fmt.Sprintf("k8s.StaticPod(%q)", r.md.ID())
}
// DeepCopy implements resource.Resource.
func (r *StaticPod) DeepCopy() resource.Resource {
return &StaticPod{
md: r.md,
spec: &staticPodSpec{
Pod: r.spec.Pod.DeepCopy(),
},
}
}
// ResourceDefinition implements core.ResourceDefinitionProvider interface.
func (r *StaticPod) ResourceDefinition() core.ResourceDefinitionSpec {
return core.ResourceDefinitionSpec{
Type: StaticPodType,
Aliases: []resource.Type{"pod", "static-pod", "pods"},
DefaultNamespace: ControlPlaneNamespaceName,
}
}
// SetPod sets pod definition.
func (r *StaticPod) SetPod(podSpec *v1.Pod) {
r.spec.Pod = podSpec
}

View File

@ -0,0 +1,91 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package k8s
import (
"encoding/json"
"fmt"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/resource/core"
v1 "k8s.io/api/core/v1"
)
// StaticPodStatusType is type of StaticPodStatus resource.
const StaticPodStatusType = resource.Type("k8s/staticPodStatus")
// StaticPodStatus resource holds definition of kubelet static pod.
type StaticPodStatus struct {
md resource.Metadata
spec *staticPodStatusSpec
}
// staticPodStatusSpec describes kubelet static pod status.
type staticPodStatusSpec struct {
*v1.PodStatus
}
func (spec *staticPodStatusSpec) MarshalYAML() (interface{}, error) {
jsonSerialized, err := json.Marshal(spec.PodStatus)
if err != nil {
return nil, err
}
var obj interface{}
err = json.Unmarshal(jsonSerialized, &obj)
return obj, err
}
// NewStaticPodStatus initializes a StaticPodStatus resource.
func NewStaticPodStatus(namespace resource.Namespace, id resource.ID) *StaticPodStatus {
r := &StaticPodStatus{
md: resource.NewMetadata(namespace, StaticPodStatusType, id, resource.VersionUndefined),
spec: &staticPodStatusSpec{},
}
r.md.BumpVersion()
return r
}
// Metadata implements resource.Resource.
func (r *StaticPodStatus) Metadata() *resource.Metadata {
return &r.md
}
// Spec implements resource.Resource.
func (r *StaticPodStatus) Spec() interface{} {
return r.spec
}
func (r *StaticPodStatus) String() string {
return fmt.Sprintf("k8s.StaticPodStatus(%q)", r.md.ID())
}
// DeepCopy implements resource.Resource.
func (r *StaticPodStatus) DeepCopy() resource.Resource {
return &StaticPodStatus{
md: r.md,
spec: &staticPodStatusSpec{
PodStatus: r.spec.PodStatus.DeepCopy(),
},
}
}
// ResourceDefinition implements core.ResourceDefinitionProvider interface.
func (r *StaticPodStatus) ResourceDefinition() core.ResourceDefinitionSpec {
return core.ResourceDefinitionSpec{
Type: StaticPodStatusType,
Aliases: []resource.Type{"podStatus"},
DefaultNamespace: ControlPlaneNamespaceName,
}
}
// SetStatus sets pod status.
func (r *StaticPodStatus) SetStatus(status *v1.PodStatus) {
r.spec.PodStatus = status
}

View File

@ -0,0 +1,93 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package secrets
import (
"fmt"
"github.com/talos-systems/crypto/x509"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/resource/core"
)
// KubernetesType is type of Kubernetes resource.
const KubernetesType = resource.Type("secrets/kubernetes")
// KubernetesID is ID of the singleton instance.
const KubernetesID = resource.ID("kubernetes")
// Kubernetes contains K8s secrets.
type Kubernetes struct {
md resource.Metadata
spec KubernetesSpec
}
// KubernetesSpec describes Kubernetes resources.
type KubernetesSpec struct {
EtcdCA *x509.PEMEncodedCertificateAndKey `yaml:"etcdCA"`
EtcdPeer *x509.PEMEncodedCertificateAndKey `yaml:"etcdPeer"`
CA *x509.PEMEncodedCertificateAndKey `yaml:"ca"`
APIServer *x509.PEMEncodedCertificateAndKey `yaml:"apiServer"`
APIServerKubeletClient *x509.PEMEncodedCertificateAndKey `yaml:"apiServerKubeletClient"`
ServiceAccount *x509.PEMEncodedKey `yaml:"serviceAccount"`
AggregatorCA *x509.PEMEncodedCertificateAndKey `yaml:"aggregatorCA"`
FrontProxy *x509.PEMEncodedCertificateAndKey `yaml:"frontProxy"`
AESCBCEncryptionSecret string `yaml:"aesCBCEncryptionSecret"`
AdminKubeconfig string `yaml:"adminKubeconfig"`
BootstrapTokenID string `yaml:"bootstrapTokenID"`
BootstrapTokenSecret string `yaml:"bootstrapTokenSecret"`
}
// NewKubernetes initializes a Kubernetes resource.
func NewKubernetes() *Kubernetes {
r := &Kubernetes{
md: resource.NewMetadata(NamespaceName, KubernetesType, KubernetesID, resource.VersionUndefined),
spec: KubernetesSpec{},
}
r.md.BumpVersion()
return r
}
// Metadata implements resource.Resource.
func (r *Kubernetes) Metadata() *resource.Metadata {
return &r.md
}
// Spec implements resource.Resource.
func (r *Kubernetes) Spec() interface{} {
return r.spec
}
func (r *Kubernetes) String() string {
return fmt.Sprintf("secrets.Kubernetes(%q)", r.md.ID())
}
// DeepCopy implements resource.Resource.
func (r *Kubernetes) DeepCopy() resource.Resource {
return &Kubernetes{
md: r.md,
spec: r.spec,
}
}
// ResourceDefinition implements core.ResourceDefinitionProvider interface.
func (r *Kubernetes) ResourceDefinition() core.ResourceDefinitionSpec {
return core.ResourceDefinitionSpec{
Type: KubernetesType,
Aliases: []resource.Type{"secrets", "secret"},
DefaultNamespace: NamespaceName,
}
}
// Secrets returns .spec.
func (r *Kubernetes) Secrets() *KubernetesSpec {
return &r.spec
}

View File

@ -0,0 +1,11 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Package secrets provides resources which store secrets.
package secrets
import "github.com/talos-systems/os-runtime/pkg/resource"
// NamespaceName contains resources containing secret material.
const NamespaceName resource.Namespace = "secrets"

View File

@ -0,0 +1,77 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package v1alpha1
import (
"fmt"
"github.com/talos-systems/os-runtime/pkg/resource"
"github.com/talos-systems/os-runtime/pkg/resource/core"
)
// BootstrapStatusType is type of BootstrapStatus resource.
const BootstrapStatusType = resource.Type("v1alpha1/bootstrapStatus")
// BootstrapStatusID is a singleton instance ID.
const BootstrapStatusID = resource.ID("bootstrapStatus")
// BootstrapStatus describes v1alpha1 (bootkube) bootstrap status.
type BootstrapStatus struct {
md resource.Metadata
spec BootstrapStatusSpec
}
// BootstrapStatusSpec describe service state.
type BootstrapStatusSpec struct {
SelfHostedControlPlane bool `yaml:"selfHostedControlPlane"`
}
// NewBootstrapStatus initializes a BootstrapStatus resource.
func NewBootstrapStatus() *BootstrapStatus {
r := &BootstrapStatus{
md: resource.NewMetadata(NamespaceName, BootstrapStatusType, BootstrapStatusID, resource.VersionUndefined),
spec: BootstrapStatusSpec{},
}
r.md.BumpVersion()
return r
}
// Metadata implements resource.Resource.
func (r *BootstrapStatus) Metadata() *resource.Metadata {
return &r.md
}
// Spec implements resource.Resource.
func (r *BootstrapStatus) Spec() interface{} {
return r.spec
}
func (r *BootstrapStatus) String() string {
return fmt.Sprintf("v1alpha1.BootstrapStatus(%q)", r.md.ID())
}
// DeepCopy implements resource.Resource.
func (r *BootstrapStatus) DeepCopy() resource.Resource {
return &BootstrapStatus{
md: r.md,
spec: r.spec,
}
}
// ResourceDefinition implements core.ResourceDefinitionProvider interface.
func (r *BootstrapStatus) ResourceDefinition() core.ResourceDefinitionSpec {
return core.ResourceDefinitionSpec{
Type: BootstrapStatusType,
Aliases: []resource.Type{"bootstrapStatus"},
DefaultNamespace: NamespaceName,
}
}
// Status returns .spec.
func (r *BootstrapStatus) Status() *BootstrapStatusSpec {
return &r.spec
}

View File

@ -73,3 +73,18 @@ func (r *Service) ResourceDefinition() core.ResourceDefinitionSpec {
func (r *Service) SetRunning(running bool) {
r.spec.Running = true
}
// SetHealthy changes .spec.healthy.
func (r *Service) SetHealthy(healthy bool) {
r.spec.Healthy = true
}
// Running returns .spec.running.
func (r *Service) Running() bool {
return r.spec.Running
}
// Healthy returns .spec.healthy.
func (r *Service) Healthy() bool {
return r.spec.Healthy
}

View File

@ -7,6 +7,8 @@ package runtime
import (
"context"
"log"
"github.com/talos-systems/os-runtime/pkg/controller"
)
// TaskSetupFunc defines the function that a task will execute for a specific runtime
@ -57,4 +59,5 @@ type Controller interface {
// V1Alpha2Controller provides glue into v2alpha1 controller runtime.
type V1Alpha2Controller interface {
Run(context.Context) error
DependencyGraph() (*controller.DependencyGraph, error)
}

View File

@ -34,8 +34,6 @@ const (
SequenceReset
// SequenceReboot is the reboot sequence.
SequenceReboot
// SequenceRecover is the recover sequence.
SequenceRecover
// SequenceNoop is the noop sequence.
SequenceNoop
)
@ -51,13 +49,12 @@ const (
stageUpgrade = "stageUpgrade"
reset = "reset"
reboot = "reboot"
recover = "recover"
noop = "noop"
)
// String returns the string representation of a `Sequence`.
func (s Sequence) String() string {
return [...]string{applyConfiguration, boot, bootstrap, initialize, install, shutdown, upgrade, stageUpgrade, reset, reboot, recover, noop}[s]
return [...]string{applyConfiguration, boot, bootstrap, initialize, install, shutdown, upgrade, stageUpgrade, reset, reboot, noop}[s]
}
// ParseSequence returns a `Sequence` that matches the specified string.
@ -85,8 +82,6 @@ func ParseSequence(s string) (seq Sequence, err error) {
seq = SequenceReset
case reboot:
seq = SequenceReboot
case recover:
seq = SequenceRecover
case noop:
seq = SequenceNoop
default:
@ -118,7 +113,6 @@ type Sequencer interface {
Initialize(Runtime) []Phase
Install(Runtime) []Phase
Reboot(Runtime) []Phase
Recover(Runtime, *machine.RecoverRequest) []Phase
Reset(Runtime, ResetOptions) []Phase
Shutdown(Runtime) []Phase
StageUpgrade(Runtime, *machine.UpgradeRequest) []Phase

View File

@ -52,11 +52,6 @@ func TestSequence_String(t *testing.T) {
s: runtime.SequenceReset,
want: "reset",
},
{
name: "recover",
s: runtime.SequenceRecover,
want: "recover",
},
}
for _, tt := range tests {
@ -121,12 +116,6 @@ func TestParseSequence(t *testing.T) {
wantSeq: runtime.SequenceReset,
wantErr: false,
},
{
name: "recover",
args: args{"recover"},
wantSeq: runtime.SequenceRecover,
wantErr: false,
},
{
name: "invalid",
args: args{"invalid"},

View File

@ -101,7 +101,7 @@ func (c *Controller) Run(seq runtime.Sequence, data interface{}, setters ...runt
// Allow only one sequence to run at a time with the exception of bootstrap
// and reset sequences.
switch seq { //nolint: exhaustive
case runtime.SequenceBootstrap, runtime.SequenceReset, runtime.SequenceRecover:
case runtime.SequenceBootstrap, runtime.SequenceReset:
// Do not attempt to lock.
default:
if opts.Force {
@ -373,17 +373,6 @@ func (c *Controller) phases(seq runtime.Sequence, data interface{}) ([]runtime.P
phases = c.s.Shutdown(c.r)
case runtime.SequenceReboot:
phases = c.s.Reboot(c.r)
case runtime.SequenceRecover:
var (
in *machine.RecoverRequest
ok bool
)
if in, ok = data.(*machine.RecoverRequest); !ok {
return nil, runtime.ErrInvalidSequenceData
}
phases = c.s.Recover(c.r, in)
case runtime.SequenceUpgrade:
var (
in *machine.UpgradeRequest

View File

@ -266,12 +266,6 @@ func (*Sequencer) Bootstrap(r runtime.Runtime) []runtime.Phase {
phases = phases.Append(
"etcd",
BootstrapEtcd,
).Append(
"kubernetes",
BootstrapKubernetes,
).Append(
"initStatus",
SetInitStatus,
)
return phases
@ -285,15 +279,6 @@ func (*Sequencer) Reboot(r runtime.Runtime) []runtime.Phase {
return phases
}
// Recover is the recover sequence.
func (*Sequencer) Recover(r runtime.Runtime, in *machineapi.RecoverRequest) []runtime.Phase {
phases := PhaseList{}
phases = phases.Append("recover", Recover)
return phases
}
// Reset is the reset sequence.
func (*Sequencer) Reset(r runtime.Runtime, in runtime.ResetOptions) []runtime.Phase {
phases := PhaseList{}

View File

@ -31,7 +31,6 @@ import (
"github.com/talos-systems/go-blockdevice/blockdevice/util"
"github.com/talos-systems/go-procfs/procfs"
"github.com/talos-systems/go-retry/retry"
"go.etcd.io/etcd/clientv3"
"golang.org/x/sys/unix"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
@ -53,7 +52,6 @@ import (
"github.com/talos-systems/talos/internal/pkg/etcd"
"github.com/talos-systems/talos/internal/pkg/kernel/kspp"
"github.com/talos-systems/talos/internal/pkg/kmsg"
"github.com/talos-systems/talos/internal/pkg/kubeconfig"
"github.com/talos-systems/talos/internal/pkg/mount"
"github.com/talos-systems/talos/pkg/cmd"
"github.com/talos-systems/talos/pkg/conditions"
@ -709,7 +707,6 @@ func StartAllServices(seq runtime.Sequence, data interface{}) (runtime.TaskExecu
svcs.Load(
&services.Trustd{},
&services.Etcd{Bootstrap: true},
&services.Bootkube{},
)
case machine.TypeControlPlane:
svcs.Load(
@ -732,8 +729,7 @@ func StartAllServices(seq runtime.Sequence, data interface{}) (runtime.TaskExecu
all = append(all, cond)
}
ctx, cancel := context.WithTimeout(ctx, constants.BootkubeRunTimeout)
ctx, cancel := context.WithTimeout(ctx, constants.BootTimeout)
defer cancel()
return conditions.WaitForAll(all...).Wait(ctx)
@ -1662,56 +1658,6 @@ func Install(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc,
}, "install"
}
// Recover attempts to recover the control plane.
//
// nolint: gocyclo
func Recover(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
var (
in *machineapi.RecoverRequest
ok bool
)
if in, ok = data.(*machineapi.RecoverRequest); !ok {
return runtime.ErrInvalidSequenceData
}
var b bytes.Buffer
if err = kubeconfig.GenerateAdmin(r.Config().Cluster(), &b); err != nil {
return err
}
if err = ioutil.WriteFile(constants.RecoveryKubeconfig, b.Bytes(), 0o600); err != nil {
return fmt.Errorf("failed to create recovery kubeconfig: %w", err)
}
// nolint: errcheck
defer os.Remove(constants.RecoveryKubeconfig)
svc := &services.Bootkube{
Recover: true,
Source: in.Source,
}
// unload bootkube (if any instance ran before)
if err = system.Services(r).Unload(ctx, svc.ID(r)); err != nil {
return err
}
system.Services(r).Load(svc)
if err = system.Services(r).Start(svc.ID(r)); err != nil {
return fmt.Errorf("failed to start bootkube: %w", err)
}
ctx, cancel := context.WithTimeout(ctx, 10*time.Minute)
defer cancel()
return system.WaitForService(system.StateEventFinished, svc.ID(r)).Wait(ctx)
}, "recover"
}
// BootstrapEtcd represents the task for bootstrapping etcd.
func BootstrapEtcd(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
@ -1771,50 +1717,6 @@ func BootstrapEtcd(seq runtime.Sequence, data interface{}) (runtime.TaskExecutio
}, "bootstrapEtcd"
}
// BootstrapKubernetes represents the task for bootstrapping Kubernetes.
func BootstrapKubernetes(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
svc := &services.Bootkube{}
system.Services(r).LoadAndStart(svc)
ctx, cancel := context.WithTimeout(ctx, constants.BootkubeRunTimeout)
defer cancel()
return system.WaitForService(system.StateEventFinished, svc.ID(r)).Wait(ctx)
}, "bootstrapKubernetes"
}
// SetInitStatus represents the task for setting the initialization status
// in etcd.
func SetInitStatus(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
client, err := etcd.NewClient([]string{"127.0.0.1:2379"})
if err != nil {
return err
}
// nolint: errcheck
defer client.Close()
err = retry.Exponential(15*time.Second, retry.WithUnits(50*time.Millisecond), retry.WithJitter(25*time.Millisecond)).Retry(func() error {
ctx := clientv3.WithRequireLeader(context.Background())
if _, err = client.Put(ctx, constants.InitializedKey, "true"); err != nil {
return retry.ExpectedError(err)
}
return nil
})
if err != nil {
return fmt.Errorf("failed to put state into etcd: %w", err)
}
logger.Println("updated initialization status in etcd")
return nil
}, "SetInitStatus"
}
// ActivateLogicalVolumes represents the task for activating logical volumes.
func ActivateLogicalVolumes(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {

View File

@ -11,6 +11,9 @@ import (
"github.com/talos-systems/os-runtime/pkg/controller"
osruntime "github.com/talos-systems/os-runtime/pkg/controller/runtime"
"github.com/talos-systems/talos/internal/app/machined/pkg/controllers/config"
"github.com/talos-systems/talos/internal/app/machined/pkg/controllers/k8s"
"github.com/talos-systems/talos/internal/app/machined/pkg/controllers/secrets"
"github.com/talos-systems/talos/internal/app/machined/pkg/controllers/v1alpha1"
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
)
@ -33,7 +36,7 @@ func NewController(v1alpha1Runtime runtime.Runtime, loggingManager runtime.Loggi
return nil, err
}
logger := log.New(logWriter, "controller-runtime: ", log.Flags())
logger := log.New(logWriter, "", log.LstdFlags|log.Lmsgprefix)
ctrl.controllerRuntime, err = osruntime.NewRuntime(v1alpha1Runtime.State().V1Alpha2().Resources(), logger)
@ -43,10 +46,20 @@ func NewController(v1alpha1Runtime runtime.Runtime, loggingManager runtime.Loggi
// Run the controller runtime.
func (ctrl *Controller) Run(ctx context.Context) error {
for _, c := range []controller.Controller{
&v1alpha1.BootstrapStatusController{},
&v1alpha1.ServiceController{
// V1Events
V1Alpha1Events: ctrl.v1alpha1Runtime.Events(),
},
&config.MachineTypeController{},
&config.K8sControlPlaneController{},
&k8s.ControlPlaneStaticPodController{},
&k8s.ExtraManifestController{},
&k8s.KubeletStaticPodController{},
&k8s.ManifestController{},
&k8s.ManifestApplyController{},
&k8s.RenderSecretsStaticPodController{},
&secrets.KubernetesController{},
} {
if err := ctrl.controllerRuntime.RegisterController(c); err != nil {
return err
@ -55,3 +68,8 @@ func (ctrl *Controller) Run(ctx context.Context) error {
return ctrl.controllerRuntime.Run(ctx)
}
// DependencyGraph returns controller-resources dependencies.
func (ctrl *Controller) DependencyGraph() (*controller.DependencyGraph, error) {
return ctrl.controllerRuntime.GetDependencyGraph()
}

View File

@ -14,6 +14,8 @@ import (
"github.com/talos-systems/os-runtime/pkg/state/registry"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/config"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/k8s"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/secrets"
"github.com/talos-systems/talos/internal/app/machined/pkg/resources/v1alpha1"
talosconfig "github.com/talos-systems/talos/pkg/machinery/config"
)
@ -53,10 +55,31 @@ func NewState() (*State, error) {
return nil, err
}
if err := s.namespaceRegistry.Register(ctx, k8s.ControlPlaneNamespaceName, "Kubernetes control plane resources.", true); err != nil {
return nil, err
}
if err := s.namespaceRegistry.Register(ctx, k8s.ExtraNamespaceName, "Kubernetes extra configuration resources.", true); err != nil {
return nil, err
}
if err := s.namespaceRegistry.Register(ctx, secrets.NamespaceName, "Resources with secret material.", true); err != nil {
return nil, err
}
// register Talos resources
for _, r := range []resource.Resource{
&v1alpha1.BootstrapStatus{},
&v1alpha1.Service{},
&config.V1Alpha1{},
&config.MachineType{},
&config.K8sControlPlane{},
&k8s.Manifest{},
&k8s.ManifestStatus{},
&k8s.StaticPod{},
&k8s.StaticPodStatus{},
&k8s.SecretsStatus{},
&secrets.Kubernetes{},
} {
if err := s.resourceRegistry.Register(ctx, r); err != nil {
return nil, err

View File

@ -9,6 +9,7 @@ import (
"github.com/golang/protobuf/ptypes"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/health"
machineapi "github.com/talos-systems/talos/pkg/machinery/api/machine"
)
@ -57,6 +58,7 @@ func (state ServiceState) String() string {
type ServiceEvent struct {
Message string
State ServiceState
Health health.Status
Timestamp time.Time
}
@ -66,6 +68,7 @@ func (event *ServiceEvent) AsProto(service string) *machineapi.ServiceStateEvent
Service: service,
Action: machineapi.ServiceStateEvent_Action(event.State),
Message: event.Message,
Health: event.Health.AsProto(),
}
}

View File

@ -20,6 +20,19 @@ type Status struct {
LastMessage string
}
// AsProto returns protobuf-ready health state.
func (status *Status) AsProto() *machineapi.ServiceHealth {
// nolint: errcheck
tspb, _ := ptypes.TimestampProto(status.LastChange)
return &machineapi.ServiceHealth{
Unknown: status.Healthy == nil,
Healthy: status.Healthy != nil && *status.Healthy,
LastMessage: status.LastMessage,
LastChange: tspb,
}
}
// StateChange is used to notify about status changes.
type StateChange struct {
Old Status
@ -114,13 +127,5 @@ func (state *State) Get() Status {
func (state *State) AsProto() *machineapi.ServiceHealth {
status := state.Get()
// nolint: errcheck
tspb, _ := ptypes.TimestampProto(status.LastChange)
return &machineapi.ServiceHealth{
Unknown: status.Healthy == nil,
Healthy: status.Healthy != nil && *status.Healthy,
LastMessage: status.LastMessage,
LastChange: tspb,
}
return status.AsProto()
}

View File

@ -125,6 +125,7 @@ func (svcrunner *ServiceRunner) healthUpdate(change health.StateChange) {
event := events.ServiceEvent{
Message: message,
State: svcrunner.state,
Health: change.New,
Timestamp: time.Now(),
}
svcrunner.events.Push(event)
@ -137,6 +138,10 @@ func (svcrunner *ServiceRunner) healthUpdate(change health.StateChange) {
if isUp {
svcrunner.notifyEvent(StateEventUp)
}
if svcrunner.runtime != nil {
svcrunner.runtime.Events().Publish(event.AsProto(svcrunner.id))
}
}
// GetEventHistory returns history of events for this service.

View File

@ -1,198 +0,0 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package services
import (
"bytes"
"context"
"errors"
"fmt"
"log"
"strconv"
"time"
"github.com/containerd/containerd/oci"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/talos-systems/go-retry/retry"
"go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/events"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner"
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner/containerd"
"github.com/talos-systems/talos/internal/pkg/containers/image"
"github.com/talos-systems/talos/internal/pkg/etcd"
"github.com/talos-systems/talos/pkg/conditions"
machineapi "github.com/talos-systems/talos/pkg/machinery/api/machine"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// Bootkube implements the Service interface. It serves as the concrete type with
// the required methods.
type Bootkube struct {
Source machineapi.RecoverRequest_Source
Recover bool
provisioned bool
}
// ID implements the Service interface.
func (b *Bootkube) ID(r runtime.Runtime) string {
return "bootkube"
}
// PreFunc implements the Service interface.
func (b *Bootkube) PreFunc(ctx context.Context, r runtime.Runtime) (err error) {
if !b.Recover {
client, err := etcd.NewClient([]string{"127.0.0.1:2379"})
if err != nil {
return err
}
// nolint: errcheck
defer client.Close()
err = retry.Exponential(3*time.Minute, retry.WithUnits(50*time.Millisecond), retry.WithJitter(25*time.Millisecond)).Retry(func() error {
var resp *clientv3.GetResponse
// limit single attempt to 15 seconds to allow for 12 attempts at least
attemptCtx, attemptCtxCancel := context.WithTimeout(ctx, 15*time.Second)
defer attemptCtxCancel()
if resp, err = client.Get(clientv3.WithRequireLeader(attemptCtx), constants.InitializedKey); err != nil {
if errors.Is(err, rpctypes.ErrGRPCKeyNotFound) {
// no key set yet, treat as not provisioned yet
return nil
}
return retry.ExpectedError(err)
}
if len(resp.Kvs) == 0 {
// no key/values in the range, treat as not provisioned yet
return nil
}
if string(resp.Kvs[0].Value) == "true" {
b.provisioned = true
}
return nil
})
if err != nil {
return fmt.Errorf("error querying cluster provisioned state in etcd: %w", err)
}
if b.provisioned {
return nil
}
}
return image.Import(ctx, "/usr/images/bootkube.tar", "talos/bootkube")
}
// PostFunc implements the Service interface.
//
// This is temorary and should be removed once we remove the init node type.
func (b *Bootkube) PostFunc(r runtime.Runtime, state events.ServiceState) (err error) {
if r.Config().Machine().Type() != machine.TypeInit {
return nil
}
if state != events.StateFinished {
log.Println("bootkube run did not complete successfully. skipping etcd update")
return nil
}
client, err := etcd.NewClient([]string{"127.0.0.1:2379"})
if err != nil {
return err
}
// nolint: errcheck
defer client.Close()
err = retry.Exponential(15*time.Second, retry.WithUnits(50*time.Millisecond), retry.WithJitter(25*time.Millisecond)).Retry(func() error {
ctx := clientv3.WithRequireLeader(context.Background())
if _, err = client.Put(ctx, constants.InitializedKey, "true"); err != nil {
return retry.ExpectedError(err)
}
return nil
})
if err != nil {
return fmt.Errorf("failed to put state into etcd: %w", err)
}
log.Println("updated initialization status in etcd")
return nil
}
// DependsOn implements the Service interface.
func (b *Bootkube) DependsOn(r runtime.Runtime) []string {
return []string{"etcd", "kubelet"}
}
// Condition implements the Service interface.
func (b *Bootkube) Condition(r runtime.Runtime) conditions.Condition {
return nil
}
// Runner implements the Service interface.
func (b *Bootkube) Runner(r runtime.Runtime) (runner.Runner, error) {
if b.provisioned {
return nil, nil
}
image := "talos/bootkube"
// Set the process arguments.
args := runner.Args{
ID: b.ID(r),
ProcessArgs: []string{
"/bootkube",
"--strict=" + strconv.FormatBool(!b.Recover),
"--recover=" + strconv.FormatBool(b.Recover),
"--recover-source=" + b.Source.String(),
},
}
env := []string{}
for key, val := range r.Config().Machine().Env() {
env = append(env, fmt.Sprintf("%s=%s", key, val))
}
// Set the required kubelet mounts.
mounts := []specs.Mount{
{Type: "bind", Destination: "/etc/ssl", Source: "/etc/ssl", Options: []string{"bind", "ro"}},
{Type: "bind", Destination: "/etc/kubernetes", Source: "/etc/kubernetes", Options: []string{"bind", "rshared", "rw"}},
}
bb, err := r.Config().Bytes()
if err != nil {
return nil, err
}
stdin := bytes.NewReader(bb)
return containerd.NewRunner(
r.Config().Debug(),
&args,
runner.WithStdin(stdin),
runner.WithLoggingManager(r.Logging()),
runner.WithContainerdAddress(constants.SystemContainerdAddress),
runner.WithContainerImage(image),
runner.WithEnv(env),
runner.WithOCISpecOpts(
oci.WithHostNamespace(specs.NetworkNamespace),
oci.WithMounts(mounts),
),
), nil
}

View File

@ -6,13 +6,10 @@ package services
import (
"context"
stdlibx509 "crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io"
"io/ioutil"
stdlibnet "net"
"os"
goruntime "runtime"
"strings"
@ -22,7 +19,6 @@ import (
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/oci"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/talos-systems/crypto/x509"
"github.com/talos-systems/go-retry/retry"
"github.com/talos-systems/net"
"go.etcd.io/etcd/clientv3"
@ -186,7 +182,6 @@ func (e *Etcd) HealthSettings(runtime.Runtime) *health.Settings {
}
}
// nolint: gocyclo
func generatePKI(r runtime.Runtime) (err error) {
if err = os.MkdirAll(constants.EtcdPKIPath, 0o644); err != nil {
return err
@ -200,96 +195,16 @@ func generatePKI(r runtime.Runtime) (err error) {
return fmt.Errorf("failed to write CA key: %w", err)
}
ips, err := net.IPAddrs()
certAndKey, err := etcd.GeneratePeerCert(r.Config().Cluster().Etcd().CA())
if err != nil {
return fmt.Errorf("failed to discover IP addresses: %w", err)
}
ips = append(ips, stdlibnet.ParseIP("127.0.0.1"))
if net.IsIPv6(ips...) {
ips = append(ips, stdlibnet.ParseIP("::1"))
}
hostname, err := os.Hostname()
if err != nil {
return fmt.Errorf("failed to get hostname: %w", err)
}
dnsNames, err := net.DNSNames()
if err != nil {
return fmt.Errorf("failed to get host DNS names: %w", err)
}
dnsNames = append(dnsNames, "localhost")
opts := []x509.Option{
x509.CommonName(hostname),
x509.DNSNames(dnsNames),
x509.RSA(true),
x509.IPAddresses(ips),
x509.NotAfter(time.Now().Add(87600 * time.Hour)),
}
peerKey, err := x509.NewRSAKey()
if err != nil {
return fmt.Errorf("failled to create RSA key: %w", err)
}
pemBlock, _ := pem.Decode(peerKey.KeyPEM)
if pemBlock == nil {
return errors.New("failed to decode peer key pem")
}
peerKeyRSA, err := stdlibx509.ParsePKCS1PrivateKey(pemBlock.Bytes)
if err != nil {
return fmt.Errorf("failled to parse private key: %w", err)
}
csr, err := x509.NewCertificateSigningRequest(peerKeyRSA, opts...)
if err != nil {
return fmt.Errorf("failed to create CSR: %w", err)
}
csrPemBlock, _ := pem.Decode(csr.X509CertificateRequestPEM)
if csrPemBlock == nil {
return errors.New("failed to decode csr pem")
}
ccsr, err := stdlibx509.ParseCertificateRequest(csrPemBlock.Bytes)
if err != nil {
return fmt.Errorf("failled to parse certificate request: %w", err)
}
caPemBlock, _ := pem.Decode(r.Config().Cluster().Etcd().CA().Crt)
if caPemBlock == nil {
return errors.New("failed to decode ca cert pem")
}
caCrt, err := stdlibx509.ParseCertificate(caPemBlock.Bytes)
if err != nil {
return fmt.Errorf("failed to parse CA: %w", err)
}
caKeyPemBlock, _ := pem.Decode(r.Config().Cluster().Etcd().CA().Key)
if caKeyPemBlock == nil {
return errors.New("failed to decode ca key pem")
}
caKey, err := stdlibx509.ParsePKCS1PrivateKey(caKeyPemBlock.Bytes)
if err != nil {
return fmt.Errorf("failed to parse CA private key: %w", err)
}
peer, err := x509.NewCertificateFromCSR(caCrt, caKey, ccsr, opts...)
if err != nil {
return fmt.Errorf("failled to create peer certificate: %w", err)
}
if err := ioutil.WriteFile(constants.KubernetesEtcdPeerKey, peerKey.KeyPEM, 0o500); err != nil {
return err
}
if err := ioutil.WriteFile(constants.KubernetesEtcdPeerCert, peer.X509CertificatePEM, 0o500); err != nil {
if err := ioutil.WriteFile(constants.KubernetesEtcdPeerKey, certAndKey.Key, 0o500); err != nil {
return err
}
if err := ioutil.WriteFile(constants.KubernetesEtcdPeerCert, certAndKey.Crt, 0o500); err != nil {
return err
}

View File

@ -10,11 +10,9 @@ import (
"encoding/base64"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
"path/filepath"
"strings"
"text/template"
"time"
@ -24,7 +22,6 @@ import (
criconstants "github.com/containerd/cri/pkg/constants"
cni "github.com/containerd/go-cni"
specs "github.com/opencontainers/runtime-spec/specs-go"
tnet "github.com/talos-systems/net"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
kubeletconfig "k8s.io/kubelet/config/v1beta1"
@ -244,9 +241,9 @@ func newKubeletConfiguration(clusterDNS []string, dnsDomain string) *kubeletconf
APIVersion: "kubelet.config.k8s.io/v1beta1",
Kind: "KubeletConfiguration",
},
StaticPodPath: "/etc/kubernetes/manifests",
StaticPodPath: constants.ManifestsDirectory,
Address: "0.0.0.0",
Port: 10250,
Port: constants.KubeletPort,
RotateCertificates: true,
Authentication: kubeletconfig.KubeletAuthentication{
X509: kubeletconfig.KubeletX509Authentication{
@ -278,7 +275,7 @@ func (k *Kubelet) args(r runtime.Runtime) ([]string, error) {
"config": "/etc/kubernetes/kubelet.yaml",
"dynamic-config-dir": "/etc/kubernetes/kubelet",
"cert-dir": "/var/lib/kubelet/pki",
"cert-dir": constants.KubeletPKIDir,
"cni-conf-dir": cni.DefaultNetDir,
}
@ -294,23 +291,18 @@ func (k *Kubelet) args(r runtime.Runtime) ([]string, error) {
}
func writeKubeletConfig(r runtime.Runtime) error {
dnsServiceIPs := []string{}
for _, cidr := range strings.Split(r.Config().Cluster().Network().ServiceCIDR(), ",") {
_, svcCIDR, err := net.ParseCIDR(cidr)
if err != nil {
return fmt.Errorf("failed to parse service CIDR %s: %v", cidr, err)
}
dnsIP, err := tnet.NthIPInNetwork(svcCIDR, 10)
if err != nil {
return fmt.Errorf("failed to calculate Nth IP in CIDR %s: %v", svcCIDR, err)
}
dnsServiceIPs = append(dnsServiceIPs, dnsIP.String())
dnsServiceIPs, err := r.Config().Cluster().Network().DNSServiceIPs()
if err != nil {
return fmt.Errorf("failed to get DNS service IPs: %w", err)
}
kubeletConfiguration := newKubeletConfiguration(dnsServiceIPs, r.Config().Cluster().Network().DNSDomain())
dnsServiceIPsString := make([]string, 0, len(dnsServiceIPs))
for _, dnsIP := range dnsServiceIPs {
dnsServiceIPsString = append(dnsServiceIPsString, dnsIP.String())
}
kubeletConfiguration := newKubeletConfiguration(dnsServiceIPsString, r.Config().Cluster().Network().DNSDomain())
serializer := json.NewSerializerWithOptions(
json.DefaultMetaFactory,

View File

@ -31,6 +31,7 @@ func main() {
router.RegisterLocalBackend("os.OSService", machinedBackend)
router.RegisterLocalBackend("machine.MachineService", machinedBackend)
router.RegisterLocalBackend("resource.ResourceService", machinedBackend)
router.RegisterLocalBackend("inspect.InspectService", machinedBackend)
router.RegisterLocalBackend("time.TimeService", backend.NewLocal("timed", constants.TimeSocketPath))
router.RegisterLocalBackend("network.NetworkService", backend.NewLocal("networkd", constants.NetworkSocketPath))
router.RegisterLocalBackend("cluster.ClusterService", machinedBackend)

View File

@ -1,147 +0,0 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// +build integration_api
package api
import (
"context"
"sort"
"testing"
"time"
"golang.org/x/sync/errgroup"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/talos-systems/talos/internal/integration/base"
machineapi "github.com/talos-systems/talos/pkg/machinery/api/machine"
"github.com/talos-systems/talos/pkg/machinery/client"
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine"
)
// RecoverSuite ...
type RecoverSuite struct {
base.K8sSuite
ctx context.Context
ctxCancel context.CancelFunc
}
// SuiteName ...
func (suite *RecoverSuite) SuiteName() string {
return "api.RecoverSuite"
}
// SetupTest ...
func (suite *RecoverSuite) SetupTest() {
if testing.Short() {
suite.T().Skip("skipping in short mode")
}
// make sure we abort at some point in time, but give enough room for Recovers
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 30*time.Minute)
}
// TearDownTest ...
func (suite *RecoverSuite) TearDownTest() {
if suite.ctxCancel != nil {
suite.ctxCancel()
}
}
// TestRecoverControlPlane removes the control plane components and attempts to recover them with the recover API.
func (suite *RecoverSuite) TestRecoverControlPlane() {
suite.T().Skip("with checkpoints enabled for kube-scheduler and kube-controller-manager this test no longer makes sense")
if !suite.Capabilities().SupportsRecover {
suite.T().Skip("cluster doesn't support recovery")
}
if suite.Cluster == nil {
suite.T().Skip("without full cluster state recover test is not reliable (can't wait for cluster readiness)")
}
for _, source := range []machineapi.RecoverRequest_Source{
machineapi.RecoverRequest_APISERVER,
machineapi.RecoverRequest_ETCD,
} {
source := source
suite.Run(source.String(), func() {
pods, err := suite.Clientset.CoreV1().Pods("kube-system").List(suite.ctx, metav1.ListOptions{
LabelSelector: "k8s-app in (kube-scheduler,kube-controller-manager)",
})
suite.Assert().NoError(err)
deletedPods := make(map[string]struct{})
var eg errgroup.Group
for _, pod := range pods.Items {
pod := pod
eg.Go(func() error {
suite.T().Logf("Deleting %s", pod.GetName())
deletedPods[pod.GetName()] = struct{}{}
return suite.Clientset.CoreV1().Pods(pod.GetNamespace()).Delete(suite.ctx, pod.GetName(), metav1.DeleteOptions{})
})
}
suite.Assert().NoError(eg.Wait())
suite.T().Logf("Waiting for the pods to be deleted")
for len(pods.Items) > 0 {
pods, err = suite.Clientset.CoreV1().Pods("kube-system").List(suite.ctx, metav1.ListOptions{
LabelSelector: "k8s-app in (kube-scheduler,kube-controller-manager)",
})
suite.Assert().NoError(err)
for _, pod := range pods.Items {
if _, ok := deletedPods[pod.GetName()]; !ok {
suite.T().Logf("Deleting %s", pod.GetName())
deletedPods[pod.GetName()] = struct{}{}
suite.Require().NoError(suite.Clientset.CoreV1().Pods(pod.GetNamespace()).Delete(suite.ctx, pod.GetName(), metav1.DeleteOptions{}))
}
}
}
nodes := suite.DiscoverNodes().NodesByType(machine.TypeControlPlane)
suite.Require().NotEmpty(nodes)
sort.Strings(nodes)
node := nodes[0]
suite.T().Log("Recovering control plane")
ctx, ctxCancel := context.WithTimeout(suite.ctx, 5*time.Minute)
defer ctxCancel()
nodeCtx := client.WithNodes(ctx, node)
in := &machineapi.RecoverRequest{
Source: source,
}
_, err = suite.Client.MachineClient.Recover(nodeCtx, in)
suite.Assert().NoError(err)
// NB: using `ctx` here to have client talking to init node by default
suite.AssertClusterHealthy(ctx)
})
}
}
func init() {
allSuites = append(allSuites, new(RecoverSuite))
}

View File

@ -153,7 +153,7 @@ func upgradeSingeNodePreserve() upgradeSpec {
// upgradeSingeNodeStage upgrade last release of Talos to the current version of Talos for single-node cluster with preserve and stage.
func upgradeSingeNodeStage() upgradeSpec {
return upgradeSpec{
ShortName: fmt.Sprintf("preserve-stage-%s-%s", DefaultSettings.CurrentVersion, DefaultSettings.CurrentVersion),
ShortName: fmt.Sprintf("preserve-stage-%s-%s", stableRelease, DefaultSettings.CurrentVersion),
SourceKernelPath: helpers.ArtifactPath(filepath.Join(trimVersion(stableRelease), constants.KernelAsset)),
SourceInitramfsPath: helpers.ArtifactPath(filepath.Join(trimVersion(stableRelease), constants.InitramfsAsset)),

View File

@ -0,0 +1,60 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package etcd
import (
"fmt"
stdlibnet "net"
"os"
"time"
"github.com/talos-systems/crypto/x509"
"github.com/talos-systems/net"
)
// GeneratePeerCert generates etcd peer certificate and key from etcd CA.
func GeneratePeerCert(etcdCA *x509.PEMEncodedCertificateAndKey) (*x509.PEMEncodedCertificateAndKey, error) {
ips, err := net.IPAddrs()
if err != nil {
return nil, fmt.Errorf("failed to discover IP addresses: %w", err)
}
ips = append(ips, stdlibnet.ParseIP("127.0.0.1"))
if net.IsIPv6(ips...) {
ips = append(ips, stdlibnet.ParseIP("::1"))
}
hostname, err := os.Hostname()
if err != nil {
return nil, fmt.Errorf("failed to get hostname: %w", err)
}
dnsNames, err := net.DNSNames()
if err != nil {
return nil, fmt.Errorf("failed to get host DNS names: %w", err)
}
dnsNames = append(dnsNames, "localhost")
opts := []x509.Option{
x509.CommonName(hostname),
x509.DNSNames(dnsNames),
x509.RSA(true),
x509.IPAddresses(ips),
x509.NotAfter(time.Now().Add(87600 * time.Hour)),
}
ca, err := x509.NewCertificateAuthorityFromCertificateAndKey(etcdCA, opts...)
if err != nil {
return nil, fmt.Errorf("failed loading CA from config: %w", err)
}
keyPair, err := x509.NewKeyPair(ca, opts...)
if err != nil {
return nil, fmt.Errorf("failed generating peer key pair: %w", err)
}
return x509.NewCertificateAndKeyFromKeyPair(keyPair), nil
}

View File

@ -36,7 +36,7 @@ type Client struct {
}
// NewClient initializes and returns an etcd client configured to talk to
// a local endpoint.
// a list of endpoints.
func NewClient(endpoints []string) (client *Client, err error) {
tlsInfo := transport.TLSInfo{
CertFile: constants.KubernetesEtcdPeerCert,
@ -62,6 +62,11 @@ func NewClient(endpoints []string) (client *Client, err error) {
return &Client{Client: c}, nil
}
// NewLocalClient initializes and returns etcd client configured to talk to localhost endpoint.
func NewLocalClient() (client *Client, err error) {
return NewClient([]string{"127.0.0.1:2379"})
}
// NewClientFromControlPlaneIPs initializes and returns an etcd client
// configured to talk to all members.
func NewClientFromControlPlaneIPs(ctx context.Context, creds *x509.PEMEncodedCertificateAndKey, endpoint *url.URL) (client *Client, err error) {

View File

@ -24,7 +24,7 @@ type ApplyConfigClient struct {
}
// ApplyConfig on the node via the API using insecure mode.
func (s *APIBoostrapper) ApplyConfig(ctx context.Context, nodes []provision.NodeRequest, out io.Writer) error {
func (s *APIBootstrapper) ApplyConfig(ctx context.Context, nodes []provision.NodeRequest, out io.Writer) error {
for _, node := range nodes {
n := node

View File

@ -19,8 +19,8 @@ import (
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine"
)
// APIBoostrapper bootstraps cluster via Talos API.
type APIBoostrapper struct {
// APIBootstrapper bootstraps cluster via Talos API.
type APIBootstrapper struct {
ClientProvider
Info
}
@ -28,7 +28,7 @@ type APIBoostrapper struct {
// Bootstrap the cluster via the API.
//
// Bootstrap implements Bootstrapper interface.
func (s *APIBoostrapper) Bootstrap(ctx context.Context, out io.Writer) error {
func (s *APIBootstrapper) Bootstrap(ctx context.Context, out io.Writer) error {
cli, err := s.Client()
if err != nil {
return err

View File

@ -98,6 +98,7 @@ func K8sFullControlPlaneAssertion(ctx context.Context, cluster ClusterInfo) erro
// ensure that all control plane nodes have been labeled with the master
// label.
// daemonset check only there for pre-0.9 clusters with self-hosted control plane
daemonsets, err := clientset.AppsV1().DaemonSets("kube-system").List(ctx, metav1.ListOptions{
LabelSelector: "k8s-app in (kube-apiserver,kube-scheduler,kube-controller-manager)",
})
@ -117,13 +118,15 @@ func K8sFullControlPlaneAssertion(ctx context.Context, cluster ClusterInfo) erro
if ds.Status.NumberReady != ds.Status.DesiredNumberScheduled {
return fmt.Errorf("expected number ready for %s to be %d, got %d", ds.GetName(), ds.Status.DesiredNumberScheduled, ds.Status.NumberReady)
}
}
for _, k8sApp := range []string{"kube-apiserver", "kube-scheduler", "kube-controller-manager"} {
// list pods to verify that daemonset status is updated properly
pods, err := clientset.CoreV1().Pods("kube-system").List(ctx, metav1.ListOptions{
LabelSelector: fmt.Sprintf("k8s-app = %s", ds.Labels["k8s-app"]),
LabelSelector: fmt.Sprintf("k8s-app = %s", k8sApp),
})
if err != nil {
return fmt.Errorf("error listing pods for daemonset %s: %w", ds.GetName(), err)
return fmt.Errorf("error listing pods for app %s: %w", k8sApp, err)
}
// filter out pod checkpoints
@ -138,8 +141,8 @@ func K8sFullControlPlaneAssertion(ctx context.Context, cluster ClusterInfo) erro
pods.Items = pods.Items[:n]
if int32(len(pods.Items)) != ds.Status.DesiredNumberScheduled {
return fmt.Errorf("expected number of pods for %s to be %d, got %d", ds.GetName(), ds.Status.DesiredNumberScheduled, len(pods.Items))
if len(pods.Items) != len(actualNodes) {
return fmt.Errorf("expected number of pods for %s to be %d, got %d", k8sApp, len(actualNodes), len(pods.Items))
}
var notReadyPods []string
@ -157,7 +160,7 @@ func K8sFullControlPlaneAssertion(ctx context.Context, cluster ClusterInfo) erro
}
if len(notReadyPods) > 0 {
return fmt.Errorf("some pods are not ready for %s: %v", ds.GetName(), notReadyPods)
return fmt.Errorf("some pods are not ready for %s: %v", k8sApp, notReadyPods)
}
}

View File

@ -8,33 +8,47 @@ import (
"fmt"
"runtime"
"github.com/talos-systems/bootkube-plugin/pkg/asset"
criconfig "github.com/containerd/cri/pkg/config"
"github.com/talos-systems/talos/pkg/machinery/config"
"github.com/talos-systems/talos/pkg/version"
)
// List returns a list of images used.
func List(config config.Provider) asset.ImageVersions {
images := asset.DefaultImages
// Versions holds all the images (and their versions) that are used in Talos.
type Versions struct {
Etcd string
Flannel string
FlannelCNI string
CoreDNS string
// Override all kube-related images with default val or specified image locations
Kubelet string
KubeAPIServer string
KubeControllerManager string
KubeProxy string
KubeScheduler string
Installer string
Pause string
}
// List returns default image versions.
func List(config config.Provider) Versions {
var images Versions
images.Etcd = config.Cluster().Etcd().Image()
images.CoreDNS = config.Cluster().CoreDNS().Image()
images.Flannel = fmt.Sprintf("quay.io/coreos/flannel:v0.12.0-%s", runtime.GOARCH)
images.FlannelCNI = fmt.Sprintf("ghcr.io/talos-systems/install-cni:%s", version.ExtrasVersion)
images.PodCheckpointer = fmt.Sprintf("ghcr.io/talos-systems/pod-checkpointer:%s", version.ExtrasVersion)
images.Kubelet = config.Machine().Kubelet().Image()
images.KubeAPIServer = config.Cluster().APIServer().Image()
images.KubeControllerManager = config.Cluster().ControllerManager().Image()
images.KubeProxy = config.Cluster().Proxy().Image()
images.KubeScheduler = config.Cluster().Scheduler().Image()
images.Etcd = config.Cluster().Etcd().Image()
// Allow for overriding by users via config data
images.CoreDNS = config.Cluster().CoreDNS().Image()
images.Installer = DefaultInstallerImage
if config.Cluster().PodCheckpointer().Image() != "" {
images.PodCheckpointer = config.Cluster().PodCheckpointer().Image()
}
images.Pause = criconfig.DefaultConfig().SandboxImage
return images
}

View File

@ -0,0 +1,93 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Package kubelet provides minimal client for the kubelet API.
package kubelet
import (
"context"
"crypto/tls"
stdx509 "crypto/x509"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
v1 "k8s.io/api/core/v1"
"github.com/talos-systems/talos/pkg/machinery/constants"
)
// Client is a kubelet API client.
//
// Client can only talk to the local kubelet on the same node.
type Client struct {
httpClient *http.Client
hostname string
}
// NewClient creates new kubelet API client.
func NewClient(clientCert tls.Certificate) (*Client, error) {
rootCAs := stdx509.NewCertPool()
kubeletCert, err := ioutil.ReadFile(filepath.Join(constants.KubeletPKIDir, "kubelet.crt"))
if err != nil {
return nil, fmt.Errorf("error reading kubelet certificate: %w", err)
}
rootCAs.AppendCertsFromPEM(kubeletCert)
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{clientCert},
RootCAs: rootCAs,
}
client := &Client{
httpClient: &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
},
},
}
client.hostname, err = os.Hostname()
if err != nil {
return nil, err
}
return client, nil
}
// Pods returns list of pods running on the kubelet.
func (c *Client) Pods(ctx context.Context) (*v1.PodList, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://%s:%d/pods", c.hostname, constants.KubeletPort), nil)
if err != nil {
return nil, fmt.Errorf("error building request: %w", err)
}
resp, err := c.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("error performing request: %w", err)
}
defer func() {
io.Copy(ioutil.Discard, resp.Body) //nolint: errcheck
resp.Body.Close() //nolint: errcheck
}()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status response %d", resp.StatusCode)
}
var podList v1.PodList
if err = json.NewDecoder(resp.Body).Decode(&podList); err != nil {
return nil, fmt.Errorf("error decoding JSON response: %w", err)
}
return &podList, nil
}

View File

@ -386,6 +386,12 @@ func (h *Client) Drain(node string) error {
return
}
if ref.Kind == "Node" {
log.Printf("skipping StaticPod pod %s\n", p.GetName())
return
}
}
if err := h.evict(p, int64(60)); err != nil {

View File

@ -0,0 +1,508 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.23.0
// protoc v3.14.0
// source: inspect/inspect.proto
package inspect
import (
context "context"
reflect "reflect"
sync "sync"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
common "github.com/talos-systems/talos/pkg/machinery/api/common"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type DependencyEdgeType int32
const (
DependencyEdgeType_MANAGES DependencyEdgeType = 0
DependencyEdgeType_STRONG DependencyEdgeType = 1
DependencyEdgeType_WEAK DependencyEdgeType = 2
)
// Enum value maps for DependencyEdgeType.
var (
DependencyEdgeType_name = map[int32]string{
0: "MANAGES",
1: "STRONG",
2: "WEAK",
}
DependencyEdgeType_value = map[string]int32{
"MANAGES": 0,
"STRONG": 1,
"WEAK": 2,
}
)
func (x DependencyEdgeType) Enum() *DependencyEdgeType {
p := new(DependencyEdgeType)
*p = x
return p
}
func (x DependencyEdgeType) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (DependencyEdgeType) Descriptor() protoreflect.EnumDescriptor {
return file_inspect_inspect_proto_enumTypes[0].Descriptor()
}
func (DependencyEdgeType) Type() protoreflect.EnumType {
return &file_inspect_inspect_proto_enumTypes[0]
}
func (x DependencyEdgeType) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use DependencyEdgeType.Descriptor instead.
func (DependencyEdgeType) EnumDescriptor() ([]byte, []int) {
return file_inspect_inspect_proto_rawDescGZIP(), []int{0}
}
// The ControllerRuntimeDependency message contains the graph of controller-resource dependencies.
type ControllerRuntimeDependency struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Metadata *common.Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
Edges []*ControllerDependencyEdge `protobuf:"bytes,2,rep,name=edges,proto3" json:"edges,omitempty"`
}
func (x *ControllerRuntimeDependency) Reset() {
*x = ControllerRuntimeDependency{}
if protoimpl.UnsafeEnabled {
mi := &file_inspect_inspect_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ControllerRuntimeDependency) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ControllerRuntimeDependency) ProtoMessage() {}
func (x *ControllerRuntimeDependency) ProtoReflect() protoreflect.Message {
mi := &file_inspect_inspect_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ControllerRuntimeDependency.ProtoReflect.Descriptor instead.
func (*ControllerRuntimeDependency) Descriptor() ([]byte, []int) {
return file_inspect_inspect_proto_rawDescGZIP(), []int{0}
}
func (x *ControllerRuntimeDependency) GetMetadata() *common.Metadata {
if x != nil {
return x.Metadata
}
return nil
}
func (x *ControllerRuntimeDependency) GetEdges() []*ControllerDependencyEdge {
if x != nil {
return x.Edges
}
return nil
}
type ControllerRuntimeDependenciesResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Messages []*ControllerRuntimeDependency `protobuf:"bytes,1,rep,name=messages,proto3" json:"messages,omitempty"`
}
func (x *ControllerRuntimeDependenciesResponse) Reset() {
*x = ControllerRuntimeDependenciesResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_inspect_inspect_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ControllerRuntimeDependenciesResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ControllerRuntimeDependenciesResponse) ProtoMessage() {}
func (x *ControllerRuntimeDependenciesResponse) ProtoReflect() protoreflect.Message {
mi := &file_inspect_inspect_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ControllerRuntimeDependenciesResponse.ProtoReflect.Descriptor instead.
func (*ControllerRuntimeDependenciesResponse) Descriptor() ([]byte, []int) {
return file_inspect_inspect_proto_rawDescGZIP(), []int{1}
}
func (x *ControllerRuntimeDependenciesResponse) GetMessages() []*ControllerRuntimeDependency {
if x != nil {
return x.Messages
}
return nil
}
type ControllerDependencyEdge struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ControllerName string `protobuf:"bytes,1,opt,name=controller_name,json=controllerName,proto3" json:"controller_name,omitempty"`
EdgeType DependencyEdgeType `protobuf:"varint,2,opt,name=edge_type,json=edgeType,proto3,enum=inspect.DependencyEdgeType" json:"edge_type,omitempty"`
ResourceNamespace string `protobuf:"bytes,3,opt,name=resource_namespace,json=resourceNamespace,proto3" json:"resource_namespace,omitempty"`
ResourceType string `protobuf:"bytes,4,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"`
ResourceId string `protobuf:"bytes,5,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"`
}
func (x *ControllerDependencyEdge) Reset() {
*x = ControllerDependencyEdge{}
if protoimpl.UnsafeEnabled {
mi := &file_inspect_inspect_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ControllerDependencyEdge) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ControllerDependencyEdge) ProtoMessage() {}
func (x *ControllerDependencyEdge) ProtoReflect() protoreflect.Message {
mi := &file_inspect_inspect_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ControllerDependencyEdge.ProtoReflect.Descriptor instead.
func (*ControllerDependencyEdge) Descriptor() ([]byte, []int) {
return file_inspect_inspect_proto_rawDescGZIP(), []int{2}
}
func (x *ControllerDependencyEdge) GetControllerName() string {
if x != nil {
return x.ControllerName
}
return ""
}
func (x *ControllerDependencyEdge) GetEdgeType() DependencyEdgeType {
if x != nil {
return x.EdgeType
}
return DependencyEdgeType_MANAGES
}
func (x *ControllerDependencyEdge) GetResourceNamespace() string {
if x != nil {
return x.ResourceNamespace
}
return ""
}
func (x *ControllerDependencyEdge) GetResourceType() string {
if x != nil {
return x.ResourceType
}
return ""
}
func (x *ControllerDependencyEdge) GetResourceId() string {
if x != nil {
return x.ResourceId
}
return ""
}
var File_inspect_inspect_proto protoreflect.FileDescriptor
var file_inspect_inspect_proto_rawDesc = []byte{
0x0a, 0x15, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x2f, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63,
0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74,
0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x13, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x22, 0x84, 0x01, 0x0a, 0x1b, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e,
0x63, 0x79, 0x12, 0x2c, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x65,
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
0x12, 0x37, 0x0a, 0x05, 0x65, 0x64, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x21, 0x2e, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x45, 0x64,
0x67, 0x65, 0x52, 0x05, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x69, 0x0a, 0x25, 0x43, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x65,
0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x2e, 0x43,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65,
0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x73, 0x22, 0xf2, 0x01, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x6c, 0x65, 0x72, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x45, 0x64, 0x67,
0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x65, 0x64,
0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e,
0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x2e, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e,
0x63, 0x79, 0x45, 0x64, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x65, 0x64, 0x67, 0x65,
0x54, 0x79, 0x70, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70,
0x61, 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x2a, 0x37, 0x0a, 0x12, 0x44, 0x65, 0x70,
0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x45, 0x64, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12,
0x0b, 0x0a, 0x07, 0x4d, 0x41, 0x4e, 0x41, 0x47, 0x45, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06,
0x53, 0x54, 0x52, 0x4f, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x45, 0x41, 0x4b,
0x10, 0x02, 0x32, 0x79, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x1d, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65,
0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2e, 0x2e,
0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65,
0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x59, 0x0a,
0x0f, 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x2e, 0x61, 0x70, 0x69,
0x42, 0x0a, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x41, 0x70, 0x69, 0x50, 0x01, 0x5a, 0x38,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73,
0x2d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x2f, 0x74, 0x61, 0x6c, 0x6f, 0x73, 0x2f, 0x70,
0x6b, 0x67, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69,
0x2f, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_inspect_inspect_proto_rawDescOnce sync.Once
file_inspect_inspect_proto_rawDescData = file_inspect_inspect_proto_rawDesc
)
func file_inspect_inspect_proto_rawDescGZIP() []byte {
file_inspect_inspect_proto_rawDescOnce.Do(func() {
file_inspect_inspect_proto_rawDescData = protoimpl.X.CompressGZIP(file_inspect_inspect_proto_rawDescData)
})
return file_inspect_inspect_proto_rawDescData
}
var (
file_inspect_inspect_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
file_inspect_inspect_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
file_inspect_inspect_proto_goTypes = []interface{}{
(DependencyEdgeType)(0), // 0: inspect.DependencyEdgeType
(*ControllerRuntimeDependency)(nil), // 1: inspect.ControllerRuntimeDependency
(*ControllerRuntimeDependenciesResponse)(nil), // 2: inspect.ControllerRuntimeDependenciesResponse
(*ControllerDependencyEdge)(nil), // 3: inspect.ControllerDependencyEdge
(*common.Metadata)(nil), // 4: common.Metadata
(*emptypb.Empty)(nil), // 5: google.protobuf.Empty
}
)
var file_inspect_inspect_proto_depIdxs = []int32{
4, // 0: inspect.ControllerRuntimeDependency.metadata:type_name -> common.Metadata
3, // 1: inspect.ControllerRuntimeDependency.edges:type_name -> inspect.ControllerDependencyEdge
1, // 2: inspect.ControllerRuntimeDependenciesResponse.messages:type_name -> inspect.ControllerRuntimeDependency
0, // 3: inspect.ControllerDependencyEdge.edge_type:type_name -> inspect.DependencyEdgeType
5, // 4: inspect.InspectService.ControllerRuntimeDependencies:input_type -> google.protobuf.Empty
2, // 5: inspect.InspectService.ControllerRuntimeDependencies:output_type -> inspect.ControllerRuntimeDependenciesResponse
5, // [5:6] is the sub-list for method output_type
4, // [4:5] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_inspect_inspect_proto_init() }
func file_inspect_inspect_proto_init() {
if File_inspect_inspect_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_inspect_inspect_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ControllerRuntimeDependency); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_inspect_inspect_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ControllerRuntimeDependenciesResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_inspect_inspect_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ControllerDependencyEdge); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_inspect_inspect_proto_rawDesc,
NumEnums: 1,
NumMessages: 3,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_inspect_inspect_proto_goTypes,
DependencyIndexes: file_inspect_inspect_proto_depIdxs,
EnumInfos: file_inspect_inspect_proto_enumTypes,
MessageInfos: file_inspect_inspect_proto_msgTypes,
}.Build()
File_inspect_inspect_proto = out.File
file_inspect_inspect_proto_rawDesc = nil
file_inspect_inspect_proto_goTypes = nil
file_inspect_inspect_proto_depIdxs = nil
}
// Reference imports to suppress errors if they are not otherwise used.
var (
_ context.Context
_ grpc.ClientConnInterface
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
// InspectServiceClient is the client API for InspectService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type InspectServiceClient interface {
ControllerRuntimeDependencies(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ControllerRuntimeDependenciesResponse, error)
}
type inspectServiceClient struct {
cc grpc.ClientConnInterface
}
func NewInspectServiceClient(cc grpc.ClientConnInterface) InspectServiceClient {
return &inspectServiceClient{cc}
}
func (c *inspectServiceClient) ControllerRuntimeDependencies(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ControllerRuntimeDependenciesResponse, error) {
out := new(ControllerRuntimeDependenciesResponse)
err := c.cc.Invoke(ctx, "/inspect.InspectService/ControllerRuntimeDependencies", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// InspectServiceServer is the server API for InspectService service.
type InspectServiceServer interface {
ControllerRuntimeDependencies(context.Context, *emptypb.Empty) (*ControllerRuntimeDependenciesResponse, error)
}
// UnimplementedInspectServiceServer can be embedded to have forward compatible implementations.
type UnimplementedInspectServiceServer struct {
}
func (*UnimplementedInspectServiceServer) ControllerRuntimeDependencies(context.Context, *emptypb.Empty) (*ControllerRuntimeDependenciesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ControllerRuntimeDependencies not implemented")
}
func RegisterInspectServiceServer(s *grpc.Server, srv InspectServiceServer) {
s.RegisterService(&_InspectService_serviceDesc, srv)
}
func _InspectService_ControllerRuntimeDependencies_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(emptypb.Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(InspectServiceServer).ControllerRuntimeDependencies(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/inspect.InspectService/ControllerRuntimeDependencies",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(InspectServiceServer).ControllerRuntimeDependencies(ctx, req.(*emptypb.Empty))
}
return interceptor(ctx, in, info, handler)
}
var _InspectService_serviceDesc = grpc.ServiceDesc{
ServiceName: "inspect.InspectService",
HandlerType: (*InspectServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ControllerRuntimeDependencies",
Handler: _InspectService_ControllerRuntimeDependencies_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "inspect/inspect.proto",
}

View File

@ -956,6 +956,7 @@ type ServiceStateEvent struct {
Service string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"`
Action ServiceStateEvent_Action `protobuf:"varint,2,opt,name=action,proto3,enum=machine.ServiceStateEvent_Action" json:"action,omitempty"`
Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
Health *ServiceHealth `protobuf:"bytes,4,opt,name=health,proto3" json:"health,omitempty"`
}
func (x *ServiceStateEvent) Reset() {
@ -1011,6 +1012,13 @@ func (x *ServiceStateEvent) GetMessage() string {
return ""
}
func (x *ServiceStateEvent) GetHealth() *ServiceHealth {
if x != nil {
return x.Health
}
return nil
}
type EventsRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -8155,7 +8163,7 @@ var file_machine_machine_proto_rawDesc = []byte{
0x74, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x22, 0x1d, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x54,
0x41, 0x52, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x01, 0x22,
0xfb, 0x01, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65,
0xab, 0x02, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65,
0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
0x39, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32,
@ -8163,7 +8171,10 @@ var file_machine_machine_proto_rawDesc = []byte{
0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x22, 0x77, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0f,
0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x53,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x06, 0x68, 0x65,
0x61, 0x6c, 0x74, 0x68, 0x22, 0x77, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0f,
0x0a, 0x0b, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x00, 0x12,
0x0d, 0x0a, 0x09, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0b,
0x0a, 0x07, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x52,
@ -9376,180 +9387,181 @@ var file_machine_machine_proto_depIdxs = []int32{
1, // 8: machine.PhaseEvent.action:type_name -> machine.PhaseEvent.Action
2, // 9: machine.TaskEvent.action:type_name -> machine.TaskEvent.Action
3, // 10: machine.ServiceStateEvent.action:type_name -> machine.ServiceStateEvent.Action
126, // 11: machine.Event.metadata:type_name -> common.Metadata
128, // 12: machine.Event.data:type_name -> google.protobuf.Any
21, // 13: machine.ResetRequest.system_partitions_to_wipe:type_name -> machine.ResetPartitionSpec
126, // 14: machine.Reset.metadata:type_name -> common.Metadata
23, // 15: machine.ResetResponse.messages:type_name -> machine.Reset
4, // 16: machine.RecoverRequest.source:type_name -> machine.RecoverRequest.Source
126, // 17: machine.Recover.metadata:type_name -> common.Metadata
26, // 18: machine.RecoverResponse.messages:type_name -> machine.Recover
126, // 19: machine.Shutdown.metadata:type_name -> common.Metadata
28, // 20: machine.ShutdownResponse.messages:type_name -> machine.Shutdown
126, // 21: machine.Upgrade.metadata:type_name -> common.Metadata
31, // 22: machine.UpgradeResponse.messages:type_name -> machine.Upgrade
126, // 23: machine.ServiceList.metadata:type_name -> common.Metadata
35, // 24: machine.ServiceList.services:type_name -> machine.ServiceInfo
33, // 25: machine.ServiceListResponse.messages:type_name -> machine.ServiceList
36, // 26: machine.ServiceInfo.events:type_name -> machine.ServiceEvents
38, // 27: machine.ServiceInfo.health:type_name -> machine.ServiceHealth
37, // 28: machine.ServiceEvents.events:type_name -> machine.ServiceEvent
129, // 29: machine.ServiceEvent.ts:type_name -> google.protobuf.Timestamp
129, // 30: machine.ServiceHealth.last_change:type_name -> google.protobuf.Timestamp
126, // 31: machine.ServiceStart.metadata:type_name -> common.Metadata
40, // 32: machine.ServiceStartResponse.messages:type_name -> machine.ServiceStart
126, // 33: machine.ServiceStop.metadata:type_name -> common.Metadata
43, // 34: machine.ServiceStopResponse.messages:type_name -> machine.ServiceStop
126, // 35: machine.ServiceRestart.metadata:type_name -> common.Metadata
46, // 36: machine.ServiceRestartResponse.messages:type_name -> machine.ServiceRestart
5, // 37: machine.ListRequest.types:type_name -> machine.ListRequest.Type
126, // 38: machine.FileInfo.metadata:type_name -> common.Metadata
126, // 39: machine.DiskUsageInfo.metadata:type_name -> common.Metadata
126, // 40: machine.Mounts.metadata:type_name -> common.Metadata
59, // 41: machine.Mounts.stats:type_name -> machine.MountStat
57, // 42: machine.MountsResponse.messages:type_name -> machine.Mounts
126, // 43: machine.Version.metadata:type_name -> common.Metadata
62, // 44: machine.Version.version:type_name -> machine.VersionInfo
63, // 45: machine.Version.platform:type_name -> machine.PlatformInfo
60, // 46: machine.VersionResponse.messages:type_name -> machine.Version
130, // 47: machine.LogsRequest.driver:type_name -> common.ContainerDriver
126, // 48: machine.Rollback.metadata:type_name -> common.Metadata
67, // 49: machine.RollbackResponse.messages:type_name -> machine.Rollback
130, // 50: machine.ContainersRequest.driver:type_name -> common.ContainerDriver
126, // 51: machine.Container.metadata:type_name -> common.Metadata
70, // 52: machine.Container.containers:type_name -> machine.ContainerInfo
71, // 53: machine.ContainersResponse.messages:type_name -> machine.Container
76, // 54: machine.ProcessesResponse.messages:type_name -> machine.Process
126, // 55: machine.Process.metadata:type_name -> common.Metadata
77, // 56: machine.Process.processes:type_name -> machine.ProcessInfo
130, // 57: machine.RestartRequest.driver:type_name -> common.ContainerDriver
126, // 58: machine.Restart.metadata:type_name -> common.Metadata
79, // 59: machine.RestartResponse.messages:type_name -> machine.Restart
130, // 60: machine.StatsRequest.driver:type_name -> common.ContainerDriver
126, // 61: machine.Stats.metadata:type_name -> common.Metadata
84, // 62: machine.Stats.stats:type_name -> machine.Stat
82, // 63: machine.StatsResponse.messages:type_name -> machine.Stats
126, // 64: machine.Memory.metadata:type_name -> common.Metadata
87, // 65: machine.Memory.meminfo:type_name -> machine.MemInfo
85, // 66: machine.MemoryResponse.messages:type_name -> machine.Memory
89, // 67: machine.HostnameResponse.messages:type_name -> machine.Hostname
126, // 68: machine.Hostname.metadata:type_name -> common.Metadata
91, // 69: machine.LoadAvgResponse.messages:type_name -> machine.LoadAvg
126, // 70: machine.LoadAvg.metadata:type_name -> common.Metadata
93, // 71: machine.SystemStatResponse.messages:type_name -> machine.SystemStat
126, // 72: machine.SystemStat.metadata:type_name -> common.Metadata
94, // 73: machine.SystemStat.cpu_total:type_name -> machine.CPUStat
94, // 74: machine.SystemStat.cpu:type_name -> machine.CPUStat
95, // 75: machine.SystemStat.soft_irq:type_name -> machine.SoftIRQStat
97, // 76: machine.CPUInfoResponse.messages:type_name -> machine.CPUsInfo
126, // 77: machine.CPUsInfo.metadata:type_name -> common.Metadata
98, // 78: machine.CPUsInfo.cpu_info:type_name -> machine.CPUInfo
100, // 79: machine.NetworkDeviceStatsResponse.messages:type_name -> machine.NetworkDeviceStats
126, // 80: machine.NetworkDeviceStats.metadata:type_name -> common.Metadata
101, // 81: machine.NetworkDeviceStats.total:type_name -> machine.NetDev
101, // 82: machine.NetworkDeviceStats.devices:type_name -> machine.NetDev
103, // 83: machine.DiskStatsResponse.messages:type_name -> machine.DiskStats
126, // 84: machine.DiskStats.metadata:type_name -> common.Metadata
104, // 85: machine.DiskStats.total:type_name -> machine.DiskStat
104, // 86: machine.DiskStats.devices:type_name -> machine.DiskStat
126, // 87: machine.EtcdLeaveCluster.metadata:type_name -> common.Metadata
106, // 88: machine.EtcdLeaveClusterResponse.messages:type_name -> machine.EtcdLeaveCluster
126, // 89: machine.EtcdForfeitLeadership.metadata:type_name -> common.Metadata
109, // 90: machine.EtcdForfeitLeadershipResponse.messages:type_name -> machine.EtcdForfeitLeadership
126, // 91: machine.EtcdMemberList.metadata:type_name -> common.Metadata
112, // 92: machine.EtcdMemberListResponse.messages:type_name -> machine.EtcdMemberList
115, // 93: machine.NetworkDeviceConfig.dhcp_options:type_name -> machine.DHCPOptionsConfig
114, // 94: machine.NetworkDeviceConfig.routes:type_name -> machine.RouteConfig
116, // 95: machine.NetworkConfig.interfaces:type_name -> machine.NetworkDeviceConfig
6, // 96: machine.MachineConfig.type:type_name -> machine.MachineConfig.MachineType
118, // 97: machine.MachineConfig.install_config:type_name -> machine.InstallConfig
117, // 98: machine.MachineConfig.network_config:type_name -> machine.NetworkConfig
121, // 99: machine.ClusterNetworkConfig.cni_config:type_name -> machine.CNIConfig
120, // 100: machine.ClusterConfig.control_plane:type_name -> machine.ControlPlaneConfig
122, // 101: machine.ClusterConfig.cluster_network:type_name -> machine.ClusterNetworkConfig
123, // 102: machine.GenerateConfigurationRequest.cluster_config:type_name -> machine.ClusterConfig
119, // 103: machine.GenerateConfigurationRequest.machine_config:type_name -> machine.MachineConfig
129, // 104: machine.GenerateConfigurationRequest.override_time:type_name -> google.protobuf.Timestamp
126, // 105: machine.GenerateConfigurationResponse.metadata:type_name -> common.Metadata
7, // 106: machine.MachineService.ApplyConfiguration:input_type -> machine.ApplyConfigurationRequest
12, // 107: machine.MachineService.Bootstrap:input_type -> machine.BootstrapRequest
69, // 108: machine.MachineService.Containers:input_type -> machine.ContainersRequest
52, // 109: machine.MachineService.Copy:input_type -> machine.CopyRequest
131, // 110: machine.MachineService.CPUInfo:input_type -> google.protobuf.Empty
131, // 111: machine.MachineService.DiskStats:input_type -> google.protobuf.Empty
73, // 112: machine.MachineService.Dmesg:input_type -> machine.DmesgRequest
19, // 113: machine.MachineService.Events:input_type -> machine.EventsRequest
111, // 114: machine.MachineService.EtcdMemberList:input_type -> machine.EtcdMemberListRequest
105, // 115: machine.MachineService.EtcdLeaveCluster:input_type -> machine.EtcdLeaveClusterRequest
108, // 116: machine.MachineService.EtcdForfeitLeadership:input_type -> machine.EtcdForfeitLeadershipRequest
124, // 117: machine.MachineService.GenerateConfiguration:input_type -> machine.GenerateConfigurationRequest
131, // 118: machine.MachineService.Hostname:input_type -> google.protobuf.Empty
131, // 119: machine.MachineService.Kubeconfig:input_type -> google.protobuf.Empty
53, // 120: machine.MachineService.List:input_type -> machine.ListRequest
54, // 121: machine.MachineService.DiskUsage:input_type -> machine.DiskUsageRequest
131, // 122: machine.MachineService.LoadAvg:input_type -> google.protobuf.Empty
64, // 123: machine.MachineService.Logs:input_type -> machine.LogsRequest
131, // 124: machine.MachineService.Memory:input_type -> google.protobuf.Empty
131, // 125: machine.MachineService.Mounts:input_type -> google.protobuf.Empty
131, // 126: machine.MachineService.NetworkDeviceStats:input_type -> google.protobuf.Empty
131, // 127: machine.MachineService.Processes:input_type -> google.protobuf.Empty
65, // 128: machine.MachineService.Read:input_type -> machine.ReadRequest
131, // 129: machine.MachineService.Reboot:input_type -> google.protobuf.Empty
78, // 130: machine.MachineService.Restart:input_type -> machine.RestartRequest
66, // 131: machine.MachineService.Rollback:input_type -> machine.RollbackRequest
22, // 132: machine.MachineService.Reset:input_type -> machine.ResetRequest
25, // 133: machine.MachineService.Recover:input_type -> machine.RecoverRequest
131, // 134: machine.MachineService.ServiceList:input_type -> google.protobuf.Empty
45, // 135: machine.MachineService.ServiceRestart:input_type -> machine.ServiceRestartRequest
39, // 136: machine.MachineService.ServiceStart:input_type -> machine.ServiceStartRequest
42, // 137: machine.MachineService.ServiceStop:input_type -> machine.ServiceStopRequest
131, // 138: machine.MachineService.Shutdown:input_type -> google.protobuf.Empty
81, // 139: machine.MachineService.Stats:input_type -> machine.StatsRequest
131, // 140: machine.MachineService.SystemStat:input_type -> google.protobuf.Empty
30, // 141: machine.MachineService.Upgrade:input_type -> machine.UpgradeRequest
131, // 142: machine.MachineService.Version:input_type -> google.protobuf.Empty
9, // 143: machine.MachineService.ApplyConfiguration:output_type -> machine.ApplyConfigurationResponse
14, // 144: machine.MachineService.Bootstrap:output_type -> machine.BootstrapResponse
72, // 145: machine.MachineService.Containers:output_type -> machine.ContainersResponse
132, // 146: machine.MachineService.Copy:output_type -> common.Data
96, // 147: machine.MachineService.CPUInfo:output_type -> machine.CPUInfoResponse
102, // 148: machine.MachineService.DiskStats:output_type -> machine.DiskStatsResponse
132, // 149: machine.MachineService.Dmesg:output_type -> common.Data
20, // 150: machine.MachineService.Events:output_type -> machine.Event
113, // 151: machine.MachineService.EtcdMemberList:output_type -> machine.EtcdMemberListResponse
107, // 152: machine.MachineService.EtcdLeaveCluster:output_type -> machine.EtcdLeaveClusterResponse
110, // 153: machine.MachineService.EtcdForfeitLeadership:output_type -> machine.EtcdForfeitLeadershipResponse
125, // 154: machine.MachineService.GenerateConfiguration:output_type -> machine.GenerateConfigurationResponse
88, // 155: machine.MachineService.Hostname:output_type -> machine.HostnameResponse
132, // 156: machine.MachineService.Kubeconfig:output_type -> common.Data
55, // 157: machine.MachineService.List:output_type -> machine.FileInfo
56, // 158: machine.MachineService.DiskUsage:output_type -> machine.DiskUsageInfo
90, // 159: machine.MachineService.LoadAvg:output_type -> machine.LoadAvgResponse
132, // 160: machine.MachineService.Logs:output_type -> common.Data
86, // 161: machine.MachineService.Memory:output_type -> machine.MemoryResponse
58, // 162: machine.MachineService.Mounts:output_type -> machine.MountsResponse
99, // 163: machine.MachineService.NetworkDeviceStats:output_type -> machine.NetworkDeviceStatsResponse
75, // 164: machine.MachineService.Processes:output_type -> machine.ProcessesResponse
132, // 165: machine.MachineService.Read:output_type -> common.Data
11, // 166: machine.MachineService.Reboot:output_type -> machine.RebootResponse
80, // 167: machine.MachineService.Restart:output_type -> machine.RestartResponse
68, // 168: machine.MachineService.Rollback:output_type -> machine.RollbackResponse
24, // 169: machine.MachineService.Reset:output_type -> machine.ResetResponse
27, // 170: machine.MachineService.Recover:output_type -> machine.RecoverResponse
34, // 171: machine.MachineService.ServiceList:output_type -> machine.ServiceListResponse
47, // 172: machine.MachineService.ServiceRestart:output_type -> machine.ServiceRestartResponse
41, // 173: machine.MachineService.ServiceStart:output_type -> machine.ServiceStartResponse
44, // 174: machine.MachineService.ServiceStop:output_type -> machine.ServiceStopResponse
29, // 175: machine.MachineService.Shutdown:output_type -> machine.ShutdownResponse
83, // 176: machine.MachineService.Stats:output_type -> machine.StatsResponse
92, // 177: machine.MachineService.SystemStat:output_type -> machine.SystemStatResponse
32, // 178: machine.MachineService.Upgrade:output_type -> machine.UpgradeResponse
61, // 179: machine.MachineService.Version:output_type -> machine.VersionResponse
143, // [143:180] is the sub-list for method output_type
106, // [106:143] is the sub-list for method input_type
106, // [106:106] is the sub-list for extension type_name
106, // [106:106] is the sub-list for extension extendee
0, // [0:106] is the sub-list for field type_name
38, // 11: machine.ServiceStateEvent.health:type_name -> machine.ServiceHealth
126, // 12: machine.Event.metadata:type_name -> common.Metadata
128, // 13: machine.Event.data:type_name -> google.protobuf.Any
21, // 14: machine.ResetRequest.system_partitions_to_wipe:type_name -> machine.ResetPartitionSpec
126, // 15: machine.Reset.metadata:type_name -> common.Metadata
23, // 16: machine.ResetResponse.messages:type_name -> machine.Reset
4, // 17: machine.RecoverRequest.source:type_name -> machine.RecoverRequest.Source
126, // 18: machine.Recover.metadata:type_name -> common.Metadata
26, // 19: machine.RecoverResponse.messages:type_name -> machine.Recover
126, // 20: machine.Shutdown.metadata:type_name -> common.Metadata
28, // 21: machine.ShutdownResponse.messages:type_name -> machine.Shutdown
126, // 22: machine.Upgrade.metadata:type_name -> common.Metadata
31, // 23: machine.UpgradeResponse.messages:type_name -> machine.Upgrade
126, // 24: machine.ServiceList.metadata:type_name -> common.Metadata
35, // 25: machine.ServiceList.services:type_name -> machine.ServiceInfo
33, // 26: machine.ServiceListResponse.messages:type_name -> machine.ServiceList
36, // 27: machine.ServiceInfo.events:type_name -> machine.ServiceEvents
38, // 28: machine.ServiceInfo.health:type_name -> machine.ServiceHealth
37, // 29: machine.ServiceEvents.events:type_name -> machine.ServiceEvent
129, // 30: machine.ServiceEvent.ts:type_name -> google.protobuf.Timestamp
129, // 31: machine.ServiceHealth.last_change:type_name -> google.protobuf.Timestamp
126, // 32: machine.ServiceStart.metadata:type_name -> common.Metadata
40, // 33: machine.ServiceStartResponse.messages:type_name -> machine.ServiceStart
126, // 34: machine.ServiceStop.metadata:type_name -> common.Metadata
43, // 35: machine.ServiceStopResponse.messages:type_name -> machine.ServiceStop
126, // 36: machine.ServiceRestart.metadata:type_name -> common.Metadata
46, // 37: machine.ServiceRestartResponse.messages:type_name -> machine.ServiceRestart
5, // 38: machine.ListRequest.types:type_name -> machine.ListRequest.Type
126, // 39: machine.FileInfo.metadata:type_name -> common.Metadata
126, // 40: machine.DiskUsageInfo.metadata:type_name -> common.Metadata
126, // 41: machine.Mounts.metadata:type_name -> common.Metadata
59, // 42: machine.Mounts.stats:type_name -> machine.MountStat
57, // 43: machine.MountsResponse.messages:type_name -> machine.Mounts
126, // 44: machine.Version.metadata:type_name -> common.Metadata
62, // 45: machine.Version.version:type_name -> machine.VersionInfo
63, // 46: machine.Version.platform:type_name -> machine.PlatformInfo
60, // 47: machine.VersionResponse.messages:type_name -> machine.Version
130, // 48: machine.LogsRequest.driver:type_name -> common.ContainerDriver
126, // 49: machine.Rollback.metadata:type_name -> common.Metadata
67, // 50: machine.RollbackResponse.messages:type_name -> machine.Rollback
130, // 51: machine.ContainersRequest.driver:type_name -> common.ContainerDriver
126, // 52: machine.Container.metadata:type_name -> common.Metadata
70, // 53: machine.Container.containers:type_name -> machine.ContainerInfo
71, // 54: machine.ContainersResponse.messages:type_name -> machine.Container
76, // 55: machine.ProcessesResponse.messages:type_name -> machine.Process
126, // 56: machine.Process.metadata:type_name -> common.Metadata
77, // 57: machine.Process.processes:type_name -> machine.ProcessInfo
130, // 58: machine.RestartRequest.driver:type_name -> common.ContainerDriver
126, // 59: machine.Restart.metadata:type_name -> common.Metadata
79, // 60: machine.RestartResponse.messages:type_name -> machine.Restart
130, // 61: machine.StatsRequest.driver:type_name -> common.ContainerDriver
126, // 62: machine.Stats.metadata:type_name -> common.Metadata
84, // 63: machine.Stats.stats:type_name -> machine.Stat
82, // 64: machine.StatsResponse.messages:type_name -> machine.Stats
126, // 65: machine.Memory.metadata:type_name -> common.Metadata
87, // 66: machine.Memory.meminfo:type_name -> machine.MemInfo
85, // 67: machine.MemoryResponse.messages:type_name -> machine.Memory
89, // 68: machine.HostnameResponse.messages:type_name -> machine.Hostname
126, // 69: machine.Hostname.metadata:type_name -> common.Metadata
91, // 70: machine.LoadAvgResponse.messages:type_name -> machine.LoadAvg
126, // 71: machine.LoadAvg.metadata:type_name -> common.Metadata
93, // 72: machine.SystemStatResponse.messages:type_name -> machine.SystemStat
126, // 73: machine.SystemStat.metadata:type_name -> common.Metadata
94, // 74: machine.SystemStat.cpu_total:type_name -> machine.CPUStat
94, // 75: machine.SystemStat.cpu:type_name -> machine.CPUStat
95, // 76: machine.SystemStat.soft_irq:type_name -> machine.SoftIRQStat
97, // 77: machine.CPUInfoResponse.messages:type_name -> machine.CPUsInfo
126, // 78: machine.CPUsInfo.metadata:type_name -> common.Metadata
98, // 79: machine.CPUsInfo.cpu_info:type_name -> machine.CPUInfo
100, // 80: machine.NetworkDeviceStatsResponse.messages:type_name -> machine.NetworkDeviceStats
126, // 81: machine.NetworkDeviceStats.metadata:type_name -> common.Metadata
101, // 82: machine.NetworkDeviceStats.total:type_name -> machine.NetDev
101, // 83: machine.NetworkDeviceStats.devices:type_name -> machine.NetDev
103, // 84: machine.DiskStatsResponse.messages:type_name -> machine.DiskStats
126, // 85: machine.DiskStats.metadata:type_name -> common.Metadata
104, // 86: machine.DiskStats.total:type_name -> machine.DiskStat
104, // 87: machine.DiskStats.devices:type_name -> machine.DiskStat
126, // 88: machine.EtcdLeaveCluster.metadata:type_name -> common.Metadata
106, // 89: machine.EtcdLeaveClusterResponse.messages:type_name -> machine.EtcdLeaveCluster
126, // 90: machine.EtcdForfeitLeadership.metadata:type_name -> common.Metadata
109, // 91: machine.EtcdForfeitLeadershipResponse.messages:type_name -> machine.EtcdForfeitLeadership
126, // 92: machine.EtcdMemberList.metadata:type_name -> common.Metadata
112, // 93: machine.EtcdMemberListResponse.messages:type_name -> machine.EtcdMemberList
115, // 94: machine.NetworkDeviceConfig.dhcp_options:type_name -> machine.DHCPOptionsConfig
114, // 95: machine.NetworkDeviceConfig.routes:type_name -> machine.RouteConfig
116, // 96: machine.NetworkConfig.interfaces:type_name -> machine.NetworkDeviceConfig
6, // 97: machine.MachineConfig.type:type_name -> machine.MachineConfig.MachineType
118, // 98: machine.MachineConfig.install_config:type_name -> machine.InstallConfig
117, // 99: machine.MachineConfig.network_config:type_name -> machine.NetworkConfig
121, // 100: machine.ClusterNetworkConfig.cni_config:type_name -> machine.CNIConfig
120, // 101: machine.ClusterConfig.control_plane:type_name -> machine.ControlPlaneConfig
122, // 102: machine.ClusterConfig.cluster_network:type_name -> machine.ClusterNetworkConfig
123, // 103: machine.GenerateConfigurationRequest.cluster_config:type_name -> machine.ClusterConfig
119, // 104: machine.GenerateConfigurationRequest.machine_config:type_name -> machine.MachineConfig
129, // 105: machine.GenerateConfigurationRequest.override_time:type_name -> google.protobuf.Timestamp
126, // 106: machine.GenerateConfigurationResponse.metadata:type_name -> common.Metadata
7, // 107: machine.MachineService.ApplyConfiguration:input_type -> machine.ApplyConfigurationRequest
12, // 108: machine.MachineService.Bootstrap:input_type -> machine.BootstrapRequest
69, // 109: machine.MachineService.Containers:input_type -> machine.ContainersRequest
52, // 110: machine.MachineService.Copy:input_type -> machine.CopyRequest
131, // 111: machine.MachineService.CPUInfo:input_type -> google.protobuf.Empty
131, // 112: machine.MachineService.DiskStats:input_type -> google.protobuf.Empty
73, // 113: machine.MachineService.Dmesg:input_type -> machine.DmesgRequest
19, // 114: machine.MachineService.Events:input_type -> machine.EventsRequest
111, // 115: machine.MachineService.EtcdMemberList:input_type -> machine.EtcdMemberListRequest
105, // 116: machine.MachineService.EtcdLeaveCluster:input_type -> machine.EtcdLeaveClusterRequest
108, // 117: machine.MachineService.EtcdForfeitLeadership:input_type -> machine.EtcdForfeitLeadershipRequest
124, // 118: machine.MachineService.GenerateConfiguration:input_type -> machine.GenerateConfigurationRequest
131, // 119: machine.MachineService.Hostname:input_type -> google.protobuf.Empty
131, // 120: machine.MachineService.Kubeconfig:input_type -> google.protobuf.Empty
53, // 121: machine.MachineService.List:input_type -> machine.ListRequest
54, // 122: machine.MachineService.DiskUsage:input_type -> machine.DiskUsageRequest
131, // 123: machine.MachineService.LoadAvg:input_type -> google.protobuf.Empty
64, // 124: machine.MachineService.Logs:input_type -> machine.LogsRequest
131, // 125: machine.MachineService.Memory:input_type -> google.protobuf.Empty
131, // 126: machine.MachineService.Mounts:input_type -> google.protobuf.Empty
131, // 127: machine.MachineService.NetworkDeviceStats:input_type -> google.protobuf.Empty
131, // 128: machine.MachineService.Processes:input_type -> google.protobuf.Empty
65, // 129: machine.MachineService.Read:input_type -> machine.ReadRequest
131, // 130: machine.MachineService.Reboot:input_type -> google.protobuf.Empty
78, // 131: machine.MachineService.Restart:input_type -> machine.RestartRequest
66, // 132: machine.MachineService.Rollback:input_type -> machine.RollbackRequest
22, // 133: machine.MachineService.Reset:input_type -> machine.ResetRequest
25, // 134: machine.MachineService.Recover:input_type -> machine.RecoverRequest
131, // 135: machine.MachineService.ServiceList:input_type -> google.protobuf.Empty
45, // 136: machine.MachineService.ServiceRestart:input_type -> machine.ServiceRestartRequest
39, // 137: machine.MachineService.ServiceStart:input_type -> machine.ServiceStartRequest
42, // 138: machine.MachineService.ServiceStop:input_type -> machine.ServiceStopRequest
131, // 139: machine.MachineService.Shutdown:input_type -> google.protobuf.Empty
81, // 140: machine.MachineService.Stats:input_type -> machine.StatsRequest
131, // 141: machine.MachineService.SystemStat:input_type -> google.protobuf.Empty
30, // 142: machine.MachineService.Upgrade:input_type -> machine.UpgradeRequest
131, // 143: machine.MachineService.Version:input_type -> google.protobuf.Empty
9, // 144: machine.MachineService.ApplyConfiguration:output_type -> machine.ApplyConfigurationResponse
14, // 145: machine.MachineService.Bootstrap:output_type -> machine.BootstrapResponse
72, // 146: machine.MachineService.Containers:output_type -> machine.ContainersResponse
132, // 147: machine.MachineService.Copy:output_type -> common.Data
96, // 148: machine.MachineService.CPUInfo:output_type -> machine.CPUInfoResponse
102, // 149: machine.MachineService.DiskStats:output_type -> machine.DiskStatsResponse
132, // 150: machine.MachineService.Dmesg:output_type -> common.Data
20, // 151: machine.MachineService.Events:output_type -> machine.Event
113, // 152: machine.MachineService.EtcdMemberList:output_type -> machine.EtcdMemberListResponse
107, // 153: machine.MachineService.EtcdLeaveCluster:output_type -> machine.EtcdLeaveClusterResponse
110, // 154: machine.MachineService.EtcdForfeitLeadership:output_type -> machine.EtcdForfeitLeadershipResponse
125, // 155: machine.MachineService.GenerateConfiguration:output_type -> machine.GenerateConfigurationResponse
88, // 156: machine.MachineService.Hostname:output_type -> machine.HostnameResponse
132, // 157: machine.MachineService.Kubeconfig:output_type -> common.Data
55, // 158: machine.MachineService.List:output_type -> machine.FileInfo
56, // 159: machine.MachineService.DiskUsage:output_type -> machine.DiskUsageInfo
90, // 160: machine.MachineService.LoadAvg:output_type -> machine.LoadAvgResponse
132, // 161: machine.MachineService.Logs:output_type -> common.Data
86, // 162: machine.MachineService.Memory:output_type -> machine.MemoryResponse
58, // 163: machine.MachineService.Mounts:output_type -> machine.MountsResponse
99, // 164: machine.MachineService.NetworkDeviceStats:output_type -> machine.NetworkDeviceStatsResponse
75, // 165: machine.MachineService.Processes:output_type -> machine.ProcessesResponse
132, // 166: machine.MachineService.Read:output_type -> common.Data
11, // 167: machine.MachineService.Reboot:output_type -> machine.RebootResponse
80, // 168: machine.MachineService.Restart:output_type -> machine.RestartResponse
68, // 169: machine.MachineService.Rollback:output_type -> machine.RollbackResponse
24, // 170: machine.MachineService.Reset:output_type -> machine.ResetResponse
27, // 171: machine.MachineService.Recover:output_type -> machine.RecoverResponse
34, // 172: machine.MachineService.ServiceList:output_type -> machine.ServiceListResponse
47, // 173: machine.MachineService.ServiceRestart:output_type -> machine.ServiceRestartResponse
41, // 174: machine.MachineService.ServiceStart:output_type -> machine.ServiceStartResponse
44, // 175: machine.MachineService.ServiceStop:output_type -> machine.ServiceStopResponse
29, // 176: machine.MachineService.Shutdown:output_type -> machine.ShutdownResponse
83, // 177: machine.MachineService.Stats:output_type -> machine.StatsResponse
92, // 178: machine.MachineService.SystemStat:output_type -> machine.SystemStatResponse
32, // 179: machine.MachineService.Upgrade:output_type -> machine.UpgradeResponse
61, // 180: machine.MachineService.Version:output_type -> machine.VersionResponse
144, // [144:181] is the sub-list for method output_type
107, // [107:144] is the sub-list for method input_type
107, // [107:107] is the sub-list for extension type_name
107, // [107:107] is the sub-list for extension extendee
0, // [0:107] is the sub-list for field type_name
}
func init() { file_machine_machine_proto_init() }

View File

@ -29,6 +29,7 @@ import (
clusterapi "github.com/talos-systems/talos/pkg/machinery/api/cluster"
"github.com/talos-systems/talos/pkg/machinery/api/common"
inspectapi "github.com/talos-systems/talos/pkg/machinery/api/inspect"
machineapi "github.com/talos-systems/talos/pkg/machinery/api/machine"
networkapi "github.com/talos-systems/talos/pkg/machinery/api/network"
resourceapi "github.com/talos-systems/talos/pkg/machinery/api/resource"
@ -57,8 +58,10 @@ type Client struct {
ClusterClient clusterapi.ClusterServiceClient
StorageClient storageapi.StorageServiceClient
ResourceClient resourceapi.ResourceServiceClient
InspectClient inspectapi.InspectServiceClient
Resources *ResourcesClient
Inspect *InspectClient
}
func (c *Client) resolveConfigContext() error {
@ -155,8 +158,10 @@ func New(ctx context.Context, opts ...OptionFunc) (c *Client, err error) {
c.ClusterClient = clusterapi.NewClusterServiceClient(c.conn)
c.StorageClient = storageapi.NewStorageServiceClient(c.conn)
c.ResourceClient = resourceapi.NewResourceServiceClient(c.conn)
c.InspectClient = inspectapi.NewInspectServiceClient(c.conn)
c.Resources = &ResourcesClient{c.ResourceClient}
c.Inspect = &InspectClient{c.InspectClient}
return c, nil
}

View File

@ -0,0 +1,30 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package client
import (
"context"
"github.com/golang/protobuf/ptypes/empty"
"google.golang.org/grpc"
inspectapi "github.com/talos-systems/talos/pkg/machinery/api/inspect"
)
// InspectClient provides access to inspect API.
type InspectClient struct {
client inspectapi.InspectServiceClient
}
// ControllerRuntimeDependencies returns graph describing dependencies between controllers.
func (c *InspectClient) ControllerRuntimeDependencies(ctx context.Context, callOptions ...grpc.CallOption) (*inspectapi.ControllerRuntimeDependenciesResponse, error) {
resp, err := c.client.ControllerRuntimeDependencies(ctx, &empty.Empty{}, callOptions...)
var filtered interface{}
filtered, err = FilterMessages(resp, err)
resp, _ = filtered.(*inspectapi.ControllerRuntimeDependenciesResponse) //nolint: errcheck
return resp, err
}

View File

@ -7,6 +7,7 @@ package config
import (
"context"
"crypto/tls"
"net"
"net/url"
"os"
"time"
@ -248,12 +249,13 @@ type ClusterConfig interface {
Token() Token
CertSANs() []string
CA() *x509.PEMEncodedCertificateAndKey
AggregatorCA() *x509.PEMEncodedCertificateAndKey
ServiceAccount() *x509.PEMEncodedKey
AESCBCEncryptionSecret() string
Config(machine.Type) (string, error)
Etcd() Etcd
Network() ClusterNetwork
LocalAPIServerPort() int
PodCheckpointer() PodCheckpointer
CoreDNS() CoreDNS
ExtraManifestURLs() []string
ExtraManifestHeaderMap() map[string]string
@ -268,6 +270,8 @@ type ClusterNetwork interface {
PodCIDR() string
ServiceCIDR() string
DNSDomain() string
APIServerIPs() ([]net.IP, error)
DNSServiceIPs() ([]net.IP, error)
}
// CNI defines the requirements for a config that pertains to Kubernetes
@ -325,13 +329,7 @@ type Token interface {
Secret() string
}
// PodCheckpointer defines the requirements for a config that pertains to bootkube
// pod-checkpointer options.
type PodCheckpointer interface {
Image() string
}
// CoreDNS defines the requirements for a config that pertains to bootkube
// CoreDNS defines the requirements for a config that pertains to CoreDNS
// coredns options.
type CoreDNS interface {
Image() string

View File

@ -129,10 +129,12 @@ func (i *Input) GetAPIServerSANs() []string {
// Certs holds the base64 encoded keys and certificates.
type Certs struct {
Admin *x509.PEMEncodedCertificateAndKey
Etcd *x509.PEMEncodedCertificateAndKey
K8s *x509.PEMEncodedCertificateAndKey
OS *x509.PEMEncodedCertificateAndKey
Admin *x509.PEMEncodedCertificateAndKey
Etcd *x509.PEMEncodedCertificateAndKey
K8s *x509.PEMEncodedCertificateAndKey
K8sAggregator *x509.PEMEncodedCertificateAndKey
K8sServiceAccount *x509.PEMEncodedKey
OS *x509.PEMEncodedCertificateAndKey
}
// Secrets holds the sensitive kubeadm data.
@ -186,12 +188,14 @@ func (c *SystemClock) SetFixedTimestamp(t time.Time) {
// NewSecretsBundle creates secrets bundle generating all secrets.
func NewSecretsBundle(clock Clock) (*SecretsBundle, error) {
var (
etcd *x509.CertificateAuthority
kubernetesCA *x509.CertificateAuthority
talosCA *x509.CertificateAuthority
trustdInfo *TrustdInfo
kubeadmTokens *Secrets
err error
etcd *x509.CertificateAuthority
kubernetesCA *x509.CertificateAuthority
aggregatorCA *x509.CertificateAuthority
serviceAccount *x509.RSAKey
talosCA *x509.CertificateAuthority
trustdInfo *TrustdInfo
kubeadmTokens *Secrets
err error
)
etcd, err = NewEtcdCA(clock.Now())
@ -204,11 +208,17 @@ func NewSecretsBundle(clock Clock) (*SecretsBundle, error) {
return nil, err
}
talosCA, err = NewTalosCA(clock.Now())
aggregatorCA, err = NewAggregatorCA(clock.Now())
if err != nil {
return nil, err
}
serviceAccount, err = x509.NewRSAKey()
if err != nil {
return nil, err
}
talosCA, err = NewTalosCA(clock.Now())
if err != nil {
return nil, err
}
@ -247,6 +257,13 @@ func NewSecretsBundle(clock Clock) (*SecretsBundle, error) {
Crt: kubernetesCA.CrtPEM,
Key: kubernetesCA.KeyPEM,
},
K8sAggregator: &x509.PEMEncodedCertificateAndKey{
Crt: aggregatorCA.CrtPEM,
Key: aggregatorCA.KeyPEM,
},
K8sServiceAccount: &x509.PEMEncodedKey{
Key: serviceAccount.KeyPEM,
},
OS: &x509.PEMEncodedCertificateAndKey{
Crt: talosCA.CrtPEM,
Key: talosCA.KeyPEM,
@ -258,9 +275,11 @@ func NewSecretsBundle(clock Clock) (*SecretsBundle, error) {
// NewSecretsBundleFromConfig creates secrets bundle using existing config.
func NewSecretsBundleFromConfig(clock Clock, c config.Provider) *SecretsBundle {
certs := &Certs{
K8s: c.Cluster().CA(),
Etcd: c.Cluster().Etcd().CA(),
OS: c.Machine().Security().CA(),
K8s: c.Cluster().CA(),
K8sAggregator: c.Cluster().AggregatorCA(),
K8sServiceAccount: c.Cluster().ServiceAccount(),
Etcd: c.Cluster().Etcd().CA(),
OS: c.Machine().Security().CA(),
}
trustd := &TrustdInfo{
@ -310,6 +329,18 @@ func NewKubernetesCA(currentTime time.Time) (ca *x509.CertificateAuthority, err
return x509.NewSelfSignedCertificateAuthority(opts...)
}
// NewAggregatorCA generates a CA for the Kubernetes aggregator/front-proxy.
func NewAggregatorCA(currentTime time.Time) (ca *x509.CertificateAuthority, err error) {
opts := []x509.Option{
x509.RSA(true),
x509.CommonName("front-proxy"),
x509.NotAfter(currentTime.Add(87600 * time.Hour)),
x509.NotBefore(currentTime),
}
return x509.NewSelfSignedCertificateAuthority(opts...)
}
// NewTalosCA generates a CA for the Talos PKI.
func NewTalosCA(currentTime time.Time) (ca *x509.CertificateAuthority, err error) {
opts := []x509.Option{

View File

@ -76,6 +76,8 @@ func initUd(in *Input) (*v1alpha1.Config, error) {
CNI: in.CNIConfig,
},
ClusterCA: in.Certs.K8s,
ClusterAggregatorCA: in.Certs.K8sAggregator,
ClusterServiceAccount: in.Certs.K8sServiceAccount,
BootstrapToken: in.Secrets.BootstrapToken,
ClusterAESCBCEncryptionSecret: in.Secrets.AESCBCEncryptionSecret,
}

View File

@ -10,6 +10,7 @@ import (
stdx509 "crypto/x509"
"fmt"
"log"
"net"
"net/url"
"os"
goruntime "runtime"
@ -18,6 +19,7 @@ import (
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/talos-systems/crypto/x509"
talosnet "github.com/talos-systems/net"
"github.com/talos-systems/talos/pkg/machinery/config"
"github.com/talos-systems/talos/pkg/machinery/config/encoder"
@ -289,6 +291,16 @@ func (c *ClusterConfig) CA() *x509.PEMEncodedCertificateAndKey {
return c.ClusterCA
}
// AggregatorCA implements the config.Provider interface.
func (c *ClusterConfig) AggregatorCA() *x509.PEMEncodedCertificateAndKey {
return c.ClusterAggregatorCA
}
// ServiceAccount implements the config.Provider interface.
func (c *ClusterConfig) ServiceAccount() *x509.PEMEncodedKey {
return c.ClusterServiceAccount
}
// AESCBCEncryptionSecret implements the config.Provider interface.
func (c *ClusterConfig) AESCBCEncryptionSecret() string {
return c.ClusterAESCBCEncryptionSecret
@ -631,6 +643,26 @@ func (c *ClusterConfig) ServiceCIDR() string {
return strings.Join(c.ClusterNetwork.ServiceSubnet, ",")
}
// APIServerIPs returns kube-apiserver IPs in the ServiceCIDR.
func (c *ClusterConfig) APIServerIPs() ([]net.IP, error) {
serviceCIDRs, err := talosnet.SplitCIDRs(c.ServiceCIDR())
if err != nil {
return nil, fmt.Errorf("failed to process Service CIDRs: %w", err)
}
return talosnet.NthIPInCIDRSet(serviceCIDRs, 1)
}
// DNSServiceIPs returns DNS service IPs in the ServiceCIDR.
func (c *ClusterConfig) DNSServiceIPs() ([]net.IP, error) {
serviceCIDRs, err := talosnet.SplitCIDRs(c.ServiceCIDR())
if err != nil {
return nil, fmt.Errorf("failed to process Service CIDRs: %w", err)
}
return talosnet.NthIPInCIDRSet(serviceCIDRs, 10)
}
// ExtraManifestURLs implements the config.Provider interface.
func (c *ClusterConfig) ExtraManifestURLs() []string {
return c.ExtraManifests
@ -641,15 +673,6 @@ func (c *ClusterConfig) ExtraManifestHeaderMap() map[string]string {
return c.ExtraManifestHeaders
}
// PodCheckpointer implements the config.Provider interface.
func (c *ClusterConfig) PodCheckpointer() config.PodCheckpointer {
if c.PodCheckpointerConfig == nil {
return &PodCheckpointer{}
}
return c.PodCheckpointerConfig
}
// CoreDNS implements the config.Provider interface.
func (c *ClusterConfig) CoreDNS() config.CoreDNS {
if c.CoreDNSConfig == nil {
@ -1074,11 +1097,6 @@ func (c *CoreDNS) Image() string {
return coreDNSImage
}
// Image implements the config.Provider interface.
func (p *PodCheckpointer) Image() string {
return p.PodCheckpointerImage
}
// CertLifetime implements the config.Provider interface.
func (a AdminKubeconfigConfig) CertLifetime() time.Duration {
if a.AdminKubeconfigCertLifetime == 0 {

View File

@ -114,6 +114,10 @@ var (
Key: []byte("LS0tLS1CRUdJTiBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0KTUM..."),
}
pemEncodedKeyExample *x509.PEMEncodedKey = &x509.PEMEncodedKey{
Key: []byte("LS0tLS1CRUdJTiBFRDI1NTE5IFBSSVZBVEUgS0VZLS0tLS0KTUM..."),
}
machineKubeletExample = &KubeletConfig{
KubeletImage: (&KubeletConfig{}).Image(),
KubeletExtraArgs: map[string]string{
@ -570,6 +574,20 @@ type ClusterConfig struct {
// value: pemEncodedCertificateExample
ClusterCA *x509.PEMEncodedCertificateAndKey `yaml:"ca,omitempty"`
// description: |
// The base64 encoded aggregator certificate authority used by Kubernetes for front-proxy certificate generation.
//
// This CA can be self-signed.
// examples:
// - name: AggregatorCA example.
// value: pemEncodedCertificateExample
ClusterAggregatorCA *x509.PEMEncodedCertificateAndKey `yaml:"aggregatorCA,omitempty"`
// description: |
// The base64 encoded private key for service account token generation.
// examples:
// - name: AggregatorCA example.
// value: pemEncodedKeyExample
ClusterServiceAccount *x509.PEMEncodedKey `yaml:"serviceAccount,omitempty"`
// description: |
// API server specific configuration options.
// examples:
// - value: clusterAPIServerExample
@ -606,7 +624,7 @@ type ClusterConfig struct {
CoreDNSConfig *CoreDNS `yaml:"coreDNS,omitempty"`
// description: |
// A list of urls that point to additional manifests.
// These will get automatically deployed by bootkube.
// These will get automatically deployed as part of the bootstrap.
// examples:
// - value: >
// []string{
@ -920,7 +938,7 @@ type ClusterNetworkConfig struct {
// The "name" key only supports options of "flannel" or "custom".
// URLs is only used if name is equal to "custom".
// URLs should point to the set of YAML files to be deployed.
// An empty struct or any other name will default to bootkube's flannel.
// An empty struct or any other name will default to Flannel CNI.
// examples:
// - value: clusterCustomCNIExample
CNI *CNIConfig `yaml:"cni,omitempty"`

View File

@ -225,7 +225,7 @@ func init() {
FieldName: "cluster",
},
}
ClusterConfigDoc.Fields = make([]encoder.Doc, 17)
ClusterConfigDoc.Fields = make([]encoder.Doc, 19)
ClusterConfigDoc.Fields[0].Name = "controlPlane"
ClusterConfigDoc.Fields[0].Type = "ControlPlaneConfig"
ClusterConfigDoc.Fields[0].Note = ""
@ -266,88 +266,102 @@ func init() {
ClusterConfigDoc.Fields[5].Comments[encoder.LineComment] = "The base64 encoded root certificate authority used by Kubernetes."
ClusterConfigDoc.Fields[5].AddExample("ClusterCA example.", pemEncodedCertificateExample)
ClusterConfigDoc.Fields[6].Name = "apiServer"
ClusterConfigDoc.Fields[6].Type = "APIServerConfig"
ClusterConfigDoc.Fields[6].Name = "aggregatorCA"
ClusterConfigDoc.Fields[6].Type = "PEMEncodedCertificateAndKey"
ClusterConfigDoc.Fields[6].Note = ""
ClusterConfigDoc.Fields[6].Description = "API server specific configuration options."
ClusterConfigDoc.Fields[6].Comments[encoder.LineComment] = "API server specific configuration options."
ClusterConfigDoc.Fields[6].Description = "The base64 encoded aggregator certificate authority used by Kubernetes for front-proxy certificate generation.\n\nThis CA can be self-signed."
ClusterConfigDoc.Fields[6].Comments[encoder.LineComment] = "The base64 encoded aggregator certificate authority used by Kubernetes for front-proxy certificate generation."
ClusterConfigDoc.Fields[6].AddExample("", clusterAPIServerExample)
ClusterConfigDoc.Fields[7].Name = "controllerManager"
ClusterConfigDoc.Fields[7].Type = "ControllerManagerConfig"
ClusterConfigDoc.Fields[6].AddExample("AggregatorCA example.", pemEncodedCertificateExample)
ClusterConfigDoc.Fields[7].Name = "serviceAccount"
ClusterConfigDoc.Fields[7].Type = "PEMEncodedKey"
ClusterConfigDoc.Fields[7].Note = ""
ClusterConfigDoc.Fields[7].Description = "Controller manager server specific configuration options."
ClusterConfigDoc.Fields[7].Comments[encoder.LineComment] = "Controller manager server specific configuration options."
ClusterConfigDoc.Fields[7].Description = "The base64 encoded private key for service account token generation."
ClusterConfigDoc.Fields[7].Comments[encoder.LineComment] = "The base64 encoded private key for service account token generation."
ClusterConfigDoc.Fields[7].AddExample("", clusterControllerManagerExample)
ClusterConfigDoc.Fields[8].Name = "proxy"
ClusterConfigDoc.Fields[8].Type = "ProxyConfig"
ClusterConfigDoc.Fields[7].AddExample("AggregatorCA example.", pemEncodedKeyExample)
ClusterConfigDoc.Fields[8].Name = "apiServer"
ClusterConfigDoc.Fields[8].Type = "APIServerConfig"
ClusterConfigDoc.Fields[8].Note = ""
ClusterConfigDoc.Fields[8].Description = "Kube-proxy server-specific configuration options"
ClusterConfigDoc.Fields[8].Comments[encoder.LineComment] = "Kube-proxy server-specific configuration options"
ClusterConfigDoc.Fields[8].Description = "API server specific configuration options."
ClusterConfigDoc.Fields[8].Comments[encoder.LineComment] = "API server specific configuration options."
ClusterConfigDoc.Fields[8].AddExample("", clusterProxyExample)
ClusterConfigDoc.Fields[9].Name = "scheduler"
ClusterConfigDoc.Fields[9].Type = "SchedulerConfig"
ClusterConfigDoc.Fields[8].AddExample("", clusterAPIServerExample)
ClusterConfigDoc.Fields[9].Name = "controllerManager"
ClusterConfigDoc.Fields[9].Type = "ControllerManagerConfig"
ClusterConfigDoc.Fields[9].Note = ""
ClusterConfigDoc.Fields[9].Description = "Scheduler server specific configuration options."
ClusterConfigDoc.Fields[9].Comments[encoder.LineComment] = "Scheduler server specific configuration options."
ClusterConfigDoc.Fields[9].Description = "Controller manager server specific configuration options."
ClusterConfigDoc.Fields[9].Comments[encoder.LineComment] = "Controller manager server specific configuration options."
ClusterConfigDoc.Fields[9].AddExample("", clusterSchedulerExample)
ClusterConfigDoc.Fields[10].Name = "etcd"
ClusterConfigDoc.Fields[10].Type = "EtcdConfig"
ClusterConfigDoc.Fields[9].AddExample("", clusterControllerManagerExample)
ClusterConfigDoc.Fields[10].Name = "proxy"
ClusterConfigDoc.Fields[10].Type = "ProxyConfig"
ClusterConfigDoc.Fields[10].Note = ""
ClusterConfigDoc.Fields[10].Description = "Etcd specific configuration options."
ClusterConfigDoc.Fields[10].Comments[encoder.LineComment] = "Etcd specific configuration options."
ClusterConfigDoc.Fields[10].Description = "Kube-proxy server-specific configuration options"
ClusterConfigDoc.Fields[10].Comments[encoder.LineComment] = "Kube-proxy server-specific configuration options"
ClusterConfigDoc.Fields[10].AddExample("", clusterEtcdExample)
ClusterConfigDoc.Fields[11].Name = "podCheckpointer"
ClusterConfigDoc.Fields[11].Type = "PodCheckpointer"
ClusterConfigDoc.Fields[10].AddExample("", clusterProxyExample)
ClusterConfigDoc.Fields[11].Name = "scheduler"
ClusterConfigDoc.Fields[11].Type = "SchedulerConfig"
ClusterConfigDoc.Fields[11].Note = ""
ClusterConfigDoc.Fields[11].Description = "Pod Checkpointer specific configuration options."
ClusterConfigDoc.Fields[11].Comments[encoder.LineComment] = "Pod Checkpointer specific configuration options."
ClusterConfigDoc.Fields[11].Description = "Scheduler server specific configuration options."
ClusterConfigDoc.Fields[11].Comments[encoder.LineComment] = "Scheduler server specific configuration options."
ClusterConfigDoc.Fields[11].AddExample("", clusterPodCheckpointerExample)
ClusterConfigDoc.Fields[12].Name = "coreDNS"
ClusterConfigDoc.Fields[12].Type = "CoreDNS"
ClusterConfigDoc.Fields[11].AddExample("", clusterSchedulerExample)
ClusterConfigDoc.Fields[12].Name = "etcd"
ClusterConfigDoc.Fields[12].Type = "EtcdConfig"
ClusterConfigDoc.Fields[12].Note = ""
ClusterConfigDoc.Fields[12].Description = "Core DNS specific configuration options."
ClusterConfigDoc.Fields[12].Comments[encoder.LineComment] = "Core DNS specific configuration options."
ClusterConfigDoc.Fields[12].Description = "Etcd specific configuration options."
ClusterConfigDoc.Fields[12].Comments[encoder.LineComment] = "Etcd specific configuration options."
ClusterConfigDoc.Fields[12].AddExample("", clusterCoreDNSExample)
ClusterConfigDoc.Fields[13].Name = "extraManifests"
ClusterConfigDoc.Fields[13].Type = "[]string"
ClusterConfigDoc.Fields[12].AddExample("", clusterEtcdExample)
ClusterConfigDoc.Fields[13].Name = "podCheckpointer"
ClusterConfigDoc.Fields[13].Type = "PodCheckpointer"
ClusterConfigDoc.Fields[13].Note = ""
ClusterConfigDoc.Fields[13].Description = "A list of urls that point to additional manifests.\nThese will get automatically deployed by bootkube."
ClusterConfigDoc.Fields[13].Comments[encoder.LineComment] = "A list of urls that point to additional manifests."
ClusterConfigDoc.Fields[13].Description = "Pod Checkpointer specific configuration options."
ClusterConfigDoc.Fields[13].Comments[encoder.LineComment] = "Pod Checkpointer specific configuration options."
ClusterConfigDoc.Fields[13].AddExample("", []string{
ClusterConfigDoc.Fields[13].AddExample("", clusterPodCheckpointerExample)
ClusterConfigDoc.Fields[14].Name = "coreDNS"
ClusterConfigDoc.Fields[14].Type = "CoreDNS"
ClusterConfigDoc.Fields[14].Note = ""
ClusterConfigDoc.Fields[14].Description = "Core DNS specific configuration options."
ClusterConfigDoc.Fields[14].Comments[encoder.LineComment] = "Core DNS specific configuration options."
ClusterConfigDoc.Fields[14].AddExample("", clusterCoreDNSExample)
ClusterConfigDoc.Fields[15].Name = "extraManifests"
ClusterConfigDoc.Fields[15].Type = "[]string"
ClusterConfigDoc.Fields[15].Note = ""
ClusterConfigDoc.Fields[15].Description = "A list of urls that point to additional manifests.\nThese will get automatically deployed as part of the bootstrap."
ClusterConfigDoc.Fields[15].Comments[encoder.LineComment] = "A list of urls that point to additional manifests."
ClusterConfigDoc.Fields[15].AddExample("", []string{
"https://www.example.com/manifest1.yaml",
"https://www.example.com/manifest2.yaml",
})
ClusterConfigDoc.Fields[14].Name = "extraManifestHeaders"
ClusterConfigDoc.Fields[14].Type = "map[string]string"
ClusterConfigDoc.Fields[14].Note = ""
ClusterConfigDoc.Fields[14].Description = "A map of key value pairs that will be added while fetching the ExtraManifests."
ClusterConfigDoc.Fields[14].Comments[encoder.LineComment] = "A map of key value pairs that will be added while fetching the ExtraManifests."
ClusterConfigDoc.Fields[16].Name = "extraManifestHeaders"
ClusterConfigDoc.Fields[16].Type = "map[string]string"
ClusterConfigDoc.Fields[16].Note = ""
ClusterConfigDoc.Fields[16].Description = "A map of key value pairs that will be added while fetching the ExtraManifests."
ClusterConfigDoc.Fields[16].Comments[encoder.LineComment] = "A map of key value pairs that will be added while fetching the ExtraManifests."
ClusterConfigDoc.Fields[14].AddExample("", map[string]string{
ClusterConfigDoc.Fields[16].AddExample("", map[string]string{
"Token": "1234567",
"X-ExtraInfo": "info",
})
ClusterConfigDoc.Fields[15].Name = "adminKubeconfig"
ClusterConfigDoc.Fields[15].Type = "AdminKubeconfigConfig"
ClusterConfigDoc.Fields[15].Note = ""
ClusterConfigDoc.Fields[15].Description = "Settings for admin kubeconfig generation.\nCertificate lifetime can be configured."
ClusterConfigDoc.Fields[15].Comments[encoder.LineComment] = "Settings for admin kubeconfig generation."
ClusterConfigDoc.Fields[17].Name = "adminKubeconfig"
ClusterConfigDoc.Fields[17].Type = "AdminKubeconfigConfig"
ClusterConfigDoc.Fields[17].Note = ""
ClusterConfigDoc.Fields[17].Description = "Settings for admin kubeconfig generation.\nCertificate lifetime can be configured."
ClusterConfigDoc.Fields[17].Comments[encoder.LineComment] = "Settings for admin kubeconfig generation."
ClusterConfigDoc.Fields[15].AddExample("", clusterAdminKubeconfigExample)
ClusterConfigDoc.Fields[16].Name = "allowSchedulingOnMasters"
ClusterConfigDoc.Fields[16].Type = "bool"
ClusterConfigDoc.Fields[16].Note = ""
ClusterConfigDoc.Fields[16].Description = "Allows running workload on master nodes."
ClusterConfigDoc.Fields[16].Comments[encoder.LineComment] = "Allows running workload on master nodes."
ClusterConfigDoc.Fields[16].Values = []string{
ClusterConfigDoc.Fields[17].AddExample("", clusterAdminKubeconfigExample)
ClusterConfigDoc.Fields[18].Name = "allowSchedulingOnMasters"
ClusterConfigDoc.Fields[18].Type = "bool"
ClusterConfigDoc.Fields[18].Note = ""
ClusterConfigDoc.Fields[18].Description = "Allows running workload on master nodes."
ClusterConfigDoc.Fields[18].Comments[encoder.LineComment] = "Allows running workload on master nodes."
ClusterConfigDoc.Fields[18].Values = []string{
"true",
"yes",
"false",
@ -772,7 +786,7 @@ func init() {
ClusterNetworkConfigDoc.Fields[0].Name = "cni"
ClusterNetworkConfigDoc.Fields[0].Type = "CNIConfig"
ClusterNetworkConfigDoc.Fields[0].Note = ""
ClusterNetworkConfigDoc.Fields[0].Description = "The CNI used.\nComposed of \"name\" and \"url\".\nThe \"name\" key only supports options of \"flannel\" or \"custom\".\nURLs is only used if name is equal to \"custom\".\nURLs should point to the set of YAML files to be deployed.\nAn empty struct or any other name will default to bootkube's flannel."
ClusterNetworkConfigDoc.Fields[0].Description = "The CNI used.\nComposed of \"name\" and \"url\".\nThe \"name\" key only supports options of \"flannel\" or \"custom\".\nURLs is only used if name is equal to \"custom\".\nURLs should point to the set of YAML files to be deployed.\nAn empty struct or any other name will default to Flannel CNI."
ClusterNetworkConfigDoc.Fields[0].Comments[encoder.LineComment] = "The CNI used."
ClusterNetworkConfigDoc.Fields[0].AddExample("", clusterCustomCNIExample)

View File

@ -123,6 +123,9 @@ const (
// PATH defines all locations where executables are stored.
PATH = "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:" + cni.DefaultCNIDir
// KubernetesDefaultCertificateValidityDuration specifies default certificate duration for Kubernetes generated certificates.
KubernetesDefaultCertificateValidityDuration = time.Hour * 24 * 365
// DefaultCertificatesDir is the path the the Kubernetes PKI directory.
DefaultCertificatesDir = "/etc/kubernetes/pki"
@ -132,18 +135,6 @@ const (
// KubernetesCAKey is the path to the root CA private key.
KubernetesCAKey = DefaultCertificatesDir + "/" + "ca.key"
// KubernetesSACert is the path to the SA certificate.
KubernetesSACert = DefaultCertificatesDir + "/" + "sa.crt"
// KubernetesSAKey is the path to the SA private key.
KubernetesSAKey = DefaultCertificatesDir + "/" + "sa.key"
// KubernetesFrontProxyCACert is the path to the front proxy CA certificate.
KubernetesFrontProxyCACert = DefaultCertificatesDir + "/" + "fp.crt"
// KubernetesFrontProxyCAKey is the path to the front proxy CA private key.
KubernetesFrontProxyCAKey = DefaultCertificatesDir + "/" + "fp.key"
// KubernetesEtcdCACert is the path to the etcd CA certificate.
KubernetesEtcdCACert = EtcdPKIPath + "/" + "ca.crt"
@ -156,21 +147,9 @@ const (
// KubernetesEtcdPeerKey is the path to the etcd CA private key.
KubernetesEtcdPeerKey = EtcdPKIPath + "/" + "peer.key"
// KubernetesEtcdServerCert defines etcd's server certificate name.
KubernetesEtcdServerCert = EtcdPKIPath + "/" + "client.crt"
// KubernetesEtcdServerKey defines etcd's server key name.
KubernetesEtcdServerKey = EtcdPKIPath + "/" + "client.key"
// KubernetesEtcdListenClientPort defines the port etcd listen on for client traffic.
KubernetesEtcdListenClientPort = "2379"
// KubernetesAPIServerEtcdClientCert defines apiserver's etcd client certificate name.
KubernetesAPIServerEtcdClientCert = DefaultCertificatesDir + "/" + "apiserver-etcd-client.crt"
// KubernetesAPIServerEtcdClientKey defines apiserver's etcd client key name.
KubernetesAPIServerEtcdClientKey = DefaultCertificatesDir + "/" + "apiserver-etcd-client.key"
// KubernetesAdminCertCommonName defines CN property of Kubernetes admin certificate.
KubernetesAdminCertCommonName = "apiserver-kubelet-client"
@ -180,10 +159,31 @@ const (
// KubernetesAdminCertDefaultLifetime defines default lifetime for Kubernetes generated admin certificate.
KubernetesAdminCertDefaultLifetime = 365 * 24 * time.Hour
// KubebernetesStaticSecretsDir defines ephemeral directory which contains rendered secrets for controlplane components.
KubebernetesStaticSecretsDir = "/system/secrets/kubernetes"
// KubernetesAPIServerSecretsDir defines ephemeral directory with kube-apiserver secrets.
KubernetesAPIServerSecretsDir = KubebernetesStaticSecretsDir + "/" + "kube-apiserver"
// KubernetesControllerManagerSecretsDir defines ephemeral directory with kube-controller-manager secrets.
KubernetesControllerManagerSecretsDir = KubebernetesStaticSecretsDir + "/" + "kube-controller-manager"
// KubernetesSchedulerSecretsDir defines ephemeral directory with kube-scheduler secrets.
KubernetesSchedulerSecretsDir = KubebernetesStaticSecretsDir + "/" + "kube-scheduler"
// KubernetesRunUser defines UID to run control plane components.
KubernetesRunUser = 65534
// KubeletBootstrapKubeconfig is the path to the kubeconfig required to
// bootstrap the kubelet.
KubeletBootstrapKubeconfig = "/etc/kubernetes/bootstrap-kubeconfig"
// KubeletPort is the kubelet port for secure API.
KubeletPort = 10250
// KubeletPKIDir is the path to the directory where kubelet stores issues certificates and keys.
KubeletPKIDir = "/var/lib/kubelet/pki"
// DefaultKubernetesVersion is the default target version of the control plane.
DefaultKubernetesVersion = "1.20.2"
@ -214,18 +214,12 @@ const (
// DefaultCoreDNSVersion is the default version for the CoreDNS.
DefaultCoreDNSVersion = "1.7.0"
// RecoveryKubeconfig is the path to kubeconfig used temporarily while recovering control plane.
RecoveryKubeconfig = "/etc/kubernetes/kubeconfig"
// LabelNodeRoleMaster is the node label required by a control plane node.
LabelNodeRoleMaster = "node-role.kubernetes.io/master"
// LabelNodeRoleControlPlane is the node label required by a control plane node.
LabelNodeRoleControlPlane = "node-role.kubernetes.io/control-plane"
// AssetsDirectory is the directory that contains all bootstrap assets.
AssetsDirectory = "/etc/kubernetes/assets"
// ManifestsDirectory is the directory that contains all static manifests.
ManifestsDirectory = "/etc/kubernetes/manifests"
@ -241,6 +235,9 @@ const (
// EtcdTalosEtcdUpgradeMutex is the etcd mutex prefix to be used to set an etcd upgrade lock.
EtcdTalosEtcdUpgradeMutex = EtcdRootTalosKey + ":etcdUpgradeMutex"
// EtcdTalosManifestApplyMutex is the etcd election .
EtcdTalosManifestApplyMutex = EtcdRootTalosKey + ":manifestApplyMutex"
// EtcdImage is the reposistory for the etcd image.
EtcdImage = "gcr.io/etcd-development/etcd"
@ -378,15 +375,12 @@ const (
// initialized.
InitializedKey = "initialized"
// BootkubeAssetTimeout is the constant in bootkube implementation.
BootkubeAssetTimeout = 20 * time.Minute
// BootkubeRunTimeout is the timeout to run bootkube.
BootkubeRunTimeout = BootkubeAssetTimeout + 5*time.Minute
// BootTimeout is the timeout to run all services.
BootTimeout = 15 * time.Minute
// NodeReadyTimeout is the timeout to wait for the node to be ready (CNI to be running).
// For bootstrap API, this includes time to run bootkube.
NodeReadyTimeout = BootkubeRunTimeout
// For bootstrap API, this includes time to run bootstrap.
NodeReadyTimeout = BootTimeout
)
// See https://linux.die.net/man/3/klogctl

View File

@ -15,10 +15,10 @@ require (
github.com/onsi/ginkgo v1.11.0 // indirect
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.6.1
github.com/talos-systems/crypto v0.2.1-0.20201203131813-e0dd56ac4745
github.com/talos-systems/net v0.2.0
github.com/talos-systems/os-runtime v0.0.0-20210119124441-98acf0d2d332
github.com/stretchr/testify v1.7.0
github.com/talos-systems/crypto v0.2.1-0.20210125160556-cf75519cab82
github.com/talos-systems/net v0.2.1-0.20210121122956-005a94f8b36b
github.com/talos-systems/os-runtime v0.0.0-20210126185717-734f1e1cee9e
golang.org/x/net v0.0.0-20200707034311-ab3426394381 // indirect
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 // indirect
golang.org/x/text v0.3.3 // indirect
@ -26,5 +26,5 @@ require (
google.golang.org/grpc v1.29.1
google.golang.org/protobuf v1.25.0
gopkg.in/yaml.v2 v2.2.8 // indirect
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

View File

@ -4,6 +4,7 @@ github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj4
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg=
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
@ -87,13 +88,15 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/talos-systems/crypto v0.2.1-0.20201203131813-e0dd56ac4745 h1:Smw6ebFiEiwrkaOD2hEYYb+xkIhQTMZNq3WVYKLszB8=
github.com/talos-systems/crypto v0.2.1-0.20201203131813-e0dd56ac4745/go.mod h1:KwqG+jANKU1FNQIapmioHQ5fkovY1DJkAqMenjYBGh0=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/talos-systems/crypto v0.2.1-0.20210125160556-cf75519cab82 h1:5TsM3o/yJJF6kakHyPee88D0yWNNDNKZJ2NCX9MFsKk=
github.com/talos-systems/crypto v0.2.1-0.20210125160556-cf75519cab82/go.mod h1:OXCK52Q0dzm88YRG4VdTBdidkPUtqrCxCyW7bUs4DAw=
github.com/talos-systems/go-retry v0.2.0/go.mod h1:HiXQqyVStZ35uSY/MTLWVvQVmC3lIW2MS5VdDaMtoKM=
github.com/talos-systems/net v0.2.0 h1:QJ2ofYboG1Zjew9b+3RAjtLIfL0mIONGuc6/LyO68MM=
github.com/talos-systems/net v0.2.0/go.mod h1:VreSAyRmxMtqussAHSKMKkJQa1YwBTSVfkmE4Jydam4=
github.com/talos-systems/os-runtime v0.0.0-20210119124441-98acf0d2d332 h1:Ib5HAIpv8GjAfdKSzcPfvUPN2mbzYwsre61Sogjt/kk=
github.com/talos-systems/os-runtime v0.0.0-20210119124441-98acf0d2d332/go.mod h1:pQ8E1nmr8SODM9TD9HXH5HlzgyfyeCO8yug4x6fDKlQ=
github.com/talos-systems/net v0.2.1-0.20210121122956-005a94f8b36b h1:y3mBkTJdW7cUn+ff53TZN0yyWCpjS6XrVmlx+vx9pwA=
github.com/talos-systems/net v0.2.1-0.20210121122956-005a94f8b36b/go.mod h1:VreSAyRmxMtqussAHSKMKkJQa1YwBTSVfkmE4Jydam4=
github.com/talos-systems/os-runtime v0.0.0-20210126185717-734f1e1cee9e h1:HrAdgwnXhVr9LlWjpc+kejkLVUpTRKbNTAJe7H+kRXM=
github.com/talos-systems/os-runtime v0.0.0-20210126185717-734f1e1cee9e/go.mod h1:+E9CUVoYpReh0nhOEvFpy7pwLiyq0700WF03I06giyk=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
@ -173,7 +176,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -15,7 +15,7 @@ type Adapter struct {
cluster.ConfigClientProvider
cluster.KubernetesClient
cluster.APICrashDumper
cluster.APIBoostrapper
cluster.APIBootstrapper
cluster.Info
cluster.ApplyConfigClient
}
@ -73,7 +73,7 @@ func NewAdapter(clusterInfo provision.Cluster, opts ...provision.Option) *Adapte
ClientProvider: &configProvider,
Info: info,
},
APIBoostrapper: cluster.APIBoostrapper{
APIBootstrapper: cluster.APIBootstrapper{
ClientProvider: &configProvider,
Info: info,
},

View File

@ -28,6 +28,15 @@ description: Talos gRPC API reference.
- [Health](#health.Health)
- [inspect/inspect.proto](#inspect/inspect.proto)
- [ControllerDependencyEdge](#inspect.ControllerDependencyEdge)
- [ControllerRuntimeDependenciesResponse](#inspect.ControllerRuntimeDependenciesResponse)
- [ControllerRuntimeDependency](#inspect.ControllerRuntimeDependency)
- [DependencyEdgeType](#inspect.DependencyEdgeType)
- [InspectService](#inspect.InspectService)
- [machine/machine.proto](#machine/machine.proto)
- [ApplyConfiguration](#machine.ApplyConfiguration)
- [ApplyConfigurationRequest](#machine.ApplyConfigurationRequest)
@ -480,6 +489,97 @@ Common metadata message nested in all reply message types
<a name="inspect/inspect.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## inspect/inspect.proto
<a name="inspect.ControllerDependencyEdge"></a>
### ControllerDependencyEdge
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| controller_name | [string](#string) | | |
| edge_type | [DependencyEdgeType](#inspect.DependencyEdgeType) | | |
| resource_namespace | [string](#string) | | |
| resource_type | [string](#string) | | |
| resource_id | [string](#string) | | |
<a name="inspect.ControllerRuntimeDependenciesResponse"></a>
### ControllerRuntimeDependenciesResponse
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| messages | [ControllerRuntimeDependency](#inspect.ControllerRuntimeDependency) | repeated | |
<a name="inspect.ControllerRuntimeDependency"></a>
### ControllerRuntimeDependency
The ControllerRuntimeDependency message contains the graph of controller-resource dependencies.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| metadata | [common.Metadata](#common.Metadata) | | |
| edges | [ControllerDependencyEdge](#inspect.ControllerDependencyEdge) | repeated | |
<!-- end messages -->
<a name="inspect.DependencyEdgeType"></a>
### DependencyEdgeType
| Name | Number | Description |
| ---- | ------ | ----------- |
| MANAGES | 0 | |
| STRONG | 1 | |
| WEAK | 2 | |
<!-- end enums -->
<!-- end HasExtensions -->
<a name="inspect.InspectService"></a>
### InspectService
The inspect service definition.
InspectService provides auxilary API to inspect OS internals.
| Method Name | Request Type | Response Type | Description |
| ----------- | ------------ | ------------- | ------------|
| ControllerRuntimeDependencies | [.google.protobuf.Empty](#google.protobuf.Empty) | [ControllerRuntimeDependenciesResponse](#inspect.ControllerRuntimeDependenciesResponse) | |
<!-- end services -->
<a name="machine/machine.proto"></a>
<p align="right"><a href="#top">Top</a></p>
@ -2125,6 +2225,7 @@ rpc servicestart
| service | [string](#string) | | |
| action | [ServiceStateEvent.Action](#machine.ServiceStateEvent.Action) | | |
| message | [string](#string) | | |
| health | [ServiceHealth](#machine.ServiceHealth) | | |

View File

@ -1105,6 +1105,68 @@ talosctl images [flags]
* [talosctl](#talosctl) - A CLI for out-of-band management of Kubernetes nodes created by Talos
## talosctl inspect dependencies
Inspect controller-resource dependencies as graphviz graph.
### Synopsis
Inspect controller-resource dependencies as graphviz graph.
Pipe the output of the command through the "dot" program (part of graphviz package)
to render the graph:
talosctl inspect dependencies | dot -Tpng > graph.png
```
talosctl inspect dependencies [flags]
```
### Options
```
-h, --help help for dependencies
--with-resources display live resource information with dependencies
```
### Options inherited from parent commands
```
--context string Context to be used in command
-e, --endpoints strings override default endpoints in Talos configuration
-n, --nodes strings target the specified nodes
--talosconfig string The path to the Talos configuration file (default "/home/user/.talos/config")
```
### SEE ALSO
* [talosctl inspect](#talosctl-inspect) - Inspect internals of Talos
## talosctl inspect
Inspect internals of Talos
### Options
```
-h, --help help for inspect
```
### Options inherited from parent commands
```
--context string Context to be used in command
-e, --endpoints strings override default endpoints in Talos configuration
-n, --nodes strings target the specified nodes
--talosconfig string The path to the Talos configuration file (default "/home/user/.talos/config")
```
### SEE ALSO
* [talosctl](#talosctl) - A CLI for out-of-band management of Kubernetes nodes created by Talos
* [talosctl inspect dependencies](#talosctl-inspect-dependencies) - Inspect controller-resource dependencies as graphviz graph.
## talosctl interfaces
List network interfaces
@ -1816,6 +1878,7 @@ A CLI for out-of-band management of Kubernetes nodes created by Talos
* [talosctl get](#talosctl-get) - Get a specific resource or list of resources.
* [talosctl health](#talosctl-health) - Check cluster health
* [talosctl images](#talosctl-images) - List the default images used by Talos
* [talosctl inspect](#talosctl-inspect) - Inspect internals of Talos
* [talosctl interfaces](#talosctl-interfaces) - List network interfaces
* [talosctl kubeconfig](#talosctl-kubeconfig) - Download the admin kubeconfig from the node
* [talosctl list](#talosctl-list) - Retrieve a directory listing

View File

@ -831,6 +831,57 @@ ca:
```
</div>
<hr />
<div class="dd">
<code>aggregatorCA</code> <i>PEMEncodedCertificateAndKey</i>
</div>
<div class="dt">
The base64 encoded aggregator certificate authority used by Kubernetes for front-proxy certificate generation.
This CA can be self-signed.
Examples:
``` yaml
aggregatorCA:
crt: TFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVSklla05DTUhGLi4u
key: TFMwdExTMUNSVWRKVGlCRlJESTFOVEU1SUZCU1NWWkJWRVVnUzBWWkxTMHRMUzBLVFVNLi4u
```
</div>
<hr />
<div class="dd">
<code>serviceAccount</code> <i>PEMEncodedKey</i>
</div>
<div class="dt">
The base64 encoded private key for service account token generation.
Examples:
``` yaml
serviceAccount:
key: TFMwdExTMUNSVWRKVGlCRlJESTFOVEU1SUZCU1NWWkJWRVVnUzBWWkxTMHRMUzBLVFVNLi4u
```
</div>
<hr />
@ -1036,7 +1087,7 @@ coreDNS:
<div class="dt">
A list of urls that point to additional manifests.
These will get automatically deployed by bootkube.
These will get automatically deployed as part of the bootstrap.
@ -2327,7 +2378,7 @@ Composed of "name" and "url".
The "name" key only supports options of "flannel" or "custom".
URLs is only used if name is equal to "custom".
URLs should point to the set of YAML files to be deployed.
An empty struct or any other name will default to bootkube's flannel.
An empty struct or any other name will default to Flannel CNI.