Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,673 changes: 863 additions & 810 deletions api/client/proto/authservice.pb.go

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions api/proto/teleport/legacy/client/proto/authservice.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2035,6 +2035,8 @@ message UpstreamInventoryHello {
// ExternalUpgrader identifies the external upgrader that the instance is configured to
// export schedules to (e.g. 'kube'). Empty if no upgrader is defined.
string ExternalUpgrader = 5;
// ExternalUpgraderVersion identifies the external upgrader version. Empty if no upgrader is defined.
string ExternalUpgraderVersion = 6;
}

// UpstreamInventoryAgentMetadata is the message sent up the inventory control stream containing
Expand Down
3 changes: 3 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,9 @@ message InstanceSpecV1 {
// ExternalUpgrader identifies the external upgrader that the instance is configured to
// export schedules to (e.g. 'kube'). Empty if no upgrader is defined.
string ExternalUpgrader = 7 [(gogoproto.jsontag) = "ext_upgrader,omitempty"];

// ExternalUpgraderVersion identifies the external upgrader version. Empty if no upgrader is defined.
string ExternalUpgraderVersion = 8 [(gogoproto.jsontag) = "ext_upgrader_version,omitempty"];
}

// InstanceControlLogEntry represents an entry in a given instance's control log. The control log of
Expand Down
8 changes: 8 additions & 0 deletions api/types/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ type Instance interface {
// upgraders.
GetExternalUpgrader() string

// GetExternalUpgraderVersion gets the reported upgrader version. This value corresponds
// to the TELEPORT_EXT_UPGRADER_VERSION env var that is set when agents are configured.
GetExternalUpgraderVersion() string

// SyncLogAndResourceExpiry filters expired entries from the control log and updates
// the resource-level expiry. All calculations are performed relative to the value of
// the LastSeen field, and the supplied TTL is used only as a default. The actual TTL
Expand Down Expand Up @@ -274,6 +278,10 @@ func (i *InstanceV1) GetExternalUpgrader() string {
return i.Spec.ExternalUpgrader
}

func (i *InstanceV1) GetExternalUpgraderVersion() string {
return i.Spec.ExternalUpgraderVersion
}

func (i *InstanceV1) GetControlLog() []InstanceControlLogEntry {
return i.Spec.ControlLog
}
Expand Down
2,920 changes: 1,483 additions & 1,437 deletions api/types/types.pb.go

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ If you have a Teleport Enterprise Cloud account, you can find agents that need t

```code
$ tctl inventory ls --upgrader=none
Server ID Hostname Services Version Upgrader
------------------------------------ ----------------- -------- ------- --------
4fb2d97d-884a-4566-b477-c805d477df09 agent.example.com Node v1.2.3 none
Server ID Hostname Services Agent Version Upgrader Upgrader Version
------------------------------------ ----------------- -------- ------------- -------- ----------------
4fb2d97d-884a-4566-b477-c805d477df09 agent.example.com Node v1.2.3 none none
...
```

Expand All @@ -62,9 +62,27 @@ your oldest agents, you can limit your search using the `--older-than` filter:

```code
$ tctl inventory ls --upgrader=none --older-than=v1.2.3
Server ID Hostname Services Version Upgrader
------------------------------------ --------------- -------- ------- --------
1e6578b6-9530-448e-8013-d32641324abb old.example.com Node v1.1.1 none
Server ID Hostname Services Agent Version Upgrader Upgrader Version
------------------------------------ --------------- -------- ------------- -------- ----------------
1e6578b6-9530-448e-8013-d32641324abb old.example.com Node v1.1.1 none none
...
```

The `tctl inventory ls` command will also display the installed version of the Teleport Upgrader, which is versioned independently from Teleport itself:
```code
$ tctl inventory ls
Server ID Hostname Services Agent Version Upgrader Upgrader Version
------------------------------------ ----------------- -------- ------------- -------- ----------------
4fb2d97d-884a-4566-b477-c805d477df09 agent.example.com Node v1.2.3 unit v14.2.0
...
```

If the Upgrader Version displays `none`, that means the Upgrader version is too old to report the version:
```code
$ tctl inventory ls
Server ID Hostname Services Agent Version Upgrader Upgrader Version
------------------------------------ ----------------- -------- ------------- -------- ----------------
4fb2d97d-884a-4566-b477-c805d477df09 agent.example.com Node v1.2.3 unit none
...
```

Expand Down
2 changes: 2 additions & 0 deletions examples/chart/teleport-kube-agent/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ spec:
{{- if .Values.updater.enabled }}
- name: TELEPORT_EXT_UPGRADER
value: kube
- name: TELEPORT_EXT_UPGRADER_VERSION
value: {{ include "teleport-kube-agent.version" . }}
{{- end }}
{{- if (gt (len .Values.extraEnv) 0) }}
{{- toYaml .Values.extraEnv | nindent 8 }}
Expand Down
2 changes: 2 additions & 0 deletions examples/chart/teleport-kube-agent/templates/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ spec:
{{- if .Values.updater.enabled }}
- name: TELEPORT_EXT_UPGRADER
value: kube
- name: TELEPORT_EXT_UPGRADER_VERSION
value: {{ include "teleport-kube-agent.version" . }}
{{- end }}
{{- if .Values.tls.existingCASecretName }}
- name: SSL_CERT_FILE
Expand Down
21 changes: 21 additions & 0 deletions examples/chart/teleport-kube-agent/tests/deployment_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -719,3 +719,24 @@ tests:
- equal:
path: spec.template.spec.containers[0].securityContext
value: null

- it: should enable maintenance schedule export when updater is enabled if action is Upgrade
template: deployment.yaml
values:
- ../.lint/updater.yaml
set:
# unit test does not support lookup functions, so to test the behavior we use this undoc value
# https://github.com/helm/helm/issues/8137
unitTestUpgrade: true
teleportVersionOverride: 13.4.5
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: TELEPORT_EXT_UPGRADER
value: kube
- contains:
path: spec.template.spec.containers[0].env
content:
name: TELEPORT_EXT_UPGRADER_VERSION
value: 13.4.5
Original file line number Diff line number Diff line change
Expand Up @@ -713,14 +713,20 @@ tests:
- it: should enable maintenance schedule export when updater is enabled
template: statefulset.yaml
values:
- ../.lint/existing-tls-secret-with-ca.yaml
- ../.lint/updater.yaml
set:
teleportVersionOverride: 13.4.5
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: TELEPORT_EXT_UPGRADER
value: kube
- contains:
path: spec.template.spec.containers[0].env
content:
name: TELEPORT_EXT_UPGRADER_VERSION
value: 13.4.5

- it: should set the installation method environment variable
template: statefulset.yaml
Expand Down
15 changes: 12 additions & 3 deletions lib/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,10 @@ var (
Name: teleport.MetricUpgraderCounts,
Help: "Tracks the number of instances advertising each upgrader",
},
[]string{teleport.TagUpgrader},
[]string{
teleport.TagUpgrader,
teleport.TagVersion,
},
)

accessRequestsCreatedMetric = prometheus.NewCounterVec(
Expand Down Expand Up @@ -1117,8 +1120,14 @@ func (a *Server) doInstancePeriodics(ctx context.Context) {
// set instance metric values
totalInstancesMetric.Set(float64(imp.TotalInstances()))
enrolledInUpgradesMetric.Set(float64(imp.TotalEnrolledInUpgrades()))
for _, upgrader := range []string{types.UpgraderKindKubeController, types.UpgraderKindSystemdUnit} {
upgraderCountsMetric.WithLabelValues(upgrader).Set(float64(imp.InstancesWithUpgrader(upgrader)))

for upgraderType, upgraderVersions := range imp.upgraderCounts {
for version, count := range upgraderVersions {
upgraderCountsMetric.With(prometheus.Labels{
teleport.TagUpgrader: upgraderType,
teleport.TagVersion: version,
}).Set(float64(count))
}
}

// create/delete upgrade enroll prompt as appropriate
Expand Down
20 changes: 10 additions & 10 deletions lib/auth/periodic.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,39 +101,39 @@ func inspectVersionCounts(counts map[string]int) (median string, total int, ok b

// instanceMetricsPeriodic is an aggregator for general instance metrics.
type instanceMetricsPeriodic struct {
upgraderCounts map[string]int
upgraderCounts map[string]map[string]int
totalInstances int
}

func newInstanceMetricsPeriodic() *instanceMetricsPeriodic {
return &instanceMetricsPeriodic{
upgraderCounts: make(map[string]int),
upgraderCounts: make(map[string]map[string]int),
}
}

// VisitInstance adds an instance to ongoing aggregations.
func (i *instanceMetricsPeriodic) VisitInstance(instance types.Instance) {
i.totalInstances++
if upgrader := instance.GetExternalUpgrader(); upgrader != "" {
i.upgraderCounts[upgrader]++
if _, exists := i.upgraderCounts[upgrader]; !exists {
i.upgraderCounts[upgrader] = make(map[string]int)
}
i.upgraderCounts[upgrader][instance.GetExternalUpgraderVersion()]++
}
}

// TotalEnrolledInUpgrades gets the total number of instances that have some upgrader defined.
func (i *instanceMetricsPeriodic) TotalEnrolledInUpgrades() int {
var total int
for _, count := range i.upgraderCounts {
total += count
for _, upgraderVersion := range i.upgraderCounts {
for _, count := range upgraderVersion {
total += count
}
}

return total
}

// InstancesWithUpgrader gets the number of instances that advertise the given upgrader.
func (i *instanceMetricsPeriodic) InstancesWithUpgrader(upgrader string) int {
return i.upgraderCounts[upgrader]
}

// TotalInstances gets the total number of known instances.
func (i *instanceMetricsPeriodic) TotalInstances() int {
return i.totalInstances
Expand Down
80 changes: 64 additions & 16 deletions lib/auth/periodic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,67 +29,115 @@ import (
func TestInstanceMetricsPeriodic(t *testing.T) {
tts := []struct {
desc string
specs []types.InstanceSpecV1
expectedCounts map[string]map[string]int
upgraders []string
expectCounts map[string]int
expectEnrolled int
}{
{
desc: "mixed",
specs: []types.InstanceSpecV1{
{ExternalUpgrader: "kube", ExternalUpgraderVersion: "13.0.0"},
{ExternalUpgrader: "kube", ExternalUpgraderVersion: "14.0.0"},
{ExternalUpgrader: "unit", ExternalUpgraderVersion: "13.0.0"},
{},
{ExternalUpgrader: "unit", ExternalUpgraderVersion: "14.0.0"},
{},
},
upgraders: []string{
"kube",
"kube",
"unit",
"",
"unit",
"",
},
expectCounts: map[string]int{
"kube": 1,
"unit": 2,
expectedCounts: map[string]map[string]int{
"kube": {
"13.0.0": 1,
"14.0.0": 1,
},
"unit": {
"13.0.0": 1,
"14.0.0": 1,
},
},
expectEnrolled: 3,
expectEnrolled: 4,
},
{
desc: "all-unenrolled",
specs: []types.InstanceSpecV1{
{},
{},
},
upgraders: []string{
"",
"",
},
expectedCounts: map[string]map[string]int{},
},
{
desc: "all-enrolled",
specs: []types.InstanceSpecV1{
{ExternalUpgrader: "kube", ExternalUpgraderVersion: "13.0.0"},
{ExternalUpgrader: "kube", ExternalUpgraderVersion: "13.0.0"},
{ExternalUpgrader: "unit", ExternalUpgraderVersion: "13.0.0"},
{ExternalUpgrader: "unit", ExternalUpgraderVersion: "13.0.0"},
},
upgraders: []string{
"kube",
"kube",
"unit",
"unit",
},
expectCounts: map[string]int{
"kube": 2,
"unit": 2,
expectedCounts: map[string]map[string]int{
"kube": {
"13.0.0": 2,
},
"unit": {
"13.0.0": 2,
},
},
expectEnrolled: 4,
},
{
desc: "nothing",
desc: "nil version",
specs: []types.InstanceSpecV1{
{ExternalUpgrader: "kube"},
{ExternalUpgrader: "unit"},
},
upgraders: []string{
"kube",
"unit",
},
expectedCounts: map[string]map[string]int{
"kube": {
"": 1,
},
"unit": {
"": 1,
},
},
expectEnrolled: 2,
},
{
desc: "nothing",
expectedCounts: map[string]map[string]int{},
},
}

for _, tt := range tts {
t.Run(tt.desc, func(t *testing.T) {
periodic := newInstanceMetricsPeriodic()

for _, upgrader := range tt.upgraders {
instance, err := types.NewInstance(uuid.New().String(), types.InstanceSpecV1{
ExternalUpgrader: upgrader,
})
for _, upgrader := range tt.specs {
instance, err := types.NewInstance(uuid.New().String(), upgrader)
require.NoError(t, err)

periodic.VisitInstance(instance)
}

for upgrader, count := range tt.expectCounts {
require.Equal(t, count, periodic.InstancesWithUpgrader(upgrader), "upgrader=%q, tt=%q", upgrader, tt.desc)
}
require.Equal(t, tt.expectedCounts, periodic.upgraderCounts, "tt=%q", tt.desc)

require.Equal(t, tt.expectEnrolled, periodic.TotalEnrolledInUpgrades(), "tt=%q", tt.desc)

Expand Down
Loading