--- /dev/null
+/*
+ * Copyright (c) 2017 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
+ */
+
+// File controller/parserimpl.go implements Parser.
+
+package controller
+
+import (
+ "fmt"
+ "io/ioutil"
+
+ . "git.tizen.org/tools/weles"
+ "git.tizen.org/tools/weles/controller/notifier"
+)
+
+// ParserImpl implements Parser for Controller.
+type ParserImpl struct {
+ // Notifier provides channel for communication with Controller.
+ notifier.Notifier
+ // jobs references module implementing Jobs management.
+ jobs JobsController
+ // artifacts references Weles module implementing ArtifactManager for
+ // managing ArtifactsDB.
+ artifacts ArtifactManager
+ // parser references Weles module implementing YamlParser for unmarshaling
+ // yaml Job recipe.
+ parser YamlParser
+}
+
+// NewParser creates a new ParserImpl structure setting up references
+// to used Weles modules.
+func NewParser(j JobsController, a ArtifactManager, p YamlParser) Parser {
+ return &ParserImpl{
+ Notifier: notifier.NewNotifier(),
+ jobs: j,
+ artifacts: a,
+ parser: p,
+ }
+}
+
+// Parse prepares new Job to be processed by saving yaml file in ArtifactDB,
+// parsing yaml and preparing Job's configuration.
+func (h *ParserImpl) Parse(j JobID) {
+ err := h.jobs.SetStatusAndInfo(j, JOB_PARSING, "")
+ if err != nil {
+ h.SendFail(j, fmt.Sprintf("Internal Weles error while changing Job status : %s", err.Error()))
+ return
+ }
+
+ yaml, err := h.jobs.GetYaml(j)
+ if err != nil {
+ h.SendFail(j, fmt.Sprintf("Internal Weles error while getting yaml description : %s", err.Error()))
+ return
+ }
+
+ path, err := h.artifacts.CreateArtifact(ArtifactDescription{
+ JobID: j,
+ Type: AM_YAMLFILE,
+ })
+ if err != nil {
+ h.SendFail(j, fmt.Sprintf("Internal Weles error while creating file path in ArtifactDB : %s", err.Error()))
+ return
+ }
+
+ err = ioutil.WriteFile(string(path), yaml, 0644)
+ if err != nil {
+ h.SendFail(j, fmt.Sprintf("Internal Weles error while saving file in ArtifactDB : %s", err.Error()))
+ return
+ }
+
+ conf, err := h.parser.ParseYaml(yaml)
+ if err != nil {
+ h.SendFail(j, fmt.Sprintf("Error parsing yaml file : %s", err.Error()))
+ return
+ }
+
+ err = h.jobs.SetConfig(j, conf)
+ if err != nil {
+ h.SendFail(j, fmt.Sprintf("Internal Weles error while setting config : %s", err.Error()))
+ return
+ }
+
+ h.SendOK(j)
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 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 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"
+ gomock "github.com/golang/mock/gomock"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("ParserImpl", func() {
+ var r <-chan Notification
+ var jc *cmock.MockJobsController
+ var am *mock.MockArtifactManager
+ var yp *mock.MockYamlParser
+ var h Parser
+ var ctrl *gomock.Controller
+ j := JobID(0xCAFE)
+ goodpath := ArtifactPath("/tmp/weles_test")
+ badpath := ArtifactPath("/such/path/does/not/exist")
+ config := Config{JobName: "Test name"}
+ yaml := []byte("test yaml")
+ err := errors.New("test error")
+
+ BeforeEach(func() {
+ ctrl = gomock.NewController(GinkgoT())
+
+ jc = cmock.NewMockJobsController(ctrl)
+ am = mock.NewMockArtifactManager(ctrl)
+ yp = mock.NewMockYamlParser(ctrl)
+
+ h = NewParser(jc, am, yp)
+ r = h.Listen()
+ })
+ AfterEach(func() {
+ ctrl.Finish()
+ })
+ Describe("NewParser", func() {
+ It("should create a new object", func() {
+ Expect(h).NotTo(BeNil())
+ Expect(h.(*ParserImpl).jobs).To(Equal(jc))
+ Expect(h.(*ParserImpl).artifacts).To(Equal(am))
+ Expect(h.(*ParserImpl).parser).To(Equal(yp))
+ })
+ })
+ Describe("Parse", func() {
+ It("should handle job successfully", func() {
+ gomock.InOrder(
+ jc.EXPECT().SetStatusAndInfo(j, JOB_PARSING, ""),
+ jc.EXPECT().GetYaml(j).Return(yaml, nil),
+ am.EXPECT().CreateArtifact(ArtifactDescription{JobID: j, Type: AM_YAMLFILE}).Return(goodpath, nil),
+ yp.EXPECT().ParseYaml(yaml).Return(config, nil),
+ jc.EXPECT().SetConfig(j, config),
+ )
+
+ h.Parse(j)
+
+ Eventually(r).Should(Receive(Equal(Notification{
+ JobID: j,
+ OK: true,
+ })))
+ })
+ It("should fail when unable to set config", func() {
+ gomock.InOrder(
+ jc.EXPECT().SetStatusAndInfo(j, JOB_PARSING, ""),
+ jc.EXPECT().GetYaml(j).Return(yaml, nil),
+ am.EXPECT().CreateArtifact(ArtifactDescription{JobID: j, Type: AM_YAMLFILE}).Return(goodpath, nil),
+ yp.EXPECT().ParseYaml(yaml).Return(config, nil),
+ jc.EXPECT().SetConfig(j, config).Return(err),
+ )
+
+ h.Parse(j)
+
+ notification := Notification{}
+ expectedNotification := Notification{
+ JobID: j,
+ OK: false,
+ Msg: "Internal Weles error while setting config : " + err.Error(),
+ }
+ Eventually(r).Should(Receive(¬ification))
+ Expect(notification).To(Equal(expectedNotification))
+ })
+ It("should fail when unable to parse yaml", func() {
+ gomock.InOrder(
+ jc.EXPECT().SetStatusAndInfo(j, JOB_PARSING, ""),
+ jc.EXPECT().GetYaml(j).Return(yaml, nil),
+ am.EXPECT().CreateArtifact(ArtifactDescription{JobID: j, Type: AM_YAMLFILE}).Return(goodpath, nil),
+ yp.EXPECT().ParseYaml(yaml).Return(Config{}, err),
+ )
+
+ h.Parse(j)
+
+ notification := Notification{}
+ expectedNotification := Notification{
+ JobID: j,
+ OK: false,
+ Msg: "Error parsing yaml file : " + err.Error(),
+ }
+ Eventually(r).Should(Receive(¬ification))
+ Expect(notification).To(Equal(expectedNotification))
+ })
+ It("should fail when unable to write yaml file", func() {
+ gomock.InOrder(
+ jc.EXPECT().SetStatusAndInfo(j, JOB_PARSING, ""),
+ jc.EXPECT().GetYaml(j).Return(yaml, nil),
+ am.EXPECT().CreateArtifact(ArtifactDescription{JobID: j, Type: AM_YAMLFILE}).Return(badpath, nil),
+ )
+
+ h.Parse(j)
+
+ notification := Notification{}
+ expectedNotification := Notification{
+ JobID: j,
+ OK: false,
+ Msg: "Internal Weles error while saving file in ArtifactDB : " + "open " + string(badpath) + ": no such file or directory",
+ }
+ Eventually(r).Should(Receive(¬ification))
+ Expect(notification).To(Equal(expectedNotification))
+ })
+ It("should fail when unable to create path in ArtifactDB", func() {
+ gomock.InOrder(
+ jc.EXPECT().SetStatusAndInfo(j, JOB_PARSING, ""),
+ jc.EXPECT().GetYaml(j).Return(yaml, nil),
+ am.EXPECT().CreateArtifact(ArtifactDescription{JobID: j, Type: AM_YAMLFILE}).Return(ArtifactPath(""), err),
+ )
+
+ h.Parse(j)
+
+ notification := Notification{}
+ expectedNotification := Notification{
+ JobID: j,
+ OK: false,
+ Msg: "Internal Weles error while creating file path in ArtifactDB : " + err.Error(),
+ }
+ Eventually(r).Should(Receive(¬ification))
+ Expect(notification).To(Equal(expectedNotification))
+ })
+ It("should fail when unable to get yaml", func() {
+ gomock.InOrder(
+ jc.EXPECT().SetStatusAndInfo(j, JOB_PARSING, ""),
+ jc.EXPECT().GetYaml(j).Return([]byte{}, err),
+ )
+
+ h.Parse(j)
+
+ notification := Notification{}
+ expectedNotification := Notification{
+ JobID: j,
+ OK: false,
+ Msg: "Internal Weles error while getting yaml description : " + err.Error(),
+ }
+ Eventually(r).Should(Receive(¬ification))
+ Expect(notification).To(Equal(expectedNotification))
+ })
+ It("should fail when unable to change job status", func() {
+ jc.EXPECT().SetStatusAndInfo(j, JOB_PARSING, "").Return(err)
+
+ h.Parse(j)
+
+ notification := Notification{}
+ expectedNotification := Notification{
+ JobID: j,
+ OK: false,
+ Msg: "Internal Weles error while changing Job status : " + err.Error(),
+ }
+ Eventually(r).Should(Receive(¬ification))
+ Expect(notification).To(Equal(expectedNotification))
+ })
+ })
+})