Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[v13] rework instance hbs to be more scalable and to track upgraders #28847

Merged
merged 1 commit into from Jul 10, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2,164 changes: 1,325 additions & 839 deletions api/client/proto/authservice.pb.go

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions api/proto/teleport/legacy/client/proto/authservice.proto
Expand Up @@ -2157,6 +2157,18 @@ message InventoryStatusSummary {
// Connected is a summary of the instances connected to the current auth server. Only set if
// the Connected flag in the status request is true.
repeated UpstreamInventoryHello Connected = 1 [(gogoproto.nullable) = false];

// InstanceCount is the total number of instance resources aggregated.
uint32 InstanceCount = 2;

// VersionCounts aggregates unique version counts.
map<string, uint32> VersionCounts = 3;

// UpgraderCounts aggregates the unique upgrader counts.
map<string, uint32> UpgraderCounts = 4;

// ServiceCounts aggregates the number of services.
map<string, uint32> ServiceCounts = 5;
}

// InventoryConnectedServiceCountsRequest requests inventory connected service counts.
Expand Down
16 changes: 16 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Expand Up @@ -644,6 +644,10 @@ message InstanceSpecV1 {
(gogoproto.nullable) = false,
(gogoproto.jsontag) = "control_log,omitempty"
];

// 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"];
}

// InstanceControlLogEntry represents an entry in a given instance's control log. The control log of
Expand Down Expand Up @@ -704,6 +708,18 @@ message InstanceFilter {
// expose *at least* one of the listed services. This is in contrast to service matching in version
// directives which match instances that expose a *at most* the listed services.
repeated string Services = 3 [(gogoproto.casttype) = "SystemRole"];

// ExternalUpgrader matches instance upgrader if specified.
string ExternalUpgrader = 4;

// NoExtUpgrader explicitly matches instances for which no upgrader is defined.
bool NoExtUpgrader = 5;

// OlderThanVersion is an optional exclusive upper version bound.
string OlderThanVersion = 6;

// NewerThanVersion is an optional exclusive lower version bound.
string NewerThanVersion = 7;
}

// ServerV2 represents a Node, App, Database, Proxy or Auth server in a Teleport cluster.
Expand Down
80 changes: 80 additions & 0 deletions api/types/instance.go
Expand Up @@ -17,8 +17,10 @@ limitations under the License.
package types

import (
"strings"
"time"

"github.com/coreos/go-semver/semver"
"github.com/gravitational/trace"
"golang.org/x/exp/slices"

Expand All @@ -39,14 +41,82 @@ func (f InstanceFilter) Match(i Instance) bool {
return false
}

if fv, ok := parseVersionRelaxed(f.OlderThanVersion); ok {
if iv, ok := parseVersionRelaxed(i.GetTeleportVersion()); ok {
if !iv.LessThan(fv) {
return false
}
}
}

if fv, ok := parseVersionRelaxed(f.NewerThanVersion); ok {
iv, ok := parseVersionRelaxed(i.GetTeleportVersion())

if !ok {
// treat instances with invalid versions are less/older than
// valid versions.
return false
}

if !fv.LessThan(iv) {
return false
}
}

// if Services was specified, ensure instance has at least one of the listed services.
if len(f.Services) != 0 && slices.IndexFunc(f.Services, i.HasService) == -1 {
return false
}

if f.ExternalUpgrader != "" && f.ExternalUpgrader != i.GetExternalUpgrader() {
return false
}

// empty upgrader matches all, so we have a separate bool flag for
// specifically matching instances with no ext upgrader defined.
if f.NoExtUpgrader && i.GetExternalUpgrader() != "" {
return false
}

return true
}

// shorthandChars are expected characters in version shorthand (e.g. "1" or "1.0" are shorthand for "1.0.0").
const shorthandChars = "0123456789."

// normalizeVersionShorthand attempts to convert go-style semver into the stricter semver
// notation expected by coreos/go-semver.
func normalizeVersionShorthand(version string) string {
version = strings.TrimPrefix(version, "v")
for _, c := range version {
if !strings.ContainsRune(shorthandChars, c) {
return version
}
}

switch strings.Count(version, ".") {
case 0:
return version + ".0.0"
case 1:
return version + ".0"
default:
return version
}
}

// parseVersionRelaxed wraps standard semver parsing with shorthand normalization.
func parseVersionRelaxed(version string) (ver semver.Version, ok bool) {
if version == "" {
return semver.Version{}, false
}

if ver.Set(normalizeVersionShorthand(version)) != nil {
return semver.Version{}, false
}

return ver, true
}

// Instance describes the configuration/status of a unique teleport server identity. Each
// instance may be running one or more teleport services, and may have multiple processes
// associated with it.
Expand Down Expand Up @@ -81,6 +151,12 @@ type Instance interface {
// and resource-level expiry values can be reevaluated.
SetLastSeen(time.Time)

// GetExternalUpgrader gets the upgrader value as represented in the most recent
// hello message from this instance. This value corresponds to the TELEPORT_EXT_UPGRADER
// env var that is set when agents are configured to export schedule values to external
// upgraders.
GetExternalUpgrader() 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 @@ -194,6 +270,10 @@ func (i *InstanceV1) SetLastSeen(t time.Time) {
i.Spec.LastSeen = t.UTC()
}

func (i *InstanceV1) GetExternalUpgrader() string {
return i.Spec.ExternalUpgrader
}

func (i *InstanceV1) GetControlLog() []InstanceControlLogEntry {
return i.Spec.ControlLog
}
Expand Down