parent
							
								
									83f8db126d
								
							
						
					
					
						commit
						970449f04f
					
				|  | @ -250,6 +250,8 @@ type Plugin struct { | ||||||
| 	Name string `json:"name"` | 	Name string `json:"name"` | ||||||
| 	// Version is the version of Jenkins plugin
 | 	// Version is the version of Jenkins plugin
 | ||||||
| 	Version string `json:"version"` | 	Version string `json:"version"` | ||||||
|  | 	// DownloadURL is the custom url from where plugin has to be downloaded.
 | ||||||
|  | 	DownloadURL string `json:"downloadURL,omitempty"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // JenkinsMaster defines the Jenkins master pod attributes and plugins,
 | // JenkinsMaster defines the Jenkins master pod attributes and plugins,
 | ||||||
|  |  | ||||||
|  | @ -268,7 +268,7 @@ chmod +x {{ .JenkinsHomePath }}/scripts/*.sh | ||||||
| echo "Installing plugins required by Operator - begin" | echo "Installing plugins required by Operator - begin" | ||||||
| cat > {{ .JenkinsHomePath }}/base-plugins << EOF | cat > {{ .JenkinsHomePath }}/base-plugins << EOF | ||||||
| {{ range $index, $plugin := .BasePlugins }} | {{ range $index, $plugin := .BasePlugins }} | ||||||
| {{ $plugin.Name }}:{{ $plugin.Version }} | {{ $plugin.Name }}:{{ $plugin.Version }}{{if $plugin.DownloadURL}}:{{ $plugin.DownloadURL }}{{end}} | ||||||
| {{ end }} | {{ end }} | ||||||
| EOF | EOF | ||||||
| 
 | 
 | ||||||
|  | @ -282,7 +282,7 @@ echo "Installing plugins required by Operator - end" | ||||||
| echo "Installing plugins required by user - begin" | echo "Installing plugins required by user - begin" | ||||||
| cat > {{ .JenkinsHomePath }}/user-plugins << EOF | cat > {{ .JenkinsHomePath }}/user-plugins << EOF | ||||||
| {{ range $index, $plugin := .UserPlugins }} | {{ range $index, $plugin := .UserPlugins }} | ||||||
| {{ $plugin.Name }}:{{ $plugin.Version }} | {{ $plugin.Name }}:{{ $plugin.Version }}{{if $plugin.DownloadURL}}:{{ $plugin.DownloadURL }}{{end}} | ||||||
| {{ end }} | {{ end }} | ||||||
| EOF | EOF | ||||||
| if [[ -z "${OPENSHIFT_JENKINS_IMAGE_VERSION}" ]]; then | if [[ -z "${OPENSHIFT_JENKINS_IMAGE_VERSION}" ]]; then | ||||||
|  |  | ||||||
|  | @ -320,7 +320,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validatePlugins(requiredBasePlugins | ||||||
| 	allPlugins := map[plugins.Plugin][]plugins.Plugin{} | 	allPlugins := map[plugins.Plugin][]plugins.Plugin{} | ||||||
| 
 | 
 | ||||||
| 	for _, jenkinsPlugin := range basePlugins { | 	for _, jenkinsPlugin := range basePlugins { | ||||||
| 		plugin, err := plugins.NewPlugin(jenkinsPlugin.Name, jenkinsPlugin.Version) | 		plugin, err := plugins.NewPlugin(jenkinsPlugin.Name, jenkinsPlugin.Version, jenkinsPlugin.DownloadURL) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			messages = append(messages, err.Error()) | 			messages = append(messages, err.Error()) | ||||||
| 		} | 		} | ||||||
|  | @ -331,7 +331,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validatePlugins(requiredBasePlugins | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for _, jenkinsPlugin := range userPlugins { | 	for _, jenkinsPlugin := range userPlugins { | ||||||
| 		plugin, err := plugins.NewPlugin(jenkinsPlugin.Name, jenkinsPlugin.Version) | 		plugin, err := plugins.NewPlugin(jenkinsPlugin.Name, jenkinsPlugin.Version, jenkinsPlugin.DownloadURL) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			messages = append(messages, err.Error()) | 			messages = append(messages, err.Error()) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ import ( | ||||||
| type Plugin struct { | type Plugin struct { | ||||||
| 	Name                     string `json:"name"` | 	Name                     string `json:"name"` | ||||||
| 	Version                  string `json:"version"` | 	Version                  string `json:"version"` | ||||||
|  | 	DownloadURL              string `json:"downloadURL"` | ||||||
| 	rootPluginNameAndVersion string | 	rootPluginNameAndVersion string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -24,6 +25,8 @@ var ( | ||||||
| 	NamePattern = regexp.MustCompile(`^[0-9a-zA-Z-_]+$`) | 	NamePattern = regexp.MustCompile(`^[0-9a-zA-Z-_]+$`) | ||||||
| 	// VersionPattern is the plugin version regex pattern
 | 	// VersionPattern is the plugin version regex pattern
 | ||||||
| 	VersionPattern = regexp.MustCompile(`^[0-9a-zA-Z+\\.-]+$`) | 	VersionPattern = regexp.MustCompile(`^[0-9a-zA-Z+\\.-]+$`) | ||||||
|  | 	// DownloadURLPattern is the plugin download url regex pattern
 | ||||||
|  | 	DownloadURLPattern = regexp.MustCompile(`https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)`) | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // New creates plugin from string, for example "name-of-plugin:0.0.1"
 | // New creates plugin from string, for example "name-of-plugin:0.0.1"
 | ||||||
|  | @ -35,7 +38,7 @@ func New(nameWithVersion string) (*Plugin, error) { | ||||||
| 	name := val[0] | 	name := val[0] | ||||||
| 	version := val[1] | 	version := val[1] | ||||||
| 
 | 
 | ||||||
| 	if err := validatePlugin(name, version); err != nil { | 	if err := validatePlugin(name, version, ""); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -46,24 +49,30 @@ func New(nameWithVersion string) (*Plugin, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NewPlugin creates plugin from name and version, for example "name-of-plugin:0.0.1"
 | // NewPlugin creates plugin from name and version, for example "name-of-plugin:0.0.1"
 | ||||||
| func NewPlugin(name, version string) (*Plugin, error) { | func NewPlugin(name, version, downloadURL string) (*Plugin, error) { | ||||||
| 	if err := validatePlugin(name, version); err != nil { | 	if err := validatePlugin(name, version, downloadURL); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return &Plugin{ | 	return &Plugin{ | ||||||
| 		Name:    name, | 		Name:        name, | ||||||
| 		Version: version, | 		Version:     version, | ||||||
|  | 		DownloadURL: downloadURL, | ||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func validatePlugin(name, version string) error { | func validatePlugin(name, version, downloadURL string) error { | ||||||
| 	if ok := NamePattern.MatchString(name); !ok { | 	if ok := NamePattern.MatchString(name); !ok { | ||||||
| 		return errors.Errorf("invalid plugin name '%s:%s', must follow pattern '%s'", name, version, NamePattern.String()) | 		return errors.Errorf("invalid plugin name '%s:%s', must follow pattern '%s'", name, version, NamePattern.String()) | ||||||
| 	} | 	} | ||||||
| 	if ok := VersionPattern.MatchString(version); !ok { | 	if ok := VersionPattern.MatchString(version); !ok { | ||||||
| 		return errors.Errorf("invalid plugin version '%s:%s', must follow pattern '%s'", name, version, VersionPattern.String()) | 		return errors.Errorf("invalid plugin version '%s:%s', must follow pattern '%s'", name, version, VersionPattern.String()) | ||||||
| 	} | 	} | ||||||
|  | 	if len(downloadURL) > 0 { | ||||||
|  | 		if ok := DownloadURLPattern.MatchString(downloadURL); !ok { | ||||||
|  | 			return errors.Errorf("invalid download URL '%s' for plugin name %s:%s, must follow pattern '%s'", downloadURL, name, version, DownloadURLPattern.String()) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,42 +12,54 @@ func TestValidatePlugin(t *testing.T) { | ||||||
| 	validPluginName := "valid" | 	validPluginName := "valid" | ||||||
| 	validPluginVersion := "0.1.2" | 	validPluginVersion := "0.1.2" | ||||||
| 	t.Run("version 1.6+build.162", func(t *testing.T) { | 	t.Run("version 1.6+build.162", func(t *testing.T) { | ||||||
| 		got := validatePlugin(validPluginName, "1.6+build.162") | 		got := validatePlugin(validPluginName, "1.6+build.162", "") | ||||||
| 		assert.NoError(t, got) | 		assert.NoError(t, got) | ||||||
| 	}) | 	}) | ||||||
| 	t.Run("version 1.8+build.201601050116", func(t *testing.T) { | 	t.Run("version 1.8+build.201601050116", func(t *testing.T) { | ||||||
| 		got := validatePlugin(validPluginName, "1.8+build.201601050116") | 		got := validatePlugin(validPluginName, "1.8+build.201601050116", "") | ||||||
| 		assert.NoError(t, got) | 		assert.NoError(t, got) | ||||||
| 	}) | 	}) | ||||||
| 	t.Run("version 1.8-RELEASE", func(t *testing.T) { | 	t.Run("version 1.8-RELEASE", func(t *testing.T) { | ||||||
| 		got := validatePlugin(validPluginName, "1.8-RELEASE") | 		got := validatePlugin(validPluginName, "1.8-RELEASE", "") | ||||||
| 		assert.NoError(t, got) | 		assert.NoError(t, got) | ||||||
| 	}) | 	}) | ||||||
| 	t.Run("version 20.810504d7462", func(t *testing.T) { | 	t.Run("version 20.810504d7462", func(t *testing.T) { | ||||||
| 		got := validatePlugin(validPluginName, "20.810504d7462") | 		got := validatePlugin(validPluginName, "20.810504d7462", "") | ||||||
| 		assert.NoError(t, got) | 		assert.NoError(t, got) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	t.Run("version 3.0-rc1", func(t *testing.T) { | 	t.Run("version 3.0-rc1", func(t *testing.T) { | ||||||
| 		got := validatePlugin(validPluginName, "3.0-rc1") | 		got := validatePlugin(validPluginName, "3.0-rc1", "") | ||||||
| 		assert.NoError(t, got) | 		assert.NoError(t, got) | ||||||
| 	}) | 	}) | ||||||
| 	t.Run("version 3.1.20180605-140134.c2e96c4", func(t *testing.T) { | 	t.Run("version 3.1.20180605-140134.c2e96c4", func(t *testing.T) { | ||||||
| 		got := validatePlugin(validPluginName, "3.1.20180605-140134.c2e96c4") | 		got := validatePlugin(validPluginName, "3.1.20180605-140134.c2e96c4", "") | ||||||
| 		assert.NoError(t, got) | 		assert.NoError(t, got) | ||||||
| 	}) | 	}) | ||||||
| 	t.Run("invalid version !", func(t *testing.T) { | 	t.Run("invalid version !", func(t *testing.T) { | ||||||
| 		got := validatePlugin(validPluginName, "0.5.1!") | 		got := validatePlugin(validPluginName, "0.5.1!", "") | ||||||
| 		assert.Error(t, got) | 		assert.Error(t, got) | ||||||
| 	}) | 	}) | ||||||
| 	t.Run("name 01234567890-abcdefghijklmnoprstuwxz_ABCDEFGHIJKLMNOPQRSTUVWXYZ", func(t *testing.T) { | 	t.Run("name 01234567890-abcdefghijklmnoprstuwxz_ABCDEFGHIJKLMNOPQRSTUVWXYZ", func(t *testing.T) { | ||||||
| 		got := validatePlugin("01234567890-abcdefghijklmnoprstuwxz_ABCDEFGHIJKLMNOPQRSTUVWXYZ", validPluginVersion) | 		got := validatePlugin("01234567890-abcdefghijklmnoprstuwxz_ABCDEFGHIJKLMNOPQRSTUVWXYZ", validPluginVersion, "") | ||||||
| 		assert.NoError(t, got) | 		assert.NoError(t, got) | ||||||
| 	}) | 	}) | ||||||
| 	t.Run("invalid name !", func(t *testing.T) { | 	t.Run("invalid name !", func(t *testing.T) { | ||||||
| 		got := validatePlugin("!", validPluginVersion) | 		got := validatePlugin("!", validPluginVersion, "") | ||||||
| 		assert.Error(t, got) | 		assert.Error(t, got) | ||||||
| 	}) | 	}) | ||||||
|  | 	t.Run("invalid download URL", func(t *testing.T) { | ||||||
|  | 		got := validatePlugin(validPluginName, validPluginVersion, "http://www.jenkins/plugin.hpi") | ||||||
|  | 		assert.Error(t, got) | ||||||
|  | 	}) | ||||||
|  | 	t.Run("valid http download URL", func(t *testing.T) { | ||||||
|  | 		got := validatePlugin(validPluginName, validPluginVersion, "http://www.jenkins.com/plugin.hpi") | ||||||
|  | 		assert.NoError(t, got) | ||||||
|  | 	}) | ||||||
|  | 	t.Run("valid https download URL", func(t *testing.T) { | ||||||
|  | 		got := validatePlugin(validPluginName, validPluginVersion, "https://www.jenkins.com/plugin.hpi") | ||||||
|  | 		assert.NoError(t, got) | ||||||
|  | 	}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestVerifyDependencies(t *testing.T) { | func TestVerifyDependencies(t *testing.T) { | ||||||
|  |  | ||||||
|  | @ -117,6 +117,7 @@ func createJenkinsCR(t *testing.T, name, namespace string, seedJob *[]v1alpha2.S | ||||||
| 					{Name: "audit-trail", Version: "2.4"}, | 					{Name: "audit-trail", Version: "2.4"}, | ||||||
| 					{Name: "simple-theme-plugin", Version: "0.5.1"}, | 					{Name: "simple-theme-plugin", Version: "0.5.1"}, | ||||||
| 					{Name: "github", Version: "1.29.4"}, | 					{Name: "github", Version: "1.29.4"}, | ||||||
|  | 					{Name: "devoptics", Version: "1.1863", DownloadURL: "https://jenkins-updates.cloudbees.com/download/plugins/devoptics/1.1863/devoptics.hpi"}, | ||||||
| 				}, | 				}, | ||||||
| 				NodeSelector: map[string]string{"kubernetes.io/os": "linux"}, | 				NodeSelector: map[string]string{"kubernetes.io/os": "linux"}, | ||||||
| 				Volumes: []corev1.Volume{ | 				Volumes: []corev1.Volume{ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue