Merge pull request #5729 from tlwr/master
Allow set_pipeline can be used across teams
This commit is contained in:
commit
ba0f27a99c
|
@ -433,6 +433,8 @@ type PlanConfig struct {
|
|||
// name of 'set_pipeline'
|
||||
SetPipeline string `json:"set_pipeline,omitempty"`
|
||||
VarFiles []string `json:"var_files,omitempty"`
|
||||
// team of 'set_pipeline', only valid for main team
|
||||
Team string `json:"team,omitempty"`
|
||||
|
||||
// config path, e.g. foo/build.yml. Multiple steps might have this field, e.g. Task step and SetPipeline step.
|
||||
File string `json:"file,omitempty"`
|
||||
|
|
|
@ -130,7 +130,47 @@ func (step *SetPipelineStep) run(ctx context.Context, state RunState) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
team := step.teamFactory.GetByID(step.metadata.TeamID)
|
||||
var team db.Team
|
||||
if step.plan.Team == "" {
|
||||
team = step.teamFactory.GetByID(step.metadata.TeamID)
|
||||
} else {
|
||||
fmt.Fprintln(stderr, "\x1b[1;33mWARNING: specifying the team in a set_pipeline step is experimental and may be removed in the future!\x1b[0m")
|
||||
fmt.Fprintln(stderr, "")
|
||||
fmt.Fprintln(stderr, "\x1b[33mcontribute to discussion #5731 with feedback: https://github.com/concourse/concourse/discussions/5731\x1b[0m")
|
||||
fmt.Fprintln(stderr, "")
|
||||
|
||||
currentTeam, found, err := step.teamFactory.FindTeam(step.metadata.TeamName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("team %s not found", step.metadata.TeamName)
|
||||
}
|
||||
|
||||
targetTeam, found, err := step.teamFactory.FindTeam(step.plan.Team)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("team %s not found", step.plan.Team)
|
||||
}
|
||||
|
||||
permitted := false
|
||||
if targetTeam.ID() == currentTeam.ID() {
|
||||
permitted = true
|
||||
}
|
||||
if currentTeam.Admin() {
|
||||
permitted = true
|
||||
}
|
||||
if !permitted {
|
||||
return fmt.Errorf(
|
||||
"only %s team can set another team's pipeline",
|
||||
atc.DefaultTeamName,
|
||||
)
|
||||
}
|
||||
|
||||
team = targetTeam
|
||||
}
|
||||
|
||||
fromVersion := db.ConfigVersion(0)
|
||||
pipeline, found, err := team.Pipeline(step.plan.Name)
|
||||
|
|
|
@ -94,14 +94,7 @@ jobs:
|
|||
|
||||
credVarsTracker vars.CredVarsTracker
|
||||
|
||||
stepMetadata = exec.StepMetadata{
|
||||
TeamID: 123,
|
||||
TeamName: "some-team",
|
||||
BuildID: 42,
|
||||
BuildName: "some-build",
|
||||
PipelineID: 4567,
|
||||
PipelineName: "some-pipeline",
|
||||
}
|
||||
stepMetadata exec.StepMetadata
|
||||
|
||||
stdout, stderr *gbytes.Buffer
|
||||
|
||||
|
@ -135,7 +128,18 @@ jobs:
|
|||
fakeTeam = new(dbfakes.FakeTeam)
|
||||
fakePipeline = new(dbfakes.FakePipeline)
|
||||
|
||||
fakeTeam.NameReturns("some-team")
|
||||
stepMetadata = exec.StepMetadata{
|
||||
TeamID: 123,
|
||||
TeamName: "some-team",
|
||||
BuildID: 42,
|
||||
BuildName: "some-build",
|
||||
PipelineID: 4567,
|
||||
PipelineName: "some-pipeline",
|
||||
}
|
||||
|
||||
fakeTeam.IDReturns(stepMetadata.TeamID)
|
||||
fakeTeam.NameReturns(stepMetadata.TeamName)
|
||||
|
||||
fakePipeline.NameReturns("some-pipeline")
|
||||
fakeTeamFactory.GetByIDReturns(fakeTeam)
|
||||
|
||||
|
@ -305,6 +309,117 @@ jobs:
|
|||
Expect(succeeded).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
Context("when team is configured", func() {
|
||||
var (
|
||||
fakeUserCurrentTeam *dbfakes.FakeTeam
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
fakeUserCurrentTeam = new(dbfakes.FakeTeam)
|
||||
fakeUserCurrentTeam.IDReturns(111)
|
||||
fakeUserCurrentTeam.NameReturns("main")
|
||||
fakeUserCurrentTeam.AdminReturns(false)
|
||||
|
||||
stepMetadata.TeamID = fakeUserCurrentTeam.ID()
|
||||
stepMetadata.TeamName = fakeUserCurrentTeam.Name()
|
||||
fakeTeamFactory.FindTeamReturnsOnCall(
|
||||
0,
|
||||
fakeUserCurrentTeam, true, nil,
|
||||
)
|
||||
})
|
||||
|
||||
Context("when team is set to the empty string", func() {
|
||||
BeforeEach(func() {
|
||||
fakeTeam.PipelineReturns(fakePipeline, true, nil)
|
||||
fakeTeam.SavePipelineReturns(fakePipeline, false, nil)
|
||||
spPlan.Team = ""
|
||||
})
|
||||
|
||||
It("should finish successfully", func() {
|
||||
Expect(fakeDelegate.FinishedCallCount()).To(Equal(1))
|
||||
_, succeeded := fakeDelegate.FinishedArgsForCall(0)
|
||||
Expect(succeeded).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
Context("when team does not exist", func() {
|
||||
BeforeEach(func() {
|
||||
spPlan.Team = "not-found"
|
||||
fakeTeamFactory.FindTeamReturnsOnCall(
|
||||
1,
|
||||
nil, false, nil,
|
||||
)
|
||||
})
|
||||
|
||||
It("should return error", func() {
|
||||
Expect(stepErr).To(HaveOccurred())
|
||||
Expect(stepErr.Error()).To(Equal("team not-found not found"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when team exists", func() {
|
||||
Context("when the target team is the current team", func() {
|
||||
BeforeEach(func() {
|
||||
spPlan.Team = fakeUserCurrentTeam.Name()
|
||||
fakeTeamFactory.FindTeamReturnsOnCall(
|
||||
1,
|
||||
fakeUserCurrentTeam, true, nil,
|
||||
)
|
||||
|
||||
fakeUserCurrentTeam.PipelineReturns(fakePipeline, true, nil)
|
||||
fakeUserCurrentTeam.SavePipelineReturns(fakePipeline, false, nil)
|
||||
})
|
||||
|
||||
It("should finish successfully", func() {
|
||||
Expect(fakeDelegate.FinishedCallCount()).To(Equal(1))
|
||||
_, succeeded := fakeDelegate.FinishedArgsForCall(0)
|
||||
Expect(succeeded).To(BeTrue())
|
||||
})
|
||||
|
||||
It("should print an experimental message", func() {
|
||||
Expect(stderr).To(gbytes.Say("WARNING: specifying the team"))
|
||||
Expect(stderr).To(gbytes.Say("contribute to discussion #5731"))
|
||||
Expect(stderr).To(gbytes.Say("discussions/5731"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when the team is not the current team", func() {
|
||||
BeforeEach(func() {
|
||||
spPlan.Team = fakeTeam.Name()
|
||||
fakeTeamFactory.FindTeamReturnsOnCall(
|
||||
1,
|
||||
fakeTeam, true, nil,
|
||||
)
|
||||
})
|
||||
|
||||
Context("when the current team is an admin team", func() {
|
||||
BeforeEach(func() {
|
||||
fakeUserCurrentTeam.AdminReturns(true)
|
||||
|
||||
fakeTeam.PipelineReturns(fakePipeline, true, nil)
|
||||
fakeTeam.SavePipelineReturns(fakePipeline, false, nil)
|
||||
})
|
||||
|
||||
It("should finish successfully", func() {
|
||||
Expect(fakeDelegate.FinishedCallCount()).To(Equal(1))
|
||||
_, succeeded := fakeDelegate.FinishedArgsForCall(0)
|
||||
Expect(succeeded).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
Context("when the current team is not an admin team", func() {
|
||||
It("should return error", func() {
|
||||
|
||||
Expect(stepErr).To(HaveOccurred())
|
||||
Expect(stepErr.Error()).To(Equal(
|
||||
"only main team can set another team's pipeline",
|
||||
))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -211,6 +211,7 @@ type TaskPlan struct {
|
|||
type SetPipelinePlan struct {
|
||||
Name string `json:"name"`
|
||||
File string `json:"file"`
|
||||
Team string `json:"team,omitempty"`
|
||||
Vars map[string]interface{} `json:"vars,omitempty"`
|
||||
VarFiles []string `json:"var_files,omitempty"`
|
||||
}
|
||||
|
|
|
@ -262,8 +262,10 @@ func (plan TaskPlan) Public() *json.RawMessage {
|
|||
func (plan SetPipelinePlan) Public() *json.RawMessage {
|
||||
return enc(struct {
|
||||
Name string `json:"name"`
|
||||
Team string `json:"team"`
|
||||
}{
|
||||
Name: plan.Name,
|
||||
Team: plan.Team,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -354,6 +354,7 @@ var _ = Describe("Plan", func() {
|
|||
ID: "37",
|
||||
SetPipeline: &atc.SetPipelinePlan{
|
||||
Name: "some-pipeline",
|
||||
Team: "some-team",
|
||||
File: "some-file",
|
||||
VarFiles: []string{"vf"},
|
||||
Vars: map[string]interface{}{"k1": "v1"},
|
||||
|
@ -621,7 +622,8 @@ var _ = Describe("Plan", func() {
|
|||
{
|
||||
"id": "37",
|
||||
"set_pipeline": {
|
||||
"name": "some-pipeline"
|
||||
"name": "some-pipeline",
|
||||
"team": "some-team"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -281,6 +281,7 @@ func (factory *buildFactory) basePlan(
|
|||
plan = factory.planFactory.NewPlan(atc.SetPipelinePlan{
|
||||
Name: name,
|
||||
File: planConfig.File,
|
||||
Team: planConfig.Team,
|
||||
Vars: planConfig.Vars,
|
||||
VarFiles: planConfig.VarFiles,
|
||||
})
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
resources:
|
||||
- name: some-resource
|
||||
type: mock
|
||||
source:
|
||||
create_files:
|
||||
pipeline.yml: |
|
||||
---
|
||||
jobs:
|
||||
- name: normal-job
|
||||
public: true
|
||||
plan:
|
||||
- task: a-task
|
||||
config:
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: mock
|
||||
source: {mirror_self: true}
|
||||
run:
|
||||
path: echo
|
||||
args: ["hello world"]
|
||||
name.yml: |
|
||||
---
|
||||
name: somebody
|
||||
|
||||
jobs:
|
||||
- name: sp
|
||||
public: true
|
||||
plan:
|
||||
- get: some-resource
|
||||
- set_pipeline: ((pipeline_name))
|
||||
team: ((team_name))
|
||||
file: some-resource/pipeline.yml
|
||||
var_files:
|
||||
- some-resource/name.yml
|
||||
vars:
|
||||
greetings: hello
|
|
@ -1,103 +1,134 @@
|
|||
package testflight_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/gbytes"
|
||||
"github.com/onsi/gomega/gexec"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var _ = Describe("set-pipeline Step", func() {
|
||||
|
||||
const pipeline_content = `---
|
||||
resources:
|
||||
- name: some-resource
|
||||
type: mock
|
||||
source:
|
||||
create_files:
|
||||
pipeline.yml: |
|
||||
---
|
||||
jobs:
|
||||
- name: normal-job
|
||||
public: true
|
||||
plan:
|
||||
- task: a-task
|
||||
config:
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: mock
|
||||
source: {mirror_self: true}
|
||||
run:
|
||||
path: echo
|
||||
args: ["hello world"]
|
||||
name.yml: |
|
||||
---
|
||||
name: somebody
|
||||
|
||||
jobs:
|
||||
- name: sp
|
||||
public: true
|
||||
plan:
|
||||
- get: some-resource
|
||||
- set_pipeline: %s
|
||||
file: some-resource/pipeline.yml
|
||||
var_files:
|
||||
- some-resource/name.yml
|
||||
vars:
|
||||
greetings: hello
|
||||
`
|
||||
|
||||
var fixture string
|
||||
var (
|
||||
createdPipelineName string
|
||||
currentTeamName string
|
||||
currentFlyTarget string
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
var err error
|
||||
|
||||
fixture = filepath.Join(tmp, "fixture")
|
||||
|
||||
err = os.MkdirAll(fixture, 0755)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
createdPipelineName = randomPipelineName()
|
||||
})
|
||||
|
||||
Context("set other pipeline", func() {
|
||||
var secondPipelineName string
|
||||
BeforeEach(func() {
|
||||
pipelineName = "first-sp"
|
||||
secondPipelineName = "second-sp"
|
||||
|
||||
err := ioutil.WriteFile(
|
||||
filepath.Join(fixture, pipelineName+".yml"),
|
||||
[]byte(fmt.Sprintf(pipeline_content, secondPipelineName)),
|
||||
0755,
|
||||
JustBeforeEach(func() {
|
||||
withFlyTarget(currentFlyTarget, func() {
|
||||
setAndUnpausePipeline(
|
||||
"fixtures/set-pipeline.yml",
|
||||
"-v", "team_name="+currentTeamName,
|
||||
"-v", "pipeline_name="+createdPipelineName,
|
||||
)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
fly("set-pipeline", "-n", "-p", pipelineName, "-c", fixture+"/"+pipelineName+".yml")
|
||||
fly("unpause-pipeline", "-p", pipelineName)
|
||||
AfterEach(func() {
|
||||
withFlyTarget(currentFlyTarget, func() {
|
||||
fly("destroy-pipeline", "-n", "-p", pipelineName)
|
||||
})
|
||||
})
|
||||
|
||||
Context("when setting the current team's pipeline", func() {
|
||||
BeforeEach(func() {
|
||||
currentFlyTarget = testflightFlyTarget
|
||||
currentTeamName = ""
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
fly("destroy-pipeline", "-n", "-p", secondPipelineName)
|
||||
fly("destroy-pipeline", "-n", "-p", createdPipelineName)
|
||||
})
|
||||
|
||||
It("set the other pipeline", func() {
|
||||
It("sets the other pipeline", func() {
|
||||
By("second pipeline should initially not exist")
|
||||
execS := spawnFly("get-pipeline", "-p", secondPipelineName)
|
||||
execS := spawnFly("get-pipeline", "-p", createdPipelineName)
|
||||
<-execS.Exited
|
||||
Expect(execS).To(gexec.Exit(1))
|
||||
Expect(execS.Err).To(gbytes.Say("pipeline not found"))
|
||||
|
||||
By("set-pipeline step should succeed")
|
||||
execS = fly("trigger-job", "-w", "-j", pipelineName+"/sp")
|
||||
Expect(execS.Out).To(gbytes.Say("setting pipeline: second-sp"))
|
||||
Expect(execS.Out).To(gbytes.Say("setting pipeline: " + createdPipelineName))
|
||||
Expect(execS.Out).To(gbytes.Say("done"))
|
||||
|
||||
By("should trigger the second pipeline job successfully")
|
||||
execS = fly("trigger-job", "-w", "-j", secondPipelineName+"/normal-job")
|
||||
execS = fly("trigger-job", "-w", "-j", createdPipelineName+"/normal-job")
|
||||
Expect(execS.Out).To(gbytes.Say("hello world"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when setting another team's pipeline from the main team", func() {
|
||||
BeforeEach(func() {
|
||||
currentFlyTarget = adminFlyTarget
|
||||
currentTeamName = teamName
|
||||
})
|
||||
|
||||
It("sets the other pipeline", func() {
|
||||
By("second pipeline should initially not exist")
|
||||
withFlyTarget(testflightFlyTarget, func() {
|
||||
execS := spawnFly("get-pipeline", "-p", createdPipelineName)
|
||||
<-execS.Exited
|
||||
Expect(execS).To(gexec.Exit(1))
|
||||
Expect(execS.Err).To(gbytes.Say("pipeline not found"))
|
||||
})
|
||||
|
||||
By("set-pipeline step should succeed")
|
||||
withFlyTarget(adminFlyTarget, func() {
|
||||
execS := fly("trigger-job", "-w", "-j", pipelineName+"/sp")
|
||||
Expect(execS.Out).To(gbytes.Say("setting pipeline: " + createdPipelineName))
|
||||
Expect(execS.Out).To(gbytes.Say("done"))
|
||||
})
|
||||
|
||||
By("should trigger the second pipeline job successfully")
|
||||
withFlyTarget(testflightFlyTarget, func() {
|
||||
execS := fly("trigger-job", "-w", "-j", createdPipelineName+"/normal-job")
|
||||
Expect(execS.Out).To(gbytes.Say("hello world"))
|
||||
})
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
withFlyTarget(testflightFlyTarget, func() {
|
||||
fly("destroy-pipeline", "-n", "-p", createdPipelineName)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Context("when setting the main team's pipeline from a normal team", func() {
|
||||
BeforeEach(func() {
|
||||
currentFlyTarget = testflightFlyTarget
|
||||
currentTeamName = "main"
|
||||
})
|
||||
|
||||
It("fails to set the other pipeline", func() {
|
||||
By("second pipeline should initially not exist")
|
||||
withFlyTarget(adminFlyTarget, func() {
|
||||
execS := spawnFly("get-pipeline", "-p", createdPipelineName)
|
||||
<-execS.Exited
|
||||
Expect(execS).To(gexec.Exit(1))
|
||||
Expect(execS.Err).To(gbytes.Say("pipeline not found"))
|
||||
})
|
||||
|
||||
By("set-pipeline step should fail")
|
||||
withFlyTarget(testflightFlyTarget, func() {
|
||||
execS := spawnFly("trigger-job", "-w", "-j", pipelineName+"/sp")
|
||||
<-execS.Exited
|
||||
Expect(execS).To(gexec.Exit(2))
|
||||
Expect(execS.Out).To(gbytes.Say("only main team can set another team's pipeline"))
|
||||
Expect(execS.Out).To(gbytes.Say("errored"))
|
||||
})
|
||||
|
||||
By("second pipeline should still not exist")
|
||||
withFlyTarget(adminFlyTarget, func() {
|
||||
execS := spawnFly("get-pipeline", "-p", createdPipelineName)
|
||||
<-execS.Exited
|
||||
Expect(execS).To(gexec.Exit(1))
|
||||
Expect(execS.Err).To(gbytes.Say("pipeline not found"))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue