Skip to content

Commit cc4cf71

Browse files
authored
Merge pull request #126 from richiMarchi/add_feature_loadtopology
Add feature loadtopology
2 parents 8659149 + ee9e8c5 commit cc4cf71

File tree

7 files changed

+136
-31
lines changed

7 files changed

+136
-31
lines changed

Documentation/polycubectl/polycubectl.rst

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,15 @@ How to use
1515
----------
1616

1717
**NOTE**: ``polycubed`` must be running, in order to use ``polycubectl``.
18-
You can start the daemon typing ``sudo polycubed`` in another terminal. Refer to :doc:`Quick Start <../quickstart>`.
18+
You can start the daemon typing ``sudo polycubed`` in another terminal.
19+
Refer to :doc:`Quick Start <../quickstart>`.
1920

2021
``polycubectl`` is a generic CLI, that enables the user to interact with ``Cubes`` (``bridge``, ``router``, ...) and with some framework primitives to ``connect``, ``show`` and build complex ``topologies``.
2122

2223
::
2324

2425
# Show help
2526
polycubectl --help
26-
27-
::
28-
2927
Keyword Type Description
3028
simpleforwarder service Simple Forwarder Base Service
3129
simplebridge service Simple L2 Bridge Service
@@ -45,14 +43,71 @@ You can start the daemon typing ``sudo polycubed`` in another terminal. Refer to
4543
connect command Connect ports
4644
disconnect command Disconnect ports
4745

48-
attach command Attach transparent cubes
49-
detach command Detach transparent cubes
46+
attach command Attach transparent cubes
47+
detach command Detach transparent cubes
5048

5149
services command Show/Add/Del services (e.g. Bridge, Router, ..)
5250
cubes command Show running service instances (e.g. br1, nat2, ..)
5351
topology command Show topology of service instances
5452
netdevs command Show net devices available
5553

54+
``polycubectl`` is service agnostic, hence the syntax is service dependent.
55+
However we can generalize the syntax as:
56+
57+
::
58+
59+
polycubectl [parent] [command] [child] [argument0=value0] [argument1=value1]
60+
61+
62+
- ``parent``: path of the parent resource where the command has to be applied.
63+
- ``command``: ``add``, ``del``, ``show``, ``set`` or a yang action.
64+
- ``child``: specific resource where the command is applied.
65+
- ``argument``: some commands accept additional commands that are sent in the body request.
66+
67+
Some examples:
68+
69+
::
70+
71+
polycubectl router r0 add loglevel=debug
72+
polycubectl r0 ports add port1 ip=10.1.0.1 netmask=255.255.0.0
73+
polycubectl r0 show routing table
74+
polycubectl r0 ports port1 set peer=veth1
75+
polycubectl r0 ports del port1
76+
77+
# yang action
78+
polycubectl firewall1 chain ingress append src=10.0.0.1 action=DROP
79+
80+
81+
The best way to know what is the syntax for each service is to use the `Help`_ or the bash completion by pressing ``<TAB>`` at any point.
82+
83+
84+
``polycubectl`` is also able to read the contents of the request from the standard input, it can be used in two ways:
85+
86+
Passing complex configuration from the command line
87+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
88+
::
89+
90+
# create a helloworld instance with loglevel debug and action forward
91+
polycubectl helloworld add hw0 << EOF
92+
{
93+
"loglevel": "debug",
94+
"action": "forward"
95+
}
96+
EOF
97+
98+
99+
Reading configuration from a file
100+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
101+
::
102+
103+
# create helloworld from a yaml file
104+
polycubectl helloworld add hw0 < hw0.yaml
105+
106+
# create a router from a json file
107+
polycubectl router add r0 < r0.json
108+
109+
# add a list of cubes
110+
polycubectl cubes add < mycubes.yaml
56111

57112
Help
58113
^^^^
@@ -124,7 +179,8 @@ More complete examples are available in :doc:`tutorials <../tutorials/index>`.
124179
Configuration
125180
-------------
126181

127-
By default, the CLI contacts ``polycubed`` daemon at ``http://localhost:9000/polycube/v1/``. The user can override this configuration with following instructions.
182+
By default, ``polycubectl`` contacts ``polycubed`` at ``http://localhost:9000/polycube/v1/``.
183+
The user can override this configuration with following instructions.
128184

129185
Parameters
130186
^^^^^^^^^^

src/polycubectl/aliases.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package main
1818

