Skip to content

Commit

Permalink
Merge pull request #281 from fujiwara/ignore
Browse files Browse the repository at this point in the history
Add --ignore flag to deploy and diff command.
  • Loading branch information
fujiwara authored Jan 27, 2024
2 parents a5c03b3 + 949ec42 commit 41c5965
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 48 deletions.
15 changes: 9 additions & 6 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
version: 2
updates:
- package-ecosystem: gomod
directory: "/"
schedule:
interval: weekly
time: "20:00"
open-pull-requests-limit: 10
- package-ecosystem: gomod
directory: "/"
schedule:
interval: monthly
open-pull-requests-limit: 10
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: monthly
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ When you hope to manage these resources, we recommend other deployment tools ([A
$ brew install fujiwara/tap/lambroll
```

### aqua

[aqua](https://aquaproj.github.io/) is a declarative CLI Version Manager.

```console
$ aqua g -i fujiwara/lambroll
```

### Binary packages

[Releases](https://github.com/fujiwara/lambroll/releases)
Expand Down
2 changes: 2 additions & 0 deletions cmd/lambroll/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func _main() int {
AliasToLatest: deploy.Flag("alias-to-latest", "set alias to unpublished $LATEST version").Default("false").Bool(),
SkipArchive: deploy.Flag("skip-archive", "skip to create zip archive. requires Code.S3Bucket and Code.S3Key in function definition").Default("false").Bool(),
KeepVersions: deploy.Flag("keep-versions", "Number of latest versions to keep. Older versions will be deleted. (Optional value: default 0).").Default("0").Int(),
Ignore: deploy.Flag("ignore", `ignore function elements. jq queries joined with ",". for example, ".Foo, .Bar"`).String(),
}
rollback := kingpin.Command("rollback", "rollback function")
Expand Down Expand Up @@ -119,6 +120,7 @@ func _main() int {
CodeSha256: diff.Flag("code", "diff of code sha256").Default("false").Bool(),
ExcludeFile: diff.Flag("exclude-file", "exclude file").Default(lambroll.IgnoreFilename).String(),
Src: diff.Flag("src", "function zip archive or src dir").Default(".").String(),
Ignore: diff.Flag("ignore", `ignore function elements. jq queries joined with ",". for example, ".Foo, .Bar"`).String(),
}
versions := kingpin.Command("versions", "manage function versions")
Expand Down
21 changes: 19 additions & 2 deletions deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import (
"log"
"os"

"github.com/aereal/jsondiff"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/lambda"
"github.com/aws/aws-sdk-go-v2/service/lambda/types"
"github.com/itchyny/gojq"
)

// DeployOption represens an option for Deploy()
Expand All @@ -23,6 +25,7 @@ type DeployOption struct {
DryRun bool `help:"dry run" default:"false"`
SkipArchive bool `help:"skip to create zip archive. requires Code.S3Bucket and Code.S3Key in function definition" default:"false"`
KeepVersions int `help:"Number of latest versions to keep. Older versions will be deleted. (Optional value: default 0)." default:"0"`
Ignore string `help:"ignore fields by jq queries in function.json" default:""`
FunctionURL string `help:"path to function-url definiton" default:"" env:"LAMBROLL_FUNCTION_URL"`
SkipFunction bool `help:"skip to deploy a function. deploy function-url only" default:"false"`

Expand Down Expand Up @@ -110,6 +113,22 @@ func (app *App) Deploy(ctx context.Context, opt *DeployOption) error {
}
fillDefaultValues(fn)

if ignore := opt.Ignore; ignore != "" {
q, err := gojq.Parse(ignore)
if err != nil {
return fmt.Errorf("failed to parse ignore query: %w", err)
}
q = jsondiff.WithUpdate(q)
fnAny, _ := marshalAny(fn)
fnAny, err = jsondiff.ModifyValue(q, fnAny)
if err != nil {
return fmt.Errorf("failed to modify function: %w", err)
}
src, _ := json.Marshal(fnAny)
fn = &Function{}
unmarshalJSON(src, &fn, app.functionFilePath)
}

if err := app.prepareFunctionCodeForDeploy(ctx, opt, fn); err != nil {
return fmt.Errorf("failed to prepare function code for deploy: %w", err)
}
Expand Down Expand Up @@ -142,8 +161,6 @@ func (app *App) Deploy(ctx context.Context, opt *DeployOption) error {
confIn.Environment = env
}

log.Printf("[debug]\n%s", ToJSONString(confIn))

var newerVersion string
if !opt.DryRun {
proc := func(ctx context.Context) error {
Expand Down
68 changes: 35 additions & 33 deletions diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ import (
"log"
"strings"

"github.com/aereal/jsondiff"
"github.com/fatih/color"
"github.com/hexops/gotextdiff"
"github.com/hexops/gotextdiff/myers"
"github.com/hexops/gotextdiff/span"
"github.com/itchyny/gojq"
"github.com/kylelemons/godebug/diff"

"github.com/aws/aws-sdk-go-v2/aws"
Expand All @@ -25,9 +24,9 @@ import (
type DiffOption struct {
Src string `help:"function zip archive or src dir" default:"."`
CodeSha256 bool `help:"diff of code sha256" default:"false"`
Unified bool `help:"unified diff" default:"true" negatable:"" short:"u"`
Qualifier *string `help:"the qualifier to compare"`
FunctionURL string `help:"path to function-url definiton" default:"" env:"LAMBROLL_FUNCTION_URL"`
Ignore string `help:"ignore diff by jq query" default:""`

ExcludeFileOption
}
Expand All @@ -45,7 +44,7 @@ func (app *App) Diff(ctx context.Context, opt *DiffOption) error {
fillDefaultValues(newFunc)
name := *newFunc.FunctionName

var latest *types.FunctionConfiguration
var remote *types.FunctionConfiguration
var code *types.FunctionCodeLocation

var tags Tags
Expand All @@ -62,7 +61,7 @@ func (app *App) Diff(ctx context.Context, opt *DiffOption) error {
return fmt.Errorf("failed to GetFunction %s: %w", name, err)
}
} else {
latest = res.Configuration
remote = res.Configuration
code = res.Code
{
log.Println("[debug] list tags Resource", app.functionArn(ctx, name))
Expand All @@ -79,30 +78,37 @@ func (app *App) Diff(ctx context.Context, opt *DiffOption) error {
currentCodeSha256 = *res.Configuration.CodeSha256
packageType = res.Configuration.PackageType
}
latestFunc := newFunctionFrom(latest, code, tags)
remoteFunc := newFunctionFrom(remote, code, tags)
fillDefaultValues(remoteFunc)

latestJSON, _ := marshalJSON(latestFunc)
newJSON, _ := marshalJSON(newFunc)
opts := []jsondiff.Option{}
if ignore := opt.Ignore; ignore != "" {
if p, err := gojq.Parse(ignore); err != nil {
return fmt.Errorf("failed to parse ignore query: %s %w", ignore, err)
} else {
opts = append(opts, jsondiff.Ignore(p))
}
}

remoteJSON, _ := marshalAny(remoteFunc)
newJSON, _ := marshalAny(newFunc)
remoteArn := fullQualifiedFunctionName(app.functionArn(ctx, name), opt.Qualifier)

if opt.Unified {
edits := myers.ComputeEdits(span.URIFromPath(remoteArn), string(latestJSON), string(newJSON))
if ds := fmt.Sprint(gotextdiff.ToUnified(remoteArn, app.functionFilePath, string(latestJSON), edits)); ds != "" {
fmt.Print(coloredDiff(ds))
}
} else {
if ds := diff.Diff(string(latestJSON), string(newJSON)); ds != "" {
fmt.Println(color.RedString("---" + remoteArn))
fmt.Println(color.GreenString("+++" + app.functionFilePath))
fmt.Print(coloredDiff(ds))
}
if diff, err := jsondiff.Diff(
&jsondiff.Input{Name: remoteArn, X: remoteJSON},
&jsondiff.Input{Name: app.functionFilePath, X: newJSON},
opts...,
); err != nil {
return fmt.Errorf("failed to diff: %w", err)
} else if diff != "" {
fmt.Print(coloredDiff(diff))
}

if err := validateUpdateFunction(latest, code, newFunc); err != nil {
if err := validateUpdateFunction(remote, code, newFunc); err != nil {
return err
}

if opt.CodeSha256 && latest != nil {
if opt.CodeSha256 {
if packageType != types.PackageTypeZip {
return fmt.Errorf("code-sha256 is only supported for Zip package type")
}
Expand Down Expand Up @@ -171,17 +177,13 @@ func (app *App) diffFunctionURL(ctx context.Context, name string, opt *DiffOptio
r, _ := marshalJSON(remote)
l, _ := marshalJSON(local)

if opt.Unified {
edits := myers.ComputeEdits(span.URIFromPath(fqName), string(r), string(l))
if ds := fmt.Sprint(gotextdiff.ToUnified(fqName, opt.FunctionURL, string(r), edits)); ds != "" {
fmt.Print(coloredDiff(ds))
}
} else {
if ds := diff.Diff(string(r), string(l)); ds != "" {
fmt.Println(color.RedString("---" + fqName))
fmt.Println(color.GreenString("+++" + opt.FunctionURL))
fmt.Print(coloredDiff(ds))
}
if diff, err := jsondiff.Diff(
&jsondiff.Input{Name: fqName, X: r},
&jsondiff.Input{Name: opt.FunctionURL, X: l},
); err != nil {
return fmt.Errorf("failed to diff: %w", err)
} else if diff != "" {
fmt.Print(coloredDiff(diff))
}

// permissions
Expand Down
2 changes: 1 addition & 1 deletion function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func TestLoadFunction(t *testing.T) {
t.Errorf("unexpected SecurityGroupIds %v", fn.VpcConfig.SecurityGroupIds)
}
arch := fn.Architectures
if len(arch) != 2 || arch[0] != "x86_64" || arch[1] != "arm64" {
if len(arch) != 1 || arch[0] != "x86_64" {
t.Errorf("unexpected Architectures %v", fn.Architectures)
}
if *fn.LoggingConfig.LogGroup != "/aws/lambda/test/json" {
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.20

require (
github.com/Songmu/prompter v0.5.1
github.com/aereal/jsondiff v0.2.4-0.20221231034809-2e797076aee1
github.com/alecthomas/kong v0.8.0
github.com/aws/aws-sdk-go-v2 v1.24.0
github.com/aws/aws-sdk-go-v2/config v1.26.1
Expand All @@ -18,7 +19,8 @@ require (
github.com/google/go-cmp v0.5.9
github.com/google/go-jsonnet v0.20.0
github.com/hashicorp/go-envparse v0.0.0-20200406174449-d9cfd743a15e
github.com/hexops/gotextdiff v1.0.3
github.com/hexops/gotextdiff v1.0.3 // indirect
github.com/itchyny/gojq v0.12.11
github.com/kayac/go-config v0.6.0
github.com/kylelemons/godebug v1.1.0
github.com/mattn/go-isatty v0.0.20
Expand Down Expand Up @@ -73,7 +75,6 @@ require (
github.com/hashicorp/go-slug v0.8.1 // indirect
github.com/hashicorp/go-tfe v1.2.0 // indirect
github.com/hashicorp/jsonapi v0.0.0-20210826224640-ee7dae0fb22d // indirect
github.com/itchyny/gojq v0.12.11 // indirect
github.com/itchyny/timefmt-go v0.1.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jstemmer/go-junit-report v0.9.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Songmu/prompter v0.5.1 h1:IAsttKsOZWSDw7bV1mtGn9TAmLFAjXbp9I/eYmUUogo=
github.com/Songmu/prompter v0.5.1/go.mod h1:CS3jEPD6h9IaLaG6afrl1orTgII9+uDWuw95dr6xHSw=
github.com/aereal/jsondiff v0.2.4-0.20221231034809-2e797076aee1 h1:PrNsETLYKHeiniM9hCru9topK9bOiPjxl5xdYKLQoNo=
github.com/aereal/jsondiff v0.2.4-0.20221231034809-2e797076aee1/go.mod h1:a5oayUivaiGHWcodFYZmy0km36ZbSfYtjuVMfKUQdbM=
github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0=
github.com/alecthomas/kong v0.8.0 h1:ryDCzutfIqJPnNn0omnrgHLbAggDQM2VWHikE1xqK7s=
github.com/alecthomas/kong v0.8.0/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=
Expand Down
5 changes: 2 additions & 3 deletions test/function.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"Architectures": [
"x86_64",
"arm64"
"x86_64"
],
"Description": "hello function",
"EphemeralStorage": {
Expand Down Expand Up @@ -30,7 +29,7 @@
},
"MemorySize": 128,
"Role": "{{ tfstate `data.aws_iam_role.lambda.arn` }}",
"Runtime": "nodejs12.x",
"Runtime": "nodejs16.x",
"Timeout": 5,
"TracingConfig": {
"Mode": "PassThrough"
Expand Down
1 change: 0 additions & 1 deletion test/function.jsonnet
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
Architectures: [
'x86_64',
'arm64',
],
Description: std.extVar('Description'),
EphemeralStorage: {
Expand Down
12 changes: 12 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ func marshalJSON(s interface{}) ([]byte, error) {
}
}

func marshalAny(s interface{}) (interface{}, error) {
b, err := marshalJSON(s)
if err != nil {
return nil, err
}
var res interface{}
if err := json.NewDecoder(bytes.NewReader(b)).Decode(&res); err != nil {
return nil, err
}
return res, nil
}

func unmarshalJSON(src []byte, v interface{}, path string) error {
strict := json.NewDecoder(bytes.NewReader(src))
strict.DisallowUnknownFields()
Expand Down

0 comments on commit 41c5965

Please sign in to comment.