├── .github └── dco.yml ├── .gitignore ├── .travis.yml ├── .yamllint.yml ├── CHANGELOG.md ├── CODINGSTYLE.md ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md ├── agent ├── agent.go ├── agent_test.go ├── doc.go ├── options.go ├── options_test.go └── plugin_lookup.go ├── config ├── config_test.go ├── configfileplugin.conf ├── doc.go ├── parser.go ├── parser_test.go └── plugin_config.go ├── datasync ├── aggregator.go ├── datasync_api.go ├── doc.go ├── events.go ├── grpcsync │ ├── doc.go │ ├── grpc_watcher.go │ ├── msgservice.go │ ├── options.go │ └── plugin_impl_grpsync.go ├── kvdbsync │ ├── change_event.go │ ├── doc.go │ ├── iterator.go │ ├── local │ │ ├── doc.go │ │ ├── global_api.go │ │ ├── local_bytes_txn.go │ │ └── local_proto_txn.go │ ├── options.go │ ├── plugin_impl_dbsync.go │ └── watch_impl.go ├── msgsync │ ├── doc.go │ ├── options.go │ └── plugin_impl_msgsync.go ├── options.go ├── restsync │ ├── doc.go │ ├── http_handlers.go │ └── rest_watcher.go ├── resync │ ├── doc.go │ ├── options.go │ ├── plugin_api_resync.go │ ├── plugin_impl_resync.go │ └── registration.go └── syncbase │ ├── change.go │ ├── doc.go │ ├── done.go │ ├── events.go │ ├── kv_iterator.go │ ├── msg │ ├── change_event.go │ ├── datamsg.pb.go │ ├── datamsg.proto │ ├── datamsg_grpc.pb.go │ └── doc.go │ ├── prev_revisions.go │ ├── transport_adapter.go │ ├── watcher.go │ └── watcher_test.go ├── db ├── cryptodata │ ├── client.go │ ├── decrypter.go │ ├── doc.go │ ├── options.go │ ├── plugin.go │ ├── wrapper.go │ ├── wrapper_bytes.go │ └── wrapper_proto.go ├── doc.go ├── keyval │ ├── bolt │ │ ├── bolt.conf │ │ ├── bolt.go │ │ ├── broker.go │ │ ├── integration_test.go │ │ ├── iterator.go │ │ ├── options.go │ │ ├── plugin.go │ │ ├── updates.go │ │ └── watch.go │ ├── bytes_broker_api.go │ ├── bytes_watcher_api.go │ ├── consul │ │ ├── consul.conf │ │ ├── consul.go │ │ ├── integration_test.go │ │ ├── options.go │ │ ├── plugin.go │ │ └── txn.go │ ├── doc.go │ ├── etcd │ │ ├── bytes_broker_impl.go │ │ ├── bytes_txn_impl.go │ │ ├── bytes_watcher_impl.go │ │ ├── config.go │ │ ├── doc.go │ │ ├── etcd.conf │ │ ├── etcd_integration_test.go │ │ ├── etcd_suite_test.go │ │ ├── iterator.go │ │ ├── mocks │ │ │ ├── doc.go │ │ │ └── embeded_etcd.go │ │ ├── options.go │ │ └── plugin_impl_etcd.go │ ├── filedb │ │ ├── broker.go │ │ ├── client.go │ │ ├── client_test.go │ │ ├── database │ │ │ ├── database.go │ │ │ └── database_test.go │ │ ├── decoder │ │ │ ├── decoder_api.go │ │ │ ├── decoder_json.go │ │ │ ├── decoder_test.go │ │ │ ├── decoder_yaml.go │ │ │ └── mock_decoder.go │ │ ├── export_test.go │ │ ├── filesystem.conf │ │ ├── filesystem │ │ │ ├── filesystem.go │ │ │ └── mock_filesystem.go │ │ ├── iterator.go │ │ ├── options.go │ │ ├── plugin.go │ │ └── watch.go │ ├── kvproto │ │ ├── doc.go │ │ ├── proto_broker_impl.go │ │ ├── proto_txn_impl.go │ │ └── proto_watcher_impl.go │ ├── plugin_api_keyval.go │ ├── proto_broker_api.go │ ├── proto_serializer.go │ ├── proto_watcher_api.go │ └── redis │ │ ├── bytes_broker_impl.go │ │ ├── bytes_suite_test.go │ │ ├── bytes_txn_impl.go │ │ ├── bytes_watcher_impl.go │ │ ├── config.go │ │ ├── doc.go │ │ ├── options.go │ │ └── plugin_impl_redis.go └── sql │ ├── README.md │ ├── cassandra │ ├── README.md │ ├── cassa_broker_impl.go │ ├── cassa_data_test.go │ ├── cassa_del_test.go │ ├── cassa_list_values_test.go │ ├── cassa_put_test.go │ ├── cassa_txn_impl.go │ ├── cassa_watcher_impl.go │ ├── cassandra.conf │ ├── config.go │ ├── doc.go │ ├── options.go │ ├── plugin_impl_cassa.go │ └── query.go │ ├── doc.go │ ├── plugin_api_sql.go │ ├── slice_utils.go │ ├── sql_broker_api.go │ ├── sql_expression.go │ ├── sql_struct_metadata.go │ └── sql_watcher_api.go ├── doc.go ├── docker └── dev_cn_infra │ ├── Dockerfile │ ├── build-agent.sh │ ├── build.sh │ ├── etcd.conf │ ├── kafka.conf │ ├── shrink.sh │ └── supervisord.conf ├── docs ├── README.md └── imgs │ ├── high_level_arch_cninfra.png │ └── http.png ├── examples ├── .gitignore ├── README.md ├── bolt-plugin │ ├── README.md │ ├── bolt.conf │ ├── doc.go │ └── main.go ├── cassandra-lib │ ├── Readme.md │ ├── client-config.yaml │ ├── doc.go │ └── main.go ├── configs-plugin │ ├── Readme.md │ ├── doc.go │ ├── example.conf │ └── main.go ├── consul-lib │ └── main.go ├── cryptodata-lib │ ├── key-pub.pem │ ├── key.pem │ └── main.go ├── cryptodata-plugin │ ├── cryptodata.conf │ ├── doc.go │ ├── etcd.conf │ └── main.go ├── cryptodata-proto-plugin │ ├── cryptodata.conf │ ├── doc.go │ ├── etcd.conf │ ├── ipsec │ │ ├── ipsec.pb.go │ │ ├── ipsec.proto │ │ └── keys.go │ └── main.go ├── datasync-plugin │ ├── Readme.md │ ├── doc.go │ ├── etcd.conf │ └── main.go ├── doc.go ├── etcd-lib │ ├── Makefile │ ├── Readme.md │ ├── doc.go │ ├── editor │ │ ├── doc.go │ │ └── editor.go │ ├── election │ │ └── election.go │ ├── etcd.conf │ ├── model │ │ └── phonebook │ │ │ ├── config.go │ │ │ ├── phonebook.pb.go │ │ │ └── phonebook.proto │ ├── view │ │ ├── doc.go │ │ └── view.go │ └── watcher │ │ ├── doc.go │ │ └── watcher.go ├── flags-lib │ ├── Readme.md │ ├── doc.go │ └── main.go ├── grpc-plugin │ ├── README.md │ ├── doc.go │ ├── grpc-client │ │ └── main.go │ ├── grpc-server │ │ ├── doc.go │ │ ├── grpc.conf │ │ └── main.go │ └── insecure │ │ └── insecure.go ├── kafka-lib │ ├── Makefile │ ├── asyncproducer │ │ ├── README.md │ │ ├── asyncproducer.go │ │ └── doc.go │ ├── consumer │ │ ├── README.md │ │ ├── consumer.go │ │ └── doc.go │ ├── doc.go │ ├── mux │ │ ├── README.md │ │ ├── config │ │ ├── doc.go │ │ └── main.go │ ├── syncproducer │ │ ├── README.md │ │ ├── doc.go │ │ └── syncproducer.go │ └── utils │ │ ├── doc.go │ │ └── prompter.go ├── kafka-plugin │ ├── doc.go │ ├── hash-partitioner │ │ ├── README.md │ │ ├── doc.go │ │ ├── kafka.conf │ │ └── main.go │ ├── manual-partitioner │ │ ├── README.md │ │ ├── doc.go │ │ ├── kafka.conf │ │ ├── main.go │ │ └── server.properties │ └── post-init-consumer │ │ ├── README.md │ │ ├── doc.go │ │ ├── kafka.conf │ │ └── main.go ├── logs-lib │ ├── Makefile │ ├── basic │ │ ├── REDME.md │ │ ├── basic.go │ │ └── doc.go │ ├── doc.go │ └── http │ │ ├── README.md │ │ ├── doc.go │ │ └── server.go ├── logs-plugin │ ├── README.md │ ├── doc.go │ ├── logs.conf │ └── main.go ├── model │ ├── README.md │ ├── doc.go │ ├── example.pb.go │ └── example.proto ├── process-manager-plugin │ ├── README.md │ ├── advanced-scenario │ │ └── main.go │ ├── basic-scenario │ │ └── main.go │ ├── templates │ │ └── main.go │ └── test-process │ │ └── test-process.go ├── prometheus-plugin │ ├── README.md │ └── main.go ├── redis-lib │ ├── Makefile │ ├── Readme.md │ ├── airport │ │ ├── airport.go │ │ ├── doc.go │ │ └── model │ │ │ ├── doc.go │ │ │ ├── flight.pb.go │ │ │ └── flight.proto │ ├── cluster-client.yaml │ ├── diagram.png │ ├── doc.go │ ├── node-client.yaml │ ├── sentinel-client.yaml │ └── simple │ │ ├── doc.go │ │ └── simple.go ├── redis-plugin │ ├── README.md │ ├── doc.go │ └── main.go ├── simple-agent │ ├── README.md │ ├── agent.go │ └── doc.go ├── statuscheck-plugin │ ├── README.md │ ├── doc.go │ ├── etcd.conf │ └── main.go ├── supervisor-plugin │ ├── example.log │ └── main.go └── tutorials │ ├── 01_hello-world │ └── main.go │ ├── 02_plugin-deps │ ├── helloworld.conf │ └── main.go │ ├── 03_rest-handler │ └── main.go │ ├── 04_kv-store │ ├── etcd.conf │ ├── main.go │ └── model │ │ ├── model.pb.go │ │ └── model.proto │ ├── 06_plugin_lookup │ ├── main.go │ ├── plugin1.go │ └── plugin2.go │ └── README.md ├── exec ├── processmanager │ ├── options.go │ ├── plugin.go │ ├── plugin_test.go │ ├── pm.conf │ ├── process.go │ ├── process_impl.go │ ├── process_options.go │ ├── status │ │ ├── status.go │ │ ├── status_test.go │ │ └── test-state │ └── template │ │ ├── model │ │ └── process │ │ │ ├── process.pb.go │ │ │ └── process.proto │ │ └── template.go └── supervisor │ ├── config.go │ ├── hooks.go │ ├── logger.go │ ├── options.go │ ├── plugin.go │ └── supervisor.conf ├── go.mod ├── go.sum ├── health ├── doc.go ├── probe │ ├── doc.go │ ├── options.go │ ├── plugin_impl_probe.go │ └── prometheus_probe.go └── statuscheck │ ├── doc.go │ ├── model │ └── status │ │ ├── keys_agent_status.go │ │ ├── status.pb.go │ │ └── status.proto │ ├── options.go │ ├── plugin_api_statuscheck.go │ ├── plugin_impl_statuscheck.go │ └── pluginstatusmap │ ├── doc.go │ └── plugin_status_map.go ├── idxmap ├── api.go ├── chan.go ├── doc.go └── mem │ ├── cache_helper.go │ ├── doc.go │ ├── inmemory_name_mapping.go │ └── inmemory_name_mapping_test.go ├── infra └── infra.go ├── logging ├── doc.go ├── log_api.go ├── logmanager │ ├── config.go │ ├── doc.go │ ├── hooks.go │ ├── logs.conf │ ├── options.go │ └── plugin_impl_log_manager.go ├── logrus │ ├── caller.go │ ├── doc.go │ ├── entry.go │ ├── entry_test.go │ ├── export.go │ ├── formatter.go │ ├── logger.go │ ├── logger_test.go │ ├── redact.go │ ├── redact_test.go │ ├── registry.go │ └── registry_test.go ├── measure │ ├── model │ │ └── apitrace │ │ │ ├── apitrace.pb.go │ │ │ └── apitrace.proto │ └── tracer.go └── parent.go ├── messaging ├── chan.go ├── doc.go ├── kafka │ ├── client │ │ ├── asyncproducer.go │ │ ├── asyncproducer_test.go │ │ ├── config.go │ │ ├── consumer.go │ │ ├── consumer_test.go │ │ ├── doc.go │ │ ├── messages.go │ │ ├── mocks.go │ │ ├── syncproducer.go │ │ └── syncproducer_test.go │ ├── doc.go │ ├── kafka.conf │ ├── mux │ │ ├── bytes_connection.go │ │ ├── chan.go │ │ ├── config.go │ │ ├── doc.go │ │ ├── mock.go │ │ ├── multiplexer.go │ │ ├── multiplexer_test.go │ │ └── proto_connection.go │ ├── options.go │ └── plugin_impl_kafka.go └── messaging_api.go ├── rpc ├── doc.go ├── grpc │ ├── auth.go │ ├── config.go │ ├── doc.go │ ├── grpc.conf │ ├── listen_and_serve.go │ ├── options.go │ ├── plugin_api_grpc.go │ ├── plugin_impl_grpc.go │ └── ratelimit.go ├── prometheus │ ├── doc.go │ ├── options.go │ ├── plugin_api_prometheus.go │ └── plugin_impl_prometheus.go └── rest │ ├── README.md │ ├── auth.go │ ├── config.go │ ├── doc.go │ ├── http.conf │ ├── listen_and_serve.go │ ├── middleware.go │ ├── mock │ ├── doc.go │ └── httpmock.go │ ├── options.go │ ├── plugin_api_rest.go │ ├── plugin_impl_rest.go │ └── security │ ├── auth_store.go │ ├── model │ └── access-security │ │ ├── accesssecurity.pb.go │ │ └── accesssecurity.proto │ ├── password-hasher │ ├── README.md │ └── main.go │ └── rest_security.go ├── scripts ├── check_links.sh ├── gofmt.sh ├── install-consul.sh ├── static_analysis.sh └── test_examples │ ├── docker_start_stop_functions.sh │ ├── plugin_reconnect.sh │ └── test_examples.sh ├── servicelabel ├── doc.go ├── options.go ├── plugin_api_servicelabel.go └── plugin_impl_servicelabel.go └── utils ├── addrs ├── addr_test.go ├── doc.go ├── ip.go └── mac.go ├── clienttls ├── doc.go └── tlsutil.go ├── doc.go ├── once ├── return_error.go └── return_error_test.go ├── ratelimit └── limiters.go ├── redact ├── enable_strict.go ├── enable_toggle.go ├── proto.go ├── proto_test.go ├── redact.go ├── redact_test.go ├── string.go ├── string_test.go └── testdata │ ├── model.pb.go │ ├── model.proto │ └── redactor.go ├── runtimeutils ├── doc.go └── runtimeutils.go ├── safeclose ├── doc.go └── safeclose.go └── structs ├── doc.go └── structs_reflection.go /.github/dco.yml: -------------------------------------------------------------------------------- 1 | --- 2 | require: 3 | members: false 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.so 3 | *.test 4 | *.out 5 | 6 | # goland 7 | .idea/ 8 | 9 | # eclipse 10 | *.classpath 11 | *.project 12 | *.settings 13 | 14 | db/keyval/etcd/examples/phonebook/editor/editor 15 | db/keyval/etcd/examples/phonebook/view/view 16 | db/keyval/etcd/examples/phonebook/watcher/watcher 17 | db/sql/cassandra/examples/simple/simple 18 | logging/logrus/examples/basic/basic 19 | logging/logrus/examples/custom/custom 20 | logging/logrus/examples/http/http 21 | messaging/kafka/examples/asyncproducer/asyncproducer 22 | messaging/kafka/examples/consumer/consumer 23 | messaging/kafka/examples/mux/mux 24 | messaging/kafka/examples/syncproducer/syncproducer 25 | rpc/rest/security/password-hasher/password-hasher 26 | 27 | # vendor 28 | /vendor/ 29 | 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dist: trusty 3 | sudo: required 4 | 5 | language: go 6 | go: 7 | - 1.x 8 | 9 | go_import_path: go.ligato.io/cn-infra/v2 10 | 11 | addons: 12 | apt: 13 | packages: 14 | - npm 15 | 16 | git: 17 | depth: 1 18 | 19 | before_install: 20 | - make get-linkcheck 21 | - make get-yamllint 22 | 23 | install: 24 | - make dep-check 25 | - make check-links || true 26 | - make yamllint 27 | 28 | before_script: 29 | - make get-linter 30 | - make get-testtools 31 | - go get -v github.com/mattn/goveralls 32 | 33 | script: 34 | - make lint 35 | - make build 36 | - make test-cover 37 | 38 | after_success: 39 | - goveralls -coverprofile=/tmp/coverage.out -service=travis-ci 40 | 41 | notifications: 42 | slack: 43 | rooms: 44 | - ligato:QNOK2VgHH6k40T8nQxmSgRmo 45 | on_success: change 46 | on_failure: always 47 | -------------------------------------------------------------------------------- /.yamllint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | 4 | rules: 5 | # 80 chars should be enough, but don't fail if a line is longer 6 | line-length: 7 | max: 80 8 | level: warning 9 | -------------------------------------------------------------------------------- /CODINGSTYLE.md: -------------------------------------------------------------------------------- 1 | # Coding style 2 | 3 | - Use `gofmt` to format all source files. 4 | - Address any issues that were discovered by the `golint` & `govet` tool. 5 | - Follow recommendations in [effective go][1] and [Go Code Review Comments][2]. 6 | 7 | [1]: https://golang.org/doc/effective_go.html 8 | [2]: https://github.com/golang/go/wiki/CodeReviewComments -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions to CN-Infra are welcome. We use the standard pull request 4 | model. You can either pick an open issue and assign it to yourself or open 5 | a new issue and discuss your feature. 6 | 7 | In any case, before submitting your pull request please check the 8 | [Coding style](CODINGSTYLE.md) and cover the newly added code with tests 9 | and documentation. -------------------------------------------------------------------------------- /agent/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /* 16 | Package agent provides the life-cycle management agent for plugins. It is 17 | intended to be used as a base point of an application used in main package. 18 | 19 | Here is a common example usage: 20 | 21 | func main() { 22 | plugin := myplugin.NewPlugin() 23 | 24 | a := agent.NewAgent( 25 | agent.Plugins(plugin), 26 | ) 27 | if err := a.Run(); err != nil { 28 | log.Fatal(err) 29 | } 30 | } 31 | 32 | Options 33 | 34 | There are various options available to customize agent: 35 | 36 | Version(ver, date, id) - sets version of the program 37 | QuitOnClose(chan) - sets signal used to quit the running agent when closed 38 | QuitSignals(signals) - sets signals used to quit the running agent (default: SIGINT, SIGTERM) 39 | StartTimeout(dur) - sets start timeout (default: 15s) 40 | StopTimeout(dur) - sets stop timeout (default: 5s) 41 | 42 | There are two options for adding plugins to the agent: 43 | 44 | Plugins(...) - adds just single plugins without lookup 45 | AllPlugins(...) - adds plugin along with all of its plugin deps 46 | 47 | */ 48 | package agent 49 | -------------------------------------------------------------------------------- /config/configfileplugin.conf: -------------------------------------------------------------------------------- 1 | foo = bar -------------------------------------------------------------------------------- /config/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package config contains helper functions for parsing of configuration 16 | // files. 17 | package config 18 | -------------------------------------------------------------------------------- /config/parser_test.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | func TestParseConfigFromYamlBytes(t *testing.T) { 11 | RegisterTestingT(t) 12 | 13 | type Duration string 14 | 15 | type BigConfig struct { 16 | Simple string 17 | Str string `json:"name"` 18 | Integer16 int16 19 | Timeout time.Duration 20 | NotTimeout Duration 21 | } 22 | 23 | var testData = map[string]struct { 24 | input string 25 | want BigConfig 26 | fail bool 27 | }{ 28 | "simple": {"simple: test", BigConfig{Simple: "test"}, false}, 29 | "bad simple": {"simple test", BigConfig{}, true}, 30 | "json tag": {"name: BigName", BigConfig{Str: "BigName"}, false}, 31 | "int16": {"integer16: 25", BigConfig{Integer16: 25}, false}, 32 | "duration number": {"timeout: 5000000000", BigConfig{Timeout: 5 * time.Second}, false}, 33 | "duration string": {"timeout: 5s", BigConfig{Timeout: 5 * time.Second}, false}, 34 | "bad duration": {"timeout: s5s", BigConfig{}, true}, 35 | "not duration": {"nottimeout: 30SecToAgent", BigConfig{NotTimeout: "30SecToAgent"}, false}, 36 | } 37 | 38 | for name, tt := range testData { 39 | t.Run(name, func(t *testing.T) { 40 | RegisterTestingT(t) 41 | 42 | out := BigConfig{} 43 | err := parseConfigFromYamlBytes([]byte(tt.input), &out) 44 | 45 | if tt.fail { 46 | Expect(err).To(HaveOccurred()) 47 | return 48 | } 49 | 50 | Expect(err).ToNot(HaveOccurred()) 51 | Expect(out).To(Equal(tt.want)) 52 | }) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /datasync/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package datasync defines the datasync API, which abstracts the data 16 | // transport between app plugins and backend data sources. Data sources 17 | // may be data stores, or clients connected to a message bus, or remote clients 18 | // connected to CN-Infra app. Transport may be, for example, HTTP or gRPC. 19 | // 20 | // These events are processed asynchronously. 21 | // With each event, the app plugin also receives a separate callback which is used 22 | // to propagate any errors encountered during the event processing back 23 | // to the user of the datasync package. Successfully finalized event processing 24 | // is signaled by sending nil value (meaning no error) via the associated 25 | // callback. 26 | // 27 | // See the examples under the dedicated examples package. 28 | package datasync 29 | -------------------------------------------------------------------------------- /datasync/grpcsync/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package grpcsync implements (in ALPHA VERSION) the gRPC client 16 | // and server that satisfies the datasync API (see the definition of the 17 | // service in ../syncbase/msg package). This implementation is special 18 | // (comparing to dbsync or msgsync) because it does not use any intermediate 19 | // persistence between the client and the server. Therefore the client does 20 | // remote calls to each individual server/agent instance (and needs to know 21 | // its IP address & port). 22 | package grpcsync 23 | -------------------------------------------------------------------------------- /datasync/grpcsync/options.go: -------------------------------------------------------------------------------- 1 | package grpcsync 2 | 3 | import ( 4 | "go.ligato.io/cn-infra/v2/rpc/grpc" 5 | ) 6 | 7 | // DefaultPlugin is a default instance of Plugin. 8 | var DefaultPlugin = *NewPlugin() 9 | 10 | // NewPlugin creates a new Plugin with the provided Options. 11 | func NewPlugin(opts ...Option) *Plugin { 12 | p := &Plugin{} 13 | 14 | p.PluginName = "grpcsync" 15 | p.GRPC = &grpc.DefaultPlugin 16 | 17 | for _, o := range opts { 18 | o(p) 19 | } 20 | 21 | return p 22 | } 23 | 24 | // Option is a function that can be used in NewPlugin to customize Plugin. 25 | type Option func(*Plugin) 26 | 27 | // UseDeps returns Option that can inject custom dependencies. 28 | func UseDeps(cb func(*Deps)) Option { 29 | return func(p *Plugin) { 30 | cb(&p.Deps) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /datasync/grpcsync/plugin_impl_grpsync.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package grpcsync 16 | 17 | import ( 18 | "go.ligato.io/cn-infra/v2/datasync" 19 | "go.ligato.io/cn-infra/v2/datasync/syncbase" 20 | "go.ligato.io/cn-infra/v2/infra" 21 | "go.ligato.io/cn-infra/v2/rpc/grpc" 22 | ) 23 | 24 | // Plugin grpcsync implements Plugin interface, therefore can be loaded with other plugins. 25 | type Plugin struct { 26 | Deps 27 | 28 | Adapter datasync.KeyValProtoWatcher 29 | } 30 | 31 | // Deps represent Plugin dependencies. 32 | type Deps struct { 33 | infra.PluginName 34 | GRPC grpc.Server 35 | } 36 | 37 | // Init registers new gRPC service and instantiates plugin.Adapter. 38 | func (p *Plugin) Init() error { 39 | p.Adapter = &syncbase.Adapter{ 40 | Watcher: NewAdapter(p.GRPC.GetServer()), 41 | } 42 | return nil 43 | } 44 | 45 | // Close does nothing. 46 | func (p *Plugin) Close() error { 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /datasync/kvdbsync/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package kvdbsync defines a key-value data store client API for unified 16 | // access among key-value datastore servers. The datasync API contains the 17 | // Data Broker & KeyValProtoWatcher APIs, which are only facades in front of 18 | // different key-value or SQL stores. 19 | // 20 | // A key-value store is used as a transport channel between a remote client 21 | // and an agent (server). It stores data/configuration for multiple agents 22 | // (servers). Therefore, a client only needs to know the address of the 23 | // key-value store but does not need to know the addresses of individual agents. 24 | // The client can write data/configuration independently of the agent's 25 | // (server's) lifecycle. 26 | // 27 | // The Data KeyValProtoWatcher is used during regular operation to efficiently 28 | // propagate data/configuration changes from the key-value store to the 29 | // agents (servers). Upon receiving a data change event, the watcher makes 30 | // an incremental update to its data. When data resynchronization (RESYNC) is 31 | // triggered, then the Data Broker is used to read all particular keys & 32 | // values from the key-value store. Reading all particular keys & values is 33 | // more reliable but less efficient data synchronization method. 34 | package kvdbsync 35 | -------------------------------------------------------------------------------- /datasync/kvdbsync/iterator.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package kvdbsync 16 | 17 | import ( 18 | "go.ligato.io/cn-infra/v2/datasync" 19 | "go.ligato.io/cn-infra/v2/db/keyval" 20 | ) 21 | 22 | // Iterator adapts the db_proto.KeyValIterator to the datasync.KeyValIterator. 23 | type Iterator struct { 24 | delegate keyval.ProtoKeyValIterator 25 | } 26 | 27 | // NewIterator creates a new instance of Iterator. 28 | func NewIterator(delegate keyval.ProtoKeyValIterator) *Iterator { 29 | return &Iterator{delegate: delegate} 30 | } 31 | 32 | // GetNext only delegates the call to internal iterator. 33 | func (it *Iterator) GetNext() (kv datasync.KeyVal, stop bool) { 34 | kv, stop = it.delegate.GetNext() 35 | if stop { 36 | return nil, stop 37 | } 38 | return kv, stop 39 | } 40 | -------------------------------------------------------------------------------- /datasync/kvdbsync/local/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package local implements DB Transactions for the local "in memory" 16 | // transport. This implementation uses a collection of transaction items that 17 | // are propagated to registered GO channels. 18 | package local 19 | -------------------------------------------------------------------------------- /datasync/kvdbsync/local/global_api.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package local 16 | 17 | import ( 18 | "go.ligato.io/cn-infra/v2/datasync/syncbase" 19 | ) 20 | 21 | // DefaultRegistry is a default registry. 22 | var DefaultRegistry = syncbase.NewRegistry() 23 | 24 | // Get returns the global singleton instance. 25 | func Get() *syncbase.Registry { 26 | // TODO: obsolete, use DefaultRegistry directly instead 27 | return DefaultRegistry 28 | } 29 | -------------------------------------------------------------------------------- /datasync/kvdbsync/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package kvdbsync 16 | 17 | import ( 18 | "fmt" 19 | 20 | "go.ligato.io/cn-infra/v2/datasync/resync" 21 | "go.ligato.io/cn-infra/v2/db/keyval" 22 | "go.ligato.io/cn-infra/v2/logging" 23 | "go.ligato.io/cn-infra/v2/servicelabel" 24 | ) 25 | 26 | // NewPlugin creates a new Plugin with the provided Options. 27 | func NewPlugin(opts ...Option) *Plugin { 28 | p := &Plugin{} 29 | 30 | p.PluginName = "kvdb" 31 | p.ServiceLabel = &servicelabel.DefaultPlugin 32 | p.ResyncOrch = &resync.DefaultPlugin 33 | 34 | for _, o := range opts { 35 | o(p) 36 | } 37 | 38 | name := p.String() 39 | if p.Deps.KvPlugin != nil { 40 | name = fmt.Sprintf("%s-%s", name, p.Deps.KvPlugin.String()) 41 | } 42 | p.Deps.SetName(name + "-datasync") 43 | 44 | if p.Deps.Log == nil { 45 | p.Deps.Log = logging.ForPlugin(p.String()) 46 | } 47 | 48 | return p 49 | } 50 | 51 | // Option is a function that can be used in NewPlugin to customize Plugin. 52 | type Option func(*Plugin) 53 | 54 | // UseDeps returns Option that can inject custom dependencies. 55 | func UseDeps(cb func(*Deps)) Option { 56 | return func(p *Plugin) { 57 | cb(&p.Deps) 58 | } 59 | } 60 | 61 | // UseKV returns Option that sets KvPlugin dependency. 62 | func UseKV(kv keyval.KvProtoPlugin) Option { 63 | return func(p *Plugin) { 64 | p.KvPlugin = kv 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /datasync/msgsync/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package msgsync propagates protobuf messages to a particular topic. 16 | package msgsync 17 | -------------------------------------------------------------------------------- /datasync/msgsync/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package msgsync 16 | 17 | import ( 18 | "go.ligato.io/cn-infra/v2/messaging" 19 | ) 20 | 21 | // NewPlugin creates a new Plugin with the provided Options. 22 | func NewPlugin(opts ...Option) *Plugin { 23 | p := &Plugin{} 24 | 25 | p.PluginName = "msgsync" 26 | 27 | for _, o := range opts { 28 | o(p) 29 | } 30 | 31 | p.PluginDeps.Setup() 32 | 33 | return p 34 | } 35 | 36 | // Option is a function that can be used in NewPlugin to customize Plugin. 37 | type Option func(*Plugin) 38 | 39 | // UseDeps returns Option that can inject custom dependencies. 40 | func UseDeps(cb func(*Deps)) Option { 41 | return func(p *Plugin) { 42 | cb(&p.Deps) 43 | } 44 | } 45 | 46 | // UseConf returns Option which injects a particular configuration. 47 | func UseConf(conf Config) Option { 48 | return func(p *Plugin) { 49 | p.Config = conf 50 | } 51 | } 52 | 53 | // UseMessaging returns Option that sets Messaging. 54 | func UseMessaging(m messaging.Mux) Option { 55 | return func(p *Plugin) { 56 | p.Deps.Messaging = m 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /datasync/restsync/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package restsync implements (in ALPHA VERSION) the datasync API for the 16 | // HTTP/REST transport. This implementation is special (compared to dbsync 17 | // or bussync) because it does not use any intermediate persistence between 18 | // the client and the server. Therefore, the client does remote calls to each 19 | // individual server/agent instance (and needs to know its IP address & port). 20 | package restsync 21 | -------------------------------------------------------------------------------- /datasync/resync/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package resync implements the mechanism to notify previously registered 16 | // plugins that the resync procedure needs to start. 17 | package resync 18 | -------------------------------------------------------------------------------- /datasync/resync/options.go: -------------------------------------------------------------------------------- 1 | package resync 2 | 3 | import ( 4 | "go.ligato.io/cn-infra/v2/logging" 5 | ) 6 | 7 | // DefaultPlugin is a default instance of Plugin. 8 | var DefaultPlugin = *NewPlugin() 9 | 10 | // NewPlugin creates a new Plugin with the provided Options. 11 | func NewPlugin(opts ...Option) *Plugin { 12 | p := &Plugin{} 13 | 14 | p.PluginName = "resync" 15 | 16 | for _, o := range opts { 17 | o(p) 18 | } 19 | 20 | if p.Deps.Log == nil { 21 | p.Deps.Log = logging.ForPlugin(p.String()) 22 | } 23 | 24 | return p 25 | } 26 | 27 | // Option is a function that can be used in NewPlugin to customize Plugin. 28 | type Option func(*Plugin) 29 | 30 | // UseDeps returns Option that can inject custom dependencies. 31 | func UseDeps(cb func(*Deps)) Option { 32 | return func(p *Plugin) { 33 | cb(&p.Deps) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /datasync/resync/plugin_api_resync.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package resync 16 | 17 | // Subscriber is an API used by plugins to register for notifications from the 18 | // RESYNC Orcherstrator. 19 | type Subscriber interface { 20 | // Register function is supposed to be called in Init() by all VPP Agent plugins. 21 | // Those plugins will use Registration.StatusChan() to listen 22 | // The plugins are supposed to load current state of their objects when newResync() is called. 23 | Register(resyncName string) Registration 24 | } 25 | 26 | // Registration is an interface that is returned by the Register() call. 27 | type Registration interface { 28 | StatusChan() <-chan StatusEvent 29 | String() string 30 | //TODO io.Closer 31 | } 32 | 33 | // Status used in the events. 34 | type Status string 35 | 36 | const ( 37 | // Started means that the Resync has started. 38 | Started Status = "Started" 39 | // NotActive means that Resync has not started yet or it has been finished. 40 | NotActive Status = "NotActive" 41 | ) 42 | 43 | // StatusEvent is the base type that will be propagated to the channel. 44 | type StatusEvent interface { 45 | // Status() is used by the Plugin if it needs to Start resync. 46 | ResyncStatus() Status 47 | 48 | // Ack() is used by the Plugin to acknowledge that it processed this event. 49 | // This is supposed to be called after the configuration was applied by the Plugin. 50 | Ack() 51 | } 52 | -------------------------------------------------------------------------------- /datasync/syncbase/change.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package syncbase 16 | 17 | import ( 18 | "google.golang.org/protobuf/proto" 19 | 20 | "go.ligato.io/cn-infra/v2/datasync" 21 | ) 22 | 23 | // Change represents a single Key-value pair plus changeType. 24 | type Change struct { 25 | changeType datasync.Op 26 | datasync.KeyVal 27 | } 28 | 29 | // NewChange creates a new instance of Change. 30 | func NewChange(key string, value proto.Message, rev int64, changeType datasync.Op) *Change { 31 | return &Change{ 32 | changeType: changeType, 33 | KeyVal: &KeyVal{key, &lazyProto{value}, rev}, 34 | } 35 | } 36 | 37 | // NewChangeBytes creates a new instance of NewChangeBytes. 38 | func NewChangeBytes(key string, value []byte, rev int64, changeType datasync.Op) *Change { 39 | return &Change{ 40 | changeType: changeType, 41 | KeyVal: &KeyValBytes{key, value, rev}, 42 | } 43 | } 44 | 45 | // GetChangeType returns type of the change. 46 | func (kv *Change) GetChangeType() datasync.Op { 47 | return kv.changeType 48 | } 49 | -------------------------------------------------------------------------------- /datasync/syncbase/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package syncbase defines common structures used in multiple datasync 16 | // transports. The following reusable structures are defined: 17 | // 18 | // - KeyValProtoWatcher maintains watch registrations/subscriptions. 19 | // 20 | // - Registry of the latest revisions of values per each key, synchronized by 21 | // datasync. 22 | // 23 | // - Default implementation of Events & Iterators interfaces defined in data_api.go. 24 | // 25 | // - Events & Iterators in this package are reused by some datasync transports. 26 | package syncbase 27 | -------------------------------------------------------------------------------- /datasync/syncbase/msg/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package msg contains: 16 | // - the definition of PROTOBUF structures and gRPC service, 17 | // - helpers for mapping between PROTOBUF structures & the datasync_api.go. 18 | package msg 19 | -------------------------------------------------------------------------------- /datasync/syncbase/transport_adapter.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package syncbase 16 | 17 | import ( 18 | "google.golang.org/protobuf/proto" 19 | 20 | "go.ligato.io/cn-infra/v2/datasync" 21 | "go.ligato.io/cn-infra/v2/logging/logrus" 22 | ) 23 | 24 | // Adapter implements datasync.TransportAdapter but allows the Watch/ Put functions to be optionally implemented. 25 | type Adapter struct { 26 | Watcher datasync.KeyValProtoWatcher 27 | Publisher datasync.KeyProtoValWriter 28 | } 29 | 30 | // Watch uses Kafka KeyValProtoWatcher Topic KeyValProtoWatcher. 31 | func (adapter *Adapter) Watch(resyncName string, changeChan chan datasync.ChangeEvent, 32 | resyncChan chan datasync.ResyncEvent, keyPrefixes ...string) (datasync.WatchRegistration, error) { 33 | 34 | if adapter.Watcher != nil { 35 | return adapter.Watcher.Watch(resyncName, changeChan, resyncChan, keyPrefixes...) 36 | } 37 | logrus.DefaultLogger().Debug("KeyValProtoWatcher is nil") 38 | 39 | return nil, nil 40 | } 41 | 42 | // Put uses Kafka KeyValProtoWatcher Topic KeyProtoValWriter. 43 | func (adapter *Adapter) Put(key string, data proto.Message) error { 44 | if adapter.Publisher != nil { 45 | return adapter.Publisher.Put(key, data) 46 | } 47 | 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /db/cryptodata/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package cryptodata provides support for wrapping key-value store with 16 | // crypto layer that will automatically decrypt all data passing through. 17 | package cryptodata 18 | -------------------------------------------------------------------------------- /db/cryptodata/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cryptodata 16 | 17 | // DefaultPlugin is a default instance of Plugin. 18 | var DefaultPlugin = *NewPlugin() 19 | 20 | // NewPlugin creates a new Plugin with the provided Options. 21 | func NewPlugin(opts ...Option) *Plugin { 22 | p := &Plugin{} 23 | 24 | p.PluginName = "cryptodata" 25 | 26 | for _, o := range opts { 27 | o(p) 28 | } 29 | 30 | p.PluginDeps.Setup() 31 | 32 | return p 33 | } 34 | 35 | // Option is a function that can be used in NewPlugin to customize Plugin. 36 | type Option func(*Plugin) 37 | 38 | // UseDeps returns Option that can inject custom dependencies. 39 | func UseDeps(cb func(*Deps)) Option { 40 | return func(p *Plugin) { 41 | cb(&p.Deps) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /db/cryptodata/wrapper.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cryptodata 16 | 17 | // decryptData holds values required for decrypting 18 | type decryptData struct { 19 | // Function used for decrypting arbitrary data later 20 | decryptFunc DecryptFunc 21 | // ArbitraryDecrypter is used to decrypt data 22 | decrypter ArbitraryDecrypter 23 | } -------------------------------------------------------------------------------- /db/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package db is the parent package for the Data Broker client implementations 16 | // for various key-value and SQL data stores. 17 | package db 18 | -------------------------------------------------------------------------------- /db/keyval/bolt/bolt.conf: -------------------------------------------------------------------------------- 1 | # Path to Bolt DB file 2 | db-path: /tmp/bolt.db 3 | 4 | # File's mode and permission bits in decimal format ... 432 = --rw-rw---- 5 | file-mode: 432 6 | 7 | # Timeout is the amount of time to wait to obtain a file lock 8 | # When set to zero it will wait indefinitely 9 | lock-timeout: 0s -------------------------------------------------------------------------------- /db/keyval/bolt/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package bolt 16 | 17 | // DefaultPlugin is a default instance of Plugin. 18 | var DefaultPlugin = *NewPlugin() 19 | 20 | // NewPlugin creates a new Plugin with the provided Options. 21 | func NewPlugin(opts ...Option) *Plugin { 22 | p := &Plugin{} 23 | 24 | p.PluginName = "bolt" 25 | 26 | for _, o := range opts { 27 | o(p) 28 | } 29 | 30 | p.PluginDeps.Setup() 31 | 32 | return p 33 | } 34 | 35 | // Option is a function that can be used in NewPlugin to customize Plugin. 36 | type Option func(*Plugin) 37 | 38 | // UseDeps returns Option that can inject custom dependencies. 39 | func UseDeps(cb func(*Deps)) Option { 40 | return func(p *Plugin) { 41 | cb(&p.Deps) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /db/keyval/bytes_watcher_api.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package keyval 16 | 17 | import ( 18 | "time" 19 | 20 | "go.ligato.io/cn-infra/v2/datasync" 21 | "go.ligato.io/cn-infra/v2/logging" 22 | ) 23 | 24 | // BytesWatcher defines API for monitoring changes in datastore. 25 | type BytesWatcher interface { 26 | // Watch starts subscription for changes associated with the selected keys. 27 | // Watch events will be delivered to callback (not channel) . 28 | // Channel can be used to close watching on respective key 29 | Watch(respChan func(BytesWatchResp), closeChan chan string, keys ...string) error 30 | } 31 | 32 | // BytesWatchResp represents a notification about data change. 33 | // It is sent through the respChan callback. 34 | type BytesWatchResp interface { 35 | BytesKvPair 36 | datasync.WithChangeType 37 | datasync.WithRevision 38 | } 39 | 40 | // ToChan creates a callback that can be passed to the Watch function in order 41 | // to receive notifications through a channel. If the notification cannot be 42 | // delivered until timeout, it is dropped. 43 | func ToChan(respCh chan BytesWatchResp, opts ...interface{}) func(dto BytesWatchResp) { 44 | return func(dto BytesWatchResp) { 45 | select { 46 | case respCh <- dto: 47 | // success 48 | case <-time.After(datasync.DefaultNotifTimeout): 49 | logging.Warn("Unable to deliver notification") 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /db/keyval/consul/consul.conf: -------------------------------------------------------------------------------- 1 | # Address of the Consul server 2 | address: 0.0.0.0:8500 3 | 4 | # If Consul server lost connection, the flag allows to automatically run the whole resync procedure 5 | # for all registered plugins if it reconnects 6 | resync-after-reconnect: false -------------------------------------------------------------------------------- /db/keyval/consul/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package consul 16 | 17 | import ( 18 | "go.ligato.io/cn-infra/v2/health/statuscheck" 19 | ) 20 | 21 | // DefaultPlugin is a default instance of Plugin. 22 | var DefaultPlugin = *NewPlugin() 23 | 24 | // NewPlugin creates a new Plugin with the provided Options. 25 | func NewPlugin(opts ...Option) *Plugin { 26 | p := &Plugin{} 27 | 28 | p.PluginName = "consul" 29 | p.StatusCheck = &statuscheck.DefaultPlugin 30 | 31 | for _, o := range opts { 32 | o(p) 33 | } 34 | 35 | p.PluginDeps.Setup() 36 | 37 | return p 38 | } 39 | 40 | // Option is a function that can be used in NewPlugin to customize Plugin. 41 | type Option func(*Plugin) 42 | 43 | // UseDeps returns Option that can inject custom dependencies. 44 | func UseDeps(cb func(*Deps)) Option { 45 | return func(p *Plugin) { 46 | cb(&p.Deps) 47 | } 48 | } 49 | 50 | // UseConf returns Option which injects a particular configuration. 51 | func UseConf(conf Config) Option { 52 | return func(p *Plugin) { 53 | p.Config = &conf 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /db/keyval/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package keyval provides an abstraction of a key-value data store and 16 | // defines the keyval data broker API. The Data Broker API consists of the 17 | // ProtoBroker API, the KeyValProtoWatcher API, and other supporting APIs. 18 | // It is used to access data in a key-value store. 19 | package keyval 20 | -------------------------------------------------------------------------------- /db/keyval/etcd/etcd.conf: -------------------------------------------------------------------------------- 1 | # A list of host IP addresses of ETCD database server. 2 | endpoints: 3 | - "172.17.0.1:2379" 4 | 5 | # Connection fails if it is not established till timeout 6 | dial-timeout: 100ms 7 | 8 | # Operation timeout value. 9 | operation-timeout: 300ms 10 | 11 | # Insecure transport omits TLS usage 12 | insecure-transport: false 13 | 14 | # Controls whether a client verifies the server's certificate chain and host name. 15 | # If InsecureSkipVerify is true, TLS accepts any certificate presented by the server 16 | # and any host name in that certificate. In this mode, TLS is susceptible to man-in-the-middle 17 | # attacks. This should be used only for testing. 18 | insecure-skip-tls-verify: false 19 | 20 | # TLS certification file 21 | cert-file: 22 | 23 | # TLS certification key 24 | key-file: 25 | 26 | # CA file used to create a set of x509 certificates 27 | ca-file: 28 | 29 | # Interval between ETCD auto compaction cycles. 0 means disabled. 30 | auto-compact: 0 31 | 32 | # If ETCD server lost connection, the flag allows to automatically run the whole resync procedure 33 | # for all registered plugins if it reconnects 34 | resync-after-reconnect: false 35 | 36 | # Enable start without connected ETCD database. Plugin will try to connect and if successful, overall resync will 37 | # be called 38 | allow-delayed-start: false 39 | 40 | # Interval between ETCD reconnect attempts in ns. Default value is 2 seconds. Has no use if `delayed start` is turned off 41 | reconnect-interval: 2s -------------------------------------------------------------------------------- /db/keyval/etcd/mocks/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package mocks implements an embedded etcd mock used in unit & 16 | // integration tests. 17 | package mocks 18 | -------------------------------------------------------------------------------- /db/keyval/etcd/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package etcd 16 | 17 | import ( 18 | "go.ligato.io/cn-infra/v2/datasync/resync" 19 | "go.ligato.io/cn-infra/v2/health/statuscheck" 20 | ) 21 | 22 | // DefaultPlugin is a default instance of Plugin. 23 | var DefaultPlugin = *NewPlugin() 24 | 25 | // NewPlugin creates a new Plugin with the provided Options. 26 | func NewPlugin(opts ...Option) *Plugin { 27 | p := &Plugin{} 28 | 29 | p.PluginName = "etcd" 30 | p.StatusCheck = &statuscheck.DefaultPlugin 31 | p.Resync = &resync.DefaultPlugin 32 | 33 | for _, o := range opts { 34 | o(p) 35 | } 36 | 37 | p.PluginDeps.Setup() 38 | 39 | return p 40 | } 41 | 42 | // Option is a function that can be used in NewPlugin to customize Plugin. 43 | type Option func(*Plugin) 44 | 45 | // UseDeps returns Option that can inject custom dependencies. 46 | func UseDeps(cb func(*Deps)) Option { 47 | return func(p *Plugin) { 48 | cb(&p.Deps) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /db/keyval/filedb/export_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package filedb 16 | 17 | // Export for testing 18 | 19 | // RunEventWatcher allows to run event watcher without fileDB plugin 20 | func RunEventWatcher(client *Client) { 21 | go client.eventWatcher() 22 | } 23 | -------------------------------------------------------------------------------- /db/keyval/filedb/filesystem.conf: -------------------------------------------------------------------------------- 1 | # A set of files/directories with configuration files. If target is a directory, all .json or .yaml files are read. 2 | configuration-paths: [/path/to/directory/, /path/to/file.ext] 3 | 4 | # Path where the status data will be stored. If not defined, status is not propagated. File extension determines 5 | # whether the data will be stored as .json or .yaml. Target may cannot a directory. 6 | status-path: "/path/to/status.ext" 7 | 8 | -------------------------------------------------------------------------------- /db/keyval/filedb/iterator.go: -------------------------------------------------------------------------------- 1 | package filedb 2 | 3 | import ( 4 | "strings" 5 | 6 | "go.ligato.io/cn-infra/v2/db/keyval/filedb/decoder" 7 | 8 | "go.ligato.io/cn-infra/v2/db/keyval" 9 | ) 10 | 11 | // File system DB BytesKeyValIterator implementation 12 | type bytesKeyValIterator struct { 13 | index int 14 | len int 15 | rev int 16 | data []*decoder.FileDataEntry 17 | } 18 | 19 | // File system DB BytesKeyIterator implementation 20 | type bytesKeyIterator struct { 21 | index int 22 | len int 23 | keys []string 24 | prefix string 25 | } 26 | 27 | // File system DB BytesKeyVal implementation 28 | type bytesKeyVal struct { 29 | key string 30 | value []byte 31 | prevValue []byte 32 | } 33 | 34 | func (it *bytesKeyValIterator) GetNext() (val keyval.BytesKeyVal, stop bool) { 35 | if it.index >= it.len { 36 | return nil, true 37 | } 38 | 39 | key := it.data[it.index].Key 40 | data := it.data[it.index].Value 41 | 42 | var prevValue []byte 43 | if len(it.data) > 0 && it.index > 0 { 44 | prevValue = it.data[it.index-1].Value 45 | } 46 | 47 | it.index++ 48 | 49 | return &bytesKeyVal{key, data, prevValue}, false 50 | } 51 | 52 | func (it *bytesKeyIterator) GetNext() (key string, rev int64, stop bool) { 53 | if it.index >= it.len { 54 | return "", 0, true 55 | } 56 | 57 | key = string(it.keys[it.index]) 58 | if !strings.HasPrefix(key, "/") && strings.HasPrefix(it.prefix, "/") { 59 | key = "/" + key 60 | } 61 | if it.prefix != "" { 62 | key = strings.TrimPrefix(key, it.prefix) 63 | } 64 | it.index++ 65 | 66 | return key, rev, false 67 | } 68 | 69 | func (kv *bytesKeyVal) GetValue() []byte { 70 | return kv.value 71 | } 72 | 73 | func (kv *bytesKeyVal) GetPrevValue() []byte { 74 | return kv.prevValue 75 | } 76 | 77 | func (kv *bytesKeyVal) GetKey() string { 78 | return kv.key 79 | } 80 | 81 | func (kv *bytesKeyVal) GetRevision() (rev int64) { 82 | return 0 83 | } 84 | -------------------------------------------------------------------------------- /db/keyval/filedb/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package filedb 16 | 17 | // DefaultPlugin is a default instance of Plugin. 18 | var DefaultPlugin = *NewPlugin() 19 | 20 | // NewPlugin creates a new Plugin with the provided Options. 21 | func NewPlugin(opts ...Option) *Plugin { 22 | p := &Plugin{} 23 | 24 | p.PluginName = "filedb" 25 | 26 | for _, o := range opts { 27 | o(p) 28 | } 29 | 30 | p.PluginDeps.Setup() 31 | 32 | return p 33 | } 34 | 35 | // Option is a function that can be used in NewPlugin to customize Plugin. 36 | type Option func(*Plugin) 37 | 38 | // UseDeps returns Option that can inject custom dependencies. 39 | func UseDeps(cb func(*Deps)) Option { 40 | return func(p *Plugin) { 41 | cb(&p.Deps) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /db/keyval/filedb/watch.go: -------------------------------------------------------------------------------- 1 | package filedb 2 | 3 | import ( 4 | "go.ligato.io/cn-infra/v2/datasync" 5 | ) 6 | 7 | // Implementation of BytesWatchResp (generic response) 8 | type watchResp struct { 9 | Op datasync.Op 10 | Key string 11 | Value, PrevValue []byte 12 | Rev int64 13 | } 14 | 15 | func (wr *watchResp) GetValue() []byte { 16 | return wr.Value 17 | } 18 | 19 | func (wr *watchResp) GetPrevValue() []byte { 20 | return wr.PrevValue 21 | } 22 | 23 | func (wr *watchResp) GetKey() string { 24 | return wr.Key 25 | } 26 | 27 | func (wr *watchResp) GetChangeType() datasync.Op { 28 | return wr.Op 29 | } 30 | 31 | func (wr *watchResp) GetRevision() (rev int64) { 32 | return wr.Rev 33 | } 34 | -------------------------------------------------------------------------------- /db/keyval/kvproto/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package kvproto provides a wrapper that simplifies the storing and 16 | // retrieving of proto-modelled data into/from a key-value data store. 17 | package kvproto 18 | -------------------------------------------------------------------------------- /db/keyval/proto_watcher_api.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package keyval 16 | 17 | import ( 18 | "time" 19 | 20 | "go.ligato.io/cn-infra/v2/datasync" 21 | "go.ligato.io/cn-infra/v2/logging" 22 | ) 23 | 24 | // ProtoWatcher defines API for monitoring changes in datastore. 25 | // Changes are returned as protobuf/JSON-formatted data. 26 | type ProtoWatcher interface { 27 | // Watch starts monitoring changes associated with the keys. 28 | // Watch events will be delivered to callback (not channel) . 29 | // Channel can be used to close watching on respective key 30 | Watch(respChan func(datasync.ProtoWatchResp), closeChan chan string, key ...string) error 31 | } 32 | 33 | // ToChanProto creates a callback that can be passed to the Watch function 34 | // in order to receive JSON/protobuf-formatted notifications through a channel. 35 | // If the notification cannot be delivered until timeout, it is dropped. 36 | func ToChanProto(respCh chan datasync.ProtoWatchResp, opts ...interface{}) func(dto datasync.ProtoWatchResp) { 37 | return func(dto datasync.ProtoWatchResp) { 38 | select { 39 | case respCh <- dto: 40 | // success 41 | case <-time.After(datasync.DefaultNotifTimeout): 42 | logging.Warn("Unable to deliver notification") 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /db/keyval/redis/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package redis is the implementation of the key-value Data Broker client 16 | // API for the Redis key-value data store. See cn-infra/db/keyval for the 17 | // definition of the key-value Data Broker client API. 18 | package redis 19 | -------------------------------------------------------------------------------- /db/keyval/redis/options.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "go.ligato.io/cn-infra/v2/health/statuscheck" 5 | ) 6 | 7 | // DefaultPlugin is a default instance of Plugin. 8 | var DefaultPlugin = *NewPlugin() 9 | 10 | // NewPlugin creates a new Plugin with the provided Options. 11 | func NewPlugin(opts ...Option) *Plugin { 12 | p := &Plugin{} 13 | 14 | p.PluginName = "redis" 15 | p.StatusCheck = &statuscheck.DefaultPlugin 16 | 17 | for _, o := range opts { 18 | o(p) 19 | } 20 | 21 | p.PluginDeps.Setup() 22 | 23 | return p 24 | } 25 | 26 | // Option is a function that can be used in NewPlugin to customize Plugin. 27 | type Option func(*Plugin) 28 | 29 | // UseDeps returns Option that can inject custom dependencies. 30 | func UseDeps(cb func(*Deps)) Option { 31 | return func(p *Plugin) { 32 | cb(&p.Deps) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /db/sql/README.md: -------------------------------------------------------------------------------- 1 | # SQL-like datastore 2 | 3 | The `sql` package defines the API for accessing a data store using SQL. 4 | The `Broker` interface allows reading and manipulating with data. 5 | The `Watcher` API provides functions for monitoring of changes 6 | in a data store. 7 | 8 | ## Features 9 | 10 | - The user of the API has full control over the SQL statements, 11 | types & bindings passed to the `Broker`. 12 | - Expressions: 13 | - Helper functions alleviate the need to write SQL strings. 14 | - The user can choose to only write expressions using helper 15 | functions 16 | - The user can write portions of SQL statements by a hand 17 | (the `sql.Exp` helper function) and combine them with other 18 | expressions 19 | - The user can optionally use reflection to simplify repetitive work 20 | with Iterators & Go structures 21 | - The API will be reused for different databases. 22 | A specific implementation will be provided for each database. 23 | -------------------------------------------------------------------------------- /db/sql/cassandra/cassa_txn_impl.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cassandra 16 | 17 | import ( 18 | "go.ligato.io/cn-infra/v2/db/sql" 19 | ) 20 | 21 | // NewTxn creates a new Data Broker transaction. A transaction can 22 | // hold multiple operations that are all committed to the data 23 | // store together. After a transaction has been created, one or 24 | // more operations (put or delete) can be added to the transaction 25 | // before it is committed. 26 | func (pdb *BrokerCassa) NewTxn() sql.Txn { 27 | // TODO Cassandra Batch/TXN 28 | panic("not implemented") 29 | } 30 | -------------------------------------------------------------------------------- /db/sql/cassandra/cassa_watcher_impl.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cassandra 16 | 17 | /*TODO use https://issues.apache.org/jira/browse/CASSANDRA-8844 18 | type WatcherCassa struct { 19 | watcher keyval.BytesWatcher 20 | serializer keyval.Serializer 21 | } 22 | */ 23 | -------------------------------------------------------------------------------- /db/sql/cassandra/cassandra.conf: -------------------------------------------------------------------------------- 1 | # A list of host IP addresses of cassandra cluster nodes. 2 | endpoints: 3 | - "172.17.0.1:2379" 4 | 5 | # Cassandra client port 6 | port: 9042 7 | 8 | # Connection timeout. The default value is 600ms. 9 | op_timeout: 600ms 10 | 11 | # Initial session timeout, used during initial dial to server. The default value is 600ms. 12 | dial_timeout: 600ms 13 | 14 | # If set, gocql attempt to reconnect known down nodes in every ReconnectSleep. Default is 60 seconds. 15 | redial_interval: 60s 16 | 17 | # ProtoVersion sets the version of the native protocol to use, this will 18 | # enable features in the driver for specific protocol versions, generally this 19 | # should be set to a known version (2,3,4) for the cluster being connected to. 20 | # If it is 0 or unset (the default) then the driver will attempt to discover the 21 | # highest supported protocol for the cluster. In clusters with nodes of different 22 | # versions the protocol selected is not defined (ie, it can be any of the supported in the cluster) 23 | protocol_version: 0 24 | 25 | # Transport Layer Security setup 26 | #tls: -------------------------------------------------------------------------------- /db/sql/cassandra/options.go: -------------------------------------------------------------------------------- 1 | package cassandra 2 | 3 | import ( 4 | "go.ligato.io/cn-infra/v2/health/statuscheck" 5 | ) 6 | 7 | // DefaultPlugin is a default instance of Plugin. 8 | var DefaultPlugin = *NewPlugin() 9 | 10 | // NewPlugin creates a new Plugin with the provided Options. 11 | func NewPlugin(opts ...Option) *Plugin { 12 | p := &Plugin{} 13 | 14 | p.PluginName = "cassandra" 15 | p.StatusCheck = &statuscheck.DefaultPlugin 16 | 17 | for _, o := range opts { 18 | o(p) 19 | } 20 | 21 | p.PluginDeps.Setup() 22 | 23 | return p 24 | } 25 | 26 | // Option is a function that can be used in NewPlugin to customize Plugin. 27 | type Option func(*Plugin) 28 | 29 | // UseDeps returns Option that can inject custom dependencies. 30 | func UseDeps(cb func(*Deps)) Option { 31 | return func(p *Plugin) { 32 | cb(&p.Deps) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /db/sql/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package sql provides an abstraction of a data store that supports an 16 | // SQL-like query language and defines the SQL data broker API. The SQL 17 | // data broker API consists of the Broker and KeyValProtoWatcher APIs 18 | // for accessing data in an SQL data store. 19 | package sql 20 | -------------------------------------------------------------------------------- /db/sql/plugin_api_sql.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package sql 16 | 17 | // BrokerPlugin provides unifying interface for different SQL-like datastore implementations. 18 | type BrokerPlugin interface { 19 | // NewBroker returns a Broker instance that works with Data Base. 20 | NewBroker() Broker 21 | } 22 | -------------------------------------------------------------------------------- /db/sql/slice_utils.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package sql 16 | 17 | import ( 18 | "reflect" 19 | 20 | "go.ligato.io/cn-infra/v2/utils/safeclose" 21 | ) 22 | 23 | // SliceIt reads everything from the ValIterator and stores it to pointerToASlice. 24 | // It closes the iterator (since nothing left in the iterator). 25 | func SliceIt(pointerToASlice interface{}, it ValIterator) error { 26 | /* TODO defer func() { 27 | if exp := recover(); exp != nil && it != nil { 28 | logger.Error(exp) 29 | exp = safeclose.Close(it) 30 | if exp != nil { 31 | logger.Error(exp) 32 | } 33 | } 34 | }()*/ 35 | 36 | sl := reflect.ValueOf(pointerToASlice) 37 | if sl.Kind() == reflect.Ptr { 38 | sl = sl.Elem() 39 | } else { 40 | panic("must be pointer") 41 | } 42 | 43 | if sl.Kind() != reflect.Slice { 44 | panic("must be slice") 45 | } 46 | 47 | sliceType := sl.Type() 48 | 49 | sliceElemType := sliceType.Elem() 50 | sliceElemPtr := sliceElemType.Kind() == reflect.Ptr 51 | if sliceElemPtr { 52 | sliceElemType = sliceElemType.Elem() 53 | } 54 | for { 55 | row := reflect.New(sliceElemType) 56 | if stop := it.GetNext(row.Interface()); stop { 57 | break 58 | } 59 | 60 | if sliceElemPtr { 61 | sl.Set(reflect.Append(sl, row)) 62 | } else { 63 | sl.Set(reflect.Append(sl, row.Elem())) 64 | } 65 | } 66 | 67 | return safeclose.Close(it) 68 | } 69 | -------------------------------------------------------------------------------- /db/sql/sql_struct_metadata.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package sql 16 | 17 | import "reflect" 18 | 19 | // TableName interface specifies custom table name for SQL statements. 20 | type TableName interface { 21 | // TableName returns sql table name. 22 | TableName() string 23 | } 24 | 25 | // SchemaName interface specifies custom schema name for SQL statements. 26 | type SchemaName interface { 27 | // SchemaName returns sql schema name where the table resides 28 | SchemaName() string 29 | } 30 | 31 | // EntityTableName returns the table name, possibly prefixed with the schema 32 | // name, associated with the . 33 | // The function tries to cast to TableName and SchemaName in order to 34 | // obtain the table name and the schema name, respectively. 35 | // If table name cannot be obtained, the struct name is used instead. 36 | // If schema name cannot be obtained, it is simply omitted from the result. 37 | func EntityTableName(entity interface{}) string { 38 | var tableName, schemaName string 39 | if nameProvider, ok := entity.(TableName); ok { 40 | tableName = nameProvider.TableName() 41 | } 42 | 43 | if tableName == "" { 44 | tableName = reflect.Indirect(reflect.ValueOf(entity)).Type().Name() 45 | } 46 | 47 | if schemaNameProvider, ok := entity.(SchemaName); ok { 48 | schemaName = schemaNameProvider.SchemaName() 49 | } 50 | 51 | if schemaName == "" { 52 | return tableName 53 | } 54 | 55 | return schemaName + "." + tableName 56 | } 57 | -------------------------------------------------------------------------------- /db/sql/sql_watcher_api.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package sql 16 | 17 | import "go.ligato.io/cn-infra/v2/datasync" 18 | 19 | // Watcher defines API for monitoring changes in a datastore. 20 | type Watcher interface { 21 | // Watch starts to monitor changes in a data store. 22 | // Watch events will be delivered to the . 23 | Watch(callback func(WatchResp), statement ...string) error 24 | } 25 | 26 | // WatchResp represents a notification about change. 27 | // It is passed to the Watch callback. 28 | type WatchResp interface { 29 | // GetChangeType returns the type of the change. 30 | GetChangeType() datasync.Op 31 | 32 | // GetValue returns the changed value. 33 | GetValue(outBinding interface{}) error 34 | } 35 | 36 | // ToChan TODO (not implemented yet) 37 | func ToChan(respChan chan WatchResp, options ...interface{}) func(event WatchResp) { 38 | return func(WatchResp) { 39 | /*select { 40 | case respChan <- resp: 41 | case <-time.After(defaultOpTimeout): 42 | log.Warn("Unable to deliver watch event before timeout.") 43 | } 44 | 45 | select { 46 | case wresp := <-recvChan: 47 | for _, ev := range wresp.Events { 48 | handleWatchEvent(respChan, ev) 49 | } 50 | case <-closeCh: 51 | log.WithField("key", key).Debug("Watch ended") 52 | return 53 | }*/ 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package cninfra is the parent package for all packages that are parts 16 | // of the CN-Infra platform - a Golang platform for building cloud-native 17 | // microservices. 18 | // 19 | // The CN-Infra platform is a modular platform comprising a core and a set 20 | // of plugins. The core provides lifecycle management for plugins, the 21 | // plugins provide the functionality of the platform. A plugin can consist 22 | // of one or more Golang packages. Out of the box, the CN-Infra platform 23 | // provides reusable plugins for logging, health checks, messaging (e.g. 24 | // Kafka), a common front-end API and back-end connectivity to various 25 | // data stores (Etcd, Cassandra, Redis, ...), and REST and gRPC APIs. 26 | // 27 | // The CN-Infra platform can be extended by adding a new platform plugin, 28 | // for example a new data store client or a message bus adapter. Also, each 29 | // application built on top of the platform is basically just a set of 30 | // application-specific plugins. 31 | package cninfra 32 | -------------------------------------------------------------------------------- /docker/dev_cn_infra/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | ARG AGENT_COMMIT="xxx" 4 | 5 | RUN apt-get update && apt-get install -y \ 6 | sudo wget git build-essential gdb vim nano python \ 7 | iproute2 iputils-ping inetutils-traceroute libapr1 supervisor telnet netcat 8 | 9 | RUN mkdir /opt/agent 10 | RUN mkdir /opt/agent/dev 11 | 12 | WORKDIR /opt/agent/dev 13 | 14 | 15 | # install Go & Glide 16 | RUN wget https://storage.googleapis.com/golang/go1.9.2.linux-amd64.tar.gz && \ 17 | tar -xvf go1.9.2.linux-amd64.tar.gz && \ 18 | mv go /usr/local && \ 19 | rm -f go1.9.2.linux-amd64.tar.gz 20 | 21 | # build & install Protobuf & golang protobuf compiler 22 | RUN apt-get install -y make && \ 23 | apt-get install -y autoconf automake libtool curl make g++ unzip 24 | 25 | RUN git clone https://github.com/google/protobuf.git && \ 26 | cd protobuf && ./autogen.sh && ./configure && \ 27 | make -j4 && \ 28 | make install && \ 29 | ldconfig && \ 30 | cd .. && rm -rf protobuf 31 | 32 | RUN go get github.com/golang/protobuf 33 | 34 | # copy and execute agent build script 35 | COPY build-agent.sh . 36 | RUN ./build-agent.sh ${AGENT_COMMIT} 37 | 38 | COPY etcd.conf . 39 | COPY kafka.conf . 40 | 41 | WORKDIR /root/ 42 | 43 | # add supervisor conf file 44 | COPY supervisord.conf /etc/supervisord.conf 45 | 46 | # run supervisor as the default executable 47 | CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"] 48 | -------------------------------------------------------------------------------- /docker/dev_cn_infra/build-agent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # setup Go paths 6 | export GOROOT=/usr/local/go 7 | export GOPATH=$HOME/go 8 | export PATH=$PATH:$GOROOT/bin:$GOPATH/bin 9 | echo "export GOROOT=$GOROOT" >> ~/.bashrc 10 | echo "export GOPATH=$GOPATH" >> ~/.bashrc 11 | echo "export PATH=$PATH" >> ~/.bashrc 12 | mkdir -p $GOPATH/{bin,pkg,src} 13 | 14 | # install golint, gvt & Glide 15 | #go get -u github.com/golang/lint/golint 16 | #go get -u github.com/FiloSottile/gvt 17 | #curl https://glide.sh/get | sh 18 | 19 | # checkout agent code 20 | mkdir -p $GOPATH/src/github.com/ligato 21 | cd $GOPATH/src/github.com/ligato 22 | git clone https://github.com/ligato/cn-infra.git 23 | 24 | # build the agent 25 | cd $GOPATH/src/github.com/ligato/cn-infra 26 | git checkout $1 27 | make 28 | 29 | cp examples/simple-agent/simple-agent $GOPATH/bin/ 30 | #make install 31 | #make test 32 | #make generate 33 | -------------------------------------------------------------------------------- /docker/dev_cn_infra/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set +e 4 | sudo docker rmi -f dev_cn_infra 5 | set -e 6 | 7 | CURRENT_FOLDER=`pwd` 8 | AGENT_COMMIT=`git rev-parse HEAD` 9 | echo "repo agent commit number: "$AGENT_COMMIT 10 | 11 | while [ "$1" != "" ]; do 12 | case $1 in 13 | -a | --agent ) shift 14 | AGENT_COMMIT=$1 15 | ;; 16 | * ) echo "invalid parameter "$1 17 | exit 1 18 | esac 19 | shift 20 | done 21 | 22 | echo "build agent commit number: "$AGENT_COMMIT 23 | 24 | sudo docker build --force-rm=true -t dev_cn_infra --build-arg AGENT_COMMIT=$AGENT_COMMIT --no-cache . 25 | -------------------------------------------------------------------------------- /docker/dev_cn_infra/etcd.conf: -------------------------------------------------------------------------------- 1 | insecure-transport: true 2 | dial-timeout: 1s 3 | endpoints: 4 | - "172.17.0.1:2379" 5 | -------------------------------------------------------------------------------- /docker/dev_cn_infra/kafka.conf: -------------------------------------------------------------------------------- 1 | addrs: 2 | - "172.17.0.1:9092" 3 | -------------------------------------------------------------------------------- /docker/dev_cn_infra/shrink.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set +e 4 | sudo docker rmi -f dev_cn_infra_shrink 5 | sudo docker rm -f shrink 6 | set -e 7 | 8 | sudo docker run -itd --name shrink dev_cn_infra bash 9 | sudo docker export shrink >shrink.tar 10 | sudo docker rm -f shrink 11 | sudo docker import -c "WORKDIR /root/" -c 'CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]' shrink.tar dev_cn_infra_shrink 12 | rm shrink.tar 13 | -------------------------------------------------------------------------------- /docker/dev_cn_infra/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | logfile=/var/log/supervisord.log 3 | loglevel=debug 4 | nodaemon=true 5 | 6 | [program:agent] 7 | command=/root/go/bin/simple-agent --etcd-config=/opt/agent/dev/etcd.conf --kafka-config=/opt/agent/dev/kafka.conf 8 | autorestart=true 9 | redirect_stderr=true 10 | priority=2 11 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | Docs have been moved to [docs.ligato.io](https://docs.ligato.io/). 4 | -------------------------------------------------------------------------------- /docs/imgs/high_level_arch_cninfra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ligato/cn-infra/356dce1f1754fdc28af2cab9df30603a383be829/docs/imgs/high_level_arch_cninfra.png -------------------------------------------------------------------------------- /docs/imgs/http.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ligato/cn-infra/356dce1f1754fdc28af2cab9df30603a383be829/docs/imgs/http.png -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | bolt-plugin/bolt-plugin 2 | cassandra-lib/cassandra-lib 3 | configs-plugin/configs-plugin 4 | consul-lib/consul-lib 5 | cryptodata-lib/cryptodata-lib 6 | cryptodata-plugin/cryptodata-plugin 7 | cryptodata-proto-plugin/cryptodata-proto-plugin 8 | datasync-plugin/datasync-plugin 9 | etcd-lib/editor/editor 10 | etcd-lib/election/election 11 | etcd-lib/view/view 12 | etcd-lib/watcher/watcher 13 | flags-lib/flags-lib 14 | grpc-plugin/grpc-client/grpc-client 15 | grpc-plugin/grpc-server/grpc-server 16 | kafka-lib/asyncproducer/asyncproducer 17 | kafka-lib/consumer/consumer 18 | kafka-lib/mux/mux 19 | kafka-lib/syncproducer/syncproducer 20 | kafka-plugin/hash-partitioner/hash-partitioner 21 | kafka-plugin/manual-partitioner/manual-partitioner 22 | kafka-plugin/post-init-consumer/post-init-consumer 23 | logs-lib/basic/basic 24 | logs-lib/custom/custom 25 | logs-lib/http/http 26 | logs-plugin/logs-plugin 27 | process-manager-plugin/basic-scenario/basic-scenario 28 | process-manager-plugin/advanced-scenario/advanced-scenario 29 | process-manager-plugin/templates/templates 30 | process-manager-plugin/test-process/test-process 31 | redis-lib/airport/airport-linux 32 | redis-lib/simple/simple-linux 33 | redis-lib/airport/airport 34 | redis-lib/simple/simple 35 | redis-plugin/redis-plugin 36 | simple-agent/simple-agent 37 | statuscheck-plugin/statuscheck-plugin 38 | supervisor-plugin/supervisor-plugin 39 | prometheus-plugin/prometheus-plugin 40 | tutorials/01_hello-world/01_hello-world 41 | tutorials/02_plugin-deps/02_plugin-deps 42 | tutorials/03_rest-handler/03_rest-handler 43 | tutorials/04_kv-store/04_kv-store 44 | tutorials/06_plugin_lookup/06_plugin_lookup 45 | -------------------------------------------------------------------------------- /examples/bolt-plugin/README.md: -------------------------------------------------------------------------------- 1 | # bolt-plugin 2 | 3 | A simple example demonstrating how to create a Bolt plugin. 4 | 5 | ### Usage 6 | 7 | To run the example, type: 8 | ``` 9 | go run main.go deps.go [-bolt-config ] 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/bolt-plugin/bolt.conf: -------------------------------------------------------------------------------- 1 | # Path to Bolt DB file 2 | db-path: /tmp/bolt.db 3 | 4 | # File's mode and permission bits in decimal format ... 432 = --rw-rw---- 5 | file-mode: 432 6 | 7 | # Timeout is the amount of time to wait to obtain a file lock 8 | # When set to zero it will wait indefinitely 9 | lock-timeout: 0 -------------------------------------------------------------------------------- /examples/bolt-plugin/doc.go: -------------------------------------------------------------------------------- 1 | // Example demonstrates creating a Bolt plugin 2 | package main 3 | -------------------------------------------------------------------------------- /examples/bolt-plugin/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | "go.ligato.io/cn-infra/v2/agent" 8 | "go.ligato.io/cn-infra/v2/db/keyval" 9 | "go.ligato.io/cn-infra/v2/db/keyval/bolt" 10 | "go.ligato.io/cn-infra/v2/logging" 11 | ) 12 | 13 | const pluginName = "bolt-example" 14 | 15 | func main() { 16 | example := &BoltExample{ 17 | Log: logging.ForPlugin(pluginName), 18 | DB: &bolt.DefaultPlugin, 19 | finished: make(chan struct{}), 20 | } 21 | 22 | a := agent.NewAgent( 23 | agent.AllPlugins(example), 24 | agent.QuitOnClose(example.finished), 25 | ) 26 | if err := a.Run(); err != nil { 27 | log.Fatal(err) 28 | } 29 | } 30 | 31 | // BoltExample demonstrates the usage of Bolt plugin. 32 | type BoltExample struct { 33 | Log logging.PluginLogger 34 | DB keyval.KvProtoPlugin 35 | 36 | finished chan struct{} 37 | } 38 | 39 | // Init demonstrates using Bolt plugin. 40 | func (p *BoltExample) Init() (err error) { 41 | db := p.DB.NewBroker(keyval.Root) 42 | 43 | // Store some data 44 | txn := db.NewTxn() 45 | txn.Put("/agent/config/interface/iface0", nil) 46 | txn.Put("/agent/config/interface/iface1", nil) 47 | txn.Commit(context.Background()) 48 | 49 | // List keys 50 | const listPrefix = "/agent/config/interface/" 51 | 52 | p.Log.Infof("List BoltDB keys: %s", listPrefix) 53 | 54 | keys, err := db.ListKeys(listPrefix) 55 | if err != nil { 56 | p.Log.Fatal(err) 57 | } 58 | 59 | for { 60 | key, val, all := keys.GetNext() 61 | if all == true { 62 | break 63 | } 64 | 65 | p.Log.Infof("Key: %q Val: %v", key, val) 66 | } 67 | 68 | return nil 69 | } 70 | 71 | // AfterInit closes the example. 72 | func (p *BoltExample) AfterInit() (err error) { 73 | close(p.finished) 74 | return nil 75 | } 76 | 77 | // Close frees plugin resources. 78 | func (p *BoltExample) Close() error { 79 | return nil 80 | } 81 | 82 | // String returns name of plugin. 83 | func (p *BoltExample) String() string { 84 | return pluginName 85 | } 86 | -------------------------------------------------------------------------------- /examples/cassandra-lib/Readme.md: -------------------------------------------------------------------------------- 1 | # Simple Cassandra example 2 | 3 | To start the example, you need to connect to a Cassandra database. 4 | If you don't have one running, you can start the following docker image 5 | on your localhost: 6 | 7 | ``` 8 | sudo docker run -p 9042:9042 --name cassandra01 -d cassandra:latest 9 | ``` 10 | 11 | In the example, the configuration for the connection to the cassandra 12 | is configured in a yaml-formatted config file. The config file is specified 13 | as the first CLI argument: 14 | 15 | ``` 16 | go run main.go 17 | ``` 18 | 19 | To run the example with the provided default configuration, type: 20 | 21 | ``` 22 | go run main.go ./client-config.yaml 23 | ``` 24 | -------------------------------------------------------------------------------- /examples/cassandra-lib/client-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | endpoints: 3 | - 127.0.0.1:9042 4 | op_timeout: 5000000000 # 5 seconds (creating a new keyspace is slow on travis) 5 | dial_timeout: 3000000000 # 3 seconds 6 | redial_interval: 60000000000 # 60 seconds 7 | protocol_version: 4 8 | tls: 9 | cert_path: "" 10 | ca_path: "" 11 | enable_host_verification: false 12 | key_path: "" 13 | enabled: false 14 | -------------------------------------------------------------------------------- /examples/cassandra-lib/doc.go: -------------------------------------------------------------------------------- 1 | // Example application "cassandra-lib" demonstrates the usage of the cassandra 2 | // library in a plain go program. 3 | package main 4 | -------------------------------------------------------------------------------- /examples/configs-plugin/Readme.md: -------------------------------------------------------------------------------- 1 | # Configs example 2 | 3 | To run the example, type: 4 | ``` 5 | go run main.go deps.go [--config-dir=] [--example-config=] 6 | ``` 7 | 8 | By default `config-dir=.` and `example-config=example.conf`, 9 | hence the attached `example.conf` is loaded. 10 | 11 | -------------------------------------------------------------------------------- /examples/configs-plugin/doc.go: -------------------------------------------------------------------------------- 1 | // Example program "configs-plugin" demonstrates the usage of PluginConfig API. 2 | package main 3 | -------------------------------------------------------------------------------- /examples/configs-plugin/example.conf: -------------------------------------------------------------------------------- 1 | field1: external value 2 | sleep: 1s -------------------------------------------------------------------------------- /examples/cryptodata-lib/key-pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5zyUN79vuKTr+3N+sE5A 3 | n3+rOzrF1pI+/WTn9sMRJeTkqJm7hhR/es93CsVpgs4KM1sJtPr68daOvUrJBbBK 4 | n3tXtWE+Z/BM8SRfNwnnK7PTlHW4V7jmQBB1PnNtOOjsm1wriXbY8SIp/a29gQoq 5 | CSEyatsgALmdcEThJia503IQkEllu/myngyJpk285d/K53uVz+ffcjHvcnDhdVqx 6 | 0qcUiMg0FrnCoSzjfVEZ5FrPtXkcOlgPFR2Rwhxrtwmbdzzoc4e+S5JNIOuS9nHZ 7 | YCqRfWvBlh24aD5wOHHPhHMDbv9bumtU/q8+291mJ4y67gxVWH3+Mnlm/qLHKRPP 8 | GwIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /examples/cryptodata-lib/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEA5zyUN79vuKTr+3N+sE5An3+rOzrF1pI+/WTn9sMRJeTkqJm7 3 | hhR/es93CsVpgs4KM1sJtPr68daOvUrJBbBKn3tXtWE+Z/BM8SRfNwnnK7PTlHW4 4 | V7jmQBB1PnNtOOjsm1wriXbY8SIp/a29gQoqCSEyatsgALmdcEThJia503IQkEll 5 | u/myngyJpk285d/K53uVz+ffcjHvcnDhdVqx0qcUiMg0FrnCoSzjfVEZ5FrPtXkc 6 | OlgPFR2Rwhxrtwmbdzzoc4e+S5JNIOuS9nHZYCqRfWvBlh24aD5wOHHPhHMDbv9b 7 | umtU/q8+291mJ4y67gxVWH3+Mnlm/qLHKRPPGwIDAQABAoIBADp4uxINunZ6XaHL 8 | 5rE2WGj8o5PqnLRRbtQse+uOD/wBEUEA/sY80K+BXpy+ppuI9lNeJeo5vNMCaj27 9 | d3GUzondaqRW3qzxusMPa3RDcM1AP7Q+wEqOWsrAXqVYErpdS9dNS0ULZHg1J2Ea 10 | Wd0TcOW2G0Wh+0mzpfgJstUu3bZ1mkQoCyfQ1h7c5pzYUlllCLY6rMN8CSDURKBp 11 | fli37S9lfVvcI0r//3gpxxQLrKcSWWhNT44XSnqk9bxHPTJAQ6c99Hw38ZcujauM 12 | gXZxhpKGOTuQOI444JhDXvGiNanZPIztlkd2Fnx4S9xgVRmlWZTQidEo4dVFpjXx 13 | rUZNwKECgYEA/uwVdACLNZ/OEdXuMF1XchUQix0Kr4UQ4vPyhYikBzZ6cUg89BJH 14 | OwQqmqOIcpInBjetnC2TkvzJKtmt2vR3b7E8O+o1XpZvWx9kS0BA7P44S/4FTmLs 15 | HAxKXQ0aFMGV9oT0FMI4fqOKLcpFjCk7hJtChnUgQ/yrSzLDY8VEYc8CgYEA6Dbb 16 | 5xs1LZisvftFy2j3icWTOLMZTOSUk0+/Mm3CgDteTlSaVxQnOu2gey6kXxtY6oIz 17 | rpZ0pFpUxFEXO2dYTiMI9UroAO8ITN42UX2rAbMgnlNSHnJiQjBEifpTGyd55pIF 18 | S7YTmlFG7ErupSGvhGTMbK0Sa3SH7AnJ9XbLjPUCgYEAuR7oVV0vurlaBEm+txCR 19 | uB7j7KIiaGPRZ36P17jqpPJC6JD08qlzYMAd0D6Bj/HitPkp8giG6m74B04cmqx9 20 | L3cdrsTeDNph82JQivUWMQRMDaNiZxIfNB8YwYoKLpiGNodGWOzR6eUJK0eASdCH 21 | kDzPiqTz0WtjWTB8A6/1gLECgYBB/GzKpEmdNlhH+CIiJibJSJKINySGXCH4Jl4f 22 | d18gzz4CJjphakGnliTXPC7LM9s1cGA9SVXF6kFSM/TVFY3bTktaYLnCoioKpc5r 23 | o7k3V256bxTTwA853btsNeztt28FXRMSK6AwZs4vkS91Tzgv9/C7JQcp78g8A6AX 24 | F3XKDQKBgQC6lg3EQR/TpD3DNjVkvAXeCnC1TgmBWU+8PjweevxUwrQr9GjcJwIh 25 | zV074r2r+p7C66Hu3n6+4pq9Oj7fTykZ+VoxXjBUlQPEMYaN5vQj0qgMfRqxUxXs 26 | 4qVLnq+Lf6c0KrjVqEAnuzJhjqWcfHTN05HesKnW+ywQpG9PxwQXHQ== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /examples/cryptodata-plugin/cryptodata.conf: -------------------------------------------------------------------------------- 1 | private-key-files: 2 | - ../cryptodata-lib/key.pem 3 | -------------------------------------------------------------------------------- /examples/cryptodata-plugin/doc.go: -------------------------------------------------------------------------------- 1 | // Example application "cryptodata-plugin" demonstrates the usage of the cryptodata 2 | // API. etcd plugin is used as the backend, adapted to the cryptodata API 3 | // by the cryptodata plugin in a custom-defined flavor. 4 | package main 5 | -------------------------------------------------------------------------------- /examples/cryptodata-plugin/etcd.conf: -------------------------------------------------------------------------------- 1 | insecure-transport: true 2 | dial-timeout: 1s 3 | endpoints: 4 | - "127.0.0.1:2379" 5 | -------------------------------------------------------------------------------- /examples/cryptodata-proto-plugin/cryptodata.conf: -------------------------------------------------------------------------------- 1 | private-key-files: 2 | - ../cryptodata-lib/key.pem 3 | -------------------------------------------------------------------------------- /examples/cryptodata-proto-plugin/doc.go: -------------------------------------------------------------------------------- 1 | // Example application "cryptodata-proto-plugin" demonstrates the usage of the cryptodata 2 | // API. etcd plugin is used as the backend, adapted to the cryptodata API 3 | // by the cryptodata plugin in a custom-defined flavor. 4 | package main 5 | -------------------------------------------------------------------------------- /examples/cryptodata-proto-plugin/etcd.conf: -------------------------------------------------------------------------------- 1 | insecure-transport: true 2 | dial-timeout: 1s 3 | endpoints: 4 | - "127.0.0.1:2379" 5 | -------------------------------------------------------------------------------- /examples/cryptodata-proto-plugin/ipsec/keys.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package ipsec 16 | 17 | // Prefixes 18 | const ( 19 | // KeyPrefix is the relative key prefix for IPSec 20 | KeyPrefix = "vpp/config/v1/ipsec/" 21 | // KeyPrefixSPD is the relative key prefix for IPSec's Security Policy Databases 22 | KeyPrefixSPD = KeyPrefix + "spd/" 23 | // KeyPrefixSA is the relative key prefix for IPSec's Security Associations 24 | KeyPrefixSA = KeyPrefix + "sa/" 25 | // KeyPrefixTunnel is the relative key prefix for IPSec's Tunnel Interface 26 | KeyPrefixTunnel = KeyPrefix + "tunnel/" 27 | ) 28 | 29 | // SPDKey returns key for Security Policy Database 30 | func SPDKey(name string) string { 31 | return KeyPrefixSPD + name 32 | } 33 | 34 | // SAKey returns key for Security Association 35 | func SAKey(name string) string { 36 | return KeyPrefixSA + name 37 | } 38 | 39 | // TunnelKey returns key for Tunnel Interface 40 | func TunnelKey(name string) string { 41 | return KeyPrefixTunnel + name 42 | } 43 | -------------------------------------------------------------------------------- /examples/datasync-plugin/Readme.md: -------------------------------------------------------------------------------- 1 | # DataSync example 2 | 3 | ### Requirements 4 | 5 | To start the example, you have to have the ETCD running first. 6 | Use the following command to pull the image and start the database: 7 | ``` 8 | sudo docker run -p 2379:2379 --name etcd --rm \ 9 | quay.io/coreos/etcd:v3.0.16 /usr/local/bin/etcd \ 10 | -advertise-client-urls http://0.0.0.0:2379 \ 11 | -listen-client-urls http://0.0.0.0:2379 12 | ``` 13 | 14 | It will bring up the ETCD listening on port 2379 for the client communication. 15 | 16 | ### Usage 17 | 18 | In the example, the location of the ETCD configuration file is defined 19 | with the `-etcd-config` argument or through the `ETCD_CONFIG` 20 | environment variable. By default, the application will try to search 21 | for `etcd.conf` in the current working directory. If the configuration 22 | file cannot be loaded or is not found, ETCD plugin tries to connect 23 | using default configuration. 24 | 25 | To run the example, type: 26 | ``` 27 | go run main.go deps.go [-etcd-config ] 28 | ``` 29 | 30 | -------------------------------------------------------------------------------- /examples/datasync-plugin/doc.go: -------------------------------------------------------------------------------- 1 | // Example application "datasync-plugin" demonstrates the usage of the datasync 2 | // API. etcd plugin is used as the backend, adapted to the datasync API 3 | // by the kvdbsync plugin in a custom-defined flavor. 4 | package main 5 | -------------------------------------------------------------------------------- /examples/datasync-plugin/etcd.conf: -------------------------------------------------------------------------------- 1 | insecure-transport: true 2 | dial-timeout: 1s 3 | endpoints: 4 | - "127.0.0.1:2379" 5 | -------------------------------------------------------------------------------- /examples/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package examples contains examples that demonstrate the usage of various 16 | // cn-infra components. 17 | package examples 18 | -------------------------------------------------------------------------------- /examples/etcd-lib/Makefile: -------------------------------------------------------------------------------- 1 | # generate go structures from proto files 2 | define generate_sources 3 | $(if $(shell command -v protoc --go_out=. 2> /dev/null),$(info golang/protobuf is installed),$(error golang/protobuf missing, please install it with go get github.com/golang/protobuf)) 4 | @echo "# generating sources" 5 | @cd model && go generate -x ./... 6 | endef 7 | 8 | all: generate build 9 | 10 | generate: 11 | $(call generate_sources) 12 | @echo "# done" 13 | 14 | clean: 15 | cd editor && go clean 16 | cd view && go clean 17 | cd watcher && go clean 18 | cd election && go clean 19 | 20 | build: 21 | cd view && go build 22 | cd editor && go build 23 | cd watcher && go build 24 | cd election && go build 25 | -------------------------------------------------------------------------------- /examples/etcd-lib/doc.go: -------------------------------------------------------------------------------- 1 | // Package etcdlib contains a collection of examples demonstrating 2 | // the usage of the etcd library. 3 | package etcdlib 4 | -------------------------------------------------------------------------------- /examples/etcd-lib/editor/doc.go: -------------------------------------------------------------------------------- 1 | // Example program "editor" demonstrates CREATE/UPDATE/DELETE operations with 2 | // etcd library. 3 | package main 4 | -------------------------------------------------------------------------------- /examples/etcd-lib/etcd.conf: -------------------------------------------------------------------------------- 1 | insecure-transport: true 2 | session-ttl: 10 3 | endpoints: 4 | - "172.17.0.1:2379" 5 | 6 | -------------------------------------------------------------------------------- /examples/etcd-lib/model/phonebook/config.go: -------------------------------------------------------------------------------- 1 | package phonebook 2 | 3 | import "strings" 4 | 5 | //go:generate protoc --proto_path=. --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. phonebook.proto 6 | 7 | // EtcdPath returns the base path were the phonebook records are stored. 8 | func EtcdPath() string { 9 | return "/phonebook/" 10 | } 11 | 12 | // EtcdContactPath returns the path for a given contact. 13 | func EtcdContactPath(contact *Contact) string { 14 | return EtcdPath() + strings.Replace(contact.Name, " ", "", -1) 15 | } 16 | -------------------------------------------------------------------------------- /examples/etcd-lib/model/phonebook/phonebook.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "go.ligato.io/cn-infra/v2/examples/etcd-lib/model/phonebook"; 4 | 5 | package phonebook; 6 | 7 | message Contact { 8 | string name = 1; 9 | string company = 2; 10 | string phonenumber = 3; 11 | } 12 | -------------------------------------------------------------------------------- /examples/etcd-lib/view/doc.go: -------------------------------------------------------------------------------- 1 | // Example program "view" shows how to read data from etcd datastore. 2 | package main 3 | -------------------------------------------------------------------------------- /examples/etcd-lib/watcher/doc.go: -------------------------------------------------------------------------------- 1 | // Example program *watcher* shows how to watch for changes in etcd datastore. 2 | package main 3 | -------------------------------------------------------------------------------- /examples/flags-lib/Readme.md: -------------------------------------------------------------------------------- 1 | # flags example 2 | 3 | To run the example, type: 4 | ``` 5 | go run main.go 6 | ``` 7 | 8 | Optionally, override default values of flags through the following CLI 9 | options: 10 | 11 | ``` 12 | --ep-string 13 | --ep-int 14 | --ep-int64 <64b-integer-value> 15 | --ep-uint 16 | --ep-uint64 17 | --ep-bool 18 | --ep-duration 19 | ``` -------------------------------------------------------------------------------- /examples/flags-lib/doc.go: -------------------------------------------------------------------------------- 1 | // Example program "flags-lib" demonstrates how to register CLI flags 2 | // and how to display their runtime values. 3 | package main 4 | -------------------------------------------------------------------------------- /examples/grpc-plugin/README.md: -------------------------------------------------------------------------------- 1 | # grpc-plugin 2 | 3 | Start the `grpc-server` example typing following in the grpc-server folder: 4 | ``` 5 | go run main.go 6 | ``` 7 | 8 | In order to pass custom configuration file (for example the `grpc.conf` located in the same directory), start grpc-server with following parameter: 9 | ``` 10 | go run main --grpc-config= 11 | ``` 12 | Note: `main.go` must be edited in this case because it makes use of the direct config injection via `grpc.UseConf` method, which overrides any provided config file. To enable it, remove method mentioned. 13 | 14 | Start the `grpc-client` exampl typing following in the grpc-client folder: 15 | ``` 16 | go run main.go 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /examples/grpc-plugin/doc.go: -------------------------------------------------------------------------------- 1 | // Package grpcplugin contains grpc server & grpc client example. 2 | package grpcplugin 3 | -------------------------------------------------------------------------------- /examples/grpc-plugin/grpc-client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | "golang.org/x/net/context" 7 | "google.golang.org/grpc" 8 | "google.golang.org/grpc/credentials" 9 | pb "google.golang.org/grpc/examples/helloworld/helloworld" 10 | 11 | "go.ligato.io/cn-infra/v2/examples/grpc-plugin/insecure" 12 | "go.ligato.io/cn-infra/v2/logging/logrus" 13 | ) 14 | 15 | const ( 16 | defaultAddress = "localhost:9111" 17 | defaultName = "world" 18 | ) 19 | 20 | var address = defaultAddress 21 | var name = defaultName 22 | 23 | func main() { 24 | flag.StringVar(&address, "address", defaultAddress, "address of GRPC server") 25 | flag.StringVar(&name, "name", defaultName, "name used in GRPC request") 26 | flag.Parse() 27 | 28 | // Set up a connection to the server. 29 | conn, err := grpc.Dial(address, 30 | //grpc.WithInsecure(), 31 | grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(insecure.CertPool, "")), 32 | grpc.WithPerRPCCredentials(tokenAuth{ 33 | token: "testtoken", 34 | }), 35 | ) 36 | 37 | if err != nil { 38 | logrus.DefaultLogger().Fatalf("did not connect: %v", err) 39 | } 40 | defer conn.Close() 41 | c := pb.NewGreeterClient(conn) 42 | 43 | r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name}) 44 | if err != nil { 45 | logrus.DefaultLogger().Fatalf("could not greet: %v", err) 46 | } 47 | logrus.DefaultLogger().Printf("Reply: %s (received from server)", r.Message) 48 | } 49 | 50 | type tokenAuth struct { 51 | token string 52 | } 53 | 54 | func (t tokenAuth) GetRequestMetadata(ctx context.Context, in ...string) (map[string]string, error) { 55 | return map[string]string{ 56 | "authorization": "Bearer " + t.token, 57 | }, nil 58 | } 59 | 60 | func (tokenAuth) RequireTransportSecurity() bool { 61 | return true 62 | } 63 | -------------------------------------------------------------------------------- /examples/grpc-plugin/grpc-server/doc.go: -------------------------------------------------------------------------------- 1 | // Example demonstrates the use of GRPC plugin API. 2 | package main 3 | -------------------------------------------------------------------------------- /examples/grpc-plugin/grpc-server/grpc.conf: -------------------------------------------------------------------------------- 1 | endpoint: "0.0.0.0:9111" 2 | extended-logging: true 3 | -------------------------------------------------------------------------------- /examples/kafka-lib/Makefile: -------------------------------------------------------------------------------- 1 | 2 | build: 3 | cd asyncproducer && go build -i 4 | cd consumer && go build -i 5 | cd syncproducer && go build -i 6 | cd mux && go build -i 7 | 8 | clean: 9 | rm -f asyncproducer/asyncproducer 10 | rm -f consumer/consumer 11 | rm -f syncproducer/syncproducer 12 | rm -f mux/mux -------------------------------------------------------------------------------- /examples/kafka-lib/asyncproducer/doc.go: -------------------------------------------------------------------------------- 1 | // Asyncproducer is a simple command line tool for sending messages to Kafka 2 | // using an asynchronous Kafka producer. 3 | package main 4 | -------------------------------------------------------------------------------- /examples/kafka-lib/consumer/README.md: -------------------------------------------------------------------------------- 1 | # kafka-lib Consumer 2 | 3 | A simple command line tool for consuming Kafka topic and printing 4 | the received messages to the stdout. 5 | 6 | ### Requirements 7 | 8 | To start the example you have to have Kafka broker running first. 9 | if you don't have it installed locally you can use the following docker 10 | image. 11 | ``` 12 | sudo docker run -p 2181:2181 -p 9092:9092 --name kafka --rm \ 13 | --env ADVERTISED_HOST=172.17.0.1 --env ADVERTISED_PORT=9092 spotify/kafka 14 | ``` 15 | 16 | It will bring up Kafka broker listening on port 9092 for client 17 | communication (suitable for quickstart). 18 | 19 | ### Usage 20 | 21 | - Quick-start: 22 | ``` 23 | go run consumer.go -topics=test -groupid=mygroup -brokers=localhost:9092 24 | ``` 25 | 26 | - In order to configure addresses of kafka brokers, an environment 27 | variable `KAFKA_PEERS` can be used instead: 28 | ``` 29 | export KAFKA_PEERS=kafka1:9092,kafka2:9092,kafka3:9092 30 | go run consumer.go --topics=test -groupid=mygroup 31 | ``` 32 | 33 | - In order to configure kafka brokers an environment variable can be used: 34 | ``` 35 | export KAFKA_PEERS=kafka1:9092,kafka2:9092,kafka3:9092 36 | go run consumer.go --topics=test -groupid=mygroup 37 | ``` 38 | 39 | - You can specify the offset you want to start consuming at. 40 | It can be either `oldest` or `newest`. The default is `newest`. 41 | ``` 42 | go run consumer.go -topics=test -groupid=mygroup -offset=oldest 43 | go run consumer.go -topics=test -groupid=mygroup -offset=newest 44 | ``` 45 | 46 | - You can specify the partition(s) you want to consume as a comma-separated 47 | list. The default is `all`. 48 | ``` 49 | go run consumer.go -topic=test -groupid=mygroup -partitions=1,2,3 50 | ``` 51 | 52 | - To display all command line options, type: 53 | ``` 54 | go run consumer.go -help 55 | ``` -------------------------------------------------------------------------------- /examples/kafka-lib/consumer/doc.go: -------------------------------------------------------------------------------- 1 | // Consumer is a simple command line tool for consuming a Kafka topic 2 | // and printing the received messages to the stdout. 3 | package main 4 | -------------------------------------------------------------------------------- /examples/kafka-lib/doc.go: -------------------------------------------------------------------------------- 1 | // Package kafkalib contains multiple examples with the kafka library. 2 | package kafkalib 3 | -------------------------------------------------------------------------------- /examples/kafka-lib/mux/README.md: -------------------------------------------------------------------------------- 1 | # kafka-lib Multiplexer 2 | 3 | A simple command line tool demonstrating the usage of Kafka multiplexer 4 | API which allows to create multiple producers and consumers sharing 5 | the minimal number of connections needed. 6 | 7 | ### Requirements 8 | 9 | To start the example you have to have Kafka broker running first. 10 | if you don't have it installed locally you can use the following docker 11 | image. 12 | ``` 13 | sudo docker run -p 2181:2181 -p 9092:9092 --name kafka --rm \ 14 | --env ADVERTISED_HOST=172.17.0.1 --env ADVERTISED_PORT=9092 spotify/kafka 15 | ``` 16 | 17 | It will bring up Kafka broker listening on port 9092 for client 18 | communication (suitable for quickstart). 19 | 20 | ### Usage 21 | 22 | Quick-start: 23 | ``` 24 | go run main.go [-config=] 25 | ``` 26 | 27 | By default, it is assumed that Kafka broker is running on 127.0.0.1:9092. 28 | You may change the broker address or even specify multiple (clustered) 29 | brokers in a YAML configuration file, selected with the CLI option 30 | `-config`. See the attached `config` file with an example configuration. -------------------------------------------------------------------------------- /examples/kafka-lib/mux/config: -------------------------------------------------------------------------------- 1 | addrs: 2 | - "127.0.0.1:9092" 3 | - "127.0.0.1:9093" 4 | - "127.0.0.1:9094" 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/kafka-lib/mux/doc.go: -------------------------------------------------------------------------------- 1 | // Mux is a simple command line tool demonstrating the usage of Kafka 2 | // multiplexer API. 3 | package main 4 | -------------------------------------------------------------------------------- /examples/kafka-lib/syncproducer/doc.go: -------------------------------------------------------------------------------- 1 | // Syncproducer is simple command line tool for sending messages to Kafka using 2 | // a synchronous Kafka producer. 3 | package main 4 | -------------------------------------------------------------------------------- /examples/kafka-lib/utils/doc.go: -------------------------------------------------------------------------------- 1 | // Package utils implements various tools used in examples for Kafka library. 2 | package utils 3 | -------------------------------------------------------------------------------- /examples/kafka-plugin/doc.go: -------------------------------------------------------------------------------- 1 | // Package kafkaplugin contains multiple examples with the kafka plugin. 2 | package kafkaplugin 3 | -------------------------------------------------------------------------------- /examples/kafka-plugin/hash-partitioner/README.md: -------------------------------------------------------------------------------- 1 | # kafka-plugin Hash-Partitioner 2 | 3 | A simple example demonstrating the usage of the Kafka plugin API with 4 | the automatic (hash-based) partitioning. 5 | 6 | ### Requirements 7 | 8 | To start the example, you have to have the Kafka broker running first. 9 | if you don't have it installed locally you can use the following docker 10 | image: 11 | ``` 12 | sudo docker run -p 2181:2181 -p 9092:9092 --name kafka --rm \ 13 | --env ADVERTISED_HOST=172.17.0.1 --env ADVERTISED_PORT=9092 spotify/kafka 14 | ``` 15 | 16 | It will bring up the Kafka broker listening on port 9092 for client 17 | communication. 18 | 19 | ### Usage 20 | 21 | To run the example, type: 22 | ``` 23 | go run main.go deps.go [-kafka-config ] 24 | ``` 25 | 26 | If `kafka-config` is unspecified, the application will try to search 27 | for `kafka.conf` in the current working directory. 28 | If the configuration file cannot be loaded or is not defined, default 29 | configuration will be used. 30 | -------------------------------------------------------------------------------- /examples/kafka-plugin/hash-partitioner/doc.go: -------------------------------------------------------------------------------- 1 | // Example "hash-partitioner" demonstrates the use of Kafka plugin API 2 | // with automatic (hash-based) partitioning. 3 | package main 4 | -------------------------------------------------------------------------------- /examples/kafka-plugin/hash-partitioner/kafka.conf: -------------------------------------------------------------------------------- 1 | addrs: 2 | - "127.0.0.1:9092" 3 | group-id: custom-group-id 4 | -------------------------------------------------------------------------------- /examples/kafka-plugin/manual-partitioner/README.md: -------------------------------------------------------------------------------- 1 | # kafka-plugin Manual-Partitioner 2 | 3 | A simple example demonstrating the usage of Kafka plugin API with 4 | a focus on manual partitioning. 5 | 6 | ### Requirements 7 | 8 | To start the example you have to have Kafka broker running first. 9 | Furthermore, the example assumes that each auto-created topic has 10 | at least 3 partitions (`num.partitions` >= 3 in `server.properties`). 11 | 12 | If you don't have Kafka installed locally, you can use the following 13 | docker image in combination with a prepared `server.properties` config 14 | file: 15 | ``` 16 | sudo docker create -p 2181:2181 -p 9092:9092 --name kafka --rm \ 17 | --env ADVERTISED_HOST=172.17.0.1 --env ADVERTISED_PORT=9092 spotify/kafka 18 | KAFKA_VERSION=$(docker inspect -f '{{ .Config.Env }}' kafka | tr ' ' '\n' | grep KAFKA_VERSION | sed 's/^.*=//') 19 | SCALA_VERSION=$(docker inspect -f '{{ .Config.Env }}' kafka | tr ' ' '\n' | grep SCALA_VERSION | sed 's/^.*=//') 20 | sudo docker cp server.properties kafka:/opt/kafka_${SCALA_VERSION}-${KAFKA_VERSION}/config/server.properties 21 | sudo docker start kafka 22 | ``` 23 | 24 | It will bring up Kafka broker listening on port 9092 for client 25 | communication. 26 | 27 | 28 | ### Usage 29 | 30 | To run the example, type: 31 | ``` 32 | go run main.go deps.go [-kafka-config ] 33 | ``` 34 | 35 | If `kafka-config` is unspecified, the application will try to search 36 | for `kafka.conf` in the current working directory. 37 | If the configuration file cannot be loaded or is not defined, default 38 | configuration will be used. 39 | -------------------------------------------------------------------------------- /examples/kafka-plugin/manual-partitioner/doc.go: -------------------------------------------------------------------------------- 1 | // Example "manual-partitioner" demonstrates the use of Kafka plugin API with 2 | // a focus on manual partitioning. 3 | package main 4 | -------------------------------------------------------------------------------- /examples/kafka-plugin/manual-partitioner/kafka.conf: -------------------------------------------------------------------------------- 1 | addrs: 2 | - "127.0.0.1:9092" 3 | -------------------------------------------------------------------------------- /examples/kafka-plugin/manual-partitioner/server.properties: -------------------------------------------------------------------------------- 1 | broker.id=0 2 | num.network.threads=3 3 | num.io.threads=8 4 | socket.send.buffer.bytes=102400 5 | socket.receive.buffer.bytes=102400 6 | socket.request.max.bytes=104857600 7 | log.dirs=/tmp/kafka-logs 8 | 9 | # The example requires at least 3 partitions per topic. 10 | num.partitions=3 11 | 12 | num.recovery.threads.per.data.dir=1 13 | log.retention.hours=168 14 | log.segment.bytes=1073741824 15 | log.retention.check.interval.ms=300000 16 | zookeeper.connect=localhost:2181 17 | zookeeper.connection.timeout.ms=6000 18 | -------------------------------------------------------------------------------- /examples/kafka-plugin/post-init-consumer/README.md: -------------------------------------------------------------------------------- 1 | # kafka-plugin Post-init consumer 2 | 3 | A simple example demonstrating the usage of Kafka plugin API 4 | where consumer is started after the message producer. 5 | 6 | ### Requirements 7 | 8 | To start the example you have to have Kafka broker running first. 9 | Furthermore, the example assumes that each auto-created topic has 10 | at least 3 partitions (`num.partitions` >= 3 in `server.properties`). 11 | 12 | If you don't have Kafka installed locally, you can use the following 13 | docker image in combination with a prepared `server.properties` config 14 | file: 15 | ``` 16 | sudo docker create -p 2181:2181 -p 9092:9092 --name kafka --rm \ 17 | --env ADVERTISED_HOST=172.17.0.1 --env ADVERTISED_PORT=9092 spotify/kafka 18 | KAFKA_VERSION=$(docker inspect -f '{{ .Config.Env }}' kafka | tr ' ' '\n' | grep KAFKA_VERSION | sed 's/^.*=//') 19 | SCALA_VERSION=$(docker inspect -f '{{ .Config.Env }}' kafka | tr ' ' '\n' | grep SCALA_VERSION | sed 's/^.*=//') 20 | sudo docker cp server.properties kafka:/opt/kafka_${SCALA_VERSION}-${KAFKA_VERSION}/config/server.properties 21 | sudo docker start kafka 22 | ``` 23 | 24 | It will bring up Kafka broker listening on port 9092 for client 25 | communication. 26 | 27 | 28 | ### Usage 29 | 30 | To run the example, type: 31 | ``` 32 | go run main.go deps.go [-kafka-config ] 33 | ``` 34 | 35 | If `kafka-config` is unspecified, the application will try to search 36 | for `kafka.conf` in the current working directory. 37 | If the configuration file cannot be loaded or is not defined, default 38 | configuration will be used. 39 | -------------------------------------------------------------------------------- /examples/kafka-plugin/post-init-consumer/doc.go: -------------------------------------------------------------------------------- 1 | // Example "later-stage" demonstrates the use partition watcher 2 | // initialized and used after multiplexer Init() 3 | package main 4 | -------------------------------------------------------------------------------- /examples/kafka-plugin/post-init-consumer/kafka.conf: -------------------------------------------------------------------------------- 1 | addrs: 2 | - "127.0.0.1:9092" 3 | -------------------------------------------------------------------------------- /examples/logs-lib/Makefile: -------------------------------------------------------------------------------- 1 | 2 | clean: 3 | rm -f basic/basic 4 | rm -f custom/custom 5 | rm -f http/http 6 | 7 | build: 8 | cd basic && go build -i 9 | cd custom && go build -i 10 | cd http && go build -i -------------------------------------------------------------------------------- /examples/logs-lib/basic/REDME.md: -------------------------------------------------------------------------------- 1 | # Logs-lib Basic Example 2 | 3 | To run the example, simply type: 4 | ``` 5 | go run basic.go 6 | ``` 7 | 8 | -------------------------------------------------------------------------------- /examples/logs-lib/basic/basic.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "go.ligato.io/cn-infra/v2/logging" 19 | "go.ligato.io/cn-infra/v2/logging/logrus" 20 | ) 21 | 22 | var logger logging.Logger 23 | 24 | func init() { 25 | logger = logrus.DefaultLogger() 26 | logger.SetLevel(logging.DebugLevel) 27 | } 28 | 29 | func main() { 30 | defer func() { 31 | err := recover() 32 | if err != nil { 33 | logger.WithFields(logging.Fields{ 34 | "omg": true, 35 | "err": err, 36 | "number": 100, 37 | }).Fatal("The ice breaks!") 38 | } 39 | }() 40 | 41 | logger.WithFields(logging.Fields{ 42 | "animal": "walrus", 43 | "number": 8, 44 | }).Debug("Started observing beach") 45 | 46 | logger.WithFields(logging.Fields{ 47 | "animal": "walrus", 48 | "size": 10, 49 | }).Info("A group of walrus emerges from the ocean") 50 | 51 | logger.WithFields(logging.Fields{ 52 | "omg": true, 53 | "number": 122, 54 | }).Warn("The group's number increased tremendously!") 55 | 56 | logger.WithFields(logging.Fields{ 57 | "temperature": -4, 58 | }).Debug("Temperature changes") 59 | 60 | logger.WithFields(logging.Fields{ 61 | "animal": "orca", 62 | "size": 9009, 63 | }).Panic("It's over 9000!") 64 | } 65 | -------------------------------------------------------------------------------- /examples/logs-lib/basic/doc.go: -------------------------------------------------------------------------------- 1 | // Example "basic" presents the most commonly used APIs of the logger library. 2 | package main 3 | -------------------------------------------------------------------------------- /examples/logs-lib/doc.go: -------------------------------------------------------------------------------- 1 | // Package logslib contains multiple examples showing how to use the logger 2 | // library with a focus on switching between the log levels. 3 | package logslib 4 | -------------------------------------------------------------------------------- /examples/logs-lib/http/README.md: -------------------------------------------------------------------------------- 1 | # Logs-lib HTTP Example 2 | 3 | To run the example, simply type: 4 | ``` 5 | go run server.go 6 | ``` 7 | 8 | List all registered loggers and their current log level via HTTP GET: 9 | ``` 10 | curl localhost:8080/list 11 | ``` 12 | 13 | Modify log level remotely via HTTP POST: 14 | ``` 15 | curl -X PUT localhost:8080/set/{loggerName}/{logLevel} 16 | ``` 17 | 18 | Example of setting log level for custom and default loggers: 19 | ``` 20 | curl -X PUT localhost:8080/set/MyLogger/debug 21 | curl -X PUT localhost:8080/set/defaultLogger/debug 22 | ``` -------------------------------------------------------------------------------- /examples/logs-lib/http/doc.go: -------------------------------------------------------------------------------- 1 | // Example "http" demonstrates how to change the log level remotely via REST. 2 | package main 3 | -------------------------------------------------------------------------------- /examples/logs-plugin/README.md: -------------------------------------------------------------------------------- 1 | # Logs-plugin Example 2 | 3 | To run the example, simply type: 4 | ``` 5 | go run main.go deps.go 6 | ``` 7 | 8 | -------------------------------------------------------------------------------- /examples/logs-plugin/doc.go: -------------------------------------------------------------------------------- 1 | // Example "logs-plugin" shows how to use the logger library from a simple plugin. 2 | package main 3 | -------------------------------------------------------------------------------- /examples/logs-plugin/logs.conf: -------------------------------------------------------------------------------- 1 | default-level: debug 2 | loggers: 3 | # - name: "defaultLogger" 4 | # level: info 5 | - name: "example" 6 | level: debug 7 | - name: "examplechildLogger" 8 | level: debug 9 | hooks: 10 | syslog: 11 | levels: 12 | - panic 13 | - error 14 | - warn 15 | # custom: 16 | # addres: localhost 17 | # levels: 18 | # - panic 19 | 20 | -------------------------------------------------------------------------------- /examples/model/README.md: -------------------------------------------------------------------------------- 1 | ### Protobuf Messages and Go Data Structures 2 | The Agent build tools support easy integration of protobuf data format 3 | definitions into your program. 4 | 5 | 1. Define your data formats as a set of messages in a google protobuf 6 | file. For a simple example, see `examples/model/example.proto`. 7 | 1. In the plugin's main file (for example, `etcd/main.go`), add 8 | the following line at the top of the file: 9 | ```apple js 10 | // go:generate protoc --proto_path=examples/model --go_out=examples/model examples/model/example.proto 11 | ``` 12 | 3. You can have multiple files with protobuf message definitions. Add a 13 | similar line for each file. 14 | 3. The above line will instruct the go tool to use the `protoc` code 15 | generator to generate go structures from protobuf messages defined in 16 | the [`example.proto`](example.proto) file. The line also specifies 17 | the path to the file and the location where to put the generated 18 | structures (in our example, all are the same, `examples/model`). 19 | 1. Do `make generate` to generate go structures from protobuf message 20 | definitions. The structures will be put into 21 | [`example.pb.go`](example.pb.go) in the same folder. 22 | The structures will be annotated with protobuf annotations to support 23 | marshalling/un-marshalling at run-time. 24 | 25 | You can now use the generated go structures in your code. 26 | -------------------------------------------------------------------------------- /examples/model/doc.go: -------------------------------------------------------------------------------- 1 | // Package etcdexample explains how to generate Golang structures from 2 | // protobuf-formatted data. 3 | package etcdexample 4 | 5 | //go:generate protoc --proto_path=. --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. example.proto 6 | -------------------------------------------------------------------------------- /examples/model/example.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "go.ligato.io/cn-infra/v2/examples/model;etcdexample"; 4 | 5 | package etcdexample; /* Generated code will be in the ectd_example package*/ 6 | 7 | message EtcdExample { 8 | string string_val = 1; /* Example of a string value */ 9 | uint32 uint32_val = 2; /* Example of a uint32 value */ 10 | bool bool_val = 3; /* Example of a bool value */ 11 | 12 | message structExample { /* Example of a structure */ 13 | string val1 = 1; 14 | uint32 val2 = 2; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/process-manager-plugin/README.md: -------------------------------------------------------------------------------- 1 | # Process manager example 2 | 3 | The example is divided into three scenarios: 4 | * **basic-scenario:** simple process managing like creating a process, start, stop, restart or status watching 5 | * **advanced-scenario:** status handling as attaching to running processes, reading of process status file 6 | or automatic restarts 7 | * **templates:** example how to create and use the process template 8 | 9 | All the examples use [test-application](test-process/test-process.go) called test-process, which is managed during 10 | the example. 11 | 12 | Note: in order to run the example which handles templates, process manager config file needs to be provided 13 | to the example, otherwise it will be skipped. 14 | 15 | ``` 16 | ./process-manager-plugin -process-manager-config= 17 | ``` 18 | 19 | All about process manager config file can be found in process manager [readme](../../process/README.md#Templates) 20 | 21 | -------------------------------------------------------------------------------- /examples/process-manager-plugin/test-process/test-process.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Test application just keeps running indefinitely, or for given time is defined 16 | // via parameter creating a running process. The purpose is to serve as a test 17 | // application for process manager example. 18 | 19 | package main 20 | 21 | import ( 22 | "time" 23 | 24 | "github.com/namsral/flag" 25 | 26 | "go.ligato.io/cn-infra/v2/logging/logrus" 27 | ) 28 | 29 | var log = logrus.DefaultLogger() 30 | var maxUptime = flag.Uint("max-uptime", 0, "Max uptime in seconds the test application can be running") 31 | 32 | func main() { 33 | flag.Parse() 34 | 35 | ta := &TestApp{} 36 | ta.run() 37 | } 38 | 39 | // TestApp is test application for process manager example 40 | type TestApp struct{} 41 | 42 | // Run ticker literally forever, or for given time if set 43 | func (ta *TestApp) run() { 44 | log.Info(">>> child >>> test application started") 45 | if *maxUptime != 0 { 46 | log.Infof(">>> child >>> max uptime set to %d second(s)", *maxUptime) 47 | } 48 | 49 | ticker := time.NewTicker(1 * time.Second) 50 | var uptime uint 51 | 52 | func() { 53 | for range ticker.C { 54 | uptime++ 55 | if uptime == *maxUptime { 56 | log.Info(">>> child >>> time's up, bye") 57 | return 58 | } 59 | } 60 | }() 61 | 62 | log.Info(">>> child >>> test application ended") 63 | return 64 | } 65 | -------------------------------------------------------------------------------- /examples/redis-lib/Makefile: -------------------------------------------------------------------------------- 1 | # generate go structures from proto files 2 | define generate_sources 3 | $(if $(shell command -v protoc --go_out=. 2> /dev/null),$(info golang/protobuf is installed),$(error golang/protobuf missing, please install it with go get github.com/golang/protobuf)) 4 | @echo "# generating sources" 5 | @cd airport && go generate -v 6 | endef 7 | 8 | all: generate build 9 | 10 | generate: 11 | $(call generate_sources) 12 | @echo "# done" 13 | 14 | clean: 15 | rm -f simple/simple 16 | rm -f simple/simple-linux 17 | rm -f airport/airport 18 | rm -f airport/airport-linux 19 | 20 | build: 21 | cd simple && go build -i 22 | cd airport && go build -i 23 | 24 | linux: ## build for linux 25 | @echo "building template (linux)" 26 | cd simple && env GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -i -o simple-linux 27 | cd airport && env GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -i -o airport-linux 28 | -------------------------------------------------------------------------------- /examples/redis-lib/airport/doc.go: -------------------------------------------------------------------------------- 1 | // A bit more advanced example demonstrating the redis library API. 2 | package main 3 | -------------------------------------------------------------------------------- /examples/redis-lib/airport/model/doc.go: -------------------------------------------------------------------------------- 1 | // Package flight defines protobuf-formatted data as used by the airport example. 2 | package flight 3 | -------------------------------------------------------------------------------- /examples/redis-lib/airport/model/flight.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "go.ligato.io/cn-infra/v2/examples/redis-lib-airport/model;flight"; 4 | 5 | package flight; 6 | 7 | enum Status { 8 | arrival = 0; 9 | departure = 1; 10 | } 11 | 12 | message Info { 13 | string airline = 1; 14 | uint32 number = 2; 15 | Status status = 3; 16 | uint32 priority = 4; 17 | } 18 | -------------------------------------------------------------------------------- /examples/redis-lib/cluster-client.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # github.com/ligato/cn-infra/db/keyval/redis#ClusterConfig 3 | dial-timeout: 0 4 | enable-query-on-slave: true 5 | endpoints: 6 | - 172.17.0.1:6379 7 | - 172.17.0.2:6379 8 | - 172.17.0.3:6379 9 | max-rediects: 0 10 | password: "" 11 | pool: 12 | busy-timeout: 0 13 | idle-check-frequency: 0 14 | idle-timeout: 0 15 | max-connections: 0 16 | read-timeout: 0 17 | route-by-latency: true 18 | write-timeout: 0 19 | -------------------------------------------------------------------------------- /examples/redis-lib/diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ligato/cn-infra/356dce1f1754fdc28af2cab9df30603a383be829/examples/redis-lib/diagram.png -------------------------------------------------------------------------------- /examples/redis-lib/doc.go: -------------------------------------------------------------------------------- 1 | // Package redislib contains a collection of examples demonstrating 2 | // the usage of the redis library. 3 | package redislib 4 | -------------------------------------------------------------------------------- /examples/redis-lib/node-client.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # github.com/ligato/cn-infra/db/keyval/redis#NodeConfig 3 | db: 0 4 | dial-timeout: 0 5 | enable-query-on-slave: false 6 | endpoint: localhost:6379 7 | password: "" 8 | pool: 9 | busy-timeout: 0 10 | idle-check-frequency: 0 11 | idle-timeout: 0 12 | max-connections: 0 13 | read-timeout: 0 14 | tls: 15 | ca-file: "" 16 | cert-file: "" 17 | enabled: false 18 | key-file: "" 19 | skip-verify: false 20 | write-timeout: 0 21 | -------------------------------------------------------------------------------- /examples/redis-lib/sentinel-client.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # github.com/ligato/cn-infra/db/keyval/redis#SentinelConfig 3 | db: 0 4 | dial-timeout: 0 5 | endpoints: 6 | - 172.17.0.7:26379 7 | - 172.17.0.8:26379 8 | - 172.17.0.9:26379 9 | master-name: mymaster 10 | password: "" 11 | pool: 12 | busy-timeout: 0 13 | idle-check-frequency: 0 14 | idle-timeout: 0 15 | max-connections: 0 16 | read-timeout: 0 17 | write-timeout: 0 18 | -------------------------------------------------------------------------------- /examples/redis-lib/simple/doc.go: -------------------------------------------------------------------------------- 1 | // A simple example demonstrating the redis library API. 2 | package main 3 | -------------------------------------------------------------------------------- /examples/redis-plugin/README.md: -------------------------------------------------------------------------------- 1 | # redis-plugin 2 | 3 | A simple example demonstrating how to create a Redis plugin. 4 | 5 | ### Usage 6 | 7 | To run the example, type: 8 | ``` 9 | go run main.go deps.go [-redis-config ] 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/redis-plugin/doc.go: -------------------------------------------------------------------------------- 1 | // Example demonstrates creating a Redis plugin 2 | package main 3 | -------------------------------------------------------------------------------- /examples/simple-agent/README.md: -------------------------------------------------------------------------------- 1 | # Simple agent 2 | 3 | This application demonstrates how easily a set of CN-infra based plugins 4 | can be turned into an application. 5 | 6 | ### Usage 7 | 8 | To run the example, simply type: 9 | ``` 10 | go run agent.go [-kafka-config ] [-etcd-config ] \ 11 | [-cassandra-config ] [-redis-config ] 12 | ``` 13 | 14 | All four data sources (kafka, etcd, redis, cassandra) are optional. 15 | If a particular config file path is left unspecified, the application 16 | will first try to look for the default configuration filename 17 | in the current working directory before skipping the initialization 18 | of the associated plugin. -------------------------------------------------------------------------------- /examples/simple-agent/agent.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "log" 19 | 20 | "go.ligato.io/cn-infra/v2/agent" 21 | "go.ligato.io/cn-infra/v2/datasync/resync" 22 | "go.ligato.io/cn-infra/v2/db/keyval/etcd" 23 | "go.ligato.io/cn-infra/v2/db/keyval/redis" 24 | "go.ligato.io/cn-infra/v2/db/sql/cassandra" 25 | ) 26 | 27 | func main() { 28 | 29 | // Create agent with connector plugins 30 | a := agent.NewAgent(agent.AllPlugins( 31 | &etcd.DefaultPlugin, 32 | &redis.DefaultPlugin, 33 | &cassandra.DefaultPlugin, 34 | &resync.DefaultPlugin, 35 | )) 36 | 37 | if err := a.Run(); err != nil { 38 | log.Fatal(err) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/simple-agent/doc.go: -------------------------------------------------------------------------------- 1 | // Example simple-agent shows how easily a set of CN-infra based plugins 2 | // can be turned into an application. 3 | package main 4 | -------------------------------------------------------------------------------- /examples/statuscheck-plugin/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Example application "statuscheck-plugin" demonstrates the usage of statusCheck plugin 16 | // etcd-plugin is monitored by StatusCheck plugin and examplePlugin reads the state. 17 | package main 18 | -------------------------------------------------------------------------------- /examples/statuscheck-plugin/etcd.conf: -------------------------------------------------------------------------------- 1 | insecure-transport: true 2 | dial-timeout: 1s 3 | endpoints: 4 | - "127.0.0.1:2379" 5 | -------------------------------------------------------------------------------- /examples/supervisor-plugin/example.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ligato/cn-infra/356dce1f1754fdc28af2cab9df30603a383be829/examples/supervisor-plugin/example.log -------------------------------------------------------------------------------- /examples/tutorials/01_hello-world/main.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "log" 19 | 20 | "go.ligato.io/cn-infra/v2/agent" 21 | ) 22 | 23 | func main() { 24 | // Create an instance of our plugin. 25 | p := new(HelloWorld) 26 | 27 | // Create new agent with our plugin instance. 28 | a := agent.NewAgent(agent.Plugins(p)) 29 | 30 | // Run starts the agent with plugins, wait until shutdown 31 | // and then stops the agent and its plugins. 32 | if err := a.Run(); err != nil { 33 | log.Fatalln(err) 34 | } 35 | } 36 | 37 | // HelloWorld represents our plugin. 38 | type HelloWorld struct{} 39 | 40 | // String is used to identify the plugin by giving it name. 41 | func (p *HelloWorld) String() string { 42 | return "HelloWorld" 43 | } 44 | 45 | // Init is executed on agent initialization. 46 | func (p *HelloWorld) Init() error { 47 | log.Println("Hello World!") 48 | return nil 49 | } 50 | 51 | // AfterInit is executed after initialization of all plugins. It's optional 52 | // and used for executing operations that require plugins to be initalized. 53 | func (p *HelloWorld) AfterInit() error { 54 | log.Println("All systems go!") 55 | return nil 56 | } 57 | 58 | // Close is executed on agent shutdown. 59 | func (p *HelloWorld) Close() error { 60 | log.Println("Goodbye World!") 61 | return nil 62 | } 63 | -------------------------------------------------------------------------------- /examples/tutorials/02_plugin-deps/helloworld.conf: -------------------------------------------------------------------------------- 1 | greeting: Greetings World! 2 | -------------------------------------------------------------------------------- /examples/tutorials/04_kv-store/etcd.conf: -------------------------------------------------------------------------------- 1 | insecure-transport: true 2 | dial-timeout: 1s 3 | endpoints: 4 | - "172.17.0.1:2379" 5 | -------------------------------------------------------------------------------- /examples/tutorials/04_kv-store/model/model.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "go.ligato.io/cn-infra/v2/examples/tutorials/04_kv-store/model"; 4 | 5 | package model; 6 | 7 | message Greetings { 8 | string greeting = 1; 9 | } 10 | -------------------------------------------------------------------------------- /examples/tutorials/06_plugin_lookup/main.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "log" 19 | 20 | "go.ligato.io/cn-infra/v2/agent" 21 | ) 22 | 23 | func main() { 24 | // Create new agent with our plugin instance. 25 | a := agent.NewAgent(agent.AllPlugins(New())) 26 | 27 | // Run starts the agent with plugins, wait until shutdown 28 | // and then stops the agent and its plugins. 29 | if err := a.Run(); err != nil { 30 | log.Fatalln(err) 31 | } 32 | } 33 | 34 | // Agent is a top-level plugin used as starter for other plugins 35 | type Agent struct { 36 | Hw *HelloWorld 37 | Hu *HelloUniverse 38 | } 39 | 40 | // Init is an implementation of the plugin interface 41 | func (p *Agent) Init() error { 42 | return nil 43 | } 44 | 45 | // Close is an implementation of the plugin interface 46 | func (p *Agent) Close() error { 47 | return nil 48 | } 49 | 50 | // String is an implementation of the plugin interface 51 | func (p *Agent) String() string { 52 | return "AgentPlugin" 53 | } 54 | 55 | // New returns top-level plugin object with defined plugins and their dependencies 56 | func New() *Agent { 57 | hw := &HelloWorld{} 58 | hu := &HelloUniverse{} 59 | 60 | hw.Universe = hu 61 | hu.World = hw 62 | 63 | return &Agent{ 64 | Hu: hu, 65 | Hw: hw, 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /examples/tutorials/06_plugin_lookup/plugin1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "log" 4 | 5 | // HelloWorld represents our plugin. 6 | type HelloWorld struct{ 7 | Universe *HelloUniverse 8 | } 9 | 10 | // String is used to identifying the plugin by giving its name. 11 | func (p *HelloWorld) String() string { 12 | return "HelloWorld" 13 | } 14 | 15 | // Init is executed on agent initialization. 16 | func (p *HelloWorld) Init() error { 17 | log.Println("Hello World!") 18 | p.Universe.RegisterWorld("Arrakis", 10) 19 | return nil 20 | } 21 | 22 | // AfterInit is executed after initialization of all plugins. It's optional 23 | // and used for executing operations that require plugins to be initialized. 24 | func (p *HelloWorld) AfterInit() error { 25 | log.Println("All systems go!") 26 | return nil 27 | } 28 | 29 | // Close is executed on agent shutdown. 30 | func (p *HelloWorld) Close() error { 31 | log.Println("Goodbye World!") 32 | return nil 33 | } 34 | 35 | // SetPlace is an exported method that allows other plugins to set some internal parameters 36 | func (p *HelloWorld) SetPlace(world, place string) { 37 | log.Printf("%s was placed %s", world, place) 38 | } 39 | -------------------------------------------------------------------------------- /examples/tutorials/06_plugin_lookup/plugin2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "log" 4 | 5 | // HelloUniverse represents another plugin. 6 | type HelloUniverse struct{ 7 | worlds map[string]int 8 | 9 | World *HelloWorld 10 | } 11 | 12 | // String is used to identify the plugin by giving it name. 13 | func (p *HelloUniverse) String() string { 14 | return "HelloUniverse" 15 | } 16 | 17 | // Init is executed on agent initialization. 18 | func (p *HelloUniverse) Init() error { 19 | log.Println("Hello Universe!") 20 | p.worlds = make(map[string]int) 21 | return nil 22 | } 23 | 24 | // AfterInit is executed after alll plugin's Init() 25 | func (p *HelloUniverse) AfterInit() error { 26 | for name := range p.worlds { 27 | p.World.SetPlace(name, "near Canopus") 28 | } 29 | return nil 30 | } 31 | 32 | // Close is executed on agent shutdown. 33 | func (p *HelloUniverse) Close() error { 34 | log.Println("Goodbye Universe!") 35 | return nil 36 | } 37 | 38 | // RegisterWorld is exported for other plugins to use 39 | func (p *HelloUniverse) RegisterWorld(name string, size int) { 40 | p.worlds[name] = size 41 | log.Printf("World %s (size %d) was registered", name, size) 42 | } 43 | -------------------------------------------------------------------------------- /examples/tutorials/README.md: -------------------------------------------------------------------------------- 1 | # Tutorial Examples 2 | 3 | See [tutorials section](/docs/tutorials) in docs for documentation to tutorial examples. 4 | -------------------------------------------------------------------------------- /exec/processmanager/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package processmanager 16 | 17 | // DefaultPlugin is a default instance of Plugin. 18 | var DefaultPlugin = *NewPlugin() 19 | 20 | // NewPlugin creates a new Plugin with the provided Options. 21 | func NewPlugin(opts ...Option) *Plugin { 22 | p := &Plugin{} 23 | 24 | p.PluginName = "process-manager" 25 | 26 | for _, o := range opts { 27 | o(p) 28 | } 29 | 30 | p.PluginDeps.Setup() 31 | 32 | return p 33 | } 34 | 35 | // Option is a function that can be used in NewPlugin to customize Plugin. 36 | type Option func(*Plugin) 37 | 38 | // UseDeps returns Option that can inject custom dependencies. 39 | func UseDeps(cb func(*Deps)) Option { 40 | return func(p *Plugin) { 41 | cb(&p.Deps) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /exec/processmanager/pm.conf: -------------------------------------------------------------------------------- 1 | # Template path is a path where the templates will be stored in the filesystem 2 | template-path: /tmp/template/ -------------------------------------------------------------------------------- /exec/processmanager/status/test-state: -------------------------------------------------------------------------------- 1 | Name: vpp_main 2 | Umask: 0022 3 | State: S (sleeping) 4 | Tgid: 23986 5 | Ngid: 0 6 | Pid: 23986 7 | PPid: 23985 8 | TracerPid: 0 9 | Uid: 0 0 0 0 10 | Gid: 0 997 0 997 11 | FDSize: 64 12 | Groups: 0 13 | NStgid: 23986 14 | NSpid: 23986 15 | NSpgid: 23984 16 | NSsid: 8037 17 | VmPeak: 5348632 kB 18 | VmSize: 5348632 kB 19 | VmLck: 0 kB 20 | VmPin: 0 kB 21 | VmHWM: 37880 kB 22 | VmRSS: 37880 kB 23 | RssAnon: 20004 kB 24 | RssFile: 15980 kB 25 | RssShmem: 1896 kB 26 | VmData: 5058816 kB 27 | VmStk: 132 kB 28 | VmExe: 844 kB 29 | VmLib: 22088 kB 30 | VmPTE: 592 kB 31 | VmSwap: 0 kB 32 | HugetlbPages: 32768 kB 33 | CoreDumping: 0 34 | Threads: 2 35 | SigQ: 0/31666 36 | SigPnd: 0000000000000000 37 | ShdPnd: 0000000000000000 38 | SigBlk: 0000000000000000 39 | SigIgn: 0000000000011000 40 | SigCgt: 00000001fffae4ff 41 | CapInh: 0000000000000000 42 | CapPrm: 0000003fffffffff 43 | CapEff: 0000003fffffffff 44 | CapBnd: 0000003fffffffff 45 | CapAmb: 0000000000000000 46 | NoNewPrivs: 0 47 | Seccomp: 0 48 | Speculation_Store_Bypass: vulnerable 49 | Cpus_allowed: 2 50 | Cpus_allowed_list: 1 51 | Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001 52 | Mems_allowed_list: 0 53 | voluntary_ctxt_switches: 1377 54 | nonvoluntary_ctxt_switches: 80 -------------------------------------------------------------------------------- /exec/supervisor/hooks.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package supervisor 16 | 17 | import ( 18 | "fmt" 19 | "os" 20 | "os/exec" 21 | ) 22 | 23 | // Environment variables set for executed hook command 24 | const ( 25 | svProcessName = "SUPERVISOR_PROCESS_NAME" 26 | svProcessState = "SUPERVISOR_PROCESS_STATE" 27 | seEventType = "SUPERVISOR_EVENT_TYPE" 28 | ) 29 | 30 | func (p *Plugin) watchEvents() { 31 | for { 32 | processInfo, ok := <-p.hookEventChan 33 | if !ok { 34 | p.Log.Debugf("supervisor hook watcher ended") 35 | close(p.hookDoneChan) 36 | return 37 | } 38 | 39 | // execute all hooks with env vars set 40 | for _, hook := range p.config.Hooks { 41 | cmd := exec.Command(hook.Cmd, hook.CmdArgs...) 42 | 43 | cmd.Env = append(os.Environ(), 44 | fmt.Sprintf("%s=%v", seEventType, processInfo.eventType), 45 | fmt.Sprintf("%s=%v", svProcessName, processInfo.name), 46 | fmt.Sprintf("%s=%v", svProcessState, processInfo.state), 47 | ) 48 | 49 | out, err := cmd.CombinedOutput() 50 | if err != nil { 51 | p.Log.Errorf("hook failed: %v", err) 52 | } 53 | if len(out) > 0 { 54 | p.Log.Debugf("hook output: %s", out) 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /exec/supervisor/logger.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package supervisor 16 | 17 | import ( 18 | "bufio" 19 | "log" 20 | "os" 21 | "sync" 22 | 23 | "github.com/pkg/errors" 24 | ) 25 | 26 | // SvLogger is a logger object compatible with the process manager. It uses 27 | // writer to print log to stdout or a file 28 | type SvLogger struct { 29 | mx sync.Mutex 30 | writer *bufio.Writer 31 | 32 | file *os.File 33 | } 34 | 35 | // NewSvLogger prepares new supervisor logger for given process. 36 | func NewSvLogger(logfilePath string) (svLogger *SvLogger, err error) { 37 | var file *os.File 38 | 39 | writer := bufio.NewWriterSize(os.Stdout, 1) 40 | if logfilePath != "" { 41 | if file, err = os.OpenFile(logfilePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666); err != nil { 42 | return nil, errors.Errorf("failed to open log file %s: %v", logfilePath, err) 43 | } 44 | writer = bufio.NewWriter(file) 45 | } 46 | 47 | return &SvLogger{ 48 | writer: writer, 49 | file: file, 50 | }, nil 51 | } 52 | 53 | // Write message to the file or stdout 54 | func (l *SvLogger) Write(p []byte) (n int, err error) { 55 | l.mx.Lock() 56 | defer l.mx.Unlock() 57 | 58 | return l.writer.Write(p) 59 | } 60 | 61 | // Close the file if necessary 62 | func (l *SvLogger) Close() error { 63 | if err := l.writer.Flush(); err != nil { 64 | log.Printf("error writing buffer to file: %v", err) 65 | } 66 | if l.file != nil { 67 | return l.file.Close() 68 | } 69 | return nil 70 | } 71 | -------------------------------------------------------------------------------- /exec/supervisor/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package supervisor 16 | 17 | import pm "go.ligato.io/cn-infra/v2/exec/processmanager" 18 | 19 | // DefaultPlugin is a default instance of the supervisor plugin 20 | var DefaultPlugin = *NewPlugin() 21 | 22 | // NewPlugin creates a new supervisor plugin with the provided options 23 | func NewPlugin(opts ...Option) *Plugin { 24 | p := &Plugin{} 25 | 26 | p.PluginName = "supervisor" 27 | p.PM = &pm.DefaultPlugin 28 | 29 | for _, o := range opts { 30 | o(p) 31 | } 32 | 33 | p.PluginDeps.Setup() 34 | 35 | return p 36 | } 37 | 38 | // Option is a function that can be used in the NewPlugin to customize plugin options 39 | type Option func(*Plugin) 40 | 41 | // UseDeps returns an option that can inject custom dependencies 42 | func UseDeps(cb func(*Deps)) Option { 43 | return func(p *Plugin) { 44 | cb(&p.Deps) 45 | } 46 | } 47 | 48 | // UseConf returns an option which injects a particular configuration 49 | func UseConf(conf Config) Option { 50 | return func(p *Plugin) { 51 | p.config = &conf 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /exec/supervisor/supervisor.conf: -------------------------------------------------------------------------------- 1 | # Example supervisor config file starting vpp and agent, 2 | # and defining hook for the vpp process which runs 'test.sh' 3 | # if terminated 4 | # See `taskset` man page to learn about how the cpu affinity 5 | # mask should be set. 6 | # --- 7 | # 8 | # programs: 9 | # - name: "vpp" 10 | # executable-path: "/usr/bin/vpp" 11 | # executable-args: ["-c", "/etc/vpp/base-startup.conf"] 12 | # logfile-path: "/tmp/supervisor.log" 13 | # restarts: 4 14 | # cpu-affinity-mask: 4 15 | # cpu-affinity-setup-delay: 1s 16 | # - name: "agent" 17 | # executable-path: "/usr/local/bin/vpp-agent" 18 | # executable-args: ["--config-dir=/tmp/config"] 19 | # logfile-path: "/tmp/supervisor.log" 20 | #hooks: 21 | # - program-name: "vpp" 22 | # event-type: "terminated" 23 | # cmd: "/tmp/test.sh" -------------------------------------------------------------------------------- /health/doc.go: -------------------------------------------------------------------------------- 1 | // Package health contains plugins for monitoring of the health status 2 | // of the agent. 3 | package health 4 | -------------------------------------------------------------------------------- /health/probe/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package probe implements HTTP probes: the K8s readiness and liveliness probe handlers + Prometheus format. 16 | package probe 17 | -------------------------------------------------------------------------------- /health/probe/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package probe 16 | 17 | import ( 18 | "go.ligato.io/cn-infra/v2/health/statuscheck" 19 | "go.ligato.io/cn-infra/v2/logging" 20 | "go.ligato.io/cn-infra/v2/rpc/rest" 21 | "go.ligato.io/cn-infra/v2/servicelabel" 22 | ) 23 | 24 | // DefaultPlugin is a default instance of Plugin. 25 | var DefaultPlugin = *NewPlugin() 26 | 27 | // NewPlugin creates a new Plugin with the provided Options. 28 | func NewPlugin(opts ...Option) *Plugin { 29 | p := &Plugin{} 30 | 31 | p.PluginName = "probe" 32 | p.HTTP = &rest.DefaultPlugin 33 | p.ServiceLabel = &servicelabel.DefaultPlugin 34 | p.StatusCheck = &statuscheck.DefaultPlugin 35 | 36 | for _, o := range opts { 37 | o(p) 38 | } 39 | 40 | if p.Deps.Log == nil { 41 | p.Deps.Log = logging.ForPlugin(p.String()) 42 | } 43 | 44 | return p 45 | } 46 | 47 | // Option is a function that can be used in NewPlugin to customize Plugin. 48 | type Option func(*Plugin) 49 | 50 | // UseDeps returns Option that can inject custom dependencies. 51 | func UseDeps(cb func(*Deps)) Option { 52 | return func(p *Plugin) { 53 | cb(&p.Deps) 54 | } 55 | } 56 | 57 | // WithNonFatalPlugins defines plugins whose errors are effectively ignored 58 | // in agent's overall status. 59 | func WithNonFatalPlugins(plugins []string) Option { 60 | return func(p *Plugin) { 61 | p.NonFatalPlugins = plugins 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /health/statuscheck/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package statuscheck defines the status report API for other CN-Infra 16 | // plugins and implements the health status aggregator/exporter. Health 17 | // status is collected from other plugins through the plugin status report 18 | // API and aggregated and exported/exposed via ETCD or a REST API. 19 | // 20 | // The API provides only two functions, one for registering the plugin for 21 | // status change reporting and one for reporting status changes. 22 | // 23 | // To register a plugin for providing status reports, use Register() 24 | // function: 25 | // statuscheck.Register(PluginID, probe) 26 | // 27 | // If probe is not nil, statuscheck will periodically probe the plugin 28 | // state through the provided function. Otherwise, it is expected that the 29 | // plugin itself will report state updates through ReportStateChange(), e.g.: 30 | // statuscheck.ReportStateChange(PluginID, statuscheck.OK, nil) 31 | // 32 | // The default status of a plugin after registering is Init. 33 | package statuscheck 34 | -------------------------------------------------------------------------------- /health/statuscheck/model/status/keys_agent_status.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package status 16 | 17 | const ( 18 | // StatusPrefix is the relative key prefix for the agent/plugin status. 19 | StatusPrefix = "check/status/v1/" 20 | // AgentStatusPrefix is the relative key prefix for the agent status, 21 | // filtering out statuses of individual plugins. 22 | AgentStatusPrefix = StatusPrefix + "agent" 23 | ) 24 | 25 | // AgentStatusKey returns the key used in ETCD to store the operational status 26 | // of the vpp agent instance. 27 | func AgentStatusKey() string { 28 | return AgentStatusPrefix 29 | } 30 | 31 | // PluginStatusKey returns the key used in ETCD to store the operational status 32 | // of the vpp agent plugin. 33 | func PluginStatusKey(pluginLabel string) string { 34 | return StatusPrefix + "plugin/" + pluginLabel 35 | } 36 | -------------------------------------------------------------------------------- /health/statuscheck/model/status/status.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "go.ligato.io/cn-infra/v2/health/statuscheck/model/status"; 4 | 5 | // Package status provides data model for status information of the agent. 6 | package status; 7 | 8 | enum OperationalState { 9 | INIT = 0; 10 | OK = 1; 11 | ERROR = 2; 12 | }; 13 | 14 | message AgentStatus { 15 | string build_version = 1; 16 | string build_date = 2; 17 | OperationalState state = 3; 18 | int64 start_time = 4; 19 | int64 last_change = 5; /* last change of the state */ 20 | int64 last_update = 6; /* last update of the state by some plugin */ 21 | InterfaceStats interface_stats = 7; 22 | string commit_hash = 8; 23 | repeated PluginStatus plugins = 9; 24 | } 25 | 26 | message PluginStatus { 27 | string name = 1; 28 | OperationalState state = 2; 29 | int64 last_change = 3; /* last change of the state */ 30 | int64 last_update = 4; /* last update of the state */ 31 | string error = 5; /* last seen error */ 32 | } 33 | 34 | message InterfaceStats { 35 | message Interface { 36 | string internal_name = 1; /* interface name used in VPP */ 37 | uint32 index = 3; /* sw interface index */ 38 | string status = 4; /* status (UP, DOWN, DELETED, ...) */ 39 | string ip_address = 5; 40 | string mac_address = 6; 41 | } 42 | repeated Interface interfaces = 1; 43 | } 44 | -------------------------------------------------------------------------------- /health/statuscheck/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package statuscheck 16 | 17 | import ( 18 | "go.ligato.io/cn-infra/v2/logging" 19 | ) 20 | 21 | // DefaultPlugin is a default instance of Plugin. 22 | var DefaultPlugin = *NewPlugin() 23 | 24 | // NewPlugin creates a new Plugin with the provided Options. 25 | func NewPlugin(opts ...Option) *Plugin { 26 | p := &Plugin{} 27 | 28 | p.PluginName = "status-check" 29 | 30 | for _, o := range opts { 31 | o(p) 32 | } 33 | 34 | if p.Deps.Log == nil { 35 | p.Deps.Log = logging.ForPlugin(p.String()) 36 | } 37 | 38 | return p 39 | } 40 | 41 | // Option is a function that can be used in NewPlugin to customize Plugin. 42 | type Option func(*Plugin) 43 | 44 | // UseDeps returns Option that can inject custom dependencies. 45 | func UseDeps(cb func(*Deps)) Option { 46 | return func(p *Plugin) { 47 | cb(&p.Deps) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /health/statuscheck/pluginstatusmap/doc.go: -------------------------------------------------------------------------------- 1 | // Package pluginstatusmap implements specialization of idxmap used to store 2 | // plugin status by plugin name. 3 | package pluginstatusmap 4 | -------------------------------------------------------------------------------- /idxmap/chan.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package idxmap 16 | 17 | import ( 18 | "time" 19 | 20 | "go.ligato.io/cn-infra/v2/logging" 21 | "go.ligato.io/cn-infra/v2/logging/logrus" 22 | ) 23 | 24 | // DefaultNotifTimeout for delivery of notification 25 | const DefaultNotifTimeout = 2 * time.Second 26 | 27 | // ToChan creates a callback that can be passed to the Watch function 28 | // in order to receive notifications through a channel. If the notification 29 | // can not be delivered until timeout, it is dropped. 30 | func ToChan(ch chan NamedMappingGenericEvent, opts ...interface{}) func(dto NamedMappingGenericEvent) { 31 | 32 | timeout := DefaultNotifTimeout 33 | var logger logging.Logger = logrus.DefaultLogger() 34 | 35 | /*for _, opt := range opts { 36 | switch opt.(type) { 37 | case *core.WithLoggerOpt: 38 | logger = opt.(*core.WithLoggerOpt).Logger 39 | case *core.WithTimeoutOpt: 40 | timeout = opt.(*core.WithTimeoutOpt).Timeout 41 | } 42 | }*/ 43 | 44 | return func(dto NamedMappingGenericEvent) { 45 | select { 46 | case ch <- dto: 47 | case <-time.After(timeout): 48 | logger.Warn("Unable to deliver notification") 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /logging/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package logging defines the logging API. It used by all plugins, and supports 16 | // multiple log levels (severities) and various log message formats. 17 | package logging 18 | -------------------------------------------------------------------------------- /logging/logmanager/config.go: -------------------------------------------------------------------------------- 1 | package logmanager 2 | 3 | // NewConf creates default configuration with InfoLevel & empty loggers. 4 | // Suitable also for usage in flavor to programmatically specify default behavior. 5 | func NewConf() *Config { 6 | return &Config{ 7 | DefaultLevel: "", 8 | Loggers: []LoggerConfig{}, 9 | Hooks: make(map[string]HookConfig), 10 | } 11 | } 12 | 13 | // Config is a binding that supports to define default log levels for multiple loggers 14 | type Config struct { 15 | DefaultLevel string `json:"default-level"` 16 | Loggers []LoggerConfig `json:"loggers"` 17 | Hooks map[string]HookConfig `json:"hooks"` 18 | } 19 | 20 | // LoggerConfig is configuration of a particular logger. 21 | // Currently we support only logger level. 22 | type LoggerConfig struct { 23 | Name string 24 | Level string //debug, info, warn, error, fatal, panic 25 | } 26 | 27 | // HookConfig contains configuration of hook services 28 | type HookConfig struct { 29 | Protocol string 30 | Address string 31 | Port int 32 | Levels []string 33 | } 34 | -------------------------------------------------------------------------------- /logging/logmanager/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package logmanager implements the log manager that allows users to set 16 | // log levels at run-time via a REST API. 17 | package logmanager 18 | -------------------------------------------------------------------------------- /logging/logmanager/logs.conf: -------------------------------------------------------------------------------- 1 | # Set default config level for every plugin. Overwritten by environmental variable 'INITIAL_LOGLVL' 2 | default-level: info 3 | 4 | # Specifies a list of named loggers with respective log level 5 | loggers: 6 | - name: "agentcore", 7 | level: debug 8 | - name: "status-check", 9 | level: info 10 | - name: "linux-plugin", 11 | level: warn 12 | # Specifies a list of hook for logging to external links with respective 13 | # parameters (protocol, address, port and levels) for given hook 14 | hooks: 15 | syslog: 16 | levels: 17 | - panic 18 | # - fatal 19 | # - error 20 | # - warn 21 | # - info 22 | # - debug 23 | # fluent: 24 | # address: "10.20.30.41" 25 | # port: 4521 26 | # protocol: tcp 27 | # levels: 28 | # - error 29 | # logstash: 30 | # address: "10.20.30.42" 31 | # port: 123 32 | # protocol: tcp 33 | -------------------------------------------------------------------------------- /logging/logmanager/options.go: -------------------------------------------------------------------------------- 1 | package logmanager 2 | 3 | import ( 4 | "go.ligato.io/cn-infra/v2/logging" 5 | "go.ligato.io/cn-infra/v2/rpc/rest" 6 | "go.ligato.io/cn-infra/v2/servicelabel" 7 | ) 8 | 9 | // DefaultPlugin is a default instance of Plugin. 10 | var DefaultPlugin = *NewPlugin() 11 | 12 | // NewPlugin creates a new Plugin with the provided Options. 13 | func NewPlugin(opts ...Option) *Plugin { 14 | p := &Plugin{} 15 | 16 | p.PluginName = "logs" 17 | p.LogRegistry = logging.DefaultRegistry 18 | p.HTTP = &rest.DefaultPlugin 19 | p.ServiceLabel = &servicelabel.DefaultPlugin 20 | 21 | for _, o := range opts { 22 | o(p) 23 | } 24 | 25 | p.PluginDeps.Setup() 26 | 27 | return p 28 | } 29 | 30 | // Option is a function that can be used in NewPlugin to customize Plugin. 31 | type Option func(*Plugin) 32 | 33 | // UseDeps returns Option that can inject custom dependencies. 34 | func UseDeps(cb func(*Deps)) Option { 35 | return func(p *Plugin) { 36 | cb(&p.Deps) 37 | } 38 | } 39 | 40 | // UseConf returns Option which injects a particular configuration. 41 | func UseConf(conf Config) Option { 42 | return func(p *Plugin) { 43 | p.Config = &conf 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /logging/logrus/caller.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package logrus 16 | 17 | import ( 18 | "reflect" 19 | "runtime" 20 | "strings" 21 | ) 22 | 23 | const ( 24 | sirupsenLogrusPkgPath = "sirupsen/logrus." 25 | 26 | maximumCallerDepth = 15 27 | minimumCallerDepth = 6 28 | ) 29 | 30 | var packagePath string 31 | 32 | func init() { 33 | type x struct{} 34 | packagePath = reflect.TypeOf(x{}).PkgPath() 35 | } 36 | 37 | // getCaller retrieves the name of the first non-logrus calling function 38 | func getCaller() *runtime.Frame { 39 | pcs := make([]uintptr, maximumCallerDepth) 40 | depth := runtime.Callers(minimumCallerDepth, pcs) 41 | frames := runtime.CallersFrames(pcs[:depth]) 42 | for f, more := frames.Next(); more; f, more = frames.Next() { 43 | if strings.LastIndex(f.Function, sirupsenLogrusPkgPath) != -1 { 44 | continue 45 | } 46 | if strings.LastIndex(f.Function, packagePath) == -1 { 47 | return &f 48 | } 49 | } 50 | return nil 51 | } 52 | -------------------------------------------------------------------------------- /logging/logrus/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package logrus implements the logging API based on the Logrus logger. 16 | package logrus 17 | -------------------------------------------------------------------------------- /logging/logrus/export.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package logrus 16 | 17 | import "go.ligato.io/cn-infra/v2/logging" 18 | 19 | func init() { 20 | logging.Trace = defaultLogger.Trace 21 | logging.Tracef = defaultLogger.Tracef 22 | logging.Debug = defaultLogger.Debug 23 | logging.Debugf = defaultLogger.Debugf 24 | logging.Info = defaultLogger.Info 25 | logging.Infof = defaultLogger.Infof 26 | logging.Warn = defaultLogger.Warn 27 | logging.Warnf = defaultLogger.Warnf 28 | logging.Error = defaultLogger.Error 29 | logging.Errorf = defaultLogger.Errorf 30 | logging.Fatal = defaultLogger.Fatal 31 | logging.Fatalf = defaultLogger.Fatalf 32 | logging.Panic = defaultLogger.Panic 33 | logging.Panicf = defaultLogger.Panicf 34 | } 35 | -------------------------------------------------------------------------------- /logging/logrus/redact.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package logrus 16 | 17 | import ( 18 | "go.ligato.io/cn-infra/v2/utils/redact" 19 | ) 20 | 21 | func redactData(data map[string]interface{}) map[string]interface{} { 22 | for k, v := range data { 23 | data[k] = redact.Value(v) 24 | } 25 | return data 26 | } 27 | 28 | func redactArgs(args []interface{}) []interface{} { 29 | for i, arg := range args { 30 | args[i] = redact.Value(arg) 31 | } 32 | return args 33 | } 34 | -------------------------------------------------------------------------------- /logging/measure/model/apitrace/apitrace.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "go.ligato.io/cn-infra/v2/logging/measure/model/apitrace"; 4 | 5 | // Package apitrace provides data model for binary API trace informations. 6 | package apitrace; 7 | 8 | message Trace { 9 | message Entry { 10 | uint64 index = 1; // Entry index. Each message is indexed in the order it is logged. 11 | string msg_name = 2; // Message name (or any other descriptive string) 12 | uint64 start_time = 3; 13 | uint64 duration = 4; // Duration of message call in nanoseconds 14 | } 15 | repeated Entry traced_entries = 1; 16 | 17 | message EntryStats { 18 | string msg_name = 1; // Message name, unique in this list. 19 | uint64 average_duration = 2; // Average time duration per message in nanoseconds 20 | } 21 | repeated EntryStats entry_stats = 2; 22 | 23 | uint64 overall_duration = 3; // Overall duration of all measured entries in nanoseconds 24 | } 25 | -------------------------------------------------------------------------------- /messaging/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package messaging is the parent package for implementations of various 16 | // messaging clients, e.g. Kafka. 17 | package messaging 18 | -------------------------------------------------------------------------------- /messaging/kafka/client/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package client implements the synchronous and asynchronous kafka Producers 16 | // and the kafka Consumer. 17 | package client 18 | -------------------------------------------------------------------------------- /messaging/kafka/kafka.conf: -------------------------------------------------------------------------------- 1 | # Kafka server addresses 2 | addrs: 3 | - "127.0.0.1:9092" 4 | 5 | # Name of the consumer's group. 6 | group_id: 7 | 8 | # Crypto/TLS configuration 9 | #tls: -------------------------------------------------------------------------------- /messaging/kafka/mux/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package mux implements the session multiplexer that allows multiple 16 | // plugins to share a single connection to a Kafka broker. 17 | package mux 18 | -------------------------------------------------------------------------------- /messaging/kafka/mux/mock.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package mux 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/Shopify/sarama/mocks" 21 | 22 | "go.ligato.io/cn-infra/v2/logging/logrus" 23 | "go.ligato.io/cn-infra/v2/messaging/kafka/client" 24 | ) 25 | 26 | func getMockConsumerFactory(t *testing.T) ConsumerFactory { 27 | return func(topics []string, name string) (*client.Consumer, error) { 28 | return client.GetConsumerMock(t), nil 29 | } 30 | } 31 | 32 | // Mock returns mock of Multiplexer that can be used for testing purposes. 33 | func Mock(t *testing.T) *KafkaMock { 34 | asyncP, aMock := client.GetAsyncProducerMock(t) 35 | syncP, sMock := client.GetSyncProducerMock(t) 36 | producers := multiplexerProducers{ 37 | syncP, syncP, asyncP, asyncP, 38 | } 39 | 40 | return &KafkaMock{ 41 | NewMultiplexer(getMockConsumerFactory(t), producers, &client.Config{}, "name", logrus.DefaultLogger()), 42 | aMock, sMock} 43 | } 44 | 45 | // KafkaMock for the tests 46 | type KafkaMock struct { 47 | Mux *Multiplexer 48 | AsyncPub *mocks.AsyncProducer 49 | SyncPub *mocks.SyncProducer 50 | } 51 | -------------------------------------------------------------------------------- /messaging/kafka/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package kafka 16 | 17 | import ( 18 | "go.ligato.io/cn-infra/v2/health/statuscheck" 19 | "go.ligato.io/cn-infra/v2/servicelabel" 20 | ) 21 | 22 | // DefaultPlugin is a default instance of Plugin. 23 | var DefaultPlugin = *NewPlugin() 24 | 25 | // NewPlugin creates a new Plugin with the provided Options. 26 | func NewPlugin(opts ...Option) *Plugin { 27 | p := &Plugin{} 28 | 29 | p.PluginName = "kafka" 30 | p.StatusCheck = &statuscheck.DefaultPlugin 31 | p.ServiceLabel = &servicelabel.DefaultPlugin 32 | 33 | for _, o := range opts { 34 | o(p) 35 | } 36 | 37 | p.PluginDeps.Setup() 38 | 39 | return p 40 | } 41 | 42 | // Option is a function that can be used in NewPlugin to customize Plugin. 43 | type Option func(*Plugin) 44 | 45 | // UseDeps returns Option that can inject custom dependencies. 46 | func UseDeps(cb func(*Deps)) Option { 47 | return func(p *Plugin) { 48 | cb(&p.Deps) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /rpc/doc.go: -------------------------------------------------------------------------------- 1 | // Package rpc contains plugins providing RPC-like access. 2 | package rpc 3 | -------------------------------------------------------------------------------- /rpc/grpc/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package grpc implements the GRPC netListener through which plugins can 16 | // expose their services/API to the outside world. 17 | package grpc 18 | -------------------------------------------------------------------------------- /rpc/grpc/grpc.conf: -------------------------------------------------------------------------------- 1 | # GRPC endpoint defines IP address and port (if tcp type) or unix domain socket file (if unix type). 2 | endpoint: 0.0.0.0:9111 3 | 4 | # If unix domain socket file is used for GRPC communication, permissions to the file can be set here. 5 | # Permission value uses standard three-or-four number linux binary reference. 6 | permission: 000 7 | 8 | # If socket file exists in defined path, it is not removed by default, GRPC plugin tries to use it. 9 | # Set the force removal flag to 'true' ensures that the socket file will be always re-created 10 | force-socket-removal: false 11 | 12 | # Available socket types: tcp, tcp4, tcp6, unix, unixpacket. If not set, defaults to tcp. 13 | network: tcp 14 | 15 | # Maximum message size in bytes for inbound mesages. If not set, GRPC uses the default 4MB. 16 | max-msg-size: 4096 17 | 18 | # Limit of server streams to each server transport. 19 | max-concurrent-streams: 0 20 | 21 | # TLS configuration: 22 | 23 | # If `true` TLS configuration from this config will be SKIPPED. 24 | #insecure-transport: false 25 | 26 | # Required for creating secure connection. 27 | #cert-file: /path/to/cert.pem 28 | 29 | # Also required for creating secure connection. 30 | #key-file: /path/to/key.pem 31 | 32 | # Set custom CA to verify client's certificate. 33 | # If not set, client's certificate is not required. 34 | #ca-files: 35 | # - /path/to/ca1.pem 36 | # - /path/to/ca2.pem 37 | 38 | # Enables logging additional GRPC transport messages 39 | #extended-logging: false 40 | 41 | # Enables prometheus metrics for GRPC server 42 | #prometheus-metrics: false 43 | -------------------------------------------------------------------------------- /rpc/grpc/plugin_api_grpc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package grpc 16 | 17 | import ( 18 | "google.golang.org/grpc" 19 | ) 20 | 21 | // Server defines the API for getting grpc.Server instance that 22 | // is useful for registering new GRPC services 23 | type Server interface { 24 | // Server is a getter for accessing grpc.Server (of a GRPC plugin) 25 | // 26 | // Example usage: 27 | // 28 | // protocgenerated.RegisterServiceXY(plugin.Deps.GRPC.Server(), &ServiceXYImplP{}) 29 | // 30 | // type Deps struct { 31 | // GRPC grps.Server // inject plugin implementing RegisterHandler 32 | // // other dependencies ... 33 | // } 34 | GetServer() *grpc.Server 35 | 36 | // Disabled informs other plugins about availability 37 | IsDisabled() bool 38 | } 39 | -------------------------------------------------------------------------------- /rpc/grpc/ratelimit.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package grpc 16 | 17 | import ( 18 | "context" 19 | 20 | "golang.org/x/time/rate" 21 | "google.golang.org/grpc" 22 | "google.golang.org/grpc/codes" 23 | "google.golang.org/grpc/status" 24 | ) 25 | 26 | // UnaryServerInterceptorLimiter returns a new unary server interceptors that performs request rate limiting. 27 | func UnaryServerInterceptorLimiter(limiter *rate.Limiter) grpc.UnaryServerInterceptor { 28 | return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 29 | if !limiter.Allow() { 30 | return nil, status.Errorf(codes.ResourceExhausted, "%s is rejected by ratelimit middleware, please retry later.", info.FullMethod) 31 | } 32 | 33 | return handler(ctx, req) 34 | } 35 | } 36 | 37 | // StreamServerInterceptorLimiter returns a new stream server interceptor that performs rate limiting on the request. 38 | func StreamServerInterceptorLimiter(limiter *rate.Limiter) grpc.StreamServerInterceptor { 39 | return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { 40 | if !limiter.Allow() { 41 | return status.Errorf(codes.ResourceExhausted, "%s is rejected by ratelimit middleware, please retry later.", info.FullMethod) 42 | } 43 | 44 | return handler(srv, stream) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /rpc/prometheus/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package prometheus implements plugin that allows to expose prometheus metrics. 16 | // Metrics are grouped in registries. Each registry is exposed at defined URL path. 17 | package prometheus 18 | -------------------------------------------------------------------------------- /rpc/prometheus/options.go: -------------------------------------------------------------------------------- 1 | package prometheus 2 | 3 | import ( 4 | "go.ligato.io/cn-infra/v2/logging" 5 | "go.ligato.io/cn-infra/v2/rpc/rest" 6 | ) 7 | 8 | // DefaultPlugin is a default instance of Plugin. 9 | var DefaultPlugin = *NewPlugin() 10 | 11 | // NewPlugin creates a new Plugin with the provided Options. 12 | func NewPlugin(opts ...Option) *Plugin { 13 | p := &Plugin{} 14 | 15 | p.PluginName = "prometheus" 16 | p.HTTP = &rest.DefaultPlugin 17 | 18 | for _, o := range opts { 19 | o(p) 20 | } 21 | 22 | if p.Deps.Log == nil { 23 | p.Deps.Log = logging.ForPlugin(p.String()) 24 | } 25 | 26 | return p 27 | } 28 | 29 | // Option is a function that can be used in NewPlugin to customize Plugin. 30 | type Option func(*Plugin) 31 | 32 | // UseDeps returns Option that can inject custom dependencies. 33 | func UseDeps(cb func(*Deps)) Option { 34 | return func(p *Plugin) { 35 | cb(&p.Deps) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /rpc/rest/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package rest implements the HTTP server through which plugins can 16 | // expose their REST APIs to the outside world. 17 | package rest 18 | -------------------------------------------------------------------------------- /rpc/rest/mock/doc.go: -------------------------------------------------------------------------------- 1 | // Package mock implements a mock HTTP server. 2 | package mock 3 | -------------------------------------------------------------------------------- /rpc/rest/mock/httpmock.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package mock 16 | 17 | import ( 18 | "io" 19 | "net/http" 20 | "net/http/httptest" 21 | 22 | "go.ligato.io/cn-infra/v2/rpc/rest" 23 | ) 24 | 25 | // HTTPMock is supposed to be used to mock real HTTP server but have the ability 26 | // to test all other httpmux plugin related code 27 | // 28 | // Example: 29 | // 30 | // httpmux.FromExistingServer(mock.SetHandler) 31 | // mock.NewRequest("GET", "/v1/a", nil) 32 | // 33 | type HTTPMock struct { 34 | handler http.Handler 35 | } 36 | 37 | // SetHandler is called from httpmux plugin during startup (handler is usually the gorilla mux instance) 38 | func (mock *HTTPMock) SetHandler(config rest.Config, handler http.Handler) (httpServer io.Closer, err error) { 39 | mock.handler = handler 40 | return &doNothingCloser{}, nil 41 | } 42 | 43 | // NewRequest propagates the request to the httpmux 44 | func (mock *HTTPMock) NewRequest(method, url string, body io.Reader) (*http.Response, error) { 45 | req, err := http.NewRequest(method, url, body) 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | recorder := httptest.NewRecorder() 51 | mock.handler.ServeHTTP(recorder, req) 52 | return recorder.Result(), nil 53 | } 54 | 55 | type doNothingCloser struct{} 56 | 57 | // Close does nothing 58 | func (*doNothingCloser) Close() error { 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /rpc/rest/plugin_api_rest.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package rest 16 | 17 | import ( 18 | "net/http" 19 | 20 | "github.com/gorilla/mux" 21 | "github.com/unrolled/render" 22 | 23 | access "go.ligato.io/cn-infra/v2/rpc/rest/security/model/access-security" 24 | ) 25 | 26 | // HandlerProvider is a function used for registering handlers via HTTPHandlers 27 | type HandlerProvider func(formatter *render.Render) http.HandlerFunc 28 | 29 | // HTTPHandlers defines the API exposed by the REST plugin. 30 | // Use this interface to declare dependency on the REST functionality, i.e.: 31 | // 32 | // type Deps struct { 33 | // HTTP rest.HTTPHandlers // inject plugin implementing RegisterHTTPHandler 34 | // // other dependencies ... 35 | // } 36 | // 37 | type HTTPHandlers interface { 38 | // RegisterHTTPHandler propagates to Gorilla mux 39 | RegisterHTTPHandler(path string, provider HandlerProvider, methods ...string) *mux.Route 40 | 41 | // RegisterPermissionGroup registers new permission groups for users 42 | RegisterPermissionGroup(group ...*access.PermissionGroup) 43 | 44 | // GetPort returns configured port number (for debugging purposes) 45 | GetPort() int 46 | } 47 | 48 | // BasicHTTPAuthenticator is a delegate that implements basic HTTP authentication 49 | type BasicHTTPAuthenticator interface { 50 | // Authenticate returns true if user is authenticated successfully, false otherwise. 51 | Authenticate(user string, pass string) bool 52 | } 53 | -------------------------------------------------------------------------------- /rpc/rest/security/model/access-security/accesssecurity.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "go.ligato.io/cn-infra/v2/rpc/rest/security/model/access-security"; 4 | 5 | // Package access_security provides basic definition of user and permission group 6 | package access_security; 7 | 8 | message User { 9 | string name = 1; 10 | string password = 2; 11 | repeated string permissions = 3; // Permission name, user is allowed for more permission groups 12 | } 13 | 14 | message PermissionGroup { 15 | string name = 1; 16 | message Permissions { 17 | string url = 1; // URL enabled for the permission 18 | repeated string allowed_methods = 2; // Methods enabled for the URL 19 | } 20 | repeated Permissions permissions = 2; 21 | } 22 | -------------------------------------------------------------------------------- /rpc/rest/security/password-hasher/README.md: -------------------------------------------------------------------------------- 1 | # Password Hasher 2 | 3 | RPC plugin allows to register users via config file, where user name, password 4 | in hash format and permission groups are required. To make it easier, this utility 5 | can help with password hashing. 6 | 7 | ``` 8 | password-hasher 9 | ``` 10 | 11 | Put desired password as first parameter, and cost value as second. Keep in mind 12 | that the cost value should match the one in security plugin, otherwise the password 13 | cannot be verified. Cost value range is 4 - 31, high numbers require a lot of memory 14 | and CPU time to process. -------------------------------------------------------------------------------- /scripts/check_links.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | res=0 4 | 5 | for i in `find . \( -path ./vendor -o -path ./vpp \) -prune -o -name "*.md"` 6 | do 7 | if [ -d "$i" ]; then 8 | continue 9 | fi 10 | 11 | out=$(FORCE_COLOR=1 markdown-link-check -q "$i") 12 | if [ "$?" -ne 0 ]; then 13 | echo "${out}" 14 | res=1 15 | fi 16 | done 17 | 18 | exit $res 19 | -------------------------------------------------------------------------------- /scripts/gofmt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | find $(pwd) -mount -name "*.go" -type f -not -path $(pwd)"/vendor/*" -exec gofmt -w -s {} + 4 | -------------------------------------------------------------------------------- /scripts/install-consul.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | CONSUL_VERSION=1.5.3 5 | 6 | download_url=https://releases.hashicorp.com/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_amd64.zip 7 | 8 | wget -nv -O /tmp/consul.zip ${download_url} 9 | unzip -o /tmp/consul.zip -d /tmp/consul 10 | sudo mv /tmp/consul/consul /usr/local/bin 11 | rm -rf /tmp/consul.zip /tmp/consul 12 | -------------------------------------------------------------------------------- /scripts/static_analysis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # files to exclude based on file content 6 | excludeContent="^// DO NOT EDIT|^// File generated by|^// Automatically generated|^// Code generated by protoc-gen-go. DO NOT EDIT.|^// Code generated by protoc-gen-gogo. DO NOT EDIT." 7 | filesToExclude=$(echo $(echo $(grep -lrE "${excludeContent}" | grep '\.go' | fgrep -v vendor/ | sed -e "s/$/|/g") | sed -e "s/| /|/g") | sed -e "s/|$//g") 8 | 9 | # linters to run based on parameters of this script 10 | enabledLinters="" 11 | for linterName in $*; 12 | do 13 | enabledLinters=${enabledLinters}" --enable=${linterName}" 14 | done 15 | 16 | # running linters (excluding vendor,...) 17 | golangci-lint run \ 18 | -v \ 19 | --timeout 2m \ 20 | --disable-all ${enabledLinters} \ 21 | --exclude=vendor \ 22 | --exclude="should not use dot imports" \ 23 | --exclude=${filesToExclude} \ 24 | ./... 25 | -------------------------------------------------------------------------------- /servicelabel/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package servicelabel provides support for creating/retrieving an 16 | // identifier (a service label) for a CN-Infra based app. 17 | // 18 | // p := serviceLabel.Plugin{} 19 | // // initialization plugin handled by agent core 20 | // 21 | // To retrieve service label of the VNF instance, run: 22 | // label = p.GetAgentLabel() 23 | // 24 | // To retrieve prefix that can be used to access configuration of the VNF instance in key-value datastore, run: 25 | // prefix = p.GetAgentPrefix() 26 | // 27 | // To retrieve prefix for a different VNF instance, run: 28 | // otherPrefix = p.GetDifferentAgentPrefix(differentLabel) 29 | // 30 | // To retrieve prefix that identifies configuration of all instances: 31 | // allInstances = p.GetAllAgentsPrefix() 32 | package servicelabel 33 | -------------------------------------------------------------------------------- /servicelabel/options.go: -------------------------------------------------------------------------------- 1 | package servicelabel 2 | 3 | // DefaultPlugin is a default instance of Plugin. 4 | var DefaultPlugin = *NewPlugin() 5 | 6 | // NewPlugin creates a new Plugin with the provided Options. 7 | func NewPlugin(opts ...Option) *Plugin { 8 | p := &Plugin{} 9 | 10 | p.PluginName = "service-label" 11 | 12 | for _, o := range opts { 13 | o(p) 14 | } 15 | 16 | return p 17 | } 18 | 19 | // Option is a function that can be used in NewPlugin to customize Plugin. 20 | type Option func(*Plugin) 21 | 22 | // UseLabel sets microservice label to given string 23 | func UseLabel(label string) Option { 24 | return func(p *Plugin) { 25 | p.MicroserviceLabel = label 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /utils/addrs/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package addrs contains helpers for ip and mac address conversion. 16 | package addrs 17 | -------------------------------------------------------------------------------- /utils/addrs/mac.go: -------------------------------------------------------------------------------- 1 | package addrs 2 | 3 | import ( 4 | "bytes" 5 | "strconv" 6 | ) 7 | 8 | // MacIntToString converts MAC address string representation xx:xx:xx:xx:xx:xx 9 | func MacIntToString(macInt uint64) string { 10 | const padding = "000000000000" 11 | macStr := strconv.FormatInt(int64(macInt), 16) 12 | padded := padding[:len(padding)-len(macStr)] + macStr 13 | var buffer bytes.Buffer 14 | 15 | for index, char := range padded { 16 | buffer.WriteRune(char) 17 | if (index%2 == 1) && index != len(padded)-1 { 18 | buffer.WriteRune(':') 19 | } 20 | } 21 | return buffer.String() 22 | } 23 | -------------------------------------------------------------------------------- /utils/clienttls/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package clienttls provides tls utilities. 16 | package clienttls 17 | -------------------------------------------------------------------------------- /utils/doc.go: -------------------------------------------------------------------------------- 1 | // Package utils contains multiple utilities and helper functions. 2 | package utils 3 | -------------------------------------------------------------------------------- /utils/once/return_error.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package once 16 | 17 | import "sync" 18 | 19 | // ReturnError is a wrapper around sync.Once that properly handles: 20 | // func() error 21 | // instead of just 22 | // func() 23 | type ReturnError struct { 24 | once sync.Once 25 | err error 26 | } 27 | 28 | // Do provides the same functionality as sync.Once.Do(func()) but for 29 | // func() error 30 | func (owe *ReturnError) Do(f func() error) error { 31 | owe.once.Do(func() { 32 | owe.err = f() 33 | }) 34 | return owe.err 35 | } 36 | -------------------------------------------------------------------------------- /utils/once/return_error_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package once_test 16 | 17 | import ( 18 | "errors" 19 | "testing" 20 | 21 | "github.com/onsi/gomega" 22 | 23 | "go.ligato.io/cn-infra/v2/utils/once" 24 | ) 25 | 26 | const ( 27 | testErrorString = "This is a test error" 28 | ) 29 | 30 | func returnErr() error { 31 | err := errors.New(testErrorString) 32 | return err 33 | } 34 | 35 | func TestBasicUsage(t *testing.T) { 36 | gomega.RegisterTestingT(t) 37 | owe := &once.ReturnError{} 38 | err := owe.Do(func() error { 39 | return returnErr() 40 | }) 41 | gomega.Expect(err).ShouldNot(gomega.BeNil()) 42 | gomega.Expect(err.Error()).Should(gomega.Equal(testErrorString)) 43 | } 44 | -------------------------------------------------------------------------------- /utils/ratelimit/limiters.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package ratelimit 16 | 17 | import ( 18 | "sync" 19 | 20 | "golang.org/x/time/rate" 21 | ) 22 | 23 | // Limiters provides map of rate limiters per X (user, IP..). 24 | type Limiters struct { 25 | limiters *sync.Map 26 | rate rate.Limit 27 | burst int 28 | } 29 | 30 | func NewLimiter(r rate.Limit, burst int) *Limiters { 31 | i := &Limiters{ 32 | limiters: new(sync.Map), 33 | rate: r, 34 | burst: burst, 35 | } 36 | return i 37 | } 38 | 39 | // Add creates a new rate limiter and adds it to the map. 40 | func (l *Limiters) Add(key string) *rate.Limiter { 41 | limiter := rate.NewLimiter(l.rate, l.burst) 42 | 43 | l.limiters.Store(key, limiter) 44 | 45 | return limiter 46 | } 47 | 48 | // Get returns the rate limiter for the provided key if it exists, 49 | // otherwise calls Add to add key to the map. 50 | func (l *Limiters) Get(key string) *rate.Limiter { 51 | if limiter, ok := l.limiters.Load(key); ok { 52 | return limiter.(*rate.Limiter) 53 | } 54 | 55 | return l.Add(key) 56 | } 57 | 58 | func (l *Limiters) Allow(key string) bool { 59 | limiter := l.Get(key) 60 | return limiter.Allow() 61 | } 62 | -------------------------------------------------------------------------------- /utils/redact/enable_strict.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // +build redact 16 | 17 | package redact 18 | 19 | const enabled = true 20 | -------------------------------------------------------------------------------- /utils/redact/enable_toggle.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // +build !redact 16 | 17 | package redact 18 | 19 | import "os" 20 | 21 | var enabled = true 22 | 23 | func init() { 24 | if os.Getenv("NOREDACT") != "" { 25 | enabled = false 26 | } 27 | } 28 | 29 | // SetEnabled can be used to toggle redact functionality. 30 | func SetEnabled(b bool) { 31 | enabled = b 32 | } 33 | -------------------------------------------------------------------------------- /utils/redact/string.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package redact 16 | 17 | import "strings" 18 | 19 | // MaskedString is a type that masks an actual string data. 20 | // It implements fmt.Stringer and encoding.TextMarshaler for returning 21 | // asterisks `*` characters with same length as the actual string value. 22 | type MaskedString string 23 | 24 | func (s MaskedString) Redacted() interface{} { 25 | return s.String() 26 | } 27 | 28 | func (s MaskedString) String() string { 29 | return strings.Repeat("*", len(s)) 30 | } 31 | 32 | func (s MaskedString) MarshalText() (text []byte, err error) { 33 | return []byte(s.String()), nil 34 | } 35 | -------------------------------------------------------------------------------- /utils/redact/string_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package redact 16 | 17 | import ( 18 | "fmt" 19 | "testing" 20 | ) 21 | 22 | func TestMaskedString(t *testing.T) { 23 | var input = "data" 24 | const masked = "****" 25 | 26 | clear := fmt.Sprintf("%s", input) 27 | if clear != input { 28 | t.Fatalf("expected:\n%q, got\n%q", input, clear) 29 | } 30 | 31 | out := fmt.Sprintf("%s", MaskedString(input)) 32 | if out != masked { 33 | t.Fatalf("expected:\n%q, got\n%q", masked, out) 34 | } 35 | } 36 | 37 | func TestMaskedData(t *testing.T) { 38 | type Data struct { 39 | Clear string 40 | Secret MaskedString 41 | } 42 | data := Data{"clear", "secret"} 43 | const redacted = `{Clear:clear Secret:******}` 44 | 45 | out := fmt.Sprintf("%+v", data) 46 | if out != redacted { 47 | t.Fatalf("expected:\n%q, got\n%q", redacted, out) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /utils/redact/testdata/model.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "go.ligato.io/cn-infra/v2/utils/redact/testdata"; 4 | 5 | package testdata; 6 | 7 | message TestData { 8 | string username = 1; 9 | string password = 2; 10 | } 11 | 12 | message TestNested { 13 | string name = 1; 14 | TestData data = 2; 15 | } 16 | 17 | message TestSlice { 18 | string name = 1; 19 | repeated TestData data = 2; 20 | } 21 | -------------------------------------------------------------------------------- /utils/redact/testdata/redactor.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package testdata 16 | 17 | import ( 18 | "google.golang.org/protobuf/proto" 19 | 20 | "go.ligato.io/cn-infra/v2/utils/redact" 21 | ) 22 | 23 | //go:generate protoc --proto_path=. --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. model.proto 24 | 25 | func (m *TestData) Redacted() interface{} { 26 | r := proto.Clone(m).(*TestData) 27 | r.Password = redact.String(r.Password) 28 | return r 29 | } 30 | -------------------------------------------------------------------------------- /utils/runtimeutils/doc.go: -------------------------------------------------------------------------------- 1 | // Package runtimeutils contains utilities for inspecting Go's runtime system. 2 | package runtimeutils 3 | -------------------------------------------------------------------------------- /utils/runtimeutils/runtimeutils.go: -------------------------------------------------------------------------------- 1 | package runtimeutils 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "reflect" 7 | "runtime" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | var goroutineSpace = []byte("goroutine ") 13 | 14 | // GoroutineID returns current GO Routine ID (parsed from runtime.Stack) 15 | func GoroutineID() uint64 { 16 | b := make([]byte, 64) 17 | b = b[:runtime.Stack(b, false)] 18 | // Parse the 4707 out of "goroutine 4707 [" 19 | b = bytes.TrimPrefix(b, goroutineSpace) 20 | i := bytes.IndexByte(b, ' ') 21 | if i < 0 { 22 | panic(fmt.Sprintf("No space found in %q", b)) 23 | } 24 | b = b[:i] 25 | n, err := strconv.ParseUint(string(b), 10, 64) 26 | if err != nil { 27 | panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", b, err)) 28 | } 29 | return n 30 | } 31 | 32 | // GetFunction returns metadata about function based on pointer to a function 33 | // 34 | // Example usage: 35 | // 36 | // func foo() {} 37 | // GetFunction(foo) 38 | func GetFunction(function interface{}) *runtime.Func { 39 | return runtime.FuncForPC(reflect.ValueOf(function).Pointer()) 40 | } 41 | 42 | // GetFunctionName returns name of the function 43 | // 44 | // Example usage: 45 | // 46 | // func foo() {} 47 | // GetFunctionName(foo) // returns string containing "foo" substring 48 | func GetFunctionName(function interface{}) string { 49 | fullName := GetFunction(function).Name() 50 | name := strings.TrimSuffix(fullName, "-fm") 51 | dot := strings.LastIndex(name, ".") 52 | if dot > 0 && dot+1 < len(name) { 53 | return name[dot+1:] 54 | } 55 | return fullName 56 | } 57 | -------------------------------------------------------------------------------- /utils/safeclose/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package safeclose provides utilities for safe closing of I/O resources. 16 | package safeclose 17 | -------------------------------------------------------------------------------- /utils/structs/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Cisco and/or its affiliates. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package structs provides reflection utilities to inspect structures. 16 | package structs 17 | --------------------------------------------------------------------------------