summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gometalinter.json19
-rw-r--r--ChangeLog20
-rw-r--r--Dockerfile24
-rw-r--r--Gopkg.lock362
-rw-r--r--Gopkg.toml18
-rw-r--r--Makefile84
-rw-r--r--artifact_filter_and_sort.go111
-rw-r--r--artifact_info.go54
-rw-r--r--artifact_sort_by.go2
-rw-r--r--artifact_status.go2
-rw-r--r--artifact_type.go2
-rw-r--r--artifactmanager.go3
-rw-r--r--artifacts/artifacts.go11
-rw-r--r--artifacts/artifacts_test.go10
-rw-r--r--artifacts/database/database.go86
-rw-r--r--artifacts/database/database_suite_test.go34
-rw-r--r--artifacts/database/database_test.go446
-rw-r--r--artifacts/database/errors.go10
-rw-r--r--artifacts/database/pagination_test.go96
-rw-r--r--artifacts/downloader/downloader.go2
-rw-r--r--artifacts/downloader/downloader_test.go2
-rw-r--r--cmd/weles-server/main.go40
-rw-r--r--controller/boruter.go4
-rw-r--r--controller/boruterimpl.go15
-rw-r--r--controller/boruterimpl_test.go10
-rw-r--r--controller/controller.go10
-rw-r--r--controller/controller_test.go8
-rw-r--r--controller/downloader.go4
-rw-r--r--controller/downloaderimpl.go6
-rw-r--r--controller/downloaderimpl_test.go10
-rw-r--r--controller/dryader.go4
-rw-r--r--controller/dryaderimpl.go10
-rw-r--r--controller/dryaderimpl_test.go8
-rw-r--r--controller/jobscontroller.go4
-rw-r--r--controller/jobscontrollerimpl.go5
-rw-r--r--controller/jobscontrollerimpl_test.go2
-rw-r--r--controller/mock/boruter.go6
-rw-r--r--controller/mock/downloader.go6
-rw-r--r--controller/mock/dryader.go6
-rw-r--r--controller/mock/jobscontroller.go4
-rw-r--r--controller/mock/mocks_generate.go15
-rw-r--r--controller/mock/parser.go6
-rw-r--r--controller/mock/requests.go304
-rw-r--r--controller/notifier/notification.go2
-rw-r--r--controller/notifier/notifier.go2
-rw-r--r--controller/notifier/notifierimpl.go2
-rw-r--r--controller/notifier/notifierimpl_test.go2
-rw-r--r--controller/parser.go4
-rw-r--r--controller/parserimpl.go4
-rw-r--r--controller/parserimpl_test.go8
-rw-r--r--fixtures/artifactinfo.go21
-rw-r--r--job_filter_and_sort.go111
-rw-r--r--job_sort_by.go11
-rw-r--r--job_status.go2
-rw-r--r--manager/dryad/device_communication_provider_test.go2
-rw-r--r--manager/dryad/dryad_suite_test.go2
-rw-r--r--manager/dryad/mock/mocks_generate.go2
-rw-r--r--manager/dryad/mock/session_provider.go2
-rw-r--r--manager/dryad/reverse_sshfs.go6
-rw-r--r--manager/dryad/session_provider.go13
-rw-r--r--manager/dryad_job.go9
-rw-r--r--manager/dryad_job_manager.go16
-rw-r--r--manager/dryad_job_manager_test.go5
-rw-r--r--manager/dryad_job_runner.go4
-rw-r--r--manager/dryad_job_runner_conf_test.go4
-rw-r--r--manager/dryad_job_runner_fota.go6
-rw-r--r--manager/dryad_job_runner_test.go8
-rw-r--r--manager/dryad_job_test.go4
-rw-r--r--manager/mock/communication_provider.go4
-rw-r--r--manager/mock/dryad_job_runner.go2
-rw-r--r--manager/mock/mocks_generate.go4
-rw-r--r--mock/artifactmanager.go4
-rw-r--r--mock/dryadjobmanager.go4
-rw-r--r--mock/jobmanager.go4
-rw-r--r--mock/mocks_generate.go8
-rw-r--r--mock/parser.go4
-rw-r--r--parser/parser.go4
-rw-r--r--parser/weles_parser_test.go6
-rw-r--r--server/artifact_lister_handler.go92
-rw-r--r--server/artifact_lister_handler_test.go898
-rw-r--r--server/configure_weles.go15
-rw-r--r--server/doc.go2
-rw-r--r--server/embedded_spec.go235
-rw-r--r--server/job_canceler_handler.go4
-rw-r--r--server/job_canceler_handler_test.go4
-rw-r--r--server/job_creator_handler.go4
-rw-r--r--server/job_creator_handler_test.go8
-rw-r--r--server/job_lister_handler.go95
-rw-r--r--server/job_lister_handler_test.go909
-rw-r--r--server/managers.go2
-rw-r--r--server/operations/artifacts/artifact_lister.go88
-rw-r--r--server/operations/artifacts/artifact_lister_parameters.go8
-rw-r--r--server/operations/artifacts/artifact_lister_responses.go2
-rw-r--r--server/operations/general/version.go75
-rw-r--r--server/operations/general/version_parameters.go60
-rw-r--r--server/operations/general/version_responses.go183
-rw-r--r--server/operations/general/version_urlbuilder.go102
-rw-r--r--server/operations/jobs/job_canceler_responses.go2
-rw-r--r--server/operations/jobs/job_creator_responses.go2
-rw-r--r--server/operations/jobs/job_lister.go88
-rw-r--r--server/operations/jobs/job_lister_parameters.go8
-rw-r--r--server/operations/jobs/job_lister_responses.go2
-rw-r--r--server/operations/weles_api.go19
-rw-r--r--server/server.go138
-rw-r--r--server/server_suite_test.go17
-rw-r--r--server/version_handler.go38
-rw-r--r--server/version_handler_test.go84
-rw-r--r--sort_order.go2
-rw-r--r--swagger.yml84
-rw-r--r--version.go125
-rw-r--r--weles.go3
111 files changed, 3050 insertions, 2529 deletions
diff --git a/.gometalinter.json b/.gometalinter.json
index 69ad74a..8f6e983 100644
--- a/.gometalinter.json
+++ b/.gometalinter.json
@@ -13,7 +13,7 @@
"gocyclo",
"gofmt",
"golint",
- "gas",
+ "gosec",
"ineffassign",
"interfacer",
"lll",
@@ -27,6 +27,7 @@
"vet",
"vetshadow"
],
+"Deadline":"5m",
"Vendor":true,
"Cyclo":15,
"Sort":["path","line"],
@@ -38,16 +39,26 @@
"mock",
"server/operations"],
"Exclude":[
- "server.go",
- "embedded_spec.go",
+ "artifact_alias.go",
+ "artifact_description",
+ "artifact_filter",
"artifact_info.go",
+ "artifact_path.go",
"artifact_sort_by.go",
+ "artifact_sorter.go",
"artifact_status.go",
"artifact_type.go",
+ "artifact_uri.go",
"err_response.go",
"job_filter.go",
+ "job_id.go",
"job_info.go",
"job_sort_by.go",
+ "job_sorter.go",
"job_status.go",
- "sort_order.go"]
+ "server/doc.go",
+ "server/embedded_spec.go",
+ "server/server.go",
+ "sort_order.go",
+ "version.go"]
}
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..fe10558
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,20 @@
+Release 0.1.0 - Fri Oct. 12 2018 - Paweł Wieczorek <p.wieczorek2@samsung.com>
+=============================================================================
+* Basic LAVA YAML job description support:
+ - Deploy (including partition mapping)
+ - Boot (with login and prompt variants)
+ - Test (run/push/pull actions)
+* Requesting DUT from Boruta based on "device_type" capability
+* Obtaining and storing job assets and artifacts locally
+* Sharing assets and artifacts with reverse SSHFS
+* Dryad requirements (under /usr/local/bin path):
+ - stm (for power controlling actions: -dut/-ts/-tick)
+ - fota (supporting mapping-based selective flashing)
+ - dut_boot.sh
+ - dut_login.sh
+ - dut_copyto.sh
+ - dut_copyfrom.sh
+ - dut_exec.sh
+* HTTP API v1:
+ - jobs: create new, cancel, list with filtering and sorting (paginated)
+ - artifacts: list with filtering and sorting (paginated)
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..cc4e768
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,24 @@
+FROM golang:1.11.1-stretch
+LABEL maintainer="Alexander Mazuruk <a.mazuruk@samsung.com>"
+
+ENV PROJECT="github.com/SamsungSLAV/weles"
+
+RUN go get -d "${PROJECT}"
+RUN go get -u github.com/golang/dep/cmd/dep
+
+WORKDIR "${GOPATH}/src/${PROJECT}"
+
+# Copy swagger.yml customized by user.
+# Only instance-specific values should be changed:
+# * info section - contact email and terms of service,
+# * host section.
+COPY swagger.yml .
+
+# Build swagger tool.
+RUN make tools
+
+# Regenerate server to include customized swagger.yml.
+RUN make swagger-server-generate
+
+# Build Weles server.
+RUN go build -o /weles cmd/weles-server/main.go
diff --git a/Gopkg.lock b/Gopkg.lock
index f1eba11..d3d858b 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -2,99 +2,156 @@
[[projects]]
+ digest = "1:8e47871087b94913898333f37af26732faaab30cdb41571136cf7aec9921dae7"
name = "github.com/PuerkitoBio/purell"
packages = ["."]
+ pruneopts = ""
revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4"
version = "v1.1.0"
[[projects]]
branch = "master"
+ digest = "1:331a419049c2be691e5ba1d24342fc77c7e767a80c666a18fd8a9f7b82419c1c"
name = "github.com/PuerkitoBio/urlesc"
packages = ["."]
+ pruneopts = ""
revision = "de5bf2ad457846296e2031421a34e2568e304e35"
[[projects]]
+ digest = "1:dddcbd3558fd08155e8a65399c5453777cdc726cce88ea746cee1902ec47819c"
+ name = "github.com/SamsungSLAV/boruta"
+ packages = [
+ ".",
+ "http",
+ "http/client",
+ ]
+ pruneopts = ""
+ revision = "0303d3264d97bc7af3151f570dff6ddc7e1dd900"
+ version = "v0.1.0"
+
+[[projects]]
+ digest = "1:d8a2bb36a048d1571bcc1aee208b61f39dc16c6c53823feffd37449dde162507"
name = "github.com/asaskevich/govalidator"
packages = ["."]
+ pruneopts = ""
revision = "ccb8e960c48f04d6935e72476ae4a51028f9e22f"
version = "v9"
[[projects]]
+ digest = "1:d8ee1b165eb7f4fd9ada718e1e7eeb0bc1fd462592d0bd823df694443f448681"
name = "github.com/coreos/go-oidc"
packages = ["."]
+ pruneopts = ""
revision = "1180514eaf4d9f38d0d19eef639a1d695e066e72"
version = "v2.0.0"
[[projects]]
+ digest = "1:0deddd908b6b4b768cfc272c16ee61e7088a60f7fe2f06c547bd3d8e1f8b8e77"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
- revision = "346938d642f2ec3594ed81d874461961cd0faa76"
- version = "v1.1.0"
+ pruneopts = ""
+ revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
+ version = "v1.1.1"
[[projects]]
+ digest = "1:6098222470fe0172157ce9bbef5d2200df4edde17ee649c5d6e48330e4afa4c6"
name = "github.com/dgrijalva/jwt-go"
packages = ["."]
+ pruneopts = ""
revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
version = "v3.2.0"
[[projects]]
+ digest = "1:582d54fcb7233da8dde1dfd2210a5b9675d0685f84246a8d317b07d680c18b1b"
name = "github.com/docker/go-units"
packages = ["."]
+ pruneopts = ""
revision = "47565b4f722fb6ceae66b95f853feed578a4a51c"
version = "v0.3.3"
[[projects]]
+ digest = "1:eb53021a8aa3f599d29c7102e65026242bdedce998a54837dc67f14b6a97c5fd"
name = "github.com/fsnotify/fsnotify"
packages = ["."]
+ pruneopts = ""
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
version = "v1.4.7"
[[projects]]
+ branch = "master"
+ digest = "1:ff0a3cc34addcbd669622ba0dc8231d4eff046eec7b3eae1ccafd06a901279d3"
+ name = "github.com/globalsign/mgo"
+ packages = [
+ "bson",
+ "internal/json",
+ ]
+ pruneopts = ""
+ revision = "1ca0a4f7cbcbe61c005d1bd43fdd8bb8b71df6bc"
+
+[[projects]]
+ digest = "1:9dddc4d2845064e15a0a0d415d13e5d85b35d4edbf8f5cd218f17ac5a942e9be"
name = "github.com/go-gorp/gorp"
packages = ["."]
+ pruneopts = ""
revision = "6032c66e0f5f155fd56216ed14cbbdd991034605"
version = "v2.1"
[[projects]]
+ digest = "1:1a3295dc941bb4b1eb160dc19766994d3b82c37deba34680000e93e44feb54e0"
name = "github.com/go-openapi/analysis"
- packages = ["."]
- revision = "3c8fe72ed5d307113ef76c7c3035964d7e4d4b73"
- version = "0.15.0"
+ packages = [
+ ".",
+ "internal",
+ ]
+ pruneopts = ""
+ revision = "c701774f4e604d952e4e8c56dee260be696e33c3"
+ version = "v0.17.0"
[[projects]]
+ digest = "1:24fc3668d065e515396e7c89decee9aea6babfdfa104fcaad12c2ecabd428171"
name = "github.com/go-openapi/errors"
packages = ["."]
- revision = "b2b2befaf267d082d779bcef52d682a47c779517"
- version = "0.15.0"
+ pruneopts = ""
+ revision = "d9664f9fab8994271e573ed69cf2adfc09b7a800"
+ version = "v0.17.0"
[[projects]]
+ digest = "1:770f9cb920b44f3684b0ecccaca45209772bfb29ea03354f7c088de58ec2538d"
name = "github.com/go-openapi/inflect"
packages = ["."]
- revision = "b1f6470ffb9c552dc105dd869f16e36ba86ba7d0"
- version = "0.15.0"
+ pruneopts = ""
+ revision = "16a898ed1f4943794fb9b0e7afb7376a7619cf21"
+ version = "v0.17.0"
[[projects]]
+ digest = "1:c8052dcf3ec378a9a6bc4f00ecc10d6d5eb3cc1f8faaf6b2f70f047e8881d446"
name = "github.com/go-openapi/jsonpointer"
packages = ["."]
- revision = "3a0015ad55fa9873f41605d3e8f28cd279c32ab2"
- version = "0.15.0"
+ pruneopts = ""
+ revision = "ef5f0afec364d3b9396b7b77b43dbe26bf1f8004"
+ version = "v0.17.0"
[[projects]]
+ digest = "1:1824e5330b35b2a2418d06aa55629cc59ad454b72e338aa125ba8ff98f16298b"
name = "github.com/go-openapi/jsonreference"
packages = ["."]
- revision = "3fb327e6747da3043567ee86abd02bb6376b6be2"
- version = "0.15.0"
+ pruneopts = ""
+ revision = "8483a886a90412cd6858df4ea3483dce9c8e35a3"
+ version = "v0.17.0"
[[projects]]
+ digest = "1:5cafc6762b1b7fe5ba5dd290c087bab2f88abb9c93dd1d5ae1bc259952c0387e"
name = "github.com/go-openapi/loads"
packages = [
".",
- "fmts"
+ "fmts",
]
- revision = "2a2b323bab96e6b1fdee110e57d959322446e9c9"
- version = "0.15.0"
+ pruneopts = ""
+ revision = "150d36912387ec2f607be674c5be309ddccc0eed"
+ version = "v0.17.0"
[[projects]]
+ digest = "1:f797743ba6bd5da181d715e03030bdb9f3d46614d9cdaee2776fe27de8099a05"
name = "github.com/go-openapi/runtime"
packages = [
".",
@@ -104,70 +161,90 @@
"middleware/denco",
"middleware/header",
"middleware/untyped",
- "security"
+ "security",
]
- revision = "9a3091f566c0811ef4d54b535179bc0fc484a11f"
- version = "0.15.0"
+ pruneopts = ""
+ revision = "231d7876b7019dbcbfc97a7ba764379497b67c1d"
+ version = "v0.17.0"
[[projects]]
+ digest = "1:d4680b89600466e543754c838cbc987ed58b962417a88600881cd0ed88d6b4cc"
name = "github.com/go-openapi/spec"
packages = ["."]
- revision = "bce47c9386f9ecd6b86f450478a80103c3fe1402"
- version = "0.15.0"
+ pruneopts = ""
+ revision = "5bae59e25b21498baea7f9d46e9c147ec106a42e"
+ version = "v0.17.0"
[[projects]]
+ digest = "1:d8d63c2504c5eefe770be2901eed9856b54088ae0a1fad62606b707caf697a20"
name = "github.com/go-openapi/strfmt"
packages = ["."]
- revision = "913ee058e387ac83a67e2d9f13acecdcd5769fc6"
- version = "0.15.0"
+ pruneopts = ""
+ revision = "35fe47352985e13cc75f13120d70d26fd764ed51"
+ version = "v0.17.0"
[[projects]]
+ digest = "1:062de20b7d299ae95c902a5c472c4bc87a2f3ae707751fe155ecf640d99074b4"
name = "github.com/go-openapi/swag"
packages = ["."]
- revision = "2b0bd4f193d011c203529df626a65d63cb8a79e8"
- version = "0.15.0"
+ pruneopts = ""
+ revision = "5899d5c5e619fda5fa86e14795a835f473ca284c"
+ version = "v0.17.0"
[[projects]]
+ digest = "1:3e3802ad256a6bc362935373649a355abe1d1e419bb920f65507abfac3675ae4"
name = "github.com/go-openapi/validate"
packages = ["."]
- revision = "9a6e517cddf1ddd47449be5d06a6a786e51d9986"
- version = "0.15.0"
+ pruneopts = ""
+ revision = "d2eab7d93009e9215fc85b2faa2c2f2a98c2af48"
+ version = "v0.17.0"
[[projects]]
+ digest = "1:844659db7d6734de1a2d16e379193dd4c6a1321de0825b0a73deefd9a479f0c4"
name = "github.com/go-swagger/go-swagger"
packages = ["."]
- revision = "8c101dc8c12c8e25b5803a6376b7b2b7f09a622f"
+ pruneopts = ""
+ revision = "dd867fd63c30269ac217004c102f47a1774d4f5a"
+ version = "0.16.0"
[[projects]]
branch = "master"
+ digest = "1:27e90cc2c86eb646b38cea71507935a6372a09acdd17752fdcf9ca78c7218b6b"
name = "github.com/go-swagger/scan-repo-boundary"
packages = ["makeplans"]
+ pruneopts = ""
revision = "973b3573c01343537efb657a4aeed98262a2634a"
[[projects]]
+ digest = "1:73a7106c799f98af4f3da7552906efc6a2570329f4cd2d2f5fb8f9d6c053ff2f"
name = "github.com/golang/mock"
packages = [
"gomock",
"mockgen",
- "mockgen/model"
+ "mockgen/model",
]
+ pruneopts = ""
revision = "c34cdb4725f4c3844d095133c6e40e448b86589b"
version = "v1.1.1"
[[projects]]
+ digest = "1:3dd078fda7500c341bc26cfbc6c6a34614f295a2457149fc1045cab767cbcf18"
name = "github.com/golang/protobuf"
packages = ["proto"]
- revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
- version = "v1.1.0"
+ pruneopts = ""
+ revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
+ version = "v1.2.0"
[[projects]]
+ digest = "1:66d63ec7b6035984dced87ad37066e5f4ad277c60234a9d9925537248e983200"
name = "github.com/gorilla/handlers"
packages = ["."]
- revision = "90663712d74cb411cbef281bc1e08c19d1a76145"
- version = "v1.3.0"
+ pruneopts = ""
+ revision = "7e0847f9db758cdebd26c149d0ae9d5d0b9c98ce"
+ version = "v1.4.0"
[[projects]]
- branch = "master"
+ digest = "1:d14365c51dd1d34d5c79833ec91413bfbb166be978724f15701e17080dc06dec"
name = "github.com/hashicorp/hcl"
packages = [
".",
@@ -179,57 +256,88 @@
"hcl/token",
"json/parser",
"json/scanner",
- "json/token"
+ "json/token",
]
- revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168"
+ pruneopts = ""
+ revision = "8cb6e5b959231cc1119e43259c4a608f9c51a241"
+ version = "v1.0.0"
[[projects]]
+ digest = "1:b3c5b95e56c06f5aa72cb2500e6ee5f44fcd122872d4fec2023a488e561218bc"
+ name = "github.com/hpcloud/tail"
+ packages = [
+ ".",
+ "ratelimiter",
+ "util",
+ "watch",
+ "winfile",
+ ]
+ pruneopts = ""
+ revision = "a30252cb686a21eb2d0b98132633053ec2f7f1e5"
+ version = "v1.0.0"
+
+[[projects]]
+ digest = "1:ca5c90960520407749b98c49650f54f5f90a667796e85c5ee1597478f702fb91"
name = "github.com/jessevdk/go-flags"
packages = ["."]
+ pruneopts = ""
revision = "c6ca198ec95c841fdb89fc0de7496fed11ab854e"
version = "v1.4.0"
[[projects]]
+ digest = "1:3108ec0946181c60040ff51b811908f89d03e521e2b4ade5ef5c65b3c0e911ae"
name = "github.com/kr/pretty"
packages = ["."]
+ pruneopts = ""
revision = "73f6ac0b30a98e433b289500d779f50c1a6f0712"
version = "v0.1.0"
[[projects]]
+ digest = "1:11b056b4421396ab14e384ab8ab8c2079b03f1e51aa5eb4d9b81f9e0d1aa8fbf"
name = "github.com/kr/text"
packages = ["."]
+ pruneopts = ""
revision = "e2ffdb16a802fe2bb95e2e35ff34f0e53aeef34f"
version = "v0.1.0"
[[projects]]
+ digest = "1:961dc3b1d11f969370533390fdf203813162980c858e1dabe827b60940c909a5"
name = "github.com/magiconair/properties"
packages = ["."]
+ pruneopts = ""
revision = "c2353362d570a7bfa228149c62842019201cfb71"
version = "v1.8.0"
[[projects]]
branch = "master"
+ digest = "1:212bebc561f4f654a653225868b2a97353cd5e160dc0b0bbc7232b06608474ec"
name = "github.com/mailru/easyjson"
packages = [
"buffer",
"jlexer",
- "jwriter"
+ "jwriter",
]
- revision = "3fdea8d05856a0c8df22ed4bc71b3219245e4485"
+ pruneopts = ""
+ revision = "60711f1a8329503b04e1c88535f419d0bb440bff"
[[projects]]
+ digest = "1:bc03901fc8f0965ccba8bc453eae21a9b04f95999eab664c7de6dc7290f4e8f4"
name = "github.com/mattn/go-sqlite3"
packages = ["."]
+ pruneopts = ""
revision = "25ecb14adfc7543176f7d85291ec7dba82c6f7e4"
version = "v1.9.0"
[[projects]]
- branch = "master"
+ digest = "1:bcc46a0fbd9e933087bef394871256b5c60269575bb661935874729c65bbbf60"
name = "github.com/mitchellh/mapstructure"
packages = ["."]
- revision = "bb74f1db0675b241733089d5a1faa5dd8b0ef57b"
+ pruneopts = ""
+ revision = "3536a929edddb9a5b34bd6861dc4a9647cb459fe"
+ version = "v1.1.2"
[[projects]]
+ digest = "1:a7fd918fb5bd2188436785c0424f8a50b4addfedf37a2b14d796be2a927b8007"
name = "github.com/onsi/ginkgo"
packages = [
".",
@@ -250,12 +358,14 @@
"reporters/stenographer",
"reporters/stenographer/support/go-colorable",
"reporters/stenographer/support/go-isatty",
- "types"
+ "types",
]
- revision = "fa5fabab2a1bfbd924faf4c067d07ae414e2aedf"
- version = "v1.5.0"
+ pruneopts = ""
+ revision = "3774a09d95489ccaa16032e0770d08ea77ba6184"
+ version = "v1.6.0"
[[projects]]
+ digest = "1:3ecd0a37c4a90c12a97e31c398cdbc173824351aa891898ee178120bfe71c478"
name = "github.com/onsi/gomega"
packages = [
".",
@@ -269,79 +379,101 @@
"matchers/support/goraph/edge",
"matchers/support/goraph/node",
"matchers/support/goraph/util",
- "types"
+ "types",
]
- revision = "62bff4df71bdbc266561a0caee19f0594b17c240"
- version = "v1.4.0"
+ pruneopts = ""
+ revision = "7615b9433f86a8bdf29709bf288bc4fd0636a369"
+ version = "v1.4.2"
[[projects]]
+ digest = "1:894aef961c056b6d85d12bac890bf60c44e99b46292888bfa66caf529f804457"
name = "github.com/pelletier/go-toml"
packages = ["."]
+ pruneopts = ""
revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194"
version = "v1.2.0"
[[projects]]
branch = "master"
+ digest = "1:de5481dda0c081b66450e391bbb1a5c4435b13e3c0bbf0133ba1a5baeda7b7af"
name = "github.com/pquerna/cachecontrol"
packages = [
".",
- "cacheobject"
+ "cacheobject",
]
+ pruneopts = ""
revision = "1555304b9b35fdd2b425bccf1a5613677705e7d0"
[[projects]]
+ digest = "1:d0431c2fd72e39ee43ea7742322abbc200c3e704c9102c5c3c2e2e667095b0ca"
name = "github.com/spf13/afero"
packages = [
".",
- "mem"
+ "mem",
]
- revision = "787d034dfe70e44075ccc060d346146ef53270ad"
- version = "v1.1.1"
+ pruneopts = ""
+ revision = "d40851caa0d747393da1ffb28f7f9d8b4eeffebd"
+ version = "v1.1.2"
[[projects]]
+ digest = "1:d0b38ba6da419a6d4380700218eeec8623841d44a856bb57369c172fbf692ab4"
name = "github.com/spf13/cast"
packages = ["."]
+ pruneopts = ""
revision = "8965335b8c7107321228e3e3702cab9832751bac"
version = "v1.2.0"
[[projects]]
- branch = "master"
+ digest = "1:9ceffa4ab5f7195ecf18b3a7fff90c837a9ed5e22e66d18069e4bccfe1f52aa0"
name = "github.com/spf13/jwalterweatherman"
packages = ["."]
- revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394"
+ pruneopts = ""
+ revision = "4a4406e478ca629068e7768fc33f3f044173c0a6"
+ version = "v1.0.0"
[[projects]]
+ digest = "1:cbaf13cdbfef0e4734ed8a7504f57fe893d471d62a35b982bf6fb3f036449a66"
name = "github.com/spf13/pflag"
packages = ["."]
- revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
- version = "v1.0.1"
+ pruneopts = ""
+ revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
+ version = "v1.0.3"
[[projects]]
+ digest = "1:1ed7a19588d3b74fc6a45fe89f95aa980a34870342fb9c3183b19cad08b18a1e"
name = "github.com/spf13/viper"
packages = ["."]
- revision = "b5e8006cbee93ec955a89ab31e0e3ce3204f3736"
- version = "v1.0.2"
+ pruneopts = ""
+ revision = "2c12c60302a5a0e62ee102ca9bc996277c2f64f5"
+ version = "v1.2.1"
[[projects]]
+ digest = "1:6024b14a4544c27b8d79a713006b03e474a8e2977f5fe1d01f42ebe530634816"
name = "github.com/tideland/golib"
packages = ["audit"]
+ pruneopts = ""
revision = "b56169c6bd620eeb7cfc4b9b4027fc10d2934c84"
version = "v4.24.2"
[[projects]]
+ digest = "1:e1cd343b3883ced86b6873fe4d2f76799259fba3d1656df6ac0a7fa92644c049"
name = "github.com/toqueteos/webbrowser"
packages = ["."]
+ pruneopts = ""
revision = "3232c91b8ede8ca86e8962981d881af78875542f"
version = "v1.1.0"
[[projects]]
+ digest = "1:8143ea52154df4cf52589d780ad447f625978a4c29713200842ccaa7c532350a"
name = "github.com/tylerb/graceful"
packages = ["."]
+ pruneopts = ""
revision = "4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb"
version = "v1.2.15"
[[projects]]
branch = "master"
+ digest = "1:6914c49eed986dfb8dffb33516fa129c49929d4d873f41e073c83c11c372b870"
name = "golang.org/x/crypto"
packages = [
"curve25519",
@@ -349,13 +481,16 @@
"ed25519/internal/edwards25519",
"internal/chacha20",
"internal/subtle",
+ "pbkdf2",
"poly1305",
- "ssh"
+ "ssh",
]
- revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602"
+ pruneopts = ""
+ revision = "e3636079e1a4c1f337f212cc5cd2aca108f6c900"
[[projects]]
branch = "master"
+ digest = "1:3a3c1b660248c0ec25f00cfb9c6526bd5b0ede4c8bfa2ed56a3f5e7e9d0a19cd"
name = "golang.org/x/net"
packages = [
"context",
@@ -364,26 +499,32 @@
"html/atom",
"html/charset",
"idna",
- "netutil"
+ "netutil",
]
- revision = "d0887baf81f4598189d4e12a37c6da86f0bba4d0"
+ pruneopts = ""
+ revision = "146acd28ed5894421fb5aac80ca93bc1b1f46f87"
[[projects]]
branch = "master"
+ digest = "1:235cb00e80dcf85b78a24be4bbe6c827fb28613b84037a9d524084308a849d91"
name = "golang.org/x/oauth2"
packages = [
".",
- "internal"
+ "internal",
]
- revision = "ef147856a6ddbb60760db74283d2424e98c87bff"
+ pruneopts = ""
+ revision = "c57b0facaced709681d9f90397429b9430a74754"
[[projects]]
branch = "master"
+ digest = "1:a4bda6e065eb3ccf1e6adeaa863cb416e0ae6b43e613f20a8931d52d19dc20e2"
name = "golang.org/x/sys"
packages = ["unix"]
- revision = "1b2967e3c290b7c545b3db0deeda16e9be4f98a2"
+ pruneopts = ""
+ revision = "4497e2df6f9e69048a54498c7affbbec3294ad47"
[[projects]]
+ digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4"
name = "golang.org/x/text"
packages = [
"collate",
@@ -412,24 +553,29 @@
"unicode/cldr",
"unicode/norm",
"unicode/rangetable",
- "width"
+ "width",
]
+ pruneopts = ""
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]]
branch = "master"
+ digest = "1:23317e1e3b6029cdedaf01516baa11cb4fbfe3b5051e24c4b98266345c606487"
name = "golang.org/x/tools"
packages = [
"go/ast/astutil",
"go/buildutil",
+ "go/internal/cgo",
"go/loader",
"imports",
- "internal/fastwalk"
+ "internal/fastwalk",
]
- revision = "18e9dfbf20567d5156dd6f1dd987092c021f7fa6"
+ pruneopts = ""
+ revision = "f60d9635b16a5a57b06eaa119614ba4df421966a"
[[projects]]
+ digest = "1:8c432632a230496c35a15cfdf441436f04c90e724ad99c8463ef0c82bbe93edb"
name = "google.golang.org/appengine"
packages = [
"internal",
@@ -438,39 +584,95 @@
"internal/log",
"internal/remote_api",
"internal/urlfetch",
- "urlfetch"
+ "urlfetch",
]
- revision = "b1f26356af11148e710935ed1ac8a7f5702c7612"
- version = "v1.1.0"
+ pruneopts = ""
+ revision = "ae0ab99deb4dc413a2b4bd6c8bdd0eb67f1e4d06"
+ version = "v1.2.0"
[[projects]]
- branch = "v2"
- name = "gopkg.in/mgo.v2"
- packages = [
- "bson",
- "internal/json"
- ]
- revision = "9856a29383ce1c59f308dd1cf0363a79b5bef6b5"
+ digest = "1:eb53021a8aa3f599d29c7102e65026242bdedce998a54837dc67f14b6a97c5fd"
+ name = "gopkg.in/fsnotify.v1"
+ packages = ["."]
+ pruneopts = ""
+ revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
+ source = "https://github.com/fsnotify/fsnotify/archive/v1.4.7.tar.gz"
+ version = "v1.4.7"
[[projects]]
+ digest = "1:ddc5fa8f9159bea7d1ce58143e6d8fd8054018f7bc3709940aa7f7bc92855ed9"
name = "gopkg.in/square/go-jose.v2"
packages = [
".",
"cipher",
- "json"
+ "json",
]
- revision = "76dd09796242edb5b897103a75df2645c028c960"
- version = "v2.1.6"
+ pruneopts = ""
+ revision = "ef984e69dd356202fd4e4910d4d9c24468bdf0b8"
+ version = "v2.1.9"
[[projects]]
+ branch = "v1"
+ digest = "1:a96d16bd088460f2e0685d46c39bcf1208ba46e0a977be2df49864ec7da447dd"
+ name = "gopkg.in/tomb.v1"
+ packages = ["."]
+ pruneopts = ""
+ revision = "dd632973f1e7218eb1089048e0798ec9ae7dceb8"
+
+[[projects]]
+ digest = "1:f0620375dd1f6251d9973b5f2596228cc8042e887cd7f827e4220bc1ce8c30e2"
name = "gopkg.in/yaml.v2"
packages = ["."]
+ pruneopts = ""
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
version = "v2.2.1"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
- inputs-digest = "a5e864a9f1537b8cb1a6fdceb4224e969cec77a4e1f692f62b019f7f640638b5"
+ input-imports = [
+ "github.com/SamsungSLAV/boruta",
+ "github.com/SamsungSLAV/boruta/http/client",
+ "github.com/coreos/go-oidc",
+ "github.com/davecgh/go-spew/spew",
+ "github.com/dgrijalva/jwt-go",
+ "github.com/docker/go-units",
+ "github.com/go-gorp/gorp",
+ "github.com/go-openapi/analysis",
+ "github.com/go-openapi/errors",
+ "github.com/go-openapi/inflect",
+ "github.com/go-openapi/loads",
+ "github.com/go-openapi/loads/fmts",
+ "github.com/go-openapi/runtime",
+ "github.com/go-openapi/runtime/flagext",
+ "github.com/go-openapi/runtime/middleware",
+ "github.com/go-openapi/runtime/security",
+ "github.com/go-openapi/spec",
+ "github.com/go-openapi/strfmt",
+ "github.com/go-openapi/swag",
+ "github.com/go-openapi/validate",
+ "github.com/go-swagger/go-swagger",
+ "github.com/go-swagger/scan-repo-boundary/makeplans",
+ "github.com/golang/mock/gomock",
+ "github.com/golang/mock/mockgen",
+ "github.com/golang/mock/mockgen/model",
+ "github.com/gorilla/handlers",
+ "github.com/jessevdk/go-flags",
+ "github.com/kr/pretty",
+ "github.com/mattn/go-sqlite3",
+ "github.com/onsi/ginkgo",
+ "github.com/onsi/ginkgo/extensions/table",
+ "github.com/onsi/gomega",
+ "github.com/spf13/pflag",
+ "github.com/spf13/viper",
+ "github.com/tideland/golib/audit",
+ "github.com/toqueteos/webbrowser",
+ "github.com/tylerb/graceful",
+ "golang.org/x/crypto/ssh",
+ "golang.org/x/net/netutil",
+ "golang.org/x/tools/go/loader",
+ "golang.org/x/tools/imports",
+ "gopkg.in/yaml.v2",
+ ]
solver-name = "gps-cdcl"
solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
index e46920b..04fe012 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -32,13 +32,9 @@ required = [
"github.com/tideland/golib/audit"
]
-# Due to lack of go get functionality on tizen.org boruta cannot be managed via dep.
-# Move of the project to github.com is expected to resolve the issue.
-# TODO: remove boruta from ignored after migration.
-ignored = [
- "git.tizen.org/tools/boruta",
- "git.tizen.org/tools/boruta/http/client",
- ]
+[[constraint]]
+name = "github.com/SamsungSLAV/boruta"
+version = "v0.1.0"
[[constraint]]
name = "github.com/golang/mock"
@@ -49,7 +45,13 @@ version = "v1.1.1"
# in other required packages (which do not have stable version tagged)
[[constraint]]
name = "github.com/go-swagger/go-swagger"
-revision = "8c101dc8c12c8e25b5803a6376b7b2b7f09a622f"
+version = "v0.16.0"
+
+
+# https://github.com/golang/dep/issues/1799
+[[override]]
+name = "gopkg.in/fsnotify.v1"
+source = "https://github.com/fsnotify/fsnotify/archive/v1.4.7.tar.gz"
# WARNING!
# Do not uncomment below lines
diff --git a/Makefile b/Makefile
index d0f3dbe..193fd54 100644
--- a/Makefile
+++ b/Makefile
@@ -4,13 +4,18 @@ DEV_TOOLS_DIR = $(BIN_DIR)/dev-tools
DEV_TOOLS = ./vendor/github.com/golang/mock/mockgen ./vendor/github.com/go-swagger/go-swagger/cmd/swagger
MOCKGEN_BIN = $(DEV_TOOLS_DIR)/mockgen
SWAGGER_BIN = $(DEV_TOOLS_DIR)/swagger
+
DEV_TOOLS_BIN = $(MOCKGEN_BIN) $(SWAGGER_BIN)
rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
+
WELES_FILES = $(filter-out *_test.go, $(call rwildcard, , *.go))
SERVER_MAIN = cmd/weles-server/main.go
-SERVER_BIN = $(BIN_DIR)/weles-server
+SERVER_BIN = $(BIN_DIR)/weles
+
+BUILD_DOCKER_IMAGE = weles-build-img
+BUILD_DOCKER_CONTAINER = weles-build
DOC_DIR = doc
SPHINX_DOCKER_IMAGE = weles-doc-image
@@ -20,14 +25,44 @@ SWAGGER_DOCKER_IMAGE = swaggerapi/swagger-codegen-cli
SWAGGER_DOCKER_CONTAINER = weles-swagger-container
SWAGGER_DOCKER_CONTAINER_WORKDIR = /local
-.PHONY: weles
-weles: vendor $(WELES_FILES)
- go build -o $(SERVER_BIN) $(SERVER_MAIN)
+.PHONY: all
+all: docker-build
+
+.PHONY: clean
+clean: clean-docker-build
+
+.PHONY: docker-build
+docker-build: $(SERVER_BIN)
+ docker rm $(BUILD_DOCKER_CONTAINER)
+
+$(SERVER_BIN): docker-container | $(BIN_DIR)
+ docker cp "$(BUILD_DOCKER_CONTAINER):/$(@F)" $(@)
+
+.PHONY: docker-container
+docker-container: docker-build-img
+ docker create --name "$(BUILD_DOCKER_CONTAINER)" "$(BUILD_DOCKER_IMAGE)"
+
+.PHONY: docker-build-img
+docker-build-img:
+ docker build --tag "$(BUILD_DOCKER_IMAGE)" .
+
+$(BIN_DIR):
+ mkdir -p "$(BIN_DIR)"
+
+.PHONY: clean-docker-build
+clean-docker-build:
+ -docker rm $(BUILD_DOCKER_CONTAINER)
+ -docker rmi $(BUILD_DOCKER_IMAGE)
+ -rm -f "$(SERVER_BIN)"
+ -rmdir "$(BIN_DIR)"
-# server recipe generates Weles server code. dep ensure is run after swagger
-# generation to update Gopkg.lock with packages needed to build server.
.PHONY: server
-server: swagger.yml COPYING
+server: vendor $(WELES_FILES)
+ go build -o $(SERVER_BIN) $(SERVER_MAIN)
+
+# dep ensure is run after swagger generation to update Gopkg.lock with packages needed to build server
+.PHONY: swagger-server-generate
+swagger-server-generate: swagger.yml COPYING
./$(DEV_TOOLS_DIR)/swagger generate server \
-A weles \
-f ./swagger.yml \
@@ -36,9 +71,18 @@ server: swagger.yml COPYING
-r ./COPYING \
--flag-strategy pflag \
--exclude-main \
+ --skip-models \
--compatibility-mode=modern
dep ensure
+.PHONY: swagger-models-generate
+swagger-models-generate: swagger.yml COPYING
+ ./$(DEV_TOOLS_DIR)/swagger generate model \
+ -f ./swagger.yml \
+ -m ../weles \
+ -s ./server \
+ -r ./COPYING \
+
.PHONY: docs
docs: docs-swagger docs-sphinx
@@ -92,7 +136,6 @@ clean-docker-swagger:
-docker rm "${SWAGGER_DOCKER_CONTAINER}"
-docker rmi "${SWAGGER_DOCKER_IMAGE}"
-
vendor: Gopkg.lock
dep ensure -v -vendor-only
@@ -103,21 +146,18 @@ Gopkg.lock: Gopkg.toml
dep-update: clean-vendor
dep ensure -update
-# clean-vendor has not been added to vendor dependencies as dep is able to
-# check out appropriate packages on versions set in the Gopkg.lock file.
-# Removing vendor would force dep to re-download all the packages instead of
-# only the missing ones. Global prune is turned off (see Gopkg.toml for
-# explanation) thus vendor recipe will leave unused packages in the vendor/
-# directory. If that bothers you, run sequentially clean-vendor and vendor
-# recipes.
+# clean-vendor has not been added to vendor dependencies as dep is able to check out appropriate
+# packages on versions set in the Gopkg.lock file. Removing vendor would force dep to re-download
+# all the packages instead of only the missing ones. Global prune is turned off (see Gopkg.toml
+# for explanation) thus vendor recipe will leave unused packages in the vendor/ directory. If that
+# bothers you, run sequentially clean-vendor and vendor recipes.
.PHONY: clean-vendor
clean-vendor:
- -rm -rf vendor
+ rm -rf vendor
-# Due to lack of standard approach to naming and separation of both interfaces
-# and generated mock files below recipe does not have any file dependencies and
-# is PHONY. Interface changes should be rare thus it is up to the developer to
-# regenerate mocks after interface changes.
+# Due to lack of standard approach to naming and separation of both interfaces and generated mock files
+# below recipe does not have any file dependencies and is PHONY. Interface changes should be rare thus
+# it is up to the developer to regenerate mocks after interface changes.
.PHONY: mocks
mocks: tools
go generate ./mock
@@ -127,7 +167,7 @@ mocks: tools
.PHONY: tools
tools: vendor $(DEV_TOOLS_BIN)
-# This recipe will rebuild all tools on vendor directory change. Due to short
-# build time it is not treated as issue.
+# This recipe will rebuild all tools on vendor directory change.
+# Due to short build time it is not treated as issue.
$(DEV_TOOLS_DIR)/%: $(DEV_TOOLS)
go build -o $@ $(filter %$(@F),$(DEV_TOOLS))
diff --git a/artifact_filter_and_sort.go b/artifact_filter_and_sort.go
deleted file mode 100644
index f3feda2..0000000
--- a/artifact_filter_and_sort.go
+++ /dev/null
@@ -1,111 +0,0 @@
-// Code generated by go-swagger; DO NOT EDIT.
-
-// Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License
-//
-
-package weles
-
-// This file was generated by the swagger tool.
-// Editing this file might prove futile when you re-run the swagger generate command
-
-import (
- strfmt "github.com/go-openapi/strfmt"
-
- "github.com/go-openapi/errors"
- "github.com/go-openapi/swag"
-)
-
-// ArtifactFilterAndSort Data for filtering and sorting Weles Jobs lists.
-// swagger:model ArtifactFilterAndSort
-type ArtifactFilterAndSort struct {
-
- // filter
- Filter *ArtifactFilter `json:"Filter,omitempty"`
-
- // sorter
- Sorter *ArtifactSorter `json:"Sorter,omitempty"`
-}
-
-// Validate validates this artifact filter and sort
-func (m *ArtifactFilterAndSort) Validate(formats strfmt.Registry) error {
- var res []error
-
- if err := m.validateFilter(formats); err != nil {
- res = append(res, err)
- }
-
- if err := m.validateSorter(formats); err != nil {
- res = append(res, err)
- }
-
- if len(res) > 0 {
- return errors.CompositeValidationError(res...)
- }
- return nil
-}
-
-func (m *ArtifactFilterAndSort) validateFilter(formats strfmt.Registry) error {
-
- if swag.IsZero(m.Filter) { // not required
- return nil
- }
-
- if m.Filter != nil {
- if err := m.Filter.Validate(formats); err != nil {
- if ve, ok := err.(*errors.Validation); ok {
- return ve.ValidateName("Filter")
- }
- return err
- }
- }
-
- return nil
-}
-
-func (m *ArtifactFilterAndSort) validateSorter(formats strfmt.Registry) error {
-
- if swag.IsZero(m.Sorter) { // not required
- return nil
- }
-
- if m.Sorter != nil {
- if err := m.Sorter.Validate(formats); err != nil {
- if ve, ok := err.(*errors.Validation); ok {
- return ve.ValidateName("Sorter")
- }
- return err
- }
- }
-
- return nil
-}
-
-// MarshalBinary interface implementation
-func (m *ArtifactFilterAndSort) MarshalBinary() ([]byte, error) {
- if m == nil {
- return nil, nil
- }
- return swag.WriteJSON(m)
-}
-
-// UnmarshalBinary interface implementation
-func (m *ArtifactFilterAndSort) UnmarshalBinary(b []byte) error {
- var res ArtifactFilterAndSort
- if err := swag.ReadJSON(b, &res); err != nil {
- return err
- }
- *m = res
- return nil
-}
diff --git a/artifact_info.go b/artifact_info.go
index ae5079c..2881773 100644
--- a/artifact_info.go
+++ b/artifact_info.go
@@ -1,5 +1,4 @@
// Code generated by go-swagger; DO NOT EDIT.
-// NOTE: above is not entirely true. see TODO: below.
// Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
//
@@ -34,7 +33,7 @@ import (
type ArtifactInfo struct {
ArtifactDescription
- // ID in the artifacts database
+ // unique identification of the artifact.
ID int64 `json:"ID,omitempty" db:",primarykey, autoincrement"`
// path
@@ -48,12 +47,6 @@ type ArtifactInfo struct {
Timestamp strfmt.DateTime `json:"Timestamp,omitempty"`
}
-// TODO
-// current go-swagger generates broken marshalling and unmarshalling:
-// https://github.com/go-swagger/go-swagger/issues/1617
-// it is commented out as implicit marshalling works fine.
-
-/*
// UnmarshalJSON unmarshals this object from a JSON structure
func (m *ArtifactInfo) UnmarshalJSON(raw []byte) error {
// AO0
@@ -63,6 +56,27 @@ func (m *ArtifactInfo) UnmarshalJSON(raw []byte) error {
}
m.ArtifactDescription = aO0
+ // now for regular properties
+ var propsArtifactInfo struct {
+ ID int64 `json:"ID,omitempty"`
+
+ Path ArtifactPath `json:"Path,omitempty"`
+
+ Status ArtifactStatus `json:"Status,omitempty"`
+
+ Timestamp strfmt.DateTime `json:"Timestamp,omitempty"`
+ }
+ if err := swag.ReadJSON(raw, &propsArtifactInfo); err != nil {
+ return err
+ }
+ m.ID = propsArtifactInfo.ID
+
+ m.Path = propsArtifactInfo.Path
+
+ m.Status = propsArtifactInfo.Status
+
+ m.Timestamp = propsArtifactInfo.Timestamp
+
return nil
}
@@ -76,9 +90,31 @@ func (m ArtifactInfo) MarshalJSON() ([]byte, error) {
}
_parts = append(_parts, aO0)
+ // now for regular properties
+ var propsArtifactInfo struct {
+ ID int64 `json:"ID,omitempty"`
+
+ Path ArtifactPath `json:"Path,omitempty"`
+
+ Status ArtifactStatus `json:"Status,omitempty"`
+
+ Timestamp strfmt.DateTime `json:"Timestamp,omitempty"`
+ }
+ propsArtifactInfo.ID = m.ID
+
+ propsArtifactInfo.Path = m.Path
+
+ propsArtifactInfo.Status = m.Status
+
+ propsArtifactInfo.Timestamp = m.Timestamp
+
+ jsonDataPropsArtifactInfo, errArtifactInfo := swag.WriteJSON(propsArtifactInfo)
+ if errArtifactInfo != nil {
+ return nil, errArtifactInfo
+ }
+ _parts = append(_parts, jsonDataPropsArtifactInfo)
return swag.ConcatJSON(_parts...), nil
}
-*/
// Validate validates this artifact info
func (m *ArtifactInfo) Validate(formats strfmt.Registry) error {
diff --git a/artifact_sort_by.go b/artifact_sort_by.go
index 866532c..2921f0f 100644
--- a/artifact_sort_by.go
+++ b/artifact_sort_by.go
@@ -46,7 +46,7 @@ var artifactSortByEnum []interface{}
func init() {
var res []ArtifactSortBy
- if err := json.Unmarshal([]byte(`["ID"]`), &res); err != nil {
+ if err := json.Unmarshal([]byte(`["ID",""]`), &res); err != nil {
panic(err)
}
for _, v := range res {
diff --git a/artifact_status.go b/artifact_status.go
index 2c30dab..4255c7d 100644
--- a/artifact_status.go
+++ b/artifact_status.go
@@ -62,7 +62,7 @@ var artifactStatusEnum []interface{}
func init() {
var res []ArtifactStatus
- if err := json.Unmarshal([]byte(`["DOWNLOADING","READY","FAILED","PENDING"]`), &res); err != nil {
+ if err := json.Unmarshal([]byte(`["DOWNLOADING","READY","FAILED","PENDING",""]`), &res); err != nil {
panic(err)
}
for _, v := range res {
diff --git a/artifact_type.go b/artifact_type.go
index eada618..608b49f 100644
--- a/artifact_type.go
+++ b/artifact_type.go
@@ -62,7 +62,7 @@ var artifactTypeEnum []interface{}
func init() {
var res []ArtifactType
- if err := json.Unmarshal([]byte(`["IMAGE","RESULT","TEST","YAML"]`), &res); err != nil {
+ if err := json.Unmarshal([]byte(`["IMAGE","RESULT","TEST","YAML",""]`), &res); err != nil {
panic(err)
}
for _, v := range res {
diff --git a/artifactmanager.go b/artifactmanager.go
index 357e066..b130386 100644
--- a/artifactmanager.go
+++ b/artifactmanager.go
@@ -23,7 +23,8 @@ package weles
// It is responsible for downloading job artifacts to ArtifactDB.
type ArtifactManager interface {
// List filters ArtifactDB and returns list of all matching artifacts.
- ListArtifact(filter ArtifactFilter, sorter ArtifactSorter, paginator ArtifactPagination) ([]ArtifactInfo, ListInfo, error) // nolint: lll
+ ListArtifact(filter ArtifactFilter, sorter ArtifactSorter, paginator ArtifactPagination,
+ ) ([]ArtifactInfo, ListInfo, error)
// Push inserts artifact to ArtifactDB and returns its path.
PushArtifact(artifact ArtifactDescription, ch chan ArtifactStatusChange) (ArtifactPath, error)
diff --git a/artifacts/artifacts.go b/artifacts/artifacts.go
index ce6ad2d..5003898 100644
--- a/artifacts/artifacts.go
+++ b/artifacts/artifacts.go
@@ -28,9 +28,9 @@ import (
"github.com/go-openapi/strfmt"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/artifacts/database"
- "git.tizen.org/tools/weles/artifacts/downloader"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/artifacts/database"
+ "github.com/SamsungSLAV/weles/artifacts/downloader"
)
// ArtifactDownloader downloads requested file if there is need to.
@@ -184,6 +184,9 @@ func (s *Storage) getNewPath(ad weles.ArtifactDescription) (weles.ArtifactPath,
func (s *Storage) listenToChanges() {
for change := range s.notifier {
// Error handled in SetStatus function.
- _ = s.db.SetStatus(change) //nolint: gas, gosec
+ err := s.db.SetStatus(change)
+ if err != nil {
+ log.Println("Failed to set status of artifact.")
+ }
}
}
diff --git a/artifacts/artifacts_test.go b/artifacts/artifacts_test.go
index 0333e98..dc9e825 100644
--- a/artifacts/artifacts_test.go
+++ b/artifacts/artifacts_test.go
@@ -27,7 +27,7 @@ import (
"path/filepath"
"strconv"
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
_ "github.com/mattn/go-sqlite3"
. "github.com/onsi/ginkgo"
@@ -281,9 +281,11 @@ With gently smiling jaws!
Expect(string(path)).NotTo(BeAnExistingFile())
}
- ai, err := silverKangaroo.GetArtifactInfo(path)
- Expect(err).ToNot(HaveOccurred())
- Expect(ai.Status).To(Equal(finalStatus))
+ Eventually(func() weles.ArtifactStatus {
+ ai, err := silverKangaroo.GetArtifactInfo(path)
+ Expect(err).ToNot(HaveOccurred())
+ return ai.Status
+ }).Should(Equal(finalStatus))
By("Check if artifact is in ArtifactDB")
Expect(checkPathInDb(path)).To(BeTrue())
diff --git a/artifacts/database/database.go b/artifacts/database/database.go
index 3195b4b..3dead3a 100644
--- a/artifacts/database/database.go
+++ b/artifacts/database/database.go
@@ -23,7 +23,7 @@ import (
"log"
"strings"
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
"github.com/go-gorp/gorp"
// sqlite3 is imported for side-effects and will be used
@@ -37,13 +37,19 @@ type ArtifactDB struct {
dbmap *gorp.DbMap
}
+const (
+ sqlite3BusyTimeout = "?_busy_timeout=5000"
+ sqlite3MaxOpenConn = 1
+)
+
// Open opens database connection.
func (aDB *ArtifactDB) Open(dbPath string) error {
var err error
- aDB.handler, err = sql.Open("sqlite3", dbPath)
+ aDB.handler, err = sql.Open("sqlite3", dbPath+sqlite3BusyTimeout)
if err != nil {
return errors.New(dbOpenFail + err.Error())
}
+ aDB.handler.SetMaxOpenConns(sqlite3MaxOpenConn)
aDB.dbmap = &gorp.DbMap{Db: aDB.handler, Dialect: gorp.SqliteDialect{}}
return aDB.initDB()
@@ -63,8 +69,12 @@ func (aDB *ArtifactDB) Close() error {
}
// InsertArtifactInfo inserts information about artifact to database.
-func (aDB *ArtifactDB) InsertArtifactInfo(ai *weles.ArtifactInfo) error {
- return aDB.dbmap.Insert(ai)
+func (aDB *ArtifactDB) InsertArtifactInfo(ai *weles.ArtifactInfo) (err error) {
+ err = aDB.dbmap.Insert(ai)
+ if err != nil {
+ log.Println("Failed to insert ArtifactInfo: ", err)
+ }
+ return
}
// SelectPath selects artifact from database based on its path.
@@ -80,11 +90,9 @@ func (aDB *ArtifactDB) SelectPath(path weles.ArtifactPath) (weles.ArtifactInfo,
// prepareQuery prepares query based on given filter.
// TODO code duplication
-func prepareQuery(
- filter weles.ArtifactFilter,
- sorter weles.ArtifactSorter,
- paginator weles.ArtifactPagination,
- totalRecords, remainingRecords bool, offset int64) (query string, args []interface{}) {
+func prepareQuery(filter weles.ArtifactFilter, sorter weles.ArtifactSorter,
+ paginator weles.ArtifactPagination, totalRecords, remainingRecords bool, offset int64,
+) (query string, args []interface{}) {
if !totalRecords && !remainingRecords {
query = "select * from artifacts "
@@ -97,8 +105,7 @@ func prepareQuery(
if !totalRecords && paginator.ID != 0 {
if (paginator.Forward && sorter.SortOrder == weles.SortOrderDescending) ||
- (!paginator.Forward && (sorter.SortOrder == weles.SortOrderAscending ||
- sorter.SortOrder == "")) {
+ (!paginator.Forward && sorter.SortOrder == weles.SortOrderAscending) {
conditions = append(conditions, " ID < ? ")
args = append(args, paginator.ID)
} else {
@@ -183,23 +190,34 @@ func (aDB *ArtifactDB) Filter(filter weles.ArtifactFilter, sorter weles.Artifact
if err != nil {
return nil, weles.ListInfo{}, errors.New(whileFilter + dbTransOpenFail + err.Error())
}
+ defer func() {
+ if err != nil {
+ // err should be logged when it occurs.
+ if err2 := trans.Rollback(); err2 != nil {
+ log.Printf("%v occurred when filtering, trying to rollback transaction failed: %v",
+ err, err2)
+ }
+ }
+ }()
queryForTotal, argsForTotal := prepareQuery(filter, sorter, paginator, true, false, 0)
queryForRemaining, argsForRemaining := prepareQuery(filter, sorter, paginator, false, true, 0)
var offset int64
- rr, err = aDB.dbmap.SelectInt(queryForRemaining, argsForRemaining...)
+ rr, err = trans.SelectInt(queryForRemaining, argsForRemaining...)
if err != nil {
return nil, weles.ListInfo{}, errors.New(whileFilter + dbRemainingFail + err.Error())
}
- tr, err = aDB.dbmap.SelectInt(queryForTotal, argsForTotal...)
+ tr, err = trans.SelectInt(queryForTotal, argsForTotal...)
if err != nil {
return nil, weles.ListInfo{}, errors.New(whileFilter + dbTotalFail + err.Error())
}
- // TODO: refactor this file. below is to ignore pagination object when pagination is turned off.
- if paginator.Limit == 0 {
- paginator.Forward = true
- paginator.ID = 0
+
+ if tr == 0 {
+ // err needs to be updated for deferred 'if err!=nil' to catch it and roll back the
+ // not committed transaction
+ err = weles.ErrArtifactNotFound
+ return []weles.ArtifactInfo{}, weles.ListInfo{}, err
}
if !paginator.Forward {
@@ -207,14 +225,12 @@ func (aDB *ArtifactDB) Filter(filter weles.ArtifactFilter, sorter weles.Artifact
}
queryForData, argsForData := prepareQuery(filter, sorter, paginator, false, false, offset)
- _, err = aDB.dbmap.Select(&results, queryForData, argsForData...)
+ _, err = trans.Select(&results, queryForData, argsForData...)
if err != nil {
return nil, weles.ListInfo{}, errors.New(whileFilter + dbArtifactInfoFail + err.Error())
}
if err := trans.Commit(); err != nil {
- return nil,
- weles.ListInfo{},
- errors.New(whileFilter + dbTransCommitFail + err.Error())
+ return nil, weles.ListInfo{}, errors.New(whileFilter + dbTransCommitFail + err.Error())
}
return results,
@@ -225,34 +241,6 @@ func (aDB *ArtifactDB) Filter(filter weles.ArtifactFilter, sorter weles.Artifact
nil
}
-// Select fetches artifacts from ArtifactDB.
-func (aDB *ArtifactDB) Select(arg interface{}) (artifacts []weles.ArtifactInfo, err error) {
- var (
- results []weles.ArtifactInfo
- query string
- )
- // TODO prepare efficient way of executing generic select.
- switch arg.(type) {
- case weles.JobID:
- query = "select * from artifacts where JobID = ?"
- case weles.ArtifactType:
- query = "select * from artifacts where Type = ?"
- case weles.ArtifactAlias:
- query = "select * from artifacts where Alias = ?"
- case weles.ArtifactStatus:
- query = "select * from artifacts where Status = ?"
- default:
- return nil, ErrUnsupportedQueryType
- }
- query += " ORDER BY id"
-
- _, err = aDB.dbmap.Select(&results, query, arg)
- if err != nil {
- return nil, err
- }
- return results, nil
-}
-
// SetStatus changes artifact's status in ArtifactDB.
func (aDB *ArtifactDB) SetStatus(change weles.ArtifactStatusChange) error {
ai, err := aDB.SelectPath(change.Path)
diff --git a/artifacts/database/database_suite_test.go b/artifacts/database/database_suite_test.go
index 1bd072f..4a5eadb 100644
--- a/artifacts/database/database_suite_test.go
+++ b/artifacts/database/database_suite_test.go
@@ -25,7 +25,7 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
- "git.tizen.org/tools/weles/fixtures"
+ "github.com/SamsungSLAV/weles/fixtures"
)
func TestDatabase(t *testing.T) {
@@ -38,26 +38,42 @@ var (
tmpDirPath string
)
+const (
+ dbToRead = "test-db-pagination.db"
+ tmpDirPrefix = "weles-"
+ generatedRecordsCount = 100
+ pageLimit = 30
+ pageCount = generatedRecordsCount/pageLimit + 1
+)
+
var _ = BeforeSuite(func() {
+ var (
+ err error
+ db ArtifactDB
+ )
- var err error
- tmpDirPath, err = ioutil.TempDir("", "weles-")
+ tmpDirPath, err = ioutil.TempDir("", tmpDirPrefix)
Expect(err).ToNot(HaveOccurred())
- err = silverHoneybadger.Open(filepath.Join(tmpDirPath, "test_pagination.db"))
+
+ err = db.Open(filepath.Join(tmpDirPath, dbToRead))
Expect(err).ToNot(HaveOccurred())
- artifacts := fixtures.CreateArtifactInfoSlice(100)
- trans, err := silverHoneybadger.dbmap.Begin()
+ silverHoneybadgerArtifacts := fixtures.CreateArtifactInfoSlice(generatedRecordsCount)
+
+ trans, err := db.dbmap.Begin()
Expect(err).ToNot(HaveOccurred())
- for _, artifact := range artifacts {
- err = silverHoneybadger.InsertArtifactInfo(&artifact)
+
+ for _, artifact := range silverHoneybadgerArtifacts {
+ err = trans.Insert(&artifact)
Expect(err).ToNot(HaveOccurred())
}
trans.Commit()
+ db.Close()
+ err = silverHoneybadger.Open(filepath.Join(tmpDirPath, dbToRead))
+ Expect(err).ToNot(HaveOccurred())
})
var _ = AfterSuite(func() {
-
err := silverHoneybadger.Close()
Expect(err).ToNot(HaveOccurred())
err = os.RemoveAll(tmpDirPath)
diff --git a/artifacts/database/database_test.go b/artifacts/database/database_test.go
index 4f3210e..d1e848c 100644
--- a/artifacts/database/database_test.go
+++ b/artifacts/database/database_test.go
@@ -26,7 +26,7 @@ import (
"github.com/go-openapi/strfmt"
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
@@ -40,8 +40,6 @@ var _ = Describe("ArtifactDB", func() {
invalidStatus weles.ArtifactStatus = "invalidStatus"
invalidType weles.ArtifactType = "invalidType"
invalidAlias weles.ArtifactAlias = "invalidAlias"
- goldenUnicorn ArtifactDB
- tmpDir string
artifact = weles.ArtifactInfo{
ArtifactDescription: weles.ArtifactDescription{
@@ -174,223 +172,303 @@ var _ = Describe("ArtifactDB", func() {
Alias: nil,
}
emptyFilter = weles.ArtifactFilter{}
- //default values of sorter passed by server
- defaultSorter = weles.ArtifactSorter{
+
+ emptyPaginator = weles.ArtifactPagination{}
+
+ descendingSorter = weles.ArtifactSorter{
SortOrder: weles.SortOrderDescending,
SortBy: weles.ArtifactSortByID,
}
- )
-
- jobsInDB := func(job weles.JobID) int64 {
- n, err := goldenUnicorn.dbmap.SelectInt(`SELECT COUNT(*)
- FROM artifacts
- WHERE JobID = ?`, job)
- Expect(err).ToNot(HaveOccurred())
- return n
- }
- BeforeEach(func() {
- var err error
- tmpDir, err = ioutil.TempDir("", "weles-")
- Expect(err).ToNot(HaveOccurred())
- err = goldenUnicorn.Open(filepath.Join(tmpDir, "test.db"))
- Expect(err).ToNot(HaveOccurred())
- })
-
- AfterEach(func() {
- err := goldenUnicorn.Close()
- Expect(err).ToNot(HaveOccurred())
- err = os.RemoveAll(tmpDir)
- Expect(err).ToNot(HaveOccurred())
- })
+ defaultSorter = descendingSorter
- It("should open new database, with artifact table", func() {
- n, err := goldenUnicorn.dbmap.SelectInt(`SELECT COUNT(*)
- FROM sqlite_master
- WHERE name = 'artifacts'
- AND type = 'table'`)
+ ascendingSorter = weles.ArtifactSorter{
+ SortOrder: weles.SortOrderAscending,
+ SortBy: weles.ArtifactSortByID,
+ }
+ )
+ jobInDB := func(job weles.JobID, db ArtifactDB) bool {
+ n, err := db.dbmap.SelectInt(
+ `SELECT COUNT(*)
+ FROM artifacts
+ WHERE JobID = ?`, job)
Expect(err).ToNot(HaveOccurred())
- Expect(n).To(BeNumerically("==", 1))
- })
+ return bool(n > 0)
+ }
- It("should fail to open database on invalid path", func() {
- // sql.Open only validates arguments.
- // db.Ping must be called to check the connection.
- invalidDatabasePath := filepath.Join(tmpDir, "invalid", "test.db")
- err := goldenUnicorn.Open(invalidDatabasePath)
- Expect(err).To(HaveOccurred())
- Expect(invalidDatabasePath).ToNot(BeAnExistingFile())
- })
+ Describe("Not pagination", func() {
- It("should insert new artifact to database", func() {
- Expect(jobsInDB(job)).To(BeNumerically("==", 0))
+ var (
+ goldenUnicorn ArtifactDB
+ tmpDir string
+ )
+ BeforeEach(func() {
+ var err error
+ tmpDir, err = ioutil.TempDir("", tmpDirPrefix)
+ Expect(err).ToNot(HaveOccurred())
+ err = goldenUnicorn.Open(filepath.Join(tmpDir, "test.db"))
+ Expect(err).ToNot(HaveOccurred())
+ })
- err := goldenUnicorn.InsertArtifactInfo(&artifact)
- Expect(err).ToNot(HaveOccurred())
+ AfterEach(func() {
+ err := goldenUnicorn.Close()
+ Expect(err).ToNot(HaveOccurred())
+ err = os.RemoveAll(tmpDir)
+ Expect(err).ToNot(HaveOccurred())
+ })
+ It("should open new database, with artifact table", func() {
+ n, err := goldenUnicorn.dbmap.SelectInt(
+ `SELECT COUNT(*)
+ FROM sqlite_master
+ WHERE name = 'artifacts'
+ AND type = 'table'`)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(n).To(BeNumerically("==", 1))
+ })
- Expect(jobsInDB(artifact.JobID)).To(BeNumerically("==", 1))
- })
+ It("should fail to open database on invalid path", func() {
+ // sql.Open only validates arguments.
+ // db.Ping must be called to check the connection.
+ invalidDatabasePath := filepath.Join(tmpDir, "invalid", "test.db")
+ err := goldenUnicorn.Open(invalidDatabasePath)
+ Expect(err).To(HaveOccurred())
+ Expect(invalidDatabasePath).ToNot(BeAnExistingFile())
+ })
- Describe("SelectPath", func() {
+ It("should insert new artifact to database", func() {
+ Expect(jobInDB(job, goldenUnicorn)).To(BeFalse())
- BeforeEach(func() {
err := goldenUnicorn.InsertArtifactInfo(&artifact)
Expect(err).ToNot(HaveOccurred())
- Expect(jobsInDB(artifact.JobID)).To(BeNumerically("==", 1))
+ Expect(jobInDB(artifact.JobID, goldenUnicorn)).To(BeTrue())
})
- DescribeTable("database selectpath",
- func(path weles.ArtifactPath, expectedErr error, expectedArtifact weles.ArtifactInfo) {
- result, err := goldenUnicorn.SelectPath(path)
-
- if expectedErr != nil {
- Expect(err).To(Equal(expectedErr))
- } else {
+ Describe("SetStatus", func() {
+ BeforeEach(func() {
+ trans, err := goldenUnicorn.dbmap.Begin()
+ Expect(err).ToNot(HaveOccurred())
+ defer trans.Commit()
+ for _, a := range testArtifacts {
+ err := trans.Insert(&a)
Expect(err).ToNot(HaveOccurred())
}
- expectedArtifact.ID = result.ID
- Expect(result).To(Equal(expectedArtifact))
- },
- Entry("retrieve artifact based on path",
- artifact.Path, nil, artifact),
- Entry("retrieve artifact based on invalid path",
- invalidPath, sql.ErrNoRows, weles.ArtifactInfo{}),
- )
- })
+ })
+ DescribeTable("artifact status change",
+ func(change weles.ArtifactStatusChange, expectedErr error) {
+ var a weles.ArtifactInfo
+ err := goldenUnicorn.SetStatus(change)
+ if expectedErr == nil {
+ Expect(err).ToNot(HaveOccurred())
+ a, err = goldenUnicorn.SelectPath(change.Path)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(a.Status).To(Equal(change.NewStatus))
+ } else {
+ Expect(err).To(Equal(expectedErr))
+ a, err = goldenUnicorn.SelectPath(change.Path)
+ Expect(err).To(HaveOccurred())
+ Expect(a).To(Equal(weles.ArtifactInfo{}))
+ }
+ },
+ Entry("change status of artifact not present in ArtifactDB",
+ weles.ArtifactStatusChange{
+ Path: invalidPath,
+ NewStatus: weles.ArtifactStatusDOWNLOADING,
+ },
+ sql.ErrNoRows),
+ Entry("change status of artifact present in ArtifactDB",
+ weles.ArtifactStatusChange{
+ Path: artifact.Path,
+ NewStatus: weles.ArtifactStatusDOWNLOADING,
+ },
+ nil),
+ )
+ })
- Describe("Select", func() {
+ Describe("SelectPath", func() {
- BeforeEach(func() {
- trans, err := goldenUnicorn.dbmap.Begin()
- Expect(err).ToNot(HaveOccurred())
- defer trans.Commit()
- for _, a := range testArtifacts {
- err := trans.Insert(&a)
+ BeforeEach(func() {
+ err := goldenUnicorn.InsertArtifactInfo(&artifact)
Expect(err).ToNot(HaveOccurred())
- }
- })
- DescribeTable("database select",
- func(lookedFor interface{}, expectedErr error, expectedResult ...weles.ArtifactInfo) {
- result, err := goldenUnicorn.Select(lookedFor)
+ Expect(jobInDB(artifact.JobID, goldenUnicorn)).To(BeTrue())
+ })
- if expectedErr != nil {
- Expect(err).To(Equal(expectedErr))
- Expect(result).To(BeNil())
- } else {
- Expect(err).ToNot(HaveOccurred())
- for i := range result {
- Expect(result[i].ArtifactDescription).To(Equal(
- expectedResult[i].ArtifactDescription))
- Expect(result[i].Path).To(Equal(expectedResult[i].Path))
- Expect(result[i].Status).To(Equal(expectedResult[i].Status))
- Expect(result[i].Timestamp).To(Equal(expectedResult[i].Timestamp))
+ DescribeTable("database selectpath",
+ func(path weles.ArtifactPath, expectedErr error,
+ expectedArtifact weles.ArtifactInfo) {
+ result, err := goldenUnicorn.SelectPath(path)
+
+ if expectedErr != nil {
+ Expect(err).To(Equal(expectedErr))
+ } else {
+ Expect(err).ToNot(HaveOccurred())
}
- }
- },
- // types supported by select.
- Entry("select JobID", artifact.JobID, nil, artifact),
- Entry("select Type", weles.ArtifactTypeYAML, nil, aYamlFailed),
- Entry("select Status", weles.ArtifactStatusREADY, nil, aImageReady),
- Entry("select Alias", artifact.Alias, nil, artifact),
- // type bool is not supported by select.
- Entry("select unsupported value", true, ErrUnsupportedQueryType),
- // test query itsef.
- Entry("select multiple entries for JobID", aImageReady.JobID, nil, aImageReady,
- aYamlFailed),
- Entry("select no entries for invalid JobID", invalidJob, nil),
- Entry("select multiple entries for Type", weles.ArtifactTypeIMAGE, nil, artifact,
- aImageReady),
- Entry("select multiple entries for Alias", aImageReady.Alias, nil, aImageReady,
- aYamlFailed),
- Entry("select multiple entries for Status", weles.ArtifactStatusFAILED, nil,
- aYamlFailed, aTestFailed),
- )
- })
+ expectedArtifact.ID = result.ID
+ Expect(result).To(Equal(expectedArtifact))
+ },
+ Entry("retrieve artifact based on path", artifact.Path, nil, artifact),
+ Entry("retrieve artifact based on invalid path", invalidPath, sql.ErrNoRows,
+ weles.ArtifactInfo{}),
+ )
+ })
- Describe("List", func() {
- BeforeEach(func() {
- trans, err := goldenUnicorn.dbmap.Begin()
- Expect(err).ToNot(HaveOccurred())
- defer trans.Commit()
- for _, a := range testArtifacts {
- err := trans.Insert(&a)
+ Describe("List", func() {
+ BeforeEach(func() {
+ trans, err := goldenUnicorn.dbmap.Begin()
Expect(err).ToNot(HaveOccurred())
- }
+ defer trans.Commit()
+ for _, a := range testArtifacts {
+ err := trans.Insert(&a)
+ Expect(err).ToNot(HaveOccurred())
+ }
+ })
+ DescribeTable("list artifacts matching filter",
+ func(filter weles.ArtifactFilter, expected ...weles.ArtifactInfo) {
+ results, _, err := goldenUnicorn.Filter(filter, defaultSorter, emptyPaginator)
+ Expect(err).ToNot(HaveOccurred())
+ //TODO: match all fields except ID.
+ for i := range results {
+ for j := range expected {
+ if results[i].JobID == expected[j].JobID {
+ if results[i].URI == expected[j].URI {
+ expected[j].ID = results[i].ID
+ }
+ }
+ }
+ }
+ Expect(results).To(ConsistOf(expected))
+ },
+ Entry("filter one JobID", oneJobFilter, artifact),
+ Entry("filter more than one JobIDs", twoJobsFilter, artifact, aImageReady,
+ aYamlFailed),
+ Entry("filter one Type", oneTypeFilter, aYamlFailed),
+ Entry("filter more than one Type", twoTypesFilter, aYamlFailed, aTestFailed),
+ Entry("filter one Status", oneStatusFilter, artifact),
+ Entry("filter more than one Status", twoStatusFilter, artifact, aTestFailed,
+ aYamlFailed),
+ Entry("filter one Alias", oneAliasFilter, artifact),
+ Entry("filter more than one Alias", twoAliasFilter, artifact, aImageReady,
+ aYamlFailed),
+ Entry("filter is completly set up", fullFilter, aYamlFailed),
+ Entry("filter is empty", emptyFilter, artifact, aImageReady, aYamlFailed,
+ aTestFailed),
+ )
+
+ DescribeTable("return artifact not found error",
+ func(filter weles.ArtifactFilter, expected ...weles.ArtifactInfo) {
+ _, _, err := goldenUnicorn.Filter(filter, defaultSorter, emptyPaginator)
+ Expect(err).To(Equal(weles.ErrArtifactNotFound))
+ },
+ Entry("filter JobID not in db", noJobFilter),
+ Entry("filter Type not in db", noTypeFilter),
+ Entry("filter Status not in db", noStatusFilter),
+ Entry("filter Alias not in db", noAliasFilter),
+ Entry("no artifact in db matches filter", noMatchFilter),
+ )
})
- DescribeTable("list artifacts matching filter",
- func(filter weles.ArtifactFilter, expected ...weles.ArtifactInfo) {
- results, _, err := goldenUnicorn.Filter(filter, defaultSorter,
- weles.ArtifactPagination{})
+ Describe("Sorting", func() {
+ BeforeEach(func() {
+ trans, err := goldenUnicorn.dbmap.Begin()
Expect(err).ToNot(HaveOccurred())
- //TODO: match all fields except ID.
- for i := range results {
- for j := range expected {
- if results[i].JobID == expected[j].JobID {
- if results[i].URI == expected[j].URI {
- expected[j].ID = results[i].ID
+ defer trans.Commit()
+ for _, a := range testArtifacts {
+ err := trans.Insert(&a)
+ Expect(err).ToNot(HaveOccurred())
+ }
+ })
+ DescribeTable("Should return correctly sorted artifacts",
+ func(sorter weles.ArtifactSorter) {
+ result, _, err := goldenUnicorn.Filter(emptyFilter, sorter, emptyPaginator)
+ Expect(err).ToNot(HaveOccurred())
+ var currID int
+ if sorter.SortOrder == weles.SortOrderAscending {
+ for _, a := range result {
+ if currID == 0 {
+ currID = int(a.ID)
+ continue
}
+ Expect(a.ID).To(BeEquivalentTo(currID + 1))
+ currID = int(a.ID)
+ }
+ } else {
+ for _, a := range result {
+ if currID == 0 {
+ currID = int(a.ID)
+ continue
+ }
+ Expect(a.ID).To(BeEquivalentTo(currID - 1))
+ currID = int(a.ID)
}
}
+ },
+ Entry("By ID, Ascending", ascendingSorter),
+ Entry("By ID, Descending", descendingSorter),
+ )
- }
- Expect(results).To(ConsistOf(expected))
- },
- Entry("filter one JobID", oneJobFilter, artifact),
- Entry("filter more than one JobIDs", twoJobsFilter, artifact, aImageReady, aYamlFailed),
- Entry("filter JobID not in db", noJobFilter),
- Entry("filter one Type", oneTypeFilter, aYamlFailed),
- Entry("filter more than one Type", twoTypesFilter, aYamlFailed, aTestFailed),
- Entry("filter Type not in db", noTypeFilter),
- Entry("filter one Status", oneStatusFilter, artifact),
- Entry("filter more than one Status", twoStatusFilter, artifact, aTestFailed,
- aYamlFailed),
- Entry("filter Status not in db", noStatusFilter),
- Entry("filter one Alias", oneAliasFilter, artifact),
- Entry("filter more than one Alias", twoAliasFilter, artifact, aImageReady, aYamlFailed),
- Entry("filter Alias not in db", noAliasFilter),
- Entry("filter is completly set up", fullFilter, aYamlFailed),
- Entry("no artifact in db matches filter", noMatchFilter),
- Entry("filter is empty", emptyFilter, artifact, aImageReady, aYamlFailed, aTestFailed),
- )
- })
- Describe("SetStatus", func() {
- BeforeEach(func() {
- for _, a := range testArtifacts {
- err := goldenUnicorn.InsertArtifactInfo(&a)
- Expect(err).ToNot(HaveOccurred())
- }
})
- DescribeTable("artifact status change",
- func(change weles.ArtifactStatusChange, expectedErr error) {
+ })
+ Describe("Pagination", func() {
+ Context("Database is filled with generatedRecordsCount records", func() {
+ DescribeTable("paginating through artifacts",
+ func(paginator weles.ArtifactPagination,
+ expectedResponseLength, expectedRemainingRecords int) {
- var a weles.ArtifactInfo
- err := goldenUnicorn.SetStatus(change)
- if expectedErr == nil {
- Expect(err).ToNot(HaveOccurred())
- a, err = goldenUnicorn.SelectPath(change.Path)
+ result, list, err := silverHoneybadger.Filter(
+ emptyFilter, defaultSorter, paginator)
Expect(err).ToNot(HaveOccurred())
- Expect(a.Status).To(Equal(change.NewStatus))
- } else {
- Expect(err).To(Equal(expectedErr))
- a, err = goldenUnicorn.SelectPath(change.Path)
- Expect(err).To(HaveOccurred())
- Expect(a).To(Equal(weles.ArtifactInfo{}))
- }
- },
- Entry("change status of artifact not present in ArtifactDB",
- weles.ArtifactStatusChange{
- Path: invalidPath,
- NewStatus: weles.ArtifactStatusDOWNLOADING,
- },
- sql.ErrNoRows),
- Entry("change status of artifact present in ArtifactDB",
- weles.ArtifactStatusChange{
- Path: artifact.Path,
- NewStatus: weles.ArtifactStatusDOWNLOADING,
+
+ Expect(len(result)).To(BeEquivalentTo(expectedResponseLength))
+ Expect(list.TotalRecords).To(BeEquivalentTo(generatedRecordsCount))
+ Expect(list.RemainingRecords).To(BeEquivalentTo(expectedRemainingRecords))
},
- nil),
- )
+ // please keep in mind that data is sorted in descending order.
+ Entry("first and last page (limit is 0)",
+ weles.ArtifactPagination{ID: 0, Limit: 0, Forward: true},
+ generatedRecordsCount, 0),
+
+ Entry("first page, paginating forward",
+ weles.ArtifactPagination{ID: 0, Limit: pageLimit, Forward: true},
+ pageLimit, (generatedRecordsCount-pageLimit)),
+
+ Entry("second page, paginating forward",
+ weles.ArtifactPagination{
+ ID: (generatedRecordsCount - pageLimit + 1),
+ Limit: pageLimit,
+ Forward: true,
+ },
+ pageLimit,
+ (generatedRecordsCount-(2*pageLimit))),
+
+ Entry("last page, paginating forward",
+ weles.ArtifactPagination{
+ ID: int64(generatedRecordsCount -
+ (pageLimit * int(generatedRecordsCount/pageLimit)) + 1),
+ Limit: pageLimit,
+ Forward: true,
+ },
+ generatedRecordsCount-(pageLimit*(pageCount-1)),
+ 0),
+
+ Entry("second to last page, paginating backward",
+ weles.ArtifactPagination{
+ ID: int64(generatedRecordsCount -
+ (pageLimit * int(generatedRecordsCount/pageLimit))),
+ Limit: pageLimit,
+ Forward: false,
+ },
+ pageLimit,
+ pageLimit*(pageCount-2)),
+
+ Entry("first page, paginating backward",
+ weles.ArtifactPagination{
+ ID: int64(generatedRecordsCount - pageLimit),
+ Limit: pageLimit,
+ Forward: false,
+ },
+ pageLimit,
+ 0),
+ )
+ })
})
})
diff --git a/artifacts/database/errors.go b/artifacts/database/errors.go
index e507305..4322d42 100644
--- a/artifacts/database/errors.go
+++ b/artifacts/database/errors.go
@@ -18,16 +18,6 @@
package database
-import (
- "errors"
-)
-
-var (
- // ErrUnsupportedQueryType is returned when wrong type of argument is passed to
- // ArtifactDB's Select().
- ErrUnsupportedQueryType = errors.New("unsupported argument type")
-)
-
const (
dbOpenFail = "failed to open artifacts database: "
whileFilter = "while filtering, "
diff --git a/artifacts/database/pagination_test.go b/artifacts/database/pagination_test.go
deleted file mode 100644
index 7d128aa..0000000
--- a/artifacts/database/pagination_test.go
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package database
-
-import (
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/ginkgo/extensions/table"
- . "github.com/onsi/gomega"
-
- "git.tizen.org/tools/weles"
-)
-
-//TODO: add some consts and limit 'magic' to multipliers
-
-var _ = Describe("ArtifactDB pagination", func() {
-
- emptyF := weles.ArtifactFilter{}
- //below struct is not empty but filled with default values passed from server.
- descS := weles.ArtifactSorter{
- SortOrder: weles.SortOrderDescending,
- SortBy: weles.ArtifactSortByID,
- }
- ascS := weles.ArtifactSorter{
- SortOrder: weles.SortOrderAscending,
- SortBy: weles.ArtifactSortByID,
- }
- Context("Database is filled with 100 records", func() {
- DescribeTable("paginating through artifacts",
- func(
- filter weles.ArtifactFilter,
- paginator weles.ArtifactPagination,
- sorter weles.ArtifactSorter,
- expectedResponseLength, expectedTotalRecords, expectedRemainingRecords int) {
- result, list, err := silverHoneybadger.Filter(filter, sorter, paginator)
- Expect(err).ToNot(HaveOccurred())
- Expect(len(result)).To(BeEquivalentTo(expectedResponseLength))
- Expect(list.TotalRecords).To(BeEquivalentTo(expectedTotalRecords))
- Expect(list.RemainingRecords).To(BeEquivalentTo(expectedRemainingRecords))
- },
- Entry("p1/1, no limit, forward, sort desc", emptyF,
- weles.ArtifactPagination{Forward: true},
- descS, 100, 100, 0),
- Entry("p1/4, limit 30, forward, sort desc", emptyF,
- weles.ArtifactPagination{Limit: 30, Forward: true},
- descS, 30, 100, 70),
- Entry("p2/4, limit 30, forward, sort desc", emptyF,
- weles.ArtifactPagination{ID: 71, Limit: 30, Forward: true},
- descS, 30, 100, 40),
- Entry("p3/4, limit 30, forward, sort desc", emptyF,
- weles.ArtifactPagination{ID: 41, Limit: 30, Forward: true},
- descS, 30, 100, 10),
- Entry("p4/4, limit 30, forward, sort desc", emptyF,
- weles.ArtifactPagination{ID: 11, Limit: 30, Forward: true},
- descS, 10, 100, 0),
- Entry("p3/4, limit 30, backward, sort desc", emptyF,
- weles.ArtifactPagination{ID: 10, Limit: 30, Forward: false},
- descS, 30, 100, 60),
- Entry("p2/4, limit 30, backward, sort desc", emptyF,
- weles.ArtifactPagination{ID: 40, Limit: 30, Forward: false},
- descS, 30, 100, 30),
- Entry("p1/4, limit 30, backward, sort desc", emptyF,
- weles.ArtifactPagination{ID: 70, Limit: 30, Forward: false},
- descS, 30, 100, 0),
- Entry("p1/1, no limit, forward, sort asc", emptyF,
- weles.ArtifactPagination{Forward: true},
- ascS, 100, 100, 0),
- Entry("1/4, no limit, forward, sort asc", emptyF,
- weles.ArtifactPagination{Limit: 30, Forward: true},
- ascS, 30, 100, 70),
- Entry("p2/4, no limit, forward, sort asc", emptyF,
- weles.ArtifactPagination{ID: 30, Limit: 30, Forward: true},
- ascS, 30, 100, 40),
- Entry("p3/4, no limit, forward, sort asc", emptyF,
- weles.ArtifactPagination{ID: 60, Limit: 30, Forward: true},
- ascS, 30, 100, 10),
- Entry("p4/4, no limit, forward, sort asc", emptyF,
- weles.ArtifactPagination{ID: 90, Limit: 30, Forward: true},
- ascS, 10, 100, 0),
- )
- })
-
-})
diff --git a/artifacts/downloader/downloader.go b/artifacts/downloader/downloader.go
index 3316fe5..af3335d 100644
--- a/artifacts/downloader/downloader.go
+++ b/artifacts/downloader/downloader.go
@@ -25,7 +25,7 @@ import (
"os"
"sync"
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
// Downloader implements ArtifactDownloader interface.
diff --git a/artifacts/downloader/downloader_test.go b/artifacts/downloader/downloader_test.go
index 8c9dec6..4bd390b 100644
--- a/artifacts/downloader/downloader_test.go
+++ b/artifacts/downloader/downloader_test.go
@@ -24,7 +24,7 @@ import (
"os"
"path/filepath"
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
diff --git a/cmd/weles-server/main.go b/cmd/weles-server/main.go
index ede46d9..1d0177b 100644
--- a/cmd/weles-server/main.go
+++ b/cmd/weles-server/main.go
@@ -24,13 +24,14 @@ import (
loads "github.com/go-openapi/loads"
flag "github.com/spf13/pflag"
- "git.tizen.org/tools/boruta/http/client"
- "git.tizen.org/tools/weles/artifacts"
- "git.tizen.org/tools/weles/controller"
- "git.tizen.org/tools/weles/manager"
- "git.tizen.org/tools/weles/parser"
- "git.tizen.org/tools/weles/server"
- "git.tizen.org/tools/weles/server/operations"
+ "github.com/SamsungSLAV/boruta/http/client"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/artifacts"
+ "github.com/SamsungSLAV/weles/controller"
+ "github.com/SamsungSLAV/weles/manager"
+ "github.com/SamsungSLAV/weles/parser"
+ "github.com/SamsungSLAV/weles/server"
+ "github.com/SamsungSLAV/weles/server/operations"
)
var (
@@ -41,6 +42,7 @@ var (
artifactDownloadQueueCap int
activeWorkersCap int
notifierChannelCap int
+ version bool
)
// This file was generated by the swagger tool.
@@ -84,24 +86,24 @@ func main() {
flag.IntVar(&notifierChannelCap, "notifier-channel-cap", 100, "Notifier channel capacity.")
+ flag.BoolVar(&version, "version", false, "Print Weles server version and exit.")
+
//TODO: input validation
flag.Usage = func() {
- fmt.Fprint(os.Stderr, "Usage:\n")
- fmt.Fprint(os.Stderr, " weles-server [OPTIONS]\n\n")
-
- title := "Weles"
- fmt.Fprint(os.Stderr, title+"\n\n")
- desc := "This is a Weles server. " +
- "You can find out more about Weles at [http://tbd.tbd](http://tbd.tbd)."
- if desc != "" {
- fmt.Fprintf(os.Stderr, desc+"\n\n")
- }
- fmt.Fprintln(os.Stderr, flag.CommandLine.FlagUsages())
+ _, _ = fmt.Fprint(os.Stderr,
+ `Usage: `+os.Args[0]+` [OPTIONS]
+Weles is a lightweight testing framework for Boruta, inspired by LAVA.
+You can find out more at weles.rtfd.io`+"\n\n"+flag.CommandLine.FlagUsages())
}
// parse the CLI flags
flag.Parse()
+ if version {
+ fmt.Println("weles version", weles.SrvVersion)
+ os.Exit(0)
+ }
+
var yap parser.Parser
am, err := artifacts.NewArtifactManager(
artifactDBName,
@@ -111,7 +113,7 @@ func main() {
artifactDownloadQueueCap)
exitOnErr("failed to initialize ArtifactManager ", err)
bor := client.NewBorutaClient(borutaAddress)
- djm := manager.NewDryadJobManager()
+ djm := manager.NewDryadJobManager(artifactDBLocation)
jm := controller.NewJobManager(am, &yap, bor, borutaRefreshPeriod, djm)
api := operations.NewWelesAPI(swaggerSpec)
diff --git a/controller/boruter.go b/controller/boruter.go
index e7c9b83..9d112c5 100644
--- a/controller/boruter.go
+++ b/controller/boruter.go
@@ -21,8 +21,8 @@
package controller
import (
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/controller/notifier"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/controller/notifier"
)
// Boruter defines actions run for a Job to request and acquire or release Dryad.
diff --git a/controller/boruterimpl.go b/controller/boruterimpl.go
index 152258e..e9a059a 100644
--- a/controller/boruterimpl.go
+++ b/controller/boruterimpl.go
@@ -22,12 +22,13 @@ package controller
import (
"fmt"
+ "log"
"sync"
"time"
- "git.tizen.org/tools/boruta"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/controller/notifier"
+ "github.com/SamsungSLAV/boruta"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/controller/notifier"
)
// TODO ProlongAccess to Dryad in Boruta, before time expires.
@@ -225,7 +226,7 @@ func (h *BoruterImpl) getCaps(config weles.Config) boruta.Capabilities {
}
return boruta.Capabilities{
- "DeviceType": config.DeviceType,
+ "device_type": config.DeviceType,
}
}
@@ -300,5 +301,9 @@ func (h *BoruterImpl) Release(j weles.JobID) {
if err != nil {
return
}
- _ = h.boruta.CloseRequest(r)
+ err = h.boruta.CloseRequest(r)
+ if err != nil {
+ log.Printf("While processing %d Job, failed to close %d request in Boruta: %s",
+ j, r, err.Error())
+ }
}
diff --git a/controller/boruterimpl_test.go b/controller/boruterimpl_test.go
index f2ea8e1..2a57c2e 100644
--- a/controller/boruterimpl_test.go
+++ b/controller/boruterimpl_test.go
@@ -22,10 +22,10 @@ import (
"sync"
"time"
- "git.tizen.org/tools/boruta"
- "git.tizen.org/tools/weles"
- cmock "git.tizen.org/tools/weles/controller/mock"
- "git.tizen.org/tools/weles/controller/notifier"
+ "github.com/SamsungSLAV/boruta"
+ "github.com/SamsungSLAV/weles"
+ cmock "github.com/SamsungSLAV/weles/controller/mock"
+ "github.com/SamsungSLAV/weles/controller/notifier"
gomock "github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -98,7 +98,7 @@ var _ = Describe("BoruterImpl", func() {
JobTimeout: weles.ValidPeriod(jobTimeout),
},
}
- caps = boruta.Capabilities{"DeviceType": "TestDeviceType"}
+ caps = boruta.Capabilities{"device_type": "TestDeviceType"}
priority = boruta.Priority(7)
})
AfterEach(func() {
diff --git a/controller/controller.go b/controller/controller.go
index d16d373..50b3035 100644
--- a/controller/controller.go
+++ b/controller/controller.go
@@ -26,9 +26,9 @@ import (
"sync"
"time"
- "git.tizen.org/tools/boruta"
+ "github.com/SamsungSLAV/boruta"
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
// Controller binds all major components of Weles and provides logic layer
@@ -165,13 +165,15 @@ func (c *Controller) loop() {
// fail sets Job in FAILED state and if needed stops Job's execution on Dryad
// and releases Dryad to Boruta.
func (c *Controller) fail(j weles.JobID, msg string) {
- _ = c.jobs.SetStatusAndInfo(j, weles.JobStatusFAILED, msg)
+ // errors logged in the SetStatusAndInfo.
+ _ = c.jobs.SetStatusAndInfo(j, weles.JobStatusFAILED, msg) // nolint:gosec
c.dryader.CancelJob(j)
c.boruter.Release(j)
}
// succeed sets Job in COMPLETED state.
func (c *Controller) succeed(j weles.JobID) {
- _ = c.jobs.SetStatusAndInfo(j, weles.JobStatusCOMPLETED, "")
+ // errors logged in the SetStatusAndInfo.
+ _ = c.jobs.SetStatusAndInfo(j, weles.JobStatusCOMPLETED, "") // nolint:gosec
c.boruter.Release(j)
}
diff --git a/controller/controller_test.go b/controller/controller_test.go
index de04e42..8b09d3c 100644
--- a/controller/controller_test.go
+++ b/controller/controller_test.go
@@ -21,10 +21,10 @@ import (
"sync"
"time"
- "git.tizen.org/tools/weles"
- cmock "git.tizen.org/tools/weles/controller/mock"
- "git.tizen.org/tools/weles/controller/notifier"
- mock "git.tizen.org/tools/weles/mock"
+ "github.com/SamsungSLAV/weles"
+ cmock "github.com/SamsungSLAV/weles/controller/mock"
+ "github.com/SamsungSLAV/weles/controller/notifier"
+ mock "github.com/SamsungSLAV/weles/mock"
gomock "github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
diff --git a/controller/downloader.go b/controller/downloader.go
index 0ace5f6..6271141 100644
--- a/controller/downloader.go
+++ b/controller/downloader.go
@@ -20,8 +20,8 @@
package controller
import (
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/controller/notifier"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/controller/notifier"
)
// Downloader defines action run for a Job to download artifacts required to
diff --git a/controller/downloaderimpl.go b/controller/downloaderimpl.go
index 5682d1b..38f1a76 100644
--- a/controller/downloaderimpl.go
+++ b/controller/downloaderimpl.go
@@ -22,8 +22,8 @@ import (
"fmt"
"sync"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/controller/notifier"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/controller/notifier"
)
const (
@@ -213,7 +213,7 @@ func (h *DownloaderImpl) push(j weles.JobID, t weles.ArtifactType, alias, uri st
func (h *DownloaderImpl) pullCreate(j weles.JobID, alias string) (string, error) {
p, err := h.artifacts.CreateArtifact(weles.ArtifactDescription{
JobID: j,
- Type: weles.ArtifactTypeTEST,
+ Type: weles.ArtifactTypeRESULT,
Alias: weles.ArtifactAlias(alias),
})
return string(p), err
diff --git a/controller/downloaderimpl_test.go b/controller/downloaderimpl_test.go
index 6d70c70..447cd76 100644
--- a/controller/downloaderimpl_test.go
+++ b/controller/downloaderimpl_test.go
@@ -21,10 +21,10 @@ import (
"fmt"
"sync"
- "git.tizen.org/tools/weles"
- cmock "git.tizen.org/tools/weles/controller/mock"
- "git.tizen.org/tools/weles/controller/notifier"
- mock "git.tizen.org/tools/weles/mock"
+ "github.com/SamsungSLAV/weles"
+ cmock "github.com/SamsungSLAV/weles/controller/mock"
+ "github.com/SamsungSLAV/weles/controller/notifier"
+ mock "github.com/SamsungSLAV/weles/mock"
gomock "github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -248,7 +248,7 @@ var _ = Describe("DownloaderImpl", func() {
return call
}
defaultCreate := func(successfulEntries int, fail bool) *gomock.Call {
- types := []weles.ArtifactType{weles.ArtifactTypeTEST, weles.ArtifactTypeTEST}
+ types := []weles.ArtifactType{weles.ArtifactTypeRESULT, weles.ArtifactTypeRESULT}
aliases := []weles.ArtifactAlias{"alias_2", "alias_4"}
returnPaths := []weles.ArtifactPath{weles.ArtifactPath(paths[7]),
weles.ArtifactPath(paths[8])}
diff --git a/controller/dryader.go b/controller/dryader.go
index 479314b..1986511 100644
--- a/controller/dryader.go
+++ b/controller/dryader.go
@@ -20,8 +20,8 @@
package controller
import (
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/controller/notifier"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/controller/notifier"
)
// Dryader defines actions for delegating Jobs to DryadJobManager.
diff --git a/controller/dryaderimpl.go b/controller/dryaderimpl.go
index babb7d7..ff305cd 100644
--- a/controller/dryaderimpl.go
+++ b/controller/dryaderimpl.go
@@ -21,10 +21,11 @@ package controller
import (
"fmt"
+ "log"
"sync"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/controller/notifier"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/controller/notifier"
)
// DryaderImpl implements Dryader. It delegates and controls Job execution
@@ -170,5 +171,8 @@ func (h *DryaderImpl) CancelJob(j weles.JobID) {
}
h.remove(j)
- _ = h.djm.Cancel(j)
+ err := h.djm.Cancel(j)
+ if err != nil {
+ log.Printf("Failed to cancel %d Job execution in DryadJobManager.", j)
+ }
}
diff --git a/controller/dryaderimpl_test.go b/controller/dryaderimpl_test.go
index fa9113e..f9ccba0 100644
--- a/controller/dryaderimpl_test.go
+++ b/controller/dryaderimpl_test.go
@@ -20,10 +20,10 @@ import (
"errors"
"net"
- "git.tizen.org/tools/weles"
- cmock "git.tizen.org/tools/weles/controller/mock"
- "git.tizen.org/tools/weles/controller/notifier"
- mock "git.tizen.org/tools/weles/mock"
+ "github.com/SamsungSLAV/weles"
+ cmock "github.com/SamsungSLAV/weles/controller/mock"
+ "github.com/SamsungSLAV/weles/controller/notifier"
+ mock "github.com/SamsungSLAV/weles/mock"
gomock "github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
diff --git a/controller/jobscontroller.go b/controller/jobscontroller.go
index 5a73398..76e3b49 100644
--- a/controller/jobscontroller.go
+++ b/controller/jobscontroller.go
@@ -22,7 +22,7 @@
package controller
import (
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
// Job contains all information about Job embedding public part - JobInfo.
@@ -56,5 +56,5 @@ type JobsController interface {
// - JobPagination containing element after/before which a page should be returned. It also
// contains information about direction of pagination and the size of the returned page which
// must always be set.
- List(filter weles.JobFilter, sorter weles.JobSorter, paginator weles.JobPagination) ([]weles.JobInfo, weles.ListInfo, error) // nolint: lll
+ List(filter weles.JobFilter, sorter weles.JobSorter, paginator weles.JobPagination) ([]weles.JobInfo, weles.ListInfo, error) // nolint:lll
}
diff --git a/controller/jobscontrollerimpl.go b/controller/jobscontrollerimpl.go
index 7b18b1d..dfbdff7 100644
--- a/controller/jobscontrollerimpl.go
+++ b/controller/jobscontrollerimpl.go
@@ -30,7 +30,7 @@ import (
"github.com/go-openapi/strfmt"
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
// JobsControllerImpl structure stores Weles' Jobs data. It controls
@@ -396,7 +396,8 @@ func prepareFilterRegexp(arr []string) (*regexp.Regexp, error) {
var str strings.Builder
str.Grow(size)
for _, s := range arr {
- _, _ = str.WriteString("|(" + s + ")")
+ // WriteString never returns error (as of go 1.11.2) thus err is ignored.
+ _, _ = str.WriteString("|(" + s + ")") // nolint:gosec
}
return regexp.Compile(str.String()[1:])
diff --git a/controller/jobscontrollerimpl_test.go b/controller/jobscontrollerimpl_test.go
index 3cd1376..35eaa73 100644
--- a/controller/jobscontrollerimpl_test.go
+++ b/controller/jobscontrollerimpl_test.go
@@ -27,7 +27,7 @@ import (
strfmt "github.com/go-openapi/strfmt"
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
var _ = Describe("JobsControllerImpl", func() {
diff --git a/controller/mock/boruter.go b/controller/mock/boruter.go
index a464cec..29a2672 100644
--- a/controller/mock/boruter.go
+++ b/controller/mock/boruter.go
@@ -1,12 +1,12 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.tizen.org/tools/weles/controller (interfaces: Boruter)
+// Source: github.com/SamsungSLAV/weles/controller (interfaces: Boruter)
// Package mock is a generated GoMock package.
package mock
import (
- weles "git.tizen.org/tools/weles"
- notifier "git.tizen.org/tools/weles/controller/notifier"
+ weles "github.com/SamsungSLAV/weles"
+ notifier "github.com/SamsungSLAV/weles/controller/notifier"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
diff --git a/controller/mock/downloader.go b/controller/mock/downloader.go
index 011039c..bd624d5 100644
--- a/controller/mock/downloader.go
+++ b/controller/mock/downloader.go
@@ -1,12 +1,12 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.tizen.org/tools/weles/controller (interfaces: Downloader)
+// Source: github.com/SamsungSLAV/weles/controller (interfaces: Downloader)
// Package mock is a generated GoMock package.
package mock
import (
- weles "git.tizen.org/tools/weles"
- notifier "git.tizen.org/tools/weles/controller/notifier"
+ weles "github.com/SamsungSLAV/weles"
+ notifier "github.com/SamsungSLAV/weles/controller/notifier"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
diff --git a/controller/mock/dryader.go b/controller/mock/dryader.go
index 08e77ec..542fa4b 100644
--- a/controller/mock/dryader.go
+++ b/controller/mock/dryader.go
@@ -1,12 +1,12 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.tizen.org/tools/weles/controller (interfaces: Dryader)
+// Source: github.com/SamsungSLAV/weles/controller (interfaces: Dryader)
// Package mock is a generated GoMock package.
package mock
import (
- weles "git.tizen.org/tools/weles"
- notifier "git.tizen.org/tools/weles/controller/notifier"
+ weles "github.com/SamsungSLAV/weles"
+ notifier "github.com/SamsungSLAV/weles/controller/notifier"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
diff --git a/controller/mock/jobscontroller.go b/controller/mock/jobscontroller.go
index f690d4b..ee5266d 100644
--- a/controller/mock/jobscontroller.go
+++ b/controller/mock/jobscontroller.go
@@ -1,11 +1,11 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.tizen.org/tools/weles/controller (interfaces: JobsController)
+// Source: github.com/SamsungSLAV/weles/controller (interfaces: JobsController)
// Package mock is a generated GoMock package.
package mock
import (
- weles "git.tizen.org/tools/weles"
+ weles "github.com/SamsungSLAV/weles"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
diff --git a/controller/mock/mocks_generate.go b/controller/mock/mocks_generate.go
index 044d63b..691995a 100644
--- a/controller/mock/mocks_generate.go
+++ b/controller/mock/mocks_generate.go
@@ -16,17 +16,14 @@
package mock
-//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./jobscontroller.go git.tizen.org/tools/weles/controller JobsController
+//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./jobscontroller.go github.com/SamsungSLAV/weles/controller JobsController
-// TODO: fix relative path to absolute
-// You need to have Boruta checked out next to Weles for below go generate to work.
-// Reflect mode will not work in below case.
-//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./requests.go -source=../../../boruta/boruta.go
+//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./requests.go github.com/SamsungSLAV/boruta Requests
-//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./boruter.go git.tizen.org/tools/weles/controller Boruter
+//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./boruter.go github.com/SamsungSLAV/weles/controller Boruter
-//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./downloader.go git.tizen.org/tools/weles/controller Downloader
+//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./downloader.go github.com/SamsungSLAV/weles/controller Downloader
-//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./dryader.go git.tizen.org/tools/weles/controller Dryader
+//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./dryader.go github.com/SamsungSLAV/weles/controller Dryader
-//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./parser.go git.tizen.org/tools/weles/controller Parser
+//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./parser.go github.com/SamsungSLAV/weles/controller Parser
diff --git a/controller/mock/parser.go b/controller/mock/parser.go
index 70d3d2c..dd49395 100644
--- a/controller/mock/parser.go
+++ b/controller/mock/parser.go
@@ -1,12 +1,12 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.tizen.org/tools/weles/controller (interfaces: Parser)
+// Source: github.com/SamsungSLAV/weles/controller (interfaces: Parser)
// Package mock is a generated GoMock package.
package mock
import (
- weles "git.tizen.org/tools/weles"
- notifier "git.tizen.org/tools/weles/controller/notifier"
+ weles "github.com/SamsungSLAV/weles"
+ notifier "github.com/SamsungSLAV/weles/controller/notifier"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
diff --git a/controller/mock/requests.go b/controller/mock/requests.go
index 2e6c208..8342bd7 100644
--- a/controller/mock/requests.go
+++ b/controller/mock/requests.go
@@ -1,52 +1,16 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: ../../../boruta/boruta.go
+// Source: github.com/SamsungSLAV/boruta (interfaces: Requests)
// Package mock is a generated GoMock package.
package mock
import (
- rsa "crypto/rsa"
- boruta "git.tizen.org/tools/boruta"
+ boruta "github.com/SamsungSLAV/boruta"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
time "time"
)
-// MockListFilter is a mock of ListFilter interface
-type MockListFilter struct {
- ctrl *gomock.Controller
- recorder *MockListFilterMockRecorder
-}
-
-// MockListFilterMockRecorder is the mock recorder for MockListFilter
-type MockListFilterMockRecorder struct {
- mock *MockListFilter
-}
-
-// NewMockListFilter creates a new mock instance
-func NewMockListFilter(ctrl *gomock.Controller) *MockListFilter {
- mock := &MockListFilter{ctrl: ctrl}
- mock.recorder = &MockListFilterMockRecorder{mock}
- return mock
-}
-
-// EXPECT returns an object that allows the caller to indicate expected use
-func (m *MockListFilter) EXPECT() *MockListFilterMockRecorder {
- return m.recorder
-}
-
-// Match mocks base method
-func (m *MockListFilter) Match(req *boruta.ReqInfo) bool {
- ret := m.ctrl.Call(m, "Match", req)
- ret0, _ := ret[0].(bool)
- return ret0
-}
-
-// Match indicates an expected call of Match
-func (mr *MockListFilterMockRecorder) Match(req interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Match", reflect.TypeOf((*MockListFilter)(nil).Match), req)
-}
-
// MockRequests is a mock of Requests interface
type MockRequests struct {
ctrl *gomock.Controller
@@ -70,282 +34,90 @@ func (m *MockRequests) EXPECT() *MockRequestsMockRecorder {
return m.recorder
}
-// NewRequest mocks base method
-func (m *MockRequests) NewRequest(caps boruta.Capabilities, priority boruta.Priority, owner boruta.UserInfo, validAfter, deadline time.Time) (boruta.ReqID, error) {
- ret := m.ctrl.Call(m, "NewRequest", caps, priority, owner, validAfter, deadline)
- ret0, _ := ret[0].(boruta.ReqID)
+// AcquireWorker mocks base method
+func (m *MockRequests) AcquireWorker(arg0 boruta.ReqID) (boruta.AccessInfo, error) {
+ ret := m.ctrl.Call(m, "AcquireWorker", arg0)
+ ret0, _ := ret[0].(boruta.AccessInfo)
ret1, _ := ret[1].(error)
return ret0, ret1
}
-// NewRequest indicates an expected call of NewRequest
-func (mr *MockRequestsMockRecorder) NewRequest(caps, priority, owner, validAfter, deadline interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewRequest", reflect.TypeOf((*MockRequests)(nil).NewRequest), caps, priority, owner, validAfter, deadline)
+// AcquireWorker indicates an expected call of AcquireWorker
+func (mr *MockRequestsMockRecorder) AcquireWorker(arg0 interface{}) *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AcquireWorker", reflect.TypeOf((*MockRequests)(nil).AcquireWorker), arg0)
}
// CloseRequest mocks base method
-func (m *MockRequests) CloseRequest(reqID boruta.ReqID) error {
- ret := m.ctrl.Call(m, "CloseRequest", reqID)
+func (m *MockRequests) CloseRequest(arg0 boruta.ReqID) error {
+ ret := m.ctrl.Call(m, "CloseRequest", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// CloseRequest indicates an expected call of CloseRequest
-func (mr *MockRequestsMockRecorder) CloseRequest(reqID interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseRequest", reflect.TypeOf((*MockRequests)(nil).CloseRequest), reqID)
-}
-
-// UpdateRequest mocks base method
-func (m *MockRequests) UpdateRequest(reqInfo *boruta.ReqInfo) error {
- ret := m.ctrl.Call(m, "UpdateRequest", reqInfo)
- ret0, _ := ret[0].(error)
- return ret0
-}
-
-// UpdateRequest indicates an expected call of UpdateRequest
-func (mr *MockRequestsMockRecorder) UpdateRequest(reqInfo interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateRequest", reflect.TypeOf((*MockRequests)(nil).UpdateRequest), reqInfo)
+func (mr *MockRequestsMockRecorder) CloseRequest(arg0 interface{}) *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseRequest", reflect.TypeOf((*MockRequests)(nil).CloseRequest), arg0)
}
// GetRequestInfo mocks base method
-func (m *MockRequests) GetRequestInfo(reqID boruta.ReqID) (boruta.ReqInfo, error) {
- ret := m.ctrl.Call(m, "GetRequestInfo", reqID)
+func (m *MockRequests) GetRequestInfo(arg0 boruta.ReqID) (boruta.ReqInfo, error) {
+ ret := m.ctrl.Call(m, "GetRequestInfo", arg0)
ret0, _ := ret[0].(boruta.ReqInfo)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetRequestInfo indicates an expected call of GetRequestInfo
-func (mr *MockRequestsMockRecorder) GetRequestInfo(reqID interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRequestInfo", reflect.TypeOf((*MockRequests)(nil).GetRequestInfo), reqID)
+func (mr *MockRequestsMockRecorder) GetRequestInfo(arg0 interface{}) *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRequestInfo", reflect.TypeOf((*MockRequests)(nil).GetRequestInfo), arg0)
}
// ListRequests mocks base method
-func (m *MockRequests) ListRequests(filter boruta.ListFilter) ([]boruta.ReqInfo, error) {
- ret := m.ctrl.Call(m, "ListRequests", filter)
+func (m *MockRequests) ListRequests(arg0 boruta.ListFilter) ([]boruta.ReqInfo, error) {
+ ret := m.ctrl.Call(m, "ListRequests", arg0)
ret0, _ := ret[0].([]boruta.ReqInfo)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ListRequests indicates an expected call of ListRequests
-func (mr *MockRequestsMockRecorder) ListRequests(filter interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListRequests", reflect.TypeOf((*MockRequests)(nil).ListRequests), filter)
+func (mr *MockRequestsMockRecorder) ListRequests(arg0 interface{}) *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListRequests", reflect.TypeOf((*MockRequests)(nil).ListRequests), arg0)
}
-// AcquireWorker mocks base method
-func (m *MockRequests) AcquireWorker(reqID boruta.ReqID) (boruta.AccessInfo, error) {
- ret := m.ctrl.Call(m, "AcquireWorker", reqID)
- ret0, _ := ret[0].(boruta.AccessInfo)
+// NewRequest mocks base method
+func (m *MockRequests) NewRequest(arg0 boruta.Capabilities, arg1 boruta.Priority, arg2 boruta.UserInfo, arg3, arg4 time.Time) (boruta.ReqID, error) {
+ ret := m.ctrl.Call(m, "NewRequest", arg0, arg1, arg2, arg3, arg4)
+ ret0, _ := ret[0].(boruta.ReqID)
ret1, _ := ret[1].(error)
return ret0, ret1
}
-// AcquireWorker indicates an expected call of AcquireWorker
-func (mr *MockRequestsMockRecorder) AcquireWorker(reqID interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AcquireWorker", reflect.TypeOf((*MockRequests)(nil).AcquireWorker), reqID)
+// NewRequest indicates an expected call of NewRequest
+func (mr *MockRequestsMockRecorder) NewRequest(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewRequest", reflect.TypeOf((*MockRequests)(nil).NewRequest), arg0, arg1, arg2, arg3, arg4)
}
// ProlongAccess mocks base method
-func (m *MockRequests) ProlongAccess(reqID boruta.ReqID) error {
- ret := m.ctrl.Call(m, "ProlongAccess", reqID)
+func (m *MockRequests) ProlongAccess(arg0 boruta.ReqID) error {
+ ret := m.ctrl.Call(m, "ProlongAccess", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// ProlongAccess indicates an expected call of ProlongAccess
-func (mr *MockRequestsMockRecorder) ProlongAccess(reqID interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProlongAccess", reflect.TypeOf((*MockRequests)(nil).ProlongAccess), reqID)
-}
-
-// MockSuperviser is a mock of Superviser interface
-type MockSuperviser struct {
- ctrl *gomock.Controller
- recorder *MockSuperviserMockRecorder
-}
-
-// MockSuperviserMockRecorder is the mock recorder for MockSuperviser
-type MockSuperviserMockRecorder struct {
- mock *MockSuperviser
-}
-
-// NewMockSuperviser creates a new mock instance
-func NewMockSuperviser(ctrl *gomock.Controller) *MockSuperviser {
- mock := &MockSuperviser{ctrl: ctrl}
- mock.recorder = &MockSuperviserMockRecorder{mock}
- return mock
-}
-
-// EXPECT returns an object that allows the caller to indicate expected use
-func (m *MockSuperviser) EXPECT() *MockSuperviserMockRecorder {
- return m.recorder
+func (mr *MockRequestsMockRecorder) ProlongAccess(arg0 interface{}) *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProlongAccess", reflect.TypeOf((*MockRequests)(nil).ProlongAccess), arg0)
}
-// Register mocks base method
-func (m *MockSuperviser) Register(caps boruta.Capabilities) error {
- ret := m.ctrl.Call(m, "Register", caps)
- ret0, _ := ret[0].(error)
- return ret0
-}
-
-// Register indicates an expected call of Register
-func (mr *MockSuperviserMockRecorder) Register(caps interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockSuperviser)(nil).Register), caps)
-}
-
-// SetFail mocks base method
-func (m *MockSuperviser) SetFail(uuid boruta.WorkerUUID, reason string) error {
- ret := m.ctrl.Call(m, "SetFail", uuid, reason)
- ret0, _ := ret[0].(error)
- return ret0
-}
-
-// SetFail indicates an expected call of SetFail
-func (mr *MockSuperviserMockRecorder) SetFail(uuid, reason interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetFail", reflect.TypeOf((*MockSuperviser)(nil).SetFail), uuid, reason)
-}
-
-// MockWorkers is a mock of Workers interface
-type MockWorkers struct {
- ctrl *gomock.Controller
- recorder *MockWorkersMockRecorder
-}
-
-// MockWorkersMockRecorder is the mock recorder for MockWorkers
-type MockWorkersMockRecorder struct {
- mock *MockWorkers
-}
-
-// NewMockWorkers creates a new mock instance
-func NewMockWorkers(ctrl *gomock.Controller) *MockWorkers {
- mock := &MockWorkers{ctrl: ctrl}
- mock.recorder = &MockWorkersMockRecorder{mock}
- return mock
-}
-
-// EXPECT returns an object that allows the caller to indicate expected use
-func (m *MockWorkers) EXPECT() *MockWorkersMockRecorder {
- return m.recorder
-}
-
-// ListWorkers mocks base method
-func (m *MockWorkers) ListWorkers(groups boruta.Groups, caps boruta.Capabilities) ([]boruta.WorkerInfo, error) {
- ret := m.ctrl.Call(m, "ListWorkers", groups, caps)
- ret0, _ := ret[0].([]boruta.WorkerInfo)
- ret1, _ := ret[1].(error)
- return ret0, ret1
-}
-
-// ListWorkers indicates an expected call of ListWorkers
-func (mr *MockWorkersMockRecorder) ListWorkers(groups, caps interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListWorkers", reflect.TypeOf((*MockWorkers)(nil).ListWorkers), groups, caps)
-}
-
-// GetWorkerInfo mocks base method
-func (m *MockWorkers) GetWorkerInfo(uuid boruta.WorkerUUID) (boruta.WorkerInfo, error) {
- ret := m.ctrl.Call(m, "GetWorkerInfo", uuid)
- ret0, _ := ret[0].(boruta.WorkerInfo)
- ret1, _ := ret[1].(error)
- return ret0, ret1
-}
-
-// GetWorkerInfo indicates an expected call of GetWorkerInfo
-func (mr *MockWorkersMockRecorder) GetWorkerInfo(uuid interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkerInfo", reflect.TypeOf((*MockWorkers)(nil).GetWorkerInfo), uuid)
-}
-
-// SetState mocks base method
-func (m *MockWorkers) SetState(uuid boruta.WorkerUUID, state boruta.WorkerState) error {
- ret := m.ctrl.Call(m, "SetState", uuid, state)
- ret0, _ := ret[0].(error)
- return ret0
-}
-
-// SetState indicates an expected call of SetState
-func (mr *MockWorkersMockRecorder) SetState(uuid, state interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetState", reflect.TypeOf((*MockWorkers)(nil).SetState), uuid, state)
-}
-
-// SetGroups mocks base method
-func (m *MockWorkers) SetGroups(uuid boruta.WorkerUUID, groups boruta.Groups) error {
- ret := m.ctrl.Call(m, "SetGroups", uuid, groups)
- ret0, _ := ret[0].(error)
- return ret0
-}
-
-// SetGroups indicates an expected call of SetGroups
-func (mr *MockWorkersMockRecorder) SetGroups(uuid, groups interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetGroups", reflect.TypeOf((*MockWorkers)(nil).SetGroups), uuid, groups)
-}
-
-// Deregister mocks base method
-func (m *MockWorkers) Deregister(uuid boruta.WorkerUUID) error {
- ret := m.ctrl.Call(m, "Deregister", uuid)
- ret0, _ := ret[0].(error)
- return ret0
-}
-
-// Deregister indicates an expected call of Deregister
-func (mr *MockWorkersMockRecorder) Deregister(uuid interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Deregister", reflect.TypeOf((*MockWorkers)(nil).Deregister), uuid)
-}
-
-// MockDryad is a mock of Dryad interface
-type MockDryad struct {
- ctrl *gomock.Controller
- recorder *MockDryadMockRecorder
-}
-
-// MockDryadMockRecorder is the mock recorder for MockDryad
-type MockDryadMockRecorder struct {
- mock *MockDryad
-}
-
-// NewMockDryad creates a new mock instance
-func NewMockDryad(ctrl *gomock.Controller) *MockDryad {
- mock := &MockDryad{ctrl: ctrl}
- mock.recorder = &MockDryadMockRecorder{mock}
- return mock
-}
-
-// EXPECT returns an object that allows the caller to indicate expected use
-func (m *MockDryad) EXPECT() *MockDryadMockRecorder {
- return m.recorder
-}
-
-// PutInMaintenance mocks base method
-func (m *MockDryad) PutInMaintenance(msg string) error {
- ret := m.ctrl.Call(m, "PutInMaintenance", msg)
- ret0, _ := ret[0].(error)
- return ret0
-}
-
-// PutInMaintenance indicates an expected call of PutInMaintenance
-func (mr *MockDryadMockRecorder) PutInMaintenance(msg interface{}) *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutInMaintenance", reflect.TypeOf((*MockDryad)(nil).PutInMaintenance), msg)
-}
-
-// Prepare mocks base method
-func (m *MockDryad) Prepare() (*rsa.PrivateKey, error) {
- ret := m.ctrl.Call(m, "Prepare")
- ret0, _ := ret[0].(*rsa.PrivateKey)
- ret1, _ := ret[1].(error)
- return ret0, ret1
-}
-
-// Prepare indicates an expected call of Prepare
-func (mr *MockDryadMockRecorder) Prepare() *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Prepare", reflect.TypeOf((*MockDryad)(nil).Prepare))
-}
-
-// Healthcheck mocks base method
-func (m *MockDryad) Healthcheck() error {
- ret := m.ctrl.Call(m, "Healthcheck")
+// UpdateRequest mocks base method
+func (m *MockRequests) UpdateRequest(arg0 *boruta.ReqInfo) error {
+ ret := m.ctrl.Call(m, "UpdateRequest", arg0)
ret0, _ := ret[0].(error)
return ret0
}
-// Healthcheck indicates an expected call of Healthcheck
-func (mr *MockDryadMockRecorder) Healthcheck() *gomock.Call {
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Healthcheck", reflect.TypeOf((*MockDryad)(nil).Healthcheck))
+// UpdateRequest indicates an expected call of UpdateRequest
+func (mr *MockRequestsMockRecorder) UpdateRequest(arg0 interface{}) *gomock.Call {
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateRequest", reflect.TypeOf((*MockRequests)(nil).UpdateRequest), arg0)
}
diff --git a/controller/notifier/notification.go b/controller/notifier/notification.go
index 255d881..c7e6501 100644
--- a/controller/notifier/notification.go
+++ b/controller/notifier/notification.go
@@ -20,7 +20,7 @@
package notifier
import (
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
// BuffSize is the default channel buffer size for channels passing
diff --git a/controller/notifier/notifier.go b/controller/notifier/notifier.go
index a299680..74671ed 100644
--- a/controller/notifier/notifier.go
+++ b/controller/notifier/notifier.go
@@ -20,7 +20,7 @@
package notifier
import (
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
// Notifier defines interface providing channel for notifying Controller.
diff --git a/controller/notifier/notifierimpl.go b/controller/notifier/notifierimpl.go
index 60bb7e6..ba883b7 100644
--- a/controller/notifier/notifierimpl.go
+++ b/controller/notifier/notifierimpl.go
@@ -22,7 +22,7 @@
package notifier
import (
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
// Impl implements Notifier interface
diff --git a/controller/notifier/notifierimpl_test.go b/controller/notifier/notifierimpl_test.go
index 10eb4c6..93b77e5 100644
--- a/controller/notifier/notifierimpl_test.go
+++ b/controller/notifier/notifierimpl_test.go
@@ -19,7 +19,7 @@ package notifier
import (
"fmt"
- . "git.tizen.org/tools/weles"
+ . "github.com/SamsungSLAV/weles"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
diff --git a/controller/parser.go b/controller/parser.go
index 6410ef5..aabd912 100644
--- a/controller/parser.go
+++ b/controller/parser.go
@@ -20,8 +20,8 @@
package controller
import (
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/controller/notifier"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/controller/notifier"
)
// Parser defines action run for a Job to prepare config in parsing phase.
diff --git a/controller/parserimpl.go b/controller/parserimpl.go
index fb926ef..fbf4b8b 100644
--- a/controller/parserimpl.go
+++ b/controller/parserimpl.go
@@ -22,8 +22,8 @@ import (
"fmt"
"io/ioutil"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/controller/notifier"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/controller/notifier"
)
// ParserImpl implements Parser for Controller.
diff --git a/controller/parserimpl_test.go b/controller/parserimpl_test.go
index 6a0e220..aa8fb6b 100644
--- a/controller/parserimpl_test.go
+++ b/controller/parserimpl_test.go
@@ -19,10 +19,10 @@ package controller
import (
"errors"
- "git.tizen.org/tools/weles"
- cmock "git.tizen.org/tools/weles/controller/mock"
- "git.tizen.org/tools/weles/controller/notifier"
- mock "git.tizen.org/tools/weles/mock"
+ "github.com/SamsungSLAV/weles"
+ cmock "github.com/SamsungSLAV/weles/controller/mock"
+ "github.com/SamsungSLAV/weles/controller/notifier"
+ mock "github.com/SamsungSLAV/weles/mock"
gomock "github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
diff --git a/fixtures/artifactinfo.go b/fixtures/artifactinfo.go
index bebe570..43dd29f 100644
--- a/fixtures/artifactinfo.go
+++ b/fixtures/artifactinfo.go
@@ -23,13 +23,14 @@ import (
"github.com/go-openapi/strfmt"
"github.com/tideland/golib/audit"
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
const (
- dateLayout = "Mon Jan 2 15:04:05 -0700 MST 2006"
- someDate = "Tue Jan 2 15:04:05 +0100 CET 1900"
- durationIncrement = "+25h"
+ dateLayout = "Mon Jan 2 15:04:05 -0700 MST 2006"
+ someDate = "Tue Jan 2 15:04:05 +0100 CET 1900"
+ durationIncrement = "+25h"
+ maxArtifactsPerJob = 10
)
// CreateArtifactInfoSlice returns slice of ArtifactInfos of sliceLength length.
@@ -45,14 +46,21 @@ func CreateArtifactInfoSlice(sliceLength int) []weles.ArtifactInfo {
panic(err)
}
artifactInfo := make([]weles.ArtifactInfo, sliceLength)
- gen := audit.NewGenerator(rand.New(rand.NewSource(time.Now().UTC().UnixNano())))
+
+ r := rand.New(rand.NewSource(time.Now().UnixNano()))
+ gen := audit.NewGenerator(rand.New(r))
+ var jobID, jobIDSwitchRemainingArtifacts int
for i := range artifactInfo {
+ if jobIDSwitchRemainingArtifacts == 0 {
+ jobIDSwitchRemainingArtifacts = r.Intn(maxArtifactsPerJob)
+ jobID = i + 1
+ }
tmp := weles.ArtifactInfo{}
timestamp := gen.Time(time.Local, dateTimeIter, durationIncrement)
tmp.Timestamp = strfmt.DateTime(timestamp)
tmp.ID = int64(i + 1)
tmp.ArtifactDescription.Alias = weles.ArtifactAlias(gen.Word())
- tmp.ArtifactDescription.JobID = weles.JobID(i + 1)
+ tmp.ArtifactDescription.JobID = weles.JobID(jobID)
tmp.ArtifactDescription.Type = weles.ArtifactType(gen.OneStringOf(
string(weles.ArtifactTypeIMAGE),
string(weles.ArtifactTypeRESULT),
@@ -68,6 +76,7 @@ func CreateArtifactInfoSlice(sliceLength int) []weles.ArtifactInfo {
dateTimeIter = dateTimeIter.Add(durationIncrement)
artifactInfo[i] = tmp
+ jobIDSwitchRemainingArtifacts--
}
return artifactInfo
}
diff --git a/job_filter_and_sort.go b/job_filter_and_sort.go
deleted file mode 100644
index 511ac8b..0000000
--- a/job_filter_and_sort.go
+++ /dev/null
@@ -1,111 +0,0 @@
-// Code generated by go-swagger; DO NOT EDIT.
-
-// Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License
-//
-
-package weles
-
-// This file was generated by the swagger tool.
-// Editing this file might prove futile when you re-run the swagger generate command
-
-import (
- strfmt "github.com/go-openapi/strfmt"
-
- "github.com/go-openapi/errors"
- "github.com/go-openapi/swag"
-)
-
-// JobFilterAndSort Data for filtering and sorting Weles Jobs lists.
-// swagger:model JobFilterAndSort
-type JobFilterAndSort struct {
-
- // filter
- Filter *JobFilter `json:"Filter,omitempty"`
-
- // sorter
- Sorter *JobSorter `json:"Sorter,omitempty"`
-}
-
-// Validate validates this job filter and sort
-func (m *JobFilterAndSort) Validate(formats strfmt.Registry) error {
- var res []error
-
- if err := m.validateFilter(formats); err != nil {
- res = append(res, err)
- }
-
- if err := m.validateSorter(formats); err != nil {
- res = append(res, err)
- }
-
- if len(res) > 0 {
- return errors.CompositeValidationError(res...)
- }
- return nil
-}
-
-func (m *JobFilterAndSort) validateFilter(formats strfmt.Registry) error {
-
- if swag.IsZero(m.Filter) { // not required
- return nil
- }
-
- if m.Filter != nil {
- if err := m.Filter.Validate(formats); err != nil {
- if ve, ok := err.(*errors.Validation); ok {
- return ve.ValidateName("Filter")
- }
- return err
- }
- }
-
- return nil
-}
-
-func (m *JobFilterAndSort) validateSorter(formats strfmt.Registry) error {
-
- if swag.IsZero(m.Sorter) { // not required
- return nil
- }
-
- if m.Sorter != nil {
- if err := m.Sorter.Validate(formats); err != nil {
- if ve, ok := err.(*errors.Validation); ok {
- return ve.ValidateName("Sorter")
- }
- return err
- }
- }
-
- return nil
-}
-
-// MarshalBinary interface implementation
-func (m *JobFilterAndSort) MarshalBinary() ([]byte, error) {
- if m == nil {
- return nil, nil
- }
- return swag.WriteJSON(m)
-}
-
-// UnmarshalBinary interface implementation
-func (m *JobFilterAndSort) UnmarshalBinary(b []byte) error {
- var res JobFilterAndSort
- if err := swag.ReadJSON(b, &res); err != nil {
- return err
- }
- *m = res
- return nil
-}
diff --git a/job_sort_by.go b/job_sort_by.go
index dc3a366..8af2a25 100644
--- a/job_sort_by.go
+++ b/job_sort_by.go
@@ -29,14 +29,16 @@ import (
"github.com/go-openapi/validate"
)
-// JobSortBy denotes key for sorting Jobs list. Jobs are sorted by ID (Ascending) by default.
-// You can sort jobs additionaly by
+// JobSortBy denotes key for sorting Jobs list.
+//
+// * ID - default sort key.
//
// * CreatedDate - sorting by date of creation of the weles job.
//
// * UpdatedDate - sorting by date of update of the weles job.
//
// * JobStatus - sorting by the Job Status. Descending order will sort in the order JobStatuses are listed in the docs (from NEW at the start to CANCELED at the end). Ascending will reverse this order.
+//
// When sorting is applied, and there are many jobs with the same date/status, they will be sorted by JobID (Ascending)
//
// swagger:model JobSortBy
@@ -44,6 +46,9 @@ type JobSortBy string
const (
+ // JobSortByID captures enum value "ID"
+ JobSortByID JobSortBy = "ID"
+
// JobSortByCreatedDate captures enum value "CreatedDate"
JobSortByCreatedDate JobSortBy = "CreatedDate"
@@ -59,7 +64,7 @@ var jobSortByEnum []interface{}
func init() {
var res []JobSortBy
- if err := json.Unmarshal([]byte(`["CreatedDate","UpdatedDate","JobStatus"]`), &res); err != nil {
+ if err := json.Unmarshal([]byte(`["ID","CreatedDate","UpdatedDate","JobStatus",""]`), &res); err != nil {
panic(err)
}
for _, v := range res {
diff --git a/job_status.go b/job_status.go
index 45e0888..88220b2 100644
--- a/job_status.go
+++ b/job_status.go
@@ -82,7 +82,7 @@ var jobStatusEnum []interface{}
func init() {
var res []JobStatus
- if err := json.Unmarshal([]byte(`["NEW","PARSING","DOWNLOADING","WAITING","RUNNING","COMPLETED","FAILED","CANCELED"]`), &res); err != nil {
+ if err := json.Unmarshal([]byte(`["NEW","PARSING","DOWNLOADING","WAITING","RUNNING","COMPLETED","FAILED","CANCELED",""]`), &res); err != nil {
panic(err)
}
for _, v := range res {
diff --git a/manager/dryad/device_communication_provider_test.go b/manager/dryad/device_communication_provider_test.go
index 9750bf4..48ac2bd 100644
--- a/manager/dryad/device_communication_provider_test.go
+++ b/manager/dryad/device_communication_provider_test.go
@@ -21,7 +21,7 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
- "git.tizen.org/tools/weles/manager/dryad/mock"
+ "github.com/SamsungSLAV/weles/manager/dryad/mock"
)
var _ = Describe("DeviceCommunicationProvider", func() {
diff --git a/manager/dryad/dryad_suite_test.go b/manager/dryad/dryad_suite_test.go
index 9144fc0..c5fe91e 100644
--- a/manager/dryad/dryad_suite_test.go
+++ b/manager/dryad/dryad_suite_test.go
@@ -29,7 +29,7 @@ import (
"encoding/pem"
- . "git.tizen.org/tools/weles"
+ . "github.com/SamsungSLAV/weles"
)
func TestManager(t *testing.T) {
diff --git a/manager/dryad/mock/mocks_generate.go b/manager/dryad/mock/mocks_generate.go
index 92dceef..882b83f 100644
--- a/manager/dryad/mock/mocks_generate.go
+++ b/manager/dryad/mock/mocks_generate.go
@@ -16,4 +16,4 @@
package mock
-//go:generate ../../../bin/dev-tools/mockgen -package mock -destination=./session_provider.go git.tizen.org/tools/weles/manager/dryad SessionProvider
+//go:generate ../../../bin/dev-tools/mockgen -package mock -destination=./session_provider.go github.com/SamsungSLAV/weles/manager/dryad SessionProvider
diff --git a/manager/dryad/mock/session_provider.go b/manager/dryad/mock/session_provider.go
index c3e2786..f0ca5f7 100644
--- a/manager/dryad/mock/session_provider.go
+++ b/manager/dryad/mock/session_provider.go
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.tizen.org/tools/weles/manager/dryad (interfaces: SessionProvider)
+// Source: github.com/SamsungSLAV/weles/manager/dryad (interfaces: SessionProvider)
// Package mock is a generated GoMock package.
package mock
diff --git a/manager/dryad/reverse_sshfs.go b/manager/dryad/reverse_sshfs.go
index e539aad..1a53732 100644
--- a/manager/dryad/reverse_sshfs.go
+++ b/manager/dryad/reverse_sshfs.go
@@ -66,8 +66,10 @@ func (sshfs *reverseSSHFS) open(session *ssh.Session) (err error) {
// ^log on stderr
ctx, cancel := context.WithCancel(sshfs.ctx)
- // gas/gosec returns error here about subprocess launching with variable. This is intended.
- sftp := exec.CommandContext(ctx, "/usr/lib/openssh/sftp-server", "-e", "-l", "INFO") //nolint: gas, gosec,lll
+ // gosec returns error here about subprocess launching with variable. This is intended.
+ // nolint:gosec
+ sftp := exec.CommandContext(ctx, "/usr/lib/openssh/sftp-server", "-e", "-l", "INFO")
+
session.Stdin, err = sftp.StdoutPipe()
if err != nil {
cancel()
diff --git a/manager/dryad/session_provider.go b/manager/dryad/session_provider.go
index b6964a4..7d4bcb8 100644
--- a/manager/dryad/session_provider.go
+++ b/manager/dryad/session_provider.go
@@ -26,7 +26,7 @@ import (
"crypto/rsa"
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
"golang.org/x/crypto/ssh"
)
@@ -50,15 +50,20 @@ type sessionProvider struct {
}
func prepareSSHConfig(userName string, key rsa.PrivateKey) *ssh.ClientConfig {
- signer, _ := ssh.NewSignerFromKey(&key)
+ signer, err := ssh.NewSignerFromKey(&key)
+ if err != nil {
+ log.Println("Failed to create signer from received ssh key.")
+ // TODO: If there is a problem with parsing ssh key, job should fail.
+ }
return &ssh.ClientConfig{
User: userName,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(signer),
},
- HostKeyCallback: ssh.InsecureIgnoreHostKey(),
- Timeout: 30 * time.Second, // TODO: Use value from config when such appears.
+ // TODO: Below will accept any host key. This should change in the future.
+ HostKeyCallback: ssh.InsecureIgnoreHostKey(), // nolint:gosec
+ Timeout: 30 * time.Second, // TODO: Use value from config.
}
}
diff --git a/manager/dryad_job.go b/manager/dryad_job.go
index 97dcdac..872f69a 100644
--- a/manager/dryad_job.go
+++ b/manager/dryad_job.go
@@ -21,8 +21,8 @@ import (
"fmt"
"sync"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/manager/dryad"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/manager/dryad"
)
type dryadJob struct {
@@ -55,10 +55,9 @@ func newDryadJobWithCancel(job weles.JobID, changes chan<- weles.DryadJobStatusC
// newDryadJob creates an instance of dryadJob and starts a goroutine
// executing phases of given job implemented by provider of DryadJobRunner interface.
func newDryadJob(job weles.JobID, rusalka weles.Dryad, conf weles.Config,
- changes chan<- weles.DryadJobStatusChange) *dryadJob {
+ changes chan<- weles.DryadJobStatusChange, artifactDBPath string) *dryadJob {
- // FIXME: It should use the proper path to the artifactory.
- session := dryad.NewSessionProvider(rusalka, "")
+ session := dryad.NewSessionProvider(rusalka, artifactDBPath)
device := dryad.NewDeviceCommunicationProvider(session)
ctx, cancel := context.WithCancel(context.Background())
diff --git a/manager/dryad_job_manager.go b/manager/dryad_job_manager.go
index 4dacf21..b766606 100644
--- a/manager/dryad_job_manager.go
+++ b/manager/dryad_job_manager.go
@@ -21,21 +21,23 @@ package manager
import (
"sync"
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
// DryadJobs implements DryadJobManager interface.
type DryadJobs struct {
weles.DryadJobManager
- jobs map[weles.JobID]*dryadJob
- jobsMutex *sync.RWMutex
+ jobs map[weles.JobID]*dryadJob
+ jobsMutex *sync.RWMutex
+ artifactDBPath string
}
// NewDryadJobManager returns DryadJobManager interface of a new instance of DryadJobs.
-func NewDryadJobManager() weles.DryadJobManager {
+func NewDryadJobManager(artifactDBPath string) weles.DryadJobManager {
return &DryadJobs{
- jobs: make(map[weles.JobID]*dryadJob),
- jobsMutex: new(sync.RWMutex),
+ jobs: make(map[weles.JobID]*dryadJob),
+ jobsMutex: new(sync.RWMutex),
+ artifactDBPath: artifactDBPath,
}
}
@@ -50,7 +52,7 @@ func (d *DryadJobs) Create(job weles.JobID, rusalka weles.Dryad, conf weles.Conf
d.jobsMutex.Lock()
defer d.jobsMutex.Unlock()
// FIXME(amistewicz): dryadJobs should not be stored indefinitely.
- d.jobs[job] = newDryadJob(job, rusalka, conf, changes)
+ d.jobs[job] = newDryadJob(job, rusalka, conf, changes, d.artifactDBPath)
return nil
}
diff --git a/manager/dryad_job_manager_test.go b/manager/dryad_job_manager_test.go
index df0f635..65082a6 100644
--- a/manager/dryad_job_manager_test.go
+++ b/manager/dryad_job_manager_test.go
@@ -19,7 +19,7 @@ package manager
import (
"sync"
- . "git.tizen.org/tools/weles"
+ . "github.com/SamsungSLAV/weles"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
@@ -29,9 +29,10 @@ import (
var _ = Describe("DryadJobManager", func() {
var djm DryadJobManager
jobID := JobID(666)
+ artifactDBPath := "/artifact/db/path"
BeforeEach(func() {
- djm = NewDryadJobManager()
+ djm = NewDryadJobManager(artifactDBPath)
})
create := func() {
diff --git a/manager/dryad_job_runner.go b/manager/dryad_job_runner.go
index eba526b..1feeef5 100644
--- a/manager/dryad_job_runner.go
+++ b/manager/dryad_job_runner.go
@@ -22,8 +22,8 @@ import (
"context"
"log"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/manager/dryad"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/manager/dryad"
)
// dryadJobRunner implements DryadJobRunner interface.
diff --git a/manager/dryad_job_runner_conf_test.go b/manager/dryad_job_runner_conf_test.go
index 2ad18b8..c0044a9 100644
--- a/manager/dryad_job_runner_conf_test.go
+++ b/manager/dryad_job_runner_conf_test.go
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
package manager
import (
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
// basicConfig is incomplete, but contains necessary definitions
diff --git a/manager/dryad_job_runner_fota.go b/manager/dryad_job_runner_fota.go
index fb95ca7..5b7ea89 100644
--- a/manager/dryad_job_runner_fota.go
+++ b/manager/dryad_job_runner_fota.go
@@ -24,7 +24,7 @@ import (
)
const (
- fotaCmdPath = "/usr/bin/fota"
+ fotaCmdPath = "/usr/local/bin/fota"
fotaSDCardPath = "/dev/sda"
fotaFilePath = "/tmp/fota.json"
)
@@ -36,6 +36,10 @@ type fotaCmd struct {
URLs []string
}
+// newFotaCmd creates new fotaCmd instance.
+// Currently it always receives same params thus nolint directive.
+// Those params should be based on job submission file.
+// nolint:unparam
func newFotaCmd(sdcard, mapping string, urls []string) *fotaCmd {
return &fotaCmd{
sdcard: sdcard,
diff --git a/manager/dryad_job_runner_test.go b/manager/dryad_job_runner_test.go
index d798665..457b5ef 100644
--- a/manager/dryad_job_runner_test.go
+++ b/manager/dryad_job_runner_test.go
@@ -19,10 +19,10 @@ package manager
import (
"context"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/manager/dryad"
- dmock "git.tizen.org/tools/weles/manager/dryad/mock"
- "git.tizen.org/tools/weles/manager/mock"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/manager/dryad"
+ dmock "github.com/SamsungSLAV/weles/manager/dryad/mock"
+ "github.com/SamsungSLAV/weles/manager/mock"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
diff --git a/manager/dryad_job_test.go b/manager/dryad_job_test.go
index ea59417..39ebc4e 100644
--- a/manager/dryad_job_test.go
+++ b/manager/dryad_job_test.go
@@ -20,8 +20,8 @@ import (
"context"
"errors"
- . "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/manager/mock"
+ . "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/manager/mock"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
diff --git a/manager/mock/communication_provider.go b/manager/mock/communication_provider.go
index 54a1ca4..e053562 100644
--- a/manager/mock/communication_provider.go
+++ b/manager/mock/communication_provider.go
@@ -1,11 +1,11 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.tizen.org/tools/weles/manager/dryad (interfaces: DeviceCommunicationProvider)
+// Source: github.com/SamsungSLAV/weles/manager/dryad (interfaces: DeviceCommunicationProvider)
// Package mock is a generated GoMock package.
package mock
import (
- dryad "git.tizen.org/tools/weles/manager/dryad"
+ dryad "github.com/SamsungSLAV/weles/manager/dryad"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
diff --git a/manager/mock/dryad_job_runner.go b/manager/mock/dryad_job_runner.go
index f6b88fa..6ff68bc 100644
--- a/manager/mock/dryad_job_runner.go
+++ b/manager/mock/dryad_job_runner.go
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.tizen.org/tools/weles/manager (interfaces: DryadJobRunner)
+// Source: github.com/SamsungSLAV/weles/manager (interfaces: DryadJobRunner)
// Package mock is a generated GoMock package.
package mock
diff --git a/manager/mock/mocks_generate.go b/manager/mock/mocks_generate.go
index 639381c..0604ea3 100644
--- a/manager/mock/mocks_generate.go
+++ b/manager/mock/mocks_generate.go
@@ -16,6 +16,6 @@
package mock
-//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./communication_provider.go git.tizen.org/tools/weles/manager/dryad DeviceCommunicationProvider
+//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./communication_provider.go github.com/SamsungSLAV/weles/manager/dryad DeviceCommunicationProvider
-//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./dryad_job_runner.go git.tizen.org/tools/weles/manager DryadJobRunner
+//go:generate ../../bin/dev-tools/mockgen -package mock -destination=./dryad_job_runner.go github.com/SamsungSLAV/weles/manager DryadJobRunner
diff --git a/mock/artifactmanager.go b/mock/artifactmanager.go
index 848b5fb..a2ac259 100644
--- a/mock/artifactmanager.go
+++ b/mock/artifactmanager.go
@@ -1,11 +1,11 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.tizen.org/tools/weles (interfaces: ArtifactManager)
+// Source: github.com/SamsungSLAV/weles (interfaces: ArtifactManager)
// Package mock is a generated GoMock package.
package mock
import (
- weles "git.tizen.org/tools/weles"
+ weles "github.com/SamsungSLAV/weles"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
diff --git a/mock/dryadjobmanager.go b/mock/dryadjobmanager.go
index 32efb27..19615e7 100644
--- a/mock/dryadjobmanager.go
+++ b/mock/dryadjobmanager.go
@@ -1,11 +1,11 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.tizen.org/tools/weles (interfaces: DryadJobManager)
+// Source: github.com/SamsungSLAV/weles (interfaces: DryadJobManager)
// Package mock is a generated GoMock package.
package mock
import (
- weles "git.tizen.org/tools/weles"
+ weles "github.com/SamsungSLAV/weles"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
diff --git a/mock/jobmanager.go b/mock/jobmanager.go
index 3b821ad..7d9bd7f 100644
--- a/mock/jobmanager.go
+++ b/mock/jobmanager.go
@@ -1,11 +1,11 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.tizen.org/tools/weles (interfaces: JobManager)
+// Source: github.com/SamsungSLAV/weles (interfaces: JobManager)
// Package mock is a generated GoMock package.
package mock
import (
- weles "git.tizen.org/tools/weles"
+ weles "github.com/SamsungSLAV/weles"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
diff --git a/mock/mocks_generate.go b/mock/mocks_generate.go
index 76d531d..d496e1b 100644
--- a/mock/mocks_generate.go
+++ b/mock/mocks_generate.go
@@ -16,10 +16,10 @@
package mock
-//go:generate ../bin/dev-tools/mockgen -package mock -destination=./artifactmanager.go git.tizen.org/tools/weles ArtifactManager
+//go:generate ../bin/dev-tools/mockgen -package mock -destination=./artifactmanager.go github.com/SamsungSLAV/weles ArtifactManager
-//go:generate ../bin/dev-tools/mockgen -package mock -destination=./dryadjobmanager.go git.tizen.org/tools/weles DryadJobManager
+//go:generate ../bin/dev-tools/mockgen -package mock -destination=./dryadjobmanager.go github.com/SamsungSLAV/weles DryadJobManager
-//go:generate ../bin/dev-tools/mockgen -package mock -destination=./jobmanager.go git.tizen.org/tools/weles JobManager
+//go:generate ../bin/dev-tools/mockgen -package mock -destination=./jobmanager.go github.com/SamsungSLAV/weles JobManager
-//go:generate ../bin/dev-tools/mockgen -package mock -destination=./parser.go git.tizen.org/tools/weles Parser
+//go:generate ../bin/dev-tools/mockgen -package mock -destination=./parser.go github.com/SamsungSLAV/weles Parser
diff --git a/mock/parser.go b/mock/parser.go
index ca08472..26ab8b6 100644
--- a/mock/parser.go
+++ b/mock/parser.go
@@ -1,11 +1,11 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: git.tizen.org/tools/weles (interfaces: Parser)
+// Source: github.com/SamsungSLAV/weles (interfaces: Parser)
// Package mock is a generated GoMock package.
package mock
import (
- weles "git.tizen.org/tools/weles"
+ weles "github.com/SamsungSLAV/weles"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
diff --git a/parser/parser.go b/parser/parser.go
index 7457f4a..c93b7a3 100644
--- a/parser/parser.go
+++ b/parser/parser.go
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@ import (
"gopkg.in/yaml.v2"
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
func validatePriority(conf weles.Config) error {
diff --git a/parser/weles_parser_test.go b/parser/weles_parser_test.go
index c20d98f..68d5d5b 100644
--- a/parser/weles_parser_test.go
+++ b/parser/weles_parser_test.go
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,8 +22,8 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/parser"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/parser"
)
var expectedConfig = weles.Config{
diff --git a/server/artifact_lister_handler.go b/server/artifact_lister_handler.go
index 33ea19f..e071127 100644
--- a/server/artifact_lister_handler.go
+++ b/server/artifact_lister_handler.go
@@ -17,38 +17,24 @@ package server
import (
"github.com/go-openapi/runtime/middleware"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/server/operations/artifacts"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/server/operations/artifacts"
)
-// ArtifactLister is a handler which passess requests for listing artifacts to artifactmanager.
+// ArtifactLister is a handler which passess requests for listing artifacts to ArtifactManager.
func (a *APIDefaults) ArtifactLister(params artifacts.ArtifactListerParams) middleware.Responder {
- if (params.After != nil) && (params.Before != nil) {
- return artifacts.NewArtifactListerBadRequest().WithPayload(&weles.ErrResponse{
- Message: weles.ErrBeforeAfterNotAllowed.Error()})
- }
-
- var artifactInfoReceived []weles.ArtifactInfo
- var listInfo weles.ListInfo
- var err error
paginator := weles.ArtifactPagination{}
if a.PageLimit != 0 {
+ if (params.After != nil) && (params.Before != nil) {
+ return artifacts.NewArtifactListerBadRequest().WithPayload(&weles.ErrResponse{
+ Message: weles.ErrBeforeAfterNotAllowed.Error()})
+ }
paginator = setArtifactPaginator(params, a.PageLimit)
}
+ filter := setArtifactFilter(params.ArtifactFilterAndSort.Filter)
+ sorter := setArtifactSorter(params.ArtifactFilterAndSort.Sorter)
- if params.ArtifactFilterAndSort != nil {
- artifactInfoReceived, listInfo, err = a.Managers.AM.ListArtifact(
- *params.ArtifactFilterAndSort.Filter, *params.ArtifactFilterAndSort.Sorter, paginator)
- } else {
- artifactInfoReceived, listInfo, err = a.Managers.AM.ListArtifact(
- weles.ArtifactFilter{}, weles.ArtifactSorter{}, paginator)
- }
-
- // TODO: remove this when artifactmanager will return this.
- if len(artifactInfoReceived) == 0 {
- return artifacts.NewArtifactListerNotFound().WithPayload(
- &weles.ErrResponse{Message: weles.ErrArtifactNotFound.Error()})
- }
+ artifactInfoReceived, listInfo, err := a.Managers.AM.ListArtifact(filter, sorter, paginator)
switch err {
default:
@@ -66,9 +52,9 @@ func (a *APIDefaults) ArtifactLister(params artifacts.ArtifactListerParams) midd
return responderArtifact200(listInfo, paginator, artifactInfoReturned, a.PageLimit)
} //not last page...
return responderArtifact206(listInfo, paginator, artifactInfoReturned, a.PageLimit)
-
}
+// responderArtifact206 builds 206 HTTP response with appropriate headers and body.
func responderArtifact206(listInfo weles.ListInfo, paginator weles.ArtifactPagination,
artifactInfoReturned []*weles.ArtifactInfo, defaultPageLimit int32,
) (responder *artifacts.ArtifactListerPartialContent) {
@@ -102,6 +88,7 @@ func responderArtifact206(listInfo weles.ListInfo, paginator weles.ArtifactPagin
return
}
+// responderArtifact200 builds 200 HTTP response with appropriate headers and body.
func responderArtifact200(listInfo weles.ListInfo, paginator weles.ArtifactPagination,
artifactInfoReturned []*weles.ArtifactInfo, defaultPageLimit int32,
) (responder *artifacts.ArtifactListerOK) {
@@ -133,6 +120,54 @@ func responderArtifact200(listInfo weles.ListInfo, paginator weles.ArtifactPagin
return
}
+// setArtifactFilter adjusts filter's 0 values to be consistent and acceptable by the artifacts db
+// That is []string with only 1 empty element should be removed.
+func setArtifactFilter(fi *weles.ArtifactFilter) (fo weles.ArtifactFilter) {
+ if fi != nil {
+ if len(fi.JobID) > 0 {
+ fo.JobID = fi.JobID
+ }
+ if len(fi.Alias) > 0 {
+ if !(len(fi.Alias) == 1 && fi.Alias[0] == "") {
+ fo.Alias = fi.Alias
+ }
+ }
+ if len(fi.Status) > 0 {
+ if !(len(fi.Status) == 1 && fi.Status[0] == "") {
+ fo.Status = fi.Status
+ }
+ }
+ if len(fi.Type) > 0 {
+ if !(len(fi.Type) == 1 && fi.Type[0] == "") {
+ fo.Type = fi.Type
+ }
+ }
+ }
+ return
+}
+
+// setArtifactSorter sets default sorter values.
+func setArtifactSorter(si *weles.ArtifactSorter) (so weles.ArtifactSorter) {
+ if si == nil {
+ return weles.ArtifactSorter{
+ SortOrder: weles.SortOrderAscending,
+ SortBy: weles.ArtifactSortByID,
+ }
+ }
+ if si.SortOrder == "" {
+ so.SortOrder = weles.SortOrderAscending
+ } else {
+ so.SortOrder = si.SortOrder
+ }
+ if si.SortBy == "" {
+ so.SortBy = weles.ArtifactSortByID
+ } else {
+ so.SortBy = si.SortBy
+ }
+ return
+}
+
+// setArtifactPaginator creates and fills paginator object with default values.
func setArtifactPaginator(params artifacts.ArtifactListerParams, defaultPageLimit int32,
) (paginator weles.ArtifactPagination) {
paginator.Forward = true
@@ -150,10 +185,9 @@ func setArtifactPaginator(params artifacts.ArtifactListerParams, defaultPageLimi
return paginator
}
-// artifactInfoReceivedToReturn does the same thing as jobInfoReceivedToReturn.
-// TODO:make ArtifactInfos and JobInfos types implement interface with a function that will return
-// slice of pointers. Will probably need to use reflect which I'm not familiar with thus not done
-// now.
+// artifactInfoReceivedToReturn creates slice of pointers from slice of values of ArtifactInfo
+// struct. Very similiar function can be found in job_lister_handler.go. Separate functions are
+// present as generic one would need to use reflect which affects performance.
func artifactInfoReceivedToReturn(artifactInfoReceived []weles.ArtifactInfo) []*weles.ArtifactInfo {
artifactInfoReturned := make([]*weles.ArtifactInfo, len(artifactInfoReceived))
for i := range artifactInfoReceived {
diff --git a/server/artifact_lister_handler_test.go b/server/artifact_lister_handler_test.go
index fc694b9..c24ecb4 100644
--- a/server/artifact_lister_handler_test.go
+++ b/server/artifact_lister_handler_test.go
@@ -23,20 +23,20 @@ import (
"net/http"
"net/http/httptest"
"strconv"
- "strings"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/fixtures"
- "git.tizen.org/tools/weles/mock"
- "git.tizen.org/tools/weles/server"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/fixtures"
+ "github.com/SamsungSLAV/weles/mock"
+ "github.com/SamsungSLAV/weles/server"
+ "github.com/SamsungSLAV/weles/server/operations/artifacts"
)
-var _ = Describe("ArtifactListerHandler", func() {
+var _ = Describe("Listing artifacts with server initialized", func() {
var (
mockCtrl *gomock.Controller
apiDefaults *server.APIDefaults
@@ -44,596 +44,247 @@ var _ = Describe("ArtifactListerHandler", func() {
testserver *httptest.Server
)
- BeforeEach(func() {
- mockCtrl, _, mockArtifactManager, apiDefaults, testserver = testServerSetup()
- })
-
- AfterEach(func() {
- mockCtrl.Finish()
- testserver.Close()
- })
- Describe("Listing artifacts", func() {
- createRequest := func(
- reqBody io.Reader,
- path string,
- query string,
- contentH string,
- acceptH string) (req *http.Request) {
- if path == "" {
- path = "/api/v1/artifacts/list"
- }
- req, err := http.NewRequest(http.MethodPost, testserver.URL+path+query, reqBody)
- Expect(err).ToNot(HaveOccurred())
- req.Header.Set("Content-Type", contentH)
- req.Header.Set("Accept", acceptH)
- return req
- }
-
- filterSorterReqBody := func(filter weles.ArtifactFilter, sorter weles.ArtifactSorter,
- contentH string) (rb *bytes.Reader) {
-
- artifactFilterSort := weles.ArtifactFilterAndSort{
- Filter: &filter,
- Sorter: &sorter}
-
- artifactFilterSortMarshalled, err := json.Marshal(artifactFilterSort)
- Expect(err).ToNot(HaveOccurred())
-
- return bytes.NewReader(artifactFilterSortMarshalled)
-
- }
-
- checkReceivedArtifactInfo := func(respBody []byte, artifactInfo []weles.ArtifactInfo,
- acceptH string) {
-
- artifactInfoMarshalled, err := json.Marshal(artifactInfo)
- Expect(err).ToNot(HaveOccurred())
- Expect(string(respBody)).To(MatchJSON(string(artifactInfoMarshalled)))
-
- }
-
- checkReceivedArtifactErr := func(respBody []byte, e error, acceptH string) {
- errMarshalled, err := json.Marshal(weles.ErrResponse{
- Message: e.Error(),
- Type: ""})
- Expect(err).ToNot(HaveOccurred())
- Expect(string(respBody)).To(MatchJSON(string(errMarshalled)))
- }
-
- //few structs to test against
- emptyFilterA := weles.ArtifactFilter{}
+ type queryPaginator struct {
+ query string
+ paginator weles.ArtifactPagination
+ }
+ // data to test against
+ var (
+ emptyFilter = weles.ArtifactFilter{}
- filledFilterA1 := weles.ArtifactFilter{
+ filledFilter = weles.ArtifactFilter{
Alias: []weles.ArtifactAlias{"sdaaa", "aalliass"},
JobID: []weles.JobID{1, 43, 3},
Status: []weles.ArtifactStatus{
weles.ArtifactStatusDOWNLOADING,
- weles.ArtifactStatusREADY},
+ weles.ArtifactStatusREADY,
+ },
Type: []weles.ArtifactType{
weles.ArtifactTypeRESULT,
- weles.ArtifactTypeYAML}}
+ weles.ArtifactTypeYAML,
+ },
+ }
- filledFilterA2 := weles.ArtifactFilter{
- Alias: []weles.ArtifactAlias{"aalliass"},
- JobID: []weles.JobID{1, 43, 3, 9, 2, 10404},
- Status: []weles.ArtifactStatus{
- weles.ArtifactStatusFAILED},
- Type: []weles.ArtifactType{
- weles.ArtifactTypeRESULT,
- weles.ArtifactTypeYAML}}
+ sorterEmpty = weles.ArtifactSorter{}
- filledSorterA1 := weles.ArtifactSorter{
- SortBy: weles.ArtifactSortByID,
- SortOrder: weles.SortOrderAscending}
+ sorterDescNoBy = weles.ArtifactSorter{
+ SortOrder: weles.SortOrderDescending,
+ }
- filledSorterA2 := weles.ArtifactSorter{
- SortBy: weles.ArtifactSortByID}
+ sorterAscNoBy = weles.ArtifactSorter{
+ SortOrder: weles.SortOrderAscending,
+ }
- emptySorterA := weles.ArtifactSorter{}
+ sorterNoOrderID = weles.ArtifactSorter{
+ SortBy: weles.ArtifactSortByID,
+ }
- emptyPaginatorA := weles.ArtifactPagination{}
- emptyPaginatorFw := weles.ArtifactPagination{Forward: true}
- artifactInfo420 := fixtures.CreateArtifactInfoSlice(420)
+ sorterDescID = weles.ArtifactSorter{
+ SortOrder: weles.SortOrderDescending,
+ SortBy: weles.ArtifactSortByID,
+ }
- type queryPaginator struct {
- query string
- paginator weles.ArtifactPagination
+ sorterAscID = weles.ArtifactSorter{
+ SortOrder: weles.SortOrderAscending,
+ SortBy: weles.ArtifactSortByID,
}
- queryPaginatorOK := []queryPaginator{
- {
- query: "",
- paginator: emptyPaginatorFw},
- {
- query: "?before=10",
- paginator: weles.ArtifactPagination{
- ID: int64(10),
- Forward: false}},
- {
- query: "?before=30&limit=50",
- paginator: weles.ArtifactPagination{
- ID: int64(30),
- Forward: false,
- Limit: 50}},
- {
- query: "?after=40",
- paginator: weles.ArtifactPagination{
- ID: int64(40),
- Forward: true}},
- {
- query: "?after=70",
- paginator: weles.ArtifactPagination{
- ID: int64(70),
- Forward: true,
- Limit: 200}},
- {
- query: "?limit=50",
- paginator: weles.ArtifactPagination{
- ID: int64(0),
- Forward: true,
- Limit: 50}}}
-
- Context("a: Server receives correct request and has pagination turned off", func() {
- // ginkgo does not like It clauses with the same name. To avoid conflicts with
- // tests of listing jobs, each it clause not referring to artifacts explicitly
- // is prefixed with a:
- for _, curr := range queryPaginatorOK { //expected behaviour- handler should ignore
- // different queries when pagination is turned off globally.
- DescribeTable("should respond with all avaliable artifacts, ignoring query params",
- func(
- filter weles.ArtifactFilter,
- sorter weles.ArtifactSorter,
- query string) {
- apiDefaults.PageLimit = 0
-
- listInfo := weles.ListInfo{
- TotalRecords: uint64(len(artifactInfo420)),
- RemainingRecords: 0}
-
- mockArtifactManager.EXPECT().ListArtifact(
- filter, sorter, emptyPaginatorA).Return(
- artifactInfo420, listInfo, nil)
-
- reqBody := filterSorterReqBody(filter, sorter, JSON)
-
- client := testserver.Client()
- req := createRequest(reqBody, "", query, JSON, JSON)
- resp, err := client.Do(req)
- Expect(err).ToNot(HaveOccurred())
-
- defer resp.Body.Close()
- respBody, err := ioutil.ReadAll(resp.Body)
- Expect(err).ToNot(HaveOccurred())
-
- checkReceivedArtifactInfo(respBody, artifactInfo420, JSON)
-
- Expect(resp.StatusCode).To(Equal(200))
- Expect(resp.Header.Get("Next")).To(Equal(""))
- Expect(resp.Header.Get("Previous")).To(Equal(""))
- Expect(resp.Header.Get("RemainingRecords")).To(Equal(""))
- Expect(resp.Header.Get("TotalRecords")).To(Equal(strconv.Itoa(
- len(artifactInfo420))))
-
- },
-
- Entry("a: given empty filter and sorter",
- emptyFilterA, emptySorterA, curr.query),
-
- Entry("a: given filled filter and sorter",
- filledFilterA2, filledSorterA2, curr.query),
-
- Entry("a: given filled filter and empty sorter",
- filledFilterA1, emptySorterA, curr.query),
-
- Entry("a: given empty filter and filled sorter",
- emptyFilterA, filledSorterA1, curr.query),
- )
- }
- })
+ // default value
+ sorterDefault = sorterAscID
- Context("a: Server receives correct request and has pagination turned on", func() {
- artifactInfoAll := fixtures.CreateArtifactInfoSlice(100)
- globalLimit := []int32{70, 100, 111}
- for _, currgl := range globalLimit {
- for _, curr := range queryPaginatorOK {
- // expected behaviour- handler passes query parameters to AM.
- // this should impact data returned by JM. It is not reflected in the
- // below mock of JM as it is out of scope of server unit tests.
- DescribeTable("a: should respond with all artifacts",
- func(artifactInfo []weles.ArtifactInfo,
- filter weles.ArtifactFilter,
- sorter weles.ArtifactSorter,
- paginator weles.ArtifactPagination,
- query string, gl int32) {
-
- apiDefaults.PageLimit = gl
-
- if !strings.Contains(query, "limit") {
- paginator.Limit = apiDefaults.PageLimit
- }
-
- listInfo := weles.ListInfo{
- TotalRecords: uint64(len(artifactInfo)),
- RemainingRecords: 0}
-
- mockArtifactManager.EXPECT().ListArtifact(
- filter, sorter, paginator).Return(
- artifactInfo, listInfo, nil)
-
- reqBody := filterSorterReqBody(filter, sorter, JSON)
- req := createRequest(reqBody, "", query, JSON, JSON)
-
- client := testserver.Client()
- resp, err := client.Do(req)
- Expect(err).ToNot(HaveOccurred())
-
- defer resp.Body.Close()
- respBody, err := ioutil.ReadAll(resp.Body)
- Expect(err).ToNot(HaveOccurred())
-
- checkReceivedArtifactInfo(respBody, artifactInfo, JSON)
-
- Expect(resp.StatusCode).To(Equal(200))
- // Next and Previous headers are ignored here as they are tested
- // in other context.
- Expect(resp.Header.Get("RemainingRecords")).To(Equal(""))
- Expect(resp.Header.Get("TotalRecords")).To(
- Equal(strconv.Itoa(len(artifactInfo))))
- },
- Entry("given empty request when AM has less jobs than page size",
- artifactInfoAll[:40], emptyFilterA, emptySorterA, curr.paginator,
- curr.query, currgl),
-
- Entry("given filled filter, when AM returns less jobs than "+
- "Default Page size",
- artifactInfoAll[10:67], filledFilterA2, emptySorterA, curr.paginator,
- curr.query, currgl),
-
- Entry("given filled filter, when AM returns same amount of filtered jobs"+
- " as Default Page Size",
- artifactInfoAll, filledFilterA1, filledSorterA2, curr.paginator,
- curr.query, currgl),
- )
- }
- }
- })
+ // when pagination is on and no query params are set. When used, limit should also be set.
+ emptyPaginatorOn = weles.ArtifactPagination{Forward: true}
+ // when pagination is off
+ emptyPaginatorOff = weles.ArtifactPagination{}
- Context("a: Pagination on", func() {
- artifactInfoAll := fixtures.CreateArtifactInfoSlice(400)
- DescribeTable("a: paginating forward",
- func(artifactInfo []weles.ArtifactInfo,
- startingPageNo int,
- filter weles.ArtifactFilter,
- sorter weles.ArtifactSorter) {
+ artifactInfo420 = fixtures.CreateArtifactInfoSlice(420)
+ )
- apiDefaults.PageLimit = 100
+ BeforeEach(func() {
+ mockCtrl, _, mockArtifactManager, apiDefaults, testserver = testServerSetup()
+ })
- //prepare data for first call
- artifactInfoStartingPage := artifactInfo[(startingPageNo-1)*
- int(apiDefaults.PageLimit) : startingPageNo*
- int(apiDefaults.PageLimit)] //first page of data
+ AfterEach(func() {
+ mockCtrl.Finish()
+ testserver.Close()
+ })
- startingPageQuery := ""
+ // helper functions
+ createRequest := func(reqBody io.Reader, query, contentH, acceptH string) (req *http.Request) {
+ req, err := http.NewRequest(
+ http.MethodPost, testserver.URL+basePath+listArtifactsPath+query, reqBody)
+ Expect(err).ToNot(HaveOccurred())
+ req.Header.Set("Content-Type", contentH)
+ req.Header.Set("Accept", acceptH)
+ return req
+ }
+
+ createRequestBody := func(f weles.ArtifactFilter, s weles.ArtifactSorter) *bytes.Reader {
+ tomarshall := artifacts.ArtifactListerBody{
+ Filter: &f,
+ Sorter: &s,
+ }
+ marshalled, err := json.Marshal(tomarshall)
+ Expect(err).ToNot(HaveOccurred())
+ return bytes.NewReader(marshalled)
+ }
- paginator := weles.ArtifactPagination{
- Limit: apiDefaults.PageLimit,
- Forward: true,
- }
- if startingPageNo != 1 {
- paginator.Forward = true
- paginator.ID = artifactInfoStartingPage[0].ID
- startingPageQuery = "?after=" +
- strconv.FormatInt(artifactInfo[(startingPageNo-1)*int(
- apiDefaults.PageLimit)].ID, 10)
- }
+ checkReceivedArtifactInfo := func(respBody []byte, artifactInfo []weles.ArtifactInfo) {
- listInfo := weles.ListInfo{
- TotalRecords: uint64(len(artifactInfo)),
- RemainingRecords: uint64(len(artifactInfo) - startingPageNo*len(
- artifactInfoStartingPage)),
- }
+ marshalled, err := json.Marshal(artifactInfo)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(string(respBody)).To(MatchJSON(string(marshalled)))
- first := mockArtifactManager.EXPECT().ListArtifact(
- filter, sorter, paginator).Return(artifactInfoStartingPage, listInfo, nil)
+ }
- reqBody := filterSorterReqBody(filter, sorter, JSON)
- req := createRequest(reqBody, "", startingPageQuery, JSON, JSON)
- req.Close = true
- client := testserver.Client()
- resp, err := client.Do(req)
- Expect(err).ToNot(HaveOccurred())
+ checkReceivedArtifactErr := func(respBody []byte, e error) {
+ errMarshalled, err := json.Marshal(weles.ErrResponse{
+ Message: e.Error(),
+ Type: "",
+ })
+ Expect(err).ToNot(HaveOccurred())
+ Expect(string(respBody)).To(MatchJSON(string(errMarshalled)))
+ }
+
+ Describe("Pagination is turned off", func() {
+ Describe("client sends correct request", func() {
+ It("server should accept empty post request", func() {
+ apiDefaults.PageLimit = 0
+
+ listInfo := weles.ListInfo{
+ TotalRecords: uint64(len(artifactInfo420)),
+ RemainingRecords: 0,
+ }
+ // should pass correct default values of Sorter to ArtifactManager
+ mockArtifactManager.EXPECT().ListArtifact(
+ emptyFilter, sorterDefault, emptyPaginatorOff).Return(
+ artifactInfo420, listInfo, nil)
- respBody, err := ioutil.ReadAll(resp.Body)
- Expect(err).ToNot(HaveOccurred())
+ client := testserver.Client()
+ req := createRequest(nil, "", JSON, JSON)
+ req.Close = true
+ _, err := client.Do(req)
+ Expect(err).ToNot(HaveOccurred())
- checkReceivedArtifactInfo(respBody, artifactInfoStartingPage, JSON)
- Expect(resp.StatusCode).To(Equal(206))
+ })
- Expect(resp.Header.Get("Next")).To(Equal("/api/v1/artifacts/list" + "?after=" +
- strconv.FormatInt(artifactInfoStartingPage[apiDefaults.PageLimit-1].ID,
- 10)))
- prevCheck := ""
- if startingPageNo != 1 {
- prevCheck = "/api/v1/artifacts/list" + "?before=" +
- strconv.FormatInt(artifactInfoStartingPage[0].ID, 10)
- }
- Expect(resp.Header.Get("Previous")).To(Equal(prevCheck))
- Expect(resp.Header.Get("RemainingRecords")).To(
- Equal(strconv.Itoa(len(artifactInfo) - (startingPageNo * len(
- artifactInfoStartingPage)))))
- Expect(resp.Header.Get("TotalRecords")).To(
- Equal(strconv.Itoa(len(artifactInfo))))
-
- nextPage := resp.Header.Get("Next")
- resp.Body.Close()
- testserver.CloseClientConnections()
-
- //prepare data for second call based on previous
- var artifactInfo2 []weles.ArtifactInfo
- var secondReturnCode int
- if (len(artifactInfo) - startingPageNo*
- int(apiDefaults.PageLimit)) <= int(apiDefaults.PageLimit) {
-
- artifactInfo2 = artifactInfo[startingPageNo*int(apiDefaults.PageLimit):]
- //next page is not full
- secondReturnCode = 200
- } else {
- artifactInfo2 = artifactInfo[startingPageNo*
- int(apiDefaults.PageLimit) : (startingPageNo+1)*
- int(apiDefaults.PageLimit)] //last page is full
- secondReturnCode = 206
- }
+ DescribeTable("server should ignore query params",
+ func(query string) {
+ apiDefaults.PageLimit = 0
- paginator2 := weles.ArtifactPagination{
- Limit: apiDefaults.PageLimit,
- Forward: true,
- ID: artifactInfoStartingPage[int(apiDefaults.PageLimit)-
- 1].ID}
- listInfo2 := weles.ListInfo{TotalRecords: listInfo.TotalRecords}
-
- if tmp := len(artifactInfo) - (startingPageNo+1)*int(
- apiDefaults.PageLimit); tmp < 0 {
- listInfo2.RemainingRecords = 0
- } else {
- listInfo2.RemainingRecords = uint64(tmp)
+ listInfo := weles.ListInfo{
+ TotalRecords: uint64(len(artifactInfo420)),
+ RemainingRecords: 0,
}
- //filter and sorter should stay the same.
- mockArtifactManager.EXPECT().ListArtifact(filter, sorter, paginator2).Return(
- artifactInfo2, listInfo2, nil).After(first)
-
- client2 := testserver.Client()
- req2 := createRequest(reqBody, nextPage, "", JSON, JSON)
- req2.Close = true
- resp2, err := client2.Do(req2)
- Expect(err).ToNot(HaveOccurred())
+ mockArtifactManager.EXPECT().ListArtifact(emptyFilter,
+ sorterDefault, emptyPaginatorOff).Return(
+ artifactInfo420, listInfo, nil)
- defer resp2.Body.Close()
- respBody2, err := ioutil.ReadAll(resp2.Body)
+ client := testserver.Client()
+ req := createRequest(nil, query, JSON, JSON)
+ req.Close = true
+ _, err := client.Do(req)
Expect(err).ToNot(HaveOccurred())
-
- checkReceivedArtifactInfo(respBody2, artifactInfo2, JSON)
-
- Expect(resp2.StatusCode).To(Equal(secondReturnCode))
-
- if secondReturnCode == 200 {
- Expect(resp2.Header.Get("Next")).To(Equal(""))
- prevCheck = "/api/v1/artifacts/list" + "?before=" +
- strconv.FormatInt(artifactInfo2[0].ID, 10)
- Expect(resp2.Header.Get("Previous")).To(Equal(prevCheck))
- } else {
- prevCheck = "/api/v1/artifacts/list" + "?before=" +
- strconv.FormatInt(artifactInfo2[0].ID, 10)
- nextCheck := "/api/v1/artifacts/list" + "?after=" +
- strconv.FormatInt(artifactInfo2[int(apiDefaults.PageLimit)-1].ID, 10)
- Expect(resp2.Header.Get("Next")).To(Equal(nextCheck))
- Expect(resp2.Header.Get("Previous")).To(Equal(prevCheck))
- }
- if tmp := strconv.Itoa(len(artifactInfo) -
- startingPageNo*len(artifactInfoStartingPage) -
- len(artifactInfo2)); tmp != "0" {
- Expect(resp2.Header.Get("RemainingRecords")).To(Equal(tmp))
- } else {
-
- Expect(resp2.Header.Get("RemainingRecords")).To(Equal(""))
- }
- Expect(resp2.Header.Get("TotalRecords")).To(
- Equal(strconv.Itoa(len(artifactInfo))))
-
},
- Entry("a: 1->2/2", // from 1 to 2 out of 2 (pages)
- artifactInfoAll[:170], 1, emptyFilterA, emptySorterA),
- Entry("a: 1->2/3",
- artifactInfoAll[:270], 1, emptyFilterA, emptySorterA),
- Entry("a: 2->3/3",
- artifactInfoAll[:300], 2, emptyFilterA, emptySorterA),
- Entry("a: 2->3/4",
- artifactInfoAll[:350], 2, emptyFilterA, emptySorterA),
+
+ Entry("no query params set", ""),
+ Entry("after query set", "?after=50"),
+ Entry("after and limit query set", "?after=50&limit=10"),
+ Entry("after and before query set", "?after=50&before=20"),
+ Entry("after and before and limit query set", "?after=50&before=30&limit=13"),
+ Entry("before query set", "?before=100"),
+ Entry("before and limit query set", "?before=100&limit=12"),
)
- DescribeTable("a: paginating backward",
- func(artifactInfo []weles.ArtifactInfo,
- startingPageNo int, pages int,
- filter weles.ArtifactFilter,
- sorter weles.ArtifactSorter) {
+ DescribeTable("server should pass filter to ArtifactManager",
+ func(filter weles.ArtifactFilter) {
- apiDefaults.PageLimit = 100
- paginator := weles.ArtifactPagination{Limit: apiDefaults.PageLimit}
- //prepare data for first call
- var artifactInfoStartingPage []weles.ArtifactInfo
- var startingPageQuery string
- listInfo := weles.ListInfo{}
- if startingPageNo == pages {
- artifactInfoStartingPage = artifactInfo[(startingPageNo-1)*
- int(apiDefaults.PageLimit) : len(artifactInfo)-1]
- paginator.Forward = true
- paginator.ID = artifactInfoStartingPage[len(artifactInfoStartingPage)-1].ID
- startingPageQuery = "?after=" + strconv.FormatInt(paginator.ID, 10)
- listInfo = weles.ListInfo{
- TotalRecords: uint64(len(artifactInfo)),
- RemainingRecords: 0}
-
- } else {
- artifactInfoStartingPage = artifactInfo[(startingPageNo)*
- int(apiDefaults.PageLimit) : (startingPageNo+1)*
- int(apiDefaults.PageLimit)] //first page of data
- paginator.Forward = false
- paginator.ID = artifactInfo[(startingPageNo*
- int(apiDefaults.PageLimit))-1].ID
- startingPageQuery = "?before=" + strconv.FormatInt(paginator.ID, 10)
- listInfo = weles.ListInfo{
- TotalRecords: uint64(len(artifactInfo)),
- RemainingRecords: uint64(len(artifactInfo) - (int(
- apiDefaults.PageLimit) * startingPageNo))}
+ apiDefaults.PageLimit = 0
+ listInfo := weles.ListInfo{
+ TotalRecords: uint64(len(artifactInfo420)),
+ RemainingRecords: 0,
}
- first := mockArtifactManager.EXPECT().ListArtifact(filter, sorter,
- paginator).Return(artifactInfoStartingPage, listInfo, nil)
+ mockArtifactManager.EXPECT().ListArtifact(
+ filter, sorterDefault, emptyPaginatorOff).Return(
+ artifactInfo420, listInfo, nil)
+ reqBody := createRequestBody(filter, sorterEmpty)
- reqBody := filterSorterReqBody(filter, sorter, JSON)
- req := createRequest(reqBody, "", startingPageQuery, JSON, JSON)
- req.Close = true
client := testserver.Client()
- resp, err := client.Do(req)
- Expect(err).ToNot(HaveOccurred())
+ req := createRequest(reqBody, "", JSON, JSON)
- respBody, err := ioutil.ReadAll(resp.Body)
+ _, err := client.Do(req)
Expect(err).ToNot(HaveOccurred())
+ },
+ Entry("when receiving empty filter", emptyFilter),
+ Entry("when receiving filled filter", filledFilter),
+ )
- checkReceivedArtifactInfo(respBody, artifactInfoStartingPage, JSON)
-
- if startingPageNo == pages {
- Expect(resp.StatusCode).To(Equal(200))
- Expect(resp.Header.Get("Previous")).To(
- Equal("/api/v1/artifacts/list?before=" +
- strconv.FormatInt(artifactInfoStartingPage[0].ID, 10)))
- Expect(resp.Header.Get("Next")).To(Equal(""))
- Expect(resp.Header.Get("TotalRecords")).To(
- Equal(strconv.Itoa(len(artifactInfo))))
- Expect(resp.Header.Get("RemainingRecords")).To(Equal(""))
-
- } else {
- Expect(resp.StatusCode).To(Equal(206))
- Expect(resp.Header.Get("Previous")).To(
- Equal("/api/v1/artifacts/list?before=" +
- strconv.FormatInt(artifactInfoStartingPage[0].ID, 10)))
- Expect(resp.Header.Get("Next")).To(
- Equal("/api/v1/artifacts/list?after=" +
- strconv.FormatInt(artifactInfoStartingPage[len(
- artifactInfoStartingPage)-1].ID, 10)))
- Expect(resp.Header.Get("TotalRecords")).To(
- Equal(strconv.Itoa(len(artifactInfo))))
- Expect(resp.Header.Get("RemainingRecords")).To(
- Equal(strconv.FormatUint(listInfo.RemainingRecords, 10)))
- }
-
- prevPage := resp.Header.Get("Previous")
-
- resp.Body.Close()
- testserver.CloseClientConnections()
+ DescribeTable("server should pass sorter to ArtifactManager, but set default values "+
+ "on empty fields",
+ func(sent, expected weles.ArtifactSorter) {
- //prepare data for second call based on previous
+ apiDefaults.PageLimit = 0
- var artifactInfo2 []weles.ArtifactInfo
- paginator2 := weles.ArtifactPagination{
- Limit: apiDefaults.PageLimit,
- Forward: false,
- ID: artifactInfoStartingPage[0].ID,
+ listInfo := weles.ListInfo{
+ TotalRecords: uint64(len(artifactInfo420)),
+ RemainingRecords: 0,
}
- listInfo2 := weles.ListInfo{TotalRecords: listInfo.TotalRecords}
- if startingPageNo == pages {
- artifactInfo2 = artifactInfo[(startingPageNo-2)*
- int(apiDefaults.PageLimit) : (startingPageNo-1)*
- int(apiDefaults.PageLimit)]
-
- if startingPageNo-1 == 1 {
- listInfo2.RemainingRecords = 0
- } else {
- listInfo2.RemainingRecords = uint64((pages - (startingPageNo - 1)) *
- int(apiDefaults.PageLimit))
- }
- } else {
- artifactInfo2 = artifactInfo[(startingPageNo-1)*
- int(apiDefaults.PageLimit) : startingPageNo*
- int(apiDefaults.PageLimit)]
-
- listInfo2.RemainingRecords = uint64(apiDefaults.PageLimit)
- }
+ mockArtifactManager.EXPECT().ListArtifact(
+ emptyFilter, expected, emptyPaginatorOff).Return(
+ artifactInfo420, listInfo, nil)
+ reqBody := createRequestBody(emptyFilter, sent)
- mockArtifactManager.EXPECT().ListArtifact(filter, sorter, paginator2).Return(
- artifactInfo2, listInfo2, nil).After(first)
- client2 := testserver.Client()
- req2 := createRequest(reqBody, prevPage, "", JSON, JSON)
- req2.Close = true
- resp2, err := client2.Do(req2)
- Expect(err).ToNot(HaveOccurred())
+ client := testserver.Client()
+ req := createRequest(reqBody, "", JSON, JSON)
- defer resp2.Body.Close()
- respBody2, err := ioutil.ReadAll(resp2.Body)
+ _, err := client.Do(req)
Expect(err).ToNot(HaveOccurred())
-
- checkReceivedArtifactInfo(respBody2, artifactInfo2, JSON)
- if startingPageNo == pages {
-
- if startingPageNo-1 == 1 {
- Expect(resp2.StatusCode).To(Equal(200))
- Expect(resp2.Header.Get("RemainingRecords")).To(Equal(""))
- Expect(resp2.Header.Get("Previous")).To(Equal(""))
-
- } else {
- Expect(resp2.StatusCode).To(Equal(206))
- Expect(resp2.Header.Get("RemainingRecords")).To(Equal("100"))
- Expect(resp2.Header.Get("Previous")).To(
- Equal("/api/v1/artifacts/list?before=" +
- strconv.FormatInt(artifactInfo2[0].ID, 10)))
- }
- } else {
- Expect(resp2.StatusCode).To(Equal(206))
- Expect(resp2.Header.Get("RemainingRecords")).To(Equal("100"))
- }
-
- Expect(resp2.Header.Get("Next")).To(
- Equal("/api/v1/artifacts/list?after=" +
- strconv.FormatInt(artifactInfo2[len(artifactInfo2)-1].ID, 10)))
- Expect(resp2.Header.Get("TotalRecords")).To(
- Equal(strconv.Itoa(len(artifactInfo))))
},
- Entry("a: 2->1/2",
- artifactInfoAll[:170], 2, 2, emptyFilterA, emptySorterA),
- Entry("a: 2->1/3",
- artifactInfoAll[:270], 2, 3, emptyFilterA, emptySorterA),
- Entry("a: 3->2/4",
- artifactInfoAll[:350], 3, 4, emptyFilterA, emptySorterA),
- Entry("a: 3->2/3",
- artifactInfoAll[:300], 3, 3, emptyFilterA, emptySorterA),
+ Entry("should set default order and by",
+ sorterEmpty, sorterDefault),
+ Entry("should pass ascending order and by ID",
+ sorterAscID, sorterAscID),
+ Entry("should pass descending order and by ID",
+ sorterDescID, sorterDescID),
+ Entry("should pass descending order and set default by",
+ sorterDescNoBy, weles.ArtifactSorter{
+ SortOrder: sorterDescNoBy.SortOrder,
+ SortBy: sorterDefault.SortBy,
+ }),
+ Entry("should pass ascending order and set default by",
+ sorterAscNoBy, weles.ArtifactSorter{
+ SortOrder: sorterAscNoBy.SortOrder,
+ SortBy: sorterDefault.SortBy,
+ }),
+ Entry("should pass by ID and set default order",
+ sorterNoOrderID, weles.ArtifactSorter{
+ SortOrder: sorterDefault.SortOrder,
+ SortBy: sorterNoOrderID.SortBy,
+ }),
)
- })
- Context("a: There is an error", func() {
- DescribeTable("Server should respond with error from ArtifactManager",
- func(pageLimit, aviArtifacts int, filter weles.ArtifactFilter,
- sorter weles.ArtifactSorter, statusCode int, amerr error) {
+ DescribeTable("should respond with all artifacts and correct headers",
+ func(recordCount int) {
+ apiDefaults.PageLimit = 0
- apiDefaults.PageLimit = int32(pageLimit)
- artifactInfo := fixtures.CreateArtifactInfoSlice(aviArtifacts)
- paginator := weles.ArtifactPagination{Limit: apiDefaults.PageLimit}
+ artifactInfo := fixtures.CreateArtifactInfoSlice(recordCount)
- if pageLimit == 0 {
- paginator.Forward = false
- } else {
- paginator.Forward = true
- }
listInfo := weles.ListInfo{
- TotalRecords: uint64(aviArtifacts),
+ TotalRecords: uint64(len(artifactInfo)),
RemainingRecords: 0,
}
- mockArtifactManager.EXPECT().ListArtifact(filter, sorter, paginator).Return(
- artifactInfo, listInfo, amerr)
- reqBody := filterSorterReqBody(filter, sorter, JSON)
+ mockArtifactManager.EXPECT().ListArtifact(emptyFilter,
+ sorterDefault, emptyPaginatorOff).Return(
+ artifactInfo, listInfo, nil)
+
+ reqBody := createRequestBody(emptyFilter, sorterDefault)
+
client := testserver.Client()
- req := createRequest(reqBody, "", "", JSON, JSON)
+ req := createRequest(reqBody, "", JSON, JSON)
resp, err := client.Do(req)
Expect(err).ToNot(HaveOccurred())
@@ -641,73 +292,166 @@ var _ = Describe("ArtifactListerHandler", func() {
respBody, err := ioutil.ReadAll(resp.Body)
Expect(err).ToNot(HaveOccurred())
- checkReceivedArtifactErr(respBody, amerr, JSON)
+ checkReceivedArtifactInfo(respBody, artifactInfo)
- Expect(resp.StatusCode).To(Equal(statusCode))
+ By("Response must have 200 statuscode")
+ Expect(resp.StatusCode).To(Equal(200))
+ By("Next, Previous, RemainingRecords Headers should not be set")
Expect(resp.Header.Get("Next")).To(Equal(""))
Expect(resp.Header.Get("Previous")).To(Equal(""))
- Expect(resp.Header.Get("TotalRecords")).To(Equal(""))
Expect(resp.Header.Get("RemainingRecords")).To(Equal(""))
+ By("TotalRecords should be set to length of list")
+ Expect(resp.Header.Get("TotalRecords")).To(Equal(strconv.Itoa(
+ len(artifactInfo))))
},
- Entry("404 status, Artifact not found error, "+
- "when server has 0 artifacts avaliable,pagination off",
- 0, 0, emptyFilterA, emptySorterA,
- 404, weles.ErrArtifactNotFound),
-
- Entry("404 status, Artifact not found error "+
- "when server has 0 jobs avaliable, pagination on",
- 100, 0, emptyFilterA, emptySorterA,
- 404, weles.ErrArtifactNotFound),
- Entry("404 status, Artifact not found error, "+
- "when server has 100 artifacts but none fulfilling filter, pagination off",
- 0, 100, filledFilterA1, emptySorterA,
- 404, weles.ErrArtifactNotFound),
- Entry("404status, Artifact not found error "+
- "when server has 100 artifacts but none fulfilling filter, pagination on",
- 100, 100, filledFilterA1, emptySorterA,
- 404, weles.ErrArtifactNotFound),
- Entry("500 status, ArtifactManager unexpected error "+
- "when server has 100 artifacts, pagination off",
- 0, 100, emptyFilterA, emptySorterA,
- 500, errors.New("This is some errors string")),
- Entry("500 status, ArtifactManager unexpected error "+
- "when server has 100 artifacts, pagination on",
- 100, 100, emptyFilterA, emptySorterA,
- 500, errors.New("This is some errors string")),
+ Entry("20 records avaliable", 20),
+ Entry("420 records avaliable", 420),
)
+
})
- DescribeTable("a: Error returned by server due to both before and after query params set",
- func(defaultPageLimit int32, query string, filter weles.ArtifactFilter,
- sorter weles.ArtifactSorter) {
+ })
+
+ Describe("ArtifactManager returns error", func() {
+ DescribeTable("Server should return appropriate status code and error message",
+ func(pageLimit int32, statusCode int, amerr error) {
- apiDefaults.PageLimit = defaultPageLimit
+ apiDefaults.PageLimit = pageLimit
- reqBody := filterSorterReqBody(filter, sorter, JSON)
- req := createRequest(reqBody, "", query, JSON, JSON)
+ listInfo := weles.ListInfo{
+ TotalRecords: uint64(len(artifactInfo420)),
+ RemainingRecords: 0,
+ }
+ var paginator weles.ArtifactPagination
+ if pageLimit == 0 {
+ paginator = emptyPaginatorOff
+ } else {
+ paginator = emptyPaginatorOn
+ paginator.Limit = pageLimit
+ }
+ mockArtifactManager.EXPECT().ListArtifact(
+ emptyFilter, sorterDefault, paginator).Return(
+ artifactInfo420, listInfo, amerr)
+ reqBody := createRequestBody(emptyFilter, sorterDefault)
client := testserver.Client()
+ req := createRequest(reqBody, "", JSON, JSON)
resp, err := client.Do(req)
Expect(err).ToNot(HaveOccurred())
- defer resp.Body.Close()
+ defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
Expect(err).ToNot(HaveOccurred())
- checkReceivedArtifactErr(respBody, weles.ErrBeforeAfterNotAllowed, JSON)
- Expect(resp.StatusCode).To(Equal(400))
+ checkReceivedArtifactErr(respBody, amerr)
+ By("Headers should not be set")
+ Expect(resp.StatusCode).To(Equal(statusCode))
Expect(resp.Header.Get("Next")).To(Equal(""))
Expect(resp.Header.Get("Previous")).To(Equal(""))
Expect(resp.Header.Get("TotalRecords")).To(Equal(""))
Expect(resp.Header.Get("RemainingRecords")).To(Equal(""))
},
- Entry("a: json, pagination off",
- int32(0), "?before=10&after=20", emptyFilterA, emptySorterA),
- Entry("a: json, pagination on",
- int32(100), "?before=10&after=20", emptyFilterA, emptySorterA),
+ Entry("pagination off, 404 status, Artifact not found error",
+ int32(0), 404, weles.ErrArtifactNotFound),
+ Entry("pagination on, 404 status, Artifact not found error",
+ int32(100), 404, weles.ErrArtifactNotFound),
+ Entry("pagination off, 500 status, Unexpected error",
+ int32(0), 500, errors.New("This is unexpected error")),
+ Entry("pagination on, 500 status, Unexpected error",
+ int32(100), 500, errors.New("This is unexpected error")),
)
+ })
+ Describe("Pagination turned on", func() {
+ Describe("Correct request", func() {
+ DescribeTable("server should set paginator object depending on query params",
+ func(query string, expectedPaginator weles.ArtifactPagination) {
+ apiDefaults.PageLimit = 500
+
+ listInfo := weles.ListInfo{
+ TotalRecords: uint64(len(artifactInfo420)),
+ RemainingRecords: 0,
+ }
+
+ mockArtifactManager.EXPECT().ListArtifact(
+ emptyFilter, sorterDefault, expectedPaginator).Return(
+ artifactInfo420, listInfo, nil)
+ reqBody := createRequestBody(emptyFilter, sorterDefault)
+
+ client := testserver.Client()
+ req := createRequest(reqBody, query, JSON, JSON)
+ _, err := client.Do(req)
+ Expect(err).ToNot(HaveOccurred())
+ },
+ Entry("when no query params set", "",
+ weles.ArtifactPagination{Forward: true, Limit: 500}),
+ Entry("when after param is set", "?after=30",
+ weles.ArtifactPagination{Forward: true, Limit: 500, ID: 30}),
+ Entry("when after and limit params are set", "?after=30&limit=20",
+ weles.ArtifactPagination{Forward: true, Limit: 20, ID: 30}),
+ Entry("when before param is set", "?before=30",
+ weles.ArtifactPagination{Forward: false, Limit: 500, ID: 30}),
+ Entry("when before and limit params are set", "?before=30&limit=15",
+ weles.ArtifactPagination{Forward: false, Limit: 15, ID: 30}),
+ Entry("when limit param is set", "?limit=30",
+ weles.ArtifactPagination{Forward: true, Limit: 30}),
+ )
+
+ DescribeTable("server should respond with 200/206 depending on "+
+ "ListInfo.RemainingRecords returned by ArtifactManager",
+ func(listInfo weles.ListInfo, statusCode int) {
+
+ apiDefaults.PageLimit = 100
+ paginator := emptyPaginatorOn
+ paginator.Limit = apiDefaults.PageLimit
+ mockArtifactManager.EXPECT().
+ ListArtifact(emptyFilter, sorterDefault, paginator).
+ Return(artifactInfo420, listInfo, nil)
+ reqBody := createRequestBody(emptyFilter, sorterDefault)
+
+ client := testserver.Client()
+ req := createRequest(reqBody, "", JSON, JSON)
+ _, err := client.Do(req)
+ Expect(err).ToNot(HaveOccurred())
+
+ //TODO: check headers
+ },
+ Entry("No more artifacts",
+ weles.ListInfo{RemainingRecords: 0}, 200),
+ Entry("More artifacts to show",
+ weles.ListInfo{RemainingRecords: 320}, 206),
+ )
+ })
+
+ Describe("Error ", func() {
+ DescribeTable("returned by server due to both before and after query params set",
+ func(query string) {
+ apiDefaults.PageLimit = 100
+
+ req := createRequest(nil, query, JSON, JSON)
+
+ client := testserver.Client()
+ resp, err := client.Do(req)
+ Expect(err).ToNot(HaveOccurred())
+ defer resp.Body.Close()
+
+ respBody, err := ioutil.ReadAll(resp.Body)
+ Expect(err).ToNot(HaveOccurred())
+ checkReceivedArtifactErr(respBody, weles.ErrBeforeAfterNotAllowed)
+
+ Expect(resp.StatusCode).To(Equal(400))
+ By("Headers should not be set")
+ Expect(resp.Header.Get("Next")).To(Equal(""))
+ Expect(resp.Header.Get("Previous")).To(Equal(""))
+ Expect(resp.Header.Get("TotalRecords")).To(Equal(""))
+ Expect(resp.Header.Get("RemainingRecords")).To(Equal(""))
+
+ },
+ Entry("empty body", "?before=10&after=20"),
+ Entry("empty body, additional limit query set", "?before=10&after=20&limit=10"),
+ )
+ })
})
})
diff --git a/server/configure_weles.go b/server/configure_weles.go
index 8835f92..f5440b3 100644
--- a/server/configure_weles.go
+++ b/server/configure_weles.go
@@ -24,9 +24,16 @@ import (
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
- "git.tizen.org/tools/weles/server/operations"
- "git.tizen.org/tools/weles/server/operations/artifacts"
- "git.tizen.org/tools/weles/server/operations/jobs"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/server/operations"
+ "github.com/SamsungSLAV/weles/server/operations/artifacts"
+ "github.com/SamsungSLAV/weles/server/operations/general"
+ "github.com/SamsungSLAV/weles/server/operations/jobs"
+)
+
+const (
+ apiVersion = "v1"
+ apiState = weles.VersionStateDevel
)
func configureFlags(api *operations.WelesAPI) {
@@ -58,6 +65,8 @@ func welesConfigureAPI(api *operations.WelesAPI, a *APIDefaults) http.Handler {
api.ArtifactsArtifactListerHandler = artifacts.ArtifactListerHandlerFunc(a.ArtifactLister)
+ api.GeneralVersionHandler = general.VersionHandlerFunc(a.Version)
+
api.ServerShutdown = func() {}
return setupGlobalMiddleware(api.Serve(setupMiddlewares))
diff --git a/server/doc.go b/server/doc.go
index 41796c5..5defa69 100644
--- a/server/doc.go
+++ b/server/doc.go
@@ -28,7 +28,7 @@ http://tbd.tbd/terms/
http
Host: localhost:8088
BasePath: /api/v1
- Version: 0.0.0
+ Version: v1
License: Apache 2.0 http://www.apache.org/licenses/LICENSE-2.0.html
Contact: <tbd@tbd.com>
diff --git a/server/embedded_spec.go b/server/embedded_spec.go
index 8197aae..b0a831f 100644
--- a/server/embedded_spec.go
+++ b/server/embedded_spec.go
@@ -54,7 +54,7 @@ func init() {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
- "version": "0.0.0"
+ "version": "v1"
},
"host": "localhost:8088",
"basePath": "/api/v1",
@@ -79,7 +79,16 @@ func init() {
"name": "artifactFilterAndSort",
"in": "body",
"schema": {
- "$ref": "#/definitions/ArtifactFilterAndSort"
+ "description": "Data for filtering and sorting Weles Jobs lists.",
+ "type": "object",
+ "properties": {
+ "Filter": {
+ "$ref": "#/definitions/ArtifactFilter"
+ },
+ "Sorter": {
+ "$ref": "#/definitions/ArtifactSorter"
+ }
+ }
}
},
{
@@ -236,7 +245,16 @@ func init() {
"name": "jobFilterAndSort",
"in": "body",
"schema": {
- "$ref": "#/definitions/JobFilterAndSort"
+ "description": "Data for filtering and sorting Weles Jobs lists.",
+ "type": "object",
+ "properties": {
+ "Filter": {
+ "$ref": "#/definitions/JobFilter"
+ },
+ "Sorter": {
+ "$ref": "#/definitions/JobSorter"
+ }
+ }
}
},
{
@@ -369,6 +387,44 @@ func init() {
}
}
}
+ },
+ "/version": {
+ "get": {
+ "description": "Version and state of API (e.g. v1 obsolete, v2 stable, v3 devel) and server version.",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "general"
+ ],
+ "summary": "Show current version of Weles internals",
+ "operationId": "Version",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/Version"
+ },
+ "headers": {
+ "Weles-API-State": {
+ "type": "string",
+ "description": "State of Weles API."
+ },
+ "Weles-API-Version": {
+ "type": "string",
+ "description": "Version of Weles API."
+ },
+ "Weles-Server-Version": {
+ "type": "string",
+ "description": "Version of Weles server."
+ }
+ }
+ },
+ "500": {
+ "$ref": "#/responses/InternalServer"
+ }
+ }
+ }
}
},
"definitions": {
@@ -425,18 +481,6 @@ func init() {
}
}
},
- "ArtifactFilterAndSort": {
- "description": "Data for filtering and sorting Weles Jobs lists.",
- "type": "object",
- "properties": {
- "Filter": {
- "$ref": "#/definitions/ArtifactFilter"
- },
- "Sorter": {
- "$ref": "#/definitions/ArtifactSorter"
- }
- }
- },
"ArtifactInfo": {
"description": "describes single artifact stored in ArtifactDB.",
"type": "object",
@@ -571,18 +615,6 @@ func init() {
}
}
},
- "JobFilterAndSort": {
- "description": "Data for filtering and sorting Weles Jobs lists.",
- "type": "object",
- "properties": {
- "Filter": {
- "$ref": "#/definitions/JobFilter"
- },
- "Sorter": {
- "$ref": "#/definitions/JobSorter"
- }
- }
- },
"JobID": {
"description": "is a unique identifier for Weles Job.",
"type": "integer",
@@ -621,9 +653,10 @@ func init() {
}
},
"JobSortBy": {
- "description": "denotes key for sorting Jobs list. Jobs are sorted by ID (Ascending) by default.\nYou can sort jobs additionaly by\n\n* CreatedDate - sorting by date of creation of the weles job.\n\n* UpdatedDate - sorting by date of update of the weles job.\n\n* JobStatus - sorting by the Job Status. Descending order will sort in the order JobStatuses are listed in the docs (from NEW at the start to CANCELED at the end). Ascending will reverse this order.\nWhen sorting is applied, and there are many jobs with the same date/status, they will be sorted by JobID (Ascending)\n",
+ "description": "denotes key for sorting Jobs list.\n\n* ID - default sort key.\n\n* CreatedDate - sorting by date of creation of the weles job.\n\n* UpdatedDate - sorting by date of update of the weles job.\n\n* JobStatus - sorting by the Job Status. Descending order will sort in the order JobStatuses are listed in the docs (from NEW at the start to CANCELED at the end). Ascending will reverse this order.\n\nWhen sorting is applied, and there are many jobs with the same date/status, they will be sorted by JobID (Ascending)\n",
"type": "string",
"enum": [
+ "ID",
"CreatedDate",
"UpdatedDate",
"JobStatus"
@@ -662,6 +695,29 @@ func init() {
"Ascending",
"Descending"
]
+ },
+ "Version": {
+ "description": "defines version of Weles API (and its state) and server.\n",
+ "type": "object",
+ "properties": {
+ "API": {
+ "description": "Version of Weles API.",
+ "type": "string"
+ },
+ "Server": {
+ "description": "Version of Weles server.",
+ "type": "string"
+ },
+ "State": {
+ "description": "State of Weles API.",
+ "type": "string",
+ "enum": [
+ "devel",
+ "stable",
+ "deprecated"
+ ]
+ }
+ }
}
},
"responses": {
@@ -710,6 +766,10 @@ func init() {
{
"description": "Info about all artifacts used by Weles jobs.",
"name": "artifacts"
+ },
+ {
+ "description": "Info about Weles (e.g. version)",
+ "name": "general"
}
],
"externalDocs": {
@@ -739,7 +799,7 @@ func init() {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
- "version": "0.0.0"
+ "version": "v1"
},
"host": "localhost:8088",
"basePath": "/api/v1",
@@ -764,7 +824,16 @@ func init() {
"name": "artifactFilterAndSort",
"in": "body",
"schema": {
- "$ref": "#/definitions/ArtifactFilterAndSort"
+ "description": "Data for filtering and sorting Weles Jobs lists.",
+ "type": "object",
+ "properties": {
+ "Filter": {
+ "$ref": "#/definitions/ArtifactFilter"
+ },
+ "Sorter": {
+ "$ref": "#/definitions/ArtifactSorter"
+ }
+ }
}
},
{
@@ -939,7 +1008,16 @@ func init() {
"name": "jobFilterAndSort",
"in": "body",
"schema": {
- "$ref": "#/definitions/JobFilterAndSort"
+ "description": "Data for filtering and sorting Weles Jobs lists.",
+ "type": "object",
+ "properties": {
+ "Filter": {
+ "$ref": "#/definitions/JobFilter"
+ },
+ "Sorter": {
+ "$ref": "#/definitions/JobSorter"
+ }
+ }
}
},
{
@@ -1090,6 +1168,47 @@ func init() {
}
}
}
+ },
+ "/version": {
+ "get": {
+ "description": "Version and state of API (e.g. v1 obsolete, v2 stable, v3 devel) and server version.",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "general"
+ ],
+ "summary": "Show current version of Weles internals",
+ "operationId": "Version",
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/Version"
+ },
+ "headers": {
+ "Weles-API-State": {
+ "type": "string",
+ "description": "State of Weles API."
+ },
+ "Weles-API-Version": {
+ "type": "string",
+ "description": "Version of Weles API."
+ },
+ "Weles-Server-Version": {
+ "type": "string",
+ "description": "Version of Weles server."
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server error",
+ "schema": {
+ "$ref": "#/definitions/ErrResponse"
+ }
+ }
+ }
+ }
}
},
"definitions": {
@@ -1146,18 +1265,6 @@ func init() {
}
}
},
- "ArtifactFilterAndSort": {
- "description": "Data for filtering and sorting Weles Jobs lists.",
- "type": "object",
- "properties": {
- "Filter": {
- "$ref": "#/definitions/ArtifactFilter"
- },
- "Sorter": {
- "$ref": "#/definitions/ArtifactSorter"
- }
- }
- },
"ArtifactInfo": {
"description": "describes single artifact stored in ArtifactDB.",
"type": "object",
@@ -1292,18 +1399,6 @@ func init() {
}
}
},
- "JobFilterAndSort": {
- "description": "Data for filtering and sorting Weles Jobs lists.",
- "type": "object",
- "properties": {
- "Filter": {
- "$ref": "#/definitions/JobFilter"
- },
- "Sorter": {
- "$ref": "#/definitions/JobSorter"
- }
- }
- },
"JobID": {
"description": "is a unique identifier for Weles Job.",
"type": "integer",
@@ -1342,9 +1437,10 @@ func init() {
}
},
"JobSortBy": {
- "description": "denotes key for sorting Jobs list. Jobs are sorted by ID (Ascending) by default.\nYou can sort jobs additionaly by\n\n* CreatedDate - sorting by date of creation of the weles job.\n\n* UpdatedDate - sorting by date of update of the weles job.\n\n* JobStatus - sorting by the Job Status. Descending order will sort in the order JobStatuses are listed in the docs (from NEW at the start to CANCELED at the end). Ascending will reverse this order.\nWhen sorting is applied, and there are many jobs with the same date/status, they will be sorted by JobID (Ascending)\n",
+ "description": "denotes key for sorting Jobs list.\n\n* ID - default sort key.\n\n* CreatedDate - sorting by date of creation of the weles job.\n\n* UpdatedDate - sorting by date of update of the weles job.\n\n* JobStatus - sorting by the Job Status. Descending order will sort in the order JobStatuses are listed in the docs (from NEW at the start to CANCELED at the end). Ascending will reverse this order.\n\nWhen sorting is applied, and there are many jobs with the same date/status, they will be sorted by JobID (Ascending)\n",
"type": "string",
"enum": [
+ "ID",
"CreatedDate",
"UpdatedDate",
"JobStatus"
@@ -1383,6 +1479,29 @@ func init() {
"Ascending",
"Descending"
]
+ },
+ "Version": {
+ "description": "defines version of Weles API (and its state) and server.\n",
+ "type": "object",
+ "properties": {
+ "API": {
+ "description": "Version of Weles API.",
+ "type": "string"
+ },
+ "Server": {
+ "description": "Version of Weles server.",
+ "type": "string"
+ },
+ "State": {
+ "description": "State of Weles API.",
+ "type": "string",
+ "enum": [
+ "devel",
+ "stable",
+ "deprecated"
+ ]
+ }
+ }
}
},
"responses": {
@@ -1431,6 +1550,10 @@ func init() {
{
"description": "Info about all artifacts used by Weles jobs.",
"name": "artifacts"
+ },
+ {
+ "description": "Info about Weles (e.g. version)",
+ "name": "general"
}
],
"externalDocs": {
diff --git a/server/job_canceler_handler.go b/server/job_canceler_handler.go
index 449226f..fe725bf 100644
--- a/server/job_canceler_handler.go
+++ b/server/job_canceler_handler.go
@@ -15,8 +15,8 @@
package server
import (
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/server/operations/jobs"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/server/operations/jobs"
middleware "github.com/go-openapi/runtime/middleware"
)
diff --git a/server/job_canceler_handler_test.go b/server/job_canceler_handler_test.go
index c918c5e..c1e36bf 100644
--- a/server/job_canceler_handler_test.go
+++ b/server/job_canceler_handler_test.go
@@ -26,8 +26,8 @@ import (
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/mock"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/mock"
)
var _ = Describe("JobCancelerHandler", func() {
diff --git a/server/job_creator_handler.go b/server/job_creator_handler.go
index 70bacbd..17ca942 100644
--- a/server/job_creator_handler.go
+++ b/server/job_creator_handler.go
@@ -15,8 +15,8 @@
package server
import (
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/server/operations/jobs"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/server/operations/jobs"
middleware "github.com/go-openapi/runtime/middleware"
"io/ioutil"
diff --git a/server/job_creator_handler_test.go b/server/job_creator_handler_test.go
index c536436..11cba31 100644
--- a/server/job_creator_handler_test.go
+++ b/server/job_creator_handler_test.go
@@ -29,10 +29,10 @@ import (
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/mock"
- "git.tizen.org/tools/weles/server"
- "git.tizen.org/tools/weles/server/operations/jobs"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/mock"
+ "github.com/SamsungSLAV/weles/server"
+ "github.com/SamsungSLAV/weles/server/operations/jobs"
)
var _ = Describe("JobCreatorHandler", func() {
diff --git a/server/job_lister_handler.go b/server/job_lister_handler.go
index 8b10697..e1c7c58 100644
--- a/server/job_lister_handler.go
+++ b/server/job_lister_handler.go
@@ -15,35 +15,29 @@
package server
import (
+ "time"
+
"github.com/go-openapi/runtime/middleware"
+ "github.com/go-openapi/strfmt"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/server/operations/jobs"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/server/operations/jobs"
)
// JobLister is a handler which passess requests for listing jobs to jobmanager.
func (a *APIDefaults) JobLister(params jobs.JobListerParams) middleware.Responder {
- if (params.After != nil) && (params.Before != nil) {
- return jobs.NewJobListerBadRequest().WithPayload(
- &weles.ErrResponse{Message: weles.ErrBeforeAfterNotAllowed.Error()})
- }
-
- var jobInfoReceived []weles.JobInfo
- var listInfo weles.ListInfo
- var err error
paginator := weles.JobPagination{}
-
if a.PageLimit != 0 {
+ if (params.After != nil) && (params.Before != nil) {
+ return jobs.NewJobListerBadRequest().WithPayload(
+ &weles.ErrResponse{Message: weles.ErrBeforeAfterNotAllowed.Error()})
+ }
paginator = setJobPaginator(params, a.PageLimit)
}
+ filter := setJobFilter(params.JobFilterAndSort.Filter)
+ sorter := setJobSorter(params.JobFilterAndSort.Sorter)
- if params.JobFilterAndSort != nil {
- jobInfoReceived, listInfo, err = a.Managers.JM.ListJobs(
- *params.JobFilterAndSort.Filter, *params.JobFilterAndSort.Sorter, paginator)
- } else {
- jobInfoReceived, listInfo, err = a.Managers.JM.ListJobs(
- weles.JobFilter{}, weles.JobSorter{}, paginator)
- }
+ jobInfoReceived, listInfo, err := a.Managers.JM.ListJobs(filter, sorter, paginator)
if err != nil {
// due to weles.ErrInvalidArgument implementing error interface rather than being error
// (which is intentional as we want to pass underlying error) switch err.(type) checks only
@@ -68,7 +62,6 @@ func (a *APIDefaults) JobLister(params jobs.JobListerParams) middleware.Responde
return responder200(listInfo, paginator, jobInfoReturned, a.PageLimit)
}
return responder206(listInfo, paginator, jobInfoReturned, a.PageLimit)
-
}
func responder206(listInfo weles.ListInfo, paginator weles.JobPagination,
@@ -134,6 +127,49 @@ func responder200(listInfo weles.ListInfo, paginator weles.JobPagination,
return
}
+// normalizeDate is a helper function - adjusts 0 value to "0001-01-01T00:00:00.000Z" instead of
+// Unix 0 "1970-01-01T00:00:00.000Z". This is required by controller.
+func normalizeDate(i strfmt.DateTime) strfmt.DateTime {
+ if time.Time(i).Unix() != 0 {
+ return i
+ }
+ return strfmt.DateTime{}
+}
+
+// setJobFilter adjusts filter's 0 values to be consistent and acceptable by controller.
+// Controller treats slices with 0 len as empty, slices with lenght of 1 and empty value should not
+// be passed to controller.
+func setJobFilter(i *weles.JobFilter) (o weles.JobFilter) {
+ if i != nil {
+ o.CreatedBefore = normalizeDate(i.CreatedBefore)
+ o.CreatedAfter = normalizeDate(i.CreatedAfter)
+ o.UpdatedBefore = normalizeDate(i.UpdatedBefore)
+ o.UpdatedAfter = normalizeDate(i.UpdatedAfter)
+
+ if len(i.JobID) > 0 {
+ if !(len(i.JobID) == 1 && i.JobID[0] == 0) {
+ o.JobID = i.JobID
+ }
+ }
+ if len(i.Info) > 0 {
+ if !(len(i.Info) == 1 && i.Info[0] == "") {
+ o.Info = i.Info
+ }
+ }
+ if len(i.Name) > 0 {
+ if !(len(i.Name) == 1 && i.Name[0] == "") {
+ o.Name = i.Name
+ }
+ }
+ if len(i.Status) > 0 {
+ if !(len(i.Status) == 1 && i.Status[0] == "") {
+ o.Status = i.Status
+ }
+ }
+ }
+ return
+}
+
func setJobPaginator(params jobs.JobListerParams, defaultPageLimit int32,
) (paginator weles.JobPagination) {
paginator.Forward = true
@@ -152,6 +188,27 @@ func setJobPaginator(params jobs.JobListerParams, defaultPageLimit int32,
return
}
+// setJobSorter sets default sorter values.
+func setJobSorter(si *weles.JobSorter) (so weles.JobSorter) {
+ if si == nil {
+ return weles.JobSorter{
+ SortOrder: weles.SortOrderAscending,
+ SortBy: weles.JobSortByID,
+ }
+ }
+ if si.SortOrder == "" {
+ so.SortOrder = weles.SortOrderAscending
+ } else {
+ so.SortOrder = si.SortOrder
+ }
+ if si.SortBy == "" {
+ so.SortBy = weles.JobSortByID
+ } else {
+ so.SortBy = si.SortBy
+ }
+ return
+}
+
//jobInfoReceivedToReturned is a function which changes the slice of values to slice of pointers.
//It is required due to fact that swagger generates responses as slices of pointers rather than
//slices of values that the interface provides.
diff --git a/server/job_lister_handler_test.go b/server/job_lister_handler_test.go
index c64ae16..e76a924 100644
--- a/server/job_lister_handler_test.go
+++ b/server/job_lister_handler_test.go
@@ -23,22 +23,21 @@ import (
"net/http"
"net/http/httptest"
"strconv"
- "strings"
"time"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/mock"
- "git.tizen.org/tools/weles/server"
-
"github.com/go-openapi/strfmt"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
-)
-var _ = Describe("JobListerHandler", func() {
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/mock"
+ "github.com/SamsungSLAV/weles/server"
+ "github.com/SamsungSLAV/weles/server/operations/jobs"
+)
+var _ = Describe("Listing jobs with server initialized", func() {
var (
mockCtrl *gomock.Controller
apiDefaults *server.APIDefaults
@@ -46,676 +45,412 @@ var _ = Describe("JobListerHandler", func() {
testserver *httptest.Server
)
- BeforeEach(func() {
- mockCtrl, mockJobManager, _, apiDefaults, testserver = testServerSetup()
- })
-
- AfterEach(func() {
- mockCtrl.Finish()
- testserver.Close()
- })
+ type queryPaginator struct {
+ query string
+ paginator weles.JobPagination
+ }
+ // data to test against
+ var (
+ emptyJobFilter = weles.JobFilter{}
- Describe("Listing jobs", func() {
- createRequest := func(
- reqBody io.Reader,
- path string,
- query string,
- contentH string,
- acceptH string) (req *http.Request) {
- if path == "" {
- path = "/api/v1/jobs/list"
- }
- req, err := http.NewRequest(http.MethodPost, testserver.URL+path+query, reqBody)
- Expect(err).ToNot(HaveOccurred())
- req.Header.Set("Content-Type", contentH)
- req.Header.Set("Accept", acceptH)
- return req
+ filledJobFilter = weles.JobFilter{
+ JobID: []weles.JobID{10, 100, 131},
+ Info: []string{"something", "and something else"},
+ Name: []string{"name123"},
+ // time.Date nsec arg must be 0 as it is 0ed out when transported via api
+ CreatedAfter: strfmt.DateTime(time.Date(2017, time.May, 3, 11, 34, 55, 0, time.UTC)),
}
- filterSorterReqBody := func(
- filter weles.JobFilter,
- sorter weles.JobSorter,
- contentH string) (
- rb *bytes.Reader) {
-
- jobFilterSort := weles.JobFilterAndSort{
- Filter: &filter,
- Sorter: &sorter}
+ sorterEmpty = weles.JobSorter{}
- jobFilterSortMarshalled, err := json.Marshal(jobFilterSort)
- Expect(err).ToNot(HaveOccurred())
+ sorterDescNoBy = weles.JobSorter{
+ SortOrder: weles.SortOrderDescending,
+ }
- return bytes.NewReader(jobFilterSortMarshalled)
+ sorterAscNoBy = weles.JobSorter{
+ SortOrder: weles.SortOrderAscending,
+ }
+ sorterNoOrderID = weles.JobSorter{
+ SortBy: weles.JobSortByID,
}
- checkReceivedJobInfo := func(respBody []byte, jobInfo []weles.JobInfo, acceptH string) {
- jobInfoMarshalled, err := json.Marshal(jobInfo)
- Expect(err).ToNot(HaveOccurred())
- Expect(string(respBody)).To(MatchJSON(string(jobInfoMarshalled)))
+ sorterNoOrderCreatedDate = weles.JobSorter{
+ SortBy: weles.JobSortByCreatedDate,
+ }
+ sorterDescID = weles.JobSorter{
+ SortOrder: weles.SortOrderDescending,
+ SortBy: weles.JobSortByID,
}
- checkReceivedErr := func(respBody []byte, jmerr error, acceptH string) {
- errMarshalled, err := json.Marshal(weles.ErrResponse{
- Message: jmerr.Error(),
- Type: ""})
- Expect(err).ToNot(HaveOccurred())
- Expect(string(respBody)).To(MatchJSON(string(errMarshalled)))
+ sorterAscID = weles.JobSorter{
+ SortOrder: weles.SortOrderAscending,
+ SortBy: weles.JobSortByID,
}
- //few structs to test against
- someTime := strfmt.DateTime(time.Date(2017, time.May, 3, 11, 34, 55, 0, time.UTC))
- // time.Date nsec argument must be 0 as it is 0ed out when transported via api.
+ // default value
+ sorterDefault = sorterAscID
- filledFilter1 := weles.JobFilter{
- CreatedAfter: someTime,
- Status: []weles.JobStatus{
- weles.JobStatusNEW,
- weles.JobStatusPARSING,
- weles.JobStatusDOWNLOADING}}
+ // when pagination is on and no query params are set. When used, limit should also be set.
+ emptyPaginatorOn = weles.JobPagination{Forward: true}
+ // when pagination is off
+ emptyPaginatorOff = weles.JobPagination{}
- filledFilter2 := weles.JobFilter{
- JobID: []weles.JobID{10, 100, 131},
- Info: []string{
- "something",
- "something else",
- "some really different thing"}}
-
- filledFilter3 := weles.JobFilter{
- UpdatedBefore: someTime,
- Name: []string{
- "daass",
- "sdasa",
- "asdasf32qw;;dq"}}
-
- emptyFilter := weles.JobFilter{}
-
- filledSorter1 := weles.JobSorter{
- SortBy: weles.JobSortByCreatedDate,
- SortOrder: weles.SortOrderAscending}
-
- filledSorter2 := weles.JobSorter{
- SortBy: weles.JobSortByJobStatus,
- SortOrder: weles.SortOrderDescending}
-
- emptySorter := weles.JobSorter{}
-
- emptyPaginator := weles.JobPagination{}
- emptyPaginator2 := weles.JobPagination{Forward: true}
- after100 := "?after=100"
- pAfter100 := weles.JobPagination{
- JobID: weles.JobID(100),
- Forward: true}
- after100Limit50 := "?after=100&limit=50"
- pAfter100Limit50 := weles.JobPagination{
- JobID: weles.JobID(100),
- Forward: true,
- Limit: int32(50)}
-
- before100 := "?before=100"
- pBefore100 := weles.JobPagination{
- JobID: weles.JobID(100),
- Forward: false}
-
- before100Limit50 := "?before=100&limit=50"
- pBefore100Limit50 := weles.JobPagination{
- JobID: weles.JobID(100),
- Forward: false,
- Limit: int32(50)}
-
- limit50 := "?limit=50"
- pLimit50 := weles.JobPagination{
- Forward: true,
- Limit: int32(50)}
-
- type queryPaginator struct {
- query string
- paginator weles.JobPagination
+ jobInfo420 = createJobInfoSlice(420)
+ )
+
+ BeforeEach(func() {
+ mockCtrl, mockJobManager, _, apiDefaults, testserver = testServerSetup()
+ })
+
+ AfterEach(func() {
+ mockCtrl.Finish()
+ testserver.Close()
+ })
+
+ // helper functions
+ createRequest := func(reqBody io.Reader, query, contentH, acceptH string) (req *http.Request) {
+ req, err := http.NewRequest(http.MethodPost, testserver.URL+basePath+listJobsPath+query,
+ reqBody)
+ Expect(err).ToNot(HaveOccurred())
+ req.Header.Set("Content-Type", contentH)
+ req.Header.Set("Accept", acceptH)
+ return req
+ }
+
+ createRequestBody := func(f weles.JobFilter, s weles.JobSorter) *bytes.Reader {
+ tomarshall := jobs.JobListerBody{
+ Filter: &f,
+ Sorter: &s,
}
+ marshalled, err := json.Marshal(tomarshall)
+ Expect(err).ToNot(HaveOccurred())
+ return bytes.NewReader(marshalled)
+ }
- queryPaginatorOK := []queryPaginator{
- {
- query: "",
- paginator: emptyPaginator2},
- {
- query: before100,
- paginator: pBefore100},
- {
- query: before100Limit50,
- paginator: pBefore100Limit50},
- {
- query: after100,
- paginator: pAfter100},
- {
- query: after100Limit50,
- paginator: pAfter100Limit50},
- {
- query: limit50,
- paginator: pLimit50}}
-
- queriesOK := []string{"", before100, before100Limit50, after100, after100Limit50, limit50}
-
- jobInfoSlice420 := createJobInfoSlice(420)
-
- Context("j: Server receives correct request and has pagination turned off", func() {
- for _, currQuery := range queriesOK { // expected behaviour - handler should ignore
- // different queries when pagination is turned off globally.
- DescribeTable("should respond with all avaliable jobs, ignoring query params",
- func(filter weles.JobFilter, sorter weles.JobSorter, query string) {
- apiDefaults.PageLimit = 0
-
- listInfo := weles.ListInfo{
- TotalRecords: uint64(len(jobInfoSlice420)),
- RemainingRecords: 0}
-
- mockJobManager.EXPECT().ListJobs(
- filter, sorter, emptyPaginator).Return(
- jobInfoSlice420, listInfo, nil)
-
- reqBody := filterSorterReqBody(filter, sorter, JSON)
-
- client := testserver.Client()
- req := createRequest(reqBody, "", query, JSON, JSON)
- resp, err := client.Do(req)
- Expect(err).ToNot(HaveOccurred())
-
- defer resp.Body.Close()
- respBody, err := ioutil.ReadAll(resp.Body)
- Expect(err).ToNot(HaveOccurred())
-
- checkReceivedJobInfo(respBody, jobInfoSlice420, JSON)
-
- Expect(resp.StatusCode).To(Equal(200))
- Expect(resp.Header.Get("Next")).To(Equal(""))
- Expect(resp.Header.Get("Previous")).To(Equal(""))
- Expect(resp.Header.Get("RemainingRecords")).To(Equal(""))
- Expect(resp.Header.Get("TotalRecords")).To(Equal(strconv.Itoa(len(
- jobInfoSlice420))))
-
- },
-
- Entry("given empty filter and sorter", emptyFilter, emptySorter,
- currQuery),
-
- Entry("given filled filter and sorter", filledFilter2, filledSorter2,
- currQuery),
-
- Entry("given filled filter and empty sorter", filledFilter1, emptySorter,
- currQuery),
-
- Entry("given empty filter and filled sorter", emptyFilter, filledSorter1,
- currQuery),
- )
- }
- })
+ checkReceivedJobInfo := func(respBody []byte, jobInfo []weles.JobInfo) {
- Context("server receives correct request and has pagination turned on", func() {
- jobInfoAll := createJobInfoSlice(100)
- globalLimit := []int32{70, 100, 111}
- for _, currgl := range globalLimit {
- for _, curr := range queryPaginatorOK {
- // expected behaviour - handler passes query parameters to JM.
- // this should impact data returned by JM. It is not reflected in the
- // below mock of JM as it is out of scope of server unit tests.
- DescribeTable("should respond with all jobs",
- func(jobInfo []weles.JobInfo,
- filter weles.JobFilter,
- sorter weles.JobSorter,
- paginator weles.JobPagination,
- query string, gl int32) {
-
- apiDefaults.PageLimit = gl
-
- if !strings.Contains(query, "limit") {
- paginator.Limit = apiDefaults.PageLimit
- }
-
- listInfo := weles.ListInfo{
- TotalRecords: uint64(len(jobInfo)),
- RemainingRecords: 0}
-
- mockJobManager.EXPECT().ListJobs(
- filter, sorter, paginator).Return(
- jobInfo, listInfo, nil)
-
- reqBody := filterSorterReqBody(filter, sorter, JSON)
- req := createRequest(reqBody, "", query, JSON, JSON)
-
- client := testserver.Client()
- resp, err := client.Do(req)
- Expect(err).ToNot(HaveOccurred())
-
- defer resp.Body.Close()
- respBody, err := ioutil.ReadAll(resp.Body)
- Expect(err).ToNot(HaveOccurred())
-
- checkReceivedJobInfo(respBody, jobInfo, JSON)
-
- Expect(resp.StatusCode).To(Equal(200))
- // Next and Previous headers are ignored here as they are tested
- // in other context.
- Expect(resp.Header.Get("RemainingRecords")).To(Equal(""))
- Expect(resp.Header.Get("TotalRecords")).To(
- Equal(strconv.Itoa(len(jobInfo))))
- },
- Entry("given empty request, when JM has less jobs than page size",
- jobInfoAll[:40], emptyFilter, emptySorter, curr.paginator, curr.query,
- currgl),
-
- Entry("given filled filter, when JM returns less jobs than Default "+
- "Page size",
- jobInfoAll[10:67], filledFilter3, emptySorter, curr.paginator,
- curr.query, currgl),
-
- Entry("given filled filter, when JM returns same amount of filtered jobs"+
- " as Default Page Size",
- jobInfoAll, filledFilter1, filledSorter2, curr.paginator, curr.query,
- currgl),
- )
- }
- }
- })
+ marshalled, err := json.Marshal(jobInfo)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(string(respBody)).To(MatchJSON(string(marshalled)))
- Context("Pagination on", func() {
- jobInfoAll := createJobInfoSlice(400)
- DescribeTable("paginating forward",
- func(jobInfo []weles.JobInfo,
- startingPageNo int,
- filter weles.JobFilter,
- sorter weles.JobSorter) {
+ }
- apiDefaults.PageLimit = 100
+ checkReceivedJobErr := func(respBody []byte, e error) {
+ errMarshalled, err := json.Marshal(weles.ErrResponse{
+ Message: e.Error(),
+ Type: "",
+ })
+ Expect(err).ToNot(HaveOccurred())
+ Expect(string(respBody)).To(MatchJSON(string(errMarshalled)))
+ }
+
+ Describe("Pagination is turned off", func() {
+ Describe("client sends correct request", func() {
+ It("server should accept empty post request", func() {
+ apiDefaults.PageLimit = 0
+
+ listInfo := weles.ListInfo{
+ TotalRecords: uint64(len(jobInfo420)),
+ RemainingRecords: 0,
+ }
+ // should pass correct default values of Sorter to JobManager
+ mockJobManager.EXPECT().ListJobs(
+ emptyJobFilter, sorterDefault, emptyPaginatorOff).Return(
+ jobInfo420, listInfo, nil)
- //prepare data for first call
- jobInfoStartingPage := jobInfo[(startingPageNo-1)*
- int(apiDefaults.PageLimit) : startingPageNo*
- int(apiDefaults.PageLimit)] //first page of data
+ client := testserver.Client()
+ req := createRequest(nil, "", JSON, JSON)
+ req.Close = true
+ _, err := client.Do(req)
+ Expect(err).ToNot(HaveOccurred())
- startingPageQuery := ""
+ })
- paginator := weles.JobPagination{Limit: apiDefaults.PageLimit}
- paginator.Forward = true
- if startingPageNo != 1 {
- paginator.JobID = jobInfoStartingPage[0].JobID
- startingPageQuery = "?after=" +
- jobInfo[(startingPageNo-1)*int(apiDefaults.PageLimit)].JobID.String()
- }
+ DescribeTable("server should ignore query params",
+ func(query string) {
+ apiDefaults.PageLimit = 0
listInfo := weles.ListInfo{
- TotalRecords: uint64(len(jobInfo)),
- RemainingRecords: uint64(len(jobInfo) - startingPageNo*len(
- jobInfoStartingPage)),
+ TotalRecords: uint64(len(jobInfo420)),
+ RemainingRecords: 0,
}
+ mockJobManager.EXPECT().ListJobs(emptyJobFilter,
+ sorterDefault, emptyPaginatorOff).Return(
+ jobInfo420, listInfo, nil)
- first := mockJobManager.EXPECT().ListJobs(filter, sorter, paginator).Return(
- jobInfoStartingPage, listInfo, nil)
-
- reqBody := filterSorterReqBody(filter, sorter, JSON)
- req := createRequest(reqBody, "", startingPageQuery, JSON, JSON)
- req.Close = true
client := testserver.Client()
- resp, err := client.Do(req)
+ req := createRequest(nil, query, JSON, JSON)
+ req.Close = true
+ _, err := client.Do(req)
Expect(err).ToNot(HaveOccurred())
+ },
- respBody, err := ioutil.ReadAll(resp.Body)
- Expect(err).ToNot(HaveOccurred())
+ Entry("no query params set", ""),
+ Entry("after query set", "?after=50"),
+ Entry("after and limit query set", "?after=50&limit=10"),
+ Entry("after and before query set", "?after=50&before=20"),
+ Entry("after and before and limit query set", "?after=50&before=30&limit=13"),
+ Entry("before query set", "?before=100"),
+ Entry("before and limit query set", "?before=100&limit=12"),
+ )
- checkReceivedJobInfo(respBody, jobInfoStartingPage, JSON)
- Expect(resp.StatusCode).To(Equal(206))
+ DescribeTable("server should pass filter to JobManager",
+ func(filter weles.JobFilter) {
- Expect(resp.Header.Get("Next")).To(
- Equal("/api/v1/jobs/list" + "?after=" +
- jobInfoStartingPage[apiDefaults.PageLimit-1].JobID.String()))
- prevCheck := ""
- if startingPageNo != 1 {
- prevCheck = "/api/v1/jobs/list" + "?before=" +
- jobInfoStartingPage[0].JobID.String()
- }
+ apiDefaults.PageLimit = 0
- Expect(resp.Header.Get("Previous")).To(Equal(prevCheck))
- Expect(resp.Header.Get("RemainingRecords")).To(
- Equal(strconv.Itoa(len(jobInfo) - (startingPageNo * len(
- jobInfoStartingPage)))))
- Expect(resp.Header.Get("TotalRecords")).To(Equal(strconv.Itoa(len(jobInfo))))
-
- nextPage := resp.Header.Get("Next")
- resp.Body.Close()
- testserver.CloseClientConnections()
-
- //prepare data for second call based on previous
- var jobInfo2 []weles.JobInfo
- var secondReturnCode int
- if (len(jobInfo) - startingPageNo*int(apiDefaults.PageLimit)) <= int(
- apiDefaults.PageLimit) {
-
- jobInfo2 = jobInfo[startingPageNo*int(apiDefaults.PageLimit):]
- //next page is not full
- secondReturnCode = 200
- } else {
- jobInfo2 = jobInfo[startingPageNo*
- int(apiDefaults.PageLimit) : (startingPageNo+1)*
- int(apiDefaults.PageLimit)] //last page is full
- secondReturnCode = 206
+ listInfo := weles.ListInfo{
+ TotalRecords: uint64(len(jobInfo420)),
+ RemainingRecords: 0,
}
- paginator2 := weles.JobPagination{
- Limit: apiDefaults.PageLimit,
- Forward: true,
- JobID: jobInfoStartingPage[int(apiDefaults.PageLimit)-1].JobID}
-
- listInfo2 := weles.ListInfo{TotalRecords: listInfo.TotalRecords}
-
- if tmp := len(jobInfo) - (startingPageNo+1)*
- int(apiDefaults.PageLimit); tmp < 0 {
- listInfo2.RemainingRecords = 0
- } else {
- listInfo2.RemainingRecords = uint64(tmp)
- }
- //filter and sorter should stay the same.
mockJobManager.EXPECT().ListJobs(
- filter, sorter, paginator2).Return(jobInfo2, listInfo2, nil).After(first)
+ filter, sorterDefault, emptyPaginatorOff).Return(
+ jobInfo420, listInfo, nil)
+ reqBody := createRequestBody(filter, sorterEmpty)
- client2 := testserver.Client()
- req2 := createRequest(reqBody, nextPage, "", JSON, JSON)
- req2.Close = true
- resp2, err := client2.Do(req2)
- Expect(err).ToNot(HaveOccurred())
+ client := testserver.Client()
+ req := createRequest(reqBody, "", JSON, JSON)
- defer resp2.Body.Close()
- respBody2, err := ioutil.ReadAll(resp2.Body)
+ _, err := client.Do(req)
Expect(err).ToNot(HaveOccurred())
+ },
+ Entry("when receiving empty filter", emptyJobFilter),
+ Entry("when receiving filled filter", filledJobFilter),
+ )
- checkReceivedJobInfo(respBody2, jobInfo2, JSON)
-
- Expect(resp2.StatusCode).To(Equal(secondReturnCode))
-
- if secondReturnCode == 200 {
- Expect(resp2.Header.Get("Next")).To(Equal(""))
- prevCheck = "/api/v1/jobs/list" + "?before=" + jobInfo2[0].JobID.String()
- Expect(resp2.Header.Get("Previous")).To(Equal(prevCheck))
- } else {
- prevCheck = "/api/v1/jobs/list" + "?before=" +
- jobInfo2[0].JobID.String()
+ DescribeTable("server should pass sorter to JobManager, but set default values "+
+ "on empty fields",
+ func(sent, expected weles.JobSorter) {
- nextCheck := "/api/v1/jobs/list" + "?after=" +
- jobInfo2[int(apiDefaults.PageLimit)-1].JobID.String()
+ apiDefaults.PageLimit = 0
- Expect(resp2.Header.Get("Next")).To(Equal(nextCheck))
- Expect(resp2.Header.Get("Previous")).To(Equal(prevCheck))
+ listInfo := weles.ListInfo{
+ TotalRecords: uint64(len(jobInfo420)),
+ RemainingRecords: 0,
}
- if tmp := strconv.Itoa(
- len(jobInfo) - startingPageNo*len(jobInfoStartingPage) - len(
- jobInfo2)); tmp != "0" {
- Expect(resp2.Header.Get("RemainingRecords")).To(Equal(tmp))
- } else {
- Expect(resp2.Header.Get("RemainingRecords")).To(Equal(""))
- }
- Expect(resp2.Header.Get("TotalRecords")).To(Equal(strconv.Itoa(len(jobInfo))))
+ mockJobManager.EXPECT().ListJobs(
+ emptyJobFilter, expected, emptyPaginatorOff).Return(
+ jobInfo420, listInfo, nil)
+ reqBody := createRequestBody(emptyJobFilter, sent)
+ client := testserver.Client()
+ req := createRequest(reqBody, "", JSON, JSON)
+
+ _, err := client.Do(req)
+ Expect(err).ToNot(HaveOccurred())
},
- Entry("1->2/2", // from 1 to 2 out of 2 (pages)
- jobInfoAll[:170], 1, emptyFilter, emptySorter),
- Entry("1->2/3",
- jobInfoAll[:270], 1, emptyFilter, emptySorter),
- Entry("2->3/3",
- jobInfoAll[:300], 2, emptyFilter, emptySorter),
- Entry("2->3/4",
- jobInfoAll[:350], 2, emptyFilter, emptySorter),
+ Entry("should set default order and by",
+ sorterEmpty, sorterDefault),
+ Entry("should pass ascending order and by ID",
+ sorterAscID, sorterAscID),
+ Entry("should pass descending order and by ID",
+ sorterDescID, sorterDescID),
+ Entry("should pass descending order and set default by",
+ sorterDescNoBy, weles.JobSorter{
+ SortOrder: sorterDescNoBy.SortOrder,
+ SortBy: sorterDefault.SortBy,
+ }),
+ Entry("should pass ascending order and set default by",
+ sorterAscNoBy, weles.JobSorter{
+ SortOrder: sorterAscNoBy.SortOrder,
+ SortBy: sorterDefault.SortBy,
+ }),
+ Entry("should pass by ID and set default order",
+ sorterNoOrderID, weles.JobSorter{
+ SortOrder: sorterDefault.SortOrder,
+ SortBy: sorterNoOrderID.SortBy,
+ }),
+ Entry("should pass by CreatedDate and set default order",
+ sorterNoOrderCreatedDate, weles.JobSorter{
+ SortOrder: sorterDefault.SortOrder,
+ SortBy: sorterNoOrderCreatedDate.SortBy,
+ }),
)
- DescribeTable("paginating backward",
- func(jobInfo []weles.JobInfo,
- startingPageNo int, pages int,
- filter weles.JobFilter,
- sorter weles.JobSorter) {
+ DescribeTable("should respond with all jobs and correct headers",
+ func(recordCount int) {
+ apiDefaults.PageLimit = 0
- apiDefaults.PageLimit = 100
- paginator := weles.JobPagination{Limit: apiDefaults.PageLimit}
- //prepare data for first call
- var jobInfoStartingPage []weles.JobInfo
- var startingPageQuery string
- listInfo := weles.ListInfo{}
- if startingPageNo == pages {
- jobInfoStartingPage = jobInfo[(startingPageNo-1)*
- int(apiDefaults.PageLimit) : len(jobInfo)-1]
- paginator.Forward = true
- paginator.JobID = jobInfoStartingPage[len(jobInfoStartingPage)-1].JobID
- startingPageQuery = "?after=" + paginator.JobID.String()
- listInfo = weles.ListInfo{
- TotalRecords: uint64(len(jobInfo)),
- RemainingRecords: 0}
-
- } else {
- jobInfoStartingPage = jobInfo[(startingPageNo)*
- int(apiDefaults.PageLimit) : (startingPageNo+1)*
- int(apiDefaults.PageLimit)] //first page of data
- paginator.Forward = false
- paginator.JobID = jobInfo[(startingPageNo*int(
- apiDefaults.PageLimit))-1].JobID
- startingPageQuery = "?before=" + paginator.JobID.String()
- listInfo = weles.ListInfo{
- TotalRecords: uint64(len(jobInfo)),
- RemainingRecords: uint64(len(jobInfo) - (int(apiDefaults.PageLimit) *
- startingPageNo))}
+ jobInfo := createJobInfoSlice(recordCount)
+ listInfo := weles.ListInfo{
+ TotalRecords: uint64(len(jobInfo)),
+ RemainingRecords: 0,
}
- first := mockJobManager.EXPECT().ListJobs(
- filter, sorter, paginator).Return(jobInfoStartingPage, listInfo, nil)
+ mockJobManager.EXPECT().ListJobs(emptyJobFilter,
+ sorterDefault, emptyPaginatorOff).Return(
+ jobInfo, listInfo, nil)
+
+ reqBody := createRequestBody(emptyJobFilter, sorterDefault)
- reqBody := filterSorterReqBody(filter, sorter, JSON)
- req := createRequest(reqBody, "", startingPageQuery, JSON, JSON)
- req.Close = true
client := testserver.Client()
+ req := createRequest(reqBody, "", JSON, JSON)
resp, err := client.Do(req)
Expect(err).ToNot(HaveOccurred())
+ defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
Expect(err).ToNot(HaveOccurred())
- checkReceivedJobInfo(respBody, jobInfoStartingPage, JSON)
-
- if startingPageNo == pages {
- Expect(resp.StatusCode).To(Equal(200))
- Expect(resp.Header.Get("Previous")).To(
- Equal("/api/v1/jobs/list?before=" +
- jobInfoStartingPage[0].JobID.String()))
- Expect(resp.Header.Get("Next")).To(
- Equal(""))
- Expect(resp.Header.Get("TotalRecords")).To(
- Equal(strconv.Itoa(len(jobInfo))))
- Expect(resp.Header.Get("RemainingRecords")).To(
- Equal(""))
- } else {
- Expect(resp.StatusCode).To(
- Equal(206))
- Expect(resp.Header.Get("Previous")).To(
- Equal("/api/v1/jobs/list?before=" +
- jobInfoStartingPage[0].JobID.String()))
- Expect(resp.Header.Get("Next")).To(
- Equal("/api/v1/jobs/list?after=" +
- jobInfoStartingPage[len(jobInfoStartingPage)-1].JobID.String()))
- Expect(resp.Header.Get("TotalRecords")).To(
- Equal(strconv.Itoa(len(jobInfo))))
- Expect(resp.Header.Get("RemainingRecords")).To(
- Equal(strconv.FormatUint(listInfo.RemainingRecords, 10)))
- }
+ checkReceivedJobInfo(respBody, jobInfo)
- prevPage := resp.Header.Get("Previous")
+ Expect(resp.StatusCode).To(Equal(200))
+ Expect(resp.Header.Get("Next")).To(Equal(""))
+ Expect(resp.Header.Get("Previous")).To(Equal(""))
+ Expect(resp.Header.Get("RemainingRecords")).To(Equal(""))
+ Expect(resp.Header.Get("TotalRecords")).To(Equal(strconv.Itoa(
+ len(jobInfo))))
- resp.Body.Close()
- testserver.CloseClientConnections()
+ },
+ Entry("20 records avaliable", 20),
+ Entry("420 records avaliable", 420),
+ )
- //prepare data for second call based on previous
+ })
- var jobInfo2 []weles.JobInfo
- paginator2 := weles.JobPagination{
- Limit: apiDefaults.PageLimit,
- Forward: false,
- JobID: jobInfoStartingPage[0].JobID,
- }
+ })
+
+ Describe("JobManager returns error", func() {
+ DescribeTable("Server should return appropriate status code and error message",
+ func(pageLimit int32, statusCode int, amerr error) {
+
+ apiDefaults.PageLimit = pageLimit
+
+ listInfo := weles.ListInfo{
+ TotalRecords: uint64(len(jobInfo420)),
+ RemainingRecords: 0,
+ }
+ var paginator weles.JobPagination
+ if pageLimit == 0 {
+ paginator = emptyPaginatorOff
+ } else {
+ paginator = emptyPaginatorOn
+ paginator.Limit = pageLimit
+ }
+ mockJobManager.EXPECT().ListJobs(
+ emptyJobFilter, sorterDefault, paginator).Return(
+ jobInfo420, listInfo, amerr)
+ reqBody := createRequestBody(emptyJobFilter, sorterDefault)
+
+ client := testserver.Client()
+ req := createRequest(reqBody, "", JSON, JSON)
+ resp, err := client.Do(req)
+ Expect(err).ToNot(HaveOccurred())
- listInfo2 := weles.ListInfo{TotalRecords: listInfo.TotalRecords}
- if startingPageNo == pages {
- jobInfo2 = jobInfo[(startingPageNo-2)*
- int(apiDefaults.PageLimit) : (startingPageNo-1)*
- int(apiDefaults.PageLimit)]
-
- if startingPageNo-1 == 1 {
- listInfo2.RemainingRecords = 0
- } else {
- listInfo2.RemainingRecords = uint64((pages - (startingPageNo - 1)) *
- int(apiDefaults.PageLimit))
- }
- } else {
- jobInfo2 = jobInfo[(startingPageNo-1)*
- int(apiDefaults.PageLimit) : startingPageNo*
- int(apiDefaults.PageLimit)]
-
- listInfo2.RemainingRecords = uint64(apiDefaults.PageLimit)
+ defer resp.Body.Close()
+ respBody, err := ioutil.ReadAll(resp.Body)
+ Expect(err).ToNot(HaveOccurred())
+
+ checkReceivedJobErr(respBody, amerr)
+ Expect(resp.StatusCode).To(Equal(statusCode))
+ Expect(resp.Header.Get("Next")).To(Equal(""))
+ Expect(resp.Header.Get("Previous")).To(Equal(""))
+ Expect(resp.Header.Get("TotalRecords")).To(Equal(""))
+ Expect(resp.Header.Get("RemainingRecords")).To(Equal(""))
+
+ },
+ Entry("pagination off, 404 status, Job not found error",
+ int32(0), 404, weles.ErrJobNotFound),
+ Entry("pagination on, 404 status, Job not found error",
+ int32(100), 404, weles.ErrJobNotFound),
+ Entry("pagination off, 500 status, Unexpected error",
+ int32(0), 500, errors.New("This is unexpected error")),
+ Entry("pagination on, 500 status, Unexpected error",
+ int32(100), 500, errors.New("This is unexpected error")),
+ )
+ })
+ Describe("Pagination turned on", func() {
+ Describe("Correct request", func() {
+ DescribeTable("server should set paginator object depending on query params",
+ func(query string, expectedPaginator weles.JobPagination) {
+ apiDefaults.PageLimit = 500
+
+ listInfo := weles.ListInfo{
+ TotalRecords: uint64(len(jobInfo420)),
+ RemainingRecords: 0,
}
mockJobManager.EXPECT().ListJobs(
- filter, sorter, paginator2).Return(jobInfo2, listInfo2, nil).After(first)
- client2 := testserver.Client()
- req2 := createRequest(reqBody, prevPage, "", JSON, JSON)
- req2.Close = true
- resp2, err := client2.Do(req2)
+ emptyJobFilter, sorterDefault, expectedPaginator).Return(
+ jobInfo420, listInfo, nil)
+ reqBody := createRequestBody(emptyJobFilter, sorterDefault)
+
+ client := testserver.Client()
+ req := createRequest(reqBody, query, JSON, JSON)
+ _, err := client.Do(req)
Expect(err).ToNot(HaveOccurred())
- defer resp2.Body.Close()
- respBody2, err := ioutil.ReadAll(resp2.Body)
+ },
+ Entry("when no query params set", "",
+ weles.JobPagination{Forward: true, Limit: 500}),
+ Entry("when after param is set", "?after=30",
+ weles.JobPagination{Forward: true, Limit: 500, JobID: 30}),
+ Entry("when after and limit params are set", "?after=30&limit=20",
+ weles.JobPagination{Forward: true, Limit: 20, JobID: 30}),
+ Entry("when before param is set", "?before=30",
+ weles.JobPagination{Forward: false, Limit: 500, JobID: 30}),
+ Entry("when before and limit params are set", "?before=30&limit=15",
+ weles.JobPagination{Forward: false, Limit: 15, JobID: 30}),
+ Entry("when limit param is set", "?limit=30",
+ weles.JobPagination{Forward: true, Limit: 30}),
+ )
+
+ DescribeTable("server should respond with 200/206 depending on "+
+ "ListInfo.RemainingRecords returned by JobManager",
+ func(listInfo weles.ListInfo, statusCode int) {
+
+ apiDefaults.PageLimit = 100
+ paginator := emptyPaginatorOn
+ paginator.Limit = apiDefaults.PageLimit
+ mockJobManager.EXPECT().ListJobs(
+ emptyJobFilter, sorterDefault, paginator).Return(
+ jobInfo420, listInfo, nil)
+ reqBody := createRequestBody(emptyJobFilter, sorterDefault)
+
+ client := testserver.Client()
+ req := createRequest(reqBody, "", JSON, JSON)
+ _, err := client.Do(req)
Expect(err).ToNot(HaveOccurred())
- checkReceivedJobInfo(respBody2, jobInfo2, JSON)
- if startingPageNo == pages {
-
- if startingPageNo-1 == 1 {
- Expect(resp2.StatusCode).To(Equal(200))
- Expect(resp2.Header.Get("RemainingRecords")).To(Equal(""))
- Expect(resp2.Header.Get("Previous")).To(Equal(""))
-
- } else {
- Expect(resp2.StatusCode).To(Equal(206))
- Expect(resp2.Header.Get("RemainingRecords")).To(
- Equal(strconv.FormatInt(int64(apiDefaults.PageLimit), 10)))
- Expect(resp2.Header.Get("Previous")).To(
- Equal("/api/v1/jobs/list?before=" + jobInfo2[0].JobID.String()))
- }
- } else {
- Expect(resp2.StatusCode).To(Equal(206))
- Expect(resp2.Header.Get("RemainingRecords")).To(
- Equal(strconv.FormatInt(int64(apiDefaults.PageLimit), 10)))
- }
- Expect(resp2.Header.Get("Next")).To(
- Equal("/api/v1/jobs/list?after=" +
- jobInfo2[len(jobInfo2)-1].JobID.String()))
- Expect(resp2.Header.Get("TotalRecords")).To(Equal(strconv.Itoa(len(jobInfo))))
+ //TODO: check headers
},
- // ginkgo does not like It clauses with the same name. To avoid conflicts with
- // tests of listing artifacts, each it clause not referring to jobs exlicitly
- // is prefixed with j:
- Entry("j: 2->1/2", //meaning: from 1 to 2 out of 2 (pages)
- jobInfoAll[:170], 2, 2, emptyFilter, emptySorter),
- Entry("j: 2->1/3",
- jobInfoAll[:270], 2, 3, emptyFilter, emptySorter),
- Entry("j: 3->2/4",
- jobInfoAll[:350], 3, 4, emptyFilter, emptySorter),
- Entry("j: 3->2/3",
- jobInfoAll[:300], 3, 3, emptyFilter, emptySorter),
+ Entry("first and last page",
+ weles.ListInfo{RemainingRecords: 0}, 200),
+ Entry("first page out of n (n>3)",
+ weles.ListInfo{RemainingRecords: 20}, 206),
)
})
- Context("There is an error", func() {
- DescribeTable("Server should respond with error from JobManager",
- func(pageLimit, aviJobs int, filter weles.JobFilter, sorter weles.JobSorter,
- statusCode int, jmerr error) {
-
- apiDefaults.PageLimit = int32(pageLimit)
- jobInfo := createJobInfoSlice(aviJobs)
- paginator := weles.JobPagination{Limit: apiDefaults.PageLimit}
- if pageLimit == 0 {
- paginator.Forward = false
- } else {
- paginator.Forward = true
- }
- listInfo := weles.ListInfo{TotalRecords: uint64(aviJobs), RemainingRecords: 0}
+ Describe("Error ", func() {
+ DescribeTable("returned by server due to both before and after query params set",
+ func(query string) {
+ apiDefaults.PageLimit = 100
+
+ req := createRequest(nil, query, JSON, JSON)
- mockJobManager.EXPECT().ListJobs(filter, sorter, paginator).Return(
- jobInfo, listInfo, jmerr)
- reqBody := filterSorterReqBody(filter, sorter, JSON)
client := testserver.Client()
- req := createRequest(reqBody, "", "", JSON, JSON)
resp, err := client.Do(req)
Expect(err).ToNot(HaveOccurred())
-
defer resp.Body.Close()
+
respBody, err := ioutil.ReadAll(resp.Body)
Expect(err).ToNot(HaveOccurred())
+ checkReceivedJobErr(respBody, weles.ErrBeforeAfterNotAllowed)
- checkReceivedErr(respBody, jmerr, JSON)
-
- Expect(resp.StatusCode).To(Equal(statusCode))
+ Expect(resp.StatusCode).To(Equal(400))
Expect(resp.Header.Get("Next")).To(Equal(""))
Expect(resp.Header.Get("Previous")).To(Equal(""))
Expect(resp.Header.Get("TotalRecords")).To(Equal(""))
Expect(resp.Header.Get("RemainingRecords")).To(Equal(""))
},
- Entry("404 status, Job not found error "+
- "when server has 0 jobs avaliable,pagination off",
- 0, 0, emptyFilter, emptySorter, 404, weles.ErrJobNotFound),
- Entry("404 status, Job not found error "+
- "when server has 100 jobs but none fulfilling filter, pagination off",
- 0, 100, filledFilter1, emptySorter, 404, weles.ErrJobNotFound),
- Entry("500 status, JobManager unexpected error "+
- "when server has 100 jobs, pagination off",
- 0, 100, emptyFilter, emptySorter, 500, errors.New(
- "This is some errors string")),
- Entry("404 status, Job not found error "+
- "when server has 0 jobs avaliable,pagination on",
- 100, 0, emptyFilter, emptySorter, 404, weles.ErrJobNotFound),
- Entry("404 status, Job not found error "+
- "when server has 100 jobs but none fulfilling filter, pagination on",
- 100, 100, filledFilter1, emptySorter, 404, weles.ErrJobNotFound),
- Entry("500 status, JobManager unexpected error "+
- "when server has 100 jobs, pagination on",
- 100, 100, emptyFilter, emptySorter, 500, errors.New(
- "This is some errors string")),
+ Entry("empty body", "?before=10&after=20"),
+ Entry("empty body, additional limit query set", "?before=10&after=20&limit=10"),
)
})
-
- DescribeTable("error returned by server due to both before and after query params set",
- func(defaultPageLimit int32, query, acceptH, contentH string, filter weles.JobFilter,
- sorter weles.JobSorter) {
-
- apiDefaults.PageLimit = defaultPageLimit
-
- reqBody := filterSorterReqBody(filter, sorter, contentH)
- req := createRequest(reqBody, "", query, contentH, acceptH)
-
- client := testserver.Client()
- resp, err := client.Do(req)
- Expect(err).ToNot(HaveOccurred())
- defer resp.Body.Close()
-
- respBody, err := ioutil.ReadAll(resp.Body)
- Expect(err).ToNot(HaveOccurred())
- checkReceivedErr(respBody, weles.ErrBeforeAfterNotAllowed, acceptH)
-
- Expect(resp.StatusCode).To(Equal(400))
- Expect(resp.Header.Get("Next")).To(Equal(""))
- Expect(resp.Header.Get("Previous")).To(Equal(""))
- Expect(resp.Header.Get("TotalRecords")).To(Equal(""))
- Expect(resp.Header.Get("RemainingRecords")).To(Equal(""))
-
- },
- Entry("json, pagination off",
- int32(0), "?before=10&after=20", JSON, JSON, emptyFilter, emptySorter),
- Entry("json, pagination on",
- int32(100), "?before=10&after=20", JSON, JSON, emptyFilter, emptySorter),
- )
-
})
})
diff --git a/server/managers.go b/server/managers.go
index f7913de..b79d599 100644
--- a/server/managers.go
+++ b/server/managers.go
@@ -15,7 +15,7 @@
package server
import (
- "git.tizen.org/tools/weles"
+ "github.com/SamsungSLAV/weles"
)
// Managers provide implementation of JobManager and ArtifactManager interfaces.
diff --git a/server/operations/artifacts/artifact_lister.go b/server/operations/artifacts/artifact_lister.go
index 863358d..44b82a1 100644
--- a/server/operations/artifacts/artifact_lister.go
+++ b/server/operations/artifacts/artifact_lister.go
@@ -23,7 +23,12 @@ package artifacts
import (
"net/http"
+ errors "github.com/go-openapi/errors"
middleware "github.com/go-openapi/runtime/middleware"
+ strfmt "github.com/go-openapi/strfmt"
+ swag "github.com/go-openapi/swag"
+
+ weles "github.com/SamsungSLAV/weles"
)
// ArtifactListerHandlerFunc turns a function with the right signature into a artifact lister handler
@@ -73,3 +78,86 @@ func (o *ArtifactLister) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
o.Context.Respond(rw, r, route.Produces, route, res)
}
+
+// ArtifactListerBody Data for filtering and sorting Weles Jobs lists.
+// swagger:model ArtifactListerBody
+type ArtifactListerBody struct {
+
+ // filter
+ Filter *weles.ArtifactFilter `json:"Filter,omitempty"`
+
+ // sorter
+ Sorter *weles.ArtifactSorter `json:"Sorter,omitempty"`
+}
+
+// Validate validates this artifact lister body
+func (o *ArtifactListerBody) Validate(formats strfmt.Registry) error {
+ var res []error
+
+ if err := o.validateFilter(formats); err != nil {
+ res = append(res, err)
+ }
+
+ if err := o.validateSorter(formats); err != nil {
+ res = append(res, err)
+ }
+
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
+
+func (o *ArtifactListerBody) validateFilter(formats strfmt.Registry) error {
+
+ if swag.IsZero(o.Filter) { // not required
+ return nil
+ }
+
+ if o.Filter != nil {
+ if err := o.Filter.Validate(formats); err != nil {
+ if ve, ok := err.(*errors.Validation); ok {
+ return ve.ValidateName("artifactFilterAndSort" + "." + "Filter")
+ }
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (o *ArtifactListerBody) validateSorter(formats strfmt.Registry) error {
+
+ if swag.IsZero(o.Sorter) { // not required
+ return nil
+ }
+
+ if o.Sorter != nil {
+ if err := o.Sorter.Validate(formats); err != nil {
+ if ve, ok := err.(*errors.Validation); ok {
+ return ve.ValidateName("artifactFilterAndSort" + "." + "Sorter")
+ }
+ return err
+ }
+ }
+
+ return nil
+}
+
+// MarshalBinary interface implementation
+func (o *ArtifactListerBody) MarshalBinary() ([]byte, error) {
+ if o == nil {
+ return nil, nil
+ }
+ return swag.WriteJSON(o)
+}
+
+// UnmarshalBinary interface implementation
+func (o *ArtifactListerBody) UnmarshalBinary(b []byte) error {
+ var res ArtifactListerBody
+ if err := swag.ReadJSON(b, &res); err != nil {
+ return err
+ }
+ *o = res
+ return nil
+}
diff --git a/server/operations/artifacts/artifact_lister_parameters.go b/server/operations/artifacts/artifact_lister_parameters.go
index 384bc98..6d90449 100644
--- a/server/operations/artifacts/artifact_lister_parameters.go
+++ b/server/operations/artifacts/artifact_lister_parameters.go
@@ -29,8 +29,6 @@ import (
"github.com/go-openapi/swag"
strfmt "github.com/go-openapi/strfmt"
-
- weles "git.tizen.org/tools/weles"
)
// NewArtifactListerParams creates a new ArtifactListerParams object
@@ -56,7 +54,7 @@ type ArtifactListerParams struct {
/*Artifact Filter and Sort object.
In: body
*/
- ArtifactFilterAndSort *weles.ArtifactFilterAndSort
+ ArtifactFilterAndSort ArtifactListerBody
/*ID of first element from next page.
In: query
*/
@@ -85,7 +83,7 @@ func (o *ArtifactListerParams) BindRequest(r *http.Request, route *middleware.Ma
if runtime.HasBody(r) {
defer r.Body.Close()
- var body weles.ArtifactFilterAndSort
+ var body ArtifactListerBody
if err := route.Consumer.Consume(r.Body, &body); err != nil {
res = append(res, errors.NewParseError("artifactFilterAndSort", "body", "", err))
} else {
@@ -95,7 +93,7 @@ func (o *ArtifactListerParams) BindRequest(r *http.Request, route *middleware.Ma
}
if len(res) == 0 {
- o.ArtifactFilterAndSort = &body
+ o.ArtifactFilterAndSort = body
}
}
}
diff --git a/server/operations/artifacts/artifact_lister_responses.go b/server/operations/artifacts/artifact_lister_responses.go
index 8033622..ed2e195 100644
--- a/server/operations/artifacts/artifact_lister_responses.go
+++ b/server/operations/artifacts/artifact_lister_responses.go
@@ -26,7 +26,7 @@ import (
"github.com/go-openapi/runtime"
"github.com/go-openapi/swag"
- weles "git.tizen.org/tools/weles"
+ weles "github.com/SamsungSLAV/weles"
)
// ArtifactListerOKCode is the HTTP code returned for type ArtifactListerOK
diff --git a/server/operations/general/version.go b/server/operations/general/version.go
new file mode 100644
index 0000000..2955ed1
--- /dev/null
+++ b/server/operations/general/version.go
@@ -0,0 +1,75 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License
+//
+
+package general
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the generate command
+
+import (
+ "net/http"
+
+ middleware "github.com/go-openapi/runtime/middleware"
+)
+
+// VersionHandlerFunc turns a function with the right signature into a version handler
+type VersionHandlerFunc func(VersionParams) middleware.Responder
+
+// Handle executing the request and returning a response
+func (fn VersionHandlerFunc) Handle(params VersionParams) middleware.Responder {
+ return fn(params)
+}
+
+// VersionHandler interface for that can handle valid version params
+type VersionHandler interface {
+ Handle(VersionParams) middleware.Responder
+}
+
+// NewVersion creates a new http.Handler for the version operation
+func NewVersion(ctx *middleware.Context, handler VersionHandler) *Version {
+ return &Version{Context: ctx, Handler: handler}
+}
+
+/*Version swagger:route GET /version general version
+
+Show current version of Weles internals
+
+Version and state of API (e.g. v1 obsolete, v2 stable, v3 devel) and server version.
+
+*/
+type Version struct {
+ Context *middleware.Context
+ Handler VersionHandler
+}
+
+func (o *Version) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ route, rCtx, _ := o.Context.RouteInfo(r)
+ if rCtx != nil {
+ r = rCtx
+ }
+ var Params = NewVersionParams()
+
+ if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
+ o.Context.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+
+ res := o.Handler.Handle(Params) // actually handle the request
+
+ o.Context.Respond(rw, r, route.Produces, route, res)
+
+}
diff --git a/server/operations/general/version_parameters.go b/server/operations/general/version_parameters.go
new file mode 100644
index 0000000..8552984
--- /dev/null
+++ b/server/operations/general/version_parameters.go
@@ -0,0 +1,60 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License
+//
+
+package general
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime/middleware"
+)
+
+// NewVersionParams creates a new VersionParams object
+// no default values defined in spec.
+func NewVersionParams() VersionParams {
+
+ return VersionParams{}
+}
+
+// VersionParams contains all the bound params for the version operation
+// typically these are obtained from a http.Request
+//
+// swagger:parameters Version
+type VersionParams struct {
+
+ // HTTP Request Object
+ HTTPRequest *http.Request `json:"-"`
+}
+
+// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
+// for simple values it will use straight method calls.
+//
+// To ensure default values, the struct must have been initialized with NewVersionParams() beforehand.
+func (o *VersionParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
+ var res []error
+
+ o.HTTPRequest = r
+
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
diff --git a/server/operations/general/version_responses.go b/server/operations/general/version_responses.go
new file mode 100644
index 0000000..d425d10
--- /dev/null
+++ b/server/operations/general/version_responses.go
@@ -0,0 +1,183 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License
+//
+
+package general
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime"
+
+ weles "github.com/SamsungSLAV/weles"
+)
+
+// VersionOKCode is the HTTP code returned for type VersionOK
+const VersionOKCode int = 200
+
+/*VersionOK OK
+
+swagger:response versionOK
+*/
+type VersionOK struct {
+ /*State of Weles API.
+
+ */
+ WelesAPIState string `json:"Weles-API-State"`
+ /*Version of Weles API.
+
+ */
+ WelesAPIVersion string `json:"Weles-API-Version"`
+ /*Version of Weles server.
+
+ */
+ WelesServerVersion string `json:"Weles-Server-Version"`
+
+ /*
+ In: Body
+ */
+ Payload *weles.Version `json:"body,omitempty"`
+}
+
+// NewVersionOK creates VersionOK with default headers values
+func NewVersionOK() *VersionOK {
+
+ return &VersionOK{}
+}
+
+// WithWelesAPIState adds the welesApiState to the version o k response
+func (o *VersionOK) WithWelesAPIState(welesAPIState string) *VersionOK {
+ o.WelesAPIState = welesAPIState
+ return o
+}
+
+// SetWelesAPIState sets the welesApiState to the version o k response
+func (o *VersionOK) SetWelesAPIState(welesAPIState string) {
+ o.WelesAPIState = welesAPIState
+}
+
+// WithWelesAPIVersion adds the welesApiVersion to the version o k response
+func (o *VersionOK) WithWelesAPIVersion(welesAPIVersion string) *VersionOK {
+ o.WelesAPIVersion = welesAPIVersion
+ return o
+}
+
+// SetWelesAPIVersion sets the welesApiVersion to the version o k response
+func (o *VersionOK) SetWelesAPIVersion(welesAPIVersion string) {
+ o.WelesAPIVersion = welesAPIVersion
+}
+
+// WithWelesServerVersion adds the welesServerVersion to the version o k response
+func (o *VersionOK) WithWelesServerVersion(welesServerVersion string) *VersionOK {
+ o.WelesServerVersion = welesServerVersion
+ return o
+}
+
+// SetWelesServerVersion sets the welesServerVersion to the version o k response
+func (o *VersionOK) SetWelesServerVersion(welesServerVersion string) {
+ o.WelesServerVersion = welesServerVersion
+}
+
+// WithPayload adds the payload to the version o k response
+func (o *VersionOK) WithPayload(payload *weles.Version) *VersionOK {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the version o k response
+func (o *VersionOK) SetPayload(payload *weles.Version) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *VersionOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ // response header Weles-API-State
+
+ welesAPIState := o.WelesAPIState
+ if welesAPIState != "" {
+ rw.Header().Set("Weles-API-State", welesAPIState)
+ }
+
+ // response header Weles-API-Version
+
+ welesAPIVersion := o.WelesAPIVersion
+ if welesAPIVersion != "" {
+ rw.Header().Set("Weles-API-Version", welesAPIVersion)
+ }
+
+ // response header Weles-Server-Version
+
+ welesServerVersion := o.WelesServerVersion
+ if welesServerVersion != "" {
+ rw.Header().Set("Weles-Server-Version", welesServerVersion)
+ }
+
+ rw.WriteHeader(200)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
+
+// VersionInternalServerErrorCode is the HTTP code returned for type VersionInternalServerError
+const VersionInternalServerErrorCode int = 500
+
+/*VersionInternalServerError Internal Server error
+
+swagger:response versionInternalServerError
+*/
+type VersionInternalServerError struct {
+
+ /*
+ In: Body
+ */
+ Payload *weles.ErrResponse `json:"body,omitempty"`
+}
+
+// NewVersionInternalServerError creates VersionInternalServerError with default headers values
+func NewVersionInternalServerError() *VersionInternalServerError {
+
+ return &VersionInternalServerError{}
+}
+
+// WithPayload adds the payload to the version internal server error response
+func (o *VersionInternalServerError) WithPayload(payload *weles.ErrResponse) *VersionInternalServerError {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the version internal server error response
+func (o *VersionInternalServerError) SetPayload(payload *weles.ErrResponse) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *VersionInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(500)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/server/operations/general/version_urlbuilder.go b/server/operations/general/version_urlbuilder.go
new file mode 100644
index 0000000..d185d09
--- /dev/null
+++ b/server/operations/general/version_urlbuilder.go
@@ -0,0 +1,102 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License
+//
+
+package general
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the generate command
+
+import (
+ "errors"
+ "net/url"
+ golangswaggerpaths "path"
+)
+
+// VersionURL generates an URL for the version operation
+type VersionURL struct {
+ _basePath string
+}
+
+// WithBasePath sets the base path for this url builder, only required when it's different from the
+// base path specified in the swagger spec.
+// When the value of the base path is an empty string
+func (o *VersionURL) WithBasePath(bp string) *VersionURL {
+ o.SetBasePath(bp)
+ return o
+}
+
+// SetBasePath sets the base path for this url builder, only required when it's different from the
+// base path specified in the swagger spec.
+// When the value of the base path is an empty string
+func (o *VersionURL) SetBasePath(bp string) {
+ o._basePath = bp
+}
+
+// Build a url path and query string
+func (o *VersionURL) Build() (*url.URL, error) {
+ var result url.URL
+
+ var _path = "/version"
+
+ _basePath := o._basePath
+ if _basePath == "" {
+ _basePath = "/api/v1"
+ }
+ result.Path = golangswaggerpaths.Join(_basePath, _path)
+
+ return &result, nil
+}
+
+// Must is a helper function to panic when the url builder returns an error
+func (o *VersionURL) Must(u *url.URL, err error) *url.URL {
+ if err != nil {
+ panic(err)
+ }
+ if u == nil {
+ panic("url can't be nil")
+ }
+ return u
+}
+
+// String returns the string representation of the path with query string
+func (o *VersionURL) String() string {
+ return o.Must(o.Build()).String()
+}
+
+// BuildFull builds a full url with scheme, host, path and query string
+func (o *VersionURL) BuildFull(scheme, host string) (*url.URL, error) {
+ if scheme == "" {
+ return nil, errors.New("scheme is required for a full url on VersionURL")
+ }
+ if host == "" {
+ return nil, errors.New("host is required for a full url on VersionURL")
+ }
+
+ base, err := o.Build()
+ if err != nil {
+ return nil, err
+ }
+
+ base.Scheme = scheme
+ base.Host = host
+ return base, nil
+}
+
+// StringFull returns the string representation of a complete url
+func (o *VersionURL) StringFull(scheme, host string) string {
+ return o.Must(o.BuildFull(scheme, host)).String()
+}
diff --git a/server/operations/jobs/job_canceler_responses.go b/server/operations/jobs/job_canceler_responses.go
index 556049c..fbb05a9 100644
--- a/server/operations/jobs/job_canceler_responses.go
+++ b/server/operations/jobs/job_canceler_responses.go
@@ -25,7 +25,7 @@ import (
"github.com/go-openapi/runtime"
- weles "git.tizen.org/tools/weles"
+ weles "github.com/SamsungSLAV/weles"
)
// JobCancelerNoContentCode is the HTTP code returned for type JobCancelerNoContent
diff --git a/server/operations/jobs/job_creator_responses.go b/server/operations/jobs/job_creator_responses.go
index a7c73cc..ce3de27 100644
--- a/server/operations/jobs/job_creator_responses.go
+++ b/server/operations/jobs/job_creator_responses.go
@@ -25,7 +25,7 @@ import (
"github.com/go-openapi/runtime"
- weles "git.tizen.org/tools/weles"
+ weles "github.com/SamsungSLAV/weles"
)
// JobCreatorCreatedCode is the HTTP code returned for type JobCreatorCreated
diff --git a/server/operations/jobs/job_lister.go b/server/operations/jobs/job_lister.go
index 002c4c5..38fe24b 100644
--- a/server/operations/jobs/job_lister.go
+++ b/server/operations/jobs/job_lister.go
@@ -23,7 +23,12 @@ package jobs
import (
"net/http"
+ errors "github.com/go-openapi/errors"
middleware "github.com/go-openapi/runtime/middleware"
+ strfmt "github.com/go-openapi/strfmt"
+ swag "github.com/go-openapi/swag"
+
+ weles "github.com/SamsungSLAV/weles"
)
// JobListerHandlerFunc turns a function with the right signature into a job lister handler
@@ -73,3 +78,86 @@ func (o *JobLister) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
o.Context.Respond(rw, r, route.Produces, route, res)
}
+
+// JobListerBody Data for filtering and sorting Weles Jobs lists.
+// swagger:model JobListerBody
+type JobListerBody struct {
+
+ // filter
+ Filter *weles.JobFilter `json:"Filter,omitempty"`
+
+ // sorter
+ Sorter *weles.JobSorter `json:"Sorter,omitempty"`
+}
+
+// Validate validates this job lister body
+func (o *JobListerBody) Validate(formats strfmt.Registry) error {
+ var res []error
+
+ if err := o.validateFilter(formats); err != nil {
+ res = append(res, err)
+ }
+
+ if err := o.validateSorter(formats); err != nil {
+ res = append(res, err)
+ }
+
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
+
+func (o *JobListerBody) validateFilter(formats strfmt.Registry) error {
+
+ if swag.IsZero(o.Filter) { // not required
+ return nil
+ }
+
+ if o.Filter != nil {
+ if err := o.Filter.Validate(formats); err != nil {
+ if ve, ok := err.(*errors.Validation); ok {
+ return ve.ValidateName("jobFilterAndSort" + "." + "Filter")
+ }
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (o *JobListerBody) validateSorter(formats strfmt.Registry) error {
+
+ if swag.IsZero(o.Sorter) { // not required
+ return nil
+ }
+
+ if o.Sorter != nil {
+ if err := o.Sorter.Validate(formats); err != nil {
+ if ve, ok := err.(*errors.Validation); ok {
+ return ve.ValidateName("jobFilterAndSort" + "." + "Sorter")
+ }
+ return err
+ }
+ }
+
+ return nil
+}
+
+// MarshalBinary interface implementation
+func (o *JobListerBody) MarshalBinary() ([]byte, error) {
+ if o == nil {
+ return nil, nil
+ }
+ return swag.WriteJSON(o)
+}
+
+// UnmarshalBinary interface implementation
+func (o *JobListerBody) UnmarshalBinary(b []byte) error {
+ var res JobListerBody
+ if err := swag.ReadJSON(b, &res); err != nil {
+ return err
+ }
+ *o = res
+ return nil
+}
diff --git a/server/operations/jobs/job_lister_parameters.go b/server/operations/jobs/job_lister_parameters.go
index abfbd17..1613e18 100644
--- a/server/operations/jobs/job_lister_parameters.go
+++ b/server/operations/jobs/job_lister_parameters.go
@@ -29,8 +29,6 @@ import (
"github.com/go-openapi/swag"
strfmt "github.com/go-openapi/strfmt"
-
- weles "git.tizen.org/tools/weles"
)
// NewJobListerParams creates a new JobListerParams object
@@ -60,7 +58,7 @@ type JobListerParams struct {
/*Job Filter and Sort object.
In: body
*/
- JobFilterAndSort *weles.JobFilterAndSort
+ JobFilterAndSort JobListerBody
/*Custom page limit. Denotes number of JobInfo structures that will be returned.
In: query
*/
@@ -90,7 +88,7 @@ func (o *JobListerParams) BindRequest(r *http.Request, route *middleware.Matched
if runtime.HasBody(r) {
defer r.Body.Close()
- var body weles.JobFilterAndSort
+ var body JobListerBody
if err := route.Consumer.Consume(r.Body, &body); err != nil {
res = append(res, errors.NewParseError("jobFilterAndSort", "body", "", err))
} else {
@@ -100,7 +98,7 @@ func (o *JobListerParams) BindRequest(r *http.Request, route *middleware.Matched
}
if len(res) == 0 {
- o.JobFilterAndSort = &body
+ o.JobFilterAndSort = body
}
}
}
diff --git a/server/operations/jobs/job_lister_responses.go b/server/operations/jobs/job_lister_responses.go
index 54c3556..83a41d0 100644
--- a/server/operations/jobs/job_lister_responses.go
+++ b/server/operations/jobs/job_lister_responses.go
@@ -26,7 +26,7 @@ import (
"github.com/go-openapi/runtime"
"github.com/go-openapi/swag"
- weles "git.tizen.org/tools/weles"
+ weles "github.com/SamsungSLAV/weles"
)
// JobListerOKCode is the HTTP code returned for type JobListerOK
diff --git a/server/operations/weles_api.go b/server/operations/weles_api.go
index a997979..1ca5ea9 100644
--- a/server/operations/weles_api.go
+++ b/server/operations/weles_api.go
@@ -34,8 +34,9 @@ import (
strfmt "github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
- "git.tizen.org/tools/weles/server/operations/artifacts"
- "git.tizen.org/tools/weles/server/operations/jobs"
+ "github.com/SamsungSLAV/weles/server/operations/artifacts"
+ "github.com/SamsungSLAV/weles/server/operations/general"
+ "github.com/SamsungSLAV/weles/server/operations/jobs"
)
// NewWelesAPI creates a new Weles instance
@@ -68,6 +69,9 @@ func NewWelesAPI(spec *loads.Document) *WelesAPI {
JobsJobListerHandler: jobs.JobListerHandlerFunc(func(params jobs.JobListerParams) middleware.Responder {
return middleware.NotImplemented("operation JobsJobLister has not yet been implemented")
}),
+ GeneralVersionHandler: general.VersionHandlerFunc(func(params general.VersionParams) middleware.Responder {
+ return middleware.NotImplemented("operation GeneralVersion has not yet been implemented")
+ }),
}
}
@@ -109,6 +113,8 @@ type WelesAPI struct {
JobsJobCreatorHandler jobs.JobCreatorHandler
// JobsJobListerHandler sets the operation handler for the job lister operation
JobsJobListerHandler jobs.JobListerHandler
+ // GeneralVersionHandler sets the operation handler for the version operation
+ GeneralVersionHandler general.VersionHandler
// ServeError is called when an error is received, there is a default handler
// but you can set your own with this
@@ -192,6 +198,10 @@ func (o *WelesAPI) Validate() error {
unregistered = append(unregistered, "jobs.JobListerHandler")
}
+ if o.GeneralVersionHandler == nil {
+ unregistered = append(unregistered, "general.VersionHandler")
+ }
+
if len(unregistered) > 0 {
return fmt.Errorf("missing registration: %s", strings.Join(unregistered, ", "))
}
@@ -313,6 +323,11 @@ func (o *WelesAPI) initHandlerCache() {
}
o.handlers["POST"]["/jobs/list"] = jobs.NewJobLister(o.context, o.JobsJobListerHandler)
+ if o.handlers["GET"] == nil {
+ o.handlers["GET"] = make(map[string]http.Handler)
+ }
+ o.handlers["GET"]["/version"] = general.NewVersion(o.context, o.GeneralVersionHandler)
+
}
// Serve creates a http handler to serve the API over HTTP
diff --git a/server/server.go b/server/server.go
index 25a265b..f37a876 100644
--- a/server/server.go
+++ b/server/server.go
@@ -40,7 +40,7 @@ import (
flag "github.com/spf13/pflag"
"golang.org/x/net/netutil"
- "git.tizen.org/tools/weles/server/operations"
+ "github.com/SamsungSLAV/weles/server/operations"
)
const (
@@ -100,9 +100,9 @@ func init() {
flag.StringVar(&tlsHost, "tls-host", "localhost", "the IP to listen on")
flag.IntVar(&tlsPort, "tls-port", 0, "the port to listen on for secure connections, defaults to a random value")
- flag.StringVar(&tlsCertificate, "tls-certificate", "", "the certificate to use for secure connections")
- flag.StringVar(&tlsCertificateKey, "tls-key", "", "the private key to use for secure conections")
- flag.StringVar(&tlsCACertificate, "tls-ca", "", "the certificate authority file to be used with mutual tls auth")
+ flag.StringVar(&tlsCertificate, "tls-certificate", "", "the certificate file to use for secure connections")
+ flag.StringVar(&tlsCertificateKey, "tls-key", "", "the private key file to use for secure connections (without passphrase)")
+ flag.StringVar(&tlsCACertificate, "tls-ca", "", "the certificate authority certificate file to be used with mutual tls auth")
flag.IntVar(&tlsListenLimit, "tls-listen-limit", 0, "limit the number of outstanding requests")
flag.DurationVar(&tlsKeepAlive, "tls-keep-alive", 3*time.Minute, "sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)")
flag.DurationVar(&tlsReadTimeout, "tls-read-timeout", 30*time.Second, "maximum duration before timing out read of the request")
@@ -283,11 +283,14 @@ func (s *Server) Serve() (err error) {
s.SetHandler(s.api.Serve(nil))
}
- var wg sync.WaitGroup
- quitting := make(chan struct{})
+ wg := new(sync.WaitGroup)
once := new(sync.Once)
signalNotify(s.interrupt)
- go handleInterrupt(once, s, quitting)
+ go handleInterrupt(once, s)
+
+ servers := []*http.Server{}
+ wg.Add(1)
+ go s.handleShutdown(wg, &servers)
if s.hasScheme(schemeUnix) {
domainSocket := new(http.Server)
@@ -299,16 +302,16 @@ func (s *Server) Serve() (err error) {
configureServer(domainSocket, "unix", string(s.SocketPath))
- wg.Add(2)
+ wg.Add(1)
s.Logf("Serving weles at unix://%s", s.SocketPath)
go func(l net.Listener) {
defer wg.Done()
- if err := domainSocket.Serve(l); err != nil {
+ if err := domainSocket.Serve(l); err != nil && err != http.ErrServerClosed {
s.Fatalf("%v", err)
}
s.Logf("Stopped serving weles at unix://%s", s.SocketPath)
}(s.domainSocketL)
- go s.handleShutdown(&wg, domainSocket)
+ servers = append(servers, domainSocket)
}
if s.hasScheme(schemeHTTP) {
@@ -329,16 +332,16 @@ func (s *Server) Serve() (err error) {
configureServer(httpServer, "http", s.httpServerL.Addr().String())
- wg.Add(2)
+ wg.Add(1)
s.Logf("Serving weles at http://%s", s.httpServerL.Addr())
go func(l net.Listener) {
defer wg.Done()
- if err := httpServer.Serve(l); err != nil {
+ if err := httpServer.Serve(l); err != nil && err != http.ErrServerClosed {
s.Fatalf("%v", err)
}
s.Logf("Stopped serving weles at http://%s", l.Addr())
}(s.httpServerL)
- go s.handleShutdown(&wg, httpServer)
+ servers = append(servers, httpServer)
}
if s.hasScheme(schemeHTTPS) {
@@ -373,33 +376,40 @@ func (s *Server) Serve() (err error) {
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+ tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
},
}
+ // build standard config from server options
if s.TLSCertificate != "" && s.TLSCertificateKey != "" {
httpsServer.TLSConfig.Certificates = make([]tls.Certificate, 1)
httpsServer.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(s.TLSCertificate, s.TLSCertificateKey)
+ if err != nil {
+ return err
+ }
}
if s.TLSCACertificate != "" {
+ // include specified CA certificate
caCert, caCertErr := ioutil.ReadFile(s.TLSCACertificate)
if caCertErr != nil {
- log.Fatal(caCertErr)
+ return caCertErr
}
caCertPool := x509.NewCertPool()
- caCertPool.AppendCertsFromPEM(caCert)
+ ok := caCertPool.AppendCertsFromPEM(caCert)
+ if !ok {
+ return fmt.Errorf("cannot parse CA certificate")
+ }
httpsServer.TLSConfig.ClientCAs = caCertPool
httpsServer.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert
}
+ // call custom TLS configurator
configureTLS(httpsServer.TLSConfig)
- httpsServer.TLSConfig.BuildNameToCertificate()
-
- if err != nil {
- return err
- }
if len(httpsServer.TLSConfig.Certificates) == 0 {
+ // after standard and custom config are passed, this ends up with no certificate
if s.TLSCertificate == "" {
if s.TLSCertificateKey == "" {
s.Fatalf("the required flags `--tls-certificate` and `--tls-key` were not specified")
@@ -409,20 +419,25 @@ func (s *Server) Serve() (err error) {
if s.TLSCertificateKey == "" {
s.Fatalf("the required flag `--tls-key` was not specified")
}
+ // this happens with a wrong custom TLS configurator
+ s.Fatalf("no certificate was configured for TLS")
}
+ // must have at least one certificate or panics
+ httpsServer.TLSConfig.BuildNameToCertificate()
+
configureServer(httpsServer, "https", s.httpsServerL.Addr().String())
- wg.Add(2)
+ wg.Add(1)
s.Logf("Serving weles at https://%s", s.httpsServerL.Addr())
go func(l net.Listener) {
defer wg.Done()
- if err := httpsServer.Serve(l); err != nil {
+ if err := httpsServer.Serve(l); err != nil && err != http.ErrServerClosed {
s.Fatalf("%v", err)
}
s.Logf("Stopped serving weles at https://%s", l.Addr())
}(tls.NewListener(s.httpsServerL, httpsServer.TLSConfig))
- go s.handleShutdown(&wg, httpsServer)
+ servers = append(servers, httpsServer)
}
wg.Wait()
@@ -502,48 +517,49 @@ func (s *Server) Listen() error {
// Shutdown server and clean up resources
func (s *Server) Shutdown() error {
- if atomic.LoadInt32(&s.shuttingDown) != 0 {
- s.Logf("already shutting down")
- return nil
+ if atomic.CompareAndSwapInt32(&s.shuttingDown, 0, 1) {
+ close(s.shutdown)
}
- close(s.shutdown)
return nil
}
-func (s *Server) handleShutdown(wg *sync.WaitGroup, server *http.Server) {
+func (s *Server) handleShutdown(wg *sync.WaitGroup, serversPtr *[]*http.Server) {
+ // wg.Done must occur last, after s.api.ServerShutdown()
+ // (to preserve old behaviour)
defer wg.Done()
+
+ <-s.shutdown
+
+ servers := *serversPtr
+
ctx, cancel := context.WithTimeout(context.TODO(), 15*time.Second)
defer cancel()
- <-s.shutdown
- if err := server.Shutdown(ctx); err != nil {
- // Error from closing listeners, or context timeout:
- s.Logf("HTTP server Shutdown: %v", err)
- } else {
- atomic.AddInt32(&s.shuttingDown, 1)
- select {
- case <-ctx.Done():
- if err := ctx.Err(); err != nil {
- s.Logf("Error %s", err)
- }
- default:
- done := make(chan error)
- defer close(done)
- go func() {
- <-ctx.Done()
- done <- ctx.Err()
- }()
- go func() {
- //done <- s.api.Shutdown(ctx)
- s.api.ServerShutdown()
- done <- errors.New("API shut down")
+ shutdownChan := make(chan bool)
+ for i := range servers {
+ server := servers[i]
+ go func() {
+ var success bool
+ defer func() {
+ shutdownChan <- success
}()
- if err := <-done; err != nil {
- s.Logf("Error %s", err)
+ if err := server.Shutdown(ctx); err != nil {
+ // Error from closing listeners, or context timeout:
+ s.Logf("HTTP server Shutdown: %v", err)
+ } else {
+ success = true
}
- }
+ }()
+ }
+
+ // Wait until all listeners have successfully shut down before calling ServerShutdown
+ success := true
+ for range servers {
+ success = success && <-shutdownChan
+ }
+ if success {
+ s.api.ServerShutdown()
}
- return
}
// GetHandler returns a handler useful for testing
@@ -586,7 +602,7 @@ func (s *Server) TLSListener() (net.Listener, error) {
return s.httpsServerL, nil
}
-func handleInterrupt(once *sync.Once, s *Server, quitting chan struct{}) {
+func handleInterrupt(once *sync.Once, s *Server) {
once.Do(func() {
for _ = range s.interrupt {
if s.interrupted {
@@ -595,17 +611,7 @@ func handleInterrupt(once *sync.Once, s *Server, quitting chan struct{}) {
}
s.interrupted = true
s.Logf("Shutting down... ")
- close(quitting)
-
- if err := s.httpServerL.Close(); err != nil {
- s.Logf("Error: %s", err)
- }
- if err := s.httpsServerL.Close(); err != nil {
- s.Logf("Error: %s", err)
- }
- if err := s.domainSocketL.Close(); err != nil {
- s.Logf("Error: %s", err)
- }
+ s.Shutdown()
}
})
}
diff --git a/server/server_suite_test.go b/server/server_suite_test.go
index 6e137ae..e7b16c1 100644
--- a/server/server_suite_test.go
+++ b/server/server_suite_test.go
@@ -27,19 +27,24 @@ import (
. "github.com/onsi/gomega"
"github.com/tideland/golib/audit"
- "git.tizen.org/tools/weles"
- "git.tizen.org/tools/weles/mock"
- "git.tizen.org/tools/weles/server"
- "git.tizen.org/tools/weles/server/operations"
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/mock"
+ "github.com/SamsungSLAV/weles/server"
+ "github.com/SamsungSLAV/weles/server/operations"
)
const (
- JSON = "application/json"
- OMIT = "omit"
+ JSON = "application/json"
+ OMIT = "omit"
+
dateLayout = "Mon Jan 2 15:04:05 -0700 MST 2006"
someDate = "Tue Jan 2 15:04:05 +0100 CET 1900"
durationIncrement1 = "25h"
durationIncrement2 = "+100h"
+
+ basePath = "/api/v1"
+ listArtifactsPath = "/artifacts/list"
+ listJobsPath = "/jobs/list"
)
func TestServer(t *testing.T) {
diff --git a/server/version_handler.go b/server/version_handler.go
new file mode 100644
index 0000000..322fa65
--- /dev/null
+++ b/server/version_handler.go
@@ -0,0 +1,38 @@
+// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License
+
+package server
+
+import (
+ "github.com/go-openapi/runtime/middleware"
+
+ "github.com/SamsungSLAV/weles"
+ "github.com/SamsungSLAV/weles/server/operations/general"
+)
+
+// Version is Weles version information API endpoint handler.
+//
+// Due to go-swagger server generation, and how the API endpoint was designed, parameter to this
+// function will never be used.
+// nolint:unparam
+func (a *APIDefaults) Version(params general.VersionParams) middleware.Responder {
+ var v = &weles.Version{
+ Server: weles.SrvVersion,
+ API: apiVersion,
+ State: apiState,
+ }
+
+ return general.NewVersionOK().WithPayload(v).
+ WithWelesAPIState(v.State).WithWelesAPIVersion(v.API).WithWelesServerVersion(v.Server)
+}
diff --git a/server/version_handler_test.go b/server/version_handler_test.go
new file mode 100644
index 0000000..f241d9b
--- /dev/null
+++ b/server/version_handler_test.go
@@ -0,0 +1,84 @@
+// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License
+
+package server_test
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+
+ "github.com/SamsungSLAV/weles"
+)
+
+var _ = Describe("VersionHandler", func() {
+ var (
+ testserver *httptest.Server
+ v1on010 = &weles.Version{
+ API: "v1",
+ State: "devel",
+ Server: "0.1.0",
+ }
+ )
+
+ BeforeEach(func() {
+ _, _, _, _, testserver = testServerSetup()
+ })
+
+ AfterEach(func() {
+ testserver.Close()
+ })
+
+ Describe("obtaining information on API and server version", func() {
+ getClientResp := func() (resp *http.Response) {
+ client := testserver.Client()
+
+ req, err := http.NewRequest(http.MethodGet, testserver.URL+"/api/v1/version", nil)
+ Expect(err).ToNot(HaveOccurred())
+
+ resp, err = client.Do(req)
+ Expect(err).ToNot(HaveOccurred())
+
+ return resp
+ }
+
+ Context("request to v0.1.0 API on v0.1.0 server", func() {
+ It("should respond with proper body and 200 Status Code", func() {
+ resp := getClientResp()
+ Expect(resp.StatusCode).To(Equal(200))
+ Expect(resp.Header).To(HaveKeyWithValue("Weles-Api-Version", []string{v1on010.API}))
+ Expect(resp.Header).To(HaveKeyWithValue("Weles-Api-State", []string{v1on010.State}))
+ Expect(resp.Header).To(HaveKeyWithValue("Weles-Server-Version",
+ []string{v1on010.Server}))
+
+ respBody, err := ioutil.ReadAll(resp.Body)
+ Expect(err).ToNot(HaveOccurred())
+ defer resp.Body.Close()
+
+ versionEncoded, err := json.Marshal(weles.Version{
+ API: v1on010.API,
+ State: v1on010.State,
+ Server: v1on010.Server,
+ })
+ Expect(err).ToNot(HaveOccurred())
+
+ Expect(string(respBody)).To(MatchJSON(string(versionEncoded)))
+ })
+ })
+ })
+})
diff --git a/sort_order.go b/sort_order.go
index f650ceb..404d772 100644
--- a/sort_order.go
+++ b/sort_order.go
@@ -52,7 +52,7 @@ var sortOrderEnum []interface{}
func init() {
var res []SortOrder
- if err := json.Unmarshal([]byte(`["Ascending","Descending"]`), &res); err != nil {
+ if err := json.Unmarshal([]byte(`["Ascending","Descending",""]`), &res); err != nil {
panic(err)
}
for _, v := range res {
diff --git a/swagger.yml b/swagger.yml
index 3781afe..58f2e60 100644
--- a/swagger.yml
+++ b/swagger.yml
@@ -3,7 +3,7 @@ info:
description: >-
This is a Weles server. You can find out more about Weles at
[http://tbd.tbd](http://tbd.tbd).
- version: 0.0.0
+ version: v1
title: Weles
termsOfService: 'http://tbd.tbd/terms/'
contact:
@@ -22,6 +22,8 @@ tags:
description: Info and management of Weles jobs.
- name: artifacts
description: Info about all artifacts used by Weles jobs.
+ - name: general
+ description: Info about Weles (e.g. version)
schemes:
- http
paths:
@@ -96,7 +98,13 @@ paths:
description: Job Filter and Sort object.
required: false
schema:
- $ref: '#/definitions/JobFilterAndSort'
+ description: Data for filtering and sorting Weles Jobs lists.
+ type: object
+ properties:
+ Filter:
+ $ref: '#/definitions/JobFilter'
+ Sorter:
+ $ref: '#/definitions/JobSorter'
- in: query
name: after
description: JobID of the last element from previous page.
@@ -185,7 +193,13 @@ paths:
description: Artifact Filter and Sort object.
required: false
schema:
- $ref: '#/definitions/ArtifactFilterAndSort'
+ description: Data for filtering and sorting Weles Jobs lists.
+ type: object
+ properties:
+ Filter:
+ $ref: '#/definitions/ArtifactFilter'
+ Sorter:
+ $ref: '#/definitions/ArtifactSorter'
- in: query
name: after
description: ID of the last element from previous page.
@@ -257,6 +271,33 @@ paths:
$ref: '#/responses/NotFound'
'500':
$ref: '#/responses/InternalServer'
+ /version:
+ get:
+ tags:
+ - general
+ summary: Show current version of Weles internals
+ description: Version and state of API (e.g. v1 obsolete, v2 stable,
+ v3 devel) and server version.
+ operationId: Version
+ produces:
+ - application/json
+ responses:
+ '200':
+ description: OK
+ schema:
+ $ref: '#/definitions/Version'
+ headers:
+ Weles-Server-Version:
+ type: string
+ description: Version of Weles server.
+ Weles-API-Version:
+ type: string
+ description: Version of Weles API.
+ Weles-API-State:
+ type: string
+ description: State of Weles API.
+ '500':
+ $ref: '#/responses/InternalServer'
responses:
BadRequest:
description: Bad Request
@@ -375,17 +416,20 @@ definitions:
type: string
JobSortBy:
description: |
- denotes key for sorting Jobs list. Jobs are sorted by ID (Ascending) by default.
- You can sort jobs additionaly by
+ denotes key for sorting Jobs list.
+
+ * ID - default sort key.
* CreatedDate - sorting by date of creation of the weles job.
* UpdatedDate - sorting by date of update of the weles job.
* JobStatus - sorting by the Job Status. Descending order will sort in the order JobStatuses are listed in the docs (from NEW at the start to CANCELED at the end). Ascending will reverse this order.
+
When sorting is applied, and there are many jobs with the same date/status, they will be sorted by JobID (Ascending)
type: string
enum:
+ - ID
- CreatedDate
- UpdatedDate
- JobStatus
@@ -410,14 +454,6 @@ definitions:
$ref: '#/definitions/JobSortBy'
SortOrder:
$ref: '#/definitions/SortOrder'
- JobFilterAndSort:
- description: Data for filtering and sorting Weles Jobs lists.
- type: object
- properties:
- Filter:
- $ref: '#/definitions/JobFilter'
- Sorter:
- $ref: '#/definitions/JobSorter'
ArtifactType:
description: |
denotes type and function of an artifact.
@@ -545,14 +581,24 @@ definitions:
$ref: '#/definitions/ArtifactSortBy'
SortOrder:
$ref: '#/definitions/SortOrder'
- ArtifactFilterAndSort:
- description: Data for filtering and sorting Weles Jobs lists.
+ Version:
+ description: |
+ defines version of Weles API (and its state) and server.
type: object
properties:
- Filter:
- $ref: '#/definitions/ArtifactFilter'
- Sorter:
- $ref: '#/definitions/ArtifactSorter'
+ Server:
+ description: Version of Weles server.
+ type: string
+ API:
+ description: Version of Weles API.
+ type: string
+ State:
+ description: State of Weles API.
+ type: string
+ enum:
+ - devel
+ - stable
+ - deprecated
externalDocs:
description: TBD
url: 'http://TBD.tbd'
diff --git a/version.go b/version.go
new file mode 100644
index 0000000..a73fa17
--- /dev/null
+++ b/version.go
@@ -0,0 +1,125 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License
+//
+
+package weles
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "encoding/json"
+
+ strfmt "github.com/go-openapi/strfmt"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/swag"
+ "github.com/go-openapi/validate"
+)
+
+// Version defines version of Weles API (and its state) and server.
+//
+// swagger:model Version
+type Version struct {
+
+ // Version of Weles API.
+ API string `json:"API,omitempty"`
+
+ // Version of Weles server.
+ Server string `json:"Server,omitempty"`
+
+ // State of Weles API.
+ // Enum: [devel stable deprecated]
+ State string `json:"State,omitempty"`
+}
+
+// Validate validates this version
+func (m *Version) Validate(formats strfmt.Registry) error {
+ var res []error
+
+ if err := m.validateState(formats); err != nil {
+ res = append(res, err)
+ }
+
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
+
+var versionTypeStatePropEnum []interface{}
+
+func init() {
+ var res []string
+ if err := json.Unmarshal([]byte(`["devel","stable","deprecated"]`), &res); err != nil {
+ panic(err)
+ }
+ for _, v := range res {
+ versionTypeStatePropEnum = append(versionTypeStatePropEnum, v)
+ }
+}
+
+const (
+
+ // VersionStateDevel captures enum value "devel"
+ VersionStateDevel string = "devel"
+
+ // VersionStateStable captures enum value "stable"
+ VersionStateStable string = "stable"
+
+ // VersionStateDeprecated captures enum value "deprecated"
+ VersionStateDeprecated string = "deprecated"
+)
+
+// prop value enum
+func (m *Version) validateStateEnum(path, location string, value string) error {
+ if err := validate.Enum(path, location, value, versionTypeStatePropEnum); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (m *Version) validateState(formats strfmt.Registry) error {
+
+ if swag.IsZero(m.State) { // not required
+ return nil
+ }
+
+ // value enum
+ if err := m.validateStateEnum("State", "body", m.State); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// MarshalBinary interface implementation
+func (m *Version) MarshalBinary() ([]byte, error) {
+ if m == nil {
+ return nil, nil
+ }
+ return swag.WriteJSON(m)
+}
+
+// UnmarshalBinary interface implementation
+func (m *Version) UnmarshalBinary(b []byte) error {
+ var res Version
+ if err := swag.ReadJSON(b, &res); err != nil {
+ return err
+ }
+ *m = res
+ return nil
+}
diff --git a/weles.go b/weles.go
index 43d1c08..028a4cb 100644
--- a/weles.go
+++ b/weles.go
@@ -16,3 +16,6 @@
// Package weles represents the base of the Weles system.
package weles
+
+// SrvVersion indicates version of Weles server.
+const SrvVersion string = "0.1.0"