1919
import (
2020
"fmt"
21-
//"reflect"
2221
"github.com/polycube-network/polycube/src/polycubectl/cliargs"
2322
)
2423

src/polycubectl/cliargs/cliargs.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ import (
2121
"strconv"
2222
"strings"
2323

24+
"os"
25+
"bufio"
26+
"bytes"
27+
"github.com/ghodss/yaml"
28+
2429
"github.com/polycube-network/polycube/src/polycubectl/config"
2530
"github.com/polycube-network/polycube/src/polycubectl/httprequest"
2631

@@ -441,7 +446,25 @@ func (cli *CLIArgs) GetHTTPRequest() (*httprequest.HTTPRequest, error) {
441446
url += url0
442447
body = body0
443448
} else {
444-
body = cli.buildBody()
449+
// if there is text on the standard input that'll used as the body
450+
var buffer bytes.Buffer
451+
reader := bufio.NewReader(os.Stdin)
452+
text, _ := reader.ReadString('\n')
453+
for text != "" {
454+
buffer.WriteString(text)
455+
text, _ = reader.ReadString('\n')
456+
}
457+
458+
if buffer.Len() > 0 {
459+
jsonBuff, err := yaml.YAMLToJSON(buffer.Bytes())
460+
if err != nil {
461+
return nil, err
462+
} else {
463+
body = jsonBuff
464+
}
465+
} else {
466+
body = cli.buildBody()
467+
}
445468
}
446469
}
447470

src/polycubed/src/rest_server.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ void RestServer::setup_routes() {
171171
router_->get(base + std::string("/cubes/:cubeName"),
172172
bind(&RestServer::get_cube, this));
173173

174+
router_->post(base + std::string("/cubes"),
175+
bind(&RestServer::post_cubes, this));
176+
174177
router_->options(base + std::string("/cubes"),
175178
bind(&RestServer::cubes_help, this));
176179

@@ -428,6 +431,31 @@ void RestServer::get_cube(const Pistache::Rest::Request &request,
428431
}
429432
}
430433

434+
void RestServer::post_cubes(const Pistache::Rest::Request &request,
435+
Pistache::Http::ResponseWriter response) {
436+
logRequest(request);
437+
try {
438+
json j = json::parse(request.body());
439+
logJson(j);
440+
std::vector<Response> resp = {{ErrorTag::kNoContent, nullptr}};
441+
bool error = false;
442+
for (auto &it : j) {
443+
resp = core.get_service_controller(it["service-name"]).get_management_interface()->get_service()
444+
->CreateReplaceUpdate(it["name"], it, false, true);
445+
if (!error && resp[0].error_tag != kCreated) {
446+
Rest::Server::ResponseGenerator::Generate(std::move(resp), std::move(response));
447+
error = true;
448+
}
449+
}
450+
if (!error) {
451+
Rest::Server::ResponseGenerator::Generate(std::move(resp), std::move(response));
452+
}
453+
} catch (const std::runtime_error &e) {
454+
logger->error("{0}", e.what());
455+
response.send(Pistache::Http::Code::Bad_Request, e.what());
456+
}
457+
}
458+
431459
void RestServer::cubes_help(const Pistache::Rest::Request &request,
432460
Pistache::Http::ResponseWriter response) {
433461
json j = json::object();

src/polycubed/src/rest_server.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ class RestServer {
8585
void get_cube(const Pistache::Rest::Request &request,
8686
Pistache::Http::ResponseWriter response);
8787

88+
void post_cubes(const Pistache::Rest::Request &request,
89+
Pistache::Http::ResponseWriter response);
90+
8891
void cubes_help(const Pistache::Rest::Request &request,
8992
Pistache::Http::ResponseWriter response);
9093

src/polycubed/src/server/Resources/Endpoint/Service.cpp

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,8 @@ void Service::ClearCubes() {
6767
}
6868
}
6969

70-
void Service::CreateReplaceUpdate(const std::string &name, nlohmann::json &body,
71-
ResponseWriter response, bool update,
72-
bool initialization) {
70+
std::vector<Response>
71+
Service::CreateReplaceUpdate(const std::string &name, nlohmann::json &body, bool update, bool initialization) {
7372
if (update || !ServiceController::exists_cube(name)) {
7473
auto op = OperationType(update, initialization);
7574
auto k = ListKeyValues{};
@@ -82,9 +81,7 @@ void Service::CreateReplaceUpdate(const std::string &name, nlohmann::json &body,
8281

8382
auto body_errors = BodyValidate(name, k, jbody, initialization);
8483
if (!body_errors.empty()) {
85-
Server::ResponseGenerator::Generate(std::move(body_errors),
86-
std::move(response));
87-
return;
84+
return std::move(body_errors);
8885
}
8986

9087
auto resp = WriteValue(name, body, k, op);
@@ -93,12 +90,9 @@ void Service::CreateReplaceUpdate(const std::string &name, nlohmann::json &body,
9390
resp.error_tag == ErrorTag::kNoContent)) {
9491
cube_names_.AddValue(name);
9592
}
96-
Server::ResponseGenerator::Generate(std::vector<Response>{resp},
97-
std::move(response));
93+
return std::vector<Response>{resp};
9894
} else {
99-
Server::ResponseGenerator::Generate(
100-
std::vector<Response>{{ErrorTag::kDataExists, nullptr}},
101-
std::move(response));
95+
return std::vector<Response>{{ErrorTag::kDataExists, nullptr}};
10296
}
10397
}
10498

@@ -129,8 +123,8 @@ void Service::post_body(const Request &request, ResponseWriter response) {
129123
return;
130124
}
131125

132-
CreateReplaceUpdate(body["name"].get<std::string>(), body,
133-
std::move(response), false, true);
126+
auto resp = CreateReplaceUpdate(body["name"].get<std::string>(), body, false, true);
127+
Server:: ResponseGenerator::Generate(std::move(resp), std::move(response));
134128
}
135129

136130
void Service::post(const Request &request, ResponseWriter response) {
@@ -151,7 +145,8 @@ void Service::post(const Request &request, ResponseWriter response) {
151145
}
152146
}
153147

154-
CreateReplaceUpdate(name, body, std::move(response), false, true);
148+
auto resp = CreateReplaceUpdate(name, body, false, true);
149+
Server:: ResponseGenerator::Generate(std::move(resp), std::move(response));
155150
}
156151

