Skip to content

Commit

Permalink
feat: Support ignition metadata
Browse files Browse the repository at this point in the history
This adds support for retrieving the instance ID from ignition metadata, as used by CoreOS and Flatcar Linux
  • Loading branch information
hrak committed Jun 20, 2024
1 parent 40fbd87 commit 3a1a315
Showing 1 changed file with 55 additions and 2 deletions.
57 changes: 55 additions & 2 deletions pkg/cloud/metadata.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package cloud

import (
"bufio"
"context"
"encoding/json"
"fmt"
"log/slog"
"os"
"strings"

Expand All @@ -13,9 +13,12 @@ import (

const (
cloudInitInstanceFilePath = "/run/cloud-init/instance-data.json"
ignitionMetadataFilePath = "/run/metadata/coreos"
cloudStackCloudName = "cloudstack"
)

// metadataInstanceID tries to find the instance ID from either the environment variable NODE_ID,
// or cloud-init or ignition metadata. Returns empty string if not found in any of these sources.
func (c *client) metadataInstanceID(ctx context.Context) string {
logger := klog.FromContext(ctx)
logger.V(4).Info("Attempting to retrieve metadata from envvar NODE_ID")
Expand All @@ -39,13 +42,32 @@ func (c *client) metadataInstanceID(ctx context.Context) string {

return ciData.V1.InstanceID
}
slog.Error("cloud-init instance ID is not provided")
logger.Error(nil, "cloud-init instance ID is not provided")
} else if os.IsNotExist(err) {
logger.V(4).Info("File " + cloudInitInstanceFilePath + " does not exist")
} else {
logger.Error(err, "Cannot read file "+cloudInitInstanceFilePath)
}

// Try Ignition (CoreOS / Flatcar)
logger.V(4).Info("Trying with ignition")
if _, err := os.Stat(ignitionMetadataFilePath); err == nil {
logger.V(4).Info("File " + ignitionMetadataFilePath + " exists")
instanceID, err := c.readIgnition(ctx, ignitionMetadataFilePath)
if err != nil {
logger.Error(err, "Cannot read ignition metadata")
} else if instanceID != "" {
logger.V(4).Info("Found CloudStack VM ID from ignition", "nodeID", instanceID)

return instanceID
}
logger.Error(nil, "Failed to find instance ID in ignition metadata")
} else if os.IsNotExist(err) {
logger.V(4).Info("File " + ignitionMetadataFilePath + " does not exist")
} else {
logger.Error(err, "Cannot read file "+ignitionMetadataFilePath)
}

logger.V(4).Info("CloudStack VM ID not found in meta-data")

return ""
Expand Down Expand Up @@ -87,3 +109,34 @@ func (c *client) readCloudInit(ctx context.Context, instanceFilePath string) (*c

return &data, nil
}

// readIgnition reads the ignition metadata file and returns the instance ID, or empty string if not found.
func (c *client) readIgnition(ctx context.Context, instanceFilePath string) (string, error) {
logger := klog.FromContext(ctx)

f, err := os.Open(instanceFilePath)
if err != nil {
logger.Error(err, "Cannot read file "+instanceFilePath)

return "", err
}
defer f.Close()

instanceID := ""
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, "COREOS_CLOUDSTACK_INSTANCE_ID") {
lineSplit := strings.SplitAfter(line, "=")
if len(lineSplit) == 2 {
instanceID = strings.SplitAfter(line, "=")[1]
}
}
}

if err := scanner.Err(); err != nil {
logger.Error(err, "Error scanning ignition metadata")
}

return instanceID, nil
}

0 comments on commit 3a1a315

Please sign in to comment.