Skip to content

Commit

Permalink
Merge pull request #219 from azar-writes-code/feat-xmlconvert
Browse files Browse the repository at this point in the history
feat: command `xmlconvert` and `customLicense` added to compage cli
  • Loading branch information
devopstoday11 authored May 29, 2024
2 parents 0ac2096 + bb0c053 commit 7303d6c
Show file tree
Hide file tree
Showing 9 changed files with 365 additions and 256 deletions.
21 changes: 21 additions & 0 deletions cmd/customLicense.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cmd

import (
"github.com/intelops/compage/cmd/subcommand/customLicense"
"github.com/sirupsen/logrus"
)

func init() {
// Create the logger instance
logger := logrus.New()
logger.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2006-01-02 15:04:05",
})

// Create the instance for customlicense
customlicense := customLicense.NewCustomLicenseCmd(logger)

// Add Subcommand for the root command
rootCmd.AddCommand(customlicense.Execute())
}
10 changes: 10 additions & 0 deletions cmd/subcommand/customLicense/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package customLicense

Check failure on line 1 in cmd/subcommand/customLicense/constants.go

View workflow job for this annotation

GitHub Actions / build-and-test

ST1003: should not use MixedCaps in package name; customLicense should be customlicense (stylecheck)

const exampleCommand = `
# Convert XML file to JSON and YAML with the file path provided in the command line
compage customLicense path=https://raw.githubusercontent.com/licenses/license-templates/master/templates/apache.txt projectPath=/some/local/path/LICENSE
`
var (
path = "https://raw.githubusercontent.com/licenses/license-templates/master/templates/apache.txt"
projectPath = "LICENSE"
)
101 changes: 101 additions & 0 deletions cmd/subcommand/customLicense/customLicense.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package customLicense

Check failure on line 1 in cmd/subcommand/customLicense/customLicense.go

View workflow job for this annotation

GitHub Actions / build-and-test

ST1003: should not use MixedCaps in package name; customLicense should be customlicense (stylecheck)

