Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6a84c3a

Browse files
Ben Howardopenshift-merge-robot
Ben Howard
authored andcommittedNov 17, 2020
Gangplank: allow for unbound pod creation in OpenShift or Podman
Instead of having a generic "ci" command, this supports generic Kubernetes or Podman as "backend" workers for Gangplank. The podman interface is primarly targeted for developer use-cases, while the OpenShift kubernetes interface is for running Gangplank in arbitrary clusters (i.e. GKE, AKE, etc.). This allows for CoreOS builds to happen anywhere a pod-can be run without needing to know much more than some YAML. Signed-off-by: Ben Howard <[email protected]>
1 parent 913310d commit 6a84c3a

17 files changed

+498
-190
lines changed
 

‎gangplank/cmd/build.go

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ func init() {
4545
// source or binary build strategies.
4646
func runOCP(c *cobra.Command, args []string) {
4747
defer cancel()
48+
defer ctx.Done()
4849

4950
// Terminal "keep alive" helper. When following logs via the `oc` commands,
5051
// cloud-deployed will send an EOF. To get around the EOF, the func sends a

‎gangplank/cmd/ci.go

-44
This file was deleted.

‎gangplank/cmd/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ var (
3838
cmdRoot = &cobra.Command{
3939
Use: "gangplank [command]",
4040
Short: "COSA Gangplank",
41-
Long: `Openshift COSA Job Runner
41+
Long: `OpenShift COSA Job Runner
4242
Wrapper for COSA commands and templates`,
4343
PersistentPreRun: preRun,
4444
}

‎gangplank/cmd/pod.go

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package main
2+
3+
import (
4+
"os"
5+
6+
"github.com/coreos/gangplank/ocp"
7+
log "github.com/sirupsen/logrus"
8+
"github.com/spf13/cobra"
9+
)
10+
11+
const cosaDefaultImage = "quay.io/coreos-assembler/coreos-assembler:latest"
12+
13+
var (
14+
cmdPod = &cobra.Command{
15+
Use: "pod",
16+
Short: "Execute COSA command in an OpenShift Cluster (default) or Podman",
17+
Run: runPod,
18+
}
19+
20+
// cosaOverrideImage uses a different image
21+
cosaOverrideImage string
22+
23+
// serviceAccount is the service acount to use for pod creation
24+
// and reading of the secrets.
25+
serviceAccount string
26+
27+
// cosaCmds is used to define the commands to run
28+
cosaCmds []string
29+
30+
// Run CI pod via podman (out of cluster)
31+
cosaViaPodman bool
32+
33+
// workDir is used for podman mode
34+
cosaWorkDir string
35+
)
36+
37+
func init() {
38+
cmdRoot.AddCommand(cmdPod)
39+
cmdPod.Flags().BoolVarP(&cosaViaPodman, "podman", "", false, "use podman to execute task")
40+
cmdPod.Flags().StringSliceVarP(&cosaCmds, "cmd", "c", []string{}, "commands to run")
41+
cmdPod.Flags().StringVarP(&cosaOverrideImage, "image", "i", "", "use an alternative image")
42+
cmdPod.Flags().StringVarP(&cosaWorkDir, "workDir", "w", "", "podman mode - workdir to use")
43+
cmdPod.Flags().StringVarP(&serviceAccount, "serviceaccount", "a", "", "service account to use")
44+
}
45+
46+
// runPod is the Jenkins/CI interface into Gangplank. It "mocks"
47+
// the OpenShift buildconfig API with just-enough information to be
48+
// useful.
49+
func runPod(c *cobra.Command, args []string) {
50+
defer cancel()
51+
52+
inCluster := true
53+
launchMode := "OpenShift"
54+
if cosaViaPodman {
55+
inCluster = false
56+
launchMode = "Podman"
57+
if cosaOverrideImage == "" {
58+
cosaOverrideImage = cosaDefaultImage
59+
}
60+
if cosaWorkDir == "" {
61+
cosaWorkDir, _ = os.Getwd()
62+
}
63+
}
64+
pb, err := ocp.NewPodBuilder(ctx, inCluster, cosaOverrideImage, serviceAccount, specFile, cosaWorkDir)
65+
if err != nil {
66+
log.Fatalf("failed to define builder pod: %v", err)
67+
}
68+
69+
log.Infof("Lauching %s worker pod(s)", launchMode)
70+
if err := pb.Exec(ctx, cosaWorkDir); err != nil {
71+
log.Fatalf("failed to execute CI builder: %v", err)
72+
}
73+
}

‎gangplank/ocp/bc.go

+21-20
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/coreos/gangplank/spec"
2424
buildapiv1 "github.com/openshift/api/build/v1"
2525
log "github.com/sirupsen/logrus"
26+
"k8s.io/client-go/kubernetes"
2627
)
2728

2829
var (
@@ -56,6 +57,9 @@ type buildConfig struct {
5657

5758
// Internal copy of the JobSpec
5859
JobSpec spec.JobSpec
60+
61+
KubeClient *kubernetes.Clientset
62+
KubeProject string
5963
}
6064

6165
// newBC accepts a context and returns a buildConfig
@@ -74,31 +78,30 @@ func newBC() (*buildConfig, error) {
7478
}
7579
}
7680

77-
// Open the Kubernetes Client
78-
ac, pn, kubeErr := k8sInClusterClient()
79-
8081
// Init the OpenShift Build API Client.
81-
buildAPIErr := ocpBuildClient()
82-
if buildAPIErr != nil && buildAPIErr != ErrNoOCPBuildSpec {
83-
log.Errorf("Failed to initalized the OpenShift Build API Client: %v", buildAPIErr)
84-
return nil, buildAPIErr
85-
}
86-
87-
if kubeErr != nil && buildAPIErr != nil {
88-
return nil, ErrInvalidOCPMode
82+
if err := ocpBuildClient(); err != nil {
83+
log.WithError(err).Error("Failed to initalized the OpenShift Build API Client")
84+
return nil, err
8985
}
9086

9187
// Query Kubernetes to find out what this pods network identity is.
9288
// TODO: remove this CI exception once we have a kubernetes mock
9389
if !forceNotInCluster {
90+
ac, pn, kubeErr := k8sInClusterClient()
91+
if kubeErr != nil {
92+
return nil, ErrInvalidOCPMode
93+
}
94+
v.KubeClient = ac
95+
v.KubeProject = pn
96+
9497
v.HostPod = fmt.Sprintf("%s-%s-build",
9598
apiBuild.Annotations[buildapiv1.BuildConfigAnnotation],
9699
apiBuild.Annotations[buildapiv1.BuildNumberAnnotation],
97100
)
98101

99-
_, ok := apiBuild.Annotations[ciRunnerTag]
102+
_, ok := apiBuild.Annotations[podBuildRunnerTag]
100103
if ok {
101-
v.HostIP = apiBuild.Annotations[fmt.Sprintf(ciAnnotation, "IP")]
104+
v.HostIP = apiBuild.Annotations[fmt.Sprintf(podBuildAnnotation, "IP")]
102105
} else {
103106
log.Info("Querying for pod ID")
104107
hIP, err := getPodIP(ac, pn, v.HostPod)
@@ -140,6 +143,8 @@ func newBC() (*buildConfig, error) {
140143
v.JobSpec = njs
141144
}
142145
}
146+
147+
log.Info("Running Pod in buildconfig mode.")
143148
return &v, nil
144149
}
145150

@@ -152,11 +157,6 @@ func (bc *buildConfig) Exec(ctx context.Context) error {
152157
return err
153158
}
154159

155-
ac, pn, err := k8sInClusterClient()
156-
if err != nil {
157-
return fmt.Errorf("failed create a kubernetes client: %w", err)
158-
}
159-
160160
// Define, but do not start minio.
161161
m := newMinioServer()
162162
m.dir = cosaSrvDir
@@ -200,6 +200,7 @@ binary build interface.`)
200200
if err := m.start(ctx); err != nil {
201201
return fmt.Errorf("failed to start Minio: %w", err)
202202
}
203+
defer m.kill()
203204

204205
if err := m.ensureBucketExists(ctx, "builds"); err != nil {
205206
return err
@@ -296,12 +297,12 @@ binary build interface.`)
296297
}
297298

298299
index := n + 1
299-
cpod, err := NewCosaPodder(ctx, apiBuild, ac, pn, index)
300+
cpod, err := NewCosaPodder(ctx, apiBuild, bc.KubeClient, bc.KubeProject, index)
300301
if err != nil {
301302
log.Errorf("FAILED TO CREATE POD DEFINITION: %v", err)
302303
continue
303304
}
304-
if err := cpod.WorkerRunner(eVars); err != nil {
305+
if err := cpod.WorkerRunner(ctx, eVars); err != nil {
305306
log.Errorf("FAILED stage: %v", err)
306307
}
307308
}

‎gangplank/ocp/bc_ci_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func init() {
1818
}
1919

2020
func TestNoEnv(t *testing.T) {
21-
if _, err := newBC(); err != ErrInvalidOCPMode {
21+
if _, err := newBC(); err != ErrNoOCPBuildSpec {
2222
t.Errorf("failed to raise error\n want: %v\n got: %v", ErrInvalidOCPMode, err)
2323
}
2424
}

‎gangplank/ocp/client.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package ocp
22

3-
import "context"
3+
import (
4+
"context"
5+
"os"
6+
7+
log "github.com/sirupsen/logrus"
8+
)
49

510
// Builder implements the Build
611
type Builder interface {
@@ -13,6 +18,13 @@ var (
1318
cosaSrvDir = defaultContextDir
1419
)
1520

21+
func init() {
22+
if _, ok := os.LookupEnv(localPodEnvVar); ok {
23+
log.Infof("EnvVar %s defined, using local pod mode", localPodEnvVar)
24+
forceNotInCluster = true
25+
}
26+
}
27+
1628
// NewBuilder returns a Builder. NewBuilder determines what
1729
// "Builder" to return.
1830
func NewBuilder(ctx context.Context) (Builder, error) {

0 commit comments

Comments
 (0)
Please sign in to comment.