Skip to content

Commit 6f005e7

Browse files
authored
Add PBF catalog commands func.yaml, and deploy support to Fn CLI (#723)
1 parent a69a19f commit 6f005e7

10 files changed

Lines changed: 697 additions & 35 deletions

File tree

README.md

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,42 @@ deploy:
151151
152152
When these OCI-specific flags are used with a non-Oracle provider or local Fn server workflows, Fn CLI accepts them and emits user-friendly warnings where the settings are not applicable.
153153
154-
### Pre-Built Function create support
154+
### Pre-Built Function (PBF) support
155+
List available Pre-Built Functions:
156+
157+
```sh
158+
fn list pbfs
159+
fn list pbfs --search Document
160+
fn list pbfs --trigger http
161+
fn list pbfs --output json
162+
```
163+
164+
Get a specific PBF listing:
165+
166+
```sh
167+
fn get pbfs <pbf-name-or-ocid>
168+
```
169+
170+
List versions for a PBF:
171+
172+
```sh
173+
fn list pbfs versions <pbf-name-or-ocid>
174+
fn list pbfs versions <pbf-name-or-ocid> --current
175+
```
176+
177+
Get a specific PBF version:
178+
179+
```sh
180+
fn get pbfs version <pbf-listing-version-ocid>
181+
```
182+
183+
List supported PBF trigger names:
184+
185+
```sh
186+
fn list pbfs triggers
187+
fn list pbfs triggers http
188+
```
189+
155190
Create a function from a Pre-Built Function (PBF) listing OCID:
156191

157192
```sh
@@ -164,7 +199,42 @@ For PBF create flows:
164199
- Fn CLI automatically resolves the minimum required memory from the current PBF version when possible
165200
- if you specify `--memory`, it must be greater than or equal to the PBF minimum requirement
166201

167-
Current limitation: `--pbf` support is currently focused on `fn create function` and is not yet persisted through `func.yaml` / deploy flows.
202+
Persist a PBF-backed function definition using `fn init`:
203+
204+
```sh
205+
fn init --name hello-pbf --pbf <pbf-listing-ocid>
206+
```
207+
208+
Example `func.yaml` for a PBF-backed function:
209+
210+
```yaml
211+
deploy:
212+
oci:
213+
pbf:
214+
listing_id: <pbf-listing-ocid>
215+
```
216+
217+
Deploy a persisted PBF-backed function:
218+
219+
```sh
220+
fn deploy --app <app-name>
221+
```
222+
223+
For PBF-backed deploys, Fn CLI skips image build/push/sign flows and creates or updates the function using PBF source details instead.
224+
225+
Inspect/list output also surfaces PBF-backed functions:
226+
227+
```sh
228+
fn inspect function <app-name> <function-name>
229+
fn list functions <app-name>
230+
```
231+
232+
`fn list functions` includes a `SOURCE` column, for example:
233+
234+
```text
235+
NAME IMAGE SOURCE ID
236+
hello-pbf pbf:<pbf-listing-ocid> <function-ocid>
237+
```
168238

169239
### Detached invoke examples
170240
Invoke a function in detached mode:

commands/commands.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/fnproject/cli/objects/app"
2424
"github.com/fnproject/cli/objects/context"
2525
"github.com/fnproject/cli/objects/fn"
26+
"github.com/fnproject/cli/objects/pbf"
2627
"github.com/fnproject/cli/objects/server"
2728
"github.com/fnproject/cli/objects/trigger"
2829
"github.com/urfave/cli"
@@ -97,6 +98,7 @@ var DeleteCmds = Cmd{
9798

9899
var GetCmds = Cmd{
99100
"config": ConfigCommand("get"),
101+
"pbfs": pbf.Get(),
100102
}
101103

102104
var InspectCmds = Cmd{
@@ -110,6 +112,7 @@ var ListCmds = Cmd{
110112
"config": ConfigCommand("list"),
111113
"apps": app.List(),
112114
"functions": fn.List(),
115+
"pbfs": pbf.List(),
113116
"triggers": trigger.List(),
114117
"contexts": context.List(),
115118
}

commands/deploy.go

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,8 @@ func (p *deploycmd) deployFuncV20180708(c *cli.Context, app *models.App, funcfil
355355
common.WarnIfOCIManagedFunctionSettingsUnsupported(os.Stderr, p.provider, funcfile.Name, funcfile)
356356

357357
oracleProvider, _ := getOracleProvider()
358-
if oracleProvider != nil && oracleProvider.ImageCompartmentID != "" {
358+
isPBFDeploy := funcfile.Deploy != nil && funcfile.Deploy.OCI != nil && funcfile.Deploy.OCI.PBF != nil && strings.TrimSpace(funcfile.Deploy.OCI.PBF.ListingID) != ""
359+
if !isPBFDeploy && oracleProvider != nil && oracleProvider.ImageCompartmentID != "" {
359360
// If the provider is Oracle and ImageCompartmentID is present, we need to deploy image to the ImageCompartmentID.
360361
// The repository name should be unique throughout a tenancy. We check if a repository exists in the compartment and create it if it doesn't already exist.
361362
// If the creation fails, it could be because the repository name aready exists in a different compartment.
@@ -393,36 +394,42 @@ func (p *deploycmd) deployFuncV20180708(c *cli.Context, app *models.App, funcfil
393394
// TODO: this whole funcfile handling needs some love, way too confusing. Only bump makes permanent changes to it.
394395
}
395396

396-
buildArgs := c.StringSlice("build-arg")
397+
if !isPBFDeploy {
398+
buildArgs := c.StringSlice("build-arg")
397399

398-
// In case of local ignore the architectures parameter
399-
shape := ""
400-
if !p.local && !p.localDebug {
401-
// fetch the architectures
402-
shape = app.Shape
403-
if shape == "" {
404-
shape = common.DefaultAppShape
405-
app.Shape = shape
406-
}
400+
// In case of local ignore the architectures parameter
401+
shape := ""
402+
if !p.local && !p.localDebug {
403+
// fetch the architectures
404+
shape = app.Shape
405+
if shape == "" {
406+
shape = common.DefaultAppShape
407+
app.Shape = shape
408+
}
407409

408-
if _, ok := common.ShapeMap[shape]; !ok {
409-
return errors.New(fmt.Sprintf("Invalid application : %s shape: %s", app.Name, shape))
410+
if _, ok := common.ShapeMap[shape]; !ok {
411+
return errors.New(fmt.Sprintf("Invalid application : %s shape: %s", app.Name, shape))
412+
}
410413
}
411-
}
412414

413-
_, err := common.BuildFuncV20180708(common.IsVerbose(), funcfilePath, funcfile, buildArgs, p.noCache, shape, p.localDebug)
414-
if err != nil {
415-
return err
416-
}
415+
_, err := common.BuildFuncV20180708(common.IsVerbose(), funcfilePath, funcfile, buildArgs, p.noCache, shape, p.localDebug)
416+
if err != nil {
417+
return err
418+
}
417419

418-
if err := p.signImage(funcfile); err != nil {
419-
return err
420+
if err := p.signImage(funcfile); err != nil {
421+
return err
422+
}
420423
}
421424
return p.updateFunction(c, app.ID, funcfile)
422425
}
423426

424427
func (p *deploycmd) updateFunction(c *cli.Context, appID string, ff *common.FuncFileV20180708) error {
425-
fmt.Printf("Updating function %s using image %s...\n", ff.Name, ff.ImageNameV20180708())
428+
if ff.Deploy != nil && ff.Deploy.OCI != nil && ff.Deploy.OCI.PBF != nil && strings.TrimSpace(ff.Deploy.OCI.PBF.ListingID) != "" {
429+
fmt.Printf("Updating function %s using PBF listing %s...\n", ff.Name, ff.Deploy.OCI.PBF.ListingID)
430+
} else {
431+
fmt.Printf("Updating function %s using image %s...\n", ff.Name, ff.ImageNameV20180708())
432+
}
426433
var detachedSeconds int
427434
if ff.Deploy != nil && ff.Deploy.OCI != nil && ff.Deploy.OCI.DetachedMode != nil && ff.Deploy.OCI.DetachedMode.Timeout != "" {
428435
_, seconds, err := common.ParseDetachedTimeoutSpec(ff.Deploy.OCI.DetachedMode.Timeout)
@@ -441,6 +448,11 @@ func (p *deploycmd) updateFunction(c *cli.Context, appID string, ff *common.Func
441448
if err := function.WithFuncFileV20180708(ff, fn); err != nil {
442449
return fmt.Errorf("Error getting function with funcfile: %s", err)
443450
}
451+
if ff.Deploy != nil && ff.Deploy.OCI != nil && ff.Deploy.OCI.PBF != nil {
452+
if err := function.ResolvePBFMemoryForListing(p.provider, fn, ff.Deploy.OCI.PBF.ListingID); err != nil {
453+
return err
454+
}
455+
}
444456
if detachedSeconds > 0 && common.IsOracleProvider(p.provider) {
445457
function.SetDetachedTimeoutAnnotation(fn, detachedSeconds)
446458
}

commands/init.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ func initFlags(a *initFnCmd) []cli.Flag {
143143
Name: "provisioned-concurrency",
144144
Usage: "Set OCI provisioned concurrency using 'none' or 'constant:<count>'",
145145
},
146+
cli.StringFlag{
147+
Name: "pbf",
148+
Usage: "Initialize func.yaml for a Pre-Built Function using a PBF listing OCID",
149+
},
146150
}
147151

148152
return fgs
@@ -220,6 +224,15 @@ func (a *initFnCmd) init(c *cli.Context) error {
220224
return err
221225
}
222226
common.SetProvisionedConcurrency(a.ff, pcConfig)
227+
if pbfListingID := strings.TrimSpace(c.String("pbf")); pbfListingID != "" {
228+
if a.ff.Deploy == nil {
229+
a.ff.Deploy = &common.FuncDeployConfig{}
230+
}
231+
if a.ff.Deploy.OCI == nil {
232+
a.ff.Deploy.OCI = &common.OCIFunctionDeployConfig{}
233+
}
234+
a.ff.Deploy.OCI.PBF = &common.OCIPBFSourceConfig{ListingID: pbfListingID}
235+
}
223236
freeformTags, err := common.ParseFreeformTagSpecs(c.StringSlice("tag"))
224237
if err != nil {
225238
return err
@@ -249,7 +262,6 @@ func (a *initFnCmd) init(c *cli.Context) error {
249262
return fmt.Errorf("Runtime %s is no more supported for new apps. Please use python or %s runtime for new apps.", runtime, runtime[:strings.LastIndex(runtime, ".")])
250263
}
251264
}
252-
253265
path := c.Args().First()
254266
if path != "" {
255267
fmt.Printf("Creating function at: ./%s\n", path)
@@ -427,6 +439,9 @@ func (a *initFnCmd) BuildFuncFileV20180708(c *cli.Context, path string) error {
427439
if c.String("init-image") != "" {
428440
return nil
429441
}
442+
if strings.TrimSpace(c.String("pbf")) != "" {
443+
return nil
444+
}
430445

431446
var helper langs.LangHelper
432447
if runtime == "" {

common/funcfile.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,16 @@ type OCIProvisionedConcurrencyConfig struct {
8787
Count *int `yaml:"count,omitempty" json:"count,omitempty"`
8888
}
8989

90+
// OCIPBFSourceConfig stores Pre-Built Function source details for OCI Functions.
91+
type OCIPBFSourceConfig struct {
92+
ListingID string `yaml:"listing_id,omitempty" json:"listing_id,omitempty"`
93+
}
94+
9095
// OCIFunctionDeployConfig stores OCI-specific deploy configuration for a function.
9196
type OCIFunctionDeployConfig struct {
9297
ProvisionedConcurrency *OCIProvisionedConcurrencyConfig `yaml:"provisioned_concurrency,omitempty" json:"provisioned_concurrency,omitempty"`
9398
DetachedMode *OCIDetachedModeConfig `yaml:"detached_mode,omitempty" json:"detached_mode,omitempty"`
99+
PBF *OCIPBFSourceConfig `yaml:"pbf,omitempty" json:"pbf,omitempty"`
94100
FreeformTags map[string]string `yaml:"freeform_tags,omitempty" json:"freeform_tags,omitempty"`
95101
DefinedTags OCIDefinedTags `yaml:"defined_tags,omitempty" json:"defined_tags,omitempty"`
96102
}
@@ -439,6 +445,9 @@ func (ff *FuncFileV20180708) HasOCIManagedFunctionSettings() bool {
439445
if len(oci.FreeformTags) > 0 || len(oci.DefinedTags) > 0 {
440446
return true
441447
}
448+
if oci.PBF != nil && strings.TrimSpace(oci.PBF.ListingID) != "" {
449+
return true
450+
}
442451

443452
return false
444453
}
@@ -459,6 +468,9 @@ func (ff *FuncFileV20180708) OCIManagedFunctionSettingNames() []string {
459468
settings = append(settings, "detached_mode")
460469
}
461470
settings = append(settings, OCIManagedResourceTagSettingNames(ff)...)
471+
if oci.PBF != nil && strings.TrimSpace(oci.PBF.ListingID) != "" {
472+
settings = append(settings, "pbf")
473+
}
462474

463475
return settings
464476
}

0 commit comments

Comments
 (0)