Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ILX Workspace management #106

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions cmd/ilx_example/example.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package main

import (
"context"
"fmt"
"log"
"os"
"time"

"github.com/f5devcentral/go-bigip"
)

func main() {
// Connect to the BIG-IP system.
config := bigip.Config{
Address: os.Getenv("BIG_IP_HOST"),
Username: os.Getenv("BIG_IP_USER"),
Password: os.Getenv("BIG_IP_PASSWORD"),
CertVerifyDisable: true,
}

// Create a new BIG-IP session with the provided configuration.
f5 := bigip.NewSession(&config)

// Create a context with a timeout of 1 second.
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()

// Define the workspace configuration.
workspaceConfig := bigip.WorkspaceConfig{
WorkspaceName: "ExampleWorkspace",
Partition: "Common",
}

// Create a new workspace.
err := f5.CreateWorkspace(ctx, workspaceConfig.WorkspaceName)
if err != nil {
panic(err)
}

// Fetch the details of the created workspace.
result, err := f5.GetWorkspace(ctx, workspaceConfig.WorkspaceName)
if err != nil {
panic(err)
}
log.Printf("Workspace: %v", result)

// Define the extension configuration.
opts := bigip.ExtensionConfig{
WorkspaceConfig: workspaceConfig,
ExtensionName: "exampleExt",
}

// Create a new extension.
err = f5.CreateExtension(ctx, opts)
if err != nil {
panic(err)
}

// Read the package.json file.
const packagePath string = "cmd/ilx_example/ilx/package.json"
packagejson, err := os.ReadFile(packagePath)
if err != nil {
fmt.Println("File reading error", err)
return
}

// Write the package.json file to the extension.
err = f5.WriteExtensionFile(ctx, opts, string(packagejson), bigip.PackageJSON)
if err != nil {
panic(err)
}

// Read the index.js file.
const indexjsPath string = "cmd/ilx_example/ilx/index.js"
indexjs, err := os.ReadFile(indexjsPath)
if err != nil {
fmt.Println("File reading error", err)
return
}

// Write the index.js file to the extension.
err = f5.WriteExtensionFile(ctx, opts, string(indexjs), bigip.IndexJS)
if err != nil {
panic(err)
}

// Read the index.js file from the extension.
content, err := f5.ReadExtensionFile(ctx, opts, bigip.IndexJS)
if err != nil {
panic(err)
}
fmt.Printf("Content: %+v\n", content)

// Write a TCL rule file to the workspace.
err = f5.WriteRuleFile(ctx, workspaceConfig, "<sometcl>", "Example.tcl")
if err != nil {
panic(err)
}

// Read the TCL rule file from the workspace.
out, err := f5.ReadRuleFile(ctx, workspaceConfig, "Example.tcl")
if err != nil {
panic(err)
}
log.Printf("Rule: %v", out.Content)
}
10 changes: 10 additions & 0 deletions cmd/ilx_example/ilx/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
var f5 = require('f5-nodejs');
var ilx = new f5.ILXServer();

ilx.addMethod('greeter', function(req, res) {
var arg = req.params()[0];

res.reply('Hello ' + arg);
});

ilx.listen();
34 changes: 34 additions & 0 deletions cmd/ilx_example/ilx/package-lock.json

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

