Skip to content

rabobank/cf-plugins

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CF-plugins

A library to allow existing cf cli plugins to start using the v3 cc api instead of the v2 which is called through rpc calls. It only uses the rpc calls to obtain context information ( like current org and space, for example) and the cf token which can be used to directly interact with the cf landscape.

Usage

The library mimicks the normal cli plugins framework and emulates the plugin CliConnection object, to migrate to v3 one must simply import the cf-plugins library and use it to start the plugin instead of directly using the cf cli plugin library, which means that for a simple plugin like:

package main

import (
    "fmt"
    "os"

    "code.cloudfoundry.org/cli/plugin"
)

type CfPlugin struct{}

func (c *CfPlugin) Run(cliConnection plugin.CliConnection, args []string) {
    if args[0] == "CLI-MESSAGE-UNINSTALL" {
        return
    }
    
    fmt.Println("I'm a plugin")
}

func (c *CfPlugin) GetMetadata() plugin.PluginMetadata {
    return plugin.PluginMetadata{
        Name:          "test-plugin",
        Version:       plugin.VersionType{Major: 1, Minor: 0, Build: 0},
        MinCliVersion: plugin.VersionType{Major: 8, Minor: 0, Build: 0},
        Commands:      []plugin.Command{
            {
                Name:     "tester",
                HelpText: "Simple test plugin",
            },
        },
    }
}

func main() {
    if len(os.Args) == 1 {
        _, _ = fmt.Fprintf(os.Stderr, "This executable is a cf plugin.\n"+
            "Run `cf install-plugin %s` to install it",
            os.Args[0])
        os.Exit(1)
    }

    plugin.Start(new(CfPlugin))
}

a simple import of cf-plugins and using the plugins Start method is enough to convert the plugin

package main

import (
    "fmt"
    "os"

    "code.cloudfoundry.org/cli/plugin"
    "github.com/rabobank/cf-plugins" // Add this import
)
                 .
                 .
                 .
func main() {
    if len(os.Args) == 1 {
        _, _ = fmt.Fprintf(os.Stderr, "This executable is a cf plugin.\n"+
            "Run `cf install-plugin %s` to install it",
            os.Args[0])
        os.Exit(1)
    }

    plugins.Start(new(CfPlugin)) // Switch to plugins instead of plugin
}

Improved Usage

The CliConnection emulation is quite inefficient when using the standard CliConnection methods to get app, service, orgs and spaces information. This is due to the more modularized v3 api nature (as compared to v2) which requires several calls to provide the same information the v2 app used to. Quite often, most of that information is not required so it would be much more efficient to directly use the cc api to get the specific information.

To further migrate away from the standard cli plugin framework, you may explicitly implement the cf-plugins interface and use Execute instead of Run to get a cli connection which provides you a ccv3 api client which you may call to directly query cloud controller if required.

package main

import (
    "fmt"
    "os"

    "code.cloudfoundry.org/cli/plugin"
    "github.com/rabobank/cf-plugins" // Add this import
)

type CfPlugin struct{}

func (c *CfPlugin) Execute(cliConnection plugins.CliConnection, args []string) {
    if args[0] == "CLI-MESSAGE-UNINSTALL" {
        return
    }
    
    fmt.Println("I'm a plugin")
}

func (c *CfPlugin) GetMetadata() plugin.PluginMetadata {
    return plugin.PluginMetadata{
        Name:          "test-plugin",
        Version:       plugin.VersionType{Major: 1, Minor: 0, Build: 0},
        MinCliVersion: plugin.VersionType{Major: 8, Minor: 0, Build: 0},
        Commands:      []plugin.Command{
            {
                Name:     "tester",
                HelpText: "Simple test plugin",
            },
        },
    }
}

func main() {
    if len(os.Args) == 1 {
        _, _ = fmt.Fprintf(os.Stderr, "This executable is a cf plugin.\n"+
            "Run `cf install-plugin %s` to install it",
            os.Args[0])
        os.Exit(1)
    }

    plugins.Execute(new(CfPlugin))
}

Caveats

When using the emulated CliConnection to retrieve organization or space users, the flag IsAdmin will always be set to false as to avoid having to query UAA to check the user roles.

The BuildpackUrl attribute of the App object when calling GetApp from the CliConnection will return a single buildpack name.

The App object is not suitable for the now multiple-process supporting CF model, as such it will be based on the first process type of the app

The list of apps will not get the additional usage statistics for every app, this is also due to the multiple-process nature of the CF model which would require calling the processes api for each app and use the first one.

About

Wrapper for the cf cli plugin package to handle v3 api

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages