diff --git a/.gitignore b/.gitignore index c910b72b6..d16904b57 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ tmp .settings .classpath target +!hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target .allure .vscode .springbeans diff --git a/README.md b/README.md index d8de696ea..9f81604b9 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ Eclipse [hawkBit](http://www.eclipse.org/hawkbit/index.html) is an domain independent back end solution for rolling out software updates to constrained edge devices as well as more powerful controllers and gateways connected to IP based networking infrastructure. Build: [![Circle CI](https://circleci.com/gh/eclipse/hawkbit.svg?style=shield)](https://circleci.com/gh/eclipse/hawkbit) - [![SonarQuality](https://sonar.ops.bosch-iot-rollouts.com/api/badges/gate?key=org.eclipse.hawkbit:hawkbit-parent)](https://sonar.ops.bosch-iot-rollouts.com) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.eclipse.hawkbit/hawkbit-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.eclipse.hawkbit/hawkbit-parent) + [![SonarQuality](https://sonar.ops.bosch-iot-rollouts.com/api/badges/gate?key=org.eclipse.hawkbit:hawkbit-parent)](https://sonar.ops.bosch-iot-rollouts.com) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.eclipse.hawkbit/hawkbit-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.eclipse.hawkbit/hawkbit-parent) + +Docker images: [![Docker](https://images.microbadger.com/badges/version/hawkbit/hawkbit-update-server:0.2.0M9.svg)](https://microbadger.com/images/hawkbit/hawkbit-update-server:0.2.0M9 "Get your own version badge on microbadger.com") [![Docker MYSQL](https://images.microbadger.com/badges/version/hawkbit/hawkbit-update-server:0.2.0M9-mysql.svg)](https://microbadger.com/images/hawkbit/hawkbit-update-server:0.2.0M9-mysql "Get your own version badge on microbadger.com") # Documentation diff --git a/docs/README.md b/docs/README.md index cc9a3475f..dd4a1f1b0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,16 +2,22 @@ The hawkBit documentation is based on [Jekyll](http://jekyllrb.com/). Jekyll is a Ruby gem and thus requires a Ruby runtime to be executed. Compiling the documentation is not included within the regular Maven build. -# Build and Serve documentation +## Build and Serve documentation + +### Unix / Mac -## Unix / Mac On a unix or mac you don't need to extra install Jekyll. The Maven build is downloading the ruby runtime and the necessary ruby-gems via the Maven rubygems-proxy repository. The Ruby runtime is downloaded into the `target` folder and executed during the build. To serve the current documentation you only need to call `mvn install gem:exec@jekyll-serve` (within the `docs` folder). It automatically monitors the filesystem and every local changes are generated on-demand on the local server [http://127.0.0.1:4000/hawkbit/](http://127.0.0.1:4000/hawkbit/). -## Windows +### Windows + On a Windows operating system you'll need to install Jekyll manually. If you don't have installed Jekyll on your machine you can use the [PortableJekyll](https://github.com/madhur/PortableJekyll) project. Just clone the Github repository and start the `setpath.cmd` which setups the necessary path entries into the CMD (don't forget to copy them into the environment path variable to have the path set for every command prompt). The Maven build on windows just executes the `Jekyll` process using the maven-exec plugin. This allows to use Maven to build and serve the documentation on a windows machine as well. To serve the current documentation you only need to call `mvn exec:exec@jekyll-serve`. It automatically monitors the filesystem and every local changes are generated on-demand on the local server [http://127.0.0.1:4000/hawkbit/](http://127.0.0.1:4000/hawkbit/). + +## Test API docs integration + +In order to verify the hawkbit-rest-docs integration you have to run the serve command above and when running call `mvn install`in parallel to include the generated rest docs into the serve run. diff --git a/docs/pom.xml b/docs/pom.xml index 7879d0fe2..ea0e46309 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -86,6 +86,32 @@ false + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack-api-docs + generate-resources + + unpack + + + + + org.eclipse.hawkbit + hawkbit-rest-docs + ${project.version} + jar + true + ${basedir}/target/classes/documentation/ + ** + + + + + + diff --git a/docs/src/main/resources/_includes/footer.html b/docs/src/main/resources/_includes/footer.html index 39c18b672..893744e14 100644 --- a/docs/src/main/resources/_includes/footer.html +++ b/docs/src/main/resources/_includes/footer.html @@ -1,25 +1,26 @@ - + \ No newline at end of file diff --git a/docs/src/main/resources/css/hawkbit.css b/docs/src/main/resources/css/hawkbit.css index 875341d57..390c4e308 100644 --- a/docs/src/main/resources/css/hawkbit.css +++ b/docs/src/main/resources/css/hawkbit.css @@ -1,8 +1,8 @@ @import url('http://fonts.googleapis.com/css?family=Open+Sans:300,300italic,600,600italic,700'); - body { - margin-top: 50px; /* padding for .navbar-fixed-top. */ - font-family:'Open Sans', sans-serif; + margin-top: 50px; + /* padding for .navbar-fixed-top. */ + font-family: 'Open Sans', sans-serif; line-height: 1.85em; color: #111; font-weight: 300; @@ -11,7 +11,13 @@ body { } a { - color:#0088cc; + color: #0088cc; +} + +iframe { + width: 100%; + height: 1280px; + border: 0; } a:hover { @@ -19,103 +25,102 @@ a:hover { } code { - color: #919191; - background-color: #f9f2f4; + color: #919191; + background-color: #f9f2f4; } -.image-center -{ +.image-center { margin: 0 auto; display: block; } -.image-left -{ +.image-left { float: left; margin: 0px 0 0px 0px; - padding: 20px; + padding: 20px; } .navbar-inverse .navbar-brand { font-size: 48px; font-weight: bold; - padding-top:10px; + padding-top: 10px; color: #6ab252; } .navbar-inverse .navbar-brand-logo { - background-image: url("../img/hawkbit_flower.png"); - background-size: 250px; - background-repeat: no-repeat; - position: absolute; - display: block; - width: 230px; + background-image: url("../img/hawkbit_flower.png"); + background-size: 250px; + background-repeat: no-repeat; + position: absolute; + display: block; + width: 230px; height: 200px; } + /*scroll stuff*/ -.navbar-lp{ + +.navbar-lp { -webkit-transition: height 0.3s; -moz-transition: height 0.3s; - transition: height 0.3s; + transition: height 0.3s; } .navbar-lp .navbar-brand { - font-size:65px; + font-size: 65px; font-weight: bold; - padding-top:40px; + padding-top: 40px; color: #6ab252; } .navbar-lp .navbar-brand-logo { - background-image: url("../img/hawkbit_flower.png"); - background-size: 250px; - background-repeat: no-repeat; - position: absolute; - display: block; - width: 250px; + background-image: url("../img/hawkbit_flower.png"); + background-size: 250px; + background-repeat: no-repeat; + position: absolute; + display: block; + width: 250px; height: 200px; - top: 0; + top: 0; } .navbar-lp .navbar-nav { - padding-top:30px; + padding-top: 30px; } -.navbar-lp -{ - -webkit-transition: all 0.3s; - -moz-transition: all 0.3s; - transition: all 0.3s; +.navbar-lp { + -webkit-transition: all 0.3s; + -moz-transition: all 0.3s; + transition: all 0.3s; } -.navbar-lp.scroll .navbar-brand -{ +.navbar-lp.scroll .navbar-brand { font-size: 48px; - padding-top:10px; + padding-top: 10px; -webkit-transition: all 0.3s; -moz-transition: all 0.3s; transition: all 0.3s; } .navbar-lp.scroll .navbar-brand-logo { - background-image: url("../img/hawkbit_flower.png"); - background-size: 80px; - background-repeat: no-repeat; - position: absolute; - width: 110px; - height: 80px; - top: 0; + background-image: url("../img/hawkbit_flower.png"); + background-size: 80px; + background-repeat: no-repeat; + position: absolute; + width: 110px; + height: 80px; + top: 0; } .navbar-lp.scroll .navbar-nav { - padding-top:0px; + padding-top: 0px; } + /*scroll stuff ends*/ .navbar-inverse .navbar-nav>li>a { - color: rgba(255,255,255,0.65); + color: rgba(255, 255, 255, 0.65); font-size: 16px; font-weight: bold; } @@ -134,12 +139,14 @@ code { border-color: #411355; } -.navbar-inverse .navbar-toggle:hover, .navbar-inverse .navbar-toggle:focus { +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { background-color: #411355; } -.navbar-inverse .navbar-collapse, .navbar-inverse .navbar-form { - border-color: rgba(255,255,255,0); +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: rgba(255, 255, 255, 0); } .header { @@ -156,12 +163,11 @@ code { .tagline { padding: 60px 0 50px; - } .tagline h1 { font-size: 60px; - color: rgba(255,255,255,0.9); + color: rgba(255, 255, 255, 0.9); } .box-separator { @@ -205,15 +211,12 @@ footer { .box-separator { margin: 50px 0; } - .box-img.pull-left { margin-right: 20px; } - .box-img.pull-right { margin-left: 20px; } - .box-headline { font-size: 35px; } @@ -223,15 +226,12 @@ footer { .box-separator { margin: 40px 0; } - .box-img.pull-left { margin-right: 10px; } - .box-img.pull-right { margin-left: 10px; } - .box-headline { font-size: 30px; } @@ -241,11 +241,9 @@ footer { .container { margin: 0 15px; } - .box-separator { margin: 40px 0; } - .box-headline { font-size: 25px; } @@ -265,17 +263,17 @@ footer { font-size: 65px; padding-top: 20px; } - .navbar-inverse .navbar-brand-logo { - background-image: url("../img/hawkbit_flower.png"); - background-size: 100px; - background-repeat: no-repeat; - position: absolute; - width: 100px; - height: 200px; - } + .navbar-inverse .navbar-brand-logo { + background-image: url("../img/hawkbit_flower.png"); + background-size: 100px; + background-repeat: no-repeat; + position: absolute; + width: 100px; + height: 200px; + } .tagline h1 { font-size: 45px; - margin-top: 10px; + margin-top: 10px; } } @@ -283,24 +281,23 @@ footer { .box-separator { margin: 10px 0; } - .box-img { max-width: 100%; } - .box-img.pull-left { margin-right: 0; margin-bottom: 10px; } - .box-img.pull-right { margin-bottom: 10px; margin-left: 0; } } + /*Content Header ========================*/ + .content-header { margin: 50px 0px; } @@ -309,18 +306,22 @@ footer { color: #666; } + /*Blog/News ========================*/ -.blogpost, .news { - padding:0 0 0px; + +.blogpost, +.news { + padding: 0 0 0px; margin: 20px 0 0px; } -.blogpost h3, .news h3 { +.blogpost h3, +.news h3 { font-size: 28px; } -.blogpost p .news p{ +.blogpost p .news p { margin: 20px 0; font-size: 18px; } @@ -331,7 +332,8 @@ footer { } .metadata ul { - margin: 0; padding: 0 + margin: 0; + padding: 0 } .metadata ul li { @@ -344,57 +346,71 @@ footer { color: #666; } + /*downloads ========================*/ -.box-dl h3{ + +.box-dl h3 { margin-top: 5px; font-weight: bold; color: #333; } -.box-dl .fa{ +.box-dl .fa { color: #999; } + + /*Home page Image-Hover*/ + .zoom1 { - -webkit-transform: scale(1); - transform: scale(1); - -ms-transform: scale(1); - -webkit-transition: .3s ease-in-out; - -ms-transition: .3s ease-in-out; - transition: .3s ease-in-out; + -webkit-transform: scale(1); + transform: scale(1); + -ms-transform: scale(1); + -webkit-transition: .3s ease-in-out; + -ms-transition: .3s ease-in-out; + transition: .3s ease-in-out; } + .zoom1:hover { - -webkit-transform: scale(0.9); - -ms-transform: scale(0.9); - transform: scale(0.9); + -webkit-transform: scale(0.9); + -ms-transform: scale(0.9); + transform: scale(0.9); } + /*Home page Image-VideoOverlay*/ -.thumb1, .thumb2, .thumb3,.thumb4, .thumb5{ - position: relative; + +.thumb1, +.thumb2, +.thumb3, +.thumb4, +.thumb5 { + position: relative; } -.thumb1 .play-icon{ - outline: medium none; - position: absolute; - z-index: 100; - opacity: 0.8; - color: #003151; - font-size: 4em; - left: 325px; - top: 125px; - +.thumb1 .play-icon { + outline: medium none; + position: absolute; + z-index: 100; + opacity: 0.8; + color: #003151; + font-size: 4em; + left: 325px; + top: 125px; } -.thumb1 .play-icon:hover, .thumb2 .play-icon:hover, .thumb3 .play-icon:hover, .thumb4 .play-icon:hover, .thumb5 .play-icon:hover{ -opacity: 1; --webkit-transform: scale(1.1); --ms-transform: scale(1.1); - transform: scale(1.1); +.thumb1 .play-icon:hover, +.thumb2 .play-icon:hover, +.thumb3 .play-icon:hover, +.thumb4 .play-icon:hover, +.thumb5 .play-icon:hover { + opacity: 1; + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); } - .thumb2 .play-icon { color: #003151; font-size: 4em; @@ -416,6 +432,7 @@ opacity: 1; z-index: 100; top: 115px; } + .thumb4 .play-icon { color: #003151; font-size: 4em; @@ -426,6 +443,7 @@ opacity: 1; z-index: 100; top: 125px; } + .thumb5 .play-icon { color: #003151; font-size: 4em; @@ -436,11 +454,14 @@ opacity: 1; z-index: 100; top: 125px; } + + /*community*/ + .team { - background: -moz-linear-gradient(center top , rgba(106, 178, 82, 1) 0%, rgba(147, 200, 130, 1) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); - background: linear-gradient(center top , rgba(106, 178, 82, 1) 0%, rgba(147, 200, 130, 1) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); - background: -webkit-linear-gradient(top , rgba(106, 178, 82, 1) 0%, rgba(147, 200, 130, 1) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); + background: -moz-linear-gradient(center top, rgba(106, 178, 82, 1) 0%, rgba(147, 200, 130, 1) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); + background: linear-gradient(center top, rgba(106, 178, 82, 1) 0%, rgba(147, 200, 130, 1) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); + background: -webkit-linear-gradient(top, rgba(106, 178, 82, 1) 0%, rgba(147, 200, 130, 1) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); border-radius: 30px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), 0 1px 0 rgba(0, 0, 0, 0.1) inset; height: auto; @@ -450,9 +471,9 @@ opacity: 1; } .team:hover { - background: -moz-linear-gradient(center top , rgba(106, 178, 82, 1) 0%, rgba(255, 255, 255, 0.3) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); - background: linear-gradient(center top , rgba(106, 178, 82, 1) 0%, rgba(255, 255, 255, 0.3) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); - background: -webkit-linear-gradient(top , rgba(106, 178, 82, 1) 0%, rgba(255, 255, 255, 0.3) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); + background: -moz-linear-gradient(center top, rgba(106, 178, 82, 1) 0%, rgba(255, 255, 255, 0.3) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); + background: linear-gradient(center top, rgba(106, 178, 82, 1) 0%, rgba(255, 255, 255, 0.3) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); + background: -webkit-linear-gradient(top, rgba(106, 178, 82, 1) 0%, rgba(255, 255, 255, 0.3) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); border-radius: 30px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), 0 1px 0 rgba(0, 0, 0, 0.1) inset; border: 0px solid #3300CC; @@ -462,13 +483,14 @@ opacity: 1; color: #333; } -/*Usecases*/ -.teamuc { - background: -moz-linear-gradient(center top , rgba(106, 178, 82, 1) 0%, rgba(177, 189, 205, 1) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); - background: linear-gradient(center top , rgba(106, 178, 82, 1) 0%, rgba(177, 189, 205, 1) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); - background: -webkit-linear-gradient(top , rgba(106, 178, 82, 1) 0%, rgba(177, 189, 205, 1) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a7cfdf', endColorstr='#23538a',GradientType=0 ); +/*Usecases*/ + +.teamuc { + background: -moz-linear-gradient(center top, rgba(106, 178, 82, 1) 0%, rgba(177, 189, 205, 1) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); + background: linear-gradient(center top, rgba(106, 178, 82, 1) 0%, rgba(177, 189, 205, 1) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); + background: -webkit-linear-gradient(top, rgba(106, 178, 82, 1) 0%, rgba(177, 189, 205, 1) 100%) repeat scroll 0 0 rgba(0, 0, 0, 0); + filter: progid: DXImageTransform.Microsoft.gradient( startColorstr='#a7cfdf', endColorstr='#23538a', GradientType=0); border-radius: 4px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), 0 1px 0 rgba(0, 0, 0, 0.1) inset; height: auto; @@ -478,106 +500,115 @@ opacity: 1; } p.ex { -color: #fff; + color: #fff; } + h2.ex { color: #fff; font-weight: bold; } + .vbtn { - background: #3498db; - background-image: -webkit-linear-gradient(top, #002E5C, #2980b9); - background-image: -moz-linear-gradient(top, #002E5C, #2980b9); - background-image: -ms-linear-gradient(top, #002E5C, #2980b9); - background-image: -o-linear-gradient(top, #002E5C, #2980b9); - background-image: linear-gradient(top bottom, #002E5C, #2980b9); - -webkit-border-radius: 28; - -moz-border-radius: 28; - border-radius: 28px; - color: #ffffff; - font-weight: bold; - padding: 10px 20px 10px 20px; - text-decoration: none; - } + background: #3498db; + background-image: -webkit-linear-gradient(top, #002E5C, #2980b9); + background-image: -moz-linear-gradient(top, #002E5C, #2980b9); + background-image: -ms-linear-gradient(top, #002E5C, #2980b9); + background-image: -o-linear-gradient(top, #002E5C, #2980b9); + background-image: linear-gradient(top bottom, #002E5C, #2980b9); + -webkit-border-radius: 28; + -moz-border-radius: 28; + border-radius: 28px; + color: #ffffff; + font-weight: bold; + padding: 10px 20px 10px 20px; + text-decoration: none; +} .vbtn:hover { - background: #3cb0fd; - background-image: -webkit-linear-gradient(top, #30567B, #3498db); - background-image: -moz-linear-gradient(top, #30567B, #3498db); - background-image: -ms-linear-gradient(top, #30567B, #3498db); - background-image: -o-linear-gradient(top, #30567B, #3498db); - background-image: linear-gradient(to bottom, #30567B, #3498db); - color: #ffffff; - font-weight: bold; - text-decoration: none; - box-shadow: inset 0 0 0 1px #27496d,0 5px 15px #193047; - + background: #3cb0fd; + background-image: -webkit-linear-gradient(top, #30567B, #3498db); + background-image: -moz-linear-gradient(top, #30567B, #3498db); + background-image: -ms-linear-gradient(top, #30567B, #3498db); + background-image: -o-linear-gradient(top, #30567B, #3498db); + background-image: linear-gradient(to bottom, #30567B, #3498db); + color: #ffffff; + font-weight: bold; + text-decoration: none; + box-shadow: inset 0 0 0 1px #27496d, 0 5px 15px #193047; } + .vbtn:active { - background: #3cb0fd; - background-image: -webkit-linear-gradient(top, #30567B, #3498db); - background-image: -moz-linear-gradient(top, #30567B, #3498db); - background-image: -ms-linear-gradient(top, #30567B, #3498db); - background-image: -o-linear-gradient(top, #30567B, #3498db); - background-image: linear-gradient(to bottom, #30567B, #3498db); - color: #ffffff; - font-weight: bold; - text-decoration: none; - box-shadow: inset 0 0 0 1px #27496d,0 5px 15px #193047; + background: #3cb0fd; + background-image: -webkit-linear-gradient(top, #30567B, #3498db); + background-image: -moz-linear-gradient(top, #30567B, #3498db); + background-image: -ms-linear-gradient(top, #30567B, #3498db); + background-image: -o-linear-gradient(top, #30567B, #3498db); + background-image: linear-gradient(to bottom, #30567B, #3498db); + color: #ffffff; + font-weight: bold; + text-decoration: none; + box-shadow: inset 0 0 0 1px #27496d, 0 5px 15px #193047; +} -} .vbtn:focus { - background: #3cb0fd; - background-image: -webkit-linear-gradient(top, #30567B, #3498db); - background-image: -moz-linear-gradient(top, #30567B, #3498db); - background-image: -ms-linear-gradient(top, #30567B, #3498db); - background-image: -o-linear-gradient(top, #30567B, #3498db); - background-image: linear-gradient(to bottom, #30567B, #3498db); - color: #ffffff; - font-weight: bold; - text-decoration: none; - box-shadow: inset 0 0 0 1px #27496d,0 5px 15px #193047; + background: #3cb0fd; + background-image: -webkit-linear-gradient(top, #30567B, #3498db); + background-image: -moz-linear-gradient(top, #30567B, #3498db); + background-image: -ms-linear-gradient(top, #30567B, #3498db); + background-image: -o-linear-gradient(top, #30567B, #3498db); + background-image: linear-gradient(to bottom, #30567B, #3498db); + color: #ffffff; + font-weight: bold; + text-decoration: none; + box-shadow: inset 0 0 0 1px #27496d, 0 5px 15px #193047; } + + /*Footer ========================*/ -footer{ - border-top:1px solid #eee; +footer { + border-top: 1px solid #eee; background: #f5f5f5; padding: 30px 0; color: #ccc; - margin-top:40px; - margin-bottom:0px; + margin-top: 40px; + margin-bottom: 0px; } #extra h3 { - font-weight: 400; - border-bottom: 1px solid #999; - padding: 5px; + font-weight: 400; + border-bottom: 1px solid #999; + padding: 5px; } + .footer-links-header { - color: #333; - padding-top: 0px; - margin-top: 0px; + color: #333; + padding-top: 0px; + margin-top: 0px; } + footer h3 { - margin-top: 16px; - margin-bottom: 6px; - font-size: 20px; - font-weight: 555; + margin-top: 16px; + margin-bottom: 6px; + font-size: 20px; + font-weight: 555; } + .footer-links { - width: 49%; - display: inline-block; - margin: 0; - list-style: none; + width: 49%; + display: inline-block; + margin: 0; + list-style: none; } footer ul { -webkit-padding-start: 0px; } + /*documentation*/ + .nav-bar { margin-top: 50px; background-color: #dadada; @@ -602,40 +633,54 @@ footer ul { } .info-note { - color: #2283A3; - font-size: 2em; + color: #2283A3; + font-size: 2em; } + /* blogs*/ @media (max-width: 767px) { - .blogstep .blogpicture {float:none; text-align:center;} - .blogstep .blogtext {padding:0;} + .blogstep .blogpicture { + float: none; + text-align: center; + } + .blogstep .blogtext { + padding: 0; + } } .blogstep { - padding:0 0 20px 40px; - background:url(../img/blogpics/stepline.png) no-repeat 10px 3px; + padding: 0 0 20px 40px; + background: url(../img/blogpics/stepline.png) no-repeat 10px 3px; } + .blogstep .blogpicture { - float:right; + float: right; } + .blogstep .blogpicture img { - max-width:100%; + max-width: 100%; } + .blogstep .blogtext { - padding:0 400px 0 0; - color:#848484; -} -.blogstep .blogtext p{ - padding-bottom:10px; -} -.blogstep .blogtext a{ - color:#0066FF; + padding: 0 400px 0 0; + color: #848484; } -.clear{ clear:both; height:0; overflow:hidden;} +.blogstep .blogtext p { + padding-bottom: 10px; +} +.blogstep .blogtext a { + color: #0066FF; +} + +.clear { + clear: both; + height: 0; + overflow: hidden; +} table { background: #B0C4DE none repeat scroll 0 0; @@ -643,57 +688,68 @@ table { border-radius: 4px; margin: 20px; width: 100%; - } + table th { - background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top , #B0C4DE, #B0C4DE) repeat scroll 0 0; - background: rgba(0, 0, 0, 0) linear-gradient(center top , #B0C4DE, #B0C4DE) repeat scroll 0 0; - background: rgba(0, 0, 0, 0) -webkit-linear-gradient(center top , #B0C4DE, #B0C4DE) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #B0C4DE, #B0C4DE) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) linear-gradient(center top, #B0C4DE, #B0C4DE) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) -webkit-linear-gradient(center top, #B0C4DE, #B0C4DE) repeat scroll 0 0; border-bottom: 1px solid #c0c0c0; border-top: 1px solid #e0e0e0; padding: 4px 6px; } + table tr:first-child th:first-child { border-top-left-radius: 3px; } + table tr:first-child th:last-child { border-top-right-radius: 3px; } + table td:first-child { border-left: 0 none; text-align: left; } + table td { - background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top , #fbfbfb, #fafafa) repeat scroll 0 0; - background: rgba(0, 0, 0, 0) linear-gradient(center top , #fbfbfb, #fafafa) repeat scroll 0 0; - background: rgba(0, 0, 0, 0) -webkit-linear-gradient(center top , #fbfbfb, #fafafa) repeat scroll 0 0; - border-bottom: 1px solid #e0e0e0; - border-left: 1px solid #e0e0e0; - border-top: 1px solid #f0f0f0; - padding: 4px 6px; + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #fbfbfb, #fafafa) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) linear-gradient(center top, #fbfbfb, #fafafa) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) -webkit-linear-gradient(center top, #fbfbfb, #fafafa) repeat scroll 0 0; + border-bottom: 1px solid #e0e0e0; + border-left: 1px solid #e0e0e0; + border-top: 1px solid #f0f0f0; + padding: 4px 6px; } + table tr.even td { - background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top , #f8f8f8, #f6f6f6) repeat scroll 0 0; - background: rgba(0, 0, 0, 0) linear-gradient(center top , #f8f8f8, #f6f6f6) repeat scroll 0 0; - background: rgba(0, 0, 0, 0) -webkit-linear-gradient(center top , #f8f8f8, #f6f6f6) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #f8f8f8, #f6f6f6) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) linear-gradient(center top, #f8f8f8, #f6f6f6) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) -webkit-linear-gradient(center top, #f8f8f8, #f6f6f6) repeat scroll 0 0; } + table tr:last-child td { border-bottom: 0 none; } + table tr:last-child td:first-child { border-bottom-left-radius: 3px; } + table tr:last-child td:last-child { border-bottom-right-radius: 3px; } + table tr:hover td { - background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top , #f2f2f2, #f0f0f0) repeat scroll 0 0; - background: rgba(0, 0, 0, 0) linear-gradient(center top , #f2f2f2, #f0f0f0) repeat scroll 0 0; - background: rgba(0, 0, 0, 0) -webkit-linear-gradient(center top , #f2f2f2, #f0f0f0) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) -moz-linear-gradient(center top, #f2f2f2, #f0f0f0) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) linear-gradient(center top, #f2f2f2, #f0f0f0) repeat scroll 0 0; + background: rgba(0, 0, 0, 0) -webkit-linear-gradient(center top, #f2f2f2, #f0f0f0) repeat scroll 0 0; } + #zoo table { margin: 0; } + .pricing { -moz-border-bottom-colors: none; -moz-border-left-colors: none; @@ -705,25 +761,27 @@ table tr:hover td { border-style: solid; border-width: 1px 1px 4px; color: #c0c2c2; - font-family: "Lato",sans-serif; + font-family: "Lato", sans-serif; font-size: 12px; font-weight: 400; margin-bottom: 40px; width: 100%; } + .pricing thead th { background: #333 none repeat scroll 0 0; border-top-left-radius: 4px; border-top-right-radius: 4px; color: #f4f4f4; float: left; - font-family: "Lato",sans-serif; + font-family: "Lato", sans-serif; font-size: 24px; padding: 13px 8%; text-align: center; text-transform: uppercase; width: 100%; } + .pricing tfoot td { background: #ededed none repeat scroll 0 0; border-bottom-left-radius: 6px; @@ -731,6 +789,7 @@ table tr:hover td { padding: 20px 8%; width: 100%; } + .pricing td { background: #fff none repeat scroll 0 0; border: 1px solid #d4d4d4; @@ -738,56 +797,66 @@ table tr:hover td { padding: 10px 8%; width: 100%; } + .pricing tfoot td { text-align: center; } + .pricing td.focus { - background: #3a5a82; none repeat scroll 0 0; + background: #3a5a82; + none repeat scroll 0 0; border-bottom: 1px solid #d4d4d4; color: #fff; - font-family: "Lato",sans-serif; + font-family: "Lato", sans-serif; font-size: 32px; font-weight: 400; padding: 25px 8%; text-align: center; width: 100%; } + .pricing td.focus-best { background: #a00 none repeat scroll 0 0; border-bottom: 1px solid #d4d4d4; color: #fff; - font-family: "Lato",sans-serif; + font-family: "Lato", sans-serif; font-size: 32px; font-weight: 400; padding: 25px 8%; text-align: center; width: 100%; } + .pricing td.focus span { display: block; font-size: 10px; margin-top: 5px; } + .pricing td.focus-best span { display: block; font-size: 10px; } + .pricing td h6 { color: #c0c2c2; float: left; - font-family: "Lato",sans-serif; + font-family: "Lato", sans-serif; font-size: 12px; font-weight: 400; width: 60%; } + .pricing td p { float: left; text-align: right; width: 40%; } + .btn-primary:hover { box-shadow: 0 0 3px rgba(0, 0, 0, 1); } -#tbltext{ + +#tbltext { color: #000000; -} +} \ No newline at end of file diff --git a/docs/src/main/resources/documentation/interfaces/ddi-api.md b/docs/src/main/resources/documentation/interfaces/ddi-api.md index 918651959..22a978a80 100644 --- a/docs/src/main/resources/documentation/interfaces/ddi-api.md +++ b/docs/src/main/resources/documentation/interfaces/ddi-api.md @@ -12,6 +12,7 @@ The _hawkbit_ [update server](https://github.com/eclipse/hawkbit) provides REST Note: in DDI the target is identified using a **controllerId**. Controller is used as a term for the actual service/client on the device. That allows users to have in some cases even multiple clients on the same target for different tasks, e.g. Firmware update and App management. # State Machine Mapping + For historical reasons the DDI has a different state machine and status messages than the [Target State Machine](../architecture/targetstate.html) of the _hawkBit_ update server. This is kept in order to ensure that _DDI_ stays compatible for devices out there in the field. A future version "2" of _DDI_ might change that. _DDI_ also defines more states than the update server, e.g. multiple DDI states are currently mapped by the _DDI_ implementation to _RUNNING_ state. It is possible that in the future _hawkBit_ will fully leverage these additional states. @@ -28,147 +29,5 @@ SCHEDULED | This can be used by the target to inform that it s RESUMED | This can be used by the target to inform that it continued to work on the action. | RUNNING # Resource Overview -The following chapters provide basic examples for the most important resources but we provide also a [detailed resource documentation](https://docs.bosch-iot-rollouts.com/documentation/rest-api/rootcontroller-api-guide.html). -## Base Poll Resource - -``` -GET /{tenant}/controller/v1/{controllerId} -``` - -In the answer to the baseUrl polling the backend can send action links. A possible action is a deploy command. The client makes a GET request on the given link: - -_Example Response_ - -``` -{ - "config": { - "polling": { - "sleep": "00:05:00" - } - }, - "_links": { - "deploymentBase": { - "href": "http://localhost:8080/default/controller/v1/example/deploymentBase/1?c=644088541" - }, - "configData": { - "href": "http://localhost:8080/default/controller/v1/example/configData" - } - } -} -``` - -## Deployment Base Resource - -``` -GET /{tenant}/controller/v1/{controllerId}/deploymentBase/{id} -``` - -_Example Response_ - -``` -{ - "deployment": { - "download": "forced", - "update": "forced", - "chunks": [ - { - "part": "os", - "version": "1.0.0", - "name": "Linux", - "artifacts": [ - { - "filename": "linux.zip", - "hashes": { - "sha1": "46fc56de883ec027759d8513458fe1010aa7e793", - "md5": "5813e9655bd6871d0c25b8d510fd8605" - }, - "size": 52167, - "_links": { - "download": { - "href": "http://localhost:8080/default/controller/v1/example/softwaremodules/1/artifacts/linux.zip" - }, - "md5sum": { - "href": "http://localhost:8080/default/controller/v1/example/softwaremodules/1/artifacts/linux.zip.MD5SUM" - } - } - } - ] - } - ] - }, - "id": "1", - "actionHistory": { - "status": "RETRIEVED", - "messages": [ - "Installing update", - "Downloading artifacts" - ] - } -} -``` - -## Deployment Feedback Resource -To every deployment the client can post feedback back to the update-server about the deployment status. - -``` -POST /{tenant}/controller/v1/{controllerId}/deploymentBase/{id}/feedback -Content-Type: application/json -``` - -_Example Body Deployment Success_ - -``` -{ - "id": 1, - "time": "20140511T121314", - "status": { - "execution": "closed", - "result": { - "finished": "success", - "progress": {} - } - } -} -``` - -_Example Body Deployment Proceeding_ - -``` -{ - "id": "1", - "time": "20140511T121314", - "status": { - "execution": "proceeding", - "result": { - "finished": "none", - "progress": { - "cnt": 2, - "of": 5 - } - }, - "details": [ - "checking hash sums" - ] - } -} -``` - -_Example Body Deployment Error_ - -``` -{ - "id": 1, - "time": "20140511T121314", - "status": { - "execution": "rejected", - "result": { - "finished": "failure", - "progress": {} - }, - "details": [ - "something bad happend" - ] - } -} -``` \ No newline at end of file + \ No newline at end of file diff --git a/docs/src/main/resources/documentation/interfaces/management-api.md b/docs/src/main/resources/documentation/interfaces/management-api.md index c5dd47f8a..19a908232 100644 --- a/docs/src/main/resources/documentation/interfaces/management-api.md +++ b/docs/src/main/resources/documentation/interfaces/management-api.md @@ -8,6 +8,7 @@ title: Management-API # Management API ## Overview + The Management API is a RESTful API that enables to perform Create/Read/Update/Delete operations for provisioning targets (i.e. devices) and repository content (i.e. software). Based on the Management API you can manage and monitor software update operations via HTTP/HTTPS. The _Management API_ supports JSON payload with hypermedia as well as filtering, sorting and paging. Furthermore the Management API provides permission based access control and standard roles as well as custom role creation. The API is protected and needs authentication and authorization based on the security concept. @@ -29,15 +30,16 @@ Supported HTTP-methods are: Available Management APIs resources are: -* [Targets](https://docs.bosch-iot-rollouts.com/documentation/rest-api/targets-api-guide.html) -* [Distribution Sets](https://docs.bosch-iot-rollouts.com/documentation/rest-api/distributionsets-api-guide.html) -* [Distribution Set Types](https://docs.bosch-iot-rollouts.com/documentation/rest-api/distributionsettypes-api-guide.html) -* [Software Modules](https://docs.bosch-iot-rollouts.com/documentation/rest-api/softwaremodules-api-guide.html) -* [Software Module Types](https://docs.bosch-iot-rollouts.com/documentation/rest-api/softwaremoduletypes-api-guide.html) -* [Target Tag](https://docs.bosch-iot-rollouts.com/documentation/rest-api/targettag-api-guide.html) -* [Distribution Set Tag](https://docs.bosch-iot-rollouts.com/documentation/rest-api/distributionsettag-api-guide.html) -* [Rollouts](https://docs.bosch-iot-rollouts.com/documentation/rest-api/rollout-api-guide.html) -* [System Configuration](https://docs.bosch-iot-rollouts.com/documentation/rest-api/tenant-api-guide.html) +- [Targets](managementapi/targets.html) +- [Distribution sets](managementapi/distributionsets.html) +- [Distribution set types](managementapi/distributionsettypes.html) +- [Software modules](managementapi/softwaremodules.html) +- [Software module types](managementapi/softwaremoduletypes.html) +- [Target tag](managementapi/targettag.html) +- [Distribution set tag](managementapi/distributionsettag.html) +- [Rollouts](managementapi/rollouts.html) +- [Target filters](managementapi/targetfilters.html) +- [System configuration](managementapi/tenant.html) ## Headers diff --git a/docs/src/main/resources/documentation/interfaces/managementapi/distributionsets.md b/docs/src/main/resources/documentation/interfaces/managementapi/distributionsets.md new file mode 100644 index 000000000..f2c381017 --- /dev/null +++ b/docs/src/main/resources/documentation/interfaces/managementapi/distributionsets.md @@ -0,0 +1,6 @@ +--- +layout: documentation +title: Management-API +--- + + diff --git a/docs/src/main/resources/documentation/interfaces/managementapi/distributionsettag.md b/docs/src/main/resources/documentation/interfaces/managementapi/distributionsettag.md new file mode 100644 index 000000000..2bfbbd90e --- /dev/null +++ b/docs/src/main/resources/documentation/interfaces/managementapi/distributionsettag.md @@ -0,0 +1,6 @@ +--- +layout: documentation +title: Management-API +--- + + diff --git a/docs/src/main/resources/documentation/interfaces/managementapi/distributionsettypes.md b/docs/src/main/resources/documentation/interfaces/managementapi/distributionsettypes.md new file mode 100644 index 000000000..0dd3b592e --- /dev/null +++ b/docs/src/main/resources/documentation/interfaces/managementapi/distributionsettypes.md @@ -0,0 +1,7 @@ +--- +layout: documentation +title: Management-API +--- + + + diff --git a/docs/src/main/resources/documentation/interfaces/managementapi/rollouts.md b/docs/src/main/resources/documentation/interfaces/managementapi/rollouts.md new file mode 100644 index 000000000..6433ea1a8 --- /dev/null +++ b/docs/src/main/resources/documentation/interfaces/managementapi/rollouts.md @@ -0,0 +1,6 @@ +--- +layout: documentation +title: Management-API +--- + + diff --git a/docs/src/main/resources/documentation/interfaces/managementapi/softwaremodules.md b/docs/src/main/resources/documentation/interfaces/managementapi/softwaremodules.md new file mode 100644 index 000000000..463e7d59a --- /dev/null +++ b/docs/src/main/resources/documentation/interfaces/managementapi/softwaremodules.md @@ -0,0 +1,6 @@ +--- +layout: documentation +title: Management-API +--- + + diff --git a/docs/src/main/resources/documentation/interfaces/managementapi/softwaremoduletypes.md b/docs/src/main/resources/documentation/interfaces/managementapi/softwaremoduletypes.md new file mode 100644 index 000000000..0a94ad218 --- /dev/null +++ b/docs/src/main/resources/documentation/interfaces/managementapi/softwaremoduletypes.md @@ -0,0 +1,6 @@ +--- +layout: documentation +title: Management-API +--- + + diff --git a/docs/src/main/resources/documentation/interfaces/managementapi/targetfilters.md b/docs/src/main/resources/documentation/interfaces/managementapi/targetfilters.md new file mode 100644 index 000000000..fbda69b20 --- /dev/null +++ b/docs/src/main/resources/documentation/interfaces/managementapi/targetfilters.md @@ -0,0 +1,6 @@ +--- +layout: documentation +title: Management-API +--- + + diff --git a/docs/src/main/resources/documentation/interfaces/managementapi/targets.md b/docs/src/main/resources/documentation/interfaces/managementapi/targets.md new file mode 100644 index 000000000..cdf640a1b --- /dev/null +++ b/docs/src/main/resources/documentation/interfaces/managementapi/targets.md @@ -0,0 +1,6 @@ +--- +layout: documentation +title: Management-API +--- + + diff --git a/docs/src/main/resources/documentation/interfaces/managementapi/targettag.md b/docs/src/main/resources/documentation/interfaces/managementapi/targettag.md new file mode 100644 index 000000000..2b513d8c9 --- /dev/null +++ b/docs/src/main/resources/documentation/interfaces/managementapi/targettag.md @@ -0,0 +1,6 @@ +--- +layout: documentation +title: Management-API +--- + + diff --git a/docs/src/main/resources/documentation/interfaces/managementapi/tenant.md b/docs/src/main/resources/documentation/interfaces/managementapi/tenant.md new file mode 100644 index 000000000..0514c605b --- /dev/null +++ b/docs/src/main/resources/documentation/interfaces/managementapi/tenant.md @@ -0,0 +1,6 @@ +--- +layout: documentation +title: Management-API +--- + + diff --git a/hawkbit-ddi-api/README.md b/hawkbit-rest/hawkbit-ddi-api/README.md similarity index 100% rename from hawkbit-ddi-api/README.md rename to hawkbit-rest/hawkbit-ddi-api/README.md diff --git a/hawkbit-ddi-api/pom.xml b/hawkbit-rest/hawkbit-ddi-api/pom.xml similarity index 86% rename from hawkbit-ddi-api/pom.xml rename to hawkbit-rest/hawkbit-ddi-api/pom.xml index aeb3637e0..3099c92c4 100644 --- a/hawkbit-ddi-api/pom.xml +++ b/hawkbit-rest/hawkbit-ddi-api/pom.xml @@ -13,12 +13,12 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 - org.eclipse.hawkbit - hawkbit-parent - 0.2.0-SNAPSHOT + org.eclipse.hawkbit + hawkbit-rest-parent + 0.2.0-SNAPSHOT hawkbit-ddi-api - hawkBit :: DDI API + hawkBit :: REST :: DDI API diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionFeedback.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionFeedback.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionFeedback.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionFeedback.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionHistory.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionHistory.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionHistory.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionHistory.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifact.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifact.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifact.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifact.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifactHash.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifactHash.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifactHash.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifactHash.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiCancel.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiCancel.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiCancel.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiCancel.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiCancelActionToStop.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiCancelActionToStop.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiCancelActionToStop.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiCancelActionToStop.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfig.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfig.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfig.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfig.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfigData.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfigData.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfigData.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfigData.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiControllerBase.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiControllerBase.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiControllerBase.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiControllerBase.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeploymentBase.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeploymentBase.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeploymentBase.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeploymentBase.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiMetadata.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiMetadata.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiMetadata.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiMetadata.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiPolling.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiPolling.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiPolling.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiPolling.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiProgress.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiProgress.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiProgress.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiProgress.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiResult.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiResult.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiResult.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiResult.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiStatus.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiStatus.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiStatus.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiStatus.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiUpdateMode.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiUpdateMode.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiUpdateMode.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiUpdateMode.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRestConstants.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRestConstants.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRestConstants.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRestConstants.java diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRootControllerRestApi.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRootControllerRestApi.java similarity index 100% rename from hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRootControllerRestApi.java rename to hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRootControllerRestApi.java diff --git a/hawkbit-ddi-resource/README.md b/hawkbit-rest/hawkbit-ddi-resource/README.md similarity index 100% rename from hawkbit-ddi-resource/README.md rename to hawkbit-rest/hawkbit-ddi-resource/README.md diff --git a/hawkbit-ddi-resource/pom.xml b/hawkbit-rest/hawkbit-ddi-resource/pom.xml similarity index 96% rename from hawkbit-ddi-resource/pom.xml rename to hawkbit-rest/hawkbit-ddi-resource/pom.xml index 83c4475d6..98384aec1 100644 --- a/hawkbit-ddi-resource/pom.xml +++ b/hawkbit-rest/hawkbit-ddi-resource/pom.xml @@ -13,12 +13,12 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 - org.eclipse.hawkbit - hawkbit-parent - 0.2.0-SNAPSHOT + org.eclipse.hawkbit + hawkbit-rest-parent + 0.2.0-SNAPSHOT hawkbit-ddi-resource - hawkBit :: DDI Resources + hawkBit :: REST :: DDI Resources diff --git a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java b/hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java similarity index 100% rename from hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java rename to hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java diff --git a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiApiConfiguration.java b/hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiApiConfiguration.java similarity index 100% rename from hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiApiConfiguration.java rename to hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiApiConfiguration.java diff --git a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java b/hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java similarity index 100% rename from hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java rename to hawkbit-rest/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java similarity index 100% rename from hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java rename to hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java similarity index 100% rename from hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java rename to hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java similarity index 100% rename from hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java rename to hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfigDataTest.java b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfigDataTest.java similarity index 100% rename from hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfigDataTest.java rename to hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiConfigDataTest.java diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java similarity index 100% rename from hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java rename to hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java similarity index 100% rename from hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java rename to hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DosFilterTest.java b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DosFilterTest.java similarity index 100% rename from hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DosFilterTest.java rename to hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DosFilterTest.java diff --git a/hawkbit-ddi-resource/src/test/resources/ddi-test.properties b/hawkbit-rest/hawkbit-ddi-resource/src/test/resources/ddi-test.properties similarity index 100% rename from hawkbit-ddi-resource/src/test/resources/ddi-test.properties rename to hawkbit-rest/hawkbit-ddi-resource/src/test/resources/ddi-test.properties diff --git a/hawkbit-mgmt-api/README.md b/hawkbit-rest/hawkbit-mgmt-api/README.md similarity index 100% rename from hawkbit-mgmt-api/README.md rename to hawkbit-rest/hawkbit-mgmt-api/README.md diff --git a/hawkbit-mgmt-api/pom.xml b/hawkbit-rest/hawkbit-mgmt-api/pom.xml similarity index 93% rename from hawkbit-mgmt-api/pom.xml rename to hawkbit-rest/hawkbit-mgmt-api/pom.xml index 2c916aa54..7cbddfedf 100644 --- a/hawkbit-mgmt-api/pom.xml +++ b/hawkbit-rest/hawkbit-mgmt-api/pom.xml @@ -13,11 +13,11 @@ 4.0.0 org.eclipse.hawkbit - hawkbit-parent + hawkbit-rest-parent 0.2.0-SNAPSHOT hawkbit-mgmt-api - hawkBit :: Mgmt REST API + hawkBit :: REST :: Management API diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtBaseEntity.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtBaseEntity.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtBaseEntity.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtBaseEntity.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtId.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtId.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtId.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtId.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMaintenanceWindow.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMaintenanceWindow.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMaintenanceWindow.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMaintenanceWindow.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMaintenanceWindowRequestBody.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMaintenanceWindowRequestBody.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMaintenanceWindowRequestBody.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMaintenanceWindowRequestBody.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadata.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadata.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadata.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadata.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadataBodyPut.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadataBodyPut.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadataBodyPut.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtMetadataBodyPut.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtNamedEntity.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtNamedEntity.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtNamedEntity.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtNamedEntity.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtPollStatus.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtPollStatus.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtPollStatus.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/MgmtPollStatus.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/PagedList.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/PagedList.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/PagedList.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/PagedList.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtAction.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtAction.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtAction.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtAction.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionRequestBodyPut.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionRequestBodyPut.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionRequestBodyPut.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionRequestBodyPut.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionStatus.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionStatus.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionStatus.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionStatus.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifact.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifact.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifact.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifact.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtActionType.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtActionType.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtActionType.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtActionType.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtDistributionSet.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtDistributionSet.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtDistributionSet.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtDistributionSet.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtDistributionSetRequestBodyPost.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtDistributionSetRequestBodyPost.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtDistributionSetRequestBodyPost.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtDistributionSetRequestBodyPost.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtDistributionSetRequestBodyPut.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtDistributionSetRequestBodyPut.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtDistributionSetRequestBodyPut.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtDistributionSetRequestBodyPut.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtTargetAssignmentRequestBody.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtTargetAssignmentRequestBody.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtTargetAssignmentRequestBody.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtTargetAssignmentRequestBody.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtTargetAssignmentResponseBody.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtTargetAssignmentResponseBody.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtTargetAssignmentResponseBody.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionset/MgmtTargetAssignmentResponseBody.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionsettype/MgmtDistributionSetType.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionsettype/MgmtDistributionSetType.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionsettype/MgmtDistributionSetType.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionsettype/MgmtDistributionSetType.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionsettype/MgmtDistributionSetTypeRequestBodyPost.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionsettype/MgmtDistributionSetTypeRequestBodyPost.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionsettype/MgmtDistributionSetTypeRequestBodyPost.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionsettype/MgmtDistributionSetTypeRequestBodyPost.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionsettype/MgmtDistributionSetTypeRequestBodyPut.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionsettype/MgmtDistributionSetTypeRequestBodyPut.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionsettype/MgmtDistributionSetTypeRequestBodyPut.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/distributionsettype/MgmtDistributionSetTypeRequestBodyPut.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/AbstractMgmtRolloutConditionsEntity.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/AbstractMgmtRolloutConditionsEntity.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/AbstractMgmtRolloutConditionsEntity.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/AbstractMgmtRolloutConditionsEntity.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutCondition.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutCondition.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutCondition.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutCondition.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutErrorAction.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutErrorAction.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutErrorAction.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutErrorAction.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutResponseBody.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutResponseBody.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutResponseBody.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutResponseBody.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutRestRequestBody.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutRestRequestBody.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutRestRequestBody.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutRestRequestBody.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutSuccessAction.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutSuccessAction.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutSuccessAction.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutSuccessAction.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rolloutgroup/MgmtRolloutGroup.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rolloutgroup/MgmtRolloutGroup.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rolloutgroup/MgmtRolloutGroup.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rolloutgroup/MgmtRolloutGroup.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rolloutgroup/MgmtRolloutGroupResponseBody.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rolloutgroup/MgmtRolloutGroupResponseBody.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rolloutgroup/MgmtRolloutGroupResponseBody.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rolloutgroup/MgmtRolloutGroupResponseBody.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModule.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModule.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModule.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModule.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleAssigment.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleAssigment.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleAssigment.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleAssigment.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadata.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadata.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadata.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadata.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadataBodyPut.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadataBodyPut.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadataBodyPut.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleMetadataBodyPut.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleRequestBodyPost.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleRequestBodyPost.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleRequestBodyPost.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleRequestBodyPost.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleRequestBodyPut.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleRequestBodyPut.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleRequestBodyPut.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremodule/MgmtSoftwareModuleRequestBodyPut.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleType.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleType.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleType.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleType.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleTypeAssigment.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleTypeAssigment.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleTypeAssigment.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleTypeAssigment.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleTypeRequestBodyPost.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleTypeRequestBodyPost.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleTypeRequestBodyPost.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleTypeRequestBodyPost.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleTypeRequestBodyPut.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleTypeRequestBodyPut.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleTypeRequestBodyPut.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/softwaremoduletype/MgmtSoftwareModuleTypeRequestBodyPut.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/system/MgmtSystemTenantConfigurationValue.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/system/MgmtSystemTenantConfigurationValue.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/system/MgmtSystemTenantConfigurationValue.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/system/MgmtSystemTenantConfigurationValue.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/system/MgmtSystemTenantConfigurationValueRequest.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/system/MgmtSystemTenantConfigurationValueRequest.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/system/MgmtSystemTenantConfigurationValueRequest.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/system/MgmtSystemTenantConfigurationValueRequest.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/systemmanagement/MgmtSystemCache.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/systemmanagement/MgmtSystemCache.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/systemmanagement/MgmtSystemCache.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/systemmanagement/MgmtSystemCache.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/systemmanagement/MgmtSystemStatisticsRest.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/systemmanagement/MgmtSystemStatisticsRest.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/systemmanagement/MgmtSystemStatisticsRest.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/systemmanagement/MgmtSystemStatisticsRest.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/systemmanagement/MgmtSystemTenantServiceUsage.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/systemmanagement/MgmtSystemTenantServiceUsage.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/systemmanagement/MgmtSystemTenantServiceUsage.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/systemmanagement/MgmtSystemTenantServiceUsage.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtAssignedDistributionSetRequestBody.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtAssignedDistributionSetRequestBody.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtAssignedDistributionSetRequestBody.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtAssignedDistributionSetRequestBody.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtAssignedTargetRequestBody.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtAssignedTargetRequestBody.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtAssignedTargetRequestBody.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtAssignedTargetRequestBody.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtDistributionSetTagAssigmentResult.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtDistributionSetTagAssigmentResult.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtDistributionSetTagAssigmentResult.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtDistributionSetTagAssigmentResult.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtTag.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtTag.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtTag.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtTag.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtTagRequestBodyPut.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtTagRequestBodyPut.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtTagRequestBodyPut.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtTagRequestBodyPut.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtTargetTagAssigmentResult.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtTargetTagAssigmentResult.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtTargetTagAssigmentResult.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/tag/MgmtTargetTagAssigmentResult.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtDistributionSetAssignment.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtDistributionSetAssignment.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtDistributionSetAssignment.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtDistributionSetAssignment.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTarget.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTarget.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTarget.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTarget.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetAttributes.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetAttributes.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetAttributes.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetAttributes.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetRequestBody.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetRequestBody.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetRequestBody.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetRequestBody.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/targetfilter/MgmtTargetFilterQuery.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/targetfilter/MgmtTargetFilterQuery.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/targetfilter/MgmtTargetFilterQuery.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/targetfilter/MgmtTargetFilterQuery.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/targetfilter/MgmtTargetFilterQueryRequestBody.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/targetfilter/MgmtTargetFilterQueryRequestBody.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/targetfilter/MgmtTargetFilterQueryRequestBody.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/targetfilter/MgmtTargetFilterQueryRequestBody.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetRestApi.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetTagRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetTagRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetTagRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetTagRestApi.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetTypeRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetTypeRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetTypeRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDistributionSetTypeRestApi.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadArtifactRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadArtifactRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadArtifactRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadArtifactRestApi.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadRestApi.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRestConstants.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRolloutRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRolloutRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRolloutRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtRolloutRestApi.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleRestApi.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleTypeRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleTypeRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleTypeRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSoftwareModuleTypeRestApi.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSystemManagementRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSystemManagementRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSystemManagementRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtSystemManagementRestApi.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetFilterQueryRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetFilterQueryRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetFilterQueryRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetFilterQueryRestApi.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetRestApi.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetTagRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetTagRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetTagRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetTagRestApi.java diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTenantManagementRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTenantManagementRestApi.java similarity index 100% rename from hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTenantManagementRestApi.java rename to hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTenantManagementRestApi.java diff --git a/hawkbit-mgmt-api/src/test/java/org/eclipse/hawkbit/mgmt/json/model/PagedListTest.java b/hawkbit-rest/hawkbit-mgmt-api/src/test/java/org/eclipse/hawkbit/mgmt/json/model/PagedListTest.java similarity index 100% rename from hawkbit-mgmt-api/src/test/java/org/eclipse/hawkbit/mgmt/json/model/PagedListTest.java rename to hawkbit-rest/hawkbit-mgmt-api/src/test/java/org/eclipse/hawkbit/mgmt/json/model/PagedListTest.java diff --git a/hawkbit-mgmt-resource/.gitignore b/hawkbit-rest/hawkbit-mgmt-resource/.gitignore similarity index 100% rename from hawkbit-mgmt-resource/.gitignore rename to hawkbit-rest/hawkbit-mgmt-resource/.gitignore diff --git a/hawkbit-mgmt-resource/README.md b/hawkbit-rest/hawkbit-mgmt-resource/README.md similarity index 100% rename from hawkbit-mgmt-resource/README.md rename to hawkbit-rest/hawkbit-mgmt-resource/README.md diff --git a/hawkbit-mgmt-resource/pom.xml b/hawkbit-rest/hawkbit-mgmt-resource/pom.xml similarity index 97% rename from hawkbit-mgmt-resource/pom.xml rename to hawkbit-rest/hawkbit-mgmt-resource/pom.xml index 1cb70aa05..4de8b138e 100644 --- a/hawkbit-mgmt-resource/pom.xml +++ b/hawkbit-rest/hawkbit-mgmt-resource/pom.xml @@ -13,11 +13,11 @@ 4.0.0 org.eclipse.hawkbit - hawkbit-parent + hawkbit-rest-parent 0.2.0-SNAPSHOT hawkbit-mgmt-resource - hawkBit :: REST Mgmt Resources + hawkBit :: REST :: Management Resources diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtApiConfiguration.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtApiConfiguration.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtApiConfiguration.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtApiConfiguration.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetMapper.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetMapper.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetMapper.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeMapper.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeMapper.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeMapper.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRestModelMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRestModelMapper.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRestModelMapper.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRestModelMapper.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutMapper.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutMapper.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutMapper.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeMapper.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeMapper.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeMapper.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSystemManagementResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSystemManagementResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSystemManagementResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSystemManagementResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTagMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTagMapper.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTagMapper.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTagMapper.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryMapper.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryMapper.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryMapper.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementMapper.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementMapper.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementMapper.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResource.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResource.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResource.java diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/PagingUtility.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/PagingUtility.java similarity index 100% rename from hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/PagingUtility.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/PagingUtility.java diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/AbstractManagementApiIntegrationTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/AbstractManagementApiIntegrationTest.java similarity index 100% rename from hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/AbstractManagementApiIntegrationTest.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/AbstractManagementApiIntegrationTest.java diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java similarity index 100% rename from hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResourceTest.java diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResourceTest.java similarity index 100% rename from hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResourceTest.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTagResourceTest.java diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResourceTest.java similarity index 100% rename from hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResourceTest.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetTypeResourceTest.java diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResourceTest.java similarity index 100% rename from hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResourceTest.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResourceTest.java diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java similarity index 100% rename from hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java similarity index 100% rename from hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResourceTest.java diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResourceTest.java similarity index 100% rename from hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResourceTest.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleTypeResourceTest.java diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResourceTest.java similarity index 100% rename from hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResourceTest.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetFilterQueryResourceTest.java diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java similarity index 100% rename from hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResourceTest.java similarity index 100% rename from hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResourceTest.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetTagResourceTest.java diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/ResourceUtility.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/ResourceUtility.java similarity index 100% rename from hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/ResourceUtility.java rename to hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/ResourceUtility.java diff --git a/hawkbit-rest-core/pom.xml b/hawkbit-rest/hawkbit-rest-core/pom.xml similarity index 97% rename from hawkbit-rest-core/pom.xml rename to hawkbit-rest/hawkbit-rest-core/pom.xml index fbfbb9b85..774628b90 100644 --- a/hawkbit-rest-core/pom.xml +++ b/hawkbit-rest/hawkbit-rest-core/pom.xml @@ -13,11 +13,11 @@ 4.0.0 org.eclipse.hawkbit - hawkbit-parent + hawkbit-rest-parent 0.2.0-SNAPSHOT hawkbit-rest-core - hawkBit :: REST Core + hawkBit :: REST :: Core diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/RestConfiguration.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/RestConfiguration.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/RestConfiguration.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/RestConfiguration.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/data/ResponseList.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/data/ResponseList.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/data/ResponseList.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/data/ResponseList.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/data/SortDirection.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/data/SortDirection.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/data/SortDirection.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/data/SortDirection.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MessageNotReadableException.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MessageNotReadableException.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MessageNotReadableException.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MessageNotReadableException.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MultiPartFileUploadException.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MultiPartFileUploadException.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MultiPartFileUploadException.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MultiPartFileUploadException.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterSyntaxErrorException.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterSyntaxErrorException.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterSyntaxErrorException.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterSyntaxErrorException.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedDirectionException.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedDirectionException.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedDirectionException.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedDirectionException.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedFieldException.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedFieldException.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedFieldException.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedFieldException.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/filter/ExcludePathAwareShallowETagFilter.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/filter/ExcludePathAwareShallowETagFilter.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/filter/ExcludePathAwareShallowETagFilter.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/filter/ExcludePathAwareShallowETagFilter.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/json/model/ExceptionInfo.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/json/model/ExceptionInfo.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/json/model/ExceptionInfo.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/json/model/ExceptionInfo.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingFailedException.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingFailedException.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingFailedException.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingFailedException.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingProgressListener.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingProgressListener.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingProgressListener.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingProgressListener.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingUtil.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingUtil.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingUtil.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileStreamingUtil.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FilterHttpResponse.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FilterHttpResponse.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FilterHttpResponse.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FilterHttpResponse.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpResponseFactoryBean.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpResponseFactoryBean.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpResponseFactoryBean.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpResponseFactoryBean.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpUtil.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpUtil.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpUtil.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpUtil.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RequestResponseContextHolder.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RequestResponseContextHolder.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RequestResponseContextHolder.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RequestResponseContextHolder.java diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/SortUtility.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/SortUtility.java similarity index 100% rename from hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/SortUtility.java rename to hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/SortUtility.java diff --git a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/AbstractRestIntegrationTest.java b/hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/AbstractRestIntegrationTest.java similarity index 100% rename from hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/AbstractRestIntegrationTest.java rename to hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/AbstractRestIntegrationTest.java diff --git a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/filter/ExcludePathAwareShallowETagFilterTest.java b/hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/filter/ExcludePathAwareShallowETagFilterTest.java similarity index 100% rename from hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/filter/ExcludePathAwareShallowETagFilterTest.java rename to hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/filter/ExcludePathAwareShallowETagFilterTest.java diff --git a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/json/model/ExceptionInfoTest.java b/hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/json/model/ExceptionInfoTest.java similarity index 100% rename from hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/json/model/ExceptionInfoTest.java rename to hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/json/model/ExceptionInfoTest.java diff --git a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java b/hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java similarity index 100% rename from hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java rename to hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java diff --git a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/MockMvcResultPrinter.java b/hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/MockMvcResultPrinter.java similarity index 100% rename from hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/MockMvcResultPrinter.java rename to hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/MockMvcResultPrinter.java diff --git a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/SortUtilityTest.java b/hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/SortUtilityTest.java similarity index 100% rename from hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/SortUtilityTest.java rename to hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/SortUtilityTest.java diff --git a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/SuccessCondition.java b/hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/SuccessCondition.java similarity index 94% rename from hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/SuccessCondition.java rename to hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/SuccessCondition.java index f3424b0c0..e112ae5ea 100644 --- a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/SuccessCondition.java +++ b/hawkbit-rest/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/SuccessCondition.java @@ -9,8 +9,6 @@ package org.eclipse.hawkbit.rest.util; /** - * - * @author Dennis Melzer * * @param */ diff --git a/hawkbit-rest/hawkbit-rest-docs/README.md b/hawkbit-rest/hawkbit-rest-docs/README.md new file mode 100644 index 000000000..1a9f74b28 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/README.md @@ -0,0 +1,17 @@ +# hawkBit Rest Documentation tests + +The hawkBit Rest Documentation tests are based on [Rest Docs](https://projects.spring.io/spring-restdocs/). These tests generate documentation for our RESTful services. + +## Run and create snippets + +Run the test with maven + +```bash +mvn clean package +``` + +Every rest test will create snippets (e.g. curl-request.adoc, http-request.adoc) in the target\generated-snippets\ directory. + +## Use the snippets + +The snippets get included using Asciidoc within our API documents in src\main\asciidoc. Those documents in turn are used to generate HTML documents in the target\classes directory when building with maven. diff --git a/hawkbit-rest/hawkbit-rest-docs/pom.xml b/hawkbit-rest/hawkbit-rest-docs/pom.xml new file mode 100644 index 000000000..19faf1991 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/pom.xml @@ -0,0 +1,159 @@ + + + 4.0.0 + + org.eclipse.hawkbit + hawkbit-rest-parent + 0.2.0-SNAPSHOT + + hawkbit-rest-docs + hawkbit :: REST :: Documentation + + + ${maven.build.timestamp} + + + + + + org.eclipse.hawkbit + hawkbit-repository-api + ${project.version} + test + + + org.eclipse.hawkbit + hawkbit-repository-jpa + ${project.version} + test + + + org.springframework.restdocs + spring-restdocs-mockmvc + test + + + org.springframework.security + spring-security-config + test + + + org.eclipse.hawkbit + hawkbit-rest-core + ${project.version} + tests + test + + + org.eclipse.hawkbit + hawkbit-ddi-resource + ${project.version} + test + + + org.eclipse.hawkbit + hawkbit-mgmt-resource + ${project.version} + test + + + org.eclipse.hawkbit + hawkbit-repository-test + ${project.version} + test + + + org.eclipse.hawkbit + hawkbit-http-security + ${project.version} + test + + + com.jayway.jsonpath + json-path + test + + + org.json + json + test + + + com.fasterxml.jackson.core + jackson-databind + test + + + com.fasterxml.jackson.core + jackson-core + test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-aspects + test + + + ru.yandex.qatools.allure + allure-junit-adaptor + + + org.springframework + spring-context-support + test + + + + + + org.asciidoctor + asciidoctor-maven-plugin + 1.5.2 + + + generate-docs + prepare-package + + process-asciidoc + + + html + book + + ${project.build.directory}/generated-snippets + + ${project.build.directory}/classes/rest-api + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + + diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/distributionsets-api-guide.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/distributionsets-api-guide.adoc new file mode 100644 index 000000000..5d13ae997 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/distributionsets-api-guide.adoc @@ -0,0 +1,840 @@ +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: macro +:toclevels: 1 +:sectlinks: +:linkattrs: + +[[distributionsets]] += Distributionsets + +toc::[] + +== GET /rest/v1/distributionsets + +=== Implementation notes + +Handles the GET request of retrieving all distribution sets within SP. Required permission: READ_REPOSITORY + +=== Get paged list of Distribution Sets + +==== Curl + +include::{snippets}/distributionsets/get-distribution-sets/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/get-distribution-sets/http-request.adoc[] + +==== Request query parameter + +include::{snippets}/distributionsets/get-distribution-sets-with-parameters/request-parameters.adoc[] + +==== Request query parameter example + +include::{snippets}/distributionsets/get-distribution-sets-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsets/get-distribution-sets/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsets/get-distribution-sets/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/distributionsets + +=== Implementation Notes +Handles the POST request of creating new distribution sets within SP. The request body must always be a list of sets. Required permission: CREATE_REPOSITORY + +=== Create Distribution Sets + + +==== CURL + +include::{snippets}/distributionsets/create-distribution-sets/curl-request.adoc[] + + +==== Request URL + +include::{snippets}/distributionsets/create-distribution-sets/http-request.adoc[] + +==== Request fields + +include::{snippets}/distributionsets/create-distribution-sets/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsets/create-distribution-sets/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsets/create-distribution-sets/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/distributionsets/{distributionSetId} + + +=== Implementation Notes + +Handles the DELETE request for a single Distribution Set within SP. Required permission: DELETE_REPOSITORY + +=== Delete Distribution Set + +==== CURL + +include::{snippets}/distributionsets/delete-distribution-set/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/delete-distribution-set/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/delete-distribution-set/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/distributionsets/delete-distribution-set/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== GET /rest/v1/distributionsets/{distributionSetId} + +=== Implementation Notes + +Handles the GET request of retrieving a single distribution set within SP. Required permission: READ_REPOSITORY + +=== Get Distribution Set + +==== CURL + +include::{snippets}/distributionsets/get-distribution-set/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/get-distribution-set/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/get-distribution-set/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsets/get-distribution-set/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsets/get-distribution-set/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== PUT /rest/v1/distributionsets/{distributionSetId} + +=== Implementation Notes + +Handles the UPDATE request for a single Distribution Set within SP. Required permission: UPDATE_REPOSITORY + +=== Updating a Distribution Set + +==== Curl + +include::{snippets}/distributionsets/update-distribution-set/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/update-distribution-set/http-request.adoc[] + + +==== Request path parameter + +include::{snippets}/distributionsets/update-distribution-set/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/distributionsets/update-distribution-set/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsets/update-distribution-set/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsets/update-distribution-set/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== GET /rest/v1/distributionsets/{distributionSetId}/assignedSM + +=== Implementation Notes +Handles the GET request of retrieving a single distribution set within SP. Required permission: READ_REPOSITORY + +=== Get assigned Software Modules + +==== Curl + +include::{snippets}/distributionsets/get-assigned-software-modules/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/get-assigned-software-modules/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/get-assigned-software-modules/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/distributionsets/get-assigned-software-modules-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/distributionsets/get-assigned-software-modules-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsets/get-assigned-software-modules/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsets/get-assigned-software-modules/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/distributionsets/{distributionSetId}/assignedSM + +=== Implementation Notes + +Handles the POST request for assigning multiple software modules to a distribution set.The request body must always be a list of software module IDs. Required permissions: READ_REPOSITORY and UPDATE_REPOSITORY + +=== Assign Software Modules to Distribution Set + + +==== CURL + +include::{snippets}/distributionsets/assign-software-modules/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/assign-software-modules/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/assign-software-modules/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/distributionsets/assign-software-modules/request-fields.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/distributionsets/assign-software-modules/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== DELETE /rest/v1/distributionsets/{distributionSetId}/assignedSM/{softwareModuleId} + + +=== Implementation Notes + +Delete a assignment. Required permission: UPDATE_REPOSITORY + +=== Delete assignment of Software Module + +==== CURL + +include::{snippets}/distributionsets/delete-assign-software-modules/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/delete-assign-software-modules/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/delete-assign-software-modules/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/distributionsets/delete-assign-software-modules/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/distributionsets/{distributionSetId}/assignedTargets + + +=== Implementation Notes +Handles the GET request for retrieving assigned targets of a single distribution set. Required permissions: READ_REPOSITORY and READ_TARGET + +=== Get assigned targets + +==== Curl + +include::{snippets}/distributionsets/get-assigned-targets/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/get-assigned-targets/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/get-assigned-targets/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/distributionsets/get-assigned-targets-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/distributionsets/get-assigned-targets-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsets/get-assigned-targets/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsets/get-assigned-targets/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/distributionsets/{distributionSetId}/assignedTargets + + +=== Implementation Notes + +Handles the POST request for assigning multiple targets to a distribution set.The request body must always be a list of target IDs. Required permissions: READ_REPOSITORY and UPDATE_TARGET + +=== Assign targets to a distribution set + +==== CURL + +include::{snippets}/distributionsets/create-assigned-target/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/create-assigned-target/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/create-assigned-target/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/distributionsets/create-assigned-target/request-parameters.adoc[] + +==== Request fields + +include::{snippets}/distributionsets/create-assigned-target/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsets/create-assigned-target/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsets/create-assigned-target/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== GET /rest/v1/distributionsets/{distributionSetId}/installedTargets + +=== Implementation Notes + +Handles the GET request for retrieving installed targets of a single distribution set. Required permissions: READ_REPOSITORY and READ_TARGET + +=== Get installed targets + +==== Curl + +include::{snippets}/distributionsets/get-installed-targets/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/get-installed-targets/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/get-installed-targets/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/distributionsets/get-installed-targets-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/distributionsets/get-installed-targets-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsets/get-installed-targets/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsets/get-installed-targets/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/distributionsets/{distributionSetId}/autoAssignTargetFilters + +=== Implementation Notes + +Handles the GET request for retrieving assigned target filter queries of a single distribution set. Required permissions: READ_REPOSITORY and READ_TARGET + +=== Get installed targets + +==== Curl + +include::{snippets}/distributionsets/get-auto-assign-target-filter-queries/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/get-auto-assign-target-filter-queries/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/get-auto-assign-target-filter-queries/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/distributionsets/get-auto-assign-target-filter-queries-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/distributionsets/get-auto-assign-target-filter-queries-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsets/get-auto-assign-target-filter-queries/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsets/get-auto-assign-target-filter-queries/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/distributionsets/{distributionSetId}/metadata + +=== Implementation Notes + +Get a paged list of meta data for a distribution set. Required permission: READ_REPOSITORY + +=== Get a paged list of meta data + +==== Curl + +include::{snippets}/distributionsets/get-metadata/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/get-metadata/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/get-metadata/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/distributionsets/get-metadata-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/distributionsets/get-metadata-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsets/get-metadata/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsets/get-metadata/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== POST /rest/v1/distributionsets/{distributionSetId}/metadata + +=== Implementation Notes + +Create a list of meta data entries Required permissions: READ_REPOSITORY and UPDATE_TARGET + +=== Create a list of meta data entries + + +==== CURL + +include::{snippets}/distributionsets/create-metadata/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/create-metadata/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/create-metadata/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/distributionsets/create-metadata/request-fields.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/distributionsets/create-metadata/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/distributionsets/{distributionSetId}/metadata/{metadataKey} + + +=== Implementation Notes + +Delete a single meta data. Required permission: UPDATE_REPOSITORY + +=== Delete a single meta data + +==== CURL + +include::{snippets}/distributionsets/delete-metadata/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/delete-metadata/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/delete-metadata/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/distributionsets/delete-metadata/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/distributionsets/{distributionSetId}/metadata/{metadataKey} + + +=== Implementation Notes + +Get a single meta data value for a meta data key. Required permission: READ_REPOSITORY + +=== Get a single meta data value + +==== Curl + +include::{snippets}/distributionsets/get-metadata-value/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/get-metadata-value/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/get-metadata-value/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsets/get-metadata-value/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsets/get-metadata-value/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== PUT /rest/v1/distributionsets/{distributionSetId}/metadata/{metadataKey} + + +=== Implementation Notes + +Update a single meta data value for speficic key. Required permission: UPDATE_REPOSITORY + +=== Update a single meta data value + +==== Curl + +include::{snippets}/distributionsets/update-metadata/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsets/update-metadata/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsets/update-metadata/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/distributionsets/update-metadata/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsets/update-metadata/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsets/update-metadata/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== Additional content + +[[error-body]] +=== Error body + +include::../errors/error-response-body.adoc[] + diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/distributionsettag-api-guide.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/distributionsettag-api-guide.adoc new file mode 100644 index 000000000..d02e761bb --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/distributionsettag-api-guide.adoc @@ -0,0 +1,433 @@ +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: macro +:toclevels: 1 +:sectlinks: +:linkattrs: + +[[distributionsettag]] += Distribution set Tag + +toc::[] + + +== GET /rest/v1/distributionsettags + +=== Implementation notes + +Handles the GET request of retrieving all distribution set tags. + +=== Get paged list of distribution set tags + +==== CURL + +include::{snippets}/distributionsettag/get-distribution-set-tags/curl-request.adoc[] + +==== Request URL + +A `GET` request is used to access the distribution set tags + +include::{snippets}/distributionsettag/get-distribution-set-tags/http-request.adoc[] + +==== Request query parameter + +include::{snippets}/distributionsettag/get-distribution-set-tags-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/distributionsettag/get-distribution-set-tags-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettag/get-distribution-set-tags/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettag/get-distribution-set-tags/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/distributionsettags/{distributionsetTagId} + +=== Implementation notes + +Handles the GET request of retrieving a single distribution set tag. + +=== Get a single distribution set tag + +==== CURL + +include::{snippets}/distributionsettag/get-distribution-set-tag/curl-request.adoc[] + +==== Request URL + +A `GET` request is used to access the distribution set tag + +include::{snippets}/distributionsettag/get-distribution-set-tag/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettag/get-distribution-set-tag/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettag/get-distribution-set-tag/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettag/get-distribution-set-tag/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/distributionsettags + +=== Implementation Notes + +Handles the POST request of creating new distribution set tag. The request body must always be a list of distribution set tags. + +=== Create list of distribution set tags + +==== CURL + +include::{snippets}/distributionsettag/create-distribution-set-tags/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettag/create-distribution-set-tags/http-request.adoc[] + +==== Request fields + +include::{snippets}/distributionsettag/create-distribution-set-tags/request-fields.adoc[] + +=== Response (Status 201) + +==== Response fields + +include::{snippets}/distributionsettag/create-distribution-set-tags/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettag/create-distribution-set-tags/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== PUT /rest/v1/distributionsettags/{distributionsetTagId} + +=== Implementation Notes + +Handles the PUT request of updating a distribution set tag. + +=== Update a distribution set tag + +==== Curl + +include::{snippets}/distributionsettag/update-distribution-set-tag/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettag/update-distribution-set-tag/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettag/update-distribution-set-tag/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/distributionsettag/update-distribution-set-tag/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettag/update-distribution-set-tag/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettag/update-distribution-set-tag/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/distributionsettags/{distributionsetTagId} + +=== Implementation Notes + +Handles the DELETE request of deleting a single distribution set tag. + +=== Deleting a distribution set tag + +==== CURL + +include::{snippets}/distributionsettag/delete-distribution-set-tag/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettag/delete-distribution-set-tag/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettag/delete-distribution-set-tag/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/distributionsettag/delete-distribution-set-tag/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/distributionsettags/{distributionsetTagId}/distributionsets + +=== Implementation Notes + +Handles the GET request of retrieving a list of assigned distributions. + +=== Get a list of assigned distributions + +==== CURL + +include::{snippets}/distributionsettag/get-assigned-distribution-sets/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettag/get-assigned-distribution-sets/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettag/get-assigned-distribution-sets/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettag/get-assigned-distribution-sets/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettag/get-assigned-distribution-sets/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/distributionsettags/{distributionsetTagId}/distributionsets/toggleTagAssignment + +=== Implementation Notes + +Handles the POST request of toogle distribution assignment. The request body must always be a list of controller ids. + +=== Toogle distribution assignment + +==== CURL + +include::{snippets}/distributionsettag/toggle-tag-assignment/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettag/toggle-tag-assignment/http-request.adoc[] + +==== Request fields + +include::{snippets}/distributionsettag/toggle-tag-assignment/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettag/toggle-tag-assignment/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettag/toggle-tag-assignment/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== POST /rest/v1/distributionsettags/{distributionsetTagId}/distributionsets + +=== Implementation Notes + +Handles the POST request of distribution assignment. Already assigned distribution will be ignored. + +=== Distribution assignment + +==== CURL + +include::{snippets}/distributionsettag/assign-distribution-sets/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettag/assign-distribution-sets/http-request.adoc[] + +==== Request fields + +include::{snippets}/distributionsettag/assign-distribution-sets/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettag/assign-distribution-sets/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettag/assign-distribution-sets/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== DELETE /rest/v1/distributionsettags/{distributionsetTagId}/distributionsets/{distributionsetId} + +=== Implementation Notes + +Handles the DELETE request of unassign the given distribution. + +=== Unassign a distribution + +==== CURL + +include::{snippets}/distributionsettag/unassign-distribution-set/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettag/unassign-distribution-set/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettag/unassign-distribution-set/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/distributionsettag/unassign-distribution-set/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== Additional content + +[[error-body]] +=== Error body + +include::../errors/error-response-body.adoc[] + + + diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/distributionsettypes-api-guide.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/distributionsettypes-api-guide.adoc new file mode 100644 index 000000000..c1398a1be --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/distributionsettypes-api-guide.adoc @@ -0,0 +1,638 @@ +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: macro +:toclevels: 1 +:sectlinks: +:linkattrs: + +[[distributionset-types]] += Distribution Set Types + +toc::[] + +== GET /rest/v1/distributionsettypes + +=== Implementation notes + +Handles the GET request of retrieving all distribution set types withinfGET /rest/v1/distributionsettypes SP. Required Permission: READ_REPOSITORY + +=== Get distribution set types + +==== CURL + +include::{snippets}/distributionsettypes/get-distribution-set-types/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/get-distribution-set-types/http-request.adoc[] + +==== Request query parameter + +include::{snippets}/distributionsettypes/get-distribution-set-types-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/distributionsettypes/get-distribution-set-types-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettypes/get-distribution-set-types/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettypes/get-distribution-set-types/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/distributionsettypes + +=== Implementation notes + +Handles the POST request for creating new distribution set types within SP. The request body must always be a list of types. Required Permission: CREATE_REPOSITORY + +=== Create distribution set types + +==== CURL + +include::{snippets}/distributionsettypes/post-distribution-set-types/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/post-distribution-set-types/http-request.adoc[] + +==== Request fields + +include::{snippets}/distributionsettypes/post-distribution-set-types/request-fields.adoc[] + +=== Response (Status 201) + +==== Response fields + +include::{snippets}/distributionsettypes/post-distribution-set-types/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettypes/post-distribution-set-types/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Distribution set type was not found. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +| `409 Conflict` +| Distribution set type already exists +| See <> +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/distributionsettypes/{distributionSetTypeId} + +=== Implementation Notes + +Handles the DELETE request for a single distribution set type within SP. Required Permission: DELETE_REPOSITORY + +=== Delete distribution set type + +==== CURL + +include::{snippets}/distributionsettypes/delete-distribution-set-type/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/delete-distribution-set-type/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettypes/delete-distribution-set-type/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/distributionsettypes/delete-distribution-set-type/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Distribution set type was not found. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/distributionsettypes/{distributionSetTypeId} + +=== Implementation notes + +Handles the GET request of retrieving a single distribution set type within SP. Required Permission: READ_REPOSITORY + +=== Get distribution set type + +==== CURL + +include::{snippets}/distributionsettypes/get-distribution-set-type/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/get-distribution-set-type/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettypes/get-distribution-set-type/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettypes/get-distribution-set-type/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettypes/get-distribution-set-type/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Distribution set type was not found. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== PUT /rest/v1/distributionsettypes/{distributionSetTypeId} + +=== Implementation notes + +Handles the PUT request for a single distribution set type within SP. Required Permission: UPDATE_REPOSITORY + +=== Update distribution set type + +==== CURL + +include::{snippets}/distributionsettypes/put-distribution-set-type/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/put-distribution-set-type/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettypes/put-distribution-set-type/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/distributionsettypes/put-distribution-set-type/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettypes/put-distribution-set-type/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettypes/put-distribution-set-type/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Distribution set type was not found. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/distributionsettypes/{distributionSetTypeId}/mandatorymoduletypes + +=== Implementation notes + +Handles the GET request of retrieving the list of mandatory software module types in that distribution set type. Required Permission: READ_REPOSITORY + +=== Lists all mandatory software module types + +==== CURL + +include::{snippets}/distributionsettypes/get-mandatory-modules/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/get-mandatory-modules/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettypes/get-mandatory-modules/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettypes/get-mandatory-modules/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettypes/get-mandatory-modules/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Distribution set type was not found. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/distributionsettypes/{distributionSetTypeId}/mandatorymoduletypes + +=== Implementation notes + +Handles the POST request for adding a mandatory software module type to a distribution set type.Note that a DS type cannot be changed after it has been used by a DS. Required Permission: UPDATE_REPOSITORY and READ_REPOSITORY + +=== Add mandatory software module type + +==== CURL + +include::{snippets}/distributionsettypes/post-mandatory-module/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/post-mandatory-module/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettypes/post-mandatory-module/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/distributionsettypes/post-mandatory-module/request-fields.adoc[] + +=== Response (Status 201) + +==== Response example + +include::{snippets}/distributionsettypes/post-mandatory-module/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Distribution set type was not found. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +| `409 Conflict` +| Distribution set type already exists +| See <> +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/distributionsettypes/{distributionSetTypeId}/mandatorymoduletypes/{softwareModuleTypeId} + +=== Implementation Notes + +Handles the DELETE request for removing a software module type from a single distribution set type within SP. Required Permission: DELETE_REPOSITORY + +Delete mandatory software module type. + +=== Remove mandatory module from distribution set type + +==== CURL + +include::{snippets}/distributionsettypes/delete-mandatory-module/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/delete-mandatory-module/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettypes/delete-mandatory-module/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/distributionsettypes/delete-mandatory-module/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Distribution set type was not found. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/distributionsettypes/{distributionSetTypeId}/mandatorymoduletypes/{softwareModuleTypeId} + +=== Implementation notes + +Handles the GET request of retrieving the single mandatory software module type in that distribution set type. Required Permission: READ_REPOSITORY + +=== Retrieve mandatory software module type + +==== CURL + +include::{snippets}/distributionsettypes/get-mandatory-module/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/get-mandatory-module/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettypes/get-mandatory-module/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettypes/get-mandatory-module/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettypes/get-mandatory-module/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Distribution set type was not found. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/distributionsettypes/{distributionSetTypeId}/optionalmoduletypes + +=== Implementation notes + +Handles the GET request of retrieving the list of optional software module types in that distribution set type. Required Permission: READ_REPOSITORY + +=== Lists all optional software module types + +==== CURL + +include::{snippets}/distributionsettypes/get-optional-modules/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/get-optional-modules/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettypes/get-optional-modules/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettypes/get-optional-modules/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettypes/get-optional-modules/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Distribution set type was not found. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== POST /rest/v1/distributionsettypes/{distributionSetTypeId}/optionalmoduletypes + +=== Implementation notes + +Handles the POST request for adding an optional software module type to a distribution set type.Note that a DS type cannot be changed after it has been used by a DS. Required Permission: UPDATE_REPOSITORY and READ_REPOSITORY + +=== Add optional software module type + +==== CURL + +include::{snippets}/distributionsettypes/post-optional-module/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/post-optional-module/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettypes/post-optional-module/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/distributionsettypes/post-optional-module/request-fields.adoc[] + +=== Response (Status 201) + +==== Response example + +include::{snippets}/distributionsettypes/post-optional-module/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Distribution set type was not found. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +| `409 Conflict` +| Distribution set type already exists +| See <> +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/distributionsettypes/{distributionSetTypeId}/optionalmoduletypes/{softwareModuleTypeId} + +== DELETE /rest/v1/distributionsettypes/{distributionSetTypeId}/mandatorymoduletypes/{softwareModuleTypeId} + +=== Implementation Notes + +Handles DELETE request for removing an optional module from the distribution set type.Note that a DS type cannot be changed after it has been used by a DS. Required Permission: UPDATE_REPOSITORY and READ_REPOSITORY + +=== Remove optional module from distribution set type + +==== CURL + +include::{snippets}/distributionsettypes/delete-optional-module/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/delete-optional-module/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettypes/delete-optional-module/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/distributionsettypes/delete-optional-module/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Distribution set type was not found. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/distributionsettypes/{distributionSetTypeId}/optionalmoduletypes/{softwareModuleTypeId} + +=== Implementation notes + +Handles the GET request of retrieving the single optional software module type in that distribution set type. Required Permission: READ_REPOSITORY + +=== Retrieve optional software module type + +==== CURL + +include::{snippets}/distributionsettypes/get-optional-module/curl-request.adoc[] + +==== Request URL + +include::{snippets}/distributionsettypes/get-optional-module/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/distributionsettypes/post-optional-module/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/distributionsettypes/get-optional-module/response-fields.adoc[] + +==== Response example + +include::{snippets}/distributionsettypes/get-optional-module/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Distribution set type was not found. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== Additional content + +[[error-body]] +=== Error body + +include::../errors/error-response-body.adoc[] \ No newline at end of file diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/rollout-api-guide.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/rollout-api-guide.adoc new file mode 100644 index 000000000..ad6b2962d --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/rollout-api-guide.adoc @@ -0,0 +1,477 @@ +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: macro +:toclevels: 1 +:sectlinks: +:linkattrs: + + + +[[rollouts]] += Rollouts + +toc::[] + + +== GET /rest/v1/rollouts + +=== Implementation notes + +Handles the GET request of retrieving all rollouts within SP. Required Permission: READ_ROLLOUT + +=== Get paged list of Rollouts + +==== Curl + +include::{snippets}/rollouts/get-rollouts/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rollouts/get-rollouts/http-request.adoc[] + +==== Request query parameter + +include::{snippets}/rollouts/get-rollouts-with-parameters/request-parameters.adoc[] + +==== Request query parameter example + +include::{snippets}/rollouts/get-rollouts-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/rollouts/get-rollouts/response-fields.adoc[] + +==== Response example + +include::{snippets}/rollouts/get-rollouts/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== GET /rest/v1/rollouts/{rolloutId} + +=== Implementation Notes + +Handles the GET request of retrieving a single rollout within SP. Required Permission: READ_ROLLOUT + +=== Get Rollout + +==== CURL + +include::{snippets}/rollouts/get-rollout/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rollouts/get-rollout/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rollouts/get-rollout/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/rollouts/get-rollout/response-fields.adoc[] + +==== Response example + +include::{snippets}/rollouts/get-rollout/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== POST /rest/v1/rollouts + +=== Implementation Notes +Handles the POST request of creating new rollout within SP. Required Permission: CREATE_ROLLOUT + +=== Create Rollout with defined amount of groups + + +==== CURL + +include::{snippets}/rollouts/create-rollout/curl-request.adoc[] + + +==== Request URL + +include::{snippets}/rollouts/create-rollout/http-request.adoc[] + +==== Request fields + +include::{snippets}/rollouts/create-rollout/request-fields.adoc[] + +=== Response (Status 201) + +==== Response fields + +include::{snippets}/rollouts/create-rollout/response-fields.adoc[] + +==== Response example + +include::{snippets}/rollouts/create-rollout/http-response.adoc[] + + +=== Create Rollout with groups definition + + +==== CURL + +include::{snippets}/rollouts/create-rollout-with-groups-definition/curl-request.adoc[] + + +==== Request URL + +include::{snippets}/rollouts/create-rollout-with-groups-definition/http-request.adoc[] + +==== Request fields + +include::{snippets}/rollouts/create-rollout-with-groups-definition/request-fields.adoc[] + +=== Response (Status 201) + +==== Response fields + +include::{snippets}/rollouts/create-rollout-with-groups-definition/response-fields.adoc[] + +==== Response example + +include::{snippets}/rollouts/create-rollout-with-groups-definition/http-response.adoc[] + + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== POST /rest/v1/rollouts/{rolloutId}/start + +=== Implementation Notes +Handles the POST request of starting a created rollout within SP. Required Permission: HANDLE_ROLLOUT + +=== Start Rollout + + +==== CURL + +include::{snippets}/rollouts/start-rollout/curl-request.adoc[] + + +==== Request URL + +include::{snippets}/rollouts/start-rollout/http-request.adoc[] + + +=== Response (Status 200) + +==== Response example + +include::{snippets}/rollouts/start-rollout/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== POST /rest/v1/rollouts/{rolloutId}/pause + +=== Implementation Notes +Handles the POST request of pausing a running rollout within SP. Required Permission: HANDLE_ROLLOUT + +=== Pause Rollout + + +==== CURL + +include::{snippets}/rollouts/pause-rollout/curl-request.adoc[] + + +==== Request URL + +include::{snippets}/rollouts/pause-rollout/http-request.adoc[] + +==== Response example + +include::{snippets}/rollouts/pause-rollout/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== POST /rest/v1/rollouts/{rolloutId}/resume + +=== Implementation Notes +Handles the POST request of resuming a paused rollout within SP. Required Permission: HANDLE_ROLLOUT + +=== Resume Rollout + + +==== CURL + +include::{snippets}/rollouts/resume-rollout/curl-request.adoc[] + + +==== Request URL + +include::{snippets}/rollouts/resume-rollout/http-request.adoc[] + +==== Response example + +include::{snippets}/rollouts/resume-rollout/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== DELETE /rest/v1/rollouts/{rolloutId} + +=== Implementation Notes + +Handles the DELETE request of deleting a rollout within SP. Required Permission: DELETE_ROLLOUT + +=== Deleting a rollout + +==== CURL + +include::{snippets}/rollouts/delete-rollout/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rollouts/delete-rollout/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rollouts/delete-rollout/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/rollouts/delete-rollout/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== GET /rest/v1/rollouts/{rolloutId}/deploygroups + +=== Implementation Notes + +Handles the GET request of retrieving all deploy groups of a specific rollout within SP. Required Permission: READ_ROLLOUT + +=== Get Deploy Groups + +==== CURL + +include::{snippets}/rollouts/get-rollout-deploy-groups/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rollouts/get-rollout-deploy-groups/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rollouts/get-rollout-deploy-groups/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/rollouts/get-rollouts-with-parameters/request-parameters.adoc[] + +==== Request query parameter example + +include::{snippets}/rollouts/get-rollouts-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/rollouts/get-rollout-deploy-groups/response-fields.adoc[] + +==== Response example + +include::{snippets}/rollouts/get-rollout-deploy-groups/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== GET /rest/v1/rollouts/{rolloutId}/deploygroups/{deployGroupId} + +=== Implementation Notes + +Handles the GET request of a single deploy group of a specific rollout within SP. Required Permission: READ_ROLLOUT + +=== Get Deploy Groups + +==== CURL + +include::{snippets}/rollouts/get-rollout-deploy-group/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rollouts/get-rollout-deploy-group/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rollouts/get-rollout-deploy-group/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/rollouts/get-rollout-deploy-group/response-fields.adoc[] + +==== Response example + +include::{snippets}/rollouts/get-rollout-deploy-group/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== GET /rest/v1/rollouts/{rolloutId}/deploygroups/{deployGroupId}/targets + +=== Implementation Notes + +Handles the GET request of retrieving all targets of a single deploy group of a specific rollout within SP. Required Permissions: READ_ROLLOUT, READ_TARGET. + +=== Get Deploy Group Targets + +==== CURL + +include::{snippets}/rollouts/get-rollout-deploy-group-targets/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rollouts/get-rollout-deploy-group-targets/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rollouts/get-rollout-deploy-group-targets/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/rollouts/get-rollout-deploy-group-targets-with-parameters/request-parameters.adoc[] + +==== Request query parameter example + +include::{snippets}/rollouts/get-rollout-deploy-group-targets-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/rollouts/get-rollout-deploy-group-targets/response-fields.adoc[] + +==== Response example + +include::{snippets}/rollouts/get-rollout-deploy-group-targets/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== Additional content + +[[error-body]] +=== Error body + +include::../errors/error-response-body.adoc[] \ No newline at end of file diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/rootcontroller-api-guide.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/rootcontroller-api-guide.adoc new file mode 100644 index 000000000..ddd6fb521 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/rootcontroller-api-guide.adoc @@ -0,0 +1,398 @@ +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: macro +:toclevels: 1 +:sectlinks: +:linkattrs: + +[[root-controller]] += Root Controller + +toc::[] + +== GET /{tenant}/controller/v1/{targetid} + +=== Implementation notes + +This base resource can be regularly polled by the controller on the provisioning target or device in order to retrieve actions that need to be executed. Those are provided as a list of links to more detailed information about the action. The resource supports Etag based modification checks in order to save traffic. Note: deployments have to be confirmed in order to move on to the next action. Cancellations have to be confirmed or rejected. + +=== Controller base poll resource + +==== Curl + +include::{snippets}/rootcontroller/get-controller-base-with-open-deplyoment/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rootcontroller/get-controller-base-with-open-deplyoment/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rootcontroller/get-controller-base-with-open-deplyoment/path-parameters.adoc[] + +=== Response (Status 200) with an active deployment + +==== Response fields + +include::{snippets}/rootcontroller/get-controller-base-with-open-deplyoment/response-fields.adoc[] + +==== Response example + +include::{snippets}/rootcontroller/get-controller-base-with-open-deplyoment/http-response.adoc[] + +=== Response (Status 200) with an active cancellation + +==== Response fields + +include::{snippets}/rootcontroller/get-controller-base-with-open-deployment-cancellation/response-fields.adoc[] + +==== Response example + +include::{snippets}/rootcontroller/get-controller-base-with-open-deployment-cancellation/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403_quota.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /{tenant}/controller/v1/{targetid}/cancelAction/{actionId} + +=== Implementation notes + +The SP server might cancel an operation, e.g. an unfinished update has a sucessor. It is up to the provisiong target to decide to accept the cancelation or reject it. + +=== Cancel an action + +==== Curl + +include::{snippets}/rootcontroller/get-controller-cancel-action/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rootcontroller/get-controller-cancel-action/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rootcontroller/get-controller-cancel-action/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/rootcontroller/get-controller-cancel-action/response-fields.adoc[] + +==== Response example + +include::{snippets}/rootcontroller/get-controller-cancel-action/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + + +== POST /{tenant}/controller/v1/{targetid}/cancelAction/{actionId}/feedback + +=== Implementation notes + +It is up to the device how much intermediate feedback is provided. However, the action will be kept open until the controller on the device reports a finished (either successful or error) or rejects the action, e.g. the canceled actions have been started already. + +=== Feedback channel for cancel actions + +==== Curl + +include::{snippets}/rootcontroller/post-cancel-action-feedback/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rootcontroller/post-cancel-action-feedback/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rootcontroller/post-cancel-action-feedback/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/rootcontroller/post-cancel-action-feedback/request-fields.adoc[] + +=== Response (Status 200) + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== PUT /{tenant}/controller/v1/{targetid}/configData + +=== Implementation notes + +The usual behaviour is that when a new device resgisters at the server it is requested to provide the meta information that will allow the server to identify the device on a hardware level (e.g. hardware revision, mac address, serial number etc.). + +=== Response to a requested metadata pull from the provisioning target device. + +==== Curl + +include::{snippets}/rootcontroller/put-config-data/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rootcontroller/put-config-data/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rootcontroller/put-config-data/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/rootcontroller/put-config-data/request-fields.adoc[] + +=== Response (Status 200) + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /{tenant}/controller/v1/{targetid}/deploymentBase/{actionId} + +=== Implementation notes + +Core resource for deployment operations. Contains all information necessary in order to execute the operation. + +Keep in mind that the provided download links for the artifacts are generated dynamically by the update server. Host, port and path and not guaranteed to be similar to the provided examples below but will be defined at runtime. + +=== Deployment or update action + +==== Curl + +include::{snippets}/rootcontroller/get-controller-basedeployment-action/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rootcontroller/get-controller-basedeployment-action/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rootcontroller/get-controller-basedeployment-action/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/rootcontroller/get-controller-basedeployment-action/request-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/rootcontroller/get-controller-basedeployment-action/response-fields.adoc[] + +==== Response example + +In this case the (optional) query for the last 10 messages, previously provided by the device, are included. Useful if the devices provide state information previously on the feedback channel and won't store it locally. + +include::{snippets}/rootcontroller/get-controller-basedeployment-action/http-response.adoc[] + + +=== Response (Status 200) with a maintenance window defined but not active yet + +In addition to the straight forward approach to inform the device to download and install the software in one transaction hawkBit supports the separation of download and installation into separate steps. + +This feature is called Maintenance Window where the device is informed to download the software first and then when it enters a defined (maintenance) window the installation triggers follows as in the example above. + +==== Response example + +Note: artifact details not shown in this example. + +include::{snippets}/rootcontroller/get-controller-basedeployment-action-with-maintenance-window/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + + + +== POST /{tenant}/controller/v1/{targetid}/deploymentBase/{actionId}/feedback + + +=== Implementation notes + +Feedback channel. It is up to the device how much intermediate feedback is provided. However, the action will be kept open until the controller on the device reports a finished (either successful or error). + +=== Feedback channel for update action + +==== Curl + +include::{snippets}/rootcontroller/post-basedeployment-action-feedback/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rootcontroller/post-basedeployment-action-feedback/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rootcontroller/post-basedeployment-action-feedback/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/rootcontroller/post-basedeployment-action-feedback/request-fields.adoc[] + +=== Response (Status 200) + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== +//// +== GET /{tenant}/controller/v1/{targetid}/softwaremodules + +=== Implementation notes + +Returns all available software modules for a given target + +=== Returns software modules of given target + +==== Curl + +include::{snippets}/rootcontroller/get-software-modules/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rootcontroller/get-software-modules/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rootcontroller/get-software-modules/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/rootcontroller/get-software-modules/response-fields.adoc[] + +==== Response example + +include::{snippets}/rootcontroller/get-software-modules/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== +//// + +== GET /{tenant}/controller/v1/{targetid}/softwaremodules/{softwareModuleId}/artifacts + +=== Implementation notes + +Returns all artifacts whichs is assigned to the software module + +=== Returns artifacts of given software module + +==== Curl + +include::{snippets}/rootcontroller/get-software-modules-artifacts/curl-request.adoc[] + +==== Request URL + +include::{snippets}/rootcontroller/get-software-modules-artifacts/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/rootcontroller/get-software-modules-artifacts/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/rootcontroller/get-software-modules-artifacts/response-fields.adoc[] + +==== Response example + +include::{snippets}/rootcontroller/get-software-modules-artifacts/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== Additional content + +[[error-body]] +=== Error body + +include::../errors/error-response-body.adoc[] \ No newline at end of file diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/softwaremodules-api-guide.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/softwaremodules-api-guide.adoc new file mode 100644 index 000000000..565e3f99f --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/softwaremodules-api-guide.adoc @@ -0,0 +1,745 @@ +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: macro +:toclevels: 1 +:sectlinks: +:linkattrs: + +[[software-modules]] += Software Modules + +toc::[] + +== GET /rest/v1/softwaremodules + +=== Implementation notes + +Handles the GET request of retrieving all softwaremodules within SP. Required Permission: READ_REPOSITORY + +=== Get software modules + +==== CURL + +include::{snippets}/softwaremodules/get-software-modules/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/get-software-modules/http-request.adoc[] + +==== Request parameter + +include::{snippets}/softwaremodules/get-software-modules-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/softwaremodules/get-software-modules-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/softwaremodules/get-software-modules/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremodules/get-software-modules/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/softwaremodules + +=== Implementation notes + +Handles the POST request of creating new software modules within SP. The request body must always be a list of modules. Required Permission: CREATE_REPOSITORY + +=== Create software modules + +==== CURL + +include::{snippets}/softwaremodules/post-software-modules/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/post-software-modules/http-request.adoc[] + +==== Request fields + +include::{snippets}/softwaremodules/post-software-modules/request-fields.adoc[] + +=== Response (Status 201) + +==== Response fields + +include::{snippets}/softwaremodules/post-software-modules/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremodules/post-software-modules/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/softwaremodules/{softwareModuleId} + +=== Implementation Notes + +Handles the DELETE request for a single softwaremodule within SP. Required Permission: DELETE_REPOSITORY + +=== Delete software module + +==== CURL + +include::{snippets}/softwaremodules/delete-software-module/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/delete-software-module/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/delete-software-module/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/softwaremodules/delete-software-module/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/softwaremodules/{softwareModuleId} + +=== Implementation notes + +Handles the GET request of retrieving a single softwaremodule within SP. Required Permission: READ_REPOSITORY + +=== Get software module + +==== CURL + +include::{snippets}/softwaremodules/get-software-module/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/get-software-module/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/get-software-module/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/softwaremodules/get-software-module/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremodules/get-software-module/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== PUT /rest/v1/softwaremodules/{softwareModuleId} + +=== Implementation notes + +Handles the PUT request for a single softwaremodule within SP. Required Permission: UPDATE_REPOSITORY + +=== Update software module + +==== CURL + +include::{snippets}/softwaremodules/put-software-module/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/put-software-module/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/put-software-module/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/softwaremodules/put-software-module/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/softwaremodules/put-software-module/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremodules/put-software-module/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/softwaremodules/{softwareModuleId}/artifacts + +=== Implementation notes + +Handles the GET request of retrieving all meta data of artifacts assigned to a software module. Required Permission: READ_REPOSITORY + +=== List artifacts metadata + +==== CURL + +include::{snippets}/softwaremodules/get-artifacts/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/get-artifacts/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/get-artifacts/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/softwaremodules/get-artifacts/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremodules/get-artifacts/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/softwaremodules/{softwareModuleId}/artifacts + +=== Implementation notes + +Handles POST request for artifact upload. Required Permission: CREATE_REPOSITORY + +=== Upload artifact + +==== CURL + +include::{snippets}/softwaremodules/post-artifact/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/post-artifact/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/post-artifact/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/softwaremodules/post-artifact-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/softwaremodules/post-artifact-with-parameters/http-request.adoc[] + +=== Response (Status 201) + +==== Response fields + +include::{snippets}/softwaremodules/post-artifact/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremodules/post-artifact/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/softwaremodules/{softwareModuleId}/artifacts/{artifactId} + +=== Implementation Notes + +Handles the DELETE request for a single SoftwareModule within SP. Required Permission: DELETE_REPOSITORY + +=== Delete arifact + +==== CURL + +include::{snippets}/softwaremodules/delete-artifact/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/delete-artifact/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/delete-artifact/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/softwaremodules/delete-artifact/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/softwaremodules/{softwareModuleId}/artifacts/{artifactId} + +=== Implementation notes + +Handles the GET request of retrieving a single Artifact meta data request. Required Permission: READ_REPOSITORY + +=== Get artifact metadata + +==== CURL + +include::{snippets}/softwaremodules/get-artifact/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/get-artifact/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/get-artifact/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/softwaremodules/get-artifact/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremodules/get-artifact/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/softwaremodules/{softwareModuleId}/artifacts/{artifactId}/download + +=== Implementation notes + +Handles the GET request for downloading an artifact. Required Permission: READ_REPOSITORY + +=== Download artifact + +==== CURL + +include::{snippets}/softwaremodules/get-download-artifact/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/get-download-artifact/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/get-download-artifact/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/softwaremodules/get-download-artifact/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/softwaremodules/{softwareModuleId}/metadata + +=== Implementation notes + +Get a paged list of meta data for a software module. Required Permission: READ_REPOSITORY + +=== Get a paged list of metadata + +==== CURL + +include::{snippets}/softwaremodules/get-metadata/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/get-metadata/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/get-metadata/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/softwaremodules/get-metadata-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/softwaremodules/get-metadata-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/softwaremodules/get-metadata/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremodules/get-metadata/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/softwaremodules/{softwareModuleId}/metadata + +=== Implementation notes + +Create a list of meta data entries Required Permission: UPDATE_REPOSITORY + +=== Create a list of metadata entries + +==== CURL + +include::{snippets}/softwaremodules/post-metadata/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/post-metadata/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/post-metadata/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/softwaremodules/post-metadata/request-fields.adoc[] + +=== Response (Status 201) + +==== Response fields + +include::{snippets}/softwaremodules/post-metadata/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremodules/post-metadata/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== DELETE /rest/v1/softwaremodules/{softwareModuleId}/metadata/{metadataKey} + +=== Implementation Notes + +Delete a single meta data. Required Permission: UPDATE_REPOSITORY + +=== Deleting a single metadata + +==== CURL + +include::{snippets}/softwaremodules/delete-metadata/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/delete-metadata/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/delete-metadata/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/softwaremodules/delete-metadata/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/softwaremodules/{softwareModuleId}/metadata/{metadataKey} + +=== Implementation notes + +Get a single meta data value for a meta data key. Required Permission: READ_REPOSITORY + +=== Get a single metadata value + +==== CURL + +include::{snippets}/softwaremodules/get-metadata-value/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/get-metadata-value/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/get-metadata-value/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/softwaremodules/get-metadata-value/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremodules/get-metadata-value/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== PUT /rest/v1/softwaremodules/{softwareModuleId}/metadata/{metadataKey} + +=== Implementation notes + +Update a single meta data value for speficic key. Required Permission: UPDATE_REPOSITORY + +=== Updating a single metadata value + +==== CURL + +include::{snippets}/softwaremodules/put-metadata/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremodules/put-metadata/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremodules/put-metadata/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/softwaremodules/put-metadata/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/softwaremodules/put-metadata/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremodules/put-software-module/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== Additional content + +[[error-body]] +=== Error body + +include::../errors/error-response-body.adoc[] + + diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/softwaremoduletypes-api-guide.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/softwaremoduletypes-api-guide.adoc new file mode 100644 index 000000000..075ebd546 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/softwaremoduletypes-api-guide.adoc @@ -0,0 +1,255 @@ +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: macro +:toclevels: 1 +:sectlinks: +:linkattrs: + +[[software-module-types]] += Software Module Types + +toc::[] + +== GET /rest/v1/softwaremoduletypes + +=== Implementation notes + +Handles the GET request of retrieving all software module types within SP. Required Permission: READ_REPOSITORY + +=== Get software module types + +==== CURL + +include::{snippets}/softwaremoduletypes/get-software-module-types/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremoduletypes/get-software-module-types/http-request.adoc[] + +==== Request query parameter + +include::{snippets}/softwaremoduletypes/get-software-module-types-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/softwaremoduletypes/get-software-module-types-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/softwaremoduletypes/get-software-module-types/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremoduletypes/get-software-module-types/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/softwaremoduletypes + +=== Implementation notes + +Handles the POST request of creating new software module types within SP. The request body must always be a list of module types. Required Permission: CREATE_REPOSITORY + +=== Creating software module types + +==== CURL + +include::{snippets}/softwaremoduletypes/post-software-module-types/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremoduletypes/post-software-module-types/http-request.adoc[] + +==== Request fields + +include::{snippets}/softwaremoduletypes/post-software-module-types/request-fields.adoc[] + +=== Response (Status 201) + +==== Response fields + +include::{snippets}/softwaremoduletypes/post-software-module-types/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremoduletypes/post-software-module-types/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module Type. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/softwaremoduletypes/{softwareModuleTypeId} + +=== Implementation Notes + +Handles the DELETE request for a single software module type within SP. Required Permission: DELETE_REPOSITORY + +=== Delete software module type + +==== CURL + +include::{snippets}/softwaremoduletypes/delete-software-module-type/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremoduletypes/delete-software-module-type/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremoduletypes/delete-software-module-type/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/softwaremoduletypes/delete-software-module-type/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/softwaremoduletypes/{softwareModuleTypeId} + +=== Implementation notes + +Handles the GET request of retrieving a single software module type within SP. Required Permission: READ_REPOSITORY + +=== Accessing a software module type + +==== CURL + +include::{snippets}/softwaremoduletypes/get-software-module-type/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremoduletypes/get-software-module-type/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremoduletypes/get-software-module-type/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/softwaremoduletypes/get-software-module-type/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremoduletypes/get-software-module-type/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== PUT /rest/v1/softwaremoduletypes/{softwareModuleTypeId} + +=== Implementation notes + +Handles the PUT request for a single software module type within SP. Required Permission: UPDATE_REPOSITORY + +=== Updating a software module types + +==== CURL + +include::{snippets}/softwaremoduletypes/put-software-module-type/curl-request.adoc[] + +==== Request URL + +include::{snippets}/softwaremoduletypes/put-software-module-type/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/softwaremoduletypes/put-software-module-type/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/softwaremoduletypes/put-software-module-type/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/softwaremoduletypes/put-software-module-type/response-fields.adoc[] + +==== Response example + +include::{snippets}/softwaremoduletypes/put-software-module-type/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +| `404 Not Found` +| Not Found Software Module Type. +| See <> +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== Additional content + +[[error-body]] +=== Error body + +include::../errors/error-response-body.adoc[] + diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/targetfilters-api-guide.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/targetfilters-api-guide.adoc new file mode 100644 index 000000000..4a8bd1a0e --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/targetfilters-api-guide.adoc @@ -0,0 +1,392 @@ +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: macro +:toclevels: 1 +:sectlinks: +:linkattrs: + +[[targetfilters]] += Target filter queries + +toc::[] + + +== GET /rest/v1/targetfilters + +=== Implementation notes + +Handles the GET request of retrieving all target filter queries within SP. Required permission: READ_TARGET + +=== Get paged list of target filter queries + +==== CURL + +include::{snippets}/targetfilters/get-target-filter-queries/curl-request.adoc[] + +==== Request URL + +A `GET` request is used to access the target filter queries + +include::{snippets}/targetfilters/get-target-filter-queries/http-request.adoc[] + +==== Request query parameter + +include::{snippets}/targetfilters/get-target-filter-queries-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/targetfilters/get-target-filter-queries-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targetfilters/get-target-filter-queries/response-fields.adoc[] + +==== Response example + +include::{snippets}/targetfilters/get-target-filter-queries/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/targetfilters + +=== Implementation Notes + +Handles the POST request to create a new target filter query within SP. Required permission: CREATE_TARGET + +=== Create a target filter query + +==== CURL + +include::{snippets}/targetfilters/post-target-filter-query/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targetfilters/post-target-filter-query/http-request.adoc[] + +==== Request fields + +include::{snippets}/targetfilters/post-target-filter-query/request-fields.adoc[] + +=== Response (Status 201) + +==== Response fields + +include::{snippets}/targetfilters/post-target-filter-query/response-fields.adoc[] + +==== Response example + +include::{snippets}/targetfilters/post-target-filter-query/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403_quota.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/targetfilters/{targetFilterQueryId} + +=== Implementation Notes + +Handles the DELETE request of deleting a target filter query within SP. Required permission: DELETE_TARGET + +=== Deleting a target + +==== CURL + +include::{snippets}/targetfilters/delete-target-filter-query/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targetfilters/delete-target-filter-query/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targetfilters/delete-target-filter-query/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/targetfilters/delete-target-filter-query/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/targetfilters/{targetFilterQueryId} + +=== Implementation Notes + +Handles the GET request of retrieving a single target filter query within SP. Required permission: READ_TARGET + +=== Get single target + +==== CURL + +include::{snippets}/targetfilters/get-target-filter-query/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targetfilters/get-target-filter-query/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targetfilters/get-target-filter-query/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targetfilters/get-target-filter-query/response-fields.adoc[] + +==== Response example + +include::{snippets}/targetfilters/get-target-filter-query/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== PUT /rest/v1/targetfilters/{targetFilterQueryId} + +=== Implementation Notes + +Handles the PUT request of updating a target filter query within SP. Required permission: UPDATE_TARGET + +=== Update a target + +==== Curl + +include::{snippets}/targetfilters/put-target-filter-query/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targetfilters/put-target-filter-query/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targetfilters/put-target-filter-query/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/targetfilters/put-target-filter-query/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targetfilters/put-target-filter-query/response-fields.adoc[] + +==== Response example + +include::{snippets}/targetfilters/put-target-filter-query/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/targetfilters/{targetFilterQueryId}/autoAssignDS + +=== Implementation Notes + +Handles the GET request of retrieving the auto assign distribution set. Required permission: READ_TARGET + +=== Get auto assign distribution set + +==== Curl + +include::{snippets}/targetfilters/get-assign-d-s/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targetfilters/get-assign-d-s/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targetfilters/get-assign-d-s/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targetfilters/get-assign-d-s/response-fields.adoc[] + +==== Response example + +include::{snippets}/targetfilters/get-assign-d-s/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/targetfilters/{targetFilterQueryId}/autoAssignDS + +=== Implementation Notes + +Handles the POST request of setting the auto assign distribution set for a target filter query. +Required permissions: UPDATE_TARGET and READ_REPOSITORY + +=== Set auto assign distribution set + +==== Curl + +include::{snippets}/targetfilters/post-auto-assign-d-s/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targetfilters/post-auto-assign-d-s/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targetfilters/post-auto-assign-d-s/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/targetfilters/post-auto-assign-d-s/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targetfilters/post-auto-assign-d-s/response-fields.adoc[] + +==== Response example + +include::{snippets}/targetfilters/post-auto-assign-d-s/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/targetfilters/{targetFilterQueryId}/autoAssignDS + +=== Implementation Notes + +Removes the auto assign distribution set from the target filter query. Required permission: UPDATE_TARGET + +=== Removing the auto assign distribution set + +==== Curl + +include::{snippets}/targetfilters/delete-auto-assign-d-s/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targetfilters/delete-auto-assign-d-s/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targetfilters/delete-auto-assign-d-s/path-parameters.adoc[] + +=== Response (Status 204) + +==== Response example + +include::{snippets}/targetfilters/delete-auto-assign-d-s/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + + +== Additional content + +[[error-body]] +=== Error body + +include::../errors/error-response-body.adoc[] + + diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/targets-api-guide.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/targets-api-guide.adoc new file mode 100644 index 000000000..ef3ffb199 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/targets-api-guide.adoc @@ -0,0 +1,694 @@ +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: macro +:toclevels: 1 +:sectlinks: +:linkattrs: + +[[targets]] += Targets + +toc::[] + + +== GET /rest/v1/targets + +=== Implementation notes + +Handles the GET request of retrieving all targets within SP. Required permission: READ_TARGET + +=== Get paged list of targets + +==== CURL + +include::{snippets}/targets/get-targets/curl-request.adoc[] + +==== Request URL + +A `GET` request is used to access the targets + +include::{snippets}/targets/get-targets/http-request.adoc[] + +==== Request query parameter + +include::{snippets}/targets/get-targets-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/targets/get-targets-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targets/get-targets/response-fields.adoc[] + +==== Response example + +include::{snippets}/targets/get-targets/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/targets + +=== Implementation Notes + +Handles the POST request of creating new targets within SP. The request body must always be a list of targets. Required Permission: CREATE_TARGET + +=== Create list of targets + +==== CURL + +include::{snippets}/targets/post-targets/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targets/post-targets/http-request.adoc[] + +==== Request fields + +include::{snippets}/targets/post-targets/request-fields.adoc[] + +=== Response (Status 201) + +==== Response fields + +include::{snippets}/targets/post-targets/response-fields.adoc[] + +==== Response example + +include::{snippets}/targets/post-targets/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403_quota.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/targets/{targetId} + +=== Implementation Notes + +Handles the DELETE request of deleting a single target within SP. Required Permission: DELETE_TARGET + +=== Deleting a target + +==== CURL + +include::{snippets}/targets/delete-target/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targets/delete-target/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targets/delete-target/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/targets/delete-target/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/targets/{targetId} + +=== Implementation Notes + +Handles the GET request of retrieving a single target within SP. Required Permission: READ_TARGET + +=== Get single target + +==== CURL + +include::{snippets}/targets/get-target/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targets/get-target/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targets/get-target/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targets/get-target/response-fields.adoc[] + +==== Response example + +include::{snippets}/targets/get-target/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== PUT /rest/v1/targets/{targetId} + +=== Implementation Notes + +Handles the PUT request of updating a target within SP. Required Permission: UPDATE_TARGET + +=== Update a target + +==== Curl + +include::{snippets}/targets/put-target/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targets/put-target/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targets/put-target/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/targets/put-target/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targets/put-target/response-fields.adoc[] + +==== Response example + +include::{snippets}/targets/put-target/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/targets/{targetId}/actions + +=== Implementation Notes + +Handles the GET request of retrieving the full action history of a specific target. Required Permission: READ_TARGET + +=== List all actions of Target + +==== Curl + +include::{snippets}/targets/get-actions-from-target/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targets/get-actions-from-target/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targets/get-actions-from-target/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/targets/get-actions-from-target-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/targets/get-actions-from-target-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targets/get-actions-from-target-with-maintenance-window/response-fields.adoc[] + +==== Response example + +include::{snippets}/targets/get-actions-from-target/http-response.adoc[] + +==== Response example with Maintenance Window + +include::{snippets}/targets/get-actions-from-target-with-maintenance-window/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== PUT /rest/v1/targets/{targetId}/actions/{actionId} + +=== Implementation Notes + +Handles the PUT request to switch an action from soft to forced. Required Permission: UPDATE_TARGET. + +=== Update a target + +==== Curl + +include::{snippets}/targets/switch-action-to-forced/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targets/switch-action-to-forced/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targets/switch-action-to-forced/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/targets/switch-action-to-forced/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targets/switch-action-to-forced/response-fields.adoc[] + +==== Response example + +include::{snippets}/targets/switch-action-to-forced/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== DELETE /rest/v1/targets/{targetId}/actions/{actionId} + +=== Implementation Notes + +Cancels an active action, only active actions can be deleted. Required Permission: UPDATE_TARGET + +=== Canceling an active action + +==== Curl + +include::{snippets}/targets/delete-action-from-target/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targets/delete-action-from-target/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targets/delete-action-from-target/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/targets/delete-actions-from-target-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/targets/delete-actions-from-target-with-parameters/http-request.adoc[] + +=== Response (Status 204) + +==== Response example + +include::{snippets}/targets/delete-action-from-target/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/targets/{targetId}/actions/{actionId} + +=== Implementation Notes + +Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET + +=== Get assigned action of target + +==== Curl + +include::{snippets}/targets/get-action-from-target/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targets/get-action-from-target/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targets/get-action-from-target/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targets/get-action-from-target-with-maintenance-window/response-fields.adoc[] + +==== Response example + +include::{snippets}/targets/get-action-from-target/http-response.adoc[] + +==== Response example with Maintenance Window + +include::{snippets}/targets/get-action-from-target-with-maintenance-window/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/targets/{targetId}/actions/{actionId}/status + +=== Implementation Notes + +Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET + +=== Get statuses of assigned action + +==== Curl + +include::{snippets}/targets/get-status-from-action/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targets/get-status-from-action/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targets/get-status-from-action/path-parameters.adoc[] + +==== Request parameter + +include::{snippets}/targets/get-status-from-action-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/targets/get-status-from-action-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targets/get-status-from-action/response-fields.adoc[] + +==== Response example + +include::{snippets}/targets/get-status-from-action/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/targets/{targetId}/assignedDS + +=== Implementation Notes + +Handles the GET request of retrieving the assigned distribution set of an specific target. Required Permission: READ_TARGET + +=== Get assigned distribution set of target + +==== Curl + +include::{snippets}/targets/get-assigned-distribution-set-from-action/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targets/get-assigned-distribution-set-from-action/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targets/get-assigned-distribution-set-from-action/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targets/get-assigned-distribution-set-from-action/response-fields.adoc[] + +==== Response example + +include::{snippets}/targets/get-assigned-distribution-set-from-action/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/targets/{targetId}/assignedDS + +=== Implementation Notes + +Handles the POST request for assigning a distribution set to a specific target. Required Permission: READ_REPOSITORY and UPDATE_TARGET + +=== Asssin distribution set to target + +==== Curl + +include::{snippets}/targets/post-assign-distribution-set-to-target/curl-request.adoc[] + +==== Request path parameter + +include::{snippets}/targets/post-assign-distribution-set-to-target/path-parameters.adoc[] + +==== Request query parameter + +include::{snippets}/targets/post-assign-distribution-set-to-target/request-parameters.adoc[] + +==== Request fields + +include::{snippets}/targets/post-assign-distribution-set-to-target/request-fields.adoc[] + +==== Request URL + +include::{snippets}/targets/post-assign-distribution-set-to-target/http-request.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/targets/post-assign-distribution-set-to-target/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/targets/{targetId}/attributes + +=== Implementation Notes + +Handles the GET request of retrieving the attributes of a specific target. Reponse is a key/value list. Required Permission: READ_TARGET + +=== Get attributes of target + +==== Curl + +include::{snippets}/targets/get-controller-attributes/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targets/get-controller-attributes/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targets/get-controller-attributes/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/targets/get-controller-attributes/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/targets/{targetId}/installedDS + +=== Implementation Notes + +Handles the GET request of retrieving the installed distribution set of an specific target. Required Permission: READ_TARGET + +=== Get installed distribution set of target + +==== Curl + +include::{snippets}/targets/get-installed-distribution-set-from-target/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targets/get-installed-distribution-set-from-target/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targets/get-installed-distribution-set-from-target/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targets/get-installed-distribution-set-from-target/response-fields.adoc[] + +==== Response example + +include::{snippets}/targets/get-installed-distribution-set-from-target/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== Additional content + +[[error-body]] +=== Error body + +include::../errors/error-response-body.adoc[] + + diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/targettag-api-guide.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/targettag-api-guide.adoc new file mode 100644 index 000000000..a1a9cfccb --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/targettag-api-guide.adoc @@ -0,0 +1,431 @@ +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: macro +:toclevels: 1 +:sectlinks: +:linkattrs: + +[[targettag]] += Target Tag + +toc::[] + + +== GET /rest/v1/targettags + +=== Implementation notes + +Handles the GET request of retrieving all target tags. + +=== Get paged list of target tags + +==== CURL + +include::{snippets}/targettag/get-target-tags/curl-request.adoc[] + +==== Request URL + +A `GET` request is used to access the target tags + +include::{snippets}/targettag/get-target-tags/http-request.adoc[] + +==== Request query parameter + +include::{snippets}/targettag/get-target-tags-with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/targettag/get-target-tags-with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targettag/get-target-tags/response-fields.adoc[] + +==== Response example + +include::{snippets}/targettag/get-target-tags/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/targettags/{targetTagId} + +=== Implementation notes + +Handles the GET request of retrieving a single target tag. + +=== Get a single target tag + +==== CURL + +include::{snippets}/targettag/get-target-tag/curl-request.adoc[] + +==== Request URL + +A `GET` request is used to access the target tag + +include::{snippets}/targettag/get-target-tag/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targettag/get-target-tag/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targettag/get-target-tag/response-fields.adoc[] + +==== Response example + +include::{snippets}/targettag/get-target-tag/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/targettags + +=== Implementation Notes + +Handles the POST request of creating new target tag. The request body must always be a list of target tags. + +=== Create list of target tags + +==== CURL + +include::{snippets}/targettag/create-target-tags/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targettag/create-target-tags/http-request.adoc[] + +==== Request fields + +include::{snippets}/targettag/create-target-tags/request-fields.adoc[] + +=== Response (Status 201) + +==== Response fields + +include::{snippets}/targettag/create-target-tags/response-fields.adoc[] + +==== Response example + +include::{snippets}/targettag/create-target-tags/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== PUT /rest/v1/targettags/{targetTagId} + +=== Implementation Notes + +Handles the PUT request of updating a target tag. + +=== Update a target tag + +==== Curl + +include::{snippets}/targettag/update-tagret-tag/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targettag/update-tagret-tag/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targettag/update-tagret-tag/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/targettag/update-tagret-tag/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targettag/update-tagret-tag/response-fields.adoc[] + +==== Response example + +include::{snippets}/targettag/update-tagret-tag/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + + +== DELETE /rest/v1/targettags/{targetTagId} + +=== Implementation Notes + +Handles the DELETE request of deleting a single target tag. + +=== Deleting a target tag + +==== CURL + +include::{snippets}/targettag/delete-target-tag/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targettag/delete-target-tag/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targettag/delete-target-tag/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/targettag/delete-target-tag/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== GET /rest/v1/targettags/{targetTagId}/assigned + +=== Implementation Notes + +Handles the GET request of retrieving a list of assigned targets. + +=== Get a list of assigned targets + +==== CURL + +include::{snippets}/targettag/get-assigned-targets/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targettag/get-assigned-targets/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targettag/get-assigned-targets/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targettag/get-assigned-targets/response-fields.adoc[] + +==== Response example + +include::{snippets}/targettag/get-assigned-targets/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + + +== POST /rest/v1/targettags/{targetTagId}/assigned/toggleTagAssignment + +=== Implementation Notes + +Handles the POST request of toogle target assignment. The request body must always be a list of controller ids. + +=== Toogle target assignment + +==== CURL + +include::{snippets}/targettag/toggle-tag-assignment/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targettag/toggle-tag-assignment/http-request.adoc[] + +==== Request fields + +include::{snippets}/targettag/toggle-tag-assignment/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targettag/toggle-tag-assignment/response-fields.adoc[] + +==== Response example + +include::{snippets}/targettag/toggle-tag-assignment/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== POST /rest/v1/targettags/{targetTagId}/assigned + +=== Implementation Notes + +Handles the POST request of target assignment. Already assigned target will be ignored. + +=== Target assignment + +==== CURL + +include::{snippets}/targettag/assign-targets/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targettag/assign-targets/http-request.adoc[] + +==== Request fields + +include::{snippets}/targettag/assign-targets/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/targettag/assign-targets/response-fields.adoc[] + +==== Response example + +include::{snippets}/targettag/assign-targets/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== DELETE /rest/v1/targettags/{targetTagId}/assigned/{controllerId} + +=== Implementation Notes + +Handles the DELETE request to unassign the given target. + +=== Unassign a target + +==== CURL + +include::{snippets}/targettag/unassign-target/curl-request.adoc[] + +==== Request URL + +include::{snippets}/targettag/unassign-target/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/targettag/unassign-target/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response example + +include::{snippets}/targettag/unassign-target/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== Additional content + +[[error-body]] +=== Error body + +include::../errors/error-response-body.adoc[] + + + diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/tenant-api-guide.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/tenant-api-guide.adoc new file mode 100644 index 000000000..6bc35a948 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/asciidoc/tenant-api-guide.adoc @@ -0,0 +1,194 @@ +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: macro +:toclevels: 1 +:sectlinks: +:linkattrs: + +[[tenant]] += System Configuration + +toc::[] + + +== GET /rest/v1/system/configs + +=== Implementation notes + +The GET request returns a list of all possible configuration keys for the tenant. Required Permission: TENANT_CONFIGURATION + +=== Get all configuration parameters + +==== CURL + +include::{snippets}/tenant/get-tenant-configrations/curl-request.adoc[] + +==== Request URL + +include::{snippets}/tenant/get-tenant-configrations/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/tenant/get-tenant-configrations/response-fields.adoc[] + +==== Response example + +include::{snippets}/tenant/get-tenant-configrations/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== GET /rest/v1/system/configs/{keyName} + +=== Implementation notes + +The GET request returns the configuration value of a specific configuration key for the tenant. Required Permission: TENANT_CONFIGURATION + +=== Read a configuration parameter + +==== CURL + +include::{snippets}/tenant/get-tenant-configration/curl-request.adoc[] + +==== Request URL + +include::{snippets}/tenant/get-tenant-configration/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/tenant/get-tenant-configration/path-parameters.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/tenant/get-tenant-configration/response-fields.adoc[] + +==== Response example + +include::{snippets}/tenant/get-tenant-configration/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== PUT /rest/v1/system/configs/{keyName} + +=== Implementation notes + +The PUT request changes a configuration value of a specific configuration key for the tenant. Required Permission: TENANT_CONFIGURATION + +=== Change a configuration parameter + +==== CURL + +include::{snippets}/tenant/put-tenant-configration/curl-request.adoc[] + +==== Request URL + +include::{snippets}/tenant/put-tenant-configration/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/tenant/put-tenant-configration/path-parameters.adoc[] + +==== Request fields + +include::{snippets}/tenant/put-tenant-configration/request-fields.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/tenant/put-tenant-configration/response-fields.adoc[] + +==== Response example + +include::{snippets}/tenant/put-tenant-configration/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/409.adoc[] +include::../errors/415.adoc[] +include::../errors/429.adoc[] +|=== + +== DELETE /rest/v1/system/configs/{keyName} + +=== Implementation notes + +The DELETE request removes a tenant specific configuration value for the tenant. Afterwards the global default value is used. Required Permission: TENANT_CONFIGURATION + +=== Removes a configuration parameter + +==== CURL + +include::{snippets}/tenant/delete-tenant-configration/curl-request.adoc[] + +==== Request URL + +include::{snippets}/tenant/delete-tenant-configration/http-request.adoc[] + +==== Request path parameter + +include::{snippets}/tenant/delete-tenant-configration/path-parameters.adoc[] + +=== Response (Status 204) + +==== Response example + +include::{snippets}/tenant/delete-tenant-configration/http-response.adoc[] + +=== Error responses + +|=== +| HTTP Status Code | Reason | Response Model + +include::../errors/400.adoc[] +include::../errors/401.adoc[] +include::../errors/403.adoc[] +include::../errors/404.adoc[] +include::../errors/405.adoc[] +include::../errors/406.adoc[] +include::../errors/429.adoc[] +|=== + +== Additional content + +[[error-body]] +=== Error body + +include::../errors/error-response-body.adoc[] diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/errors/400.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/400.adoc new file mode 100644 index 000000000..18af7627b --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/400.adoc @@ -0,0 +1,3 @@ +| `400 Bad Request` +| Bad Request - e.g. invalid parameters +| diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/errors/401.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/401.adoc new file mode 100644 index 000000000..bfe5050c9 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/401.adoc @@ -0,0 +1,3 @@ +| `401 Unauthorized` +| The request requires user authentication. +| diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/errors/403.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/403.adoc new file mode 100644 index 000000000..492f5a722 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/403.adoc @@ -0,0 +1,3 @@ +| `403 Forbidden` +| Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies. +| See <> diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/errors/403_quota.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/403_quota.adoc new file mode 100644 index 000000000..1a817026b --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/403_quota.adoc @@ -0,0 +1,3 @@ +| `403 Forbidden` +| Insufficient permissions, data volume restriction applies or quota limit exceeded. +| See <> diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/errors/404.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/404.adoc new file mode 100644 index 000000000..13a2b6335 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/404.adoc @@ -0,0 +1,3 @@ +| `404 Not Found` +| Not Found Target. +| See <> diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/errors/405.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/405.adoc new file mode 100644 index 000000000..01159992b --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/405.adoc @@ -0,0 +1,3 @@ +| `405 Method Not Allowed` +| The http request method is not allowed on the resource. +| diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/errors/406.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/406.adoc new file mode 100644 index 000000000..8a3dc60b7 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/406.adoc @@ -0,0 +1,3 @@ +| `406 Not Acceptable` +| In case accept header is specified and not application/json. +| diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/errors/409.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/409.adoc new file mode 100644 index 000000000..363b0e04d --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/409.adoc @@ -0,0 +1,3 @@ +| `409 Conflict` +| E.g. in case an entity is created or modified by another user in another request at the same time. You may retry your modification request. +| See <> diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/errors/415.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/415.adoc new file mode 100644 index 000000000..5a993596d --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/415.adoc @@ -0,0 +1,3 @@ +| `415 Unsupported Media Type` +| The request was attempt with a media-type which is not supported by the server for this resource. +| diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/errors/429.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/429.adoc new file mode 100644 index 000000000..c215b43de --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/429.adoc @@ -0,0 +1,3 @@ +| `429 Too Many Request` +| Too many requests. The server will refuse further attempts and the client has to wait another second. +| diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/errors/error-response-body.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/error-response-body.adoc new file mode 100644 index 000000000..a842b56fb --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/errors/error-response-body.adoc @@ -0,0 +1,27 @@ +[source,http] +---- + +{ + "errorCode": "string", + "exceptionClass": "string", + "message": "string", + "parameters": [ + "string" + ] +} + +---- + +=== Field description + +|=== +|**Field** |**Description** +| errorCode +| A error code/key set by server +| exceptionClass +| The involved exceptionClass +| message +| An error message set by the server +| parameters +| A list of parameters +|=== diff --git a/hawkbit-rest/hawkbit-rest-docs/src/main/template/template.adoc b/hawkbit-rest/hawkbit-rest-docs/src/main/template/template.adoc new file mode 100644 index 000000000..13d600c0f --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/main/template/template.adoc @@ -0,0 +1,64 @@ += Management API +Eclipse hawkBit; +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: macro +:toclevels: 1 +:sectlinks: +:linkattrs: + +[[resource-name]] += Resource name + +toc::[] + + +== The request: Example: GET /rest/v1/targets + +=== Implementation notes + +..... Implementation notes ..... +..... Implementation notes ..... + +=== Describe the request: Example: Get paged list of targets + +==== CURL + +include::{snippets}/ ... ...curl-request.adoc[] + +==== Request URL + +include::{snippets}/... ...http-request.adoc[] + +==== Request path parameter + +include::{snippets}/ ... ...path-parameters.adoc[] + +==== Request fields + +include::{snippets}/ ... ...request-fields.adoc[] + +==== Request query parameter + +include::{snippets}/ ... ...with-parameters/request-parameters.adoc[] + +==== Request parameter example + +include::{snippets}/ ... ...with-parameters/http-request.adoc[] + +=== Response (Status 200) + +==== Response fields + +include::{snippets}/ ... ...response-fields.adoc[] + +==== Response example + +include::{snippets}/ ... ...http-response.adoc[] + +=== Error responses + +include::../errors/... +include::../errors/... +... \ No newline at end of file diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/ddi/documentation/DdiApiModelProperties.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/ddi/documentation/DdiApiModelProperties.java new file mode 100644 index 000000000..44708fc7e --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/ddi/documentation/DdiApiModelProperties.java @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.ddi.documentation; + +/** + * Model properties for the DDI API documentation. + */ +final class DdiApiModelProperties { + + // Direct Device Integration API + static final String CONTROLLER_ID = "id of the controller"; + + static final String TARGET_TIME = "time on the target device"; + + static final String TARGET_STATUS = "target action status"; + + static final String TARGET_EXEC_STATUS = "status of the action execution"; + + static final String TARGET_RESULT_VALUE = "result of the action execution"; + + static final String TARGET_RESULT_DETAILS = "List of details message information"; + + static final String TARGET_RESULT_FINISHED = "defined status of the result"; + + static final String TARGET_RESULT_PROGRESS = "progress assumption of the device"; + + static final String TARGET_PROGRESS_CNT = "current progress level"; + + static final String TARGET_PROGRESS_OF = "assumption concerning max progress level"; + + static final String ACTION_ID = "id of the action"; + + static final String CANCEL_ACTION = "action that needs to be canceled"; + + static final String ACTION_ID_CANCELED = "id of the action that needs to be canceled (typically identical to id field on the cancel action itself)"; + + static final String ARTIFACT_HTTPS_HASHES_MD5SUM_LINK = "HTTPs Download resource for MD5SUM file is an optional auto generated artifact that is especially useful for " + + "Linux based devices on order to check artifact consistency after download by using the md5sum " + + "command line tool. The MD5 and SHA1 are in addition available as metadata in the deployment command itself."; + + static final String ARTIFACT_HTTP_HASHES_MD5SUM_LINK = "HTTP Download resource for MD5SUM file is an optional auto generated artifact that is especially useful for " + + "Linux based devices on order to check artifact consistency after download by using the md5sum " + + "command line tool. The MD5 and SHA1 are in addition available as metadata in the deployment command itself. " + + "(note: anonymous download needs to be enabled on the service account for non-TLS access)"; + + static final String ARTIFACT_HTTPS_DOWNLOAD_LINK_BY_CONTROLLER = "HTTPs Download resource for artifacts. The resource supports partial download " + + "as specified by RFC7233 (range requests). Keep in mind that the target " + + "needs to have the artifact assigned in order to be granted permission to download."; + + static final String ARTIFACT_HTTP_DOWNLOAD_LINK_BY_CONTROLLER = "HTTP Download resource for artifacts. The resource supports partial download " + + "as specified by RFC7233 (range requests). Keep in mind that the target " + + "needs to have the artifact assigned in order to be granted permission to download. " + + "(note: anonymous download needs to be enabled on the service account for non-TLS access)"; + + static final String CHUNK_TYPE = "Type of the chunk, e.g. firmware, bundle, app. In update server mapped to Software Module Type."; + + static final String SOFTWARE_MODUL_TYPE = "type of the software module, e.g. firmware, bundle, app"; + + static final String SOFTWARE_MODULE_VERSION = "version of the software module"; + + static final String SOFTWARE_MODULE_NAME = "name of the software module"; + + static final String SOFTWARE_MODULE_ARTIFACT_LINKS = "artifact links of the software module"; + + static final String SOFTWARE_MODUL_ID = "id of the software module"; + + static final String CHUNK_VERSION = "software version of the chunk"; + + static final String CHUNK_NAME = "name of the chunk"; + + static final String CHUNK_META_DATA = "meta data of the respective software module that has been marked with 'target visible'"; + + static final String CHUNK_META_DATA_KEY = "key of meta data entry"; + + static final String CHUNK_META_DATA_VALUE = "value of meta data entry"; + + static final String ARTIFACTS = "list of artifacts"; + + static final String TARGET_CONFIGURATION = "target configuration setup by the server"; + + static final String TARGET_POLL_TIME = "suggested sleep time between polls"; + + static final String TARGET_OPEN_ACTIONS = "Open Actions that the server has for the target"; + + static final String TARGET_SLEEP = "sleep time in HH:MM:SS notation"; + + static final String DEPLOYMENT = "Detailed deployment operation"; + + static final String CANCEL = "Detailed cancel operation of a deployment."; + + static final String HANDLING_DOWNLOAD = "handling for the download part of the provisioning process ('skip': do not download yet, 'attempt': server asks to download, 'forced': server requests immediate download)"; + + static final String HANDLING_UPDATE = "handling for the update part of the provisioning process ('skip': do not update yet, 'attempt': server asks to update, 'forced': server requests immediate update)"; + + static final String MAINTENANCE_WINDOW = "separation of download and installation by defining a maintenance window for the installation. Status shows if currently in a window."; + + static final String CHUNK = "Software chunks of an update. In server mapped by Software Module."; + + static final String SOFTWARE_MODUL = "software modules of an update"; + + static final String ARTIFACT = "artifact modules of an update"; + + static final String FILENAME = "file name of artifact"; + + static final String TARGET_CONFIG_DATA = "configuration data as key/value list"; + + static final String ARTIFACT_HASHES_SHA1 = "SHA1 hash of the artifact in Base 16 format"; + static final String ARTIFACT_HASHES_MD5 = "MD5 hash of the artifact"; + static final String ARTIFACT_SIZE = "size of the artifact"; + + static final String ACTION_HISTORY = "Optional GET parameter to retrieve a given number of messages which are previously provided by the device. " + + "Useful if the devices sent state information to the feedback channel and never stored them locally."; + + static final String ACTION_HISTORY_RESP = "Current deployment state."; + + static final String ACTION_HISTORY_RESP_STATUS = "Status of the deployment based on previous feedback by the device."; + + static final String ACTION_HISTORY_RESP_MESSAGES = "Messages are previously sent to the feedback channel in LIFO order by the device."; + + static final String UPDATE_MODE = "Optional parameter to specify the update mode that should be applied when updating target attributes. " + + "Valid values are 'merge', 'replace', and 'remove'. Defaults to 'merge'."; + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/ddi/documentation/RootControllerDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/ddi/documentation/RootControllerDocumentationTest.java new file mode 100644 index 000000000..5329a4abc --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/ddi/documentation/RootControllerDocumentationTest.java @@ -0,0 +1,459 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.ddi.documentation; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.restdocs.snippet.Attributes.key; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.ByteArrayInputStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.RandomStringUtils; +import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; +import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.Status; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.Target; +import org.eclipse.hawkbit.repository.test.util.WithUser; +import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation; +import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric; +import org.eclipse.hawkbit.rest.util.JsonBuilder; +import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; +import org.junit.Before; +import org.junit.Test; +import org.springframework.hateoas.MediaTypes; +import org.springframework.http.MediaType; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +/** + * Documentation generation for Direct Device Integration API. + * + */ +@Features("Documentation Verfication - Direct Device Integration API") +@Stories("Root Resource") +public class RootControllerDocumentationTest extends AbstractApiRestDocumentation { + private static final String CONTROLLER_ID = "CONTROLLER_ID"; + + @Override + @Before + public void setUp() { + host = "ddi-api.host"; + resourceName = "rootcontroller"; + super.setUp(); + } + + @Test + @Description("This base resource can be regularly polled by the controller on the provisiong target or device " + + "in order to retrieve actions that need to be executed. In this case including a config pull request and a deployment. The resource supports Etag based modification " + + "checks in order to save traffic.") + @WithUser(tenantId = "TENANT_ID", authorities = "ROLE_CONTROLLER", allSpPermissions = true) + public void getControllerBaseWithOpenDeplyoment() throws Exception { + final DistributionSet set = testdataFactory.createDistributionSet("one"); + + final Target target = targetManagement.create(entityFactory.target().create().controllerId(CONTROLLER_ID)); + deploymentManagement.assignDistributionSet(set.getId(), Arrays.asList(target.getTargetWithActionType())); + + mockMvc.perform(get(DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}", + tenantAware.getCurrentTenant(), target.getControllerId()).accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters(parameterWithName("tenant").description(ApiModelPropertiesGeneric.TENANT), + parameterWithName("controllerId").description(DdiApiModelProperties.CONTROLLER_ID)), + responseFields( + fieldWithPath("config.polling").description(DdiApiModelProperties.TARGET_POLL_TIME), + fieldWithPath("config.polling.sleep").description(DdiApiModelProperties.TARGET_SLEEP), + fieldWithPath("_links").description(DdiApiModelProperties.TARGET_OPEN_ACTIONS), + fieldWithPath("_links.deploymentBase").description(DdiApiModelProperties.DEPLOYMENT), + fieldWithPath("_links.configData") + .description(DdiApiModelProperties.TARGET_CONFIG_DATA)))); + } + + @Test + @Description("This base resource can be regularly polled by the controller on the provisiong target or device " + + "in order to retrieve actions that need to be executed. In this case including a config pull request and a cancellation. " + + "Note: as with deployments the cancel action has to be confirmed or rejected in order to move on to the next action.") + @WithUser(tenantId = "TENANT_ID", authorities = "ROLE_CONTROLLER", allSpPermissions = true) + public void getControllerBaseWithOpenDeploymentCancellation() throws Exception { + final DistributionSet set = testdataFactory.createDistributionSet("one"); + final DistributionSet setTwo = testdataFactory.createDistributionSet("two"); + + final Target target = targetManagement.create(entityFactory.target().create().controllerId(CONTROLLER_ID)); + deploymentManagement.assignDistributionSet(set.getId(), Arrays.asList(target.getTargetWithActionType())); + deploymentManagement.assignDistributionSet(setTwo.getId(), Arrays.asList(target.getTargetWithActionType())); + + mockMvc.perform(get(DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}", + tenantAware.getCurrentTenant(), target.getControllerId()).accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters(parameterWithName("tenant").description(ApiModelPropertiesGeneric.TENANT), + parameterWithName("controllerId").description(DdiApiModelProperties.CONTROLLER_ID)), + responseFields( + fieldWithPath("config.polling").description(DdiApiModelProperties.TARGET_POLL_TIME), + fieldWithPath("config.polling.sleep").description(DdiApiModelProperties.TARGET_SLEEP), + fieldWithPath("_links").description(DdiApiModelProperties.TARGET_OPEN_ACTIONS), + fieldWithPath("_links.cancelAction").description(DdiApiModelProperties.DEPLOYMENT), + fieldWithPath("_links.configData") + .description(DdiApiModelProperties.TARGET_CONFIG_DATA)))); + } + + @Test + @Description("The SP server might cancel an operation, e.g. an unfinished update has a sucessor. " + + "It is up to the provisiong target to decide either to accept the cancelation or reject it.") + @WithUser(tenantId = "TENANT_ID", authorities = "ROLE_CONTROLLER", allSpPermissions = true) + public void getControllerCancelAction() throws Exception { + final DistributionSet set = testdataFactory.createDistributionSet("one"); + + set.getModules().forEach(module -> { + final byte random[] = RandomStringUtils.random(5).getBytes(); + + artifactManagement.create(new ByteArrayInputStream(random), module.getId(), "binary.tgz", false, 0); + artifactManagement.create(new ByteArrayInputStream(random), module.getId(), "file.signature", false, 0); + }); + + final Target target = targetManagement.create(entityFactory.target().create().controllerId(CONTROLLER_ID)); + final Long actionId = deploymentManagement + .assignDistributionSet(set.getId(), Arrays.asList(target.getTargetWithActionType())).getActions() + .get(0); + final Action cancelAction = deploymentManagement.cancelAction(actionId); + + mockMvc.perform( + get(DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.CANCEL_ACTION + + "/{actionId}", tenantAware.getCurrentTenant(), target.getControllerId(), cancelAction.getId()) + .accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters(parameterWithName("tenant").description(ApiModelPropertiesGeneric.TENANT), + parameterWithName("controllerId").description(DdiApiModelProperties.CONTROLLER_ID), + parameterWithName("actionId").description(DdiApiModelProperties.ACTION_ID_CANCELED)), + + responseFields(fieldWithPath("id").description(DdiApiModelProperties.ACTION_ID), + fieldWithPath("cancelAction").description(DdiApiModelProperties.CANCEL_ACTION), + fieldWithPath("cancelAction.stopId") + .description(DdiApiModelProperties.ACTION_ID_CANCELED) + + ))); + } + + @Test + @Description("It is up to the device to decided how much intermediate feedback is " + + "provided. However, the action will be kept open until the controller on the device reports a " + + "finished (either successfull or error) or rejects the oprtioan, e.g. the canceled actions have been started already.") + @WithUser(tenantId = "TENANT_ID", authorities = "ROLE_CONTROLLER", allSpPermissions = true) + public void postCancelActionFeedback() throws Exception { + final DistributionSet set = testdataFactory.createDistributionSet("one"); + + final Target target = targetManagement.create(entityFactory.target().create().controllerId(CONTROLLER_ID)); + final Long actionId = deploymentManagement + .assignDistributionSet(set.getId(), Arrays.asList(target.getTargetWithActionType())).getActions() + .get(0); + final Action cancelAction = deploymentManagement.cancelAction(actionId); + + mockMvc.perform(post( + DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.CANCEL_ACTION + + "/{actionId}/feedback", + tenantAware.getCurrentTenant(), target.getControllerId(), cancelAction.getId()).content( + JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "closed", "Some feedback")) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("tenant").description(ApiModelPropertiesGeneric.TENANT), + parameterWithName("controllerId").description(DdiApiModelProperties.CONTROLLER_ID), + parameterWithName("actionId").description(DdiApiModelProperties.ACTION_ID_CANCELED)), + requestFields(optionalRequestFieldWithPath("id").description(DdiApiModelProperties.ACTION_ID), + optionalRequestFieldWithPath("time").description(DdiApiModelProperties.TARGET_TIME), + requestFieldWithPath("status").description(DdiApiModelProperties.TARGET_STATUS), + requestFieldWithPath("status.execution") + .description(DdiApiModelProperties.TARGET_EXEC_STATUS).type("enum") + .attributes(key("value").value( + "['closed', 'proceeding', 'canceled','scheduled', 'rejected', 'resumed']")), + requestFieldWithPath("status.result") + .description(DdiApiModelProperties.TARGET_RESULT_VALUE), + requestFieldWithPath("status.result.finished") + .description(DdiApiModelProperties.TARGET_RESULT_FINISHED).type("enum") + .attributes(key("value").value("['success', 'failure', 'none']")), + optionalRequestFieldWithPath("status.details") + .description(DdiApiModelProperties.TARGET_RESULT_DETAILS)))); + } + + @Test + @Description("The usual behaviour is that when a new device resgisters at the server it is " + + "requested to provide the meta information that will allow the server to identify the device on a " + + "hardware level (e.g. hardware revision, mac address, serial number etc.).") + @WithUser(tenantId = "TENANT_ID", authorities = "ROLE_CONTROLLER", allSpPermissions = true) + public void putConfigData() throws Exception { + final Target target = targetManagement.create(entityFactory.target().create().controllerId(CONTROLLER_ID)); + + final Map attributes = new HashMap<>(); + attributes.put("hwRevision", "2"); + attributes.put("VIN", "JH4TB2H26CC000000"); + + mockMvc.perform( + put(DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.CONFIG_DATA_ACTION, + tenantAware.getCurrentTenant(), target.getControllerId()) + .content(JsonBuilder.configData("", attributes, "closed", "merge")) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("tenant").description(ApiModelPropertiesGeneric.TENANT), + parameterWithName("controllerId").description(DdiApiModelProperties.CONTROLLER_ID)), + requestFields(optionalRequestFieldWithPath("id").description(DdiApiModelProperties.ACTION_ID), + optionalRequestFieldWithPath("time").description(DdiApiModelProperties.TARGET_TIME), + requestFieldWithPath("status").description(DdiApiModelProperties.TARGET_STATUS), + requestFieldWithPath("status.execution") + .description(DdiApiModelProperties.TARGET_EXEC_STATUS).type("enum") + .attributes(key("value").value( + "['closed', 'proceeding', 'canceled','scheduled', 'rejected', 'resumed']")), + requestFieldWithPath("status.result") + .description(DdiApiModelProperties.TARGET_RESULT_VALUE), + requestFieldWithPath("status.result.finished") + .description(DdiApiModelProperties.TARGET_RESULT_FINISHED).type("enum") + .attributes(key("value").value("['success', 'failure', 'none']")), + optionalRequestFieldWithPath("status.details") + .description(DdiApiModelProperties.TARGET_RESULT_DETAILS), + requestFieldWithPath("data").description(DdiApiModelProperties.TARGET_CONFIG_DATA), + optionalRequestFieldWithPath("mode").description(DdiApiModelProperties.UPDATE_MODE) + .type("enum") + .attributes(key("value").value("['merge', 'replace', 'remove']"))))); + + } + + @Test + @Description("Core resource for deployment operations. Contains all information necessary in order to execute the operation.") + @WithUser(tenantId = "TENANT_ID", authorities = "ROLE_CONTROLLER", allSpPermissions = true) + public void getControllerBasedeploymentAction() throws Exception { + final DistributionSet set = testdataFactory.createDistributionSet("one"); + + set.getModules().forEach(module -> { + final byte random[] = RandomStringUtils.random(5).getBytes(); + + artifactManagement.create(new ByteArrayInputStream(random), module.getId(), "binary.tgz", false, 0); + artifactManagement.create(new ByteArrayInputStream(random), module.getId(), "file.signature", false, 0); + }); + + softwareModuleManagement.createMetaData( + entityFactory.softwareModuleMetadata().create(set.getModules().iterator().next().getId()) + .key("aMetadataKey").value("Metadata value as defined in software module").targetVisible(true)); + + final Target target = targetManagement.create(entityFactory.target().create().controllerId(CONTROLLER_ID)); + final Long actionId = assignDistributionSetWithMaintenanceWindow(set.getId(), target.getControllerId(), + getTestSchedule(-5), getTestDuration(10), getTestTimeZone()).getActions().get(0); + + controllerManagement.addInformationalActionStatus( + entityFactory.actionStatus().create(actionId).message("Started download").status(Status.DOWNLOAD)); + controllerManagement.addInformationalActionStatus(entityFactory.actionStatus().create(actionId) + .message("Download failed. ErrorCode #5876745. Retry").status(Status.WARNING)); + controllerManagement.addInformationalActionStatus( + entityFactory.actionStatus().create(actionId).message("Download done").status(Status.DOWNLOADED)); + controllerManagement.addInformationalActionStatus( + entityFactory.actionStatus().create(actionId).message("Write firmware").status(Status.RUNNING)); + controllerManagement.addInformationalActionStatus( + entityFactory.actionStatus().create(actionId).message("Reboot").status(Status.RUNNING)); + + mockMvc.perform(get( + DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.DEPLOYMENT_BASE_ACTION + + "/{actionId}?actionHistory=10", + tenantAware.getCurrentTenant(), target.getControllerId(), actionId).accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters(parameterWithName("tenant").description(ApiModelPropertiesGeneric.TENANT), + parameterWithName("controllerId").description(DdiApiModelProperties.CONTROLLER_ID), + parameterWithName("actionId").description(DdiApiModelProperties.ACTION_ID)), + requestParameters( + parameterWithName("actionHistory").description(DdiApiModelProperties.ACTION_HISTORY)), + responseFields(fieldWithPath("id").description(DdiApiModelProperties.ACTION_ID), + fieldWithPath("deployment").description(DdiApiModelProperties.DEPLOYMENT), + fieldWithPath("deployment.download") + .description(DdiApiModelProperties.HANDLING_DOWNLOAD).type("enum") + .attributes(key("value").value("['skip', 'attempt', 'forced']")), + fieldWithPath("deployment.update").description(DdiApiModelProperties.HANDLING_UPDATE) + .type("enum").attributes(key("value").value("['skip', 'attempt', 'forced']")), + fieldWithPath("deployment.maintenanceWindow") + .description(DdiApiModelProperties.MAINTENANCE_WINDOW).type("enum") + .attributes(key("value").value("['available', 'unavailable']")), + fieldWithPath("deployment.chunks").description(DdiApiModelProperties.CHUNK), + fieldWithPath("deployment.chunks[].metadata") + .description(DdiApiModelProperties.CHUNK_META_DATA), + fieldWithPath("deployment.chunks[].metadata[].key") + .description(DdiApiModelProperties.CHUNK_META_DATA_KEY), + fieldWithPath("deployment.chunks[].metadata[].value") + .description(DdiApiModelProperties.CHUNK_META_DATA_VALUE), + fieldWithPath("deployment.chunks[].part").description(DdiApiModelProperties.CHUNK_TYPE), + fieldWithPath("deployment.chunks[].name").description(DdiApiModelProperties.CHUNK_NAME), + fieldWithPath("deployment.chunks[].version") + .description(DdiApiModelProperties.CHUNK_VERSION), + fieldWithPath("deployment.chunks[].artifacts") + .description(DdiApiModelProperties.ARTIFACTS), + fieldWithPath("deployment.chunks[].artifacts[].filename") + .description(DdiApiModelProperties.ARTIFACTS), + fieldWithPath("deployment.chunks[].artifacts[].hashes") + .description(DdiApiModelProperties.ARTIFACTS), + fieldWithPath("deployment.chunks[].artifacts[].hashes.sha1") + .description(DdiApiModelProperties.ARTIFACT_HASHES_SHA1), + fieldWithPath("deployment.chunks[].artifacts[].hashes.md5") + .description(DdiApiModelProperties.ARTIFACT_HASHES_MD5), + fieldWithPath("deployment.chunks[].artifacts[].size") + .description(DdiApiModelProperties.ARTIFACT_SIZE), + fieldWithPath("deployment.chunks[].artifacts[]._links.download") + .description(DdiApiModelProperties.ARTIFACT_HTTPS_DOWNLOAD_LINK_BY_CONTROLLER), + fieldWithPath("deployment.chunks[].artifacts[]._links.md5sum") + .description(DdiApiModelProperties.ARTIFACT_HTTPS_HASHES_MD5SUM_LINK), + fieldWithPath("deployment.chunks[].artifacts[]._links.download-http") + .description(DdiApiModelProperties.ARTIFACT_HTTP_DOWNLOAD_LINK_BY_CONTROLLER), + fieldWithPath("deployment.chunks[].artifacts[]._links.md5sum-http") + .description(DdiApiModelProperties.ARTIFACT_HTTP_HASHES_MD5SUM_LINK), + fieldWithPath("actionHistory").description(DdiApiModelProperties.ACTION_HISTORY_RESP), + fieldWithPath("actionHistory.status") + .description(DdiApiModelProperties.ACTION_HISTORY_RESP_STATUS), + fieldWithPath("actionHistory.messages") + .description(DdiApiModelProperties.ACTION_HISTORY_RESP_MESSAGES)))); + + } + + @Test + @Description("Core resource for deployment operations. Contains all information necessary in order to execute the operation. Example with maintenance window where the device is requested to download only as it is not in the maintenance window yet.") + @WithUser(tenantId = "TENANT_ID", authorities = "ROLE_CONTROLLER", allSpPermissions = true) + public void getControllerBasedeploymentActionWithMaintenanceWindow() throws Exception { + final DistributionSet set = testdataFactory.createDistributionSet("one"); + + final Target target = targetManagement.create(entityFactory.target().create().controllerId(CONTROLLER_ID)); + final Long actionId = assignDistributionSetWithMaintenanceWindow(set.getId(), target.getControllerId(), + getTestSchedule(2), getTestDuration(1), getTestTimeZone()).getActions().get(0); + + mockMvc.perform(get( + DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.DEPLOYMENT_BASE_ACTION + + "/{actionId}?actionHistory=10", + tenantAware.getCurrentTenant(), target.getControllerId(), actionId).accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters(parameterWithName("tenant").description(ApiModelPropertiesGeneric.TENANT), + parameterWithName("controllerId").description(DdiApiModelProperties.CONTROLLER_ID), + parameterWithName("actionId").description(DdiApiModelProperties.ACTION_ID)), + requestParameters( + parameterWithName("actionHistory").description(DdiApiModelProperties.ACTION_HISTORY)), + responseFields(fieldWithPath("id").description(DdiApiModelProperties.ACTION_ID), + fieldWithPath("deployment").description(DdiApiModelProperties.DEPLOYMENT), + fieldWithPath("deployment.download") + .description(DdiApiModelProperties.HANDLING_DOWNLOAD), + fieldWithPath("deployment.update").description(DdiApiModelProperties.HANDLING_UPDATE) + .type("enum").attributes(key("value").value("['attempt', 'forced']")), + fieldWithPath("deployment.maintenanceWindow") + .description(DdiApiModelProperties.MAINTENANCE_WINDOW).type("enum") + .attributes(key("value").value("['available', 'unavailable']")), + fieldWithPath("deployment.chunks").description(DdiApiModelProperties.CHUNK), + fieldWithPath("deployment.chunks[].part").description(DdiApiModelProperties.CHUNK_TYPE), + fieldWithPath("deployment.chunks[].name").description(DdiApiModelProperties.CHUNK_NAME), + fieldWithPath("deployment.chunks[].version") + .description(DdiApiModelProperties.CHUNK_VERSION)))); + + } + + @Test + @Description("Feedback channel. It is up to the device to decided how much intermediate feedback is " + + "provided. However, the action will be kept open until the controller on the device reports a " + + "finished (either successfull or error).") + @WithUser(tenantId = "TENANT_ID", authorities = "ROLE_CONTROLLER", allSpPermissions = true) + public void postBasedeploymentActionFeedback() throws Exception { + final DistributionSet set = testdataFactory.createDistributionSet("one"); + + final Target target = targetManagement.create(entityFactory.target().create().controllerId(CONTROLLER_ID)); + final Long actionId = deploymentManagement + .assignDistributionSet(set.getId(), Arrays.asList(target.getTargetWithActionType())).getActions() + .get(0); + + mockMvc.perform(post(DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + + DdiRestConstants.DEPLOYMENT_BASE_ACTION + "/{actionId}/feedback", tenantAware.getCurrentTenant(), + target.getControllerId(), actionId) + .content( + JsonBuilder.deploymentActionFeedback(actionId.toString(), "closed", "Feddback message")) + .contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("tenant").description(ApiModelPropertiesGeneric.TENANT), + parameterWithName("controllerId").description(DdiApiModelProperties.CONTROLLER_ID), + parameterWithName("actionId").description(DdiApiModelProperties.ACTION_ID)), + + requestFields(optionalRequestFieldWithPath("id").description(DdiApiModelProperties.ACTION_ID), + optionalRequestFieldWithPath("time").description(DdiApiModelProperties.TARGET_TIME), + requestFieldWithPath("status").description(DdiApiModelProperties.TARGET_STATUS), + requestFieldWithPath("status.execution") + .description(DdiApiModelProperties.TARGET_EXEC_STATUS).type("enum") + .attributes(key("value").value( + "['closed', 'proceeding', 'canceled','scheduled', 'rejected', 'resumed']")), + requestFieldWithPath("status.result") + .description(DdiApiModelProperties.TARGET_RESULT_VALUE), + requestFieldWithPath("status.result.finished") + .description(DdiApiModelProperties.TARGET_RESULT_FINISHED).type("enum") + .attributes(key("value").value("['success', 'failure', 'none']")), + optionalRequestFieldWithPath("status.result.progress") + .description(DdiApiModelProperties.TARGET_RESULT_PROGRESS), + optionalRequestFieldWithPath("status.details") + .description(DdiApiModelProperties.TARGET_RESULT_DETAILS)))); + } + + @Test + @Description("Returns all artifacts whichs is assigned to the software module." + + "Can be usesfull for the target to double check that its current state matches with the targeted state.") + @WithUser(tenantId = "TENANT_ID", authorities = "ROLE_CONTROLLER", allSpPermissions = true) + public void getSoftwareModulesArtifacts() throws Exception { + final DistributionSet set = testdataFactory.createDistributionSet(""); + + final SoftwareModule module = (SoftwareModule) set.getModules().toArray()[0]; + + final byte random[] = RandomStringUtils.random(5).getBytes(); + artifactManagement.create(new ByteArrayInputStream(random), module.getId(), "binaryFile", false, 0); + + final Target target = targetManagement.create(entityFactory.target().create().controllerId(CONTROLLER_ID)); + deploymentManagement.assignDistributionSet(set.getId(), Arrays.asList(target.getTargetWithActionType())); + + mockMvc.perform( + get(DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/softwaremodules/{moduleId}/artifacts", + tenantAware.getCurrentTenant(), target.getControllerId(), module.getId()) + .accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters(parameterWithName("tenant").description(ApiModelPropertiesGeneric.TENANT), + parameterWithName("controllerId").description(DdiApiModelProperties.CONTROLLER_ID), + parameterWithName("moduleId").description(DdiApiModelProperties.SOFTWARE_MODUL_ID)), + responseFields(fieldWithPath("[]filename").description(DdiApiModelProperties.ARTIFACTS), + fieldWithPath("[]hashes").description(DdiApiModelProperties.ARTIFACTS), + fieldWithPath("[]hashes.sha1").description(DdiApiModelProperties.ARTIFACT_HASHES_SHA1), + fieldWithPath("[]hashes.md5").description(DdiApiModelProperties.ARTIFACT_HASHES_MD5), + fieldWithPath("[]size").description(DdiApiModelProperties.ARTIFACT_SIZE), + fieldWithPath("[]_links.download") + .description(DdiApiModelProperties.ARTIFACT_HTTPS_DOWNLOAD_LINK_BY_CONTROLLER), + fieldWithPath("[]_links.md5sum") + .description(DdiApiModelProperties.ARTIFACT_HTTPS_HASHES_MD5SUM_LINK), + fieldWithPath("[]_links.download-http") + .description(DdiApiModelProperties.ARTIFACT_HTTP_DOWNLOAD_LINK_BY_CONTROLLER), + fieldWithPath("[]_links.md5sum-http") + .description(DdiApiModelProperties.ARTIFACT_HTTP_HASHES_MD5SUM_LINK)))); + } + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/AbstractApiRestDocumentation.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/AbstractApiRestDocumentation.java new file mode 100644 index 000000000..460353084 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/AbstractApiRestDocumentation.java @@ -0,0 +1,294 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.documentation; + +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.restdocs.snippet.Attributes.key; + +import java.io.ByteArrayInputStream; +import java.util.Arrays; +import java.util.List; + +import org.apache.commons.lang3.RandomStringUtils; +import org.eclipse.hawkbit.ddi.rest.resource.DdiApiConfiguration; +import org.eclipse.hawkbit.mgmt.rest.resource.MgmtApiConfiguration; +import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.Status; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.Target; +import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; +import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest; +import org.eclipse.hawkbit.rest.util.FilterHttpResponse; +import org.junit.Before; +import org.junit.Rule; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.restdocs.JUnitRestDocumentation; +import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.restdocs.payload.FieldDescriptor; +import org.springframework.restdocs.snippet.Snippet; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Lists; + +import ru.yandex.qatools.allure.annotations.Features; + +/** + * Parent class for all Management API rest documentation classes. + * + */ +@Features("Documentation Verfication - API") +@SpringApplicationConfiguration(classes = { DdiApiConfiguration.class, MgmtApiConfiguration.class }) +@TestPropertySource(locations = { "classpath:/updateserver-restdocumentation-test.properties" }) +public abstract class AbstractApiRestDocumentation extends AbstractRestIntegrationTest { + + @Rule + public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets"); + + @Autowired + protected ObjectMapper objectMapper; + + @Autowired + private FilterHttpResponse filterHttpResponse; + + protected MockMvc mockMvc; + + protected String resourceName = "output"; + + protected RestDocumentationResultHandler document; + + protected String arrayPrefix; + + protected String host = "management-api.host"; + + @Before + protected void setUp() { + this.document = document(resourceName + "/{method-name}", preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint())); + this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) + .apply(MockMvcRestDocumentation.documentationConfiguration(this.restDocumentation).uris() + .withScheme("https").withHost(host + ".com").withPort(443)) + .alwaysDo(this.document).addFilter(filterHttpResponse).build(); + arrayPrefix = "[]"; + } + + public static MyFieldFieldDesc requestFieldWithPath(final String path, final boolean mandatory) { + final MyFieldFieldDesc myFieldDesc = new MyFieldFieldDesc(path); + myFieldDesc.attributes(key("mandatory").value(mandatory ? "X" : "")); + // defaults + myFieldDesc.attributes(key("value").value("")); + return myFieldDesc; + } + + public static MyFieldFieldDesc requestFieldWithPath(final String path) { + return requestFieldWithPath(path, true); + } + + protected static MyFieldFieldDesc optionalRequestFieldWithPath(final String path) { + return requestFieldWithPath(path, false); + } + + public static class MyFieldFieldDesc extends FieldDescriptor { + + /** + * @param path + */ + protected MyFieldFieldDesc(final String path) { + super(path); + } + } + + /** + * Wrapper for FieldDescriptor adding attribute with a key named value if + * not set. + * + * @param path + * @return FieldDescriptor with value key + */ + public static FieldDescriptor fieldWithPath(final String path) { + final MyFieldFieldDesc myFieldDesc = new MyFieldFieldDesc(path); + // defaults + myFieldDesc.attributes(key("value").value("")); + return myFieldDesc; + } + + protected Target createTargetByGivenNameWithAttributes(final String name, final boolean inSync, + final boolean timeforced, final DistributionSet distributionSet) { + return createTargetByGivenNameWithAttributes(name, inSync, timeforced, distributionSet, null, null, null); + } + + protected Target createTargetByGivenNameWithAttributes(final String name, final boolean inSync, + final boolean timeforced, final DistributionSet distributionSet, final String maintenanceWindowSchedule, + final String maintenanceWindowDuration, final String maintenanceWindowTimeZone) { + + final Target savedTarget = targetManagement.create(entityFactory.target().create().controllerId(name) + .status(TargetUpdateStatus.UNKNOWN).address("http://192.168.0.1").description("My name is " + name) + .lastTargetQuery(System.currentTimeMillis())); + + final List updatedTargets = maintenanceWindowSchedule == null + ? assignWithoutMaintenanceWindow(distributionSet, savedTarget, timeforced) + : assignWithMaintenanceWindow(distributionSet, savedTarget, timeforced, maintenanceWindowSchedule, + maintenanceWindowDuration, maintenanceWindowTimeZone); + + if (inSync) { + feedbackToByInSync(distributionSet); + } + + return updatedTargets.get(0); + } + + private List assignWithoutMaintenanceWindow(final DistributionSet distributionSet, final Target savedTarget, + final boolean timeforced) { + return timeforced ? assignDistributionSetTimeForced(distributionSet, savedTarget).getAssignedEntity() + : assignDistributionSet(distributionSet, savedTarget).getAssignedEntity(); + } + + private List assignWithMaintenanceWindow(final DistributionSet distributionSet, final Target savedTarget, + final boolean timeforced, final String maintenanceWindowSchedule, final String maintenanceWindowDuration, + final String maintenanceWindowTimeZone) { + return timeforced + ? assignDistributionSetWithMaintenanceWindowTimeForced(distributionSet.getId(), + savedTarget.getControllerId(), maintenanceWindowSchedule, maintenanceWindowDuration, + maintenanceWindowTimeZone).getAssignedEntity() + : assignDistributionSetWithMaintenanceWindow(distributionSet.getId(), savedTarget.getControllerId(), + maintenanceWindowSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone) + .getAssignedEntity(); + } + + protected DistributionSet createDistributionSet() { + DistributionSet distributionSet = testdataFactory.createDistributionSet(""); + distributionSet = distributionSetManagement.update(entityFactory.distributionSet() + .update(distributionSet.getId()).description("The descption of the distribution set.")); + + distributionSet.getModules().forEach(module -> { + final byte[] random = RandomStringUtils.random(5).getBytes(); + artifactManagement.create(new ByteArrayInputStream(random), module.getId(), "file1", false, 0); + softwareModuleManagement.update(entityFactory.softwareModule().update(module.getId()) + .description("Description of the software module")); + }); + + return distributionSet; + } + + /* + * helper method to give feedback mark an target IN_SNCY * + */ + private void feedbackToByInSync(final DistributionSet savedSet) { + final Action action = deploymentManagement.findActionsByDistributionSet(PAGE, savedSet.getId()).getContent() + .get(0); + + controllerManagement + .addUpdateActionStatus(entityFactory.actionStatus().create(action.getId()).status(Status.FINISHED)); + } + + protected Target createTargetByGivenNameWithAttributes(final String name, final DistributionSet distributionSet) { + return createTargetByGivenNameWithAttributes(name, true, false, distributionSet); + } + + protected String getArrayPrefix(final boolean isArray) { + return isArray ? arrayPrefix : ""; + } + + protected Snippet getResponseFieldTarget(final boolean isArray, final FieldDescriptor... descriptors) { + final String fieldArrayPrefix = getArrayPrefix(isArray); + + final List fields = Lists.newArrayList( + fieldWithPath(fieldArrayPrefix + "createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath(fieldArrayPrefix + "address").description(MgmtApiModelProperties.ADDRESS), + fieldWithPath(fieldArrayPrefix + "createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath(fieldArrayPrefix + "name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath(fieldArrayPrefix + "description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath(fieldArrayPrefix + "controllerId").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath(fieldArrayPrefix + "updateStatus").description(MgmtApiModelProperties.UPDATE_STATUS) + .type("enum") + .attributes(key("value").value("['error', 'in_sync', 'pending', 'registered', 'unknown']")), + fieldWithPath(fieldArrayPrefix + "securityToken").description(MgmtApiModelProperties.SECURITY_TOKEN), + fieldWithPath(fieldArrayPrefix + "installedAt").description(MgmtApiModelProperties.INSTALLED_AT), + fieldWithPath(fieldArrayPrefix + "lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number"), + fieldWithPath(fieldArrayPrefix + "lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY).type("String"), + fieldWithPath(fieldArrayPrefix + "ipAddress").description(MgmtApiModelProperties.IP_ADDRESS) + .type("String"), + fieldWithPath(fieldArrayPrefix + "lastControllerRequestAt") + .description(MgmtApiModelProperties.LAST_REQUEST_AT).type("Number"), + fieldWithPath(fieldArrayPrefix + "_links.self").ignored()); + + if (!isArray) { + fields.addAll(Arrays.asList( + fieldWithPath(fieldArrayPrefix + "pollStatus").description(MgmtApiModelProperties.POLL_STATUS), + fieldWithPath(fieldArrayPrefix + "pollStatus.lastRequestAt") + .description(MgmtApiModelProperties.POLL_LAST_REQUEST_AT), + fieldWithPath(fieldArrayPrefix + "pollStatus.nextExpectedRequestAt") + .description(MgmtApiModelProperties.POLL_NEXT_EXPECTED_REQUEST_AT), + fieldWithPath(fieldArrayPrefix + "pollStatus.overdue") + .description(MgmtApiModelProperties.POLL_OVERDUE), + fieldWithPath(fieldArrayPrefix + "_links.assignedDS") + .description(MgmtApiModelProperties.LINKS_ASSIGNED_DS), + fieldWithPath(fieldArrayPrefix + "_links.installedDS") + .description(MgmtApiModelProperties.LINKS_INSTALLED_DS), + fieldWithPath(fieldArrayPrefix + "_links.attributes") + .description(MgmtApiModelProperties.LINKS_ATTRIBUTES), + fieldWithPath(fieldArrayPrefix + "_links.actions") + .description(MgmtApiModelProperties.LINKS_ACTIONS))); + } + fields.addAll(Arrays.asList(descriptors)); + + return responseFields(fields); + } + + protected Snippet getResponseFieldsDistributionSet(final boolean isArray, final FieldDescriptor... descriptors) { + final String arrayPrefix = getArrayPrefix(isArray); + final List fields = Lists.newArrayList( + fieldWithPath(arrayPrefix + "id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath(arrayPrefix + "name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath(arrayPrefix + "description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath(arrayPrefix + "createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath(arrayPrefix + "createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath(arrayPrefix + "lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath(arrayPrefix + "lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath(arrayPrefix + "type").description(MgmtApiModelProperties.DS_TYPE), + fieldWithPath(arrayPrefix + "requiredMigrationStep") + .description(MgmtApiModelProperties.DS_REQUIRED_STEP), + fieldWithPath(arrayPrefix + "complete").description(MgmtApiModelProperties.DS_COMPLETE), + fieldWithPath(arrayPrefix + "deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath(arrayPrefix + "version").description(MgmtApiModelProperties.VERSION), + fieldWithPath(arrayPrefix + "_links.self").ignored(), fieldWithPath(arrayPrefix + "modules").ignored()); + + fields.addAll(Arrays.asList(descriptors)); + + if (!isArray) { + fields.add(fieldWithPath(arrayPrefix + "_links.type").description(MgmtApiModelProperties.DS_TYPE)); + fields.add(fieldWithPath(arrayPrefix + "_links.metadata").description(MgmtApiModelProperties.META_DATA)); + fields.add(fieldWithPath(arrayPrefix + "_links.modules").description(MgmtApiModelProperties.SM_LIST)); + } + + return responseFields(fields); + } + + protected Snippet getFilterRequestParamter() { + return requestParameters( + parameterWithName("limit").attributes(key("type").value("query")) + .description(ApiModelPropertiesGeneric.LIMIT), + parameterWithName("sort").description(ApiModelPropertiesGeneric.SORT), + parameterWithName("offset").description(ApiModelPropertiesGeneric.OFFSET), + parameterWithName("q").description(ApiModelPropertiesGeneric.FIQL)); + } + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/ApiModelPropertiesGeneric.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/ApiModelPropertiesGeneric.java new file mode 100644 index 000000000..50453dd32 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/ApiModelPropertiesGeneric.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.documentation; + +/** + * Constants for API documentation. + */ +public final class ApiModelPropertiesGeneric { + public static final String ENDING = " of the entity"; + + // generic + public static final String TENANT = "The tenant"; + public static final String ITEM_ID = "The technical identifier " + ENDING; + public static final String NAME = "The name" + ENDING; + public static final String DESCRPTION = "The description" + ENDING; + public static final String COLOUR = "The colour" + ENDING; + public static final String DELETED = "Deleted flag, used for soft deleted entities"; + + public static final String CREATED_BY = "Entity was originally created by Bosch IoT Permission user (IM: + UUID), Rollout cloud user (CLD: + UUID), AMQP-Controller, anonymous etc.)"; + public static final String CREATED_AT = "Entity was originally created at (timestamp UTC in milliseconds)"; + public static final String LAST_MODIFIED_BY = "Entity was last modified by Bosch IoT Permission user (IM: + UUID), Rollout cloud user (CLD: + UUID), AMQP-Controller, anonymous etc.)"; + public static final String LAST_MODIFIED_AT = "Entity was last modified at (timestamp UTC in milliseconds)"; + + // Paging elements + public static final String SIZE = "Current page size"; + public static final String TOTAL_ELEMENTS = "Total number of elements"; + public static final String SELF_LINKS_TO_RESOURCE = "Links to the given resource itself"; + + private ApiModelPropertiesGeneric() { + // utility class + } + + // parameters + public static final String OFFSET = "The paging offset (default is 0)."; + public static final String LIMIT = "The maximum number of entries in a page (default is 50)."; + public static final String SORT = "The query parameter sort allows to define the sort order for the result of a query. " + + "A sort criteria consists of the name of a field and the sort direction (ASC for ascending and DESC descending). " + + "The sequence of the sort criteria (multiple can be used) defines the sort order of the entities in the result."; + public static final String FIQL = "Query fields based on the Feed Item Query Language (FIQL). See link:../developerguide/apispecifications/managementapi/queryparameters.html[FIQL search syntax, window=\"_parent\"]."; + + // Error/exception handling + public static final String EXCEPTION_CLASS = "The exception class name."; + public static final String ERROR_CODE = "The exception error code."; + public static final String ERROR_MESSAGE = "The exception human readable message."; + public static final String ERROR_PARAMETERS = "The exception message parameters."; + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/DocumenationResponseFieldsSnippet.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/DocumenationResponseFieldsSnippet.java new file mode 100644 index 000000000..9dd0c45b5 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/DocumenationResponseFieldsSnippet.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.documentation; + +import java.util.List; + +import org.springframework.restdocs.payload.FieldDescriptor; +import org.springframework.restdocs.payload.ResponseFieldsSnippet; + +/** + * {@link ResponseFieldsSnippet} with public constructor + */ +public class DocumenationResponseFieldsSnippet extends ResponseFieldsSnippet { + public DocumenationResponseFieldsSnippet(final List descriptors) { + super(descriptors); + } + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/MgmtApiModelProperties.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/MgmtApiModelProperties.java new file mode 100644 index 000000000..bee86013a --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/MgmtApiModelProperties.java @@ -0,0 +1,209 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.documentation; + +/** + * Model properties for the Management API documentation. + */ +public final class MgmtApiModelProperties { + + // Versioned entity + public static final String VERSION = "Package version."; + public static final String VENDOR = "The software vendor."; + + public static final String ACTION_ID = "ID of the action."; + + public static final String LINKS_ASSIGNED_DS = "Links to assigned distribution sets."; + public static final String LINKS_INSTALLED_DS = "Links to installed distribution sets."; + public static final String LINKS_ATTRIBUTES = "Links to attributes of the target."; + public static final String LINKS_ACTIONS = "Links to actions of the target."; + public static final String LINK_TO_ACTION = "The link to the action."; + public static final String LINK_TO_DS = "The link to the distribution set."; + public static final String LINKS_ACTION_STATUSES = "The link to all statuses of the action."; + public static final String LINK_TO_ARTIFACTS = "The link to all artifact of a software module."; + public static final String LINK_TO_SM_TYPE = "The link to the software module type."; + public static final String LINK_TO_METADATA = "The link to the metadata."; + public static final String LINK_TO_MANDATORY_SMT = "Link to mandatory software modules types in this distribution set type."; + public static final String LINK_TO_OPTIONAL_SMT = "Link to optional software modules types in this distribution set type."; + + // software module types + public static final String SMT_TYPE = "The type of the software module identified by its key."; + public static final String SMT_VENDOR = "The software vendor of the entity."; + public static final String SMT_VERSION = "The version of the software module type."; + public static final String SMT_KEY = "The key of the software module type."; + public static final String SMT_MAX_ASSIGNMENTS = "Software modules of that type can be assigned at this maximum number (e.g. operating system only once)."; + + // software module + public static final String SM_TYPE = "The software module type " + ApiModelPropertiesGeneric.ENDING; + public static final String ARTIFACT_HASHES = "Hashes of the artifact."; + public static final String ARTIFACT_SIZE = "Size of the artifact."; + public static final String ARTIFACT_PROVIDED_FILE = "Binary of file."; + public static final String ARTIFACT_PROVIDED_FILENAME = "Filename of the artifact."; + public static final String ARTIFACT_HASHES_SHA1 = "SHA1 hash of the artifact."; + public static final String ARTIFACT_HASHES_MD5 = "MD5 hash of the artifact."; + + public static final String ARTIFACT_DOWNLOAD_LINK = "Download link of the artifact."; + + public static final String ARTIFACT_LIST = "List of artifacts of given software module."; + + // Distribution Set + public static final String DS_OS = "Operating system or firmware software module - DEPRECATED (use modules)."; + public static final String DS_RUNTIME = "Runtime software module (e.g. JVM) - DEPRECATED (use modules)."; + public static final String DS_APPLICATION = "Application software module (e.g. OSGi container) - DEPRECATED (use modules)."; + public static final String DS_MODULES = "Software modules (e.g. OSGi bundles, runtimes)."; + public static final String DS_REQUIRED_STEP = "True if DS a required migration step. As a result the DS will be installed even when a newer. (note: updatable only if DS is not yet assigned to a target)"; + public static final String DS_ASSIGNED_TARGETS = "Targets that have this distribution set assigned."; + public static final String DS_INSTALLED_TARGETS = "Targets that have this distribution set installed."; + public static final String DS_LIST = "List of distribution sets."; + public static final String DS_NEW_ASSIGNED_TARGETS = "Targets that now have this distribution set assigned."; + public static final String DS_ALREADY_ASSIGNED_TARGETS = "Targets that had this distribution set already assigned (in \"offline\" case this includes targets that have arbitrary updates running)"; + public static final String DS_TOTAL_ASSIGNED_TARGETS = "Overall assigned as part of this request."; + public static final String DS_ID = "Id of the distribution set."; + + // Target + public static final String INSTALLED_AT = "Installation time of current installed DistributionSet."; + + public static final String LAST_REQUEST_AT = "Last time where the target polled the server, same as pollStatus.lastRequestAt."; + // poll status + public static final String POLL_LAST_REQUEST_AT = "Last time when the target polled the server."; + public static final String POLL_NEXT_EXPECTED_REQUEST_AT = "Next expected time when the target polls the server."; + public static final String POLL_STATUS = "Poll status of the target. In many scenarios that target will poll the update server on a regular basis to look for potential updates. If that poll does not happen it might imply that the target is offline."; + public static final String POLL_OVERDUE = "Defines if the target poll time is overdue based on the next expected poll time plus the configured overdue poll time threshold."; + + // rollout + public static final String ROLLOUT_FILTER_QUERY = "target filter query language expression"; + public static final String ROLLOUT_GROUP_FILTER_QUERY = "target filter query language expression that selects a subset of targets which match the target filter of the Rollout"; + public static final String ROLLOUT_GROUP_TARGET_PERCENTAGE = "percentage of remaining and matching targets that should be added to this group"; + public static final String ROLLOUT_DS_ID = "the ID of distributionset of this rollout"; + public static final String ROLLOUT_TOTAL_TARGETS = "the total targets of a rollout"; + public static final String ROLLOUT_TOTAL_TARGETS_PER_STATUS = "the total targets per status"; + public static final String ROLLOUT_STATUS = "the status of this rollout"; + public static final String ROLLOUT_GROUP_STATUS = "the status of this rollout group"; + public static final String ROLLOUT_AMOUNT_GROUPS = "the amount of groups the rollout should split targets into"; + public static final String ROLLOUT_GROUPS = "the list of group definitions"; + public static final String ROLLOUT_SUCCESS_CONDITION = "the success condition which takes in place to evaluate if a rollout group is successful and so the next group can be started"; + public static final String ROLLOUT_SUCCESS_CONDITION_CONDITION = "the type of the condition"; + public static final String ROLLOUT_SUCCESS_CONDITION_EXP = "the expression according to the condition, e.g. the value of threshold in percentage"; + public static final String ROLLOUT_SUCCESS_ACTION = "the success action which takes in place to execute in case the success action is fulfilled"; + public static final String ROLLOUT_SUCCESS_ACTION_ACTION = "the success action to execute"; + public static final String ROLLOUT_SUCCESS_ACTION_EXP = "the expression for the success action"; + public static final String ROLLOUT_ERROR_CONDITION = "the error condition which takes in place to evaluate if a rollout group encounter errors"; + public static final String ROLLOUT_ERROR_CONDITION_CONDITION = "the type of the condition"; + public static final String ROLLOUT_ERROR_CONDITION_EXP = "the expression according to the condition, e.g. the value of threshold in percentage"; + public static final String ROLLOUT_ERROR_ACTION = "the error action which is executed if the error condition is fulfilled"; + public static final String ROLLOUT_ERROR_ACTION_ACTION = "the error action to execute"; + public static final String ROLLOUT_ERROR_ACTION_EXP = "the expression for the error action"; + public static final String ROLLOUT_LINKS_START_SYNC = "Link to start the rollout in sync mode"; + public static final String ROLLOUT_LINKS_START_ASYNC = "Link to start the rollout in async mode"; + public static final String ROLLOUT_LINKS_PAUSE = "Link to pause a running rollout"; + public static final String ROLLOUT_LINKS_RESUME = "Link to resume a paused rollout"; + public static final String ROLLOUT_LINKS_GROUPS = "Link to retrieve the groups a rollout"; + public static final String ROLLOUT_START_ASYNC = "Start the rollout asynchronous"; + + public static final String UPDATE_STATUS = "Current update status of the target."; + public static final String TARGET_ATTRIBUTES = "Target attributes."; + + public static final String TARGET_LIST = "List of provisioning targets."; + + public static final String SM_LIST = "List of software modules."; + + public static final String ROLLOUT_LIST = "list of rollouts"; + + public static final String ACTION_TYPE = "Type of action."; + + public static final String ACTION_FORCE_TYPE = "Force type of the action that provides a hint if the controller should apply the action immediately or whenever possible."; + + public static final String ACTION_FORCE_TIME = "In case of timeforced mode the difference, measured in milliseconds, between the time the action should switch to forced and midnight, January 1, 1970 UTC."; + + public static final String ACTION_FORCED = "Set to forced in order to switch action to forced mode."; + + public static final String ACTION_STATUS_TYPE = "Type of the action status."; + + public static final String ACTION_STATUS_MESSAGES = "Messages related to the status."; + + public static final String ACTION_STATUS_REPORTED_AT = "Time at which the status was reported (server time)."; + + public static final String ACTION_STATUS_LIST = "List of action status."; + + public static final String ACTION_EXECUTION_STATUS = "Status of action."; + + public static final String ACTION_LIST = "List of actions."; + + public static final String IP_ADDRESS = "Last known IP address of the target. Only presented if IP address of the target itself is known (connected directy through DDI API)."; + + public static final String ADDRESS = "The last known address URI of the target. Includes information of the target is connected either directly (DDI) through HTTP or indirectly (DMF) through amqp."; + + public static final String SECURITY_TOKEN = "Pre-Shared key that allows targets to authenticate at Direct Device Integration API if enabled in the tenant settings."; + + public static final String META_DATA = "List of metadata."; + + public static final String META_DATA_KEY = "Metadata property key."; + + public static final String META_DATA_VALUE = "Metadata property value."; + + public static final String SM_META_DATA_TARGET_VISIBLE = "Metadata property is visible to targets as part of software update action."; + + public static final String SM_TYPE_KEY = "Key that can be interpreted by the target."; + + public static final String SM_MAX_ASSIGNMENTS = "Maximum number of assigments to a distribution set/target, e.g. only one firmware but multiple applications."; + + public static final String SM_TYPE_LIST = "List of software modules types."; + + public static final String DS_TYPE_KEY = "Functional key of the distribution set type."; + + public static final String DS_TYPE_LIST = "List of distribution set types."; + + public static final String DS_TYPE = "The type of the distribution set."; + + public static final String DS_COMPLETE = "True of the distribution set software module setup is complete as defined by the distribution set type."; + + public static final String DS_TYPE_MANDATORY_MODULES = "Mandatory module type IDs."; + + public static final String DS_TYPE_OPTIONAL_MODULES = "Optional module type IDs."; + + public static final String MAINTENANCE_WINDOW = "Separation of download and install by defining a maintenance window for the installation."; + public static final String MAINTENANCE_WINDOW_SCHEDULE = "Schedule for the maintenance window start in quartz cron notation, such as '0 15 10 * * ? 2018' for 10:15am every day during the year 2018."; + public static final String MAINTENANCE_WINDOW_DURATION = "Duration of the window, such as '02:00:00' for 2 hours."; + public static final String MAINTENANCE_WINDOW_TIMEZONE = "A time-zone offset from Greenwich/UTC, such as '+02:00'."; + public static final String MAINTENANCE_WINDOW_NEXT_START_AT = "The time (timestamp UTC in milliseconds) of the next maintenance window start"; + + // target filter query + public static final String TARGET_FILTER_QUERY = "target filter query expression"; + public static final String TARGET_FILTER_QUERIES_LIST = "List of target filter queries."; + public static final String TARGET_FILTER_QUERY_AUTO_ASSIGN_DS_ID = "Auto assign distribution set id"; + public static final String TARGET_FILTER_QUERY_LINK_AUTO_ASSIGN_DS = "Link to manage the auto assign distribution set"; + public static final String TARGET_FILTER_QUERY_PARAM_Q = "Name filter"; + + // request parameter + public static final String FORCETIME = "Forcetime in milliseconds."; + public static final String FORCE = "Force as boolean."; + public static final String FORCETIME_TYPE = "The type of the forcetime."; + public static final String TARGET_ASSIGNED = "The number of targets that have been assigned as part of this operation."; + public static final String TARGET_ASSIGNED_ALREADY = "The number of targets which already had been the assignment."; + public static final String TARGET_ASSIGNED_TOTAL = "The total number of targets that are part of this operation."; + + public static final String ASSIGNED_TARGETS = "Assigned targets."; + public static final String UN_ASSIGNED_TARGETS = "Unassigned targets."; + public static final String LINKS_ASSIGNED_TARGETS = "Links to assigned targets."; + + public static final String ASSIGNED_DISTRIBUTION_SETS = "Assigned distribution sets."; + public static final String UN_ASSIGNED_DISTRIBUTION_SETS = "Unassigned distribution sets."; + public static final String LINKS_ASSIGNED_DISTRIBUTION_SETS = "Links to assigned distribution sets."; + public static final Object OFFLINE_UPDATE = "Offline update (set param to true) that is only reported but not managed by the service, " + + "e.g. defaults set in factory, manual updates or migrations from other update systems. A completed action is added to the history of the target(s)." + + " Target is set to IN_SYNC state as both assigend and installed DS are set. " + + "Note: only executed if the target has currently no running update."; + + // configuration + public static final String CONFIG_LIST = "List of all available configuration parameter."; + public static final String CONFIG_VALUE = "Current value of of configuration parameter."; + public static final String CONFIG_GLOBAL = "true - if the current value is the global configuration value, false - if there is a tenant specific value configured."; + public static final String CONFIG_PARAM = "The name of the configuration parameter."; + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/DistributionSetTagResourceDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/DistributionSetTagResourceDocumentationTest.java new file mode 100644 index 000000000..e3ac79651 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/DistributionSetTagResourceDocumentationTest.java @@ -0,0 +1,305 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.mgmt.documentation; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtAssignedDistributionSetRequestBody; +import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtTagRequestBodyPut; +import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.DistributionSetTag; +import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation; +import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric; +import org.eclipse.hawkbit.rest.documentation.DocumenationResponseFieldsSnippet; +import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties; +import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.FieldDescriptor; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.restdocs.snippet.Snippet; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +/** + * Documentation generation for Management API for {@link DistributionSetTag}. + * + */ +@Features("Spring Rest Docs Tests - DistributionSetTag") +@Stories("DistributionSet Tag Resource") +public class DistributionSetTagResourceDocumentationTest extends AbstractApiRestDocumentation { + + private DistributionSet distributionSet; + + @Override + @Before + public void setUp() { + resourceName = "distributionsettag"; + super.setUp(); + distributionSet = createDistributionSet(); + } + + @Test + @Description("Handles the GET request of retrieving all distribution set tags") + public void getDistributionSetTags() throws Exception { + createDistributionSetTag(); + arrayPrefix = "content[]."; + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING)).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(getResponseFieldsTag(true, + fieldWithPath("size").type(JsonFieldType.NUMBER).description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("content").description(MgmtApiModelProperties.TARGET_LIST)))); + } + + @Test + @Description("Handles the GET request of retrieving all distribution set tags based by parameter") + public void getDistributionSetTagsWithParameters() throws Exception { + createDistributionSetTag(); + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + + "?limit=10&sort=name:ASC&offset=0&q=name==DsTag")).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()).andDo(this.document.document(getFilterRequestParamter())); + } + + @Test + @Description("Handles the GET request of retrieving a single distribution set tag") + public void getDistributionSetTag() throws Exception { + final Long tagId = createDistributionSetTagId(); + + mockMvc.perform( + get(MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + "/{distributionsetTagId}", tagId)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(pathParameters( + parameterWithName("distributionsetTagId").description(ApiModelPropertiesGeneric.ITEM_ID)), + getResponseFieldsTag(false))); + } + + @Test + @Description("Handles the POST request of creating new distribution set tag. The request body must always be a list of tags.") + public void createDistributionSetTags() throws Exception { + final MgmtTagRequestBodyPut bodyPut = createDSBody(); + final ObjectMapper mapper = new ObjectMapper(); + final String json = mapper.writeValueAsString(Arrays.asList(bodyPut)); + this.mockMvc + .perform(post(MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING).content(json) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isCreated()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(getRequestFieldsTag(true), getResponseFieldsTag(true))); + } + + @Test + @Description("Handles the PUT request of updating a single distribution set tag.") + public void updateDistributionSetTag() throws Exception { + final Long tagId = createDistributionSetTagId(); + final MgmtTagRequestBodyPut bodyPut = createDSBody(); + final ObjectMapper mapper = new ObjectMapper(); + final String json = mapper.writeValueAsString(bodyPut); + + this.mockMvc + .perform( + put(MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + "/{distributionsetTagId}", tagId) + .content(json).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("distributionsetTagId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + getRequestFieldsTag(false), getResponseFieldsTag(false))); + + } + + private MgmtTagRequestBodyPut createDSBody() { + final MgmtTagRequestBodyPut bodyPut = new MgmtTagRequestBodyPut(); + bodyPut.setColour("red"); + bodyPut.setDescription("ds tag description"); + bodyPut.setName("ds tag"); + return bodyPut; + } + + @Test + @Description("Handles the DELETE request for a single distribution set tag") + public void deleteDistributionSetTag() throws Exception { + final Long tagId = createDistributionSetTagId(); + this.mockMvc + .perform(delete(MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + "/{distributionsetTagId}", + tagId).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(pathParameters( + parameterWithName("distributionsetTagId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the GET request of retrieving all assigned distribution sets by the given tag id.") + public void getAssignedDistributionSets() throws Exception { + final DistributionSetTag tag = createDistributionSetTag(); + distributionSetManagement.assignTag(Arrays.asList(distributionSet.getId()), tag.getId()); + + arrayPrefix = "content[]."; + this.mockMvc + .perform(get(MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + + MgmtRestConstants.DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING, tag.getId()) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("distributionsetTagId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + getResponseFieldsDistributionSet(true, + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("content").description(MgmtApiModelProperties.TARGET_LIST)))); + } + + @Test + @Description("andles the POST request to toggle the assignment of distribution sets by the given tag id.") + public void toggleTagAssignment() throws Exception { + final DistributionSet unassignDS = testdataFactory.createDistributionSet("unassign"); + final Long tagId = createDistributionSetTagId(); + final MgmtAssignedDistributionSetRequestBody body = new MgmtAssignedDistributionSetRequestBody(); + body.setDistributionSetId(distributionSet.getId()); + final ObjectMapper mapper = new ObjectMapper(); + final String json = mapper.writeValueAsString(Arrays.asList(body)); + + this.mockMvc + .perform(post(MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + + MgmtRestConstants.DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING + + "/toggleTagAssignment", tagId).content(json).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("distributionsetTagId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + getRequestFieldsDistributionSetAssignment(true), + getResponseAssignmentResult(distributionSet, unassignDS) + + )); + } + + @Test + @Description("Handles the POST request to assign distribution sets to the given tag id.") + public void assignDistributionSets() throws Exception { + final Long tagId = createDistributionSetTagId(); + final MgmtAssignedDistributionSetRequestBody body = new MgmtAssignedDistributionSetRequestBody(); + body.setDistributionSetId(distributionSet.getId()); + final ObjectMapper mapper = new ObjectMapper(); + final String json = mapper.writeValueAsString(Arrays.asList(body)); + + this.mockMvc + .perform(post(MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + + MgmtRestConstants.DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING, tagId).content(json) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("distributionsetTagId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + getRequestFieldsDistributionSetAssignment(true), getResponseFieldsDistributionSet(true))); + } + + @Test + @Description("Handles the DELETE request to unassign one distribution set from the given tag id.") + public void unassignDistributionSet() throws Exception { + final Long tagId = createDistributionSetTagId(); + + this.mockMvc + .perform(delete(MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + + MgmtRestConstants.DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING + + "/{distributionsetId}", tagId, distributionSet.getId()) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(pathParameters( + parameterWithName("distributionsetTagId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("distributionsetId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + private Snippet getRequestFieldsTag(final boolean isArray) { + final String arrayPrefix = getArrayPrefix(isArray); + + return requestFields(requestFieldWithPath(arrayPrefix + "name").description(ApiModelPropertiesGeneric.NAME), + requestFieldWithPath(arrayPrefix + "description").description(ApiModelPropertiesGeneric.DESCRPTION), + optionalRequestFieldWithPath(arrayPrefix + "colour").description(ApiModelPropertiesGeneric.COLOUR)); + } + + private Snippet getRequestFieldsDistributionSetAssignment(final boolean isArray) { + final String arrayPrefix = getArrayPrefix(isArray); + + return requestFields(requestFieldWithPath(arrayPrefix + "id").description(ApiModelPropertiesGeneric.ITEM_ID)); + } + + private Snippet getResponseFieldsTag(final boolean isArray, final FieldDescriptor... descriptors) + throws JsonProcessingException { + final String arrayPrefix = getArrayPrefix(isArray); + final List allFieldDescriptor = new ArrayList<>(); + allFieldDescriptor.addAll(Arrays.asList(descriptors)); + + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "id").description(ApiModelPropertiesGeneric.ITEM_ID)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "name").description(ApiModelPropertiesGeneric.NAME)); + allFieldDescriptor + .add(fieldWithPath(arrayPrefix + "description").description(ApiModelPropertiesGeneric.DESCRPTION)); + allFieldDescriptor + .add(fieldWithPath(arrayPrefix + "createdBy").description(ApiModelPropertiesGeneric.CREATED_BY)); + allFieldDescriptor + .add(fieldWithPath(arrayPrefix + "createdAt").description(ApiModelPropertiesGeneric.CREATED_AT)); + allFieldDescriptor.add( + fieldWithPath(arrayPrefix + "lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY)); + allFieldDescriptor.add( + fieldWithPath(arrayPrefix + "lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "colour").description(ApiModelPropertiesGeneric.COLOUR)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.self").ignored()); + + if (!isArray) { + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.assignedDistributionSets") + .description(MgmtApiModelProperties.LINKS_ASSIGNED_DISTRIBUTION_SETS)); + } + + return new DocumenationResponseFieldsSnippet(allFieldDescriptor); + } + + private Snippet getResponseFieldsTag(final boolean isArray) throws JsonProcessingException { + return getResponseFieldsTag(isArray, new FieldDescriptor[0]); + } + + private Snippet getResponseAssignmentResult(final DistributionSet assignment, final DistributionSet unassignment) + throws JsonProcessingException { + return responseFields( + fieldWithPath("assignedDistributionSets").description(MgmtApiModelProperties.ASSIGNED_DISTRIBUTION_SETS) + .type("Array[Object]"), + + fieldWithPath("unassignedDistributionSets") + .description(MgmtApiModelProperties.UN_ASSIGNED_DISTRIBUTION_SETS).type("Array[Object]")); + } + + private DistributionSetTag createDistributionSetTag() { + final DistributionSetTag updateTag = distributionSetTagManagement + .create(entityFactory.tag().create().name("DsTag")); + return distributionSetTagManagement.update(entityFactory.tag().update(updateTag.getId()) + .description("My name is " + updateTag.getName()).colour("default")); + } + + private Long createDistributionSetTagId() { + return createDistributionSetTag().getId(); + } + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/DistributionSetTypesDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/DistributionSetTypesDocumentationTest.java new file mode 100644 index 000000000..86eeb3b02 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/DistributionSetTypesDocumentationTest.java @@ -0,0 +1,434 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.mgmt.documentation; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.restdocs.snippet.Attributes.key; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.hawkbit.im.authentication.SpPermission; +import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; +import org.eclipse.hawkbit.repository.model.DistributionSetType; +import org.eclipse.hawkbit.repository.test.util.WithUser; +import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation; +import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric; +import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties; +import org.eclipse.hawkbit.rest.util.JsonBuilder; +import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +/** + * Documentation generation for Management API for {@link DistributionSetType}. + * + */ +@Features("Spring Rest Docs Tests - DistributionSetType") +@Stories("DistributionSetTypes Resource") +public class DistributionSetTypesDocumentationTest extends AbstractApiRestDocumentation { + + @Override + @Before + public void setUp() { + this.resourceName = "distributionsettypes"; + super.setUp(); + } + + @Test + @Description("Handles the GET request of retrieving all distribution set types within SP. Required Permission: READ_REPOSITORY.") + public void getDistributionSetTypes() throws Exception { + + distributionSetTypeManagement.update(entityFactory.distributionSetType() + .update(testdataFactory.createDistributionSet().getType().getId()).description("Desc1234")); + + mockMvc.perform( + get(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING).accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(jsonPath("$.total", equalTo(4))) + .andDo(this.document.document(responseFields( + fieldWithPath("size").type(JsonFieldType.NUMBER).description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("content").description(MgmtApiModelProperties.TARGET_LIST), + fieldWithPath("content[].createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("content[].createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("content[].description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("content[].key").description(MgmtApiModelProperties.DS_TYPE_KEY), + fieldWithPath("content[].id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("content[].lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number"), + fieldWithPath("content[].lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY).type("String"), + fieldWithPath("content[].name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("content[]._links.self").ignored()))); + } + + @Test + @Description("Handles the GET request of retrieving all distribution set types within SP with a defined page size and offset, sortet by name in descending order and filtered down to all targets which name starts with 'a'. Required Permission: READ_REPOSITORY.") + public void getDistributionSetTypesWithParameters() throws Exception { + + distributionSetTypeManagement.update(entityFactory.distributionSetType() + .update(testdataFactory.createDistributionSet().getType().getId()).description("Desc1234")); + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING).accept(MediaType.APPLICATION_JSON) + .param("offset", "1").param("limit", "2").param("sort", "name:DESC").param("q", "name==a*")) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document(getFilterRequestParamter())); + } + + @Test + @WithUser(principal = "uploadTester", allSpPermissions = true) + @Description("Handles the POST request for creating new distribution set types within SP. The request body " + + "must always be a list of types. Required Permission: CREATE_REPOSITORY.") + public void postDistributionSetTypes() throws Exception { + + assertThat(distributionSetTypeManagement.count()).isEqualTo(4); + + final List types = new ArrayList<>(); + types.add(entityFactory.distributionSetType().create().key("test1").name("TestName1").description("Desc1") + .mandatory(osType).optional(runtimeType).build()); + + mockMvc.perform(post(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING) + .content(JsonBuilder.distributionSetTypesCreateValidFieldsOnly(types)) + .contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()).andDo( + this.document.document( + requestFields( + requestFieldWithPath("[]key").description(MgmtApiModelProperties.DS_TYPE_KEY), + requestFieldWithPath("[]name").description(ApiModelPropertiesGeneric.NAME), + optionalRequestFieldWithPath("[]description") + .description(ApiModelPropertiesGeneric.DESCRPTION), + optionalRequestFieldWithPath("[]mandatorymodules") + .description(MgmtApiModelProperties.DS_TYPE_MANDATORY_MODULES), + optionalRequestFieldWithPath("[]optionalmodules") + .description(MgmtApiModelProperties.DS_TYPE_OPTIONAL_MODULES)), + responseFields( + + fieldWithPath("[]createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("[]createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("[].description") + .description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("[]key").description(MgmtApiModelProperties.DS_TYPE_KEY), + fieldWithPath("[]id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("[]lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number"), + fieldWithPath("[]lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY).type("String"), + fieldWithPath("[]name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("[]deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("[]_links.self").ignored()))); + } + + @Test + @Description("Handles the GET request of retrieving a single distribution set type within SP. Required Permission: READ_REPOSITORY") + public void deleteDistributionSetType() throws Exception { + final DistributionSetType testType = distributionSetTypeManagement.update(entityFactory.distributionSetType() + .update(testdataFactory.createDistributionSet().getType().getId()).description("Desc1234")); + + mockMvc.perform(delete(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + "/{distributionSetTypeId}", + testType.getId())).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document(pathParameters( + parameterWithName("distributionSetTypeId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the DELETE request for a single distribution set type within SP. Required Permission: DELETE_REPOSITORY.") + public void getDistributionSetType() throws Exception { + + final DistributionSetType testType = distributionSetTypeManagement.update(entityFactory.distributionSetType() + .update(testdataFactory.createDistributionSet().getType().getId()).description("Desc1234")); + + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + "/{distributionSetTypeId}", + testType.getId()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) + .andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("distributionSetTypeId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("key").description(MgmtApiModelProperties.DS_TYPE_KEY), + fieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT) + .type("Number"), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY) + .type("String"), + fieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("_links.self").ignored(), + fieldWithPath("_links.mandatorymodules") + .description(MgmtApiModelProperties.LINK_TO_MANDATORY_SMT), + fieldWithPath("_links.optionalmodules") + .description(MgmtApiModelProperties.LINK_TO_OPTIONAL_SMT)))); + } + + @Test + @Description("Handles the GET request of retrieving all distribution set types within SP based on parameter. Required Permission: READ_REPOSITORY.") + public void getDistributionSetTypesWithParameter() throws Exception { + + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + + "?limit=10&sort=name:ASC&offset=0&q=name==a")).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(requestParameters( + parameterWithName("limit").attributes(key("type").value("query")) + .description(ApiModelPropertiesGeneric.LIMIT), + parameterWithName("sort").description(ApiModelPropertiesGeneric.SORT), + parameterWithName("offset").description(ApiModelPropertiesGeneric.OFFSET), + parameterWithName("q").description(ApiModelPropertiesGeneric.FIQL)))); + } + + @Test + @Description("Handles the PUT request for a single distribution set type within SP. Required Permission: UPDATE_REPOSITORY.") + public void putDistributionSetType() throws Exception { + final DistributionSetType testType = distributionSetTypeManagement.update(entityFactory.distributionSetType() + .update(testdataFactory.createDistributionSet().getType().getId()).description("Desc1234")); + final String body = new JSONObject().put("description", "an updated desription").toString(); + + this.mockMvc + .perform(put(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + "/{distributionSetTypeId}", + testType.getId()).content(body).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("distributionSetTypeId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields( + requestFieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION)), + responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("key").description(MgmtApiModelProperties.DS_TYPE_KEY), + fieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT) + .type("Number"), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY) + .type("String"), + fieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("_links.self").ignored(), + fieldWithPath("_links.mandatorymodules") + .description(MgmtApiModelProperties.LINK_TO_MANDATORY_SMT), + fieldWithPath("_links.optionalmodules") + .description(MgmtApiModelProperties.LINK_TO_OPTIONAL_SMT)))); + + } + + @Test + @WithUser(principal = "uploadTester", allSpPermissions = true) + @Description("Handles the GET request of retrieving the list of mandatory software module types in that distribution set type. Required Permission: READ_REPOSITORY.") + public void getMandatoryModules() throws Exception { + final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType() + .create().key("test1").name("TestName1").description("Desc1").mandatory(osType).optional(runtimeType)); + + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + + "/{distributionSetTypeId}/mandatorymoduletypes", testType.getId()).accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + + .andDo(this.document.document( + pathParameters(parameterWithName("distributionSetTypeId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("[]createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("[]createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("[]description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("[]key").description(MgmtApiModelProperties.SM_TYPE_KEY), + fieldWithPath("[]maxAssignments") + .description(MgmtApiModelProperties.SMT_MAX_ASSIGNMENTS), + fieldWithPath("[]id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("[]lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number"), + fieldWithPath("[]lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY).type("String"), + fieldWithPath("[]name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("[]deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("[]_links.self").ignored()))); + + } + + @Test + @Description("Handles the POST request for adding a mandatory software module type to a distribution set type." + + "Note that a DS type cannot be changed after it has been used by a DS. Required Permission: " + + SpPermission.UPDATE_REPOSITORY + " and " + SpPermission.READ_REPOSITORY) + public void postMandatoryModule() throws Exception { + final DistributionSetType testType = distributionSetTypeManagement.create( + entityFactory.distributionSetType().create().key("test1").name("TestName1").description("Desc1")); + + mockMvc.perform(post(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + + "/{distributionSetTypeId}/mandatorymoduletypes", testType.getId()) + .content("{\"id\":" + osType.getId() + "}").contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("distributionSetTypeId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields(requestFieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the GET request of retrieving the list of software module types in that distribution set. " + + "Note that a DS type cannot be changed after it has been used by a DS. Required permissions: " + + SpPermission.UPDATE_REPOSITORY + " and " + SpPermission.READ_REPOSITORY) + public void deleteMandatoryModule() throws Exception { + final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType() + .create().key("test1").name("TestName1").description("Desc1").mandatory(osType).optional(runtimeType)); + mockMvc.perform(delete( + MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + + "/{distributionSetTypeId}/mandatorymoduletypes/{softwareModuleTypeId}", + testType.getId(), osType.getId()).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document(pathParameters( + parameterWithName("distributionSetTypeId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("softwareModuleTypeId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + + } + + @Test + @Description("Handles the GET request of retrieving the single mandatory software module type in that distribution set type. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getMandatoryModule() throws Exception { + final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType() + .create().key("test1").name("TestName1").description("Desc1").mandatory(osType).optional(runtimeType)); + + mockMvc.perform(get( + MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + + "/{distributionSetTypeId}/mandatorymoduletypes/{softwareModuleTypeId}", + testType.getId(), osType.getId()).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document(pathParameters( + parameterWithName("distributionSetTypeId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("softwareModuleTypeId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("key").description(MgmtApiModelProperties.SM_TYPE_KEY), + fieldWithPath("maxAssignments").description(MgmtApiModelProperties.SMT_MAX_ASSIGNMENTS), + fieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT) + .type("Number"), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY) + .type("String"), + fieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("_links.self").ignored()))); + } + + @Test + @Description("Handles the GET request of retrieving the list of optional software module types in that distribution set type. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getOptionalModules() throws Exception { + final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType() + .create().key("test1").name("TestName1").description("Desc1").mandatory(osType).optional(runtimeType)); + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + + "/{distributionSetTypeId}/optionalmoduletypes", testType.getId()).accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document( + pathParameters(parameterWithName("distributionSetTypeId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("[]createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("[]createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("[]description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("[]key").description(MgmtApiModelProperties.SM_TYPE_KEY), + fieldWithPath("[]maxAssignments") + .description(MgmtApiModelProperties.SMT_MAX_ASSIGNMENTS), + fieldWithPath("[]id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("[]lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath("[]lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath("[]name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("[]deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("[]_links.self").ignored()))); + } + + @Test + @Description("Handles the POST request for adding an optional software module type to a distribution set type." + + "Note that a DS type cannot be changed after it has been used by a DS. Required Permission: " + + SpPermission.UPDATE_REPOSITORY + " and " + SpPermission.READ_REPOSITORY) + public void postOptionalModule() throws Exception { + final DistributionSetType testType = distributionSetTypeManagement.create( + entityFactory.distributionSetType().create().key("test1").name("TestName1").description("Desc1")); + mockMvc.perform(post(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + + "/{distributionSetTypeId}/optionalmoduletypes", testType.getId()) + .content("{\"id\":" + appType.getId() + "}").contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("distributionSetTypeId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields(requestFieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID)))); + + } + + @Test + @Description("Handles DELETE request for removing an optional module from the distribution set type." + + "Note that a DS type cannot be changed after it has been used by a DS. Required Permission: " + + SpPermission.UPDATE_REPOSITORY + " and " + SpPermission.READ_REPOSITORY) + public void deleteOptionalModule() throws Exception { + final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType() + .create().key("test1").name("TestName1").description("Desc1").mandatory(osType).optional(runtimeType)); + mockMvc.perform(delete( + MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + + "/{distributionSetTypeId}/optionalmoduletypes/{softwareModuleTypeId}", + testType.getId(), appType.getId()).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document(pathParameters( + parameterWithName("distributionSetTypeId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("softwareModuleTypeId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the GET request of retrieving the single optional software module type in that distribution set type. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getOptionalModule() throws Exception { + final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType() + .create().key("test1").name("TestName1").description("Desc1").mandatory(osType).optional(appType)); + + mockMvc.perform(get( + MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + + "/{distributionSetTypeId}/optionalmoduletypes/{softwareModuleTypeId}", + testType.getId(), appType.getId()).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document(pathParameters( + parameterWithName("distributionSetTypeId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("softwareModuleTypeId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("key").description(MgmtApiModelProperties.SM_TYPE_KEY), + fieldWithPath("maxAssignments").description(MgmtApiModelProperties.SMT_MAX_ASSIGNMENTS), + fieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT) + .type("Number"), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY) + .type("String"), + fieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("_links.self").ignored()))); + } + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/DistributionSetsDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/DistributionSetsDocumentationTest.java new file mode 100644 index 000000000..222ab30df --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/DistributionSetsDocumentationTest.java @@ -0,0 +1,659 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.mgmt.documentation; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.restdocs.snippet.Attributes.key; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.hawkbit.im.authentication.SpPermission; +import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; +import org.eclipse.hawkbit.repository.model.Action.Status; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.Target; +import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation; +import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric; +import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties; +import org.eclipse.hawkbit.rest.util.JsonBuilder; +import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; + +import com.google.common.collect.Lists; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +/** + * Documentation generation for Management API for {@link DistributionSet}. + * + */ +@Features("Spring Rest Docs Tests - DistributionSet") +@Stories("DistributionSet Resource") +public class DistributionSetsDocumentationTest extends AbstractApiRestDocumentation { + + @Override + @Before + public void setUp() { + resourceName = "distributionsets"; + super.setUp(); + } + + @Test + @Description("Get Distribution Set. Handles the GET request of retrieving a single distribution set within SP. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getDistributionSet() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}", set.getId()) + .accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document( + pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID)), + getResponseFieldsDistributionSet(false))); + } + + @Test + @Description("Get paged list of Distribution Sets. Required Permission: " + SpPermission.READ_REPOSITORY) + public void getDistributionSets() throws Exception { + testdataFactory.createUpdatedDistributionSet(); + + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document(responseFields( + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("size").type(JsonFieldType.NUMBER).description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("content").description(MgmtApiModelProperties.DS_LIST), + fieldWithPath("content[].id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("content[].name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("content[].description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("content[].createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("content[].createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("content[].lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath("content[].lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath("content[].type").description(MgmtApiModelProperties.DS_TYPE), + fieldWithPath("content[].requiredMigrationStep") + .description(MgmtApiModelProperties.DS_REQUIRED_STEP), + fieldWithPath("content[].complete").description(MgmtApiModelProperties.DS_COMPLETE), + fieldWithPath("content[].deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("content[].version").description(MgmtApiModelProperties.VERSION), + fieldWithPath("content[]._links.self").ignored()))); + } + + @Test + @Description("Get paged list of Distribution Sets with given page size and offset including sorting by name descending and filter down to all sets which name starts with 'testDs'. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getDistributionSetsWithParameters() throws Exception { + + final List sets = testdataFactory.createDistributionSets("testDS", 3); + + sets.forEach(set -> distributionSetManagement + .update(entityFactory.distributionSet().update(set.getId()).description("updated description"))); + + mockMvc.perform( + get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).param("offset", "1").param("limit", "2") + .param("sort", "version:DESC").param("q", "name==testDS*").accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document(getFilterRequestParamter())); + + } + + @Test + @Description("Handles the DELETE request for a single Distribution Set within SP. Required Permission: " + + SpPermission.DELETE_REPOSITORY) + public void deleteDistributionSet() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + + this.mockMvc + .perform(delete(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}", + set.getId())) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Create Distribution Sets. Handles the POST request of creating new distribution sets within SP. The request body must always be a list of sets. Required Permission: " + + SpPermission.CREATE_REPOSITORY) + public void createDistributionSets() throws Exception { + + final SoftwareModule ah = testdataFactory.createSoftwareModuleApp(); + final SoftwareModule os = testdataFactory.createSoftwareModuleOs(); + + final DistributionSet one = testdataFactory.generateDistributionSet("one", "one", standardDsType, + Arrays.asList(os, ah)); + final DistributionSet two = testdataFactory.generateDistributionSet("two", "two", standardDsType, + Arrays.asList(os, ah)); + final DistributionSet three = testdataFactory.generateDistributionSet("three", "three", standardDsType, + Arrays.asList(os, ah), true); + + final List sets = Arrays.asList(one, two, three); + + this.mockMvc + .perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/") + .content(JsonBuilder.distributionSetsCreateValidFieldsOnly(sets)) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isCreated()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + requestFields(requestFieldWithPath("[]name").description(ApiModelPropertiesGeneric.NAME), + requestFieldWithPath("[]description").description(ApiModelPropertiesGeneric.DESCRPTION), + requestFieldWithPath("[]version").description(MgmtApiModelProperties.VERSION), + optionalRequestFieldWithPath("[]requiredMigrationStep") + .description(MgmtApiModelProperties.DS_REQUIRED_STEP), + requestFieldWithPath("[]type").description(MgmtApiModelProperties.DS_TYPE), + optionalRequestFieldWithPath("[]modules").ignored()), + getResponseFieldsDistributionSet(true))); + } + + @Test + @Description("Handles the UPDATE request for a single Distribution Set within SP. Required Permission: " + + SpPermission.UPDATE_REPOSITORY) + public void updateDistributionSet() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + + final DistributionSet update = entityFactory.distributionSet().create().name("another Name") + .version("another Version").description("a new description").requiredMigrationStep(true).build(); + + mockMvc.perform(put(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}", set.getId()) + .content(JsonBuilder.distributionSetUpdateValidFieldsOnly(update)) + .contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document( + pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields(optionalRequestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + optionalRequestFieldWithPath("version").description(MgmtApiModelProperties.VERSION), + optionalRequestFieldWithPath("description") + .description(ApiModelPropertiesGeneric.DESCRPTION), + optionalRequestFieldWithPath("requiredMigrationStep") + .description(MgmtApiModelProperties.DS_REQUIRED_STEP)), + getResponseFieldsDistributionSet(false))); + } + + @Test + @Description("Handles the GET request for retrieving assigned targets of a single distribution set. Required Permission: " + + SpPermission.READ_REPOSITORY + " and " + SpPermission.READ_TARGET) + public void getAssignedTargets() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + + final Target target = testdataFactory.createTarget(); + // assign knownTargetId to distribution set + assignDistributionSet(set.getId(), target.getControllerId()); + + mockMvc.perform( + get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/assignedTargets", + set.getId()).accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document( + pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("content").description(MgmtApiModelProperties.TARGET_LIST) + .type("Array[Object]")))); + + } + + @Test + @Description("Handles the GET request for retrieving assigned target filter queries of a single distribution set. Required Permission: " + + SpPermission.READ_REPOSITORY + " and " + SpPermission.READ_TARGET) + public void getAutoAssignTargetFilterQueries() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + targetFilterQueryManagement + .create(entityFactory.targetFilterQuery().create().name("filter1").query("name==a").set(set)); + targetFilterQueryManagement + .create(entityFactory.targetFilterQuery().create().name("filter2").query("name==b").set(set)); + + mockMvc.perform(get( + MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/autoAssignTargetFilters", + set.getId()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) + .andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document( + pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("content").description(MgmtApiModelProperties.TARGET_FILTER_QUERIES_LIST) + .type("Array[Object]")))); + + } + + @Test + @Description("Handles the GET request for retrieving assigned target filter queries of a single distribution set with a defined page size and offset, sorted by name in descending order and filtered down to all targets with a name that ends with '1'. Required Permission: " + + SpPermission.READ_REPOSITORY + " and " + SpPermission.READ_TARGET) + public void getAutoAssignTargetFilterQueriesWithParameters() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + targetFilterQueryManagement + .create(entityFactory.targetFilterQuery().create().name("filter1").query("name==a").set(set)); + + mockMvc.perform(get( + MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + set.getId() + "/autoAssignTargetFilters") + .param("offset", "1").param("limit", "2").param("sort", "name:DESC").param("q", "name==*1") + .accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document(requestParameters( + parameterWithName("limit").attributes(key("type").value("query")) + .description(ApiModelPropertiesGeneric.LIMIT), + parameterWithName("sort").description(ApiModelPropertiesGeneric.SORT), + parameterWithName("offset").description(ApiModelPropertiesGeneric.OFFSET), + parameterWithName("q").description(ApiModelPropertiesGeneric.FIQL)))); + + } + + @Test + @Description("Handles the GET request for retrieving assigned targets of a single distribution set with a defined page size and offset, sorted by name in descending order and filtered down to all targets which controllerID starts with 'target'. Required Permission: " + + SpPermission.READ_REPOSITORY + " and " + SpPermission.READ_TARGET) + public void getAssignedTargetsWithParameters() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + + assignDistributionSet(set, testdataFactory.createTargets(5, "targetMisc", "Test targets for query")) + .getAssignedEntity(); + + mockMvc.perform( + get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + set.getId() + "/assignedTargets") + .param("offset", "1").param("limit", "2").param("sort", "name:DESC") + .param("q", "controllerId==target*").accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document(requestParameters( + parameterWithName("limit").attributes(key("type").value("query")) + .description(ApiModelPropertiesGeneric.LIMIT), + parameterWithName("sort").description(ApiModelPropertiesGeneric.SORT), + parameterWithName("offset").description(ApiModelPropertiesGeneric.OFFSET), + parameterWithName("q").description(ApiModelPropertiesGeneric.FIQL)))); + + } + + @Test + @Description("Handles the GET request for retrieving installed targets of a single distribution set with a defined page size and offset, sortet by name in descending order and filtered down to all targets which controllerID starts with 'target'. Required Permission: " + + SpPermission.READ_REPOSITORY + " and " + SpPermission.READ_TARGET) + public void getInstalledTargetsWithParameters() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + + final List targets = assignDistributionSet(set, + testdataFactory.createTargets(5, "targetMisc", "Test targets for query")).getAssignedEntity(); + testdataFactory.sendUpdateActionStatusToTargets(targets, Status.FINISHED, "some message"); + + mockMvc.perform( + get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + set.getId() + "/installedTargets") + .param("offset", "1").param("limit", "2").param("sort", "name:DESC") + .param("q", "controllerId==target*").accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document(requestParameters( + parameterWithName("limit").attributes(key("type").value("query")) + .description(ApiModelPropertiesGeneric.LIMIT), + parameterWithName("sort").description(ApiModelPropertiesGeneric.SORT), + parameterWithName("offset").description(ApiModelPropertiesGeneric.OFFSET), + parameterWithName("q").description(ApiModelPropertiesGeneric.FIQL)))); + } + + @Test + @Description("Handles the GET request for retrieving installed targets of a single distribution set. Required Permission: " + + SpPermission.READ_REPOSITORY + " and " + SpPermission.READ_TARGET) + public void getInstalledTargets() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + + final Target target = testdataFactory.createTarget(); + // assign knownTargetId to distribution set + assignDistributionSet(set.getId(), target.getControllerId()); + // make it in install state + testdataFactory.sendUpdateActionStatusToTargets(Arrays.asList(target), Status.FINISHED, "some message"); + + mockMvc.perform( + get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/installedTargets", + set.getId()).accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document( + pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("content").description(MgmtApiModelProperties.TARGET_LIST) + .type("Array[Object]")))); + } + + @Test + @Description("Handles the POST request for assigning multiple targets to a distribution set.The request body must always be a list of target IDs." + + " Required Permission: " + SpPermission.READ_REPOSITORY + " and " + SpPermission.UPDATE_TARGET) + public void createAssignedTarget() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + + // prepare targets + final long forceTime = System.currentTimeMillis(); + final String[] knownTargetIds = new String[] { "target1", "target2", "target3", "target4", "target5" }; + final JSONArray list = new JSONArray(); + for (final String targetId : knownTargetIds) { + targetManagement.create(entityFactory.target().create().controllerId(targetId)); + list.put(new JSONObject().put("id", targetId).put("type", "timeforced").put("forcetime", forceTime).put( + "maintenanceWindow", + getMaintenanceWindow(getTestSchedule(10), getTestDuration(10), getTestTimeZone()))); + } + + // assign already one target to DS + assignDistributionSet(set.getId(), knownTargetIds[0]); + + this.mockMvc + .perform(post( + MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/assignedTargets", + set.getId()).content(list.toString()).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID)), + requestParameters(parameterWithName("offline") + .description(MgmtApiModelProperties.OFFLINE_UPDATE).optional()), + requestFields(requestFieldWithPath("[]forcetime").description(MgmtApiModelProperties.FORCETIME), + requestFieldWithPath("[]id").description(ApiModelPropertiesGeneric.ITEM_ID), + requestFieldWithPath("[]maintenanceWindow") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW).optional(), + requestFieldWithPath("[]maintenanceWindow.schedule") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_SCHEDULE).optional(), + requestFieldWithPath("[]maintenanceWindow.duration") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_DURATION).optional(), + requestFieldWithPath("[]maintenanceWindow.timezone") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_TIMEZONE).optional(), + requestFieldWithPath("[]type").description(MgmtApiModelProperties.FORCETIME_TYPE) + .attributes(key("value").value("['soft', 'forced','timeforced']"))), + responseFields( + fieldWithPath("assigned").description(MgmtApiModelProperties.DS_NEW_ASSIGNED_TARGETS), + fieldWithPath("alreadyAssigned").type(JsonFieldType.NUMBER) + .description(MgmtApiModelProperties.DS_ALREADY_ASSIGNED_TARGETS), + fieldWithPath("total").type(JsonFieldType.NUMBER) + .description(MgmtApiModelProperties.DS_TOTAL_ASSIGNED_TARGETS)))); + } + + @Test + @Description("Handles the POST request for assigning multiple software modules to a distribution set. The request body must always be a list of software module IDs." + + " Required Permission: " + SpPermission.READ_REPOSITORY + " and " + SpPermission.UPDATE_REPOSITORY) + public void assignSoftwareModules() throws Exception { + // create DisSet + final DistributionSet disSet = testdataFactory.createDistributionSetWithNoSoftwareModules("Jupiter", "398,88"); + + // create Software Modules + final List smIDs = Arrays.asList(testdataFactory.createSoftwareModuleOs().getId(), + testdataFactory.createSoftwareModuleApp().getId()); + final JSONArray list = new JSONArray(); + for (final Long smID : smIDs) { + list.put(new JSONObject().put("id", Long.valueOf(smID))); + } + + // post assignment + mockMvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/assignedSM", + disSet.getId()).contentType(MediaType.APPLICATION_JSON_UTF8).content(list.toString())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields(requestFieldWithPath("[]id").description(ApiModelPropertiesGeneric.ITEM_ID)))); + + } + + @Test + @Description("Delete a software module assignment." + " Required Permission: " + SpPermission.UPDATE_REPOSITORY) + public void deleteAssignSoftwareModules() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + + mockMvc.perform(delete( + MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + + "/{distributionSetId}/assignedSM/{softwareModuleId}", + set.getId(), set.findFirstModuleByType(osType).get().getId()) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document(pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + ; + } + + @Test + @Description("Handles the GET request of retrieving assigned software modules of a single distribution set within SP. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getAssignedSoftwareModules() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + + // post assignment + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/assignedSM", + set.getId()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) + .andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document( + pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("content").description(MgmtApiModelProperties.SM_LIST), + fieldWithPath("content[].id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("content[].name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("content[].description") + .description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("content[].vendor").description(MgmtApiModelProperties.VENDOR), + fieldWithPath("content[].createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("content[].createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("content[].lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath("content[].lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath("content[].type").description(MgmtApiModelProperties.SM_TYPE), + fieldWithPath("content[].version").description(MgmtApiModelProperties.VERSION), + fieldWithPath("content[]._links.self").ignored()))); + } + + @Test + @Description("Handles the GET request of retrieving assigned software modules of a single distribution set within SP with given page size and offset including sorting by version descending and filter down to all sets which name starts with 'one'. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getAssignedSoftwareModulesWithParameters() throws Exception { + final DistributionSet set = testdataFactory.createUpdatedDistributionSet(); + + // post assignment + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + set.getId() + "/assignedSM") + .param("offset", "1").param("limit", "2").param("sort", "version:DESC").param("q", "name==one*") + .accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(this.document.document(requestParameters( + parameterWithName("limit").attributes(key("type").value("query")) + .description(ApiModelPropertiesGeneric.LIMIT), + parameterWithName("sort").description(ApiModelPropertiesGeneric.SORT), + parameterWithName("offset").description(ApiModelPropertiesGeneric.OFFSET), + parameterWithName("q").description(ApiModelPropertiesGeneric.FIQL)))); + } + + @Test + @Description("Get a paged list of meta data for a distribution set with standard page size." + + " Required Permission: " + SpPermission.READ_REPOSITORY) + public void getMetadata() throws Exception { + final int totalMetadata = 4; + final String knownKeyPrefix = "knownKey"; + final String knownValuePrefix = "knownValue"; + final DistributionSet testDS = testdataFactory.createDistributionSet("one"); + for (int index = 0; index < totalMetadata; index++) { + distributionSetManagement.createMetaData(testDS.getId(), Lists + .newArrayList(entityFactory.generateMetadata(knownKeyPrefix + index, knownValuePrefix + index))); + } + + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata", + testDS.getId())).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("content").description(MgmtApiModelProperties.META_DATA), + fieldWithPath("content[].key").description(MgmtApiModelProperties.META_DATA_KEY), + fieldWithPath("content[].value").description(MgmtApiModelProperties.META_DATA_VALUE)))); + } + + @Test + @Description("Get a paged list of meta data for a distribution set with defined page size and sorting by name descending and key starting with 'known'." + + " Required Permission: " + SpPermission.READ_REPOSITORY) + public void getMetadataWithParameters() throws Exception { + final int totalMetadata = 4; + + final String knownKeyPrefix = "knownKey"; + final String knownValuePrefix = "knownValue"; + final DistributionSet testDS = testdataFactory.createDistributionSet("one"); + for (int index = 0; index < totalMetadata; index++) { + distributionSetManagement.createMetaData(testDS.getId(), Lists + .newArrayList(entityFactory.generateMetadata(knownKeyPrefix + index, knownValuePrefix + index))); + } + + mockMvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{dsId}/metadata", testDS.getId()) + .param("offset", "1").param("limit", "2").param("sort", "key:DESC").param("q", "key==known*")) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + requestParameters( + parameterWithName("limit").attributes(key("type").value("query")) + .description(ApiModelPropertiesGeneric.LIMIT), + parameterWithName("sort").description(ApiModelPropertiesGeneric.SORT), + parameterWithName("offset").description(ApiModelPropertiesGeneric.OFFSET), + parameterWithName("q").description(ApiModelPropertiesGeneric.FIQL)), + responseFields(fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("content").description(MgmtApiModelProperties.META_DATA), + fieldWithPath("content[].key").description(MgmtApiModelProperties.META_DATA_KEY), + fieldWithPath("content[].value").description(MgmtApiModelProperties.META_DATA_VALUE)))); + } + + @Test + @Description("Get a single meta data value for a meta data key." + " Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getMetadataValue() throws Exception { + + // prepare and create metadata + final String knownKey = "knownKey"; + final String knownValue = "knownValue"; + final DistributionSet testDS = testdataFactory.createDistributionSet("one"); + distributionSetManagement.createMetaData(testDS.getId(), + Arrays.asList(entityFactory.generateMetadata(knownKey, knownValue))); + + mockMvc.perform(get( + MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata/{metadatakey}", + testDS.getId(), knownKey)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("metadatakey").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("key").description(MgmtApiModelProperties.META_DATA_KEY), + fieldWithPath("value").description(MgmtApiModelProperties.META_DATA_VALUE)))); + } + + @Test + @Description("Update a single meta data value for speficic key." + " Required Permission: " + + SpPermission.UPDATE_REPOSITORY) + public void updateMetadata() throws Exception { + // prepare and create metadata for update + final String knownKey = "knownKey"; + final String knownValue = "knownValue"; + final String updateValue = "valueForUpdate"; + + final DistributionSet testDS = testdataFactory.createDistributionSet("one"); + distributionSetManagement.createMetaData(testDS.getId(), + Arrays.asList(entityFactory.generateMetadata(knownKey, knownValue))); + + final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue); + + mockMvc.perform(put( + MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata/{metadatakey}", + testDS.getId(), knownKey).contentType(MediaType.APPLICATION_JSON_UTF8).content(jsonObject.toString())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("metadatakey").description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields(requestFieldWithPath("key").description(MgmtApiModelProperties.META_DATA_KEY), + requestFieldWithPath("value").description(MgmtApiModelProperties.META_DATA_VALUE)), + responseFields(fieldWithPath("key").description(MgmtApiModelProperties.META_DATA_KEY), + fieldWithPath("value").description(MgmtApiModelProperties.META_DATA_VALUE)))); + + } + + @Test + @Description("Delete a single meta data." + " Required Permission: " + SpPermission.UPDATE_REPOSITORY) + public void deleteMetadata() throws Exception { + // prepare and create metadata for deletion + final String knownKey = "knownKey"; + final String knownValue = "knownValue"; + + final DistributionSet testDS = testdataFactory.createDistributionSet("one"); + distributionSetManagement.createMetaData(testDS.getId(), + Arrays.asList(entityFactory.generateMetadata(knownKey, knownValue))); + + mockMvc.perform( + delete(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata/{key}", + testDS.getId(), knownKey)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document(pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("key").description(ApiModelPropertiesGeneric.ITEM_ID)))); + + } + + @Test + @Description("Create a list of meta data entries" + " Required Permission: " + SpPermission.READ_REPOSITORY + + " and " + SpPermission.UPDATE_TARGET) + public void createMetadata() throws Exception { + + final DistributionSet testDS = testdataFactory.createDistributionSet("one"); + + final String knownKey1 = "knownKey1"; + final String knownKey2 = "knownKey2"; + + final String knownValue1 = "knownValue1"; + final String knownValue2 = "knownValue2"; + + final JSONArray jsonArray = new JSONArray(); + jsonArray.put(new JSONObject().put("key", knownKey1).put("value", knownValue1)); + jsonArray.put(new JSONObject().put("key", knownKey2).put("value", knownValue2)); + + mockMvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata", + testDS.getId()).contentType(MediaType.APPLICATION_JSON_UTF8).content(jsonArray.toString())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters( + parameterWithName("distributionSetId").description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields(requestFieldWithPath("[]key").description(MgmtApiModelProperties.META_DATA_KEY), + optionalRequestFieldWithPath("[]value") + .description(MgmtApiModelProperties.META_DATA_VALUE)))); + } +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/RolloutResourceDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/RolloutResourceDocumentationTest.java new file mode 100644 index 000000000..91b2abadd --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/RolloutResourceDocumentationTest.java @@ -0,0 +1,597 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.mgmt.documentation; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.snippet.Attributes.key; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.hawkbit.im.authentication.SpPermission; +import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; +import org.eclipse.hawkbit.repository.model.Rollout; +import org.eclipse.hawkbit.repository.model.RolloutGroup; +import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorAction; +import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorCondition; +import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessAction; +import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition; +import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; +import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; +import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation; +import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric; +import org.eclipse.hawkbit.rest.documentation.DocumenationResponseFieldsSnippet; +import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties; +import org.eclipse.hawkbit.rest.util.JsonBuilder; +import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; +import org.junit.Before; +import org.junit.Test; +import org.springframework.data.domain.PageRequest; +import org.springframework.hateoas.MediaTypes; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.FieldDescriptor; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.restdocs.snippet.Snippet; + +import com.fasterxml.jackson.core.JsonProcessingException; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +/** + * Documentation generation for Rollout API for {@link Rollout}. + * + */ +@Features("Spring Rest Docs Tests - Rollout") +@Stories("Rollout Resource") +public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentation { + + @Override + @Before + public void setUp() { + this.resourceName = "rollouts"; + super.setUp(); + arrayPrefix = "content[]."; + } + + @Test + @Description("Handles the GET request of retrieving all rollouts. Required Permission: " + + SpPermission.READ_ROLLOUT) + public void getRollouts() throws Exception { + + createRolloutEntity(); + + mockMvc.perform(get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING).accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document(getRolloutResponseFields(true, false, + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("size").type(JsonFieldType.NUMBER).description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("content").description(MgmtApiModelProperties.ROLLOUT_LIST)))); + } + + @Test + @Description("Handles the GET request of retrieving all rollouts. Required Permission: " + + SpPermission.READ_ROLLOUT) + public void getRolloutsWithParameters() throws Exception { + createRolloutEntity(); + + mockMvc.perform(get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING).param("offset", "0").param("limit", "2") + .param("sort", "id:DESC").param("q", "name==exampleRollout*").accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document(getFilterRequestParamter())); + } + + private Snippet getRolloutResponseFields(final boolean isArray, final boolean withDetails, + final FieldDescriptor... descriptors) throws JsonProcessingException { + final String arrayPrefix = getArrayPrefix(isArray); + final List allFieldDescriptor = new ArrayList<>(); + allFieldDescriptor.addAll(Arrays.asList(descriptors)); + + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "id").description(ApiModelPropertiesGeneric.ITEM_ID)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "name").description(ApiModelPropertiesGeneric.NAME)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "deleted").description(ApiModelPropertiesGeneric.DELETED)); + allFieldDescriptor + .add(fieldWithPath(arrayPrefix + "description").description(ApiModelPropertiesGeneric.DESCRPTION)); + allFieldDescriptor + .add(fieldWithPath(arrayPrefix + "createdBy").description(ApiModelPropertiesGeneric.CREATED_BY)); + allFieldDescriptor + .add(fieldWithPath(arrayPrefix + "createdAt").description(ApiModelPropertiesGeneric.CREATED_AT)); + allFieldDescriptor.add( + fieldWithPath(arrayPrefix + "lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY)); + allFieldDescriptor.add( + fieldWithPath(arrayPrefix + "lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "targetFilterQuery") + .description(MgmtApiModelProperties.ROLLOUT_FILTER_QUERY)); + allFieldDescriptor.add( + fieldWithPath(arrayPrefix + "distributionSetId").description(MgmtApiModelProperties.ROLLOUT_DS_ID)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "status").description(MgmtApiModelProperties.ROLLOUT_STATUS) + .attributes(key("value").value("['creating','ready','paused','running','finished']"))); + allFieldDescriptor.add( + fieldWithPath(arrayPrefix + "totalTargets").description(MgmtApiModelProperties.ROLLOUT_TOTAL_TARGETS)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.self").ignored()); + + if (withDetails) { + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "totalTargetsPerStatus") + .description(MgmtApiModelProperties.ROLLOUT_TOTAL_TARGETS_PER_STATUS)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.start") + .description(MgmtApiModelProperties.ROLLOUT_LINKS_START_SYNC)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.pause") + .description(MgmtApiModelProperties.ROLLOUT_LINKS_PAUSE)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.resume") + .description(MgmtApiModelProperties.ROLLOUT_LINKS_RESUME)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.groups") + .description(MgmtApiModelProperties.ROLLOUT_LINKS_GROUPS)); + } + + return new DocumenationResponseFieldsSnippet(allFieldDescriptor); + } + + @Test + @Description("Handles the GET request of retrieving a single rollout. Required Permission: " + + SpPermission.READ_ROLLOUT) + public void getRollout() throws Exception { + + final Rollout rollout = createRolloutEntity(); + + mockMvc.perform(get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}", rollout.getId()) + .accept(MediaTypes.HAL_JSON_VALUE)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document(getRolloutResponseFields(false, true), + pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the POST request of creating a rollout. Required Permission: " + SpPermission.CREATE_ROLLOUT) + public void createRollout() throws Exception { + + testdataFactory.createTargets(20, "targets-"); + + final String name = "exampleRollout"; + final String description = "Rollout for all named targets"; + final int groupSize = 10; + final Long dsId = testdataFactory.createDistributionSet().getId(); + final String targetFilter = "id==targets-*"; + final RolloutGroupConditions rolloutGroupConditions = new RolloutGroupConditionBuilder() + .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "50") + .successAction(RolloutGroupSuccessAction.NEXTGROUP, "") + .errorCondition(RolloutGroupErrorCondition.THRESHOLD, "80") + .errorAction(RolloutGroupErrorAction.PAUSE, "").build(); + mockMvc.perform(post(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING) + .content(JsonBuilder.rollout(name, description, groupSize, dsId, targetFilter, rolloutGroupConditions)) + .contentType(APPLICATION_JSON_HAL_UTF).accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document(requestFields( + requestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + requestFieldWithPath("distributionSetId").description(MgmtApiModelProperties.ROLLOUT_DS_ID), + requestFieldWithPath("targetFilterQuery") + .description(MgmtApiModelProperties.ROLLOUT_FILTER_QUERY), + requestFieldWithPath("amountGroups").description(MgmtApiModelProperties.ROLLOUT_AMOUNT_GROUPS), + optionalRequestFieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION), + optionalRequestFieldWithPath("successCondition") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION), + optionalRequestFieldWithPath("successCondition.condition") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_CONDITION) + .attributes(key("value").value("['threshold']")), + optionalRequestFieldWithPath("successCondition.expression") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_EXP), + optionalRequestFieldWithPath("successAction") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION), + optionalRequestFieldWithPath("successAction.action") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_ACTION) + .attributes(key("value").value("['nextgroup']")), + optionalRequestFieldWithPath("successAction.expression") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_EXP), + optionalRequestFieldWithPath("errorCondition") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION), + optionalRequestFieldWithPath("errorCondition.condition") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_CONDITION) + .attributes(key("value").value("['threshold']")), + optionalRequestFieldWithPath("errorCondition.expression") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_EXP), + optionalRequestFieldWithPath("errorAction") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION), + optionalRequestFieldWithPath("errorAction.action") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_ACTION) + .attributes(key("value").value("['pause']")), + optionalRequestFieldWithPath("errorAction.expression") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP)), + + getRolloutResponseFields(false, true))); + + } + + @Test + @Description("Handles the POST request of creating a rollout with a groups definition. Required Permission: " + + SpPermission.CREATE_ROLLOUT) + public void createRolloutWithGroupsDefinition() throws Exception { + + final int amountTargets = 10; + testdataFactory.createTargets(amountTargets, "targets-", "rollout"); + + final List rolloutGroups = new ArrayList<>(2); + final float percentTargetsInGroup1 = 20; + final float percentTargetsInGroup2 = 100; + + final RolloutGroup group1 = entityFactory.rolloutGroup().create().name("Group1").description("Group1desc") + .targetFilterQuery("name==targets-1*").targetPercentage(percentTargetsInGroup1) + .conditions(new RolloutGroupConditionBuilder() + .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "90") + .successAction(RolloutGroupSuccessAction.NEXTGROUP, "") + .errorCondition(RolloutGroupErrorCondition.THRESHOLD, "30") + .errorAction(RolloutGroupErrorAction.PAUSE, "").build()) + .build(); + rolloutGroups.add(group1); + + final RolloutGroup group2 = entityFactory.rolloutGroup().create().name("Group2").description("Group2desc") + .targetPercentage(percentTargetsInGroup2).build(); + rolloutGroups.add(group2); + + final String name = "exampleRolloutWithDefinedGroups"; + final String description = "Rollout for all named targets"; + final Long dsId = testdataFactory.createDistributionSet().getId(); + final String targetFilter = "id==targets-*"; + final RolloutGroupConditions rolloutGroupConditions = new RolloutGroupConditionBuilder() + .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "50") + .successAction(RolloutGroupSuccessAction.NEXTGROUP, "") + .errorCondition(RolloutGroupErrorCondition.THRESHOLD, "80") + .errorAction(RolloutGroupErrorAction.PAUSE, "").build(); + mockMvc.perform( + post(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING) + .content(JsonBuilder.rollout(name, description, null, dsId, targetFilter, + rolloutGroupConditions, rolloutGroups)) + .contentType(MediaType.APPLICATION_JSON).accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document(requestFields( + requestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + requestFieldWithPath("distributionSetId").description(MgmtApiModelProperties.ROLLOUT_DS_ID), + requestFieldWithPath("targetFilterQuery") + .description(MgmtApiModelProperties.ROLLOUT_FILTER_QUERY), + optionalRequestFieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION), + optionalRequestFieldWithPath("successCondition") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION), + optionalRequestFieldWithPath("successCondition.condition") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_CONDITION) + .attributes(key("value").value("['threshold']")), + optionalRequestFieldWithPath("successCondition.expression") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_EXP), + optionalRequestFieldWithPath("successAction") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION), + optionalRequestFieldWithPath("successAction.action") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_ACTION) + .attributes(key("value").value("['nextgroup']")), + optionalRequestFieldWithPath("successAction.expression") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_EXP), + optionalRequestFieldWithPath("errorCondition") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION), + optionalRequestFieldWithPath("errorCondition.condition") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_CONDITION) + .attributes(key("value").value("['threshold']")), + optionalRequestFieldWithPath("errorCondition.expression") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_EXP), + optionalRequestFieldWithPath("errorAction") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION), + optionalRequestFieldWithPath("errorAction.action") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_ACTION) + .attributes(key("value").value("['pause']")), + optionalRequestFieldWithPath("errorAction.expression") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP), + + requestFieldWithPath("groups").description(MgmtApiModelProperties.ROLLOUT_GROUPS), + requestFieldWithPath("groups[].name").description(ApiModelPropertiesGeneric.NAME), + requestFieldWithPath("groups[].description").description(ApiModelPropertiesGeneric.DESCRPTION), + optionalRequestFieldWithPath("groups[].targetFilterQuery") + .description(MgmtApiModelProperties.ROLLOUT_GROUP_FILTER_QUERY), + optionalRequestFieldWithPath("groups[].targetPercentage") + .description(MgmtApiModelProperties.ROLLOUT_GROUP_TARGET_PERCENTAGE) + .attributes(key("value").value("0..100")), + optionalRequestFieldWithPath("groups[].successCondition") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION), + optionalRequestFieldWithPath("groups[].successCondition.condition") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_CONDITION) + .attributes(key("value").value("['threshold']")), + optionalRequestFieldWithPath("groups[].successCondition.expression") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_EXP), + optionalRequestFieldWithPath("groups[].successAction") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION), + optionalRequestFieldWithPath("groups[].successAction.action") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_ACTION) + .attributes(key("value").value("['nextgroup']")), + optionalRequestFieldWithPath("groups[].successAction.expression") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_EXP), + optionalRequestFieldWithPath("groups[].errorCondition") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION), + optionalRequestFieldWithPath("groups[].errorCondition.condition") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_CONDITION) + .attributes(key("value").value("['threshold']")), + optionalRequestFieldWithPath("groups[].errorCondition.expression") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_EXP), + optionalRequestFieldWithPath("groups[].errorAction") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION), + optionalRequestFieldWithPath("groups[].errorAction.action") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_ACTION) + .attributes(key("value").value("['pause']")), + optionalRequestFieldWithPath("groups[].errorAction.expression") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP)), + getRolloutResponseFields(false, true))); + } + + @Test + @Description("Handles the DELETE request of deleting a rollout within SP. Required Permission: " + + SpPermission.DELETE_ROLLOUT) + public void deleteRollout() throws Exception { + final Rollout rollout = createRolloutEntity(); + this.mockMvc.perform(delete(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}", rollout.getId())) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()).andDo(this.document.document( + pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.NAME)))); + } + + @Test + @Description("Handles the POST request of starting a rollout. Required Permission: " + SpPermission.HANDLE_ROLLOUT) + public void startRollout() throws Exception { + final Rollout rollout = createRolloutEntity(); + mockMvc.perform(post(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/start", rollout.getId()) + .accept(MediaTypes.HAL_JSON_VALUE)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the POST request of pausing a rollout. Required Permission: " + SpPermission.HANDLE_ROLLOUT) + public void pauseRollout() throws Exception { + final Rollout rollout = createRolloutEntity(); + rolloutManagement.start(rollout.getId()); + + // Run here, because scheduler is disabled during tests + rolloutManagement.handleRollouts(); + + mockMvc.perform(post(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/pause", rollout.getId()) + .accept(MediaTypes.HAL_JSON_VALUE)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the POST request of resuming a rollout. Required Permission: " + SpPermission.HANDLE_ROLLOUT) + public void resumeRollout() throws Exception { + final Rollout rollout = createRolloutEntity(); + rolloutManagement.start(rollout.getId()); + + // Run here, because scheduler is disabled during tests + rolloutManagement.handleRollouts(); + + rolloutManagement.pauseRollout(rollout.getId()); + mockMvc.perform(post(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/resume", rollout.getId()) + .accept(MediaTypes.HAL_JSON_VALUE)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the GET request of retrieving the deploy groups of a rollout. Required Permission: " + + SpPermission.READ_ROLLOUT) + public void getRolloutDeployGroups() throws Exception { + final Rollout rollout = createRolloutEntity(); + + mockMvc.perform(get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/deploygroups", rollout.getId()) + .accept(MediaTypes.HAL_JSON_VALUE)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + getRolloutDeployGroupResponseFields(true, false, + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("content").description(MgmtApiModelProperties.ROLLOUT_LIST)), + pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the GET request of retrieving a deploy group of a rollout. Required Permission: " + + SpPermission.READ_ROLLOUT) + public void getRolloutDeployGroup() throws Exception { + final Rollout rollout = createRolloutEntity(); + final RolloutGroup firstRolloutGroup = rolloutGroupManagement.findByRollout(PAGE, rollout.getId()).getContent() + .get(0); + + mockMvc.perform(get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/deploygroups/{deployGroupId}", + rollout.getId(), firstRolloutGroup.getId()).accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document(getRolloutDeployGroupResponseFields(false, true), + pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("deployGroupId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + private Snippet getRolloutDeployGroupResponseFields(final boolean isArray, final boolean withDetails, + final FieldDescriptor... descriptors) throws JsonProcessingException { + final String arrayPrefix = getArrayPrefix(isArray); + final List allFieldDescriptor = new ArrayList<>(); + allFieldDescriptor.addAll(Arrays.asList(descriptors)); + + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "id").description(ApiModelPropertiesGeneric.ITEM_ID)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "name").description(ApiModelPropertiesGeneric.NAME)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "description").optional() + .description(ApiModelPropertiesGeneric.DESCRPTION)); + allFieldDescriptor + .add(fieldWithPath(arrayPrefix + "createdBy").description(ApiModelPropertiesGeneric.CREATED_BY)); + allFieldDescriptor + .add(fieldWithPath(arrayPrefix + "createdAt").description(ApiModelPropertiesGeneric.CREATED_AT)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "lastModifiedBy").optional().type(JsonFieldType.STRING) + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "lastModifiedAt").optional().type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT)); + allFieldDescriptor + .add(fieldWithPath(arrayPrefix + "status").description(MgmtApiModelProperties.ROLLOUT_GROUP_STATUS) + .attributes(key("value").value("['creating','ready','paused','running','finished']"))); + + allFieldDescriptor.add( + fieldWithPath(arrayPrefix + "totalTargets").description(MgmtApiModelProperties.ROLLOUT_TOTAL_TARGETS)); + + if (withDetails) { + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "totalTargetsPerStatus") + .description(MgmtApiModelProperties.ROLLOUT_TOTAL_TARGETS_PER_STATUS)); + } + + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "targetFilterQuery") + .description(MgmtApiModelProperties.ROLLOUT_GROUP_FILTER_QUERY)); + + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "targetPercentage") + .description(MgmtApiModelProperties.ROLLOUT_GROUP_TARGET_PERCENTAGE)); + + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "successCondition") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "successCondition.condition") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_CONDITION)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "successCondition.expression") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_EXP)); + + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "successAction") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "successAction.action") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_ACTION)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "successAction.expression") + .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_EXP)); + + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "errorCondition") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "errorCondition.condition") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_CONDITION)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "errorCondition.expression") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_EXP)); + + allFieldDescriptor.add( + fieldWithPath(arrayPrefix + "errorAction").description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "errorAction.action") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_ACTION)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "errorAction.expression") + .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP)); + + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.self").ignored()); + + return new DocumenationResponseFieldsSnippet(allFieldDescriptor); + } + + @Test + @Description("Handles the GET request of retrieving a deploy group of a rollout. Required Permission: " + + SpPermission.READ_ROLLOUT) + public void getRolloutDeployGroupWithParameters() throws Exception { + final Rollout rollout = createRolloutEntity(); + final RolloutGroup firstRolloutGroup = rolloutGroupManagement + .findByRollout(new PageRequest(0, 1), rollout.getId()).getContent().get(0); + + mockMvc.perform(get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/deploygroups/{deployGroupId}", + rollout.getId(), firstRolloutGroup.getId()).param("offset", "0").param("limit", "2") + .param("sort", "id:DESC").param("q", "id==" + firstRolloutGroup.getId()) + .accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("deployGroupId").description(ApiModelPropertiesGeneric.ITEM_ID)), + getFilterRequestParamter())); + } + + @Test + @Description("Handles the GET request of retrieving a all targets of a specific deploy group of a rollout. Required Permissions: " + + SpPermission.READ_ROLLOUT + ", " + SpPermission.READ_TARGET) + public void getRolloutDeployGroupTargets() throws Exception { + final Rollout rollout = createRolloutEntity(); + final RolloutGroup firstRolloutGroup = rolloutGroupManagement + .findByRollout(new PageRequest(0, 1), rollout.getId()).getContent().get(0); + + mockMvc.perform( + get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/deploygroups/{deployGroupId}/targets", + rollout.getId(), firstRolloutGroup.getId()).accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("deployGroupId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields( + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("content").description(MgmtApiModelProperties.TARGET_LIST), + fieldWithPath("content[].createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("content[].address").optional().type(String.class) + .description(MgmtApiModelProperties.ADDRESS), + fieldWithPath("content[].createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("content[].name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("content[].description").optional().type(String.class) + .description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("content[].controllerId").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("content[].updateStatus") + .description(MgmtApiModelProperties.UPDATE_STATUS).type("enum") + .attributes(key("value") + .value("['error', 'in_sync', 'pending', 'registered', 'unknown']")), + fieldWithPath("content[].securityToken") + .description(MgmtApiModelProperties.SECURITY_TOKEN), + fieldWithPath("content[].installedAt").optional().type(Long.class) + .description(MgmtApiModelProperties.INSTALLED_AT), + fieldWithPath("content[].lastModifiedAt").optional().type(Long.class) + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number"), + fieldWithPath("content[].lastModifiedBy").optional().type(String.class) + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY).type("String"), + fieldWithPath("content[].ipAddress").optional().type(String.class) + .description(MgmtApiModelProperties.IP_ADDRESS).type("String"), + fieldWithPath("content[].lastControllerRequestAt").optional().type(Long.class) + .description(MgmtApiModelProperties.LAST_REQUEST_AT).type("Number"), + fieldWithPath("content[]._links.self").ignored()))); + } + + @Test + @Description("Handles the GET request of retrieving a all targets of a specific deploy group of a rollout. Required Permission: " + + SpPermission.READ_ROLLOUT + ", " + SpPermission.READ_TARGET) + public void getRolloutDeployGroupTargetsWithParameters() throws Exception { + final Rollout rollout = createRolloutEntity(); + final RolloutGroup firstRolloutGroup = rolloutGroupManagement + .findByRollout(new PageRequest(0, 1), rollout.getId()).getContent().get(0); + + mockMvc.perform( + get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/deploygroups/{deployGroupId}/targets", + rollout.getId(), firstRolloutGroup.getId()).param("offset", "0").param("limit", "2") + .param("sort", "name:ASC").param("q", "controllerId==exampleTarget0") + .accept(MediaTypes.HAL_JSON_VALUE)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("deployGroupId").description(ApiModelPropertiesGeneric.ITEM_ID)), + getFilterRequestParamter())); + } + + private Rollout createRolloutEntity() { + testdataFactory.createTargets(20, "exampleTarget"); + final Rollout rollout = rolloutManagement.create( + entityFactory.rollout().create().name("exampleRollout") + .targetFilterQuery("controllerId==exampleTarget*").set(testdataFactory.createDistributionSet()), + 10, new RolloutGroupConditionBuilder().withDefaults() + .successCondition(RolloutGroupSuccessCondition.THRESHOLD, "10").build()); + + // Run here, because Scheduler is disabled during tests + rolloutManagement.handleRollouts(); + + return rolloutManagement + .update(entityFactory.rollout().update(rollout.getId()).description("exampleDescription")); + } + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/SoftwaremoduleTypesDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/SoftwaremoduleTypesDocumentationTest.java new file mode 100644 index 000000000..15d02c461 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/SoftwaremoduleTypesDocumentationTest.java @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.mgmt.documentation; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; +import org.eclipse.hawkbit.repository.model.SoftwareModuleType; +import org.eclipse.hawkbit.repository.test.util.WithUser; +import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation; +import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric; +import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties; +import org.eclipse.hawkbit.rest.util.JsonBuilder; +import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +/** + * + * Documentation generation for Management API for {@link SoftwareModuleType}. + * + */ +@Features("Spring Rest Docs Tests - SoftwareModuleType") +@Stories("Softwaremoduletypes Resource") +public class SoftwaremoduleTypesDocumentationTest extends AbstractApiRestDocumentation { + + @Override + @Before + public void setUp() { + this.resourceName = "softwaremoduletypes"; + super.setUp(); + } + + @Test + @WithUser(principal = "uploadTester", allSpPermissions = true) + @Description("Handles the GET request of retrieving all software module types within SP. Required Permission: READ_REPOSITORY.") + public void getSoftwareModuleTypes() throws Exception { + + final SoftwareModuleType testType = testdataFactory.findOrCreateSoftwareModuleType("test123"); + softwareModuleTypeManagement + .update(entityFactory.softwareModuleType().update(testType.getId()).description("Desc1234")); + + mockMvc.perform(get(MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING).accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document(responseFields( + fieldWithPath("size").type(JsonFieldType.NUMBER).description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("content").description(MgmtApiModelProperties.TARGET_LIST), + fieldWithPath("content[].createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("content[].createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("content[].description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("content[].id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("content[].lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number"), + fieldWithPath("content[].lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY).type("String"), + fieldWithPath("content[].name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("content[]._links.self").ignored()))); + } + + @Test + @WithUser(principal = "uploadTester", allSpPermissions = true) + @Description("Handles the GET request of retrieving all software module types within SP with parametsrs. In this case the first 10 result in ascending order by name wher the name starts with 'a'. Required Permission: READ_REPOSITORY.") + public void getSoftwareModuleTypesWithParameters() throws Exception { + final SoftwareModuleType testType = testdataFactory.findOrCreateSoftwareModuleType("test123"); + softwareModuleTypeManagement + .update(entityFactory.softwareModuleType().update(testType.getId()).description("Desc1234")); + + mockMvc.perform(get( + MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING + "?limit=10&sort=name:ASC&offset=0&q=name==a") + .accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document(getFilterRequestParamter())); + } + + @Test + @WithUser(principal = "uploadTester", allSpPermissions = true) + @Description("Handles the POST request of creating new software module types within SP. The request body must " + + "always be a list of module types. Required Permission: CREATE_REPOSITORY.") + public void postSoftwareModuleTypes() throws Exception { + + final List types = Arrays.asList(entityFactory.softwareModuleType().create().key("test1") + .name("TestName1").description("Desc1").build()); + + this.mockMvc + .perform(post(MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING) + .content(JsonBuilder.softwareModuleTypesCreatableFieldsOnly(types)) + .contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + requestFields( + optionalRequestFieldWithPath("[]description") + .description(ApiModelPropertiesGeneric.DESCRPTION), + optionalRequestFieldWithPath("[]key").description(MgmtApiModelProperties.SMT_KEY), + optionalRequestFieldWithPath("[]maxAssignments") + .description(MgmtApiModelProperties.SM_MAX_ASSIGNMENTS), + requestFieldWithPath("[]name").description(ApiModelPropertiesGeneric.NAME)), + responseFields(fieldWithPath("[]key").description(MgmtApiModelProperties.SMT_KEY), + fieldWithPath("[]maxAssignments") + .description(MgmtApiModelProperties.SMT_MAX_ASSIGNMENTS), + fieldWithPath("[]createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("[]createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("[]description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("[]deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("[]id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("[]lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number"), + fieldWithPath("[]lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY).type("String"), + fieldWithPath("[]name").description(ApiModelPropertiesGeneric.NAME), + + fieldWithPath("[]_links.self").ignored()))); + + } + + @Test + @WithUser(principal = "uploadTester", allSpPermissions = true) + @Description("Handles the DELETE request for a single software module Type within SP. Required Permission: DELETE_REPOSITORY.") + public void deleteSoftwareModuleType() throws Exception { + final SoftwareModuleType testType = softwareModuleTypeManagement.create( + entityFactory.softwareModuleType().create().key("test1").name("TestName1").description("Desc1")); + assertThat(softwareModuleTypeManagement.count()).isEqualTo(4); + this.mockMvc + .perform(delete(MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING + "/{softwareModuleTypeID}", + testType.getId())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document(pathParameters( + parameterWithName("softwareModuleTypeID").description(ApiModelPropertiesGeneric.ITEM_ID)))); + assertThat(softwareModuleTypeManagement.count()).isEqualTo(3); + } + + @Test + @WithUser(principal = "uploadTester", allSpPermissions = true) + @Description("Handles the GET request of retrieving a single software module type within SP. Required Permission: READ_REPOSITORY.") + public void getSoftwareModuleType() throws Exception { + final SoftwareModuleType testType = testdataFactory.findOrCreateSoftwareModuleType("test123"); + softwareModuleTypeManagement + .update(entityFactory.softwareModuleType().update(testType.getId()).description("Desc1234")); + + this.mockMvc + .perform(get(MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING + "/{softwareModuleTypeID}", + testType.getId()).accept(MediaType.APPLICATION_JSON)) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("softwareModuleTypeID") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("key").description(MgmtApiModelProperties.SMT_KEY), + fieldWithPath("maxAssignments").description(MgmtApiModelProperties.SMT_MAX_ASSIGNMENTS), + fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT) + .type("Number"), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY) + .type("String"), + fieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + + fieldWithPath("_links.self").ignored()))); + } + + @Test + @Description("Handles the PUT request for a single software module type within SP. Required Permission: UPDATE_REPOSITORY.") + public void putSoftwareModuleType() throws Exception { + final SoftwareModuleType testType = testdataFactory.findOrCreateSoftwareModuleType("test123"); + + final String body = new JSONObject().put("description", "a new description").toString(); + + this.mockMvc + .perform(put(MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING + "/{softwareModuleTypeID}", + testType.getId()).content(body.toString()).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("softwareModuleTypeID") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields( + requestFieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION)), + responseFields(fieldWithPath("key").description(MgmtApiModelProperties.SMT_KEY), + fieldWithPath("maxAssignments").description(MgmtApiModelProperties.SMT_MAX_ASSIGNMENTS), + fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT) + .type("Number"), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY) + .type("String"), + fieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("_links.self").ignored()))); + + } + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/SoftwaremodulesDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/SoftwaremodulesDocumentationTest.java new file mode 100644 index 000000000..caad88abf --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/SoftwaremodulesDocumentationTest.java @@ -0,0 +1,580 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.mgmt.documentation; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.fileUpload; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.restdocs.snippet.Attributes.key; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.ByteArrayInputStream; +import java.util.Arrays; +import java.util.List; + +import org.apache.commons.lang3.RandomStringUtils; +import org.eclipse.hawkbit.im.authentication.SpPermission; +import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; +import org.eclipse.hawkbit.repository.Constants; +import org.eclipse.hawkbit.repository.model.Artifact; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation; +import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric; +import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties; +import org.eclipse.hawkbit.rest.util.JsonBuilder; +import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.restdocs.payload.JsonFieldType; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +/** + * Documentation generation for Management API for {@link SoftwareModule}. + */ +@Features("Spring Rest Docs Tests - SoftwareModule") +@Stories("Softwaremodule Resource") +public class SoftwaremodulesDocumentationTest extends AbstractApiRestDocumentation { + + @Override + @Before + public void setUp() { + resourceName = "softwaremodules"; + super.setUp(); + } + + @Test + @Description("Handles the GET request of retrieving all softwaremodules within SP. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getSoftwareModules() throws Exception { + + final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); + softwareModuleManagement.update(entityFactory.softwareModule().update(sm.getId()).description("a description")); + + final SoftwareModule sm2 = testdataFactory.createSoftwareModuleApp(); + softwareModuleManagement + .update(entityFactory.softwareModule().update(sm2.getId()).description("a description")); + + mockMvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING)).andDo(MockMvcResultPrinter.print()) + .andExpect(status().isOk()).andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document(responseFields( + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("size").type(JsonFieldType.NUMBER).description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("content").description(MgmtApiModelProperties.SM_LIST), + fieldWithPath("content[].id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("content[].name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("content[].description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("content[].vendor").description(MgmtApiModelProperties.VENDOR), + fieldWithPath("content[].createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("content[].createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("content[].lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath("content[].lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath("content[].type").description(MgmtApiModelProperties.SM_TYPE), + fieldWithPath("content[].version").description(MgmtApiModelProperties.VERSION), + fieldWithPath("content[]._links.self").ignored()))); + } + + @Test + @Description("Handles the GET request of retrieving all softwaremodules within SP with given page size and offset including sorting by version descending and filter down to all sets which name starts with 'SM'. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getSoftwareModulesWithParameters() throws Exception { + + final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); + softwareModuleManagement.update(entityFactory.softwareModule().update(sm.getId()).description("a description")); + + final SoftwareModule sm2 = testdataFactory.createSoftwareModuleApp(); + softwareModuleManagement + .update(entityFactory.softwareModule().update(sm2.getId()).description("a description")); + + mockMvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING).param("offset", "1") + .param("limit", "2").param("sort", "version:DESC").param("q", "name==SM*")) + + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document(getFilterRequestParamter())); + } + + @Test + @Description("Handles the POST request of creating new software modules within SP. The request body must always be a list of modules. Required Permission: " + + SpPermission.CREATE_REPOSITORY) + public void postSoftwareModules() throws Exception { + final SoftwareModule os = entityFactory.softwareModule().create().type(osType).name("name1").version("version1") + .description("description1").vendor("vendor1").build(); + final SoftwareModule ah = entityFactory.softwareModule().create().type(appType).name("name3") + .version("version1").description("description1").vendor("vendor1").build(); + + final List modules = Arrays.asList(os, ah); + + mockMvc.perform(post(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING) + .content(JsonBuilder.softwareModulesCreatableFieldsOnly(modules)).contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + requestFields(requestFieldWithPath("[]name").description(ApiModelPropertiesGeneric.NAME), + optionalRequestFieldWithPath("[]description") + .description(ApiModelPropertiesGeneric.DESCRPTION), + requestFieldWithPath("[]version").description(MgmtApiModelProperties.VERSION), + optionalRequestFieldWithPath("[]vendor").description(MgmtApiModelProperties.VENDOR), + requestFieldWithPath("[]type").description(MgmtApiModelProperties.SMT_TYPE)), + responseFields(fieldWithPath("[].id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("[].name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("[].description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("[].vendor").description(MgmtApiModelProperties.VENDOR), + fieldWithPath("[].deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("[].createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("[].createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("[].lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath("[].lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath("[].type").description(MgmtApiModelProperties.SM_TYPE), + fieldWithPath("[].version").description(MgmtApiModelProperties.VERSION), + fieldWithPath("[]._links.self").ignored()))); + } + + @Test + @Description("Handles the DELETE request for a single softwaremodule within SP. Required Permission: " + + SpPermission.DELETE_REPOSITORY) + public void deleteSoftwareModule() throws Exception { + final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); + + this.mockMvc + .perform( + delete(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}", sm.getId())) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the GET request of retrieving a single softwaremodule within SP. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getSoftwareModule() throws Exception { + final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); + softwareModuleManagement.update(entityFactory.softwareModule().update(sm.getId()).description("a description")); + + mockMvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}", sm.getId())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath("vendor").description(MgmtApiModelProperties.VENDOR), + fieldWithPath("deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("type").description(MgmtApiModelProperties.SM_TYPE), + fieldWithPath("version").description(MgmtApiModelProperties.VERSION), + fieldWithPath("_links.self").ignored(), + fieldWithPath("_links.type").description(MgmtApiModelProperties.SM_TYPE), + fieldWithPath("_links.artifacts").description(MgmtApiModelProperties.ARTIFACT_LIST), + fieldWithPath("_links.metadata").description(MgmtApiModelProperties.META_DATA)))); + } + + @Test + @Description("Handles the PUT request for a single softwaremodule within SP. Required Permission: " + + SpPermission.UPDATE_REPOSITORY) + public void putSoftwareModule() throws Exception { + final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); + softwareModuleManagement.update(entityFactory.softwareModule().update(sm.getId()).description("a description")); + + final SoftwareModule update = entityFactory.softwareModule().create().name("another name") + .vendor("another Vendor").description("a new description").type(Constants.SMT_DEFAULT_OS_KEY).build(); + + mockMvc.perform(put(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}", sm.getId()) + .content(JsonBuilder.softwareModuleUpdatableFieldsOnly(update)).contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields(optionalRequestFieldWithPath("vendor").description(MgmtApiModelProperties.VENDOR), + optionalRequestFieldWithPath("description") + .description(ApiModelPropertiesGeneric.DESCRPTION)), + responseFields(fieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath("type").description(MgmtApiModelProperties.SM_TYPE), + fieldWithPath("version").description(MgmtApiModelProperties.VERSION), + fieldWithPath("vendor").description(MgmtApiModelProperties.VENDOR), + fieldWithPath("deleted").description(ApiModelPropertiesGeneric.DELETED), + fieldWithPath("_links.self").ignored(), + fieldWithPath("_links.type").description(MgmtApiModelProperties.SM_TYPE), + fieldWithPath("_links.artifacts").description(MgmtApiModelProperties.ARTIFACT_LIST), + fieldWithPath("_links.metadata").description(MgmtApiModelProperties.META_DATA)))); + + } + + @Test + @Description("Handles the GET request of retrieving all meta data of artifacts assigned to a software module. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getArtifacts() throws Exception { + final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); + + final byte random[] = RandomStringUtils.random(5).getBytes(); + + artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1", false, 0); + + mockMvc.perform( + get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts", sm.getId())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("[].id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("[].size").description(MgmtApiModelProperties.ARTIFACT_SIZE), + fieldWithPath("[].createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("[].createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("[].lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath("[].lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath("[].hashes.md5").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5), + fieldWithPath("[].hashes.sha1") + .description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1), + fieldWithPath("[].providedFilename") + .description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME), + fieldWithPath("[]._links.self").ignored()))); + } + + @Test + @Description("Handles POST request for artifact upload. Required Permission: " + SpPermission.CREATE_REPOSITORY) + public void postArtifact() throws Exception { + final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); + + // create test file + final byte random[] = RandomStringUtils.random(5).getBytes(); + final MockMultipartFile file = new MockMultipartFile("file", "origFilename", null, random); + + mockMvc.perform( + fileUpload(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts", + sm.getId()).file(file)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("size").description(MgmtApiModelProperties.ARTIFACT_SIZE), + fieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath("_links.self").ignored(), + fieldWithPath("_links.download") + .description(MgmtApiModelProperties.ARTIFACT_DOWNLOAD_LINK), + fieldWithPath("hashes.md5").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5), + fieldWithPath("hashes.sha1").description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1), + fieldWithPath("providedFilename") + .description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME))) + + ); + } + + @Test + @Description("Handles POST request for artifact upload. Required Permission: " + SpPermission.CREATE_REPOSITORY) + public void postArtifactWithParameters() throws Exception { + + final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); + + final byte random[] = RandomStringUtils.random(5).getBytes(); + final MockMultipartFile file = new MockMultipartFile("file", "origFilename", null, random); + + mockMvc.perform( + fileUpload(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts", + sm.getId()).file(file).param("filename", "filename").param("file", "s") + .param("md5sum", "md5sum").param("sha1sum", "sha1sum")) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document(requestParameters( + parameterWithName("filename").description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME), + parameterWithName("file").description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILE), + parameterWithName("md5sum").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5), + parameterWithName("sha1sum").description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1)))); + } + + @Test + @Description("Handles the DELETE request for a single SoftwareModule within SP. Required Permission: " + + SpPermission.DELETE_REPOSITORY) + public void deleteArtifact() throws Exception { + final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); + + final byte random[] = RandomStringUtils.random(5).getBytes(); + + final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1", + false, 0); + + mockMvc.perform(delete( + MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts/{artifactId}", + sm.getId(), artifact.getId())).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document(pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("artifactId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the GET request of retrieving a single Artifact meta data request. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getArtifact() throws Exception { + final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); + + final byte random[] = RandomStringUtils.random(5).getBytes(); + + final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1", + false, 0); + + mockMvc.perform( + get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts/{artifactId}", + sm.getId(), artifact.getId())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("artifactId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("size").description(MgmtApiModelProperties.ARTIFACT_SIZE), + fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath("hashes.md5").description(MgmtApiModelProperties.ARTIFACT_HASHES_MD5), + fieldWithPath("hashes.sha1").description(MgmtApiModelProperties.ARTIFACT_HASHES_SHA1), + fieldWithPath("providedFilename") + .description(MgmtApiModelProperties.ARTIFACT_PROVIDED_FILENAME), + fieldWithPath("_links.self").ignored(), fieldWithPath("_links.download") + .description(MgmtApiModelProperties.ARTIFACT_DOWNLOAD_LINK)))); + } + + @Test + @Description("Handles the GET request for downloading an artifact. Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getDownloadArtifact() throws Exception { + + final SoftwareModule sm = testdataFactory.createSoftwareModuleOs(); + + final byte random[] = RandomStringUtils.random(5).getBytes(); + + final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1", + false, 0); + + mockMvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + + "/{softwareModuleId}/artifacts/{artifactId}/download", sm.getId(), artifact.getId()) + .accept(MediaType.APPLICATION_OCTET_STREAM)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) + .andDo(this.document.document(pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("artifactId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description(" Get a paged list of meta data for a software module." + " Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getMetadata() throws Exception { + final int totalMetadata = 4; + final String knownKeyPrefix = "knownKey"; + final String knownValuePrefix = "knownValue"; + final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get(); + + for (int index = 0; index < totalMetadata; index++) { + softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(module.getId()) + .key(knownKeyPrefix + index).value(knownValuePrefix + index)); + } + + mockMvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata", + module.getId())).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("content").description(MgmtApiModelProperties.META_DATA), + fieldWithPath("content[].key").description(MgmtApiModelProperties.META_DATA_KEY), + fieldWithPath("content[].value").description(MgmtApiModelProperties.META_DATA_VALUE), + fieldWithPath("content[].targetVisible") + .description(MgmtApiModelProperties.SM_META_DATA_TARGET_VISIBLE)))); + } + + @Test + @Description(" Get a paged list of meta data for a software module with defined page size and sorting by name descending and key starting with 'known'." + + " Required Permission: " + SpPermission.READ_REPOSITORY) + public void getMetadataWithParameters() throws Exception { + final int totalMetadata = 4; + final String knownKeyPrefix = "knownKey"; + final String knownValuePrefix = "knownValue"; + final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get(); + + for (int index = 0; index < totalMetadata; index++) { + softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(module.getId()) + .key(knownKeyPrefix + index).value(knownValuePrefix + index)); + } + + mockMvc.perform(get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata", + module.getId()).param("offset", "1").param("limit", "2").param("sort", "key:DESC").param("q", + "key==known*")) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID)), + requestParameters( + parameterWithName("limit").attributes(key("type").value("query")) + .description(ApiModelPropertiesGeneric.LIMIT), + parameterWithName("sort").description(ApiModelPropertiesGeneric.SORT), + parameterWithName("offset").description(ApiModelPropertiesGeneric.OFFSET), + parameterWithName("q").description(ApiModelPropertiesGeneric.FIQL)))); + } + + @Test + @Description("Create a list of meta data entries" + " Required Permission: " + SpPermission.UPDATE_REPOSITORY) + public void postMetadata() throws Exception { + + final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get(); + + final String knownKey1 = "knownKey1"; + final String knownKey2 = "knownKey2"; + + final String knownValue1 = "knownValue1"; + final String knownValue2 = "knownValue2"; + + final JSONArray jsonArray = new JSONArray(); + jsonArray.put(new JSONObject().put("key", knownKey1).put("value", knownValue1)); + jsonArray.put(new JSONObject().put("key", knownKey2).put("value", knownValue2).put("targetVisible", true)); + + mockMvc.perform(post(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata", + module.getId()).contentType(APPLICATION_JSON_HAL_UTF).content(jsonArray.toString())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) + .andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)) + .andDo(this.document.document( + pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields(requestFieldWithPath("[]key").description(MgmtApiModelProperties.META_DATA_KEY), + requestFieldWithPath("[]value").description(MgmtApiModelProperties.META_DATA_VALUE), + requestFieldWithPath("[]targetVisible") + .description(MgmtApiModelProperties.SM_META_DATA_TARGET_VISIBLE)), + + responseFields(fieldWithPath("[]key").description(MgmtApiModelProperties.META_DATA_KEY), + fieldWithPath("[]value").description(MgmtApiModelProperties.META_DATA_VALUE), + fieldWithPath("[]targetVisible") + .description(MgmtApiModelProperties.SM_META_DATA_TARGET_VISIBLE) + + ) + + )); + } + + @Test + @Description(" Delete a single meta data." + " Required Permission: " + SpPermission.UPDATE_REPOSITORY) + public void deleteMetadata() throws Exception { + // prepare and create metadata for deletion + final String knownKey = "knownKey"; + final String knownValue = "knownValue"; + + final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get(); + softwareModuleManagement.createMetaData( + entityFactory.softwareModuleMetadata().create(module.getId()).key(knownKey).value(knownValue)); + + mockMvc.perform(delete( + MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata/{{metadataKey}", + module.getId(), knownKey)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document(pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("{metadataKey").description(MgmtApiModelProperties.META_DATA_KEY)))); + } + + @Test + @Description(" Get a single meta data value for a meta data key." + " Required Permission: " + + SpPermission.READ_REPOSITORY) + public void getMetadataValue() throws Exception { + + // prepare and create metadata + final String knownKey = "knownKey"; + final String knownValue = "knownValue"; + final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get(); + softwareModuleManagement.createMetaData( + entityFactory.softwareModuleMetadata().create(module.getId()).key(knownKey).value(knownValue)); + + mockMvc.perform( + get(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata/{metadataKey}", + module.getId(), knownKey)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters( + parameterWithName("softwareModuleId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("metadataKey").description(MgmtApiModelProperties.META_DATA_KEY)), + responseFields(fieldWithPath("key").description(MgmtApiModelProperties.META_DATA_KEY), + fieldWithPath("value").description(MgmtApiModelProperties.META_DATA_VALUE), + fieldWithPath("targetVisible") + .description(MgmtApiModelProperties.SM_META_DATA_TARGET_VISIBLE)))); + } + + @Test + @Description(" Update a single meta data value for speficic key." + " Required Permission: " + + SpPermission.UPDATE_REPOSITORY) + public void putMetadata() throws Exception { + // prepare and create metadata for update + final String knownKey = "knownKey"; + final String knownValue = "knownValue"; + final String updateValue = "valueForUpdate"; + + final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get(); + softwareModuleManagement.createMetaData( + entityFactory.softwareModuleMetadata().create(module.getId()).key(knownKey).value(knownValue)); + + final JSONObject jsonObject = new JSONObject().put("key", knownKey).put("value", updateValue) + .put("targetVisible", true); + + mockMvc.perform( + put(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata/{metadataKey}", + module.getId(), knownKey).contentType(APPLICATION_JSON_HAL_UTF).content(jsonObject.toString())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("softwareModuleId") + .description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("metadataKey").description(MgmtApiModelProperties.META_DATA_KEY)), + requestFields(requestFieldWithPath("key").description(MgmtApiModelProperties.META_DATA_KEY), + requestFieldWithPath("value").description(MgmtApiModelProperties.META_DATA_VALUE), + requestFieldWithPath("targetVisible") + .description(MgmtApiModelProperties.SM_META_DATA_TARGET_VISIBLE)), + responseFields(fieldWithPath("key").description(MgmtApiModelProperties.META_DATA_KEY), + fieldWithPath("value").description(MgmtApiModelProperties.META_DATA_VALUE), + fieldWithPath("targetVisible") + .description(MgmtApiModelProperties.SM_META_DATA_TARGET_VISIBLE)))); + } + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/TargetFilterQueriesResourceDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/TargetFilterQueriesResourceDocumentationTest.java new file mode 100644 index 000000000..1d5468492 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/TargetFilterQueriesResourceDocumentationTest.java @@ -0,0 +1,241 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.mgmt.documentation; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.restdocs.snippet.Attributes.key; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.TargetFilterQuery; +import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation; +import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric; +import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties; +import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.restdocs.snippet.Snippet; + +import com.fasterxml.jackson.core.JsonProcessingException; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +/** + * Documentation generation for Management API for {@link TargetFilterQuery}. + */ +@Features("Spring Rest Docs Tests - TargetFilterQuery") +@Stories("TargetFilterQuery Resource") +public class TargetFilterQueriesResourceDocumentationTest extends AbstractApiRestDocumentation { + + private static final String EXAMPLE_TFQ_NAME = "filter1"; + private static final String EXAMPLE_TFQ_QUERY = "name==*"; + + @Override + @Before + public void setUp() { + resourceName = "targetfilters"; + super.setUp(); + } + + @Test + @Description("Handles the GET request of retrieving all target filter queries within SP. Required Permission: READ_TARGET.") + public void getTargetFilterQueries() throws Exception { + + createTargetFilterQueryWithDS(createDistributionSet()); + + mockMvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING)).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(responseFields( + fieldWithPath("size").type(JsonFieldType.NUMBER).description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("content").description(MgmtApiModelProperties.TARGET_FILTER_QUERIES_LIST), + fieldWithPath("content[].id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("content[].name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("content[].query").description(MgmtApiModelProperties.TARGET_FILTER_QUERY), + fieldWithPath("content[].autoAssignDistributionSet") + .description(MgmtApiModelProperties.TARGET_FILTER_QUERY_AUTO_ASSIGN_DS_ID) + .type("Number"), + fieldWithPath("content[].createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("content[].createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("content[].lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath("content[].lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath("content[]._links.self").ignored()))); + } + + @Test + @Description("Handles the GET request of retrieving all target filter queries within SP based by parameter. Required Permission: READ_TARGET.") + public void getTargetFilterQueriesWithParameters() throws Exception { + + mockMvc.perform( + get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "?limit=10&sort=name:ASC&offset=0&q=name==*1")) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(requestParameters( + parameterWithName("limit").attributes(key("type").value("query")) + .description(ApiModelPropertiesGeneric.LIMIT), + parameterWithName("sort").description(ApiModelPropertiesGeneric.SORT), + parameterWithName("offset").description(ApiModelPropertiesGeneric.OFFSET), + parameterWithName("q").description(ApiModelPropertiesGeneric.FIQL)))); + } + + @Test + @Description("Handles the POST request of creating a new target filter query within SP. Required Permission: CREATE_TARGET.") + public void postTargetFilterQuery() throws Exception { + final String tfqJson = createTargetFilterQueryJson(EXAMPLE_TFQ_NAME, EXAMPLE_TFQ_QUERY); + + this.mockMvc + .perform(post(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING) + .contentType(MediaType.APPLICATION_JSON).content(tfqJson)) + .andExpect(status().isCreated()).andDo(MockMvcResultPrinter.print()).andDo( + this.document.document( + requestFields(requestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + requestFieldWithPath("query") + .description(MgmtApiModelProperties.TARGET_FILTER_QUERY)), + getResponseFieldTargetFilterQuery(false))); + + } + + @Test + @Description("Handles the DELETE request of deleting a single target filter query within SP. Required Permission: DELETE_TARGET.") + public void deleteTargetFilterQuery() throws Exception { + final TargetFilterQuery tfq = createTargetFilterQuery(); + this.mockMvc + .perform(delete(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/{targetFilterQueryId}", + tfq.getId())) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(pathParameters( + parameterWithName("targetFilterQueryId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the GET request of retrieving a single target filter query within SP. Required Permission: READ_TARGET.") + public void getTargetFilterQuery() throws Exception { + final TargetFilterQuery tfq = createTargetFilterQueryWithDS(createDistributionSet()); + + mockMvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/{targetFilterQueryId}", tfq.getId())) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("targetFilterQueryId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + getResponseFieldTargetFilterQuery(false))); + } + + @Test + @Description("Handles the PUT request of updating a target filter query within SP. Required Permission: UPDATE_TARGET.") + public void putTargetFilterQuery() throws Exception { + final TargetFilterQuery tfq = createTargetFilterQuery(); + final String targetAsJson = createTargetFilterQueryJson("newFilterName", "attribute.hwRevision==2"); + this.mockMvc + .perform(put(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/{targetFilterQueryId}", tfq.getId()) + .contentType(MediaType.APPLICATION_JSON).content(targetAsJson)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("targetFilterQueryId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields(optionalRequestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + optionalRequestFieldWithPath("query") + .description(MgmtApiModelProperties.TARGET_FILTER_QUERY)), + getResponseFieldTargetFilterQuery(false))); + + } + + @Test + @Description("Handles the GET request of retrieving a the auto assign distribution set of a target filter query within SP. Required Permission: READ_TARGET.") + public void getAssignDS() throws Exception { + final TargetFilterQuery tfq = createTargetFilterQueryWithDS(createDistributionSet()); + + mockMvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/{targetFilterQueryId}/autoAssignDS", + tfq.getId())).andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("targetFilterQueryId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + getResponseFieldsDistributionSet(false))); + } + + @Test + @Description("Handles the POST request of setting a distribution set for auto assignment within SP. Required Permission: CREATE_TARGET.") + public void postAutoAssignDS() throws Exception { + final TargetFilterQuery tfq = createTargetFilterQuery(); + final DistributionSet distributionSet = createDistributionSet(); + final String filterByDistSet = "{\"id\":\"" + distributionSet.getId() + "\"}"; + + this.mockMvc + .perform( + post(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/{targetFilterQueryId}/autoAssignDS", + tfq.getId()).contentType(MediaType.APPLICATION_JSON).content(filterByDistSet)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("targetFilterQueryId") + .description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields(requestFieldWithPath("id").description(MgmtApiModelProperties.DS_ID)), + getResponseFieldTargetFilterQuery(false))); + } + + @Test + @Description("Handles the DELETE request of deleting the auto assign distribution set from a target filter query within SP. Required Permission: DELETE_TARGET.") + public void deleteAutoAssignDS() throws Exception { + final TargetFilterQuery tfq = createTargetFilterQueryWithDS(createDistributionSet()); + this.mockMvc + .perform(delete( + MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/{targetFilterQueryId}/autoAssignDS", + tfq.getId())) + .andExpect(status().isNoContent()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(pathParameters( + parameterWithName("targetFilterQueryId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + private Snippet getResponseFieldTargetFilterQuery(final boolean isArray) { + final String arrayPrefix = getArrayPrefix(isArray); + return responseFields(fieldWithPath(arrayPrefix + "id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath(arrayPrefix + "name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath(arrayPrefix + "query").description(MgmtApiModelProperties.TARGET_FILTER_QUERY), + fieldWithPath(arrayPrefix + "autoAssignDistributionSet") + .description(MgmtApiModelProperties.TARGET_FILTER_QUERY_AUTO_ASSIGN_DS_ID).type("Number"), + fieldWithPath(arrayPrefix + "createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath(arrayPrefix + "createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath(arrayPrefix + "lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath(arrayPrefix + "lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath(arrayPrefix + "_links.self").ignored(), fieldWithPath(arrayPrefix + "_links.autoAssignDS") + .description(MgmtApiModelProperties.TARGET_FILTER_QUERY_LINK_AUTO_ASSIGN_DS)); + } + + private String createTargetFilterQueryJson(final String name, final String query) throws JsonProcessingException { + final Map target = new HashMap<>(); + target.put("name", name); + target.put("query", query); + return objectMapper.writeValueAsString(target); + } + + private TargetFilterQuery createTargetFilterQuery() { + return targetFilterQueryManagement + .create(entityFactory.targetFilterQuery().create().name(EXAMPLE_TFQ_NAME).query(EXAMPLE_TFQ_QUERY)); + } + + private TargetFilterQuery createTargetFilterQueryWithDS(final DistributionSet distributionSet) { + final TargetFilterQuery targetFilterQuery = createTargetFilterQuery(); + return targetFilterQueryManagement.updateAutoAssignDS(targetFilterQuery.getId(), distributionSet.getId()); + } +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/TargetResourceDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/TargetResourceDocumentationTest.java new file mode 100644 index 000000000..a65d5ca15 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/TargetResourceDocumentationTest.java @@ -0,0 +1,602 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.mgmt.documentation; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.restdocs.snippet.Attributes.key; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; +import org.eclipse.hawkbit.repository.ActionStatusFields; +import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action.ActionType; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.Target; +import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation; +import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric; +import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties; +import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort.Direction; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; + +import com.fasterxml.jackson.core.JsonProcessingException; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +/** + * Documentation generation for Management API for {@link Target}. + * + */ +@Features("Spring Rest Docs Tests - Target") +@Stories("Target Resource") +public class TargetResourceDocumentationTest extends AbstractApiRestDocumentation { + + private final String controllerId = "137"; + + @Override + @Before + public void setUp() { + resourceName = "targets"; + super.setUp(); + } + + @Test + @Description("Handles the GET request of retrieving all targets within SP. Required Permission: READ_TARGET.") + public void getTargets() throws Exception { + createTargetByGivenNameWithAttributes(controllerId, createDistributionSet()); + + mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING)).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(responseFields( + fieldWithPath("size").type(JsonFieldType.NUMBER).description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("content").description(MgmtApiModelProperties.TARGET_LIST), + fieldWithPath("content[].createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("content[].address").description(MgmtApiModelProperties.ADDRESS), + fieldWithPath("content[].createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("content[].name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("content[].description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("content[].controllerId").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("content[].updateStatus").description(MgmtApiModelProperties.UPDATE_STATUS) + .type("enum").attributes( + key("value").value("['error', 'in_sync', 'pending', 'registered', 'unknown']")), + fieldWithPath("content[].securityToken").description(MgmtApiModelProperties.SECURITY_TOKEN), + fieldWithPath("content[].installedAt").description(MgmtApiModelProperties.INSTALLED_AT), + fieldWithPath("content[].lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number"), + fieldWithPath("content[].lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY).type("String"), + fieldWithPath("content[].ipAddress").description(MgmtApiModelProperties.IP_ADDRESS) + .type("String"), + fieldWithPath("content[].lastControllerRequestAt") + .description(MgmtApiModelProperties.LAST_REQUEST_AT).type("Number"), + fieldWithPath("content[]._links.self").ignored()))); + } + + @Test + @Description("Handles the GET request of retrieving all targets within SP based by parameter. Required Permission: READ_TARGET.") + public void getTargetsWithParameters() throws Exception { + mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "?limit=10&sort=name:ASC&offset=0&q=name==a")) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(getFilterRequestParamter())); + } + + @Test + @Description("Handles the POST request of creating new targets within SP. The request body must always be a list of targets. Required Permission: CREATE_TARGET.") + public void postTargets() throws Exception { + final String target = createTargetJsonForPostRequest("123456", "controllerId", "test"); + + mockMvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING) + .contentType(MediaType.APPLICATION_JSON_UTF8).content(target)).andExpect(status().isCreated()) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(requestFields( + requestFieldWithPath("[]controllerId").description(ApiModelPropertiesGeneric.ITEM_ID), + requestFieldWithPath("[]name").description(ApiModelPropertiesGeneric.NAME), + optionalRequestFieldWithPath("[]description").description(ApiModelPropertiesGeneric.DESCRPTION), + optionalRequestFieldWithPath("[]address").description(MgmtApiModelProperties.ADDRESS), + optionalRequestFieldWithPath("[]securityToken") + .description(MgmtApiModelProperties.SECURITY_TOKEN)), + responseFields(fieldWithPath("[]controllerId").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("[]name").description(ApiModelPropertiesGeneric.NAME), + fieldWithPath("[]description").description(ApiModelPropertiesGeneric.DESCRPTION), + fieldWithPath("[]address").description(MgmtApiModelProperties.ADDRESS), + fieldWithPath("[]createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("[]lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY), + fieldWithPath("[]lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT), + fieldWithPath("[]ipAddress").description(MgmtApiModelProperties.IP_ADDRESS), + fieldWithPath("[]createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("[]updateStatus").description(MgmtApiModelProperties.UPDATE_STATUS) + .type("enum") + .attributes(key("value") + .value("['error', 'in_sync', 'pending', 'registered', 'unknown']")), + fieldWithPath("[]securityToken").description(MgmtApiModelProperties.SECURITY_TOKEN), + fieldWithPath("[]_links.self").ignored()))); + } + + @Test + @Description("Handles the DELETE request of deleting a single target within SP. Required Permission: DELETE_TARGET.") + public void deleteTarget() throws Exception { + final Target target = testdataFactory.createTarget(controllerId); + + mockMvc.perform( + delete(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}", target.getControllerId())) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()).andDo(this.document.document( + pathParameters(parameterWithName("controllerId").description(ApiModelPropertiesGeneric.NAME)))); + } + + @Test + @Description("Handles the GET request of retrieving a single target within SP. Required Permission: READ_TARGET.") + public void getTarget() throws Exception { + final Target target = createTargetByGivenNameWithAttributes(controllerId, createDistributionSet()); + + mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}", target.getControllerId())) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters( + parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)), + getResponseFieldTarget(false))); + } + + @Test + @Description("Handles the PUT request of updating a target within SP. Required Permission: UPDATE_TARGET.") + public void putTarget() throws Exception { + final Target target = createTargetByGivenNameWithAttributes(controllerId, createDistributionSet()); + final String targetAsJson = createJsonTarget(controllerId, "newTargetName", "I've been updated"); + + mockMvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}", target.getControllerId()) + .contentType(MediaType.APPLICATION_JSON_UTF8).content(targetAsJson)).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters( + parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields(requestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), + requestFieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION), + requestFieldWithPath("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID), + requestFieldWithPath("address").description(MgmtApiModelProperties.ADDRESS), + requestFieldWithPath("securityToken") + .description(MgmtApiModelProperties.SECURITY_TOKEN)), + getResponseFieldTarget(false))); + } + + @Test + @Description("Handles the GET request of retrieving the full action history of a specific target. Required Permission: READ_TARGET.") + public void getActionsFromTarget() throws Exception { + generateActionForTarget(controllerId); + + mockMvc.perform(get( + MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/" + MgmtRestConstants.TARGET_V1_ACTIONS, + controllerId)).andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters( + parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields( + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("content[]").description(MgmtApiModelProperties.ACTION_LIST), + fieldWithPath("content[].createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("content[].createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("content[].lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY).type("String"), + fieldWithPath("content[].lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("String"), + fieldWithPath("content[].type").description(MgmtApiModelProperties.ACTION_TYPE) + .attributes(key("value").value("['update', 'cancel']")), + + fieldWithPath("content[].status") + .description(MgmtApiModelProperties.ACTION_EXECUTION_STATUS) + .attributes(key("value").value("['finished', 'pending']")), + fieldWithPath("content[]._links").description(MgmtApiModelProperties.LINK_TO_ACTION), + fieldWithPath("content[].id").description(MgmtApiModelProperties.ACTION_ID)))); + } + + @Test + @Description("Handles the GET request of retrieving the full action history of a specific target with maintenance window. Required Permission: READ_TARGET.") + public void getActionsFromTargetWithMaintenanceWindow() throws Exception { + generateActionForTarget(controllerId, true, false, getTestSchedule(2), getTestDuration(1), getTestTimeZone()); + + mockMvc.perform(get( + MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/" + MgmtRestConstants.TARGET_V1_ACTIONS, + controllerId)).andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters( + parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields( + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("content[]").description(MgmtApiModelProperties.ACTION_LIST), + fieldWithPath("content[].createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("content[].createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("content[].lastModifiedBy") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY).type("String"), + fieldWithPath("content[].lastModifiedAt") + .description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("String"), + fieldWithPath("content[].type").description(MgmtApiModelProperties.ACTION_TYPE) + .attributes(key("value").value("['update', 'cancel']")), + + fieldWithPath("content[].status") + .description(MgmtApiModelProperties.ACTION_EXECUTION_STATUS) + .attributes(key("value").value("['finished', 'pending']")), + fieldWithPath("content[]._links").description(MgmtApiModelProperties.LINK_TO_ACTION), + fieldWithPath("content[].id").description(MgmtApiModelProperties.ACTION_ID), + fieldWithPath("content[].maintenanceWindow") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW), + fieldWithPath("content[].maintenanceWindow.schedule") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_SCHEDULE), + fieldWithPath("content[].maintenanceWindow.duration") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_DURATION), + fieldWithPath("content[].maintenanceWindow.timezone") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_TIMEZONE), + fieldWithPath("content[].maintenanceWindow.nextStartAt") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_NEXT_START_AT)))); + } + + @Test + @Description("Handles the GET request of retrieving all targets within SP based by parameter. Required Permission: READ_TARGET.") + public void getActionsFromTargetWithParameters() throws Exception { + generateActionForTarget(controllerId); + + mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + controllerId + "/" + + MgmtRestConstants.TARGET_V1_ACTIONS + "?limit=10&sort=id:ASC&offset=0&q=status==pending")) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(requestParameters( + parameterWithName("limit").attributes(key("type").value("query")) + .description(ApiModelPropertiesGeneric.LIMIT), + parameterWithName("sort").description(ApiModelPropertiesGeneric.SORT), + parameterWithName("offset").description(ApiModelPropertiesGeneric.OFFSET), + parameterWithName("q").description(ApiModelPropertiesGeneric.FIQL)))); + } + + @Test + @Description("Cancels an active action, only active actions can be deleted. Required Permission: UPDATE_TARGET.") + public void deleteActionFromTarget() throws Exception { + final Action actions = generateActionForTarget(controllerId, false); + + mockMvc.perform(delete(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/" + + MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}", controllerId, actions.getId())) + .andExpect(status().isNoContent()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the GET request of retrieving all targets within SP based by parameter. Required Permission: READ_TARGET.") + public void deleteActionsFromTargetWithParameters() throws Exception { + generateActionForTarget(controllerId); + + mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + controllerId + "/" + + MgmtRestConstants.TARGET_V1_ACTIONS + "?force=true")).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()).andDo(this.document.document( + requestParameters(parameterWithName("force").description(MgmtApiModelProperties.FORCE)))); + } + + @Test + @Description("Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET.") + public void getActionFromTarget() throws Exception { + final Action action = generateActionForTarget(controllerId, true, true); + assertThat(deploymentManagement.findAction(action.getId()).get().getActionType()) + .isEqualTo(ActionType.TIMEFORCED); + + mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/" + + MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}", controllerId, action.getId())) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("id").description(MgmtApiModelProperties.ACTION_ID), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY) + .type("String"), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT) + .type("String"), + fieldWithPath("type").description(MgmtApiModelProperties.ACTION_TYPE) + .attributes(key("value").value("['update', 'cancel']")), + fieldWithPath("forceType").description(MgmtApiModelProperties.ACTION_FORCE_TYPE) + .attributes(key("value").value("['forced', 'soft', 'timeforced']")), + fieldWithPath("forceTime").description(MgmtApiModelProperties.ACTION_FORCE_TIME) + .type("String"), + fieldWithPath("status").description(MgmtApiModelProperties.ACTION_EXECUTION_STATUS) + .attributes(key("value").value("['finished', 'pending']")), + fieldWithPath("_links.self").ignored(), + fieldWithPath("_links.distributionset").description(MgmtApiModelProperties.LINK_TO_DS), + fieldWithPath("_links.status") + .description(MgmtApiModelProperties.LINKS_ACTION_STATUSES)))); + } + + @Test + @Description("Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET.") + public void getActionFromTargetWithMaintenanceWindow() throws Exception { + final Action action = generateActionForTarget(controllerId, true, true, getTestSchedule(2), getTestDuration(1), + getTestTimeZone()); + + mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/" + + MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}", controllerId, action.getId())) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("id").description(MgmtApiModelProperties.ACTION_ID), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY) + .type("String"), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT) + .type("String"), + fieldWithPath("type").description(MgmtApiModelProperties.ACTION_TYPE) + .attributes(key("value").value("['update', 'cancel']")), + fieldWithPath("forceType").description(MgmtApiModelProperties.ACTION_FORCE_TYPE) + .attributes(key("value").value("['forced', 'soft', 'timeforced']")), + fieldWithPath("forceTime").description(MgmtApiModelProperties.ACTION_FORCE_TIME) + .type("String"), + fieldWithPath("status").description(MgmtApiModelProperties.ACTION_EXECUTION_STATUS) + .attributes(key("value").value("['finished', 'pending']")), + fieldWithPath("maintenanceWindow") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW), + fieldWithPath("maintenanceWindow.schedule") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_SCHEDULE), + fieldWithPath("maintenanceWindow.duration") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_DURATION), + fieldWithPath("maintenanceWindow.timezone") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_TIMEZONE), + fieldWithPath("maintenanceWindow.nextStartAt") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_NEXT_START_AT), + fieldWithPath("_links.self").ignored(), + fieldWithPath("_links.distributionset").description(MgmtApiModelProperties.LINK_TO_DS), + fieldWithPath("_links.status") + .description(MgmtApiModelProperties.LINKS_ACTION_STATUSES)))); + } + + @Test + @Description("Handles the PUT request to switch an action from soft to forced. Required Permission: UPDATE_TARGET.") + public void switchActionToForced() throws Exception { + final Target target = testdataFactory.createTarget(controllerId); + final DistributionSet set = testdataFactory.createDistributionSet(); + final Long actionId = deploymentManagement + .assignDistributionSet(set.getId(), ActionType.SOFT, 0, Arrays.asList(target.getControllerId())) + .getActions().get(0); + assertThat(deploymentManagement.findAction(actionId).get().getActionType()).isEqualTo(ActionType.SOFT); + + final Map body = new HashMap<>(); + body.put("forceType", "forced"); + + mockMvc.perform(put(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/" + + MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}", controllerId, actionId) + .content(this.objectMapper.writeValueAsString(body)) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters(parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)), + requestFields( + requestFieldWithPath("forceType").description(MgmtApiModelProperties.ACTION_FORCED)), + responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT), + fieldWithPath("id").description(MgmtApiModelProperties.ACTION_ID), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY) + .type("String"), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT) + .type("String"), + fieldWithPath("type").description(MgmtApiModelProperties.ACTION_TYPE) + .attributes(key("value").value("['update', 'cancel']")), + fieldWithPath("forceType").description(MgmtApiModelProperties.ACTION_FORCE_TYPE) + .attributes(key("value").value("['forced', 'soft', 'timeforced']")), + fieldWithPath("status").description(MgmtApiModelProperties.ACTION_EXECUTION_STATUS) + .attributes(key("value").value("['finished', 'pending']")), + fieldWithPath("_links.self").ignored(), + fieldWithPath("_links.distributionset").description(MgmtApiModelProperties.LINK_TO_DS), + fieldWithPath("_links.status") + .description(MgmtApiModelProperties.LINKS_ACTION_STATUSES)))); + } + + @Test + @Description("Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET.") + public void getStatusFromAction() throws Exception { + final Action action = generateActionForTarget(controllerId); + + mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/" + + MgmtRestConstants.TARGET_V1_ACTIONS + "/{actionId}/" + MgmtRestConstants.TARGET_V1_ACTION_STATUS, + controllerId, action.getId())).andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("actionId").description(ApiModelPropertiesGeneric.ITEM_ID)), + responseFields( + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("content[]").description(MgmtApiModelProperties.ACTION_STATUS_LIST), + fieldWithPath("content[].id").description(ApiModelPropertiesGeneric.ITEM_ID), + fieldWithPath("content[].messages") + .description(MgmtApiModelProperties.ACTION_STATUS_MESSAGES).type("String"), + fieldWithPath("content[].reportedAt") + .description(MgmtApiModelProperties.ACTION_STATUS_REPORTED_AT).type("String"), + fieldWithPath("content[].type").description(MgmtApiModelProperties.ACTION_STATUS_TYPE) + .attributes(key("value").value( + "['finished', 'error', 'warning', 'pending', 'running', 'canceled', 'retrieved', 'canceling']"))))); + } + + @Test + @Description("Handles the GET request of retrieving all targets within SP based by parameter. Required Permission: READ_TARGET.") + public void getStatusFromActionWithParameters() throws Exception { + final Action action = generateActionForTarget(controllerId); + + mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + controllerId + "/" + + MgmtRestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + + MgmtRestConstants.TARGET_V1_ACTION_STATUS + "?limit=10&sort=id:ASC&offset=0")) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + requestParameters(parameterWithName("limit").description(ApiModelPropertiesGeneric.LIMIT), + parameterWithName("sort").description(ApiModelPropertiesGeneric.SORT), + parameterWithName("offset").description(ApiModelPropertiesGeneric.OFFSET)))); + } + + @Test + @Description("Handles the GET request of retrieving the assigned distribution set of an specific target. Required Permission: READ_TARGET.") + public void getAssignedDistributionSetFromAction() throws Exception { + generateActionForTarget(controllerId); + + mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/" + + MgmtRestConstants.TARGET_V1_ASSIGNED_DISTRIBUTION_SET, controllerId)).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters( + parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)), + getResponseFieldsDistributionSet(false))); + } + + @Test + @Description("Handles the POST request for assigning a distribution set to a specific target. Required Permission: READ_REPOSITORY and UPDATE_TARGET.") + public void postAssignDistributionSetToTarget() throws Exception { + testdataFactory.createTarget(controllerId); + final DistributionSet set = testdataFactory.createDistributionSet("one"); + + final long forceTime = System.currentTimeMillis(); + final String body = new JSONObject().put("id", set.getId()).put("type", "timeforced") + .put("forcetime", forceTime).put("maintenanceWindow", + getMaintenanceWindow(getTestSchedule(10), getTestDuration(10), getTestTimeZone())) + .toString(); + + mockMvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/" + + MgmtRestConstants.TARGET_V1_ASSIGNED_DISTRIBUTION_SET, controllerId).content(body) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andDo(this.document.document( + pathParameters( + parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)), + requestParameters(parameterWithName("offline") + .description(MgmtApiModelProperties.OFFLINE_UPDATE).optional()), + requestFields(requestFieldWithPath("forcetime").description(MgmtApiModelProperties.FORCETIME), + requestFieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID), + requestFieldWithPath("maintenanceWindow") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW).optional(), + requestFieldWithPath("maintenanceWindow.schedule") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_SCHEDULE).optional(), + requestFieldWithPath("maintenanceWindow.duration") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_DURATION).optional(), + requestFieldWithPath("maintenanceWindow.timezone") + .description(MgmtApiModelProperties.MAINTENANCE_WINDOW_TIMEZONE).optional(), + requestFieldWithPath("type").description(MgmtApiModelProperties.FORCETIME_TYPE) + .attributes(key("value").value("['soft', 'forced','timeforced']"))), + responseFields( + fieldWithPath("assigned").description(MgmtApiModelProperties.DS_NEW_ASSIGNED_TARGETS), + fieldWithPath("alreadyAssigned").type(JsonFieldType.NUMBER) + .description(MgmtApiModelProperties.DS_ALREADY_ASSIGNED_TARGETS), + fieldWithPath("total").type(JsonFieldType.NUMBER) + .description(MgmtApiModelProperties.DS_TOTAL_ASSIGNED_TARGETS)))); + } + + @Test + @Description("Handles the GET request of retrieving the attributes of a specific target. Reponse is a key/value list. Required Permission: READ_TARGET.") + public void getControllerAttributes() throws Exception { + // create target with attributes + final Map knownControllerAttrs = new HashMap<>(); + knownControllerAttrs.put("a", "1"); + knownControllerAttrs.put("b", "2"); + final Target target = testdataFactory.createTarget(controllerId); + controllerManagement.updateControllerAttributes(controllerId, knownControllerAttrs, null); + + // test query target over rest resource + mockMvc.perform( + get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/attributes", target.getName())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath("$.a", equalTo("1"))).andExpect(jsonPath("$.b", equalTo("2"))) + .andDo(this.document.document(pathParameters( + parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the GET request of retrieving the installed distribution set of an specific target. Required Permission: READ_TARGET.") + public void getInstalledDistributionSetFromTarget() throws Exception { + final Target target = createTargetByGivenNameWithAttributes(controllerId, createDistributionSet()); + + mockMvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{controllerId}/" + + MgmtRestConstants.TARGET_V1_INSTALLED_DISTRIBUTION_SET, target.getName())).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters( + parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)), + getResponseFieldsDistributionSet(false))); + } + + private String createTargetJsonForPostRequest(final String controllerId, final String name, + final String description) throws JsonProcessingException { + final Map target = new HashMap<>(); + target.put("controllerId", controllerId); + target.put("description", description); + target.put("name", name); + target.put("address", "https://192.168.0.1"); + target.put("securityToken", "2345678DGGDGFTDzztgf"); + return "[" + this.objectMapper.writeValueAsString(target) + "]"; + } + + private String createJsonTarget(final String controllerId, final String name, final String description) + throws JsonProcessingException { + final Map target = new HashMap<>(); + target.put("controllerId", controllerId); + target.put("description", description); + target.put("name", name); + target.put("address", "https://192.168.0.1"); + target.put("securityToken", "2345678DGGDGFTDzztgf"); + return this.objectMapper.writeValueAsString(target); + } + + private Action generateActionForTarget(final String knownControllerId) throws Exception { + return generateActionForTarget(knownControllerId, true, false, null, null, null); + } + + private Action generateActionForTarget(final String knownControllerId, final boolean inSync) throws Exception { + return generateActionForTarget(knownControllerId, inSync, false, null, null, null); + } + + private Action generateActionForTarget(final String knownControllerId, final boolean inSync, + final boolean timeforced) throws Exception { + return generateActionForTarget(knownControllerId, inSync, timeforced, null, null, null); + } + + private Action generateActionForTarget(final String knownControllerId, final boolean inSync, + final boolean timeforced, final String maintenanceWindowSchedule, final String maintenanceWindowDuration, + final String maintenanceWindowTimeZone) throws Exception { + final PageRequest pageRequest = new PageRequest(0, 1, Direction.ASC, ActionStatusFields.ID.getFieldName()); + + createTargetByGivenNameWithAttributes(knownControllerId, inSync, timeforced, createDistributionSet(), + maintenanceWindowSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone); + + final List actions = deploymentManagement.findActionsAll(pageRequest).getContent(); + + assertThat(actions).hasSize(1); + return actions.get(0); + } +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/TargetTagResourceDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/TargetTagResourceDocumentationTest.java new file mode 100644 index 000000000..7f1e64c23 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/TargetTagResourceDocumentationTest.java @@ -0,0 +1,307 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.mgmt.documentation; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtAssignedTargetRequestBody; +import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtTagRequestBodyPut; +import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.Target; +import org.eclipse.hawkbit.repository.model.TargetTag; +import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation; +import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric; +import org.eclipse.hawkbit.rest.documentation.DocumenationResponseFieldsSnippet; +import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties; +import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.FieldDescriptor; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.restdocs.snippet.Snippet; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +/** + * Documentation generation for Management API for {@link TargetTag}. + * + */ +@Features("Spring Rest Docs Tests - TargetTag") +@Stories("TargetTag Resource") +public class TargetTagResourceDocumentationTest extends AbstractApiRestDocumentation { + + private DistributionSet distributionSet; + + @Override + @Before + public void setUp() { + resourceName = "targettag"; + super.setUp(); + distributionSet = createDistributionSet(); + } + + @Test + @Description("Handles the GET request of retrieving all target tags") + public void getTargetTags() throws Exception { + createTargetTagEntitiy(); + arrayPrefix = "content[]."; + mockMvc.perform(get(MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING)).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(getResponseFieldTargetTag(true, + fieldWithPath("size").type(JsonFieldType.NUMBER).description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("content").description(MgmtApiModelProperties.TARGET_LIST)))); + } + + @Test + @Description("Handles the GET request of retrieving all targets tags within SP based by parameter") + public void getTargetTagsWithParameters() throws Exception { + createTargetTagEntitiy(); + mockMvc.perform(get( + MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING + "?limit=10&sort=name:ASC&offset=0&q=name==targetTag")) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(getFilterRequestParamter())); + } + + @Test + @Description("Handles the GET request of retrieving all target tag within SP. Required Permission: READ_TARGET.") + public void getTargetTag() throws Exception { + final Long tagId = createTargetTagId(); + mockMvc.perform(get(MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING + "/{targetTagId}", tagId)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("targetTagId").description(ApiModelPropertiesGeneric.ITEM_ID)), + getResponseFieldTargetTag(false))); + } + + @Test + @Description(" Handles the POST request of creating new target tags. The request body must always be a list of tags") + public void createTargetTags() throws Exception { + final MgmtTagRequestBodyPut bodyPut = new MgmtTagRequestBodyPut(); + bodyPut.setColour("red"); + bodyPut.setDescription("target tag description"); + bodyPut.setName("target tag"); + final ObjectMapper mapper = new ObjectMapper(); + final String json = mapper.writeValueAsString(Arrays.asList(bodyPut)); + this.mockMvc + .perform(post(MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING).content(json) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isCreated()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(getRequestFieldsTargetTag(true), getResponseFieldTargetTag(true))); + } + + @Test + @Description("Handles the PUT request of updating a single target tag.") + public void updateTagretTag() throws Exception { + final Long tagId = createTargetTagId(); + final MgmtTagRequestBodyPut bodyPut = new MgmtTagRequestBodyPut(); + bodyPut.setColour("red"); + bodyPut.setDescription("target tag description"); + bodyPut.setName("target tag"); + final ObjectMapper mapper = new ObjectMapper(); + final String json = mapper.writeValueAsString(bodyPut); + + this.mockMvc + .perform(put(MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING + "/{targetTagId}", tagId).content(json) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("targetTagId").description(ApiModelPropertiesGeneric.ITEM_ID)), + getRequestFieldsTargetTag(false), getResponseFieldTargetTag(false))); + + } + + @Test + @Description("Handles the DELETE request for a single target tag") + public void deleteTargetTag() throws Exception { + final Long tagId = createTargetTagId(); + this.mockMvc + .perform(delete(MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING + "/{targetTagId}", tagId) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(pathParameters( + parameterWithName("targetTagId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + @Test + @Description("Handles the GET request of retrieving all assigned targets by the given") + public void getAssignedTargets() throws Exception { + final TargetTag tag = createTargetTagEntitiy(); + final Target target = createTargetByGivenNameWithAttributes("Target1", distributionSet); + targetManagement.assignTag(Arrays.asList(target.getControllerId()), tag.getId()); + + arrayPrefix = "content[]."; + this.mockMvc + .perform(get(MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING + + MgmtRestConstants.TARGET_TAG_TARGETS_REQUEST_MAPPING, tag.getId()) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("targetTagId").description(ApiModelPropertiesGeneric.ITEM_ID)), + getResponseFieldTarget(true, + fieldWithPath("size").type(JsonFieldType.NUMBER) + .description(ApiModelPropertiesGeneric.SIZE), + fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), + fieldWithPath("content").description(MgmtApiModelProperties.TARGET_LIST)))); + } + + @Test + @Description("Handles the POST request to toggle the assignment of targets by the given tag id") + public void toggleTagAssignment() throws Exception { + final Target assignTarget = createTargetByGivenNameWithAttributes("AssignedTarget", distributionSet); + final Target unassignTarget = createTargetByGivenNameWithAttributes("UnassignedTarget", distributionSet); + final Long tagId = createTargetTagId(); + final MgmtAssignedTargetRequestBody assignedTargetRequestBody1 = new MgmtAssignedTargetRequestBody(); + assignedTargetRequestBody1 + .setControllerId(createTargetByGivenNameWithAttributes("Target1", distributionSet).getControllerId()); + final ObjectMapper mapper = new ObjectMapper(); + final String json = mapper.writeValueAsString(Arrays.asList(assignedTargetRequestBody1)); + + this.mockMvc + .perform(post(MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING + + MgmtRestConstants.TARGET_TAG_TARGETS_REQUEST_MAPPING + "/toggleTagAssignment", tagId) + .content(json).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("targetTagId").description(ApiModelPropertiesGeneric.ITEM_ID)), + getRequestFieldsTargetAssignment(true), + getResponseAssignmentResult(assignTarget, unassignTarget) + + )); + } + + @Test + @Description("Handles the POST request to assign targets to the given tag id") + public void assignTargets() throws Exception { + final Long tagId = createTargetTagId(); + final MgmtAssignedTargetRequestBody assignedTargetRequestBody1 = new MgmtAssignedTargetRequestBody(); + assignedTargetRequestBody1 + .setControllerId(createTargetByGivenNameWithAttributes("Target1", distributionSet).getControllerId()); + final ObjectMapper mapper = new ObjectMapper(); + final String json = mapper.writeValueAsString(Arrays.asList(assignedTargetRequestBody1)); + + this.mockMvc + .perform(post(MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING + + MgmtRestConstants.TARGET_TAG_TARGETS_REQUEST_MAPPING, tagId).content(json) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("targetTagId").description(ApiModelPropertiesGeneric.ITEM_ID)), + getRequestFieldsTargetAssignment(true), getResponseFieldTarget(true))); + } + + @Test + @Description("Handles the DELETE request to unassign one target from the given tag id") + public void unassignTarget() throws Exception { + final Long tagId = createTargetTagId(); + final Target target = testdataFactory.createTarget(); + + this.mockMvc + .perform(delete( + MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING + + MgmtRestConstants.TARGET_TAG_TARGETS_REQUEST_MAPPING + "/{controllerId}", + tagId, target.getControllerId()).contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("targetTagId").description(ApiModelPropertiesGeneric.ITEM_ID), + parameterWithName("controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)))); + } + + private Snippet getRequestFieldsTargetTag(final boolean isArray) { + final String arrayPrefix = getArrayPrefix(isArray); + + return requestFields(requestFieldWithPath(arrayPrefix + "name").description(ApiModelPropertiesGeneric.NAME), + requestFieldWithPath(arrayPrefix + "description").description(ApiModelPropertiesGeneric.DESCRPTION), + optionalRequestFieldWithPath(arrayPrefix + "colour").description(ApiModelPropertiesGeneric.COLOUR)); + } + + private Snippet getRequestFieldsTargetAssignment(final boolean isArray) { + final String arrayPrefix = getArrayPrefix(isArray); + + return requestFields( + requestFieldWithPath(arrayPrefix + "controllerId").description(ApiModelPropertiesGeneric.ITEM_ID)); + } + + private Snippet getResponseFieldTargetTag(final boolean isArray) throws JsonProcessingException { + return getResponseFieldTargetTag(isArray, new FieldDescriptor[0]); + } + + private Snippet getResponseFieldTargetTag(final boolean isArray, final FieldDescriptor... descriptors) + throws JsonProcessingException { + final String arrayPrefix = getArrayPrefix(isArray); + final List allFieldDescriptor = new ArrayList<>(); + allFieldDescriptor.addAll(Arrays.asList(descriptors)); + + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "id").description(ApiModelPropertiesGeneric.ITEM_ID)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "name").description(ApiModelPropertiesGeneric.NAME)); + allFieldDescriptor + .add(fieldWithPath(arrayPrefix + "description").description(ApiModelPropertiesGeneric.DESCRPTION)); + allFieldDescriptor + .add(fieldWithPath(arrayPrefix + "createdBy").description(ApiModelPropertiesGeneric.CREATED_BY)); + allFieldDescriptor + .add(fieldWithPath(arrayPrefix + "createdAt").description(ApiModelPropertiesGeneric.CREATED_AT)); + allFieldDescriptor.add( + fieldWithPath(arrayPrefix + "lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY)); + allFieldDescriptor.add( + fieldWithPath(arrayPrefix + "lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "colour").description(ApiModelPropertiesGeneric.COLOUR)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.self").ignored()); + + if (!isArray) { + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.assignedTargets") + .description(MgmtApiModelProperties.LINKS_ASSIGNED_TARGETS)); + } + + return new DocumenationResponseFieldsSnippet(allFieldDescriptor); + } + + private Snippet getResponseAssignmentResult(final Target assignTarget, final Target unAssignTarget) + throws JsonProcessingException { + return responseFields( + fieldWithPath("assignedTargets").description(MgmtApiModelProperties.ASSIGNED_TARGETS) + .type("Array[Object]"), + + fieldWithPath("unassignedTargets").description(MgmtApiModelProperties.UN_ASSIGNED_TARGETS) + .type("Array[Object]")); + } + + private TargetTag createTargetTagEntitiy(final String name) { + final TargetTag updateTargetTag = targetTagManagement.create(entityFactory.tag().create().name(name)); + return targetTagManagement.update(entityFactory.tag().update(updateTargetTag.getId()) + .description("My name is " + name).colour("default")); + } + + private TargetTag createTargetTagEntitiy() { + return createTargetTagEntitiy("targetTag"); + } + + private Long createTargetTagId() { + return createTargetTagEntitiy().getId(); + } + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/TenantResourceDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/TenantResourceDocumentationTest.java new file mode 100644 index 000000000..e635e51ce --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/TenantResourceDocumentationTest.java @@ -0,0 +1,177 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.rest.mgmt.documentation; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.hawkbit.im.authentication.SpPermission; +import org.eclipse.hawkbit.mgmt.json.model.system.MgmtSystemTenantConfigurationValueRequest; +import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; +import org.eclipse.hawkbit.repository.model.TenantConfiguration; +import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation; +import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric; +import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties; +import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; +import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties; +import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.FieldDescriptor; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +/** + * Documentation generation for System API for {@link TenantConfiguration}. + */ +@Features("Spring Rest Docs Tests - TenantConfiguration") +@Stories("TenantConfiguration Resource") +public class TenantResourceDocumentationTest extends AbstractApiRestDocumentation { + + protected static final Map CONFIG_ITEM_DESCRIPTIONS = new HashMap<>(); + + static { + CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_ENABLED, + "if the authentication mode 'gateway security token' is enabled."); + CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY, + "the key of the gateway security token."); + CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME, + "the name of the 'authority header'."); + CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_ENABLED, + "if the authentication mode 'authority header' is enabled."); + CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED, + "if the authentication mode 'target security token' is enabled."); + CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, + "the period of time after the SP server will recognize a target, which is not performing pull requests anymore."); + CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.POLLING_TIME_INTERVAL, + "the time intervall between two poll requests of a target."); + CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.MIN_POLLING_TIME_INTERVAL, + "the smallest time intervallpermittet between two poll requests of a target."); + CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.MAINTENANCE_WINDOW_POLL_COUNT, + "the polling interval so that controller tries to poll at least these many times between the last " + + "polling and before start of maintenance window. The polling interval is" + + " bounded by configured pollingTime and minPollingTime. The polling" + + " interval is modified as per following scheme: pollingTime(@time=t) =" + + " (maintenanceWindowStartTime - t)/maintenanceWindowPollCount."); + CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.ANONYMOUS_DOWNLOAD_MODE_ENABLED, + "if the anonymous download mode is enabled."); + CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, + "if autoclose running actions with new Distribution Set assignment is enabled."); + } + + @Autowired + protected TenantConfigurationProperties tenantConfigurationProperties; + + @Override + @Before + public void setUp() { + resourceName = "tenant"; + super.setUp(); + } + + @Test + @Description("Handles GET request for receiving all tenant specific configurations. Required Permission: " + + SpPermission.TENANT_CONFIGURATION) + public void getTenantConfigrations() throws Exception { + + mockMvc.perform(get(MgmtRestConstants.SYSTEM_V1_REQUEST_MAPPING + "/configs/")).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document(responseFields(getTenantConfigurationValuesKeyResponseFields()))); + } + + @Test + @Description("Handles GET request for receiving a tenant specific configuration. Required Permission: " + + SpPermission.TENANT_CONFIGURATION) + public void getTenantConfigration() throws Exception { + mockMvc.perform(get(MgmtRestConstants.SYSTEM_V1_REQUEST_MAPPING + "/configs/{keyName}/", + TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY)).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("keyName").description(MgmtApiModelProperties.CONFIG_PARAM)), + responseFields(getTenantConfigurationValueResponseField()))); + } + + @Test + @Description("Handles PUT request for settings values in tenant specific configuration. Required Permission: " + + SpPermission.TENANT_CONFIGURATION) + public void putTenantConfigration() throws Exception { + + final MgmtSystemTenantConfigurationValueRequest bodyPut = new MgmtSystemTenantConfigurationValueRequest(); + bodyPut.setValue("exampleToken"); + final ObjectMapper mapper = new ObjectMapper(); + final String json = mapper.writeValueAsString(bodyPut); + + mockMvc.perform(put(MgmtRestConstants.SYSTEM_V1_REQUEST_MAPPING + "/configs/{keyName}/", + TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY).content(json) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) + .andDo(this.document.document( + pathParameters(parameterWithName("keyName").description(MgmtApiModelProperties.CONFIG_PARAM)), + requestFields(requestFieldWithPath("value").description(MgmtApiModelProperties.CONFIG_VALUE)), + responseFields(getTenantConfigurationValueResponseField()))); + } + + @Test + @Description("Handles DELETE request deleting a tenant specific configuration. Required Permission: " + + SpPermission.TENANT_CONFIGURATION) + public void deleteTenantConfigration() throws Exception { + mockMvc.perform(delete(MgmtRestConstants.SYSTEM_V1_REQUEST_MAPPING + "/configs/{keyName}/", + TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY)).andExpect(status().isOk()) + .andDo(MockMvcResultPrinter.print()).andDo(this.document.document( + pathParameters(parameterWithName("keyName").description(MgmtApiModelProperties.CONFIG_PARAM)))); + } + + private FieldDescriptor[] getTenantConfigurationValuesKeyResponseFields() { + final List fields = new ArrayList<>(); + for (final TenantConfigurationKey key : tenantConfigurationProperties.getConfigurationKeys()) { + fields.add(fieldWithPath("['" + key.getKeyName() + "']").type(key.getDataType().getSimpleName()) + .description(getTenantConfigurationKeyDescription(key))); + } + return fields.toArray(new FieldDescriptor[fields.size()]); + } + + private FieldDescriptor[] getTenantConfigurationValueResponseField() { + return new FieldDescriptor[] { fieldWithPath("value").description(MgmtApiModelProperties.CONFIG_VALUE), + fieldWithPath("global").description(MgmtApiModelProperties.CONFIG_GLOBAL), + fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY).type("Number").optional(), + fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT).type("String").optional(), + fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT).type("Number") + .optional(), + fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY).type("String") + .optional(), + fieldWithPath("_links.self").ignored() }; + } + + private String getTenantConfigurationKeyDescription(final TenantConfigurationKey key) { + if (!CONFIG_ITEM_DESCRIPTIONS.containsKey(key.getKeyName())) { + throw new IllegalArgumentException("Description for key " + key.getKeyName() + " is missing."); + } + + return "The configuration key '" + key.getKeyName() + "' defines " + + CONFIG_ITEM_DESCRIPTIONS.get(key.getKeyName()); + } + +} diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/resources/org/springframework/restdocs/templates/path-parameters.snippet b/hawkbit-rest/hawkbit-rest-docs/src/test/resources/org/springframework/restdocs/templates/path-parameters.snippet new file mode 100644 index 000000000..067e1fb83 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/resources/org/springframework/restdocs/templates/path-parameters.snippet @@ -0,0 +1,9 @@ +|=== +|Parameter|Description + +{{#parameters}} +|{{name}} +|{{description}} + +{{/parameters}} +|=== \ No newline at end of file diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet b/hawkbit-rest/hawkbit-rest-docs/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet new file mode 100644 index 000000000..eb6d5b353 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/resources/org/springframework/restdocs/templates/request-fields.snippet @@ -0,0 +1,12 @@ +|=== +|Path|Type|Description|Allowed Values|Mandatory + +{{#fields}} +|{{path}} +|{{type}} +|{{description}} +|{{value}} +|{{mandatory}} +{{/fields}} + +|=== \ No newline at end of file diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/resources/org/springframework/restdocs/templates/response-fields.snippet b/hawkbit-rest/hawkbit-rest-docs/src/test/resources/org/springframework/restdocs/templates/response-fields.snippet new file mode 100644 index 000000000..1578cb28f --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/resources/org/springframework/restdocs/templates/response-fields.snippet @@ -0,0 +1,11 @@ +|=== +|Path|Type|Description|Allowed Values + +{{#fields}} +|{{path}} +|{{type}} +|{{description}} +|{{value}} +{{/fields}} + +|=== \ No newline at end of file diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/resources/updateserver-restdocumentation-test.properties b/hawkbit-rest/hawkbit-rest-docs/src/test/resources/updateserver-restdocumentation-test.properties new file mode 100644 index 000000000..827e18805 --- /dev/null +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/resources/updateserver-restdocumentation-test.properties @@ -0,0 +1,37 @@ +# +# Copyright (c) 2018 Bosch Software Innovations GmbH and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# + +hawkbit.controller.pollingTime=12:00:00 +hawkbit.controller.pollingOverdueTime=23:59:59 + +## Configuration for building download URLs - START +# HTTP +hawkbit.artifact.url.protocols.download-http.rel=download-http +hawkbit.artifact.url.protocols.download-http.protocol=http +hawkbit.artifact.url.protocols.download-http.hostname=link-to-cdn.com +hawkbit.artifact.url.protocols.download-http.supports=DMF,DDI +hawkbit.artifact.url.protocols.download-http.ref={protocol}://{hostname}/api/v1/{tenant}/download/controller/{controllerId}/softwaremodules/{softwareModuleId}/filename/{artifactFileName} +hawkbit.artifact.url.protocols.md5sum-http.rel=md5sum-http +hawkbit.artifact.url.protocols.md5sum-http.protocol=${hawkbit.artifact.url.protocols.download-http.protocol} +hawkbit.artifact.url.protocols.md5sum-http.hostname=${hawkbit.artifact.url.protocols.download-http.hostname} +hawkbit.artifact.url.protocols.md5sum-http.supports=DDI +hawkbit.artifact.url.protocols.md5sum-http.ref=${hawkbit.artifact.url.protocols.download-http.ref}.MD5SUM + +# HTTPS +hawkbit.artifact.url.protocols.download.rel=download +hawkbit.artifact.url.protocols.download.protocol=https +hawkbit.artifact.url.protocols.download.hostname=link-to-cdn.com +hawkbit.artifact.url.protocols.download.supports=DMF,DDI +hawkbit.artifact.url.protocols.download.ref={protocol}://{hostname}/api/v1/{tenant}/download/controller/{controllerId}/softwaremodules/{softwareModuleId}/filename/{artifactFileName} +hawkbit.artifact.url.protocols.md5sum.rel=md5sum +hawkbit.artifact.url.protocols.md5sum.protocol=${hawkbit.artifact.url.protocols.download.protocol} +hawkbit.artifact.url.protocols.md5sum.hostname=${hawkbit.artifact.url.protocols.download.hostname} +hawkbit.artifact.url.protocols.md5sum.supports=DDI +hawkbit.artifact.url.protocols.md5sum.ref=${hawkbit.artifact.url.protocols.download.ref}.MD5SUM +## Configuration for building download URLs - END diff --git a/hawkbit-rest/pom.xml b/hawkbit-rest/pom.xml new file mode 100644 index 000000000..380dca928 --- /dev/null +++ b/hawkbit-rest/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + org.eclipse.hawkbit + hawkbit-parent + 0.2.0-SNAPSHOT + + hawkbit-rest-parent + hawkBit :: REST + pom + + + ${project.basedir}/../../target/ + + + + hawkbit-rest-core + hawkbit-mgmt-api + hawkbit-mgmt-resource + hawkbit-ddi-api + hawkbit-ddi-resource + hawkbit-rest-docs + + \ No newline at end of file diff --git a/hawkbit-security-integration/src/test/java/org/eclipse/hawkbit/security/ControllerPreAuthenticatedAnonymousDownloadTest.java b/hawkbit-security-integration/src/test/java/org/eclipse/hawkbit/security/ControllerPreAuthenticatedAnonymousDownloadTest.java index 2f8187a96..ef1705a1f 100644 --- a/hawkbit-security-integration/src/test/java/org/eclipse/hawkbit/security/ControllerPreAuthenticatedAnonymousDownloadTest.java +++ b/hawkbit-security-integration/src/test/java/org/eclipse/hawkbit/security/ControllerPreAuthenticatedAnonymousDownloadTest.java @@ -24,7 +24,6 @@ import ru.yandex.qatools.allure.annotations.Features; import ru.yandex.qatools.allure.annotations.Stories; /** - * @author Michael Hirsch * */ @Features("Unit Tests - Security") diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/footer/TargetFilterCountMessageLabel.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/footer/TargetFilterCountMessageLabel.java index 2356a917a..b24441976 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/footer/TargetFilterCountMessageLabel.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/footer/TargetFilterCountMessageLabel.java @@ -25,8 +25,6 @@ import com.vaadin.ui.Label; import com.vaadin.ui.UI; /** - * @author Venugopal Boodidadinne(RBEI/BSJ) - * * Count message label which display current filter details and details * on pinning. */ diff --git a/pom.xml b/pom.xml index ac9b7969e..f6eaced86 100644 --- a/pom.xml +++ b/pom.xml @@ -33,21 +33,17 @@ hawkbit-core hawkbit-security-core - hawkbit-rest-core - hawkbit-mgmt-api - hawkbit-mgmt-resource - hawkbit-ddi-api - hawkbit-ddi-resource - hawkbit-dmf - hawkbit-repository hawkbit-security-integration hawkbit-http-security - hawkbit-ui + hawkbit-repository hawkbit-artifact-repository-filesystem hawkbit-autoconfigure + hawkbit-ui + hawkbit-rest + hawkbit-dmf hawkbit-test-report hawkbit-runtime - hawkbit-starters + hawkbit-starters