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

feat(Landscape): Send hostagent uid to WSL landscape client #360

Merged
merged 18 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
b033eb1
Config now holds the Landscape host-agent UID
EduardGomezEscandell Oct 24, 2023
7ca542e
Config now holds the Landscape host-agent UID
EduardGomezEscandell Oct 24, 2023
b5d5bfe
Refactor config.ProvisioningTasks
EduardGomezEscandell Oct 24, 2023
f2776d8
WSL Service API now supports Landscape hostagent UID
EduardGomezEscandell Oct 24, 2023
8fb116a
Update gRPC generated code
EduardGomezEscandell Oct 24, 2023
83f64cd
LandscapeConfigure provisioning task now also sends hostagentUID
EduardGomezEscandell Oct 24, 2023
10dd221
Landscape service no longer holds the hostagent UID
EduardGomezEscandell Oct 24, 2023
ab1f31c
Update Landscape service tests
EduardGomezEscandell Oct 24, 2023
9a54158
WSL-Pro-Service: write host-agent UID into landscape.conf
EduardGomezEscandell Oct 24, 2023
e85641d
Update golden files
EduardGomezEscandell Oct 24, 2023
fc85d6f
Only send landscape config task if we've made contact already
EduardGomezEscandell Oct 24, 2023
b1d40ae
Config test: de-duplicate getter tests
EduardGomezEscandell Oct 24, 2023
08b7a0d
Config: implement tests for Landscape UID getter and setter
EduardGomezEscandell Oct 24, 2023
c8b3916
Config: get rid of default registry values
EduardGomezEscandell Oct 24, 2023
963073d
Reordered meta-test in config_tests.go
EduardGomezEscandell Oct 25, 2023
0adac69
Remove redundant t.Helper in config meta-test
EduardGomezEscandell Oct 25, 2023
bc4ba7e
Rename test parameter to emptyUID
EduardGomezEscandell Oct 25, 2023
0eb4402
Improved variable naming in config test
EduardGomezEscandell Oct 25, 2023
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
114 changes: 86 additions & 28 deletions windows-agent/internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,9 @@ import (
const (
registryPath = `Software\Canonical\UbuntuPro`

defaultToken = ""

fieldLandscapeClientConfig = "LandscapeClientConfig"
defaultLandscapeClientConfig = ""

fieldLandscapeAgentURL = "LandscapeAgentURL"
defaultLandscapeAgentURL = ""
fieldLandscapeClientConfig = "LandscapeClientConfig"
fieldLandscapeAgentURL = "LandscapeAgentURL"
fieldLandscapeAgentUID = "LandscapeAgentUID"
)

// fieldsProToken contains the fields in the registry where each source will store its token.
Expand Down Expand Up @@ -60,6 +56,7 @@ type Config struct {
type configData struct {
landscapeClientConfig string
landscapeAgentURL string
landscapeAgentUID string
}

// SubscriptionSource indicates the method the subscription was acquired.
Expand Down Expand Up @@ -130,6 +127,12 @@ func (c *Config) Subscription(ctx context.Context) (token string, source Subscri
return "", SubscriptionNone, fmt.Errorf("could not load: %v", err)
}

token, source = c.subscription()
return token, source, nil
}

// subscription is the unsafe version of Subscription. It returns the ProToken and the method it was acquired with (if any).
func (c *Config) subscription() (token string, source SubscriptionSource) {
for src := subscriptionMaxPriority - 1; src > SubscriptionNone; src-- {
token, ok := c.proTokens[src]
if !ok {
Expand All @@ -139,10 +142,10 @@ func (c *Config) Subscription(ctx context.Context) (token string, source Subscri
continue
}

return token, src, nil
return token, src
}

return "", SubscriptionNone, nil
return "", SubscriptionNone
}

// IsReadOnly returns whether the registry can be written to.
Expand All @@ -162,20 +165,29 @@ func (c *Config) IsReadOnly() (b bool, err error) {

// ProvisioningTasks returns a slice of all tasks to be submitted upon first contact with a distro.
func (c *Config) ProvisioningTasks(ctx context.Context, distroName string) ([]task.Task, error) {
token, _, err := c.Subscription(ctx)
if err != nil {
return nil, err
}
var taskList []task.Task

taskList := []task.Task{
tasks.ProAttachment{Token: token},
// Refresh data from registry
c.mu.Lock()
defer c.mu.Unlock()

if err := c.load(ctx); err != nil {
return nil, fmt.Errorf("could not load: %v", err)
}

if conf, err := c.LandscapeClientConfig(ctx); err != nil {
log.Errorf(ctx, "Could not generate provisioning task LandscapeConfigure: %v", err)
} else {
landscape := tasks.LandscapeConfigure{Config: conf}
taskList = append(taskList, landscape)
// Ubuntu Pro attachment
proToken, _ := c.subscription()
taskList = append(taskList, tasks.ProAttachment{Token: proToken})

if c.data.landscapeClientConfig == "" {
// Landscape unregistration: always
taskList = append(taskList, tasks.LandscapeConfigure{})
} else if c.data.landscapeAgentUID != "" {
// Landcape registration: only when we have a UID assigned
taskList = append(taskList, tasks.LandscapeConfigure{
Config: c.data.landscapeClientConfig,
HostagentUID: c.data.landscapeAgentUID,
})
didrocks marked this conversation as resolved.
Show resolved Hide resolved
}

return taskList, nil
Expand Down Expand Up @@ -227,6 +239,41 @@ func (c *Config) LandscapeClientConfig(ctx context.Context) (string, error) {
return c.data.landscapeClientConfig, nil
}

// LandscapeAgentUID returns the UID assigned to this agent by the Landscape server.
// An empty string is returned if no UID has been assigned.
func (c *Config) LandscapeAgentUID(ctx context.Context) (string, error) {
c.mu.Lock()
defer c.mu.Unlock()

if err := c.load(ctx); err != nil {
return "", fmt.Errorf("could not load: %v", err)
}

return c.data.landscapeAgentUID, nil
}

// SetLandscapeAgentUID overrides the Landscape agent UID.
func (c *Config) SetLandscapeAgentUID(ctx context.Context, uid string) error {
c.mu.Lock()
defer c.mu.Unlock()

// Load before dumping to avoid overriding recent changes to registry
if err := c.load(ctx); err != nil {
return err
}

old := c.data.landscapeAgentUID
c.data.landscapeAgentUID = uid

if err := c.dump(); err != nil {
log.Errorf(ctx, "Could not update landscape agent UID in registry, UID will be ignored: %v", err)
c.data.landscapeAgentUID = old
return err
}

return nil
}

func (c *Config) load(ctx context.Context) (err error) {
defer decorate.OnError(&err, "could not load data for Config")

Expand All @@ -251,8 +298,6 @@ func (c *Config) loadRegistry(ctx context.Context) (proTokens map[SubscriptionSo
k, err := c.registry.HKCUOpenKey(registryPath, registry.READ)
if errors.Is(err, registry.ErrKeyNotExist) {
log.Debug(ctx, "Registry key does not exist, using default values")
data.landscapeAgentURL = defaultLandscapeAgentURL
data.landscapeClientConfig = defaultLandscapeClientConfig
return proTokens, data, nil
}
if err != nil {
Expand All @@ -261,7 +306,7 @@ func (c *Config) loadRegistry(ctx context.Context) (proTokens map[SubscriptionSo
defer c.registry.CloseKey(k)

for source, field := range fieldsProToken {
proToken, e := c.readValue(ctx, k, field, defaultToken)
proToken, e := c.readValue(ctx, k, field)
if e != nil {
err = errors.Join(err, fmt.Errorf("could not read %q: %v", field, e))
continue
Expand All @@ -278,24 +323,29 @@ func (c *Config) loadRegistry(ctx context.Context) (proTokens map[SubscriptionSo
return nil, data, err
}

data.landscapeAgentURL, err = c.readValue(ctx, k, fieldLandscapeAgentURL, defaultLandscapeAgentURL)
data.landscapeAgentURL, err = c.readValue(ctx, k, fieldLandscapeAgentURL)
if err != nil {
return proTokens, data, err
}

data.landscapeClientConfig, err = c.readValue(ctx, k, fieldLandscapeClientConfig)
if err != nil {
return proTokens, data, err
}

data.landscapeClientConfig, err = c.readValue(ctx, k, fieldLandscapeClientConfig, defaultLandscapeClientConfig)
data.landscapeAgentUID, err = c.readValue(ctx, k, fieldLandscapeAgentUID)
if err != nil {
return proTokens, data, err
}

return proTokens, data, nil
}

func (c *Config) readValue(ctx context.Context, key uintptr, field string, defaultValue string) (string, error) {
func (c *Config) readValue(ctx context.Context, key uintptr, field string) (string, error) {
value, err := c.registry.ReadValue(key, field)
if errors.Is(err, registry.ErrFieldNotExist) {
log.Debugf(ctx, "Registry value %q does not exist, defaulting to %q", field, defaultValue)
return defaultValue, nil
log.Debugf(ctx, "Registry value %q does not exist, defaulting to empty", field)
return "", nil
}
if err != nil {
return "", err
Expand Down Expand Up @@ -328,6 +378,14 @@ func (c *Config) dump() (err error) {
return fmt.Errorf("could not write into registry key: %v", err)
}

if err := c.registry.WriteValue(k, fieldLandscapeAgentUID, c.data.landscapeAgentUID); err != nil {
return fmt.Errorf("could not write into registry key: %v", err)
}

if err := c.registry.WriteValue(k, fieldLandscapeAgentUID, c.data.landscapeAgentUID); err != nil {
return fmt.Errorf("could not write into registry key: %v", err)
}

return nil
}

Expand Down
Loading
Loading