import (
"io"
"net/http"
"os"
"path/filepath"

"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

type CustomLicenseCmd struct {
logger *logrus.Logger
}

func NewCustomLicenseCmd(logger *logrus.Logger) *CustomLicenseCmd {
return &CustomLicenseCmd{
logger: logger,
}
}

// Execute runs the xmlconvert command
func (cl *CustomLicenseCmd) Execute() *cobra.Command {
// Create a new cobra command for xmlconvert
customLicenseCmd := &cobra.Command{
Use: "customLicense",
Short: "customLicense takes the public url of the license file and stores it in the specified path of the project",
Long: `The 'customLicense' command retrieves a license file from a specified public URL and stores it in a designated path within your project. By default, it uses 'config.xml' for the license URL and 'config.yaml' for the project path, ensuring easy integration and updates of license files. This command includes pre-run validation and customizable flags for flexible usage.`,
Example: exampleCommand,
PreRun: cl.preRun, // Define a pre-run function
Run: cl.run, // Define the run function
}

// Define the flags for the xmlconvert command
customLicenseCmd.Flags().StringVar(&path, "path", path, "please specify the public url of the license file. The default path is ``")
customLicenseCmd.Flags().StringVar(&projectPath, "projectPath", projectPath, "Provide the project path to store the license file. The default path is ``")

return customLicenseCmd
}

func (cl *CustomLicenseCmd) preRun(cmd *cobra.Command, args []string) {
// Do any pre-run setup here
yellow := "\033[33m"
reset := "\033[0m"
text := "WARNING: This command is in alpha version and may need some changes."
cl.logger.Println(yellow + text + reset)
}

func (cl *CustomLicenseCmd) run(cmd *cobra.Command, args []string) {
// Ensure path is set
if path == "" {
cl.logger.Fatal("Path to the license file URL must be specified")
}

// Use the current working directory if projectPath is not provided
if projectPath == "" {
cwd, err := os.Getwd()
if err != nil {
cl.logger.Fatalf("Failed to get the current working directory: %v", err)
}
projectPath = filepath.Join(cwd, "LICENSE")
}

// Log the start of the process
cl.logger.Println("Starting to download the license file from:", path)

// Create the HTTP request to fetch the license file
response, err := http.Get(path)
if err != nil {
cl.logger.Fatalf("Failed to download the license file: %v", err)
}
defer response.Body.Close()

// Check if the HTTP request was successful
if response.StatusCode != http.StatusOK {
cl.logger.Fatalf("Failed to download the license file, HTTP Status: %s", response.Status)
}

// Create the destination directory if it does not exist
err = os.MkdirAll(filepath.Dir(projectPath), os.ModePerm)
if err != nil {
cl.logger.Fatalf("Failed to create the destination directory: %v", err)
}

// Create the destination file
outFile, err := os.Create(projectPath)
if err != nil {
cl.logger.Fatalf("Failed to create the destination file: %v", err)
}
defer outFile.Close()

// Copy the content from the response to the file
_, err = io.Copy(outFile, response.Body)
if err != nil {
cl.logger.Fatalf("Failed to save the license file: %v", err)
}

// Log the success of the operation
cl.logger.Println("License file successfully downloaded and stored at:", projectPath)
}
18 changes: 18 additions & 0 deletions cmd/subcommand/xmlconvert/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package xmlconvert

// xmlFile is the default path to the XML configuration file.
var xmlFile = "config.xml"

// outputFiles is the default list of output file paths.
var outputFiles = []string{
"config.yaml",
"config.json",
}

var exampleCommand = `
# Convert XML file to JSON and YAML with the file path provided in the command line
compage xmlconvert --xmlFile config.xml
# Convert XML file to JSON and YAML with the provided output files with path name specified
compage xmlconvert --xmlFile config.xml --outputFiles filename.yaml,filename.json
`
80 changes: 80 additions & 0 deletions cmd/subcommand/xmlconvert/converter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package xmlconvert

import (
"encoding/json"
"fmt"
"io"
"os"

"github.com/clbanning/mxj/v2"
"gopkg.in/yaml.v2"
)

// ReadXML reads the XML file from the provided path and unmarshals it into a generic map.
func ReadXML(filePath string) (map[string]interface{}, error) {
// Open the XML file.
xmlFile, err := os.Open(filePath)
if err != nil {
return nil, fmt.Errorf("failed to open XML file: %v", err)
}
defer xmlFile.Close()

// Read the XML file into a byte slice.
byteValue, _ := io.ReadAll(xmlFile)

// Convert the XML file into a generic map.
result, err := mxj.NewMapXml(byteValue)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal XML: %v", err)
}

return result, nil
}

// WriteJSON writes the given data to a JSON file at the specified path.
func WriteJSON(data map[string]interface{}, filePath string) error {
// Marshal the data into a JSON byte slice with indentation.
jsonData, err := json.MarshalIndent(data, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal JSON: %v", err)
}

// Write the JSON data to the specified file path.
err = os.WriteFile(filePath, jsonData, 0644)
if err != nil {
return fmt.Errorf("failed to write JSON file: %v", err)
}

return nil
}

// WriteYAML writes the given data to a YAML file at the specified path.
func WriteYAML(data map[string]interface{}, filePath string) error {
// Marshal the data into a YAML byte slice.
yamlData, err := yaml.Marshal(data)
if err != nil {
return fmt.Errorf("failed to marshal YAML: %v", err)
}

// Write the YAML data to the specified file path.
err = os.WriteFile(filePath, yamlData, 0644)
if err != nil {
return fmt.Errorf("failed to write YAML file: %v", err)
}

return nil
}

// CreateFile writes the given data to a file at the specified path based on the file extension.
// Supported file extensions are "json" and "yaml".
func CreateFile(data map[string]interface{}, filePath string, extension string) error {
// Determine the file type based on the extension.
switch extension {
case "json":
return WriteJSON(data, filePath)
case "yaml":
return WriteYAML(data, filePath)
default:
return fmt.Errorf("invalid file extension: %s", extension)
}
}
77 changes: 77 additions & 0 deletions cmd/subcommand/xmlconvert/xmlconvert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package xmlconvert

