Skip to content

Commit

Permalink
Merge branch 'feature/swupdater' of https://github.com/graugans/go-ov…
Browse files Browse the repository at this point in the history
…p8xx into feature/swupdater
  • Loading branch information
graugans committed Jun 14, 2024
2 parents bc34ba6 + a8fd080 commit 6773bc5
Show file tree
Hide file tree
Showing 24 changed files with 483 additions and 46 deletions.
23 changes: 22 additions & 1 deletion .devcontainer/postCreateCommand.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,25 @@
#!/bin/bash

# install missing packages
sudo apt-get update &&
sudo apt-get install -q -y git-lfs \
python3-pip \
python3-venv \
shfmt \
shellcheck &&
sudo apt-get clean &&
sudo rm -rf /var/lib/apt/lists/*

# Fetch git large files
git lfs fetch --all

# Install Python packages
export PATH=~/.local/bin:$PATH
pip3 install --break-system-packages --upgrade pip
pip3 install --break-system-packages -r requirements.txt

# Go CI Lint
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.54.0
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "$(go env GOPATH)/bin" v1.54.0

# Go tools
go install golang.org/x/tools/cmd/goimports@latest
10 changes: 5 additions & 5 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '1.20'
go-version: '1.22'
cache: false
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
# Require: The version of golangci-lint to use.
# When `install-mode` is `binary` (default) the value can be v1.2 or v1.2.3 or `latest` to use the latest version.
# When `install-mode` is `goinstall` the value can be v1.2.3, `latest`, or the hash of a commit.
version: v1.53
version: v1.57

test:
runs-on: ubuntu-latest
Expand All @@ -38,7 +38,7 @@ jobs:
- name: 👷 Prepare the Go environment
uses: actions/setup-go@v4
with:
go-version: '1.21'
go-version: '1.22'
- name: 🧪 Run the unit tests
run: go test -v -failfast -coverprofile cover.out -timeout=1m ./...
- name: 🚀 Upload the coverage reports to Codecov
Expand All @@ -52,7 +52,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '1.21'
go-version: '1.22'

- name: Install dependencies
run: go get -d ./...
Expand All @@ -72,7 +72,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '1.21'
go-version: '1.22'
- uses: go-semantic-release/action@v1
with:
hooks: goreleaser
Expand Down
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
A GO module and cli to access the ifm OVP8xx series of devices.


[![GitHub go.mod Go version of a Go module](https://img.shields.io/github/go-mod/go-version/gomods/athens.svg)](https://github.com/gomods/athens)
[![GitHub go.mod Go version of a Go module](https://img.shields.io/github/go-mod/go-version/graugans/go-ovp8xx.svg)](https://github.com/graugans/go-ovp8xx)
[![Go Reference](https://pkg.go.dev/badge/github.com/graugans/go-ovp8xx/v2.svg)](https://pkg.go.dev/github.com/graugans/go-ovp8xx/v2)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
![example workflow](https://github.com/graugans/go-ovp8xx/actions/workflows/go.yml/badge.svg)
[![codecov](https://codecov.io/gh/graugans/go-ovp8xx/graph/badge.svg?token=BU6UPYCUPI)](https://codecov.io/gh/graugans/go-ovp8xx)
Expand All @@ -18,28 +19,34 @@ A GO module and cli to access the ifm OVP8xx series of devices.

This project is still a work in progress and will suffer from breaking API changes. Please be warned. In case you have any suggestions or want to contribute please feel free to open an issue or pull request.

## CLI Installation
## CLI

### Pre Build Binaries
One of the benefits of the Go language is the easy way of producing statically linked binaries to be used on all major platforms. One of the `ovp8xx` core features is the CLI interface. The design tries to stay as close as possible to the XML-RPC API.

With the CLI you can get the configuration from the device and [filter](doc/filter.md) it as you need. After transforming the config it can be written back to the device.

### CLI Installation

#### Pre Build Binaries

The recommended and easiest way is to download the pre-build binary from the [GitHub Release page](https://github.com/graugans/go-ovp8xx/releases).

⚠️ The Windows binary maybe flagged by a Virus Scanner, please also read the note from the [Go Team](https://go.dev/doc/faq#virus) ⚠️

### Go get
#### Go get

If you have a decent Go version installed

```sh
go install github.com/graugans/go-ovp8xx/cmd/ovp8xx@latest
go install github.com/graugans/go-ovp8xx/v2/cmd/ovp8xx@latest
```

## API usage
### API usage

Within in your Go project get the ovp8xx package first

```
go get github.com/graugans/go-ovp8xx
go get github.com/graugans/go-ovp8xx/v2
```

The following example will query the software Version of your OVP8xx. This assumes that either the OVP8xx is using the default IP address of `192.168.0.69` or the environment variable `OVP8XX_IP` is set. In case you want to set the IP in code please use `ovp8xx.NewClient(ovp8xx.WithHost("192.168.0.69"))` to construct the client.
Expand All @@ -50,7 +57,7 @@ package main
import (
"fmt"

"github.com/graugans/go-ovp8xx/pkg/ovp8xx"
"github.com/graugans/go-ovp8xx/v2/pkg/ovp8xx"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion cmd/ovp8xx/cmd/diagnostic.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package cmd
import (
"fmt"

"github.com/graugans/go-ovp8xx/pkg/ovp8xx"
"github.com/graugans/go-ovp8xx/v2/pkg/ovp8xx"
"github.com/spf13/cobra"
)

Expand Down
4 changes: 2 additions & 2 deletions cmd/ovp8xx/cmd/factoryReset.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Copyright © 2023 Christian Ege <[email protected]>
package cmd

import (
"github.com/graugans/go-ovp8xx/pkg/ovp8xx"
"github.com/graugans/go-ovp8xx/v2/pkg/ovp8xx"
"github.com/spf13/cobra"
)

Expand All @@ -14,7 +14,7 @@ var factoryResetCmd = &cobra.Command{
Short: "Performs a factory reset of the device",
Long: `Sometime one wants a fresh start.
The command factoryReset resets all settings to their defaults and erases any addtional data like Docker containers.`,
The command factoryReset resets all settings to their defaults and erases any additional data like Docker containers.`,
RunE: func(cmd *cobra.Command, args []string) error {
keepNetworkSettings, err := cmd.Flags().GetBool("keepnetworksettings")
if err != nil {
Expand Down
66 changes: 63 additions & 3 deletions cmd/ovp8xx/cmd/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,40 @@ Copyright © 2023 Christian Ege <[email protected]>
package cmd

import (
"github.com/graugans/go-ovp8xx/pkg/ovp8xx"
"encoding/json"
"errors"
"fmt"
"os"
"text/template"

"github.com/graugans/go-ovp8xx/v2/pkg/ovp8xx"
"github.com/spf13/cobra"
)

// toJSON converts the given object to a JSON string representation.
// If an error occurs during marshaling, an empty string is returned.
// This is taken from https://github.com/intel/tfortools
func toJSON(obj interface{}) string {
b, err := json.MarshalIndent(obj, "", "\t")
if err != nil {
return ""
}
return string(b)
}

// prefix can be used to create a list separated by s and the very first
// element is not prefixed.
func prefix(s string) func() string {
i := -1
return func() string {
i++
if i == 0 {
return ""
}
return s
}
}

func getCommand(cmd *cobra.Command, args []string) error {
var result ovp8xx.Config
var err error
Expand All @@ -23,6 +53,35 @@ func getCommand(cmd *cobra.Command, args []string) error {
if result, err = o3r.Get(helper.jsonPointers()); err != nil {
return err
}

if cmd.Flags().Changed("format") {
if helper.prettyPrint() {
return errors.New("you can't use --pretty and --format at the same time")
}

format, err := cmd.Flags().GetString("format")
if err != nil {
return fmt.Errorf("unable to get the format string from the command line: %w", err)
}
var inputData interface{}
if err = json.Unmarshal([]byte(result.String()), &inputData); err != nil {
return fmt.Errorf("unable to unmarshal the JSON data from the 'get' call: %w", err)
}
templateFunctions := template.FuncMap{
"toJSON": toJSON,
"prefix": prefix,
}
tmpl, err := template.New("output").Funcs(templateFunctions).Parse(format)
if err != nil {
return fmt.Errorf("unable to parse the template: %w", err)
}

if err := tmpl.Execute(os.Stdout, inputData); err != nil {
return fmt.Errorf("unable to execute the template: %w", err)
}
return nil
}

if err := helper.printJSONResult(result.String()); err != nil {
return err
}
Expand All @@ -40,11 +99,11 @@ Valid queries are for example:
- To query all ports including all sub elements the query "/ports" can be used.
In contrast to the concept of a JSON pointer the OVP8xx does not response with the data
the pointer is pointing to, it returns the full object hirachie with the encapsulating
the pointer is pointing to, it returns the full object hierarchy with the encapsulating
object paths.
A query of the name of the "port6" (/ports/port6/info/name) not just returns the object of that port,
it also keeps the hirachy intact:
it also keeps the hierarchy intact:
{
"ports":
Expand All @@ -66,4 +125,5 @@ func init() {
rootCmd.AddCommand(getCmd)
getCmd.Flags().StringSliceP("pointer", "p", []string{""}, "A JSON pointer to be queried")
getCmd.Flags().Bool("pretty", false, "Pretty print the JSON received from the device")
getCmd.Flags().String("format", "", "Specify an alternative format for the JSON output")
}
6 changes: 3 additions & 3 deletions cmd/ovp8xx/cmd/getSchema.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Copyright © 2023 Christian Ege <[email protected]>
package cmd

import (
"github.com/graugans/go-ovp8xx/pkg/ovp8xx"
"github.com/graugans/go-ovp8xx/v2/pkg/ovp8xx"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -34,7 +34,7 @@ var getSchemaCmd = &cobra.Command{
Use: "getSchema",
Short: "Retrieve the currently used JSON schema from the device",
Long: `The OVP8xx getSchema command accepts a list of JSON pointers.
The JSON schema provides details about multiple aspects of a paramter. It
The JSON schema provides details about multiple aspects of a parameter. It
contains information like the type of a parameter and its defaults. It also
provides information weather a parameter is readOnly or not.
Expand Down Expand Up @@ -76,7 +76,7 @@ The pointer '/device/swVersion/diagnostics' for example provides this informatio
"type": "object"
}
When no query is provided the complete schema is returend.
When no query is provided the complete schema is returned.
`,
RunE: getSchemaCommand,
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/ovp8xx/cmd/getinit.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Copyright © 2023 Christian Ege <[email protected]>
package cmd

import (
"github.com/graugans/go-ovp8xx/pkg/ovp8xx"
"github.com/graugans/go-ovp8xx/v2/pkg/ovp8xx"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -36,7 +36,7 @@ var getInitCmd = &cobra.Command{
Long: `The OVP8xx provides a way to store a configuration on the device
NOTE: This shall be used with care, because it may lead to an system which is no
longer useable when the expectation from the safed configuration is no longer met.`,
longer useable when the expectation from the saved configuration is no longer met.`,
RunE: getInitCommand,
}

Expand Down
7 changes: 6 additions & 1 deletion cmd/ovp8xx/cmd/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type helperConfig struct {

func (c *helperConfig) printJSONResult(data string) error {
var message string = data
if c.pretty {
if c.prettyPrint() {
var js json.RawMessage
if err := json.Unmarshal([]byte(data), &js); err != nil {
return errors.New("malformed json")
Expand All @@ -44,6 +44,11 @@ func (c *helperConfig) remotePort() uint16 {
return c.port
}

// prettyPrint returns a boolean value indicating whether the output should be pretty-printed.
func (c *helperConfig) prettyPrint() bool {
return c.pretty
}

func NewHelper(cmd *cobra.Command) (helperConfig, error) {
var conf = helperConfig{}
var err error
Expand Down
4 changes: 2 additions & 2 deletions cmd/ovp8xx/cmd/pcic.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package cmd
import (
"fmt"

"github.com/graugans/go-ovp8xx/pkg/pcic"
"github.com/graugans/go-ovp8xx/v2/pkg/pcic"
"github.com/spf13/cobra"
)

Expand All @@ -22,7 +22,7 @@ type PCICReceiver struct {
// It takes a pcic.Frame as a parameter.
func (r *PCICReceiver) Result(frame pcic.Frame) {
r.frame = frame
fmt.Printf("Framecount: %d\n", r.framecount)
fmt.Printf("Frame count: %d\n", r.framecount)
r.framecount++
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/ovp8xx/cmd/reboot.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Copyright © 2023 Christian Ege <[email protected]>
package cmd

import (
"github.com/graugans/go-ovp8xx/pkg/ovp8xx"
"github.com/graugans/go-ovp8xx/v2/pkg/ovp8xx"
"github.com/spf13/cobra"
)

Expand Down
5 changes: 4 additions & 1 deletion cmd/ovp8xx/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import (
"fmt"
"os"

"github.com/graugans/go-ovp8xx/pkg/ovp8xx"
"github.com/graugans/go-ovp8xx/v2/pkg/ovp8xx"
"github.com/spf13/cobra"
)

// SetVersionInfo sets the version information for the root command.
// It formats the version, commit, and date into a string and assigns it to the rootCmd.Version variable.
func SetVersionInfo(version, commit, date string) {
rootCmd.Version = fmt.Sprintf("%s (Built on %s from Git SHA %s)", version, date, commit)
}
Expand All @@ -33,4 +35,5 @@ func Execute() {

func init() {
rootCmd.PersistentFlags().String("ip", ovp8xx.GetEnv("OVP8XX_IP", "192.168.0.69"), "The IP address or hostname of the OVP8XX. If not provided the default will be taken from the environment variable OVP8XX_IP")

}
8 changes: 4 additions & 4 deletions cmd/ovp8xx/cmd/saveinit.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ Copyright © 2023 Christian Ege <[email protected]>
package cmd

import (
"github.com/graugans/go-ovp8xx/pkg/ovp8xx"
"github.com/graugans/go-ovp8xx/v2/pkg/ovp8xx"
"github.com/spf13/cobra"
)

// saveInitCmd represents the reboot command
var saveInitCmd = &cobra.Command{
Use: "saveInit",
Short: "Saves the init configuration on the device",
Long: `To store the configuration persistant on the device the command saveInit can be used.
Long: `To store the configuration persistent on the device the command saveInit can be used.
A safed configuration persists a reboot. This is best used in combination with the "set" command.
A saved configuration persists a reboot. This is best used in combination with the "set" command.
Please use this with care. The scope should be as narrow as posible, to prevent any conflicts.
Please use this with care. The scope should be as narrow as possible, to prevent any conflicts.
In case no JSON Pointer is provided the complete configuration is saved`,
RunE: func(cmd *cobra.Command, args []string) error {
pointers, err := cmd.Flags().GetStringSlice("pointer")
Expand Down
Loading

0 comments on commit 6773bc5

Please sign in to comment.