157152
void Service::put(const Request &request, ResponseWriter response) {
@@ -163,7 +158,8 @@ void Service::put(const Request &request, ResponseWriter response) {
163158
body = nlohmann::json::parse(request.body());
164159
}
165160
body["name"] = name;
166-
CreateReplaceUpdate(name, body, std::move(response), false, true);
161+
auto resp = CreateReplaceUpdate(name, body, false, true);
162+
Server:: ResponseGenerator::Generate(std::move(resp), std::move(response));
167163
}
168164

169165
void Service::patch(const Request &request, ResponseWriter response) {
@@ -175,7 +171,8 @@ void Service::patch(const Request &request, ResponseWriter response) {
175171
body = nlohmann::json::parse(request.body());
176172
}
177173
body["name"] = name;
178-
CreateReplaceUpdate(name, body, std::move(response), true, false);
174+
auto resp = CreateReplaceUpdate(name, body, true, false);
175+
Server:: ResponseGenerator::Generate(std::move(resp), std::move(response));
179176
}
180177

181178
void Service::del(const Pistache::Rest::Request &request,
@@ -203,8 +200,8 @@ void Service::patch_body(const Request &request, ResponseWriter response) {
203200
std::move(response));
204201
return;
205202
}
206-
CreateReplaceUpdate(body["name"].get<std::string>(), body,
207-
std::move(response), true, false);
203+
auto resp = CreateReplaceUpdate(body["name"].get<std::string>(), body, true, false);
204+
Server:: ResponseGenerator::Generate(std::move(resp), std::move(response));
208205
}
209206

210207
void Service::options_body(const Request &request, ResponseWriter response) {

src/polycubed/src/server/Resources/Endpoint/Service.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,13 @@ class Service : public ParentResource, public Body::Service {
5656

5757
virtual Response ReadHelp() = 0;
5858

59+
std::vector<Response> CreateReplaceUpdate(const std::string &name, nlohmann::json &body,
60+
bool update, bool initialization);
61+
5962
private:
6063
const std::string body_rest_endpoint_;
6164
Validators::InSetValidator cube_names_;
6265

63-
void CreateReplaceUpdate(const std::string &name, nlohmann::json &body,
64-
ResponseWriter response, bool replace,
65-
bool initialization);
66-
6766
nlohmann::json getServiceKeys() const;
6867

6968
void post(const Request &request, ResponseWriter response) final;

0 commit comments

Comments
 (0)