Skip to content

Commit

Permalink
providers: add "akamai" provider
Browse files Browse the repository at this point in the history
The "akamai" provider adds support for retrieving an ignition
configuration from Akamai Connected Cloud's (a.k.a. Linode) [Metadata
Service][1].

See flatcar/Flatcar#1404

[1]: https://www.linode.com/docs/products/compute/compute-instances/guides/metadata/
  • Loading branch information
Nick Saika committed Mar 26, 2024
1 parent 7d066ae commit 3c3821e
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/supported-platforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ nav_order: 8

Ignition is currently only supported for the following platforms:

* [Akamai Connected Cloud] (`akamai`) - Ignition will read its configuration from the instance userdata. Cloud SSH keys and network configuration are handled separately.
* [Alibaba Cloud] (`aliyun`) - Ignition will read its configuration from the instance userdata. Cloud SSH keys are handled separately.
* [Apple Hypervisor] (`applehv`) - Ignition will read its configuration using an HTTP GET over a vsock connection with its host on port 1024.
* [Amazon Web Services] (`aws`) - Ignition will read its configuration from the instance userdata. Cloud SSH keys are handled separately.
Expand Down Expand Up @@ -36,6 +37,7 @@ Ignition is under active development, so this list may grow over time.

For most cloud providers, cloud SSH keys and custom network configuration are handled by [Afterburn].

[Akamai Connected Cloud]: https://www.linode.com
[Alibaba Cloud]: https://www.alibabacloud.com/product/ecs
[Apple Hypervisor]: https://developer.apple.com/documentation/hypervisor
[Amazon Web Services]: https://aws.amazon.com/ec2/
Expand Down
79 changes: 79 additions & 0 deletions internal/providers/akamai/akamai.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright 2024 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package akamai provides platform support for Akamai Connected Cloud
// (previously known as Linode).
package akamai

import (
"encoding/base64"
"fmt"
"net/http"
"net/url"

"github.com/coreos/ignition/v2/config/v3_5_experimental/types"
"github.com/coreos/ignition/v2/internal/platform"
"github.com/coreos/ignition/v2/internal/providers/util"
"github.com/coreos/ignition/v2/internal/resource"

"github.com/coreos/vcontext/report"
)

func init() {
platform.Register(platform.Provider{
Name: "akamai",
Fetch: fetchConfig,
Init: initFetcher,
})
}

var (
tokenURL = url.URL{Scheme: "http", Host: "169.254.169.254", Path: "/v1/token"}
userdataURL = url.URL{Scheme: "http", Host: "169.254.169.254", Path: "/v1/user-data"}
)

func fetchConfig(f *resource.Fetcher) (types.Config, report.Report, error) {
encoded, err := f.FetchToBuffer(userdataURL, resource.FetchOptions{})
if err != nil {
return types.Config{}, report.Report{}, err
}

// The Linode Metadata Service requires userdata to be base64-encoded
// when it is uploaded.
data := make([]byte, base64.StdEncoding.DecodedLen(len(encoded)))
if _, err := base64.StdEncoding.Decode(data, encoded); err != nil {
return types.Config{}, report.Report{}, fmt.Errorf("decode base64: %w", err)
}

return util.ParseConfig(f.Logger, data)
}

func initFetcher(f *resource.Fetcher) error {
token, err := f.FetchToBuffer(tokenURL, resource.FetchOptions{
HTTPVerb: http.MethodPut,
Headers: http.Header{
"Metadata-Token-Expiry-Seconds": []string{"3600"},
},
})

// NOTE: ErrNotFound could mean the instance is running in a region
// where the Metadata Service has not been deployed.
if err != nil {
return fmt.Errorf("generate metadata api token: %w", err)
}

f.AkamaiMetadataToken = string(token)

return nil
}
4 changes: 4 additions & 0 deletions internal/resource/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ type Fetcher struct {
// It is used when fetching resources from GCS.
GCSSession *storage.Client

// AkamaiMetadataToken holds the token returned by the Metadata Service
// and is required for subsequent requests.
AkamaiMetadataToken string

// Whether to only attempt fetches which can be performed offline. This
// currently only includes the "data" scheme. Other schemes will result in
// ErrNeedNet. In the future, we can improve on this by dropping this
Expand Down

0 comments on commit 3c3821e

Please sign in to comment.