-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
platform: implement the kola elements for Akamai
Signed-off-by: Mathieu Tortuyaux <[email protected]>
- Loading branch information
Showing
5 changed files
with
270 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// Copyright The Mantle Authors. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package akamai | ||
|
||
import ( | ||
"context" | ||
"crypto/rand" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/flatcar/mantle/platform" | ||
"github.com/flatcar/mantle/platform/conf" | ||
) | ||
|
||
type cluster struct { | ||
*platform.BaseCluster | ||
flight *flight | ||
} | ||
|
||
func (bc *cluster) NewMachine(userdata *conf.UserData) (platform.Machine, error) { | ||
conf, err := bc.RenderUserData(userdata, map[string]string{ | ||
"$public_ipv4": "${COREOS_CUSTOM_PUBLIC_IPV4}", | ||
"$private_ipv4": "${COREOS_CUSTOM_PRIVATE_IPV4}", | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Hack to workaround CT inheritance. | ||
// Can be dropped once we remove CT dependency. | ||
// https://github.com/flatcar/Flatcar/issues/1386 | ||
conf.AddSystemdUnitDropin("coreos-metadata.service", "00-custom-metadata.conf", `[Service] | ||
ExecStartPost=/usr/bin/sed -i "s/AKAMAI/CUSTOM/" /run/metadata/flatcar | ||
ExecStartPost=/usr/bin/sed -i "s/PRIVATE_IPV4_0/PRIVATE_IPV4/" /run/metadata/flatcar | ||
ExecStartPost=/usr/bin/sed -i "s/PUBLIC_IPV4_0/PUBLIC_IPV4/" /run/metadata/flatcar | ||
ExecStartPost=/usr/bin/sed -i "s#/32##" /run/metadata/flatcar | ||
`) | ||
|
||
instance, err := bc.flight.api.CreateServer(context.TODO(), bc.vmname(), conf.String()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
mach := &machine{ | ||
cluster: bc, | ||
mach: instance, | ||
} | ||
|
||
// machine to destroy | ||
m := mach | ||
defer func() { | ||
if m != nil { | ||
m.Destroy() | ||
} | ||
}() | ||
|
||
mach.dir = filepath.Join(bc.RuntimeConf().OutputDir, mach.ID()) | ||
if err := os.Mkdir(mach.dir, 0777); err != nil { | ||
return nil, err | ||
} | ||
|
||
confPath := filepath.Join(mach.dir, "ignition.json") | ||
if err := conf.WriteFile(confPath); err != nil { | ||
return nil, err | ||
} | ||
|
||
if mach.journal, err = platform.NewJournal(mach.dir); err != nil { | ||
return nil, err | ||
} | ||
|
||
if err := platform.StartMachine(mach, mach.journal); err != nil { | ||
return nil, err | ||
} | ||
|
||
m = nil | ||
bc.AddMach(mach) | ||
|
||
return mach, nil | ||
} | ||
|
||
func (bc *cluster) vmname() string { | ||
b := make([]byte, 5) | ||
rand.Read(b) | ||
return fmt.Sprintf("%s-%x", bc.Name()[0:13], b) | ||
} | ||
|
||
func (bc *cluster) Destroy() { | ||
bc.BaseCluster.Destroy() | ||
bc.flight.DelCluster(bc) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright The Mantle Authors. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package akamai | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/coreos/pkg/capnslog" | ||
ctplatform "github.com/flatcar/container-linux-config-transpiler/config/platform" | ||
|
||
"github.com/flatcar/mantle/platform" | ||
"github.com/flatcar/mantle/platform/api/akamai" | ||
) | ||
|
||
const ( | ||
Platform platform.Name = "akamai" | ||
) | ||
|
||
var ( | ||
plog = capnslog.NewPackageLogger("github.com/flatcar/mantle", "platform/machine/akamai") | ||
) | ||
|
||
type flight struct { | ||
*platform.BaseFlight | ||
api *akamai.API | ||
} | ||
|
||
func NewFlight(opts *akamai.Options) (platform.Flight, error) { | ||
api, err := akamai.New(opts) | ||
if err != nil { | ||
return nil, fmt.Errorf("creating akamai API client: %w", err) | ||
} | ||
|
||
// TODO: Rework the Base Flight to remove the CT dependency. | ||
base, err := platform.NewBaseFlight(opts.Options, Platform, ctplatform.Custom) | ||
if err != nil { | ||
return nil, fmt.Errorf("creating base flight: %w", err) | ||
} | ||
|
||
bf := &flight{ | ||
BaseFlight: base, | ||
api: api, | ||
} | ||
|
||
return bf, nil | ||
} | ||
|
||
// NewCluster creates an instance of a Cluster suitable for spawning | ||
// instances on the Akamai platform. | ||
func (bf *flight) NewCluster(rconf *platform.RuntimeConfig) (platform.Cluster, error) { | ||
bc, err := platform.NewBaseCluster(bf.BaseFlight, rconf) | ||
if err != nil { | ||
return nil, fmt.Errorf("creating akamai base cluster: %w", err) | ||
} | ||
|
||
c := &cluster{ | ||
BaseCluster: bc, | ||
flight: bf, | ||
} | ||
|
||
bf.AddCluster(c) | ||
|
||
return c, nil | ||
} | ||
|
||
func (bf *flight) Destroy() { | ||
bf.BaseFlight.Destroy() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// Copyright The Mantle Authors. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package akamai | ||
|
||
import ( | ||
"context" | ||
"strconv" | ||
|
||
"golang.org/x/crypto/ssh" | ||
|
||
"github.com/flatcar/mantle/platform" | ||
"github.com/flatcar/mantle/platform/api/akamai" | ||
) | ||
|
||
type machine struct { | ||
cluster *cluster | ||
mach *akamai.Server | ||
dir string | ||
journal *platform.Journal | ||
console string | ||
} | ||
|
||
// ID returns the ID of the machine. | ||
func (bm *machine) ID() string { | ||
return strconv.Itoa(bm.mach.Instance.ID) | ||
} | ||
|
||
// IP returns the IP of the machine. | ||
func (bm *machine) IP() string { | ||
if len(bm.mach.Instance.IPv4) > 0 { | ||
return bm.mach.Instance.IPv4[0].String() | ||
} | ||
|
||
return "" | ||
} | ||
|
||
// IP returns the private IP of the machine. | ||
func (bm *machine) PrivateIP() string { | ||
return "" | ||
} | ||
|
||
// RuntimeConf returns the runtime configuration of the cluster. | ||
func (bm *machine) RuntimeConf() *platform.RuntimeConfig { | ||
return bm.cluster.RuntimeConf() | ||
} | ||
|
||
func (bm *machine) SSHClient() (*ssh.Client, error) { | ||
return bm.cluster.SSHClient(bm.IP()) | ||
} | ||
|
||
func (bm *machine) PasswordSSHClient(user string, password string) (*ssh.Client, error) { | ||
return bm.cluster.PasswordSSHClient(bm.IP(), user, password) | ||
} | ||
|
||
func (bm *machine) SSH(cmd string) ([]byte, []byte, error) { | ||
return bm.cluster.SSH(bm, cmd) | ||
} | ||
|
||
func (bm *machine) Reboot() error { | ||
return platform.RebootMachine(bm, bm.journal) | ||
} | ||
|
||
func (bm *machine) Destroy() { | ||
// TODO: Add "saveConsole" logic here when Akamai API will support fetching the console output. | ||
|
||
if err := bm.cluster.flight.api.DeleteServer(context.TODO(), bm.ID()); err != nil { | ||
plog.Errorf("deleting server %v: %v", bm.ID(), err) | ||
} | ||
|
||
if bm.journal != nil { | ||
bm.journal.Destroy() | ||
} | ||
|
||
bm.cluster.DelMach(bm) | ||
} | ||
|
||
func (bm *machine) ConsoleOutput() string { | ||
return bm.console | ||
} | ||
|
||
func (bm *machine) JournalOutput() string { | ||
if bm.journal == nil { | ||
return "" | ||
} | ||
|
||
data, err := bm.journal.Read() | ||
if err != nil { | ||
plog.Errorf("Reading journal for instance %v: %v", bm.ID(), err) | ||
} | ||
return string(data) | ||
} | ||
|
||
func (bm *machine) Board() string { | ||
return bm.cluster.flight.Options().Board | ||
} |