Skip to content

Commit 2021157

Browse files
authored
feat: modify component configuration during runtime (#762)
1 parent 28a10d8 commit 2021157

File tree

26 files changed

+1459
-29
lines changed

26 files changed

+1459
-29
lines changed

cmd/layotto/main.go

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"strconv"
2323
"time"
2424

25+
"mosn.io/layotto/pkg/grpc/lifecycle"
26+
2527
"mosn.io/layotto/components/oss"
2628

2729
aws_oss "mosn.io/layotto/components/oss/aws"
@@ -258,6 +260,7 @@ func NewRuntimeGrpcServer(data json.RawMessage, opts ...grpc.ServerOption) (mgrp
258260
// register your gRPC API here
259261
runtime.WithGrpcAPI(
260262
default_api.NewGrpcAPI,
263+
lifecycle.NewLifecycleAPI,
261264
s3ext.NewS3Server,
262265
),
263266
// Hello

cmd/layotto_multiple_api/main.go

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"strconv"
2323
"time"
2424

25+
"mosn.io/layotto/pkg/grpc/lifecycle"
26+
2527
"mosn.io/layotto/components/oss"
2628

2729
aws_oss "mosn.io/layotto/components/oss/aws"
@@ -262,8 +264,11 @@ func NewRuntimeGrpcServer(data json.RawMessage, opts ...grpc.ServerOption) (mgrp
262264
runtime.WithGrpcAPI(
263265
// default GrpcAPI
264266
default_api.NewGrpcAPI,
267+
lifecycle.NewLifecycleAPI,
268+
265269
// a demo to show how to register your own gRPC API
266270
helloworld_api.NewHelloWorldAPI,
271+
267272
// support Dapr API
268273
// Currently it only support Dapr's InvokeService,secret API,state API and InvokeBinding API.
269274
// Note: this feature is still in Alpha state and we don't recommend that you use it in your production environment.

cmd/layotto_without_xds/main.go

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ import (
2222
"strconv"
2323
"time"
2424

25+
s3ext "mosn.io/layotto/pkg/grpc/extension/s3"
26+
"mosn.io/layotto/pkg/grpc/lifecycle"
27+
2528
"mosn.io/layotto/components/oss"
2629

2730
aws_oss "mosn.io/layotto/components/oss/aws"
@@ -241,6 +244,8 @@ func NewRuntimeGrpcServer(data json.RawMessage, opts ...grpc.ServerOption) (mgrp
241244
// register your gRPC API here
242245
runtime.WithGrpcAPI(
243246
default_api.NewGrpcAPI,
247+
lifecycle.NewLifecycleAPI,
248+
s3ext.NewS3Server,
244249
),
245250
// Hello
246251
runtime.WithHelloFactory(

components/hello/helloworld/helloworld.go

+13-3
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,22 @@ package helloworld
1818

1919
import (
2020
"context"
21+
"sync/atomic"
2122

2223
"mosn.io/layotto/components/hello"
2324
)
2425

2526
type HelloWorld struct {
26-
Say string
27+
Say atomic.Value
28+
}
29+
30+
func (hw *HelloWorld) ApplyConfig(ctx context.Context, metadata map[string]string) (err error) {
31+
greetings, ok := metadata["hello"]
32+
if !ok {
33+
return nil
34+
}
35+
hw.Say.Store(greetings)
36+
return nil
2737
}
2838

2939
var _ hello.HelloService = &HelloWorld{}
@@ -33,12 +43,12 @@ func NewHelloWorld() hello.HelloService {
3343
}
3444

3545
func (hw *HelloWorld) Init(config *hello.HelloConfig) error {
36-
hw.Say = config.HelloString
46+
hw.Say.Store(config.HelloString)
3747
return nil
3848
}
3949

4050
func (hw *HelloWorld) Hello(ctx context.Context, req *hello.HelloRequest) (*hello.HelloReponse, error) {
41-
greetings := hw.Say
51+
greetings, _ := hw.Say.Load().(string)
4252
if req.Name != "" {
4353
greetings = greetings + ", " + req.Name
4454
}

components/hello/helloworld/helloworld_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import (
2020
"context"
2121
"testing"
2222

23+
"mosn.io/layotto/components/pkg/common"
24+
2325
"mosn.io/layotto/components/hello"
2426
)
2527

@@ -37,4 +39,24 @@ func TestHelloWorld(t *testing.T) {
3739
if resp.HelloString != "Hi, Layotto" {
3840
t.Fatalf("hello output failed")
3941
}
42+
43+
// ApplyConfig, but nil
44+
dc := hs.(common.DynamicComponent)
45+
err := dc.ApplyConfig(context.Background(), nil)
46+
if err != nil {
47+
t.Fatalf("hello ApplyConfig failed")
48+
}
49+
if resp.HelloString != "Hi, Layotto" {
50+
t.Fatalf("hello output failed")
51+
}
52+
53+
// Apply new config
54+
err = dc.ApplyConfig(context.Background(), map[string]string{"hello": "Bye"})
55+
if err != nil {
56+
t.Fatalf("hello ApplyConfig failed")
57+
}
58+
resp, _ = hs.Hello(context.Background(), req)
59+
if resp.HelloString != "Bye, Layotto" {
60+
t.Fatalf("hello output failed")
61+
}
4062
}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2021 Layotto Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package common
15+
16+
import "context"
17+
18+
type DynamicComponent interface {
19+
ApplyConfig(ctx context.Context, metadata map[string]string) (err error)
20+
}

demo/lifecycle/common/client.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"google.golang.org/grpc"
8+
9+
runtimev1pb "mosn.io/layotto/spec/proto/runtime/v1"
10+
)
11+
12+
func main() {
13+
conn, err := grpc.Dial("127.0.0.1:34904", grpc.WithInsecure())
14+
if err != nil {
15+
panic(err)
16+
}
17+
// 1. invoke sayHello API
18+
client := runtimev1pb.NewRuntimeClient(conn)
19+
hello, err := client.SayHello(context.Background(), &runtimev1pb.SayHelloRequest{
20+
ServiceName: "quick_start_demo",
21+
Name: "eva",
22+
})
23+
if err != nil {
24+
panic(err)
25+
}
26+
// validate the response value
27+
if hello.Hello != "greeting, eva" {
28+
panic(fmt.Errorf("Assertion failed! Result is %v", hello.Hello))
29+
}
30+
fmt.Println(hello.Hello)
31+
32+
// 2. invoke lifecycle API to modify the `sayHello` component configuration
33+
c := runtimev1pb.NewLifecycleClient(conn)
34+
metaData := make(map[string]string)
35+
// change the configuration from "greeting" to "goodbye"
36+
metaData["hello"] = "goodbye"
37+
req := &runtimev1pb.DynamicConfiguration{ComponentConfig: &runtimev1pb.ComponentConfig{
38+
Kind: "hellos",
39+
Name: "quick_start_demo",
40+
Metadata: metaData,
41+
}}
42+
_, err = c.ApplyConfiguration(context.Background(), req)
43+
if err != nil {
44+
panic(err)
45+
}
46+
// 3. invoke sayHello API again
47+
client = runtimev1pb.NewRuntimeClient(conn)
48+
hello, err = client.SayHello(context.Background(), &runtimev1pb.SayHelloRequest{
49+
ServiceName: "quick_start_demo",
50+
Name: "eva",
51+
})
52+
if err != nil {
53+
panic(err)
54+
}
55+
// validate the response value. It should be different this time.
56+
if hello.Hello != "goodbye, eva" {
57+
panic(fmt.Errorf("Assertion failed! Result is %v", hello.Hello))
58+
}
59+
fmt.Println(hello.Hello)
60+
}

docs/_sidebar.md

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- [Use OSS API](en/start/oss/start.md)
1717
- [API plugin: register your own API](en/start/api_plugin/helloworld.md)
1818
<!--quickstart_generator-->
19+
- [Use lifecycle API](en/start/lifecycle/start)
1920
- As the data plane of istio
2021
- [Integrate with istio 1.10.6](en/start/istio/)
2122
- [Integrate with istio 1.5.x](en/start/istio/start.md)

0 commit comments

Comments
 (0)