Skip to content

Commit

Permalink
update endpoint implementation (see networkservicemesh/cmd-forwarder-…
Browse files Browse the repository at this point in the history
…vpp#429)

Signed-off-by: Laszlo Kiraly <[email protected]>
  • Loading branch information
ljkiraly committed Dec 14, 2021
1 parent 70503dc commit 953e2db
Show file tree
Hide file tree
Showing 11 changed files with 1,004 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:
- uses: actions/checkout@v2
- name: Restrict dependencies on github.com/networkservicemesh/*
env:
ALLOWED_REPOSITORIES: "sdk, api, sdk-k8s, sdk-vpp, sdk-sriov"
ALLOWED_REPOSITORIES: "sdk, api"
run: |
for i in $(grep github.com/networkservicemesh/ go.mod | grep -v '^module' | sed 's;.*\(github.com\/networkservicemesh\/[^ ]*\).*;\1;g');do
if ! [ "$(echo ${ALLOWED_REPOSITORIES} | grep ${i#github.com/networkservicemesh/})" ]; then
Expand Down
5 changes: 5 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,8 @@ issues:
exclude-use-default: false
max-issues-per-linter: 0
max-same-issues: 0
exclude-rules:
- path: main.go
linters:
- funlen
text: "Function 'main' has too many statements"
40 changes: 31 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,54 @@
# Build
#

## Build cmd binary locally
## Intro

This repo contains 'nse-remote-vlan' an NSE application for Network Service Mesh. It provides ipam and vlan configuration context for registered Network Services.

## Usage

`nse-remote-vlan` accept following environment variables:

* NSM_NAME Name of the endpoint
* NSM_CONNECT_TO An URL of registry service to connect to
* NSM_MAX_TOKEN_LIFETIME Maximum lifetime of tokens
* NSM_CIDR_PREFIX CIDR Prefix to assign IPs from
* NSM_IPV6_PREFIX Ipv6 Prefix for dual-stack
* NSM_REGISTER_SERVICE if true then registers network service on startup
* NSM_LISTEN_ON tcp:// url to be listen on. It will be used as public to register NSM
* NSM_SERVICES List of supported services

## Build

### Build cmd binary locally

You can build the locally by executing

```bash
go build ./...
```

## Build Docker container
### Build Docker container

You can build the docker container by running:

```bash
docker build .
```

# Testing
## Testing

## Testing Docker container
### Testing Docker container

Testing is run via a Docker container. To run testing run:

```bash
docker run --privileged --rm $(docker build -q --target test .)
```

# Debugging
## Debugging

### Debugging the tests

## Debugging the tests
If you wish to debug the test code itself, that can be acheived by running:

```bash
Expand All @@ -40,6 +60,7 @@ This will result in the tests running under dlv. Connecting your debugger to lo
```bash
-p 40000:40000
```

forwards port 40000 in the container to localhost:40000 where you can attach with your debugger.

```bash
Expand All @@ -48,13 +69,14 @@ forwards port 40000 in the container to localhost:40000 where you can attach wit

Runs the debug target, which is just like the test target, but starts tests with dlv listening on port 40000 inside the container.

## Debugging the cmd
### Debugging the cmd

When you run 'cmd' you will see an early line of output that tells you:

```Setting env variable DLV_LISTEN_FORWARDER to a valid dlv '--listen' value will cause the dlv debugger to execute this binary and listen as directed.```

If you follow those instructions when running the Docker container:

```bash
docker run --privileged -e DLV_LISTEN_FORWARDER=:50000 -p 50000:50000 --rm $(docker build -q --target test .)
```
Expand All @@ -65,7 +87,7 @@ dlv to listen on port 50000.
```-p 50000:50000``` tells docker to forward port 50000 in the container to port 50000 in the host. From there, you can
just connect dlv using your favorite IDE and debug cmd.

## Debugging the tests and the cmd
### Debugging the tests and the cmd

```bash
docker run --privileged -e DLV_LISTEN_FORWARDER=:50000 -p 40000:40000 -p 50000:50000 --rm $(docker build -q --target debug .)
Expand Down
16 changes: 15 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
module github.com/networkservicemesh/cmd-template
module github.com/networkservicemesh/cmd-nse-remote-vlan

go 1.16

require (
github.com/antonfisher/nested-logrus-formatter v1.3.1
github.com/edwarnicke/grpcfd v0.1.1
github.com/golang/protobuf v1.4.3
github.com/kelseyhightower/envconfig v1.4.0
github.com/networkservicemesh/api v1.0.1-0.20211110183123-3038992da61a
github.com/networkservicemesh/sdk v0.5.1-0.20211209170740-8e964705e604
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.7.0
github.com/spiffe/go-spiffe/v2 v2.0.0-alpha.4.0.20200528145730-dc11d0c74e85
github.com/stretchr/testify v1.7.0
google.golang.org/grpc v1.35.0
)
329 changes: 329 additions & 0 deletions go.sum

Large diffs are not rendered by default.

158 changes: 158 additions & 0 deletions internal/pkg/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// Copyright (c) 2021 Nordix Foundation.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package config provides methods to get configuration parameters from environment variables
package config

import (
"net/url"
"strconv"
"strings"
"time"

"github.com/kelseyhightower/envconfig"
"github.com/pkg/errors"
)

const (
vlanPrefix = "vlan:"
labelsPrefix = "labels:"
viaPrefix = "via:"
domainPrefix = "domain:"

tcpSchema = "tcp"
)

// Config holds configuration parameters from environment variables
type Config struct {
Name string `default:"vlan-server" desc:"Name of the endpoint"`
ConnectTo url.URL `default:"nsm-registry-svc:5002" desc:"url of registry service to connect to" split_words:"true"`
MaxTokenLifetime time.Duration `default:"24h" desc:"maximum lifetime of tokens" split_words:"true"`
CidrPrefix string `default:"169.254.0.0/16" desc:"CIDR Prefix to assign IPs from" split_words:"true"`
Ipv6Prefix string `default:"" desc:"Ipv6 Prefix for dual-stack" split_words:"true"`
RegisterService bool `default:"true" desc:"if true then registers network service on startup" split_words:"true"`
ListenOn url.URL `default:"tcp://:5003" desc:"tcp:// url to be listen on. It will be used as public to register NSM" split_words:"true"`

Services []ServiceConfig `default:"" desc:"list of supported services"`
}

// Process prints and processes env to config
func (c *Config) Process() error {
if err := envconfig.Usage("nsm", c); err != nil {
return errors.Wrap(err, "cannot show usage of envconfig nse")
}
if err := envconfig.Process("nsm", c); err != nil {
return errors.Wrap(err, "cannot process envconfig nse")
}
if err := validateConfig(c); err != nil {
return errors.Wrap(err, "configuration validation failed")
}
return nil
}
func validateConfig(cfg *Config) error {
if cfg.ListenOn.Scheme != tcpSchema {
return errors.New("only tcp schema is supported for this type of endpoint")
}
return nil
}

// ServiceConfig is a per-service config
type ServiceConfig struct {
Name string
Domain string
Via string
VLANTag int32
Labels map[string]string
}

// InitValues set initial values for ServiceConfig
func (s *ServiceConfig) InitValues() {
s.Domain = ""
s.VLANTag = 0
s.Via = ""
}

// UnmarshalBinary expects string(bytes) to be in format:
// Name { domain: Domain; vlan: VLANTag; labels: Labels; via: Via; }
// Labels = label_1=value_1&label_2=value_2
func (s *ServiceConfig) UnmarshalBinary(bytes []byte) (err error) {
text := string(bytes)

split := strings.Split(text, "{")
if len(split) < 2 {
return errors.Errorf("invalid format: %s", text)
}
s.Name = strings.TrimSpace(split[0])
s.InitValues()
split = strings.Split(split[1], "}")
for _, part := range strings.Split(split[0], ";") {
part = strings.TrimSpace(part)
switch {
case strings.HasPrefix(part, vlanPrefix):
s.VLANTag, err = parseInt32(trimPrefix(part, vlanPrefix))
case strings.HasPrefix(part, labelsPrefix):
s.Labels, err = parseMap(trimPrefix(part, labelsPrefix))
case strings.HasPrefix(part, viaPrefix):
s.Via = trimPrefix(part, viaPrefix)
case strings.HasPrefix(part, domainPrefix):
s.Domain = trimPrefix(part, domainPrefix)
default:
err = errors.Errorf("invalid format: %s", text)
}
if err != nil {
return err
}
}
return s.validate()
}

func trimPrefix(s, prefix string) string {
s = strings.TrimPrefix(s, prefix)
return strings.TrimSpace(s)
}

func parseInt32(s string) (int32, error) {
i, err := strconv.ParseInt(s, 0, 32)
if err != nil {
return 0, err
}
return int32(i), nil
}

func parseMap(s string) (map[string]string, error) {
m := make(map[string]string)
for _, keyValue := range strings.Split(s, "&") {
split := strings.Split(keyValue, "=")
if len(split) != 2 {
return nil, errors.Errorf("invalid key-value pair: %s", keyValue)
}
m[split[0]] = split[1]
}
return m, nil
}

func (s *ServiceConfig) validate() error {
if s.Name == "" {
return errors.New("name is empty")
}
if s.Via == "" {
return errors.New("via is empty")
}
if s.VLANTag < 0 || s.VLANTag > 4095 {
return errors.New("Invalid VLAN ID")
}
return nil
}
48 changes: 48 additions & 0 deletions internal/pkg/config/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2021 Nordix Foundation.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package config_test

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/networkservicemesh/cmd-nse-remote-vlan/internal/pkg/config"
)

func TestServiceConfig_UnmarshalBinary(t *testing.T) {
cfg := new(config.ServiceConfig)

err := cfg.UnmarshalBinary([]byte("finance-bridge { domain: service-domain.2; vlan: 100; via: gw-1 }"))
require.NoError(t, err)

require.Equal(t, &config.ServiceConfig{
Name: "finance-bridge",
Domain: "service-domain.2",
Via: "gw-1",
VLANTag: 100,
}, cfg)

err = cfg.UnmarshalBinary([]byte("finance-bridge { vlan: 200; via: service-domain.1 }"))
require.NoError(t, err)

require.Equal(t, &config.ServiceConfig{
Name: "finance-bridge",
Via: "service-domain.1",
VLANTag: 200,
}, cfg)
}
22 changes: 22 additions & 0 deletions internal/pkg/imports/gen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) 2020-2021 Doc.ai and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package imports is used for generating list of imports to optimize use of docker build cache
package imports

//go:generate bash -c "rm -rf imports*.go"
//go:generate bash -c "cd $(mktemp -d) && GO111MODULE=on go get github.com/edwarnicke/[email protected]"
//go:generate bash -c "GOOS=linux ${GOPATH}/bin/imports-gen"
Loading

0 comments on commit 953e2db

Please sign in to comment.