import (
"strings"

"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

// XMLConvertCmd represents the structure of the xmlconvert command
type XMLConvertCmd struct {
logger *logrus.Logger
}

// NewXMLConvertCmd returns a new instance of XMLConvertCmd
func NewXMLConvertCmd(logger *logrus.Logger) *XMLConvertCmd {
return &XMLConvertCmd{
logger: logger,
}
}

// Execute runs the xmlconvert command
func (xml *XMLConvertCmd) Execute() *cobra.Command {
// Create a new cobra command for xmlconvert
xmlConvertCmd := &cobra.Command{
Use: "xmlconvert",
Short: "Convert XML to JSON and YAML",
Long: "`xmlconvert` converts XML file provided in the command line arguments to JSON and YAML format. It can be used to convert XML file to JSON and YAML file.",
Example: exampleCommand,
PreRun: xml.preRun, // Define a pre-run function
Run: xml.run, // Define the run function
}

// Define the flags for the xmlconvert command
xmlConvertCmd.Flags().StringVar(&xmlFile, "xmlFile", xmlFile, "provide xml file path to convert. The default path is `config.xml`")
xmlConvertCmd.Flags().StringArrayVar(&outputFiles, "outputFiles", outputFiles, "returns converted output file. The default path is `config.yaml`")

return xmlConvertCmd
}

// preRun is a pre-run function that logs a warning message
func (xml *XMLConvertCmd) preRun(cmd *cobra.Command, args []string) {
yellow := "\033[33m"
reset := "\033[0m"
text := "WARNING: This command is in alpha version and may need some changes."
xml.logger.Println(yellow + text + reset)
}

// run is the function that will be called when the xmlconvert command is executed
func (xml *XMLConvertCmd) run(cmd *cobra.Command, args []string) {
xmlData, err := ReadXML(xmlFile)
if err != nil {
xml.logger.Fatal(err)
}
xml.logger.Info("output files: ", outputFiles)

// Check if only two output files are supported
if len(outputFiles) > 2 {
xml.logger.Fatal("only two output file extensions are supported: json and yaml")
}

// Check if output files are provided
if len(outputFiles) == 0 {
xml.logger.Fatal("please provide output file")
}

// Check if only one output file is provided
if len(outputFiles) == 1 {
fileExtension := strings.Split(outputFiles[0], ".")[len(strings.Split(outputFiles[0], "."))-1]
CreateFile(xmlData, outputFiles[0], fileExtension)

Check failure on line 70 in cmd/subcommand/xmlconvert/xmlconvert.go

View workflow job for this annotation

GitHub Actions / build-and-test

Error return value is not checked (errcheck)
} else {
for _, file := range outputFiles {
fileExtension := strings.Split(file, ".")[len(strings.Split(file, "."))-1]
CreateFile(xmlData, file, fileExtension)

Check failure on line 74 in cmd/subcommand/xmlconvert/xmlconvert.go

View workflow job for this annotation

GitHub Actions / build-and-test

Error return value is not checked (errcheck)
}
}
}
21 changes: 21 additions & 0 deletions cmd/xmlconvert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cmd

import (
"github.com/intelops/compage/cmd/subcommand/xmlconvert"
"github.com/sirupsen/logrus"
)

func init() {
// Create the logger instance
logger := logrus.New()
logger.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2006-01-02 15:04:05",
})

// Create the instance for xmlconvert
xmlConvert := xmlconvert.NewXMLConvertCmd(logger)

// Add Subcommand for the root command
rootCmd.AddCommand(xmlConvert.Execute())
}
7 changes: 2 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/intelops/compage
go 1.22

require (
github.com/clbanning/mxj/v2 v2.7.0
github.com/fatih/color v1.16.0
github.com/gertd/go-pluralize v0.2.1
github.com/go-git/go-git/v5 v5.12.0
Expand All @@ -23,6 +24,7 @@ require (
golang.org/x/text v0.14.0
google.golang.org/grpc v1.62.1
google.golang.org/protobuf v1.33.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
oras.land/oras-go/v2 v2.5.0
)
Expand Down Expand Up @@ -86,7 +88,6 @@ require (
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
Expand Down Expand Up @@ -161,15 +162,13 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mozillazg/docker-credential-acr-helper v0.3.0 // indirect
github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect
github.com/oklog/ulid v1.3.1 // indirect
Expand Down Expand Up @@ -242,11 +241,9 @@ require (
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/api v0.29.3 // indirect
k8s.io/apimachinery v0.29.3 // indirect
k8s.io/client-go v0.29.3 // indirect
Expand Down
Loading

0 comments on commit 7303d6c

Please sign in to comment.