Skip to content

Commit 1b6888f

Browse files
vdjagilevgorkavp
andcommitted
Add Excel format support (#156) (#162)
* Add Excel format support (#156) * Excel format support added * fix issuses * Update README.md * Update README.md * Update README.md * Update README.md * tweak: ci: fix branch trigger name * tweak: err check * chore: refactor writing headers * chore: minor warning fixes * chore: ci: update versions * refactor: split into smaller functions * tweak: excel: column width * tweak: excel: cosmetic text wrapping * tweak: excel: ip-addr & hostname text cosmetic improvements * tests: implement basic unit tests * tweak: linter fixes * tests: increase validation coverage * tests: coverage: output file * tests: excel: more test cases * tests: excel: bigger coverage --------- Co-authored-by: Gorka <72318822+gorkavp@users.noreply.github.com>
1 parent 03a9a5f commit 1b6888f

16 files changed

+506
-22
lines changed

.github/workflows/assets.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ jobs:
1212
id: get_version
1313
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
1414
- name: Checkout
15-
uses: actions/checkout@v3
15+
uses: actions/checkout@v4
1616
- name: Set up Go
17-
uses: actions/setup-go@v4
17+
uses: actions/setup-go@v5
1818
with:
1919
go-version: 1.20.x
2020
- name: Build and pack for linux-amd64

.github/workflows/go.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
pull_request:
77
branches:
88
- main
9-
- dev-*
9+
- "*-dev"
1010

1111
jobs:
1212
lint:
@@ -16,12 +16,12 @@ jobs:
1616
runs-on: ubuntu-latest
1717
steps:
1818
- name: Set up Go
19-
uses: actions/setup-go@v4
19+
uses: actions/setup-go@v5
2020
with:
2121
go-version: ${{ matrix.go-version }}
2222
- uses: actions/checkout@v4
2323
- name: Run golangci-lint
24-
uses: golangci/golangci-lint-action@v3
24+
uses: golangci/golangci-lint-action@v4
2525
with:
2626
version: latest
2727
args: --timeout 10m
@@ -35,7 +35,7 @@ jobs:
3535
- uses: actions/checkout@v4
3636

3737
- name: Set up Go
38-
uses: actions/setup-go@v4
38+
uses: actions/setup-go@v5
3939
with:
4040
go-version: ${{ matrix.go-version }}
4141

@@ -53,7 +53,7 @@ jobs:
5353
- uses: actions/checkout@v4
5454

5555
- name: Set up Go
56-
uses: actions/setup-go@v4
56+
uses: actions/setup-go@v5
5757
with:
5858
go-version: ${{ matrix.go-version }}
5959

.github/workflows/release-package.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,23 @@ jobs:
1717

1818
steps:
1919
- name: Checkout repository
20-
uses: actions/checkout@v3
20+
uses: actions/checkout@v4
2121

2222
- name: Log in to the Container registry
23-
uses: docker/login-action@v2
23+
uses: docker/login-action@v3
2424
with:
2525
registry: ${{ env.REGISTRY }}
2626
username: ${{ github.actor }}
2727
password: ${{ secrets.GITHUB_TOKEN }}
2828

2929
- name: Extract metadata (tags, labels) for Docker
3030
id: meta
31-
uses: docker/metadata-action@v4
31+
uses: docker/metadata-action@v5
3232
with:
3333
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
3434

3535
- name: Build and push Docker image
36-
uses: docker/build-push-action@v4
36+
uses: docker/build-push-action@v5
3737
with:
3838
context: .
3939
push: true

README.md

+11-7
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,20 @@ HTML:
1313
Graphviz:
1414
![nmap-example-graphviz](docs/images/example-dot.png)
1515

16-
A tool that allows you to convert NMAP XML output to html/csv/json/markdown/dot/sqlite.
16+
A tool that allows you to convert NMAP XML output to excel/html/csv/json/markdown/dot/sqlite.
1717

1818
## Installation
1919

20-
It's possible to install it using `go install` command
21-
2220
```
23-
go install github.com/vdjagilev/nmap-formatter/v2@latest
21+
git clone https://github.com/gorkavp/nmap-formatter.git
22+
cd nmap-formatter
23+
go build
2424
```
2525

26-
All other options can be found on [Installation Wiki page](https://github.com/vdjagilev/nmap-formatter/wiki/Installation).
27-
2826
## Usage
2927

3028
```bash
31-
nmap-formatter [html|csv|md|json|dot|sqlite] [path-to-nmap.xml] [flags]
29+
nmap-formatter [html|csv|md|json|dot|sqlite|excel] [path-to-nmap.xml] [flags]
3230
```
3331

3432
Or alternatively you can read file from `stdin` and parse it
@@ -49,6 +47,12 @@ or Markdown
4947
nmap-formatter md [path-to-nmap.xml] > some-markdown.md
5048
```
5149

50+
or Excel
51+
52+
```bash
53+
nmap-formatter excel [path-to-nmap.xml]
54+
```
55+
5256
or JSON
5357

5458
```bash

cmd/root.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ var config = formatter.Config{
3939
JSONOptions: formatter.JSONOutputOptions{},
4040
CSVOptions: formatter.CSVOutputOptions{},
4141
SqliteOutputOptions: formatter.SqliteOutputOptions{},
42+
ExcelOptions: formatter.ExcelOutputOptions{},
4243
},
4344
ShowVersion: false,
4445
CurrentVersion: VERSION,
@@ -51,9 +52,9 @@ var workflow formatter.Workflow
5152

5253
// rootCmd represents the base command when called without any subcommands
5354
var rootCmd = &cobra.Command{
54-
Use: "nmap-formatter [html|csv|md|json|dot|sqlite] [path-to-nmap.xml]",
55+
Use: "nmap-formatter [html|csv|md|json|dot|sqlite|excel] [path-to-nmap.xml]",
5556
Short: "Utility that can help you to convert NMAP XML application output to various other formats",
56-
Long: `This utility allows you to convert NMAP XML output to various other formats like (html, csv, markdown (md), json, dot)`,
57+
Long: `This utility allows you to convert NMAP XML output to various other formats like (html, csv, markdown (md), json, dot, excel, sqlite)`,
5758
Args: arguments,
5859
RunE: run,
5960
}

cmd/root_test.go

+58
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,64 @@ func Test_validate(t *testing.T) {
8888
}
8989
},
9090
},
91+
{
92+
name: "Successful validation output file",
93+
args: args{
94+
config: formatter.Config{
95+
OutputFormat: formatter.ExcelOutput,
96+
InputFileConfig: formatter.InputFileConfig{
97+
Path: path.Join(os.TempDir(), "formatter_cmd_valid_output"),
98+
},
99+
OutputFile: formatter.OutputFile("output.xlsx"),
100+
},
101+
},
102+
wantErr: false,
103+
before: func(t *testing.T) {
104+
path := path.Join(os.TempDir(), "formatter_cmd_valid_output")
105+
_, err := os.Create(path)
106+
if err != nil {
107+
t.Errorf("could not create input file: %s", path)
108+
}
109+
},
110+
after: func(t *testing.T) {},
111+
},
112+
{
113+
name: "Successful validation template",
114+
args: args{
115+
config: formatter.Config{
116+
OutputFormat: formatter.MarkdownOutput,
117+
TemplatePath: path.Join(os.TempDir(), "formatter_template_valid"),
118+
InputFileConfig: formatter.InputFileConfig{
119+
Path: path.Join(os.TempDir(), "formatter_cmd_valid_template_3"),
120+
},
121+
},
122+
},
123+
wantErr: false,
124+
before: func(t *testing.T) {
125+
templatePath := path.Join(os.TempDir(), "formatter_template_valid")
126+
filePath := path.Join(os.TempDir(), "formatter_cmd_valid_template_3")
127+
_, err := os.Create(templatePath)
128+
if err != nil {
129+
t.Errorf("could not create temporary file: %s", templatePath)
130+
}
131+
_, err = os.Create(filePath)
132+
if err != nil {
133+
t.Errorf("could not create temporary file: %s", filePath)
134+
}
135+
},
136+
after: func(t *testing.T) {
137+
templatePath := path.Join(os.TempDir(), "formatter_template_valid")
138+
filePath := path.Join(os.TempDir(), "formatter_cmd_valid_template_3")
139+
err := os.Remove(templatePath)
140+
if err != nil {
141+
t.Logf("could not remove temporary file: %s", templatePath)
142+
}
143+
err = os.Remove(filePath)
144+
if err != nil {
145+
t.Logf("could not remove temporary file: %s", filePath)
146+
}
147+
},
148+
},
91149
}
92150
for _, tt := range tests {
93151
t.Run(tt.name, func(t *testing.T) {

cmd/validation.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
// validate is checking input from the command line
1111
func validate(config formatter.Config) error {
1212
if !config.OutputFormat.IsValid() {
13-
return fmt.Errorf("not valid format: %s, please choose html/json/md/csv/sqlite", config.OutputFormat)
13+
return fmt.Errorf("not valid format: %s, please choose html/json/md/csv/excel/sqlite", config.OutputFormat)
1414
}
1515

1616
err := validateIOFiles(config)

formatter/format.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ const (
1616
DotOutput OutputFormat = "dot"
1717
// SqliteOutput constant defines OutputFormat for sqlite file, which can be used to generate sqlite embedded databases
1818
SqliteOutput OutputFormat = "sqlite"
19+
// ExcelOutput constant defines OutputFormat for Excel file, which can be used to generate Excel files
20+
ExcelOutput OutputFormat = "excel"
1921
)
2022

2123
// IsValid checks whether requested output format is valid
2224
func (of OutputFormat) IsValid() bool {
2325
// markdown & md is essentially the same thing
2426
switch of {
25-
case "markdown", "md", "html", "csv", "json", "dot", "sqlite":
27+
case "markdown", "md", "html", "csv", "json", "dot", "sqlite", "excel":
2628
return true
2729
}
2830
return false

formatter/format_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ func TestOutputFormat_IsValid(t *testing.T) {
5050
of: "sqlite",
5151
want: true,
5252
},
53+
{
54+
name: "excel",
55+
of: "sqlite",
56+
want: true,
57+
},
5358
}
5459
for _, tt := range tests {
5560
t.Run(tt.name, func(t *testing.T) {

formatter/formatter.go

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ func New(config *Config) Formatter {
2525
return &CSVFormatter{
2626
config,
2727
}
28+
case ExcelOutput:
29+
return &ExcelFormatter{
30+
config,
31+
}
2832
case DotOutput:
2933
return &DotFormatter{
3034
config,

0 commit comments

Comments
 (0)