Skip to content

Commit

Permalink
Add label chain elements and condition
Browse files Browse the repository at this point in the history
Signed-off-by: Vladimir Popov <[email protected]>
  • Loading branch information
Vladimir Popov committed Jul 30, 2021
1 parent 253c2d5 commit 879f0d9
Show file tree
Hide file tree
Showing 10 changed files with 472 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -282,3 +282,6 @@ issues:
- path: pkg/networkservice/common/switchcase/.*_test.go
linters:
- dupl
- path: pkg/networkservice/common/label/.*_test.go
linters:
- dupl
50 changes: 50 additions & 0 deletions pkg/networkservice/common/label/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) 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 label

import (
"context"

"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/emptypb"

"github.com/networkservicemesh/api/pkg/api/networkservice"

"github.com/networkservicemesh/sdk/pkg/networkservice/core/next"
)

type labelClient struct {
label, value string
}

// NewClient returns new server marking Connections with label
func NewClient(label, value string) networkservice.NetworkServiceClient {
return &labelClient{
label: label,
value: value,
}
}

func (s *labelClient) Request(ctx context.Context, request *networkservice.NetworkServiceRequest, opts ...grpc.CallOption) (*networkservice.Connection, error) {
store(ctx, s.label, s.value)
return next.Client(ctx).Request(ctx, request, opts...)
}

func (s *labelClient) Close(ctx context.Context, conn *networkservice.Connection, opts ...grpc.CallOption) (*emptypb.Empty, error) {
store(ctx, s.label, s.value)
return next.Client(ctx).Close(ctx, conn, opts...)
}
90 changes: 90 additions & 0 deletions pkg/networkservice/common/label/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright (c) 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 label_test

import (
"context"
"testing"

"github.com/stretchr/testify/require"

"github.com/networkservicemesh/api/pkg/api/networkservice"

"github.com/networkservicemesh/sdk/pkg/networkservice/common/label"
"github.com/networkservicemesh/sdk/pkg/networkservice/common/null"
"github.com/networkservicemesh/sdk/pkg/networkservice/common/switchcase"
"github.com/networkservicemesh/sdk/pkg/networkservice/common/updatepath"
"github.com/networkservicemesh/sdk/pkg/networkservice/core/adapters"
"github.com/networkservicemesh/sdk/pkg/networkservice/core/next"
"github.com/networkservicemesh/sdk/pkg/networkservice/utils/checks/checkcontext"
"github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata"
)

func TestLabelClient(t *testing.T) {
const labelKey = "key"
const labelValue = "value"

c := next.NewNetworkServiceClient(
updatepath.NewClient("name"),
metadata.NewClient(),
label.NewClient(labelKey, labelValue),
switchcase.NewClient(
&switchcase.ClientCase{
Condition: label.Condition(labelKey, "invalid"),
Client: checkcontext.NewClient(t, func(t *testing.T, _ context.Context) {
require.Fail(t, "invalid label selected for client branch")
}),
},
&switchcase.ClientCase{
Condition: label.Condition(labelKey, labelValue),
Client: null.NewClient(),
},
&switchcase.ClientCase{
Condition: switchcase.Default,
Client: checkcontext.NewClient(t, func(t *testing.T, _ context.Context) {
require.Fail(t, "no label selected for client branch")
}),
},
),
adapters.NewServerToClient(
switchcase.NewServer(
&switchcase.ServerCase{
Condition: label.Condition(labelKey, "invalid"),
Server: checkcontext.NewServer(t, func(t *testing.T, _ context.Context) {
require.Fail(t, "invalid label selected for server branch")
}),
},
&switchcase.ServerCase{
Condition: label.Condition(labelKey, labelValue),
Server: null.NewServer(),
},
&switchcase.ServerCase{
Condition: switchcase.Default,
Server: checkcontext.NewServer(t, func(t *testing.T, _ context.Context) {
require.Fail(t, "no label selected for server branch")
}),
},
),
),
)

_, err := c.Request(context.Background(), new(networkservice.NetworkServiceRequest))
require.NoError(t, err)

_, err = c.Close(context.Background(), new(networkservice.Connection))
require.NoError(t, err)
}
32 changes: 32 additions & 0 deletions pkg/networkservice/common/label/condition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) 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 label

import (
"context"

"github.com/networkservicemesh/api/pkg/api/networkservice"

"github.com/networkservicemesh/sdk/pkg/networkservice/common/switchcase"
)

// Condition returns condition validating if Connection is marked with label
func Condition(label, value string) switchcase.Condition {
return func(ctx context.Context, _ *networkservice.Connection) bool {
return load(ctx, label) == value
}
}
19 changes: 19 additions & 0 deletions pkg/networkservice/common/label/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) 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 label provides chain elements for marking Connection with label and switchcase.Condition for selecting branch
// by label
package label
25 changes: 25 additions & 0 deletions pkg/networkservice/common/label/gen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) 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 label

import (
"sync"
)

//go:generate go-syncmap -output string_map.gen.go -type stringMap<string,string>

type stringMap sync.Map
41 changes: 41 additions & 0 deletions pkg/networkservice/common/label/metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) 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 label

import (
"context"

"github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata"
)

type keyType struct{}

func store(ctx context.Context, label, value string) {
v, _ := metadata.Map(ctx, false).LoadOrStore(keyType{}, new(stringMap))
labels := v.(*stringMap)

labels.Store(label, value)
}

func load(ctx context.Context, label string) string {
v, _ := metadata.Map(ctx, false).LoadOrStore(keyType{}, new(stringMap))
labels := v.(*stringMap)

value, _ := labels.Load(label)

return value
}
49 changes: 49 additions & 0 deletions pkg/networkservice/common/label/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) 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 label

import (
"context"

"google.golang.org/protobuf/types/known/emptypb"

"github.com/networkservicemesh/api/pkg/api/networkservice"

"github.com/networkservicemesh/sdk/pkg/networkservice/core/next"
)

type labelServer struct {
label, value string
}

// NewServer returns new server marking Connections with label
func NewServer(label, value string) networkservice.NetworkServiceServer {
return &labelServer{
label: label,
value: value,
}
}

func (s *labelServer) Request(ctx context.Context, request *networkservice.NetworkServiceRequest) (*networkservice.Connection, error) {
store(ctx, s.label, s.value)
return next.Server(ctx).Request(ctx, request)
}

func (s *labelServer) Close(ctx context.Context, conn *networkservice.Connection) (*emptypb.Empty, error) {
store(ctx, s.label, s.value)
return next.Server(ctx).Close(ctx, conn)
}
Loading

0 comments on commit 879f0d9

Please sign in to comment.