Skip to content

Commit 74c84a0

Browse files
committed
status command outputs funtion URL info.
1 parent cf825f4 commit 74c84a0

File tree

5 files changed

+102
-24
lines changed

5 files changed

+102
-24
lines changed

deploy.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type DeployOption struct {
2424
SkipArchive bool `help:"skip to create zip archive. requires Code.S3Bucket and Code.S3Key in function definition" default:"false"`
2525
KeepVersions int `help:"Number of latest versions to keep. Older versions will be deleted. (Optional value: default 0)." default:"0"`
2626
FunctionURL string `help:"path to function-url definiton" default:""`
27+
SkipFunction bool `help:"skip to deploy a function. deploy function-url only" default:"false"`
2728

2829
ExcludeFileOption
2930
}
@@ -81,15 +82,20 @@ func (app *App) Deploy(ctx context.Context, opt *DeployOption) error {
8182

8283
deployFunctionURL := func(context.Context) error { return nil }
8384
if opt.FunctionURL != "" {
84-
fc, err := app.loadFunctionUrl(opt.FunctionURL, *fn.FunctionName)
85-
if err != nil {
86-
return fmt.Errorf("failed to load function url config: %w", err)
87-
}
8885
deployFunctionURL = func(ctx context.Context) error {
86+
fc, err := app.loadFunctionUrl(opt.FunctionURL, *fn.FunctionName)
87+
if err != nil {
88+
return fmt.Errorf("failed to load function url config: %w", err)
89+
}
8990
return app.deployFunctionURL(ctx, fc)
9091
}
9192
}
9293

94+
if opt.SkipFunction {
95+
// skip to deploy a function. deploy function-url only
96+
return deployFunctionURL(ctx)
97+
}
98+
9399
log.Printf("[info] starting deploy function %s", *fn.FunctionName)
94100
if current, err := app.lambda.GetFunction(ctx, &lambda.GetFunctionInput{
95101
FunctionName: fn.FunctionName,

diff.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ import (
2222

2323
// DiffOption represents options for Diff()
2424
type DiffOption struct {
25-
Src string `help:"function zip archive or src dir" default:"."`
26-
CodeSha256 bool `help:"diff of code sha256" default:"false"`
27-
Unified bool `help:"unified diff" default:"true" negatable:"" short:"u"`
28-
Qualifier string `help:"compare with" default:"$LATEST"`
25+
Src string `help:"function zip archive or src dir" default:"."`
26+
CodeSha256 bool `help:"diff of code sha256" default:"false"`
27+
Unified bool `help:"unified diff" default:"true" negatable:"" short:"u"`
28+
Qualifier *string `help:"compare with"`
2929

3030
ExcludeFileOption
3131
}
@@ -51,7 +51,7 @@ func (app *App) Diff(ctx context.Context, opt *DiffOption) error {
5151
var packageType types.PackageType
5252
if res, err := app.lambda.GetFunction(ctx, &lambda.GetFunctionInput{
5353
FunctionName: &name,
54-
Qualifier: &opt.Qualifier,
54+
Qualifier: opt.Qualifier,
5555
}); err != nil {
5656
return fmt.Errorf("failed to GetFunction %s: %w", name, err)
5757
} else {
@@ -76,7 +76,7 @@ func (app *App) Diff(ctx context.Context, opt *DiffOption) error {
7676

7777
latestJSON, _ := marshalJSON(latestFunc)
7878
newJSON, _ := marshalJSON(newFunc)
79-
remoteArn := app.functionArn(ctx, name) + ":" + opt.Qualifier
79+
remoteArn := fullQualifiedFunctionName(app.functionArn(ctx, name), opt.Qualifier)
8080

8181
if opt.Unified {
8282
edits := myers.ComputeEdits(span.URIFromPath(remoteArn), string(latestJSON), string(newJSON))

functionurl.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,15 @@ func (app *App) deployFunctionURL(ctx context.Context, fc *FunctionURL) error {
203203

204204
func (app *App) deployFunctionURLConfig(ctx context.Context, fc *FunctionURL) error {
205205
create := false
206-
if _, err := app.lambda.GetFunctionUrlConfig(ctx, &lambda.GetFunctionUrlConfigInput{
206+
fqFunctionName := fullQualifiedFunctionName(*fc.Config.FunctionName, fc.Config.Qualifier)
207+
functinoUrlConfig, err := app.lambda.GetFunctionUrlConfig(ctx, &lambda.GetFunctionUrlConfigInput{
207208
FunctionName: fc.Config.FunctionName,
208209
Qualifier: fc.Config.Qualifier,
209-
}); err != nil {
210+
})
211+
if err != nil {
210212
var nfe *types.ResourceNotFoundException
211213
if errors.As(err, &nfe) {
212-
log.Printf("[info] function url config for %s not found. creating", *fc.Config.FunctionName)
214+
log.Printf("[info] function url config for %s not found. creating", fqFunctionName)
213215
create = true
214216
} else {
215217
return fmt.Errorf("failed to get function url config: %w", err)
@@ -221,9 +223,14 @@ func (app *App) deployFunctionURLConfig(ctx context.Context, fc *FunctionURL) er
221223
if err != nil {
222224
return fmt.Errorf("failed to create function url config: %w", err)
223225
}
224-
log.Printf("[info] created function url config for %s", *fc.Config.FunctionName)
226+
log.Printf("[info] created function url config for %s", fqFunctionName)
225227
log.Printf("[info] Function URL: %s", *res.FunctionUrl)
226228
} else {
229+
log.Printf("[info] updating function url config for %s", fqFunctionName)
230+
if functinoUrlConfig.Cors != nil && fc.Config.Cors == nil {
231+
// reset cors config
232+
fc.Config.Cors = &types.Cors{}
233+
}
227234
res, err := app.lambda.UpdateFunctionUrlConfig(ctx, &lambda.UpdateFunctionUrlConfigInput{
228235
FunctionName: fc.Config.FunctionName,
229236
Qualifier: fc.Config.Qualifier,
@@ -234,13 +241,14 @@ func (app *App) deployFunctionURLConfig(ctx context.Context, fc *FunctionURL) er
234241
if err != nil {
235242
return fmt.Errorf("failed to update function url config: %w", err)
236243
}
237-
log.Printf("[info] updated function url config for %s", *fc.Config.FunctionName)
244+
log.Printf("[info] updated function url config for %s", fqFunctionName)
238245
log.Printf("[info] Function URL: %s", *res.FunctionUrl)
239246
}
240247
return nil
241248
}
242249

243250
func (app *App) deployFunctionURLPermissions(ctx context.Context, fc *FunctionURL) error {
251+
fqFunctionName := fullQualifiedFunctionName(*fc.Config.FunctionName, fc.Config.Qualifier)
244252
existsSids := []string{}
245253
{
246254
res, err := app.lambda.GetPolicy(ctx, &lambda.GetPolicyInput{
@@ -256,7 +264,7 @@ func (app *App) deployFunctionURLPermissions(ctx context.Context, fc *FunctionUR
256264
}
257265
}
258266
if res != nil {
259-
log.Printf("[debug] policy for %s: %s", *fc.Config.FunctionName, *res.Policy)
267+
log.Printf("[debug] policy for %s: %s", fqFunctionName, *res.Policy)
260268
var policy PolicyOutput
261269
if err := json.Unmarshal([]byte(*res.Policy), &policy); err != nil {
262270
return fmt.Errorf("failed to unmarshal policy: %w", err)
@@ -299,7 +307,7 @@ func (app *App) deployFunctionURLPermissions(ctx context.Context, fc *FunctionUR
299307
if _, err := app.lambda.AddPermission(ctx, in); err != nil {
300308
return fmt.Errorf("failed to add permission: %w", err)
301309
}
302-
log.Printf("[info] added permission for %s", *fc.Config.FunctionName)
310+
log.Printf("[info] added permission for %s", fqFunctionName)
303311
}
304312

305313
for _, sid := range removeSids {
@@ -331,6 +339,7 @@ func (app *App) initFunctionURL(ctx context.Context, fn *Function, opt *InitOpti
331339
return fmt.Errorf("failed to get function url config: %w", err)
332340
}
333341
}
342+
fqFunctionName := fullQualifiedFunctionName(*fn.FunctionName, opt.Qualifier)
334343
fu := &FunctionURL{
335344
Config: &lambda.CreateFunctionUrlConfigInput{
336345
Cors: fc.Cors,
@@ -354,7 +363,7 @@ func (app *App) initFunctionURL(ctx context.Context, fn *Function, opt *InitOpti
354363
}
355364
}
356365
if res != nil {
357-
log.Printf("[debug] policy for %s: %s", *fn.FunctionName, *res.Policy)
366+
log.Printf("[debug] policy for %s: %s", fqFunctionName, *res.Policy)
358367
var policy PolicyOutput
359368
if err := json.Unmarshal([]byte(*res.Policy), &policy); err != nil {
360369
return fmt.Errorf("failed to unmarshal policy: %w", err)

status.go

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,28 @@ package lambroll
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"log"
78
"strings"
89

910
"github.com/aws/aws-sdk-go-v2/aws"
1011
"github.com/aws/aws-sdk-go-v2/service/lambda"
1112
"github.com/aws/aws-sdk-go-v2/service/lambda/types"
13+
"github.com/samber/lo"
1214
)
1315

1416
// StatusOption represents options for Status()
1517
type StatusOption struct {
16-
Qualifier string `help:"compare with" default:"$LATEST"`
17-
Output string `default:"text" enum:"text,json" help:"output format"`
18+
Qualifier *string `help:"compare with"`
19+
Output string `default:"text" enum:"text,json" help:"output format"`
1820
}
1921

2022
type FunctionStatusOutput struct {
2123
Configuration *types.FunctionConfiguration
2224
Code *types.FunctionCodeLocation
2325
Tags Tags
26+
FunctionURL *types.FunctionUrlConfig
2427
}
2528

2629
// Status prints status of function
@@ -37,7 +40,7 @@ func (app *App) Status(ctx context.Context, opt *StatusOption) error {
3740

3841
if res, err := app.lambda.GetFunction(ctx, &lambda.GetFunctionInput{
3942
FunctionName: &name,
40-
Qualifier: &opt.Qualifier,
43+
Qualifier: opt.Qualifier,
4144
}); err != nil {
4245
return fmt.Errorf("failed to GetFunction %s: %w", name, err)
4346
} else {
@@ -56,11 +59,34 @@ func (app *App) Status(ctx context.Context, opt *StatusOption) error {
5659
tags = res.Tags
5760
}
5861
}
62+
5963
st := &FunctionStatusOutput{
6064
Configuration: configuration,
6165
Code: code,
6266
Tags: tags,
6367
}
68+
69+
if res, err := app.lambda.GetFunctionUrlConfig(ctx, &lambda.GetFunctionUrlConfigInput{
70+
FunctionName: fn.FunctionName,
71+
Qualifier: opt.Qualifier,
72+
}); err != nil {
73+
var nfe *types.ResourceNotFoundException
74+
if errors.As(err, &nfe) {
75+
// ignore
76+
log.Println("[debug] FunctionUrlConfig not found")
77+
} else {
78+
return fmt.Errorf("failed to get function url config: %w", err)
79+
}
80+
} else {
81+
log.Println("[debug] FunctionUrlConfig found")
82+
st.FunctionURL = &types.FunctionUrlConfig{
83+
FunctionUrl: res.FunctionUrl,
84+
AuthType: res.AuthType,
85+
Cors: res.Cors,
86+
InvokeMode: res.InvokeMode,
87+
}
88+
}
89+
6490
switch opt.Output {
6591
case "text":
6692
fmt.Print(st.String())
@@ -101,7 +127,7 @@ func (st *FunctionStatusOutput) String() string {
101127
}, "\n")
102128
}
103129

104-
res := strings.Join([]string{
130+
res := []string{
105131
"FunctionName: " + aws.ToString(st.Configuration.FunctionName),
106132
"Description: " + aws.ToString(st.Configuration.Description),
107133
"Version: " + aws.ToString(st.Configuration.Version),
@@ -120,6 +146,36 @@ func (st *FunctionStatusOutput) String() string {
120146
"CodeSize: " + fmt.Sprintf("%d", st.Configuration.CodeSize),
121147
"CodeSha256: " + aws.ToString(st.Configuration.CodeSha256),
122148
"Tags: " + strings.Join(tags, ","),
123-
}, "\n") + "\n"
124-
return res
149+
}
150+
151+
if st.FunctionURL != nil {
152+
res = append(res, []string{
153+
"FunctionUrl:",
154+
" FunctionUrl: " + aws.ToString(st.FunctionURL.FunctionUrl),
155+
" AuthType: " + string(st.FunctionURL.AuthType),
156+
" InvokeMode: " + string(st.FunctionURL.InvokeMode),
157+
}...)
158+
if cors := st.FunctionURL.Cors; cors != nil {
159+
res = append(res, " Cors:", formatCors(cors, 4))
160+
}
161+
}
162+
return strings.Join(res, "\n") + "\n"
163+
}
164+
165+
func formatCors(cors *types.Cors, indentLevel int) string {
166+
if cors == nil {
167+
return ""
168+
}
169+
indent := strings.Repeat(" ", indentLevel)
170+
res := lo.Map([]string{
171+
"AllowCredentials: " + fmt.Sprintf("%t", aws.ToBool(cors.AllowCredentials)),
172+
"AllowOrigins: " + strings.Join(cors.AllowOrigins, ","),
173+
"AllowHeaders: " + strings.Join(cors.AllowHeaders, ","),
174+
"AllowMethods: " + strings.Join(cors.AllowMethods, ","),
175+
"ExposeHeaders: " + strings.Join(cors.ExposeHeaders, ","),
176+
"MaxAge: " + fmt.Sprintf("%d", aws.ToInt32(cors.MaxAge)),
177+
}, func(item string, _ int) string {
178+
return indent + item
179+
})
180+
return strings.Join(res, "\n")
125181
}

utils.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,10 @@ func resolveLogGroup(fn *Function) string {
8484
}
8585
return fmt.Sprintf("/aws/lambda/%s", *fn.FunctionName)
8686
}
87+
88+
func fullQualifiedFunctionName(name string, qualifier *string) string {
89+
if qualifier != nil {
90+
return name + ":" + *qualifier
91+
}
92+
return name + ":" + versionLatest
93+
}

0 commit comments

Comments
 (0)