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

feat: Introduce log and refactor logic of cmd #18

Merged
merged 14 commits into from
Mar 8, 2024
Merged
24 changes: 19 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
# PAN-OS Code Generation Repository (pan-os-codegen)

Welcome to the PAN-OS Code Generation Repository! This repository provides tools for generating the [pango SDK](https://github.com/PaloAltoNetworks/pango) and the `panos` [Terraform provider](https://github.com/PaloAltoNetworks/terraform-provider-panos) for Palo Alto Networks PAN-OS devices.
Welcome to the PAN-OS Code Generation Repository! This repository provides tools for generating
the [pango SDK](https://github.com/PaloAltoNetworks/pango) and
the `panos` [Terraform provider](https://github.com/PaloAltoNetworks/terraform-provider-panos) for Palo Alto Networks
PAN-OS devices.

## Overview

PAN-OS is the operating system for Palo Alto Networks next-generation firewalls and Panorama, providing advanced security features and capabilities. This repository aims to simplify the process of building and maintainging the Go SDK and Terraform provider.
PAN-OS is the operating system for Palo Alto Networks next-generation firewalls and Panorama, providing advanced
security features and capabilities. This repository aims to simplify the process of building and maintainging the Go SDK
and Terraform provider.

The repository contains:

Expand All @@ -13,14 +18,23 @@ The repository contains:

## Roadmap

We are maintaining a [public roadmap](https://github.com/orgs/PaloAltoNetworks/projects/62) to help users understand when we will release new features, bug fixes and enhancements.
We are maintaining a [public roadmap](https://github.com/orgs/PaloAltoNetworks/projects/62) to help users understand
when we will release new features, bug fixes and enhancements.

## Getting Help

Open an [issue](https://github.com/PaloAltoNetworks/pan-os-codegen/issues) on Github.

## Usage

The code have run login in `cmd/codegen` directory, to run it with default option please use:

```bash
go run cmd/mktp/main.go cmd/mktp/config.yaml
```
go run cmd/codegen/main.go
```
This command can be parametrizes using options:
- `-t/-type` - operation type, default is to create both Terraform
- `mktp` - create only Terraform provider
- `mksdk` - create only PAN-OS SDK
- `config` - specify path for the config file, default is `cmd/codegen/config.yaml`

6 changes: 5 additions & 1 deletion SUPPORT.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Community Supported

This template/script/solution is released “as-is”, with no warranty and no support. These should be seen as community supported and Palo Alto Networks may contribute its expertise at its discretion. Palo Alto Networks, including through its Authorized Support Centers (ASC) partners and backline support options, will not provide technical support or help in using or troubleshooting this template/script/solution. The underlying product used by this template/script/solution will still be supported in accordance with the product’s applicable support policy and the customer’s entitlements.
This template/script/solution is released “as-is”, with no warranty and no support. These should be seen as community
supported and Palo Alto Networks may contribute its expertise at its discretion. Palo Alto Networks, including through
its Authorized Support Centers (ASC) partners and backline support options, will not provide technical support or help
in using or troubleshooting this template/script/solution. The underlying product used by this template/script/solution
will still be supported in accordance with the product’s applicable support policy and the customer’s entitlements.
File renamed without changes.
86 changes: 86 additions & 0 deletions cmd/codegen/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package main

import (
"context"
"flag"
"log"

"github.com/paloaltonetworks/pan-os-codegen/pkg/commands/codegen"
)

// Config holds the configuration values for the application
type Config struct {
ConfigFile string
OpType string
}

// parseFlags parses the command line flags
func parseFlags() Config {
var cfg Config
flag.StringVar(&cfg.ConfigFile, "config", "./cmd/codegen/config.yaml", "Path to the configuration file")
flag.StringVar(&cfg.OpType, "t", "", "Operation type: 'mktp', 'mksdk' or leave empty for both")
flag.StringVar(&cfg.OpType, "type", "", "Operation type: 'mktp', 'mksdk' or leave empty for both")
flag.Parse()
return cfg
}

func main() {
cfg := parseFlags()

ctx := context.Background()
log.SetFlags(log.Ldate | log.Lshortfile)

// Log the operation type and configuration file being used
opTypeMessage := "Operation type: "
if cfg.OpType == "" {
opTypeMessage += "default option, create both PAN-OS SDK and Terraform Provider"
} else {
opTypeMessage += cfg.OpType
}
log.Printf("Using configuration file: %s\n", cfg.ConfigFile)
log.Println(opTypeMessage)

cmdType := codegen.CommandTypeSDK // Default command type
if cfg.OpType == "mktp" {
cmdType = codegen.CommandTypeTerraform
} else if cfg.OpType == "mksdk" {
cmdType = codegen.CommandTypeSDK
}

if cfg.OpType == "mktp" || cfg.OpType == "mksdk" {
cmd, err := codegen.NewCommand(ctx, cmdType, cfg.ConfigFile)
if err != nil {
log.Fatalf("Failed to create command: %s", err)
}
if err := cmd.Setup(); err != nil {
log.Fatalf("Setup failed: %s", err)
}
if err := cmd.Execute(); err != nil {
log.Fatalf("Execution failed: %s", err)
}
} else { // Default behavior to execute both if no specific OpType is provided
// Execute SDK
cmdSDK, err := codegen.NewCommand(ctx, codegen.CommandTypeSDK, cfg.ConfigFile)
if err != nil {
log.Fatalf("Failed to create command: %s", err)
}
if err := cmdSDK.Setup(); err != nil {
log.Fatalf("Setup SDK failed: %s", err)
}
if err := cmdSDK.Execute(); err != nil {
log.Fatalf("Execution SDK failed: %s", err)
}

// Execute Terraform
cmdTP, err := codegen.NewCommand(ctx, codegen.CommandTypeTerraform, cfg.ConfigFile)
if err != nil {
log.Fatalf("Failed to create command: %s", err)
}
if err := cmdTP.Setup(); err != nil {
log.Fatalf("Setup Terraform failed: %s", err)
}
if err := cmdTP.Execute(); err != nil {
log.Fatalf("Execution Terraform failed: %s", err)
}
}
}
25 changes: 0 additions & 25 deletions cmd/mktp/main.go

This file was deleted.

105 changes: 105 additions & 0 deletions pkg/commands/codegen/codegen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package codegen

import (
"context"
"fmt"
"log"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a preference to not use log, but instead have the commands take a stdin / stderr / stdout, and then use fmt.Fprintf() to output messages there, as this setup provides easier access to the log messages output for unit tests / integration tests. If you look at the scm generator, although I don't have any unit tests there, this is modeled in that generator.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But testing is based on the function working correctly and not on function logs. We are expecting that function behave and gives us wanted output :)

Copy link
Contributor

@sebastianczech sebastianczech Mar 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion we can go wit log approach and in tests focus on function outputs, not logs generated by function.

If in future that decision will not work for us, we can always change it :)


"github.com/paloaltonetworks/pan-os-codegen/pkg/generate"
"github.com/paloaltonetworks/pan-os-codegen/pkg/load"
"github.com/paloaltonetworks/pan-os-codegen/pkg/properties"
)

type CommandType string

const (
CommandTypeSDK CommandType = "sdk"
CommandTypeTerraform CommandType = "terraform"
)

type Command struct {
ctx context.Context
args []string
specs []string
config string
commandType CommandType
templatePath string
}

func NewCommand(ctx context.Context, commandType CommandType, args ...string) (*Command, error) {
var templatePath string
switch commandType {
case CommandTypeSDK:
templatePath = "templates/sdk"
case CommandTypeTerraform:
templatePath = "templates/terraform"
default:
return nil, fmt.Errorf("unsupported command type: %s", commandType)
}

return &Command{
ctx: ctx,
args: args,
commandType: commandType,
templatePath: templatePath,
}, nil
}

func (c *Command) Setup() error {
var err error
if c.specs == nil {
c.specs, err = properties.GetNormalizations()
if err != nil {
return fmt.Errorf("error getting normalizations: %s", err)
}
}
return nil
}

func (c *Command) Execute() error {
log.Printf("Generating %s\n", c.commandType)

if len(c.args) == 0 {
return fmt.Errorf("path to configuration file is required")
}
configPath := c.args[0]

content, err := load.File(configPath)
if err != nil {
return fmt.Errorf("error loading %s - %s", configPath, err)
}

config, err := properties.ParseConfig(content)
if err != nil {
return fmt.Errorf("error parsing %s - %s", configPath, err)
}

for _, specPath := range c.specs {
log.Printf("Parsing %s...\n", specPath)
content, err := load.File(specPath)
if err != nil {
return fmt.Errorf("error loading %s - %s", specPath, err)
}

spec, err := properties.ParseSpec(content)
if err != nil {
return fmt.Errorf("error parsing %s - %s", specPath, err)
}

if err = spec.Sanity(); err != nil {
return fmt.Errorf("%s sanity failed: %s", specPath, err)
}

generator := generate.NewCreator(config.Output.GoSdk, c.templatePath, spec)
if err = generator.RenderTemplate(); err != nil {
return fmt.Errorf("error rendering %s - %s", specPath, err)
}
}

if err = generate.CopyAssets(config); err != nil {
return fmt.Errorf("error copying assets %s", err)
}

log.Println("Generation complete.")
return nil
}
83 changes: 83 additions & 0 deletions pkg/commands/codegen/codegen_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package codegen

import (
"context"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
)

func TestNewCommand(t *testing.T) {
// given
tests := []struct {
name string
commandType CommandType
wantPath string
}{
{"SDK Command", CommandTypeSDK, "templates/sdk"},
{"Terraform Command", CommandTypeTerraform, "templates/terraform"},
}

for _, tt := range tests {
// when
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
cmd, err := NewCommand(ctx, tt.commandType, "dummyArg")

// then
assert.NoError(t, err)
assert.Equal(t, tt.wantPath, cmd.templatePath)
})
}
}

func TestCommandFunctionality(t *testing.T) {
// given
ctx := context.Background()
cmdType := CommandTypeSDK

// Create a temporary file to simulate the config file
tmpDir := t.TempDir()
tmpFile, err := os.Create(filepath.Join(tmpDir, "config-*.yaml"))
assert.NoError(t, err)
defer func(name string) {
err := os.Remove(name)
if err != nil {
assert.NoError(t, err)
}
}(tmpFile.Name())

// Write the necessary configuration data to the temporary file
configData := `
output:
go_sdk: "../generated/pango"
terraform_provider: "../generated/terraform-provider-panos"
`
_, err = tmpFile.WriteString(configData)
assert.NoError(t, err)
err = tmpFile.Close()
assert.NoError(t, err)

// when
cmd, err := NewCommand(ctx, cmdType, tmpFile.Name())
assert.NoError(t, err)

// then
assert.NoError(t, cmd.Setup(), "Setup should not return an error")
}
func TestCommandSetup(t *testing.T) {
//given
ctx := context.Background()

cmd, err := NewCommand(ctx, CommandTypeSDK, "config.yml")
assert.NoError(t, err)

// when
err = cmd.Setup()

//then
assert.NoError(t, err)

}
4 changes: 2 additions & 2 deletions pkg/generate/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package generate

import (
"bytes"
"fmt"
"github.com/paloaltonetworks/pan-os-codegen/pkg/properties"
"io"
"io/fs"
"log"
"os"
"path/filepath"
)
Expand Down Expand Up @@ -64,7 +64,7 @@ func copyAsset(target string, asset *properties.Asset, files []string) error {
for _, sourceFilePath := range files {
// Prepare destination path
destinationFilePath := filepath.Join(destinationDir, filepath.Base(sourceFilePath))
fmt.Printf("Copy file from %s to %s\n", sourceFilePath, destinationFilePath)
log.Printf("Copy file from %s to %s\n", sourceFilePath, destinationFilePath)

// Read the contents of the source file
data, err := os.ReadFile(sourceFilePath)
Expand Down
Loading
Loading