Skip to content

Commit

Permalink
fly deploy for machines for apps v2
Browse files Browse the repository at this point in the history
We're pushing to migrate the Fly Apps platform to machines instead of nomad to improve developer experience. The first big step will be make new apps use the machines platform instead of nomad. There's a bunch of steps to get there, and this is one of them...

Update `fly deploy` when we're working on an app with machines to:

1) Prompt developer to migrate the machines into the "Fly Apps platform". The machines being deployed will become the instances of the apps. Specifically, wWe put some metadata on those machines indicating they are part of the Fly Apps platform. Subsequent deploys will only operate on machines with that metadata.

2) We create releases in the graphql api for each deployment. The release only gets created and marked as pending for now. It does not get updated. That's ok for now.
  • Loading branch information
tvdfly authored and dangra committed Jan 25, 2023
1 parent 1e55f29 commit cd586b7
Show file tree
Hide file tree
Showing 9 changed files with 491 additions and 135 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
NOW_RFC3339 = $(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
GIT_SHA = $(shell git rev-parse HEAD 2>/dev/null || no_git)

all: build cmddocs

Expand All @@ -8,7 +9,7 @@ generate:

build: generate
@echo Running Build
go build -o bin/flyctl -ldflags="-X 'github.com/superfly/flyctl/internal/buildinfo.buildDate=$(NOW_RFC3339)'" .
go build -o bin/flyctl -ldflags="-X 'github.com/superfly/flyctl/internal/buildinfo.buildDate=$(NOW_RFC3339)' -X 'github.com/superfly/flyctl/internal/buildinfo.commit=$(GIT_SHA)'" .

test:
go test ./... -ldflags="-X 'github.com/superfly/flyctl/internal/buildinfo.buildDate=$(NOW_RFC3339)'"
Expand Down
25 changes: 22 additions & 3 deletions api/machine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import (
"time"
)

const MachineConfigMetadataKeyFlyPlatformVersion = "fly_platform_version"
const MachineConfigMetadataKeyFlyRelease = "fly_release"
const MachineFlyPlatformVersion2 = "v2"
const MachineProcessGroupApp = "app"
const MachineProcessGroupReleaseCommand = "release_command"
const MachineStateDestroyed = "destroyed"

type Machine struct {
ID string `json:"id"`
Name string `json:"name"`
Expand Down Expand Up @@ -38,6 +45,18 @@ func (m Machine) ImageRefWithVersion() string {
return ref
}

func (m *Machine) IsFlyAppsPlatform() bool {
return m.Config != nil && m.Config.Metadata[MachineConfigMetadataKeyFlyPlatformVersion] == MachineFlyPlatformVersion2 && m.State != MachineStateDestroyed
}

func (m *Machine) IsActive() bool {
return m.State != MachineStateDestroyed
}

func (m *Machine) HasProcessGroup(desired string) bool {
return m.Config != nil && m.Config.Metadata["process_group"] == desired
}

func (m Machine) ImageVersion() string {
if m.ImageRef.Labels == nil {
return ""
Expand Down Expand Up @@ -174,9 +193,9 @@ type MachineCheckStatus struct {
}

type MachinePort struct {
Port *int32 `json:"port,omitempty" toml:"port,omitempty"`
StartPort *int32 `json:"start_port,omitempty" toml:"start_port,omitempty"`
EndPort *int32 `json:"end_port,omitempty" toml:"end_port,omitempty"`
Port *int `json:"port,omitempty" toml:"port,omitempty"`
StartPort *int `json:"start_port,omitempty" toml:"start_port,omitempty"`
EndPort *int `json:"end_port,omitempty" toml:"end_port,omitempty"`
Handlers []string `json:"handlers,omitempty" toml:"handlers,omitempty"`
ForceHttps bool `json:"force_https,omitempty" toml:"force_https,omitempty"`
}
Expand Down
20 changes: 19 additions & 1 deletion flaps/flaps.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/superfly/flyctl/flyctl"
"github.com/superfly/flyctl/internal/buildinfo"
"github.com/superfly/flyctl/internal/logger"
"github.com/superfly/flyctl/terminal"
)

var NonceHeader = "fly-machine-lease-nonce"
Expand Down Expand Up @@ -226,12 +227,28 @@ func (f *Client) ListActive(ctx context.Context) ([]*api.Machine, error) {
}

machines = lo.Filter(machines, func(m *api.Machine, _ int) bool {
return m.Config != nil && m.Config.Metadata["process_group"] != "release_command" && m.State != "destroyed"
return !m.HasProcessGroup(api.MachineProcessGroupReleaseCommand) && m.IsActive()
})

return machines, nil
}

// returns apps that are part of the fly apps platform that are not destroyed
func (f *Client) ListFlyAppsMachines(ctx context.Context) ([]*api.Machine, error) {
allMachines := make([]*api.Machine, 0)
err := f.sendRequest(ctx, http.MethodGet, "", nil, &allMachines, nil)
if err != nil {
return nil, fmt.Errorf("failed to list VMs: %w", err)
}
machines := make([]*api.Machine, 0)
for _, m := range allMachines {
if m.IsFlyAppsPlatform() && m.IsActive() {
machines = append(machines, m)
}
}
return machines, nil
}

func (f *Client) Destroy(ctx context.Context, input api.RemoveMachineInput) (err error) {
destroyEndpoint := fmt.Sprintf("/%s?kill=%t", input.ID, input.Kill)

Expand Down Expand Up @@ -279,6 +296,7 @@ func (f *Client) AcquireLease(ctx context.Context, machineID string, ttl *int) (
if err != nil {
return nil, fmt.Errorf("failed to get lease on VM %s: %w", machineID, err)
}
terminal.Debugf("got lease on machine %s: %v\n", machineID, out)
return out, nil
}

Expand Down
133 changes: 133 additions & 0 deletions gql/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion gql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -8621,6 +8621,11 @@ input ServiceInputPort {
Service port
"""
type ServicePort {
"""
End port for range
"""
endPort: Int

"""
Handlers to apply before forwarding service traffic
"""
Expand All @@ -8629,7 +8634,12 @@ type ServicePort {
"""
Port to listen on
"""
port: Int!
port: Int

"""
Start port for range
"""
startPort: Int
}

"""
Expand Down
20 changes: 20 additions & 0 deletions internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,26 @@ func (c *Config) GetEnvVariables() map[string]string {
return env
}

func (c *Config) GetDeployStrategy() string {
dep, ok := c.Definition["deploy"]
if !ok {
return ""
}
depMap, ok := dep.(map[string]interface{})
if !ok {
return ""
}
strategy, ok := depMap["strategy"]
if !ok {
return ""
}
stratStr, ok := strategy.(string)
if !ok {
return ""
}
return stratStr
}

func (c *Config) SetProcess(name, value string) {
var processes map[string]string

Expand Down
16 changes: 12 additions & 4 deletions internal/command/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,28 @@ func DeployWithConfig(ctx context.Context, appConfig *app.Config) (err error) {
}

if appConfig.ForMachines() {
if !flag.GetBool(ctx, "auto-confirm") {
switch confirmed, err := prompt.Confirmf(ctx, "This feature is highly experimental and may produce unexpected results. Proceed?"); {
autoConfirm := flag.GetBool(ctx, "auto-confirm")
if !autoConfirm {
switch confirmed, err := prompt.Confirmf(ctx, "Deploying machines with `fly deploy` is highly experimental and may produce unexpected results. Proceed?"); {
case err == nil:
if !confirmed {
return nil
}
case prompt.IsNonInteractive(err):
return prompt.NonInteractiveError("auto-confirm flag must be specified when not running interactively")
return prompt.NonInteractiveError("--auto-confirm flag must be specified when not running interactively")
default:
return err
}
}

return createMachinesRelease(ctx, appConfig, img, flag.GetString(ctx, "strategy"))
md, err := NewMachineDeployment(ctx, MachineDeploymentArgs{
Strategy: flag.GetString(ctx, "strategy"),
AutoConfirmMigration: autoConfirm,
})
if err != nil {
return err
}
return md.DeployMachinesApp(ctx)
}

release, releaseCommand, err = createRelease(ctx, appConfig, img)
Expand Down

0 comments on commit cd586b7

Please sign in to comment.