diff --git a/Chart.yaml b/Chart.yaml new file mode 100644 index 0000000000..df9ae415fc --- /dev/null +++ b/Chart.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +name: jx +description: Jenkins X next gen cloud CI / CD platform for Kubernetes +home: https://jenkins-x.io/ +version: 0.0.1-SNAPSHOT +appVersion: 0.1 +icon: https://jenkins-x.github.io/jenkins-x-website/img/profile.png +sources: +- https://github.com/jenkins-x/jx +maintainers: +- name: Jenkins X Team + email: jenkins-x@googlegroups.com \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index bd3f9c911f..e95f048ca3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,5 @@ -FROM scratch +FROM centos:7 -ENTRYPOINT ["/jx", "version"] - -COPY build/jx-linux-amd64 /jx +ENTRYPOINT ["jx", "version"] +COPY build/jx-linux-amd64 /usr/bin/jx \ No newline at end of file diff --git a/Makefile b/Makefile index 0c32a661a9..d1b267c097 100644 --- a/Makefile +++ b/Makefile @@ -119,8 +119,9 @@ clean: linux: CGO_ENABLED=$(CGO_ENABLED) GOOS=linux GOARCH=amd64 $(GO) build $(BUILDFLAGS) -o build/$(NAME)-linux-amd64 cmd/jx/jx.go -docker: linux Dockerfile.buildgo - docker build --no-cache -t rawlingsj/jx:dev -f Dockerfile . +docker: linux + docker build --no-cache -t jenkinsxio/jx:dev . + docker push jenkinsxio/jx:dev docker-go: linux Dockerfile.buildgo docker build --no-cache -t builder-go -f Dockerfile.buildgo . diff --git a/charts/jx/values.yaml b/charts/jx/values.yaml index b6d4297165..f2cbe8cc1c 100644 --- a/charts/jx/values.yaml +++ b/charts/jx/values.yaml @@ -1,6 +1,6 @@ image: - repository: rawlingsj/jx - tag: dev10 + repository: jenkinsxio/jx + tag: dev pullPolicy: IfNotPresent replicaCount: 1 @@ -21,13 +21,13 @@ cronjob: successfulJobsHistoryLimit: 3 concurrencyPolicy: Forbid -activeDeadlineSeconds: 100 +activeDeadlineSeconds: 300 backoffLimit: 5 # default is Always but for Jobs use Never or OnFailure restartPolicy: Never -command: ["/jx"] +command: ["jx"] args: - "gc" - "activities" diff --git a/pkg/jx/cmd/common.go b/pkg/jx/cmd/common.go index 6013db5df9..da8ff5c041 100644 --- a/pkg/jx/cmd/common.go +++ b/pkg/jx/cmd/common.go @@ -157,22 +157,21 @@ func (o *CommonOptions) JenkinsClient() (*gojenkins.Jenkins, error) { return o.jenkinsClient, nil } -func (o *CommonOptions) inclusterSetup() error { - // TODO find a better way to figure out of we are incluster +func (o *CommonOptions) inclusterJenkinsAuthSetup() error { c, ns, err := o.KubeClient() if err != nil { return err } s, err := c.CoreV1().Secrets(ns).Get(kube.SecretJenkins, v1.GetOptions{}) if err != nil { - // not running incluster so fallback to getting auth file from local machine - return nil + return err } apiToken := s.Data[kube.JenkinsAdminApiToken] j := CreateJenkinsUserOptions{ CreateOptions: CreateOptions{ CommonOptions: *o, }, + Username: "admin", ApiToken: string(apiToken), } diff --git a/pkg/jx/cmd/delete_env.go b/pkg/jx/cmd/delete_env.go index 8b76cb6d09..27123619e5 100644 --- a/pkg/jx/cmd/delete_env.go +++ b/pkg/jx/cmd/delete_env.go @@ -77,12 +77,10 @@ func (o *DeleteEnvOptions) Run() error { return err } kube.RegisterEnvironmentCRD(apisClient) - ns, currentEnv, err := kube.GetDevNamespace(kubeClient, currentNs) if err != nil { return err } - envMap, envNames, err := kube.GetEnvironments(jxClient, ns) if err != nil { return err diff --git a/pkg/jx/cmd/gc_previews.go b/pkg/jx/cmd/gc_previews.go index 190877371c..a91c495915 100644 --- a/pkg/jx/cmd/gc_previews.go +++ b/pkg/jx/cmd/gc_previews.go @@ -93,17 +93,16 @@ func (o *GCPreviewsOptions) Run() error { if err != nil { return err } + // we need pull request info to include authConfigSvc, err := o.Factory.CreateGitAuthConfigService() if err != nil { return err } - gitKind, err := o.GitServerKind(gitInfo) if err != nil { return err } - gitProvider, err := gitInfo.CreateProvider(authConfigSvc, gitKind) if err != nil { return err @@ -112,8 +111,10 @@ func (o *GCPreviewsOptions) Run() error { if err != nil { log.Warn("Unable to convert PR " + e.Spec.PreviewGitSpec.Name + " to a number" + "\n") } - - pullRequest, _ := gitProvider.GetPullRequest(gitInfo.Organisation, gitInfo.Name, prNum) + pullRequest, err := gitProvider.GetPullRequest(gitInfo.Organisation, gitInfo.Name, prNum) + if err != nil { + return err + } lowerState := strings.ToLower(*pullRequest.State) if strings.HasPrefix(lowerState, "clos") { @@ -122,6 +123,7 @@ func (o *GCPreviewsOptions) Run() error { DeleteNamespace: true, CommonOptions: o.CommonOptions, } + log.Info("6\n") deleteOpts.CommonOptions.Args = []string{e.Name} err = deleteOpts.Run() if err != nil { diff --git a/pkg/jx/cmd/util/factory.go b/pkg/jx/cmd/util/factory.go index 943953284b..d46b301d23 100644 --- a/pkg/jx/cmd/util/factory.go +++ b/pkg/jx/cmd/util/factory.go @@ -28,6 +28,8 @@ import ( "github.com/jenkins-x/jx/pkg/gits" _ "k8s.io/client-go/plugin/pkg/client/auth" + "net/url" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -76,6 +78,8 @@ type Factory interface { LoadPipelineSecrets(kind string, serviceKind string) (*corev1.SecretList, error) ImpersonateUser(user string) Factory + + IsInCluster() bool } type factory struct { @@ -104,7 +108,6 @@ func (f *factory) ImpersonateUser(user string) Factory { // CreateJenkinsClient creates a new jenkins client func (f *factory) CreateJenkinsClient() (*gojenkins.Jenkins, error) { - svc, err := f.CreateJenkinsAuthConfigService() if err != nil { return nil, err @@ -148,10 +151,49 @@ func (f *factory) CreateJenkinsAuthConfigService() (auth.AuthConfigService, erro if err != nil { return authConfigSvc, err } - _, err = authConfigSvc.LoadConfig() + config, err := authConfigSvc.LoadConfig() if err != nil { return authConfigSvc, err } + + if len(config.Servers) == 0 { + c, ns, err := f.CreateClient() + if err != nil { + return authConfigSvc, err + } + + s, err := c.CoreV1().Secrets(ns).Get(kube.SecretJenkins, metav1.GetOptions{}) + if err != nil { + return authConfigSvc, err + } + + userAuth := auth.UserAuth{ + Username: "admin", + ApiToken: string(s.Data[kube.JenkinsAdminApiToken]), + } + svc, err := c.CoreV1().Services(ns).Get(kube.ServiceJenkins, metav1.GetOptions{}) + if err != nil { + return authConfigSvc, err + } + svcURL := kube.GetServiceURL(svc) + if svcURL == "" { + return authConfigSvc, fmt.Errorf("unable to find external URL annotation on service %s", svc.Name) + } + + u, err := url.Parse(svcURL) + if err != nil { + return authConfigSvc, err + } + if !userAuth.IsInvalid() { + config.Servers = []*auth.AuthServer{ + { + Name: u.Host, + URL: svcURL, + Users: []*auth.UserAuth{&userAuth}, + }, + } + } + } return authConfigSvc, err } @@ -255,7 +297,7 @@ func (f *factory) authMergePipelineSecrets(config *auth.AuthConfig, secrets *cor func (f *factory) CreateGitAuthConfigServiceDryRun(dryRun bool) (auth.AuthConfigService, error) { if dryRun { fileName := GitAuthConfigFile - return f.createGitAuthConfigServiceFromSecrets(fileName, nil, false) + return f.createGitAuthConfigServiceFromSecrets(fileName, nil, f.IsInCluster()) } return f.CreateGitAuthConfigService() } @@ -278,10 +320,10 @@ func (f *factory) CreateGitAuthConfigService() (auth.AuthConfigService, error) { } fileName := GitAuthConfigFile - return f.createGitAuthConfigServiceFromSecrets(fileName, secrets, f.isInCDPIpeline()) + return f.createGitAuthConfigServiceFromSecrets(fileName, secrets, f.IsInCluster()) } -func (f *factory) createGitAuthConfigServiceFromSecrets(fileName string, secrets *corev1.SecretList, isCDPipeline bool) (auth.AuthConfigService, error) { +func (f *factory) createGitAuthConfigServiceFromSecrets(fileName string, secrets *corev1.SecretList, isIncluster bool) (auth.AuthConfigService, error) { authConfigSvc, err := f.CreateAuthConfigService(fileName) if err != nil { return authConfigSvc, err @@ -293,26 +335,43 @@ func (f *factory) createGitAuthConfigServiceFromSecrets(fileName string, secrets } if secrets != nil { - f.authMergePipelineSecrets(config, secrets, kube.ValueKindGit, isCDPipeline) + f.authMergePipelineSecrets(config, secrets, kube.ValueKindGit, isIncluster) } // lets add a default if there's none defined yet if len(config.Servers) == 0 { // if in cluster then there's no user configfile, so check for env vars first - userAuth := auth.CreateAuthUserFromEnvironment("GIT") - if !userAuth.IsInvalid() { - // if no config file is being used lets grab the git server from the current directory - server, err := gits.GetGitServer("") - if err != nil { - fmt.Printf("WARNING: unable to get remote git repo server, %v\n", err) - server = "https://github.com" - } - config.Servers = []*auth.AuthServer{ - { - Name: "Git", - URL: server, - Users: []*auth.UserAuth{&userAuth}, - }, + secretList, err := f.LoadPipelineSecrets(kube.ValueKindGit, "") + if err != nil { + return authConfigSvc, err + } + + var data map[string][]byte + + if secretList != nil { + for _, secret := range secretList.Items { + labels := secret.Labels + annotations := secret.Annotations + data = secret.Data + if labels != nil && labels[kube.LabelKind] == kube.ValueKindGit && annotations != nil { + u := annotations[kube.AnnotationURL] + if u != "" && data != nil { + userAuth := auth.UserAuth{ + Username: string(data[kube.SecretDataUsername]), + ApiToken: string(data[kube.SecretDataPassword]), + } + if !userAuth.IsInvalid() { + config.Servers = []*auth.AuthServer{ + { + Name: string(data[kube.AnnotationName]), + URL: u, + Users: []*auth.UserAuth{&userAuth}, + }, + } + break + } + } + } } } } @@ -494,3 +553,12 @@ func (f *factory) isInCDPIpeline() bool { // or we should test if we are in the cluster and get the current ServiceAccount name? return os.Getenv("BUILD_NUMBER") != "" } + +// function to tell if we are running incluster +func (f *factory) IsInCluster() bool { + _, err := rest.InClusterConfig() + if err != nil { + return false + } + return true +} diff --git a/templates/.syncthing.cronjob.yaml.tmp b/templates/.syncthing.cronjob.yaml.tmp new file mode 100644 index 0000000000..99dd12ddca Binary files /dev/null and b/templates/.syncthing.cronjob.yaml.tmp differ diff --git a/templates/.syncthing.daemonset.yaml.tmp b/templates/.syncthing.daemonset.yaml.tmp new file mode 100644 index 0000000000..1c9efe3d91 Binary files /dev/null and b/templates/.syncthing.daemonset.yaml.tmp differ diff --git a/templates/.syncthing.deployment.yaml.tmp b/templates/.syncthing.deployment.yaml.tmp new file mode 100644 index 0000000000..2da35e6088 Binary files /dev/null and b/templates/.syncthing.deployment.yaml.tmp differ diff --git a/templates/.syncthing.job.yaml.tmp b/templates/.syncthing.job.yaml.tmp new file mode 100644 index 0000000000..2304f07ad2 Binary files /dev/null and b/templates/.syncthing.job.yaml.tmp differ diff --git a/templates/NOTES.txt b/templates/NOTES.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/templates/NOTES.txt @@ -0,0 +1 @@ + diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl new file mode 100644 index 0000000000..448e4b1d43 --- /dev/null +++ b/templates/_helpers.tpl @@ -0,0 +1,32 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "jx.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "jx.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "jx.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/templates/service.yaml b/templates/service.yaml new file mode 100644 index 0000000000..b884b706a3 --- /dev/null +++ b/templates/service.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "jx.name" . }} + labels: + app: {{ template "jx.name" . }} + chart: {{ template "jx.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.service.serviceAnnotations }} + annotations: +{{ toYaml .Values.service.serviceAnnotations | indent 4 }} +{{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + app: {{ template "jx.name" . }} + release: {{ .Release.Name }}