diff --git a/pkg/jenkins/health.go b/pkg/jenkins/health.go index 7bb339232e..56b0207db4 100644 --- a/pkg/jenkins/health.go +++ b/pkg/jenkins/health.go @@ -2,6 +2,7 @@ package jenkins import ( "fmt" + "github.com/jenkins-x/jx/pkg/log" "net/http" "time" @@ -15,14 +16,19 @@ const ( ) // CheckHealth checks the health of Jenkins server using the login URL -func CheckHealth(url string) error { - healthEndpoin := JenkinsLoginURL(url) +func CheckHealth(url string, healthTimeout time.Duration) error { + endpoint := JenkinsLoginURL(url) + + if ping(endpoint) == nil { + return nil + } + log.Infof("waiting up to %s for the Jenkins server to be healty at URL %s\n", util.ColorInfo(healthTimeout.String()), util.ColorInfo(endpoint)) err := util.Retry(healthTimeout, func() error { - return ping(healthEndpoin) + return ping(endpoint) }) if err != nil { - return errors.Wrapf(err, "pinging Jenkins server %q", healthEndpoin) + return errors.Wrapf(err, "pinging Jenkins server %q", endpoint) } return nil } diff --git a/pkg/jx/cmd/create_env.go b/pkg/jx/cmd/create_env.go index e78ecc79e3..2f927b93bd 100644 --- a/pkg/jx/cmd/create_env.go +++ b/pkg/jx/cmd/create_env.go @@ -221,14 +221,14 @@ func (o *CreateEnvOptions) Run() error { return err } if o.Prow { - repo := fmt.Sprintf("%s/environment-%s-%s", gitInfo.Organisation, o.Prefix, env.Name) + repo := fmt.Sprintf("%s/%s", gitInfo.Organisation, gitInfo.Name) err = prow.AddEnvironment(kubeClient, []string{repo}, devEnv.Spec.Namespace, env.Spec.Namespace, &devEnv.Spec.TeamSettings) if err != nil { return fmt.Errorf("failed to add repo %s to Prow config in namespace %s: %v", repo, env.Spec.Namespace, err) } } - /* It is important this pull secret handling goes after any namespace creation code; the service account exists in the created namespace */ + /* It is important this pull secret handling goes after any namespace creation code; the service account exists in the created namespace */ if o.PullSecrets != "" { // We need the namespace to be created first - do the check if !o.GitOpsMode { diff --git a/pkg/jx/cmd/create_jenkins_token.go b/pkg/jx/cmd/create_jenkins_token.go index 1632a94a62..7d386e144c 100644 --- a/pkg/jx/cmd/create_jenkins_token.go +++ b/pkg/jx/cmd/create_jenkins_token.go @@ -63,6 +63,7 @@ type CreateJenkinsUserOptions struct { Timeout string NoREST bool RecreateToken bool + HealthTimeout time.Duration } // NewCmdCreateJenkinsUser creates a command @@ -95,6 +96,7 @@ func NewCmdCreateJenkinsUser(commonOpts *CommonOptions) *cobra.Command { cmd.Flags().BoolVarP(&options.NoREST, "no-rest", "", false, "Disables the use of REST calls to automatically find the API token if the user and password are known") cmd.Flags().BoolVarP(&options.RecreateToken, "recreate-token", "", false, "Should we recreate teh API token if it already exists") cmd.Flags().StringVarP(&options.Namespace, "namespace", "", "", "The namespace of the secret where the Jenkins API token will be stored") + cmd.Flags().DurationVarP(&options.HealthTimeout, "health-timeout", "", 30*time.Minute, "The maximum duration to wait for the Jenkins service to be healthy before trying to create the API token") return cmd } @@ -169,7 +171,7 @@ func (o *CreateJenkinsUserOptions) Run() error { } if userAuth.IsInvalid() && o.Password != "" && !o.NoREST { - err := jenkins.CheckHealth(server.URL) + err := jenkins.CheckHealth(server.URL, o.HealthTimeout) if err != nil { return errors.Wrapf(err, "checking health of Jenkins server %q", server.URL) } diff --git a/pkg/jx/cmd/get_build_logs.go b/pkg/jx/cmd/get_build_logs.go index 56d3d38236..462bfbf987 100644 --- a/pkg/jx/cmd/get_build_logs.go +++ b/pkg/jx/cmd/get_build_logs.go @@ -503,7 +503,7 @@ func (o *GetBuildLogsOptions) loadPipelines(kubeClient kubernetes.Interface, tek log.Warnf("Error creating PipelineRunInfo for PipelineRun %s: %s\n", pr.Name, err) return names, defaultName, buildMap, pipelineMap, err } - if pri != nil { + if pri != nil && o.BuildFilter.BuildMatches(pri.ToBuildPodInfo()) { buildInfos = append(buildInfos, pri) } } diff --git a/pkg/jx/cmd/install.go b/pkg/jx/cmd/install.go index df37567f50..c5f86cdaed 100644 --- a/pkg/jx/cmd/install.go +++ b/pkg/jx/cmd/install.go @@ -338,9 +338,9 @@ func (options *InstallOptions) addInstallFlags(cmd *cobra.Command, includesInit cmd.Flags().StringVarP(&flags.DockerRegistry, "docker-registry", "", "", "The Docker Registry host or host:port which is used when tagging and pushing images. If not specified it defaults to the internal registry unless there is a better provider default (e.g. ECR on AWS/EKS)") cmd.Flags().StringVarP(&flags.ExposeControllerPathMode, "exposecontroller-pathmode", "", "", "The ExposeController path mode for how services should be exposed as URLs. Defaults to using subnets. Use a value of `path` to use relative paths within the domain host such as when using AWS ELB host names") cmd.Flags().StringVarP(&flags.Version, "version", "", "", "The specific platform version to install") - cmd.Flags().BoolVarP(&flags.Prow, "prow", "", false, "Enable Prow") - cmd.Flags().BoolVarP(&flags.Tekton, "tekton", "", false, "Enables the Tekton pipeline engine (which used to be called knative build pipeline) along with Prow. Otherwise we default to use Knative Build if you enable Prow") - cmd.Flags().BoolVarP(&flags.GitOpsMode, "gitops", "", false, "Sets up the local file system for GitOps so that the current installation can be configured or upgraded at any time via GitOps") + cmd.Flags().BoolVarP(&flags.Prow, "prow", "", false, "Enable Prow to implement Serverless Jenkins and support ChatOps on Pull Requests") + cmd.Flags().BoolVarP(&flags.Tekton, "tekton", "", false, "Enables the Tekton pipeline engine (which used to be called knative build pipeline) along with Prow to provide Serverless Jenkins. Otherwise we default to use Knative Build if you enable Prow") + cmd.Flags().BoolVarP(&flags.GitOpsMode, "gitops", "", false, "Creates a git repository for the Dev environment to manage the installation, configuration, upgrade and addition of Apps in Jenkins X all via GitOps") cmd.Flags().BoolVarP(&flags.NoGitOpsEnvApply, "no-gitops-env-apply", "", false, "When using GitOps to create the source code for the development environment and installation, don't run 'jx step env apply' to perform the install") cmd.Flags().BoolVarP(&flags.NoGitOpsEnvRepo, "no-gitops-env-repo", "", false, "When using GitOps to create the source code for the development environment this flag disables the creation of a git repository for the source code") cmd.Flags().BoolVarP(&flags.NoGitOpsVault, "no-gitops-vault", "", false, "When using GitOps to create the source code for the development environment this flag disables the creation of a vault") diff --git a/pkg/jx/cmd/step_create_task.go b/pkg/jx/cmd/step_create_task.go index 050138f35e..1d0eb46423 100644 --- a/pkg/jx/cmd/step_create_task.go +++ b/pkg/jx/cmd/step_create_task.go @@ -362,7 +362,7 @@ func (o *StepCreateTaskOptions) GenerateTektonCRDs(packsDir string, projectConfi return nil, nil, nil, nil, nil, err } - if lifecycles.Pipeline != nil { + if lifecycles != nil && lifecycles.Pipeline != nil { // TODO: Seeing weird behavior seemingly related to https://golang.org/doc/faq#nil_error // if err is reused, maybe we need to switch return types (perhaps upstream in build-pipeline)? if validateErr := lifecycles.Pipeline.Validate(); validateErr != nil { diff --git a/pkg/tekton/pipeline_info.go b/pkg/tekton/pipeline_info.go index 3a51b69eb5..3abcdc9252 100644 --- a/pkg/tekton/pipeline_info.go +++ b/pkg/tekton/pipeline_info.go @@ -538,6 +538,34 @@ func (pri *PipelineRunInfo) Status() string { return string(pod.Status.Phase) } +// ToBuildPodInfo converts the object into a BuildPodInfo so it can be easily filtered +func (pri PipelineRunInfo) ToBuildPodInfo() *builds.BuildPodInfo { + answer := &builds.BuildPodInfo{ + Name: pri.Name, + Organisation: pri.Organisation, + Repository: pri.Repository, + Branch: pri.Branch, + Build: pri.Build, + BuildNumber: pri.BuildNumber, + Pipeline: pri.Pipeline, + LastCommitSHA: pri.LastCommitSHA, + LastCommitURL: pri.LastCommitURL, + LastCommitMessage: pri.LastCommitMessage, + GitInfo: pri.GitInfo, + } + pod := pri.FindFirstStagePod() + if pod != nil { + answer.Pod = pod + answer.PodName = pod.Name + containers := pod.Spec.Containers + if len(containers) > 0 { + answer.FirstStepImage = containers[0].Image + } + answer.CreatedTime = pod.CreationTimestamp.Time + } + return answer +} + // PipelineRunInfoOrder allows sorting of a slice of PipelineRunInfos type PipelineRunInfoOrder []*PipelineRunInfo