15 changes: 15 additions & 0 deletions cmd/ilx_example/ilx/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "ilx",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "npm run dev"
},
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"f5-nodejs": "^1.0.0",
"hexy": "^0.3.5"
}
}
28 changes: 15 additions & 13 deletions device.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,19 +185,21 @@ func (p *Devicegroup) UnmarshalJSON(b []byte) error {
// https://10.192.74.80/mgmt/cm/device/licensing/pool/purchased-pool/licenses
// The above command will spit out license uuid and which should be mapped uriUuid
const (
uriMgmt = "mgmt"
uriCm = "cm"
uriDiv = "device"
uriDevices = "devices"
uriDG = "device-group"
uriLins = "licensing"
uriPoo = "pool"
uriPur = "purchased-pool"
uriLicn = "licenses"
uriMemb = "members"
uriUtility = "utility"
uriOfferings = "offerings"
uriF5BIGMSPBT10G = "f37c66e0-a80d-43e8-924b-3bbe9fe96bbe"
uriMgmt = "mgmt"
uriCm = "cm"
uriDiv = "device"
uriDevices = "devices"
uriDG = "device-group"
uriLins = "licensing"
uriPoo = "pool"
uriPur = "purchased-pool"
uriLicn = "licenses"
uriMemb = "members"
uriUtility = "utility"
uriOfferings = "offerings"
uriF5BIGMSPBT10G = "f37c66e0-a80d-43e8-924b-3bbe9fe96bbe"
uriWorkspace = "workspace"
WORKSPACE_UPLOAD_PATH = "/var/ilx/workspaces"
)

func (p *LIC) MarshalJSON() ([]byte, error) {
Expand Down
132 changes: 132 additions & 0 deletions ilx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package bigip

import (
"context"
"fmt"
)

type ILXWorkspace struct {
Name string `json:"name,omitempty"`
FullPath string `json:"fullPath,omitempty"`
SelfLink string `json:"selfLink,omitempty"`
NodeVersion string `json:"nodeVersion,omitempty"`
StagedDirectory string `json:"stagedDirectory,omitempty"`
Version string `json:"version,omitempty"`
Extensions []Extension `json:"extensions,omitempty"`
Rules []ILXFile `json:"rules,omitempty"`
Generation int `json:"generation,omitempty"`
}

type ILXFile struct {
Name string `json:"name,omitempty"`
Content string `json:"content,omitempty"`
}

type Extension struct {
Name string `json:"name,omitempty"`
Files []ILXFile `json:"files,omitempty"`
}

func (b *BigIP) GetWorkspace(ctx context.Context, path string) (*ILXWorkspace, error) {
spc := &ILXWorkspace{}
err, exists := b.getForEntity(spc, uriMgmt, uriTm, uriIlx, uriWorkspace, path)
if !exists {
return nil, fmt.Errorf("workspace does not exist: %w", err)
}
if err != nil {
return nil, fmt.Errorf("error getting ILX Workspace: %w", err)
}

return spc, nil
}

func (b *BigIP) CreateWorkspace(ctx context.Context, path string) error {
err := b.post(ILXWorkspace{Name: path}, uriMgmt, uriTm, uriIlx, uriWorkspace, "")
if err != nil {
return fmt.Errorf("error creating ILX Workspace: %w", err)
}

return nil
}

func (b *BigIP) DeleteWorkspace(ctx context.Context, name string) error {
err := b.delete(uriMgmt, uriTm, uriIlx, uriWorkspace, name)
if err != nil {
return fmt.Errorf("error deleting ILX Workspace: %w", err)
}
return nil
}

func (b *BigIP) CreateExtension(ctx context.Context, opts ExtensionConfig) error {
err := b.post(ILXWorkspace{Name: opts.WorkspaceName}, uriMgmt, uriTm, uriIlx, uriWorkspace+"?options=extension,"+opts.ExtensionName)
if err != nil {
return fmt.Errorf("error creating ILX Extension: %w", err)
}
return nil
}

type ExtensionFile string

func (e ExtensionFile) Validate() error {
if e != PackageJSON && e != IndexJS {
return fmt.Errorf("invalid extension file")
}
return nil
}

const (
PackageJSON ExtensionFile = "package.json"
IndexJS ExtensionFile = "index.js"
)

type WorkspaceConfig struct {
WorkspaceName string `json:"name,omitempty"`
Partition string `json:"partition,omitempty"`
}

type ExtensionConfig struct {
WorkspaceConfig
ExtensionName string `json:"extensionName,omitempty"`
}

func (b *BigIP) WriteRuleFile(ctx context.Context, opts WorkspaceConfig, content string, filename string) error {
destination := fmt.Sprintf("%s/%s/%s/rules/%s", WORKSPACE_UPLOAD_PATH, opts.Partition, opts.WorkspaceName, filename)
err := b.WriteFile(content, destination)
if err != nil {
return fmt.Errorf("error uploading rule file: %w", err)
}
return nil
}

func (b *BigIP) WriteExtensionFile(ctx context.Context, opts ExtensionConfig, content string, filename ExtensionFile) error {
if err := filename.Validate(); err != nil {
return err
}
destination := fmt.Sprintf("%s/%s/%s/extensions/%s/%s", WORKSPACE_UPLOAD_PATH, opts.WorkspaceConfig.Partition, opts.WorkspaceConfig.WorkspaceName, opts.ExtensionName, filename)
err := b.WriteFile(content, destination)
if err != nil {
return fmt.Errorf("error uploading packagejson: %w", err)
}
return nil
}

func (b *BigIP) ReadExtensionFile(ctx context.Context, opts ExtensionConfig, filename ExtensionFile) (*ILXFile, error) {
if err := filename.Validate(); err != nil {
return nil, err
}
destination := fmt.Sprintf("%s/%s/%s/extensions/%s/%s", WORKSPACE_UPLOAD_PATH, opts.Partition, opts.WorkspaceConfig.WorkspaceName, opts.ExtensionName, filename)
files, err := b.ReadFile(destination)
if err != nil {
return nil, err
}
return files, nil
}

func (b *BigIP) ReadRuleFile(ctx context.Context, opts WorkspaceConfig, filename string) (*ILXFile, error) {
destination := fmt.Sprintf("%s/%s/%s/rules/%s", WORKSPACE_UPLOAD_PATH, opts.Partition, opts.WorkspaceName, filename)
files, err := b.ReadFile(destination)
if err != nil {
return nil, err
}
return files, nil
}
Loading