diff --git a/chart/chart.go b/chart/chart.go index 2bed1f6c5..716bd4630 100644 --- a/chart/chart.go +++ b/chart/chart.go @@ -30,6 +30,7 @@ import ( "github.com/kubernetes/deployment-manager/log" ) +// ChartfileName is the default Chart file name. const ChartfileName string = "Chart.yaml" const ( @@ -73,7 +74,7 @@ func (c *Chart) Chartfile() *Chartfile { return c.loader.chartfile() } -// Dir() returns the directory where the charts are located. +// Dir returns the directory where the charts are located. func (c *Chart) Dir() string { return c.loader.dir() } @@ -148,7 +149,7 @@ func (t *tarChart) close() error { return os.RemoveAll(t.tmpDir) } -// New creates a new chart in a directory. +// Create creates a new chart in a directory. // // Inside of dir, this will create a directory based on the name of // chartfile.Name. It will then write the Chart.yaml into this directory and diff --git a/chart/chartfile.go b/chart/chartfile.go index a7fbd0985..b694a3734 100644 --- a/chart/chartfile.go +++ b/chart/chartfile.go @@ -49,7 +49,7 @@ type Dependency struct { Location string `yaml:"location"` } -// Specify environmental constraints. +// EnvConstraint specifies environmental constraints. type EnvConstraint struct { Name string `yaml:"name"` Version string `yaml:"version"` diff --git a/chart/doc.go b/chart/doc.go index bc0ba2ca2..ec0627506 100644 --- a/chart/doc.go +++ b/chart/doc.go @@ -14,7 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -/* Package chart implements the Chart format. +/* +Package chart implements the Chart format. This package provides tools for working with the Chart format, including the Chartfile (chart.yaml) and compressed chart archives. diff --git a/chart/locator.go b/chart/locator.go index 7619ec31e..509876247 100644 --- a/chart/locator.go +++ b/chart/locator.go @@ -30,6 +30,7 @@ var ErrLocal = errors.New("cannot use local Locator as remote") // ErrRemote indicates that a remote URL was used as a local URL. var ErrRemote = errors.New("cannot use remote Locator as local") +// Constants defining recognized URL schemes. const ( SchemeHTTP = "http" SchemeHTTPS = "https" @@ -50,6 +51,7 @@ func init() { tnregexp = regexp.MustCompile("^" + TarNameRegex + "$") } +// Locator describes the location of a Chart. type Locator struct { // The scheme of the URL. Typically one of http, https, helm, or file. Scheme string @@ -70,6 +72,7 @@ type Locator struct { original string } +// Parse parses a URL into a Locator. func Parse(path string) (*Locator, error) { u, err := url.Parse(path) if err != nil { diff --git a/common/types.go b/common/types.go index 90f1a43a0..e09327c13 100644 --- a/common/types.go +++ b/common/types.go @@ -162,7 +162,7 @@ type TypeInstance struct { // KubernetesObject represents a native 'bare' Kubernetes object. type KubernetesObject struct { Kind string `json:"kind"` - ApiVersion string `json:"apiVersion"` + APIVersion string `json:"apiVersion"` Metadata map[string]interface{} `json:"metadata"` Spec map[string]interface{} `json:"spec"` } @@ -170,21 +170,26 @@ type KubernetesObject struct { // KubernetesSecret represents a Kubernetes secret type KubernetesSecret struct { Kind string `json:"kind"` - ApiVersion string `json:"apiVersion"` + APIVersion string `json:"apiVersion"` Metadata map[string]string `json:"metadata"` Data map[string]string `json:"data,omitempty"` } // Repository related types + +// BasicAuthCredential holds a username and password. type BasicAuthCredential struct { Username string `json:"username"` Password string `json:"password"` } +// APITokenCredential defines an API token. type APITokenCredential string + +// JWTTokenCredential defines a JWT token. type JWTTokenCredential string -// Credential used to access the repository +// RegistryCredential holds a credential used to access a registry. type RegistryCredential struct { APIToken APITokenCredential `json:"apitoken,omitempty"` BasicAuth BasicAuthCredential `json:"basicauth,omitempty"` @@ -204,6 +209,7 @@ type Registry struct { // RegistryType defines the technology that implements the registry type RegistryType string +// Constants that identify the supported registry layouts. const ( GithubRegistryType RegistryType = "github" GCSRegistryType RegistryType = "gcs" @@ -215,15 +221,17 @@ type RegistryFormat string const ( // Versioning. - // If a registry if versioned, then types appear under versions. + + // VersionedRegistry identifies a versioned registry, where types appear under versions. VersionedRegistry RegistryFormat = "versioned" - // If a registry is unversioned, then types appear under their names. + // UnversionedRegistry identifies an unversioned registry, where types appear under their names. UnversionedRegistry RegistryFormat = "unversioned" // Organization. - // In a collection registry, types are grouped into collections. + + // CollectionRegistry identfies a collection registry, where types are grouped into collections. CollectionRegistry RegistryFormat = "collection" - // In a one level registry, all types appear at the top level. + // OneLevelRegistry identifies a one level registry, where all types appear at the top level. OneLevelRegistry RegistryFormat = "onelevel" ) diff --git a/dm/dm.go b/dm/dm.go index ad98c9fcc..6f69fac4f 100644 --- a/dm/dm.go +++ b/dm/dm.go @@ -39,20 +39,20 @@ import ( ) var ( - deployment_name = flag.String("name", "", "Name of deployment, used for deploy and update commands (defaults to template name)") - stdin = flag.Bool("stdin", false, "Reads a configuration from the standard input") - properties = flag.String("properties", "", "Properties to use when deploying a template (e.g., --properties k1=v1,k2=v2)") + deploymentName = flag.String("name", "", "Name of deployment, used for deploy and update commands (defaults to template name)") + stdin = flag.Bool("stdin", false, "Reads a configuration from the standard input") + properties = flag.String("properties", "", "Properties to use when deploying a template (e.g., --properties k1=v1,k2=v2)") // TODO(vaikas): CHange the default name once we figure out where the charts live. - template_registry = flag.String("registry", "application-dm-templates", "Registry name") - service = flag.String("service", "http://localhost:8001/api/v1/proxy/namespaces/dm/services/manager-service:manager", "URL for deployment manager") - binary = flag.String("binary", "../expandybird/expansion/expansion.py", "Path to template expansion binary") - timeout = flag.Int("timeout", 20, "Time in seconds to wait for response") - regex_string = flag.String("regex", "", "Regular expression to filter the templates listed in a template registry") - username = flag.String("username", "", "Github user name that overrides GITHUB_USERNAME environment variable") - password = flag.String("password", "", "Github password that overrides GITHUB_PASSWORD environment variable") - apitoken = flag.String("apitoken", "", "Github api token that overrides GITHUB_API_TOKEN environment variable") - serviceaccount = flag.String("serviceaccount", "", "Service account file containing JWT token") - registryfile = flag.String("registryfile", "", "File containing registry specification") + templateRegistry = flag.String("registry", "application-dm-templates", "Registry name") + service = flag.String("service", "http://localhost:8001/api/v1/proxy/namespaces/dm/services/manager-service:manager", "URL for deployment manager") + binary = flag.String("binary", "../expandybird/expansion/expansion.py", "Path to template expansion binary") + timeout = flag.Int("timeout", 20, "Time in seconds to wait for response") + regexString = flag.String("regex", "", "Regular expression to filter the templates listed in a template registry") + username = flag.String("username", "", "Github user name that overrides GITHUB_USERNAME environment variable") + password = flag.String("password", "", "Github password that overrides GITHUB_PASSWORD environment variable") + apitoken = flag.String("apitoken", "", "Github api token that overrides GITHUB_API_TOKEN environment variable") + serviceaccount = flag.String("serviceaccount", "", "Service account file containing JWT token") + registryfile = flag.String("registryfile", "", "File containing registry specification") ) var commands = []string{ @@ -165,7 +165,7 @@ func execute() { switch args[0] { case "templates": - path := fmt.Sprintf("registries/%s/types", *template_registry) + path := fmt.Sprintf("registries/%s/types", *templateRegistry) callService(path, "GET", "list templates", nil) case "describe": describeType(args) @@ -198,7 +198,7 @@ func execute() { if err != nil { panic(fmt.Errorf("Failed to create a registry from arguments: %#v", err)) } - path := fmt.Sprintf("registries/%s", *template_registry) + path := fmt.Sprintf("registries/%s", *templateRegistry) callService(path, "POST", "create registry", ioutil.NopCloser(bytes.NewReader(reg))) case "get": if len(args) < 2 { @@ -253,16 +253,16 @@ func execute() { } tUrls := getDownloadURLs(args[1]) - var tUrl = "" + var tURL = "" if len(tUrls) == 0 { // Type is most likely a primitive. - tUrl = args[1] + tURL = args[1] } else { // TODO(vaikas): Support packages properly. - tUrl = tUrls[0] + tURL = tUrls[0] } - path := fmt.Sprintf("types/%s/instances", url.QueryEscape(tUrl)) - action := fmt.Sprintf("list deployed instances of type %s", tUrl) + path := fmt.Sprintf("types/%s/instances", url.QueryEscape(tURL)) + action := fmt.Sprintf("list deployed instances of type %s", tURL) callService(path, "GET", action, nil) case "registries": callService("registries", "GET", "list registries", nil) @@ -276,7 +276,7 @@ func execute() { func callService(path, method, action string, reader io.ReadCloser) { u := fmt.Sprintf("%s/%s", *service, path) - resp := callHttp(u, method, action, reader) + resp := callHTTP(u, method, action, reader) var j interface{} if err := json.Unmarshal([]byte(resp), &j); err != nil { panic(fmt.Errorf("Failed to parse JSON response from service: %s", resp)) @@ -290,7 +290,7 @@ func callService(path, method, action string, reader io.ReadCloser) { fmt.Println(string(y)) } -func callHttp(path, method, action string, reader io.ReadCloser) string { +func callHTTP(path, method, action string, reader io.ReadCloser) string { request, err := http.NewRequest(method, path, reader) request.Header.Add("Content-Type", "application/json") @@ -334,19 +334,19 @@ func describeType(args []string) { if !strings.Contains(tUrls[0], ".prov") { // It's not a chart, so grab the schema - path := fmt.Sprintf("registries/%s/download?file=%s.schema", *template_registry, url.QueryEscape(tUrls[0])) + path := fmt.Sprintf("registries/%s/download?file=%s.schema", *templateRegistry, url.QueryEscape(tUrls[0])) callService(path, "GET", "get schema for type ("+tUrls[0]+")", nil) } else { // It's a chart, so grab the provenance file - path := fmt.Sprintf("registries/%s/download?file=%s", *template_registry, url.QueryEscape(tUrls[0])) + path := fmt.Sprintf("registries/%s/download?file=%s", *templateRegistry, url.QueryEscape(tUrls[0])) callService(path, "GET", "get file", nil) } } // getDownloadURLs returns URLs for a type in the given registry func getDownloadURLs(tName string) []string { - path := fmt.Sprintf("%s/registries/%s/types/%s", *service, *template_registry, url.QueryEscape(tName)) - resp := callHttp(path, "GET", "get download urls", nil) + path := fmt.Sprintf("%s/registries/%s/types/%s", *service, *templateRegistry, url.QueryEscape(tName)) + resp := callHTTP(path, "GET", "get download urls", nil) u := []string{} if err := json.Unmarshal([]byte(resp), &u); err != nil { panic(fmt.Errorf("Failed to parse JSON response from service: %s", resp)) @@ -404,8 +404,8 @@ func loadTemplate(args []string) *common.Template { } // Override name if set from flags. - if *deployment_name != "" { - template.Name = *deployment_name + if *deploymentName != "" { + template.Name = *deploymentName } return template diff --git a/log/log.go b/log/log.go index 8d74d4878..c2f4ff5f7 100644 --- a/log/log.go +++ b/log/log.go @@ -1,4 +1,5 @@ -/* Package log provides simple convenience wrappers for logging. +/* +Package log provides simple convenience wrappers for logging. Following convention, this provides functions for logging warnings, errors, information and debugging. @@ -10,21 +11,21 @@ import ( "os" ) -// LogReceiver can receive log messages from this package. -type LogReceiver interface { +// Receiver can receive log messages from this package. +type Receiver interface { Printf(format string, v ...interface{}) } // Logger is the destination for this package. // // The logger that this prints to. -var Logger LogReceiver = log.New(os.Stderr, "", log.LstdFlags) +var Logger Receiver = log.New(os.Stderr, "", log.LstdFlags) // IsDebugging controls debugging output. // // If this is true, debugging messages will be printed. Expensive debugging // operations can be wrapped in `if log.IsDebugging {}`. -var IsDebugging bool = false +var IsDebugging = false // Err prints an error of severity ERROR to the log. func Err(msg string, v ...interface{}) { diff --git a/manager/deployments.go b/manager/deployments.go index a6c26c72c..74ec7038d 100644 --- a/manager/deployments.go +++ b/manager/deployments.go @@ -18,7 +18,6 @@ package main import ( "encoding/json" - "errors" "flag" "fmt" "io" @@ -237,7 +236,7 @@ func getPathVariable(w http.ResponseWriter, r *http.Request, variable, handler s vars := mux.Vars(r) escaped, ok := vars[variable] if !ok { - e := errors.New(fmt.Sprintf("%s name not found in URL", variable)) + e := fmt.Errorf("%s name not found in URL", variable) util.LogAndReturnError(handler, http.StatusBadRequest, e, w) return "", e } @@ -254,7 +253,7 @@ func getPathVariable(w http.ResponseWriter, r *http.Request, variable, handler s func getTemplate(w http.ResponseWriter, r *http.Request, handler string) *common.Template { util.LogHandlerEntry(handler, r) - j, err := getJsonFromRequest(w, r, handler) + j, err := getJSONFromRequest(w, r, handler) if err != nil { return nil @@ -382,7 +381,7 @@ func getRegistryHandlerFunc(w http.ResponseWriter, r *http.Request) { func getRegistry(w http.ResponseWriter, r *http.Request, handler string) *common.Registry { util.LogHandlerEntry(handler, r) - j, err := getJsonFromRequest(w, r, handler) + j, err := getJSONFromRequest(w, r, handler) if err != nil { return nil } @@ -506,7 +505,7 @@ func getFileHandlerFunc(w http.ResponseWriter, r *http.Request) { func getCredential(w http.ResponseWriter, r *http.Request, handler string) *common.RegistryCredential { util.LogHandlerEntry(handler, r) - j, err := getJsonFromRequest(w, r, handler) + j, err := getJSONFromRequest(w, r, handler) if err != nil { return nil } @@ -559,7 +558,7 @@ func getCredentialHandlerFunc(w http.ResponseWriter, r *http.Request) { util.LogHandlerExitWithJSON(handler, w, c, http.StatusOK) } -func getJsonFromRequest(w http.ResponseWriter, r *http.Request, handler string) ([]byte, error) { +func getJSONFromRequest(w http.ResponseWriter, r *http.Request, handler string) ([]byte, error) { util.LogHandlerEntry(handler, r) b := io.LimitReader(r.Body, *maxLength*1024) y, err := ioutil.ReadAll(b) diff --git a/manager/manager/manager_test.go b/manager/manager/manager_test.go index 305f38114..0a5066b80 100644 --- a/manager/manager/manager_test.go +++ b/manager/manager/manager_test.go @@ -230,23 +230,23 @@ func (repository *repositoryStub) GetManifest(d string, m string) (*common.Manif return nil, errTest } -func (tgr *repositoryStub) ListTypes() []string { - tgr.ListTypesCalled = true +func (repository *repositoryStub) ListTypes() []string { + repository.ListTypesCalled = true return []string{} } -func (tgr *repositoryStub) GetTypeInstances(t string) []*common.TypeInstance { - tgr.GetTypeInstancesCalled = true +func (repository *repositoryStub) GetTypeInstances(t string) []*common.TypeInstance { + repository.GetTypeInstancesCalled = true return []*common.TypeInstance{} } -func (tgr *repositoryStub) ClearTypeInstances(d string) { - tgr.TypeInstancesCleared = true +func (repository *repositoryStub) ClearTypeInstances(d string) { + repository.TypeInstancesCleared = true } -func (tgr *repositoryStub) SetTypeInstances(d string, is map[string][]*common.TypeInstance) { - for k, _ := range is { - tgr.TypeInstances[d] = append(tgr.TypeInstances[d], k) +func (repository *repositoryStub) SetTypeInstances(d string, is map[string][]*common.TypeInstance) { + for k := range is { + repository.TypeInstances[d] = append(repository.TypeInstances[d], k) } } diff --git a/manager/manager/typeresolver.go b/manager/manager/typeresolver.go index afc2eb9fe..52221b3c5 100644 --- a/manager/manager/typeresolver.go +++ b/manager/manager/typeresolver.go @@ -223,23 +223,23 @@ func (tr *typeResolver) ResolveTypes(config *common.Configuration, imports []*co func parseContent(templates []string) (string, error) { if len(templates) == 1 { return templates[0], nil - } else { - // If there are multiple URLs that need to be fetched, that implies it's a package - // of raw Kubernetes objects. We need to fetch them all as a unit and create a - // template representing a package out of that below. - fakeConfig := &common.Configuration{} - for _, template := range templates { - o, err := util.ParseKubernetesObject([]byte(template)) - if err != nil { - return "", fmt.Errorf("not a kubernetes object: %+v", template) - } - // Looks like a native Kubernetes object, create a configuration out of it - fakeConfig.Resources = append(fakeConfig.Resources, o) - } - marshalled, err := yaml.Marshal(fakeConfig) + } + + // If there are multiple URLs that need to be fetched, that implies it's a package + // of raw Kubernetes objects. We need to fetch them all as a unit and create a + // template representing a package out of that below. + fakeConfig := &common.Configuration{} + for _, template := range templates { + o, err := util.ParseKubernetesObject([]byte(template)) if err != nil { - return "", fmt.Errorf("Failed to marshal: %+v", fakeConfig) + return "", fmt.Errorf("not a kubernetes object: %+v", template) } - return string(marshalled), nil + // Looks like a native Kubernetes object, create a configuration out of it + fakeConfig.Resources = append(fakeConfig.Resources, o) + } + marshalled, err := yaml.Marshal(fakeConfig) + if err != nil { + return "", fmt.Errorf("Failed to marshal: %+v", fakeConfig) } + return string(marshalled), nil } diff --git a/manager/manager/typeresolver_test.go b/manager/manager/typeresolver_test.go index a3bdd6c75..0e175a8f7 100644 --- a/manager/manager/typeresolver_test.go +++ b/manager/manager/typeresolver_test.go @@ -304,18 +304,18 @@ func TestShortGithubUrl(t *testing.T) { "https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py.schema": registry.DownloadResponse{Err: nil, Code: http.StatusNotFound, Body: ""}, } - githubUrlMaps := map[registry.Type]registry.TestURLAndError{ + githubURLMaps := map[registry.Type]registry.TestURLAndError{ registry.NewTypeOrDie("common", "replicatedservice", "v1"): registry.TestURLAndError{URL: "https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py", Err: nil}, registry.NewTypeOrDie("common", "replicatedservice", "v2"): registry.TestURLAndError{URL: "https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py", Err: nil}, } - gcsUrlMaps := map[registry.Type]registry.TestURLAndError{ + gcsURLMaps := map[registry.Type]registry.TestURLAndError{ registry.NewTypeOrDie("common", "replicatedservice", "v1"): registry.TestURLAndError{URL: "https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py", Err: nil}, registry.NewTypeOrDie("common", "replicatedservice", "v2"): registry.TestURLAndError{URL: "https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v2/replicatedservice.py", Err: nil}, } - grp := registry.NewTestGithubRegistryProviderWithDownloads("github.com/kubernetes/application-dm-templates", githubUrlMaps, downloadResponses) - gcsrp := registry.NewTestGCSRegistryProvider("gs://charts", gcsUrlMaps) + grp := registry.NewTestGithubRegistryProviderWithDownloads("github.com/kubernetes/application-dm-templates", githubURLMaps, downloadResponses) + gcsrp := registry.NewTestGCSRegistryProvider("gs://charts", gcsURLMaps) test := resolverTestCase{ config: templateShortGithubTemplate, importOut: finalImports, diff --git a/registry/filebased_credential_provider.go b/registry/filebased_credential_provider.go index a14931c33..f508717f0 100644 --- a/registry/filebased_credential_provider.go +++ b/registry/filebased_credential_provider.go @@ -25,17 +25,19 @@ import ( "github.com/kubernetes/deployment-manager/common" ) -// CredentialProvider provides credentials for registries. +// FilebasedCredentialProvider provides credentials for registries. type FilebasedCredentialProvider struct { // Actual backing store backingCredentialProvider common.CredentialProvider } +// NamedRegistryCredential associates a name with a RegistryCredential. type NamedRegistryCredential struct { Name string `json:"name,omitempty"` common.RegistryCredential } +// NewFilebasedCredentialProvider creates a file based credential provider. func NewFilebasedCredentialProvider(filename string) (common.CredentialProvider, error) { icp := NewInmemCredentialProvider() c, err := readCredentialsFile(filename) @@ -66,10 +68,12 @@ func parseCredentials(bytes []byte) ([]NamedRegistryCredential, error) { return r, nil } +// GetCredential returns a credential by name. func (fcp *FilebasedCredentialProvider) GetCredential(name string) (*common.RegistryCredential, error) { return fcp.backingCredentialProvider.GetCredential(name) } +// SetCredential sets a credential by name. func (fcp *FilebasedCredentialProvider) SetCredential(name string, credential *common.RegistryCredential) error { return fmt.Errorf("SetCredential operation not supported with FilebasedCredentialProvider") } diff --git a/registry/gcs_registry.go b/registry/gcs_registry.go index 659571444..de2ac9d13 100644 --- a/registry/gcs_registry.go +++ b/registry/gcs_registry.go @@ -50,10 +50,14 @@ type GCSRegistry struct { } // RE for GCS storage + +// ChartFormatMatcher matches the chart name format var ChartFormatMatcher = regexp.MustCompile("(.*)-(.*).tgz") + +// URLFormatMatcher matches the GCS URL format (gs:). var URLFormatMatcher = regexp.MustCompile("gs://(.*)") -// NewGithubTemplateRegistry creates a GithubTemplateRegistry. +// NewGCSRegistry creates a GCS registry. func NewGCSRegistry(name, shortURL string, httpClient *http.Client, gcsService *storage.Service) (*GCSRegistry, error) { format := fmt.Sprintf("%s;%s", common.VersionedRegistry, common.OneLevelRegistry) trimmed := util.TrimURLScheme(shortURL) @@ -73,14 +77,17 @@ func NewGCSRegistry(name, shortURL string, httpClient *http.Client, gcsService * nil } +// GetRegistryName returns the name of the registry. func (g GCSRegistry) GetRegistryName() string { return g.name } +// GetBucket returns the registry bucket. func (g GCSRegistry) GetBucket() string { return g.bucket } +// GetRegistryType returns the registry type. func (g GCSRegistry) GetRegistryType() common.RegistryType { return common.GCSRegistryType } @@ -123,10 +130,12 @@ func (g GCSRegistry) ListTypes(regex *regexp.Regexp) ([]Type, error) { return types, nil } +// GetRegistryFormat returns the registry format. func (g GCSRegistry) GetRegistryFormat() common.RegistryFormat { return common.CollectionRegistry } +// GetRegistryShortURL returns the short URL for the registry. func (g GCSRegistry) GetRegistryShortURL() string { return g.shortURL } @@ -152,6 +161,7 @@ func (g GCSRegistry) GetDownloadURLs(t Type) ([]*url.URL, error) { return ret, err } +// Do performs an HTTP operation on the receiver's httpClient. func (g GCSRegistry) Do(req *http.Request) (resp *http.Response, err error) { return g.httpClient.Do(req) } diff --git a/registry/github_package_registry.go b/registry/github_package_registry.go index bc2ede948..08eae1d91 100644 --- a/registry/github_package_registry.go +++ b/registry/github_package_registry.go @@ -153,6 +153,7 @@ func (g GithubPackageRegistry) MakeRepositoryPath(t Type) (string, error) { return t.Name + "/manifests", nil } +// Do performs an HTTP operation on the receiver's httpClient. func (g GithubPackageRegistry) Do(req *http.Request) (resp *http.Response, err error) { return g.httpClient.Do(req) } diff --git a/registry/github_template_registry.go b/registry/github_template_registry.go index 4a9d3be48..dfb20bb9f 100644 --- a/registry/github_template_registry.go +++ b/registry/github_template_registry.go @@ -214,6 +214,7 @@ func (g GithubTemplateRegistry) MakeRepositoryPath(t Type) (string, error) { return p + t.Name + "/" + t.GetVersion(), nil } +// Do performs an HTTP operation on the receiver's httpClient. func (g GithubTemplateRegistry) Do(req *http.Request) (resp *http.Response, err error) { return g.httpClient.Do(req) } diff --git a/registry/inmem_credential_provider.go b/registry/inmem_credential_provider.go index e21f12600..d09d5c7fc 100644 --- a/registry/inmem_credential_provider.go +++ b/registry/inmem_credential_provider.go @@ -22,14 +22,17 @@ import ( "fmt" ) +// InmemCredentialProvider is a memory based credential provider. type InmemCredentialProvider struct { credentials map[string]*common.RegistryCredential } +// NewInmemCredentialProvider creates a new memory based credential provider. func NewInmemCredentialProvider() common.CredentialProvider { return &InmemCredentialProvider{credentials: make(map[string]*common.RegistryCredential)} } +// GetCredential returns a credential by name. func (fcp *InmemCredentialProvider) GetCredential(name string) (*common.RegistryCredential, error) { if val, ok := fcp.credentials[name]; ok { return val, nil @@ -37,6 +40,7 @@ func (fcp *InmemCredentialProvider) GetCredential(name string) (*common.Registry return nil, fmt.Errorf("no such credential : %s", name) } +// SetCredential sets a credential by name. func (fcp *InmemCredentialProvider) SetCredential(name string, credential *common.RegistryCredential) error { fcp.credentials[name] = &common.RegistryCredential{APIToken: credential.APIToken, BasicAuth: credential.BasicAuth, ServiceAccount: credential.ServiceAccount} return nil diff --git a/registry/inmem_registry_service.go b/registry/inmem_registry_service.go index ed1077974..c22b802e7 100644 --- a/registry/inmem_registry_service.go +++ b/registry/inmem_registry_service.go @@ -28,6 +28,7 @@ type inmemRegistryService struct { registries map[string]*common.Registry } +// NewInmemRegistryService returns a new memory based registry service. func NewInmemRegistryService() common.RegistryService { rs := &inmemRegistryService{ registries: make(map[string]*common.Registry), diff --git a/registry/registry.go b/registry/registry.go index 9fcd9818b..f1946269f 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -67,6 +67,7 @@ type ObjectStorageRegistry interface { GetBucket() string } +// Type describes a type stored in a registry. type Type struct { Collection string Name string diff --git a/registry/registryprovider.go b/registry/registryprovider.go index 48d77451e..3cd22a6a8 100644 --- a/registry/registryprovider.go +++ b/registry/registryprovider.go @@ -48,10 +48,12 @@ type registryProvider struct { registries map[string]Registry } +// NewDefaultRegistryProvider creates a default registry provider with the supplied credential. func NewDefaultRegistryProvider(cp common.CredentialProvider, rs common.RegistryService) RegistryProvider { return NewRegistryProvider(rs, NewGithubRegistryProvider(cp), NewGCSRegistryProvider(cp), cp) } +// NewRegistryProvider creates a new registry provider using the supplied arguments. func NewRegistryProvider(rs common.RegistryService, grp GithubRegistryProvider, gcsrp GCSRegistryProvider, cp common.CredentialProvider) RegistryProvider { if rs == nil { rs = NewInmemRegistryService() @@ -86,6 +88,7 @@ func (rp *registryProvider) getRegistry(cr common.Registry) (Registry, error) { } } +// GetRegistryByShortURL returns the registry identified by a short URL. func (rp *registryProvider) GetRegistryByShortURL(URL string) (Registry, error) { rp.RLock() defer rp.RUnlock() @@ -122,6 +125,7 @@ func (rp *registryProvider) findRegistryByShortURL(URL string) Registry { return nil } +// GetRegistryByName returns a registry by name. func (rp *registryProvider) GetRegistryByName(registryName string) (Registry, error) { rp.RLock() defer rp.RUnlock() @@ -141,6 +145,7 @@ func (rp *registryProvider) GetRegistryByName(registryName string) (Registry, er return r, nil } +// ParseRegistryFormat creates a map from a registry format string. func ParseRegistryFormat(rf common.RegistryFormat) map[common.RegistryFormat]bool { split := strings.Split(string(rf), ";") var result = map[common.RegistryFormat]bool{} @@ -315,7 +320,7 @@ func GetDownloadURLs(rp RegistryProvider, t string) ([]string, Registry, error) return ShortTypeToPackageDownloadURLs(rp, t) } else if IsGCSShortType(t) { return ShortTypeToGCSDownloadUrls(rp, t) - } else if util.IsHttpUrl(t) { + } else if util.IsHTTPURL(t) { result, err := url.Parse(t) if err != nil { return nil, nil, fmt.Errorf("cannot parse download URL %s: %s", t, err) @@ -389,6 +394,7 @@ func ShortTypeToPackageDownloadURLs(rp RegistryProvider, t string) ([]string, Re return util.ConvertURLsToStrings(urls), r, err } +// ShortTypeToGCSDownloadUrls returns the download URLs for a short type name. func ShortTypeToGCSDownloadUrls(rp RegistryProvider, t string) ([]string, Registry, error) { m := GCSRegistryMatcher.FindStringSubmatch(t) if len(m) != 3 { diff --git a/registry/registryprovider_test.go b/registry/registryprovider_test.go index ad12af5ca..bd41b354d 100644 --- a/registry/registryprovider_test.go +++ b/registry/registryprovider_test.go @@ -20,7 +20,7 @@ import ( "testing" ) -func testUrlConversionDriver(rp RegistryProvider, tests map[string]TestURLAndError, t *testing.T) { +func testURLConversionDriver(rp RegistryProvider, tests map[string]TestURLAndError, t *testing.T) { for in, expected := range tests { // TODO(vaikas): Test to make sure it's the right registry. actual, _, err := GetDownloadURLs(rp, in) @@ -34,8 +34,8 @@ func testUrlConversionDriver(rp RegistryProvider, tests map[string]TestURLAndErr } } -func TestShortGithubUrlTemplateMapping(t *testing.T) { - githubUrlMaps := map[Type]TestURLAndError{ +func TestShortGithubURLTemplateMapping(t *testing.T) { + githubURLMaps := map[Type]TestURLAndError{ NewTypeOrDie("common", "replicatedservice", "v1"): TestURLAndError{"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/common/replicatedservice/v1/replicatedservice.py", nil}, NewTypeOrDie("storage", "redis", "v1"): TestURLAndError{"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/storage/redis/v1/redis.jinja", nil}, } @@ -45,13 +45,13 @@ func TestShortGithubUrlTemplateMapping(t *testing.T) { "github.com/kubernetes/application-dm-templates/storage/redis:v1": TestURLAndError{"https://raw.githubusercontent.com/kubernetes/application-dm-templates/master/storage/redis/v1/redis.jinja", nil}, } - grp := NewTestGithubRegistryProvider("github.com/kubernetes/application-dm-templates", githubUrlMaps) + grp := NewTestGithubRegistryProvider("github.com/kubernetes/application-dm-templates", githubURLMaps) // TODO(vaikas): XXXX FIXME Add gcsrp - testUrlConversionDriver(NewRegistryProvider(nil, grp, nil, NewInmemCredentialProvider()), tests, t) + testURLConversionDriver(NewRegistryProvider(nil, grp, nil, NewInmemCredentialProvider()), tests, t) } -func TestShortGithubUrlPackageMapping(t *testing.T) { - githubUrlMaps := map[Type]TestURLAndError{ +func TestShortGithubURLPackageMapping(t *testing.T) { + githubURLMaps := map[Type]TestURLAndError{ NewTypeOrDie("", "mongodb", ""): TestURLAndError{"https://raw.githubusercontent.com/helm/charts/master/mongodb/manifests/mongodb.yaml", nil}, NewTypeOrDie("", "redis", ""): TestURLAndError{"https://raw.githubusercontent.com/helm/charts/master/redis/manifests/redis.yaml", nil}, } @@ -61,7 +61,7 @@ func TestShortGithubUrlPackageMapping(t *testing.T) { "github.com/helm/charts/redis": TestURLAndError{"https://raw.githubusercontent.com/helm/charts/master/redis/manifests/redis.yaml", nil}, } - grp := NewTestGithubRegistryProvider("github.com/helm/charts", githubUrlMaps) + grp := NewTestGithubRegistryProvider("github.com/helm/charts", githubURLMaps) // TODO(vaikas): XXXX FIXME Add gcsrp - testUrlConversionDriver(NewRegistryProvider(nil, grp, nil, NewInmemCredentialProvider()), tests, t) + testURLConversionDriver(NewRegistryProvider(nil, grp, nil, NewInmemCredentialProvider()), tests, t) } diff --git a/registry/secrets_credential_provider.go b/registry/secrets_credential_provider.go index ca31c8a08..5ee2f4fd9 100644 --- a/registry/secrets_credential_provider.go +++ b/registry/secrets_credential_provider.go @@ -46,12 +46,13 @@ var kubernetesConfig *util.KubernetesConfig const secretType = "Secret" -// CredentialProvider provides credentials for registries. +// SecretsCredentialProvider provides credentials for registries from Kubernertes secrets. type SecretsCredentialProvider struct { // Actual object that talks to secrets service. k util.Kubernetes } +// NewSecretsCredentialProvider creates a new secrets credential provider. func NewSecretsCredentialProvider() common.CredentialProvider { kubernetesConfig := &util.KubernetesConfig{ KubePath: *kubePath, @@ -87,6 +88,7 @@ func parseCredential(credential string) (*common.RegistryCredential, error) { return r, nil } +// GetCredential returns a credential by name. func (scp *SecretsCredentialProvider) GetCredential(name string) (*common.RegistryCredential, error) { o, err := scp.k.Get(name, secretType) if err != nil { @@ -95,6 +97,7 @@ func (scp *SecretsCredentialProvider) GetCredential(name string) (*common.Regist return parseCredential(o) } +// SetCredential sets a credential by name. func (scp *SecretsCredentialProvider) SetCredential(name string, credential *common.RegistryCredential) error { // Marshal the credential & base64 encode it. b, err := yaml.Marshal(credential) @@ -111,7 +114,7 @@ func (scp *SecretsCredentialProvider) SetCredential(name string, credential *com data["credential"] = enc obj := &common.KubernetesSecret{ Kind: secretType, - ApiVersion: "v1", + APIVersion: "v1", Metadata: metadata, Data: data, } diff --git a/registry/semver.go b/registry/semver.go index f49fd833b..0a42e2d33 100644 --- a/registry/semver.go +++ b/registry/semver.go @@ -22,12 +22,14 @@ import ( "strings" ) +// SemVer holds a semantic version as defined by semver.io. type SemVer struct { Major uint Minor uint Patch uint } +// ParseSemVer parses a semantic version string. func ParseSemVer(version string) (SemVer, error) { var err error major, minor, patch := uint64(0), uint64(0), uint64(0) @@ -70,6 +72,7 @@ func ParseSemVer(version string) (SemVer, error) { return SemVer{Major: uint(major), Minor: uint(minor), Patch: uint(patch)}, nil } +// IsZero returns true if the semantic version is zero. func (s SemVer) IsZero() bool { return s.Major == 0 && s.Minor == 0 && s.Patch == 0 } diff --git a/registry/testhelper.go b/registry/testhelper.go index 9532113b3..5472e07bd 100644 --- a/registry/testhelper.go +++ b/registry/testhelper.go @@ -32,11 +32,13 @@ import ( "strings" ) +// TestURLAndError associates a URL with an error string for testing. type TestURLAndError struct { URL string Err error } +// DownloadResponse holds a mock http reponse for testing. type DownloadResponse struct { Err error Code int @@ -55,6 +57,7 @@ type testGithubRegistry struct { downloadResponses map[string]DownloadResponse } +// NewTestGithubRegistryProvider creates a test github registry provider. func NewTestGithubRegistryProvider(shortURL string, responses map[Type]TestURLAndError) GithubRegistryProvider { return testGithubRegistryProvider{ shortURL: util.TrimURLScheme(shortURL), @@ -62,6 +65,7 @@ func NewTestGithubRegistryProvider(shortURL string, responses map[Type]TestURLAn } } +// NewTestGithubRegistryProviderWithDownloads creates a test github registry provider with download responses. func NewTestGithubRegistryProviderWithDownloads(shortURL string, responses map[Type]TestURLAndError, downloadResponses map[string]DownloadResponse) GithubRegistryProvider { return testGithubRegistryProvider{ shortURL: util.TrimURLScheme(shortURL), @@ -70,6 +74,7 @@ func NewTestGithubRegistryProviderWithDownloads(shortURL string, responses map[T } } +// GetGithubRegistry is a mock implementation of the same method on GithubRegistryProvider. func (tgrp testGithubRegistryProvider) GetGithubRegistry(cr common.Registry) (GithubRegistry, error) { trimmed := util.TrimURLScheme(cr.URL) if strings.HasPrefix(trimmed, tgrp.shortURL) { @@ -88,10 +93,12 @@ func (tgrp testGithubRegistryProvider) GetGithubRegistry(cr common.Registry) (Gi panic(fmt.Errorf("unknown registry: %v", cr)) } +// ListTypes is a mock implementation of the same method on GithubRegistryProvider. func (tgr testGithubRegistry) ListTypes(regex *regexp.Regexp) ([]Type, error) { panic(fmt.Errorf("ListTypes should not be called in the test")) } +// GetDownloadURLs is a mock implementation of the same method on GithubRegistryProvider. func (tgr testGithubRegistry) GetDownloadURLs(t Type) ([]*url.URL, error) { result := tgr.responses[t] URL, err := url.Parse(result.URL) @@ -102,8 +109,9 @@ func (tgr testGithubRegistry) GetDownloadURLs(t Type) ([]*url.URL, error) { return []*url.URL{URL}, result.Err } -func (g testGithubRegistry) Do(req *http.Request) (resp *http.Response, err error) { - response := g.downloadResponses[req.URL.String()] +// Do is a mock implementation of the same method on GithubRegistryProvider. +func (tgr testGithubRegistry) Do(req *http.Request) (resp *http.Response, err error) { + response := tgr.downloadResponses[req.URL.String()] return &http.Response{StatusCode: response.Code, Body: ioutil.NopCloser(bytes.NewBufferString(response.Body))}, response.Err } @@ -117,6 +125,7 @@ type testGCSRegistry struct { responses map[Type]TestURLAndError } +// NewTestGCSRegistryProvider creates a test GCS registry provider. func NewTestGCSRegistryProvider(shortURL string, responses map[Type]TestURLAndError) GCSRegistryProvider { return testGCSRegistryProvider{ shortURL: util.TrimURLScheme(shortURL), @@ -124,6 +133,7 @@ func NewTestGCSRegistryProvider(shortURL string, responses map[Type]TestURLAndEr } } +// GetDownloadURLs is a mock implementation of the same method on GCSRegistryProvider. func (tgrp testGCSRegistryProvider) GetGCSRegistry(cr common.Registry) (ObjectStorageRegistry, error) { trimmed := util.TrimURLScheme(cr.URL) if strings.HasPrefix(trimmed, tgrp.shortURL) { diff --git a/resourcifier/configurations.go b/resourcifier/configurations.go index 904e5d2b2..140f5159f 100644 --- a/resourcifier/configurations.go +++ b/resourcifier/configurations.go @@ -200,7 +200,7 @@ func getPathVariable(w http.ResponseWriter, r *http.Request, variable, handler s vars := mux.Vars(r) escaped, ok := vars[variable] if !ok { - e := errors.New(fmt.Sprintf("%s name not found in URL", variable)) + e := fmt.Errorf("%s name not found in URL", variable) util.LogAndReturnError(handler, http.StatusBadRequest, e, w) return "", e } @@ -226,7 +226,7 @@ func getConfiguration(w http.ResponseWriter, r *http.Request, handler string) *c // Reject the input if it exceeded the length limit, // since we may not have read all of it into the buffer. if _, err = b.Read(make([]byte, 0, 1)); err != io.EOF { - e := fmt.Errorf("configuration exceeds maximum length of %d KB.", *maxLength) + e := fmt.Errorf("configuration exceeds maximum length of %d KB", *maxLength) util.LogAndReturnError(handler, http.StatusBadRequest, e, w) return nil } diff --git a/resourcifier/configurator/configurator.go b/resourcifier/configurator/configurator.go index 8570138da..627c42e5f 100644 --- a/resourcifier/configurator/configurator.go +++ b/resourcifier/configurator/configurator.go @@ -27,10 +27,12 @@ import ( "github.com/kubernetes/deployment-manager/util" ) +// Configurator configures a Kubernetes cluster using kubectl. type Configurator struct { k util.Kubernetes } +// NewConfigurator creates a new Configurator. func NewConfigurator(kubernetes util.Kubernetes) *Configurator { return &Configurator{kubernetes} } @@ -69,7 +71,7 @@ func (e *Error) appendError(err error) error { return err } -// resource name -> set of dependencies. +// DependencyMap maps a resource name to a set of dependencies. type DependencyMap map[string]map[string]bool var refRe = regexp.MustCompile("\\$\\(ref\\.([^\\.]+)\\.([^\\)]+)\\)") diff --git a/util/httpclient.go b/util/httpclient.go index e53cbb91f..43b3ff4de 100644 --- a/util/httpclient.go +++ b/util/httpclient.go @@ -72,6 +72,7 @@ type httpClient struct { sleep Sleeper } +// DefaultHTTPClient returns a default http client. func DefaultHTTPClient() HTTPClient { return NewHTTPClient(3, http.DefaultClient, NewSleeper()) } @@ -115,6 +116,7 @@ func readBody(b io.ReadCloser, ctype string, encoding string) (body string, err return string(bytes), err } +// Get does an HTTP GET on the receiver. func (client httpClient) Get(url string) (body string, code int, err error) { retryCount := client.retries numRetries := uint(0) diff --git a/util/httputil.go b/util/httputil.go index 7a97c742f..540bc86a2 100644 --- a/util/httputil.go +++ b/util/httputil.go @@ -233,8 +233,8 @@ func ToJSONOrError(v interface{}) string { return string(j) } -// IsHttpURL returns whether a string is an HTTP URL. -func IsHttpUrl(s string) bool { +// IsHTTPURL returns true if a string is an HTTP URL. +func IsHTTPURL(s string) bool { u, err := url.Parse(s) if err != nil { return false diff --git a/util/kubernetes.go b/util/kubernetes.go index 0a9aac138..1e59b7bec 100644 --- a/util/kubernetes.go +++ b/util/kubernetes.go @@ -16,7 +16,7 @@ limitations under the License. package util -// KubernetesConfiguration defines the configuration options for talking to Kubernetes master +// KubernetesConfig defines the configuration options for talking to Kubernetes master type KubernetesConfig struct { KubePath string // The path to kubectl binary KubeService string // DNS name of the kubernetes service diff --git a/util/kubernetes_kubectl.go b/util/kubernetes_kubectl.go index 8b74a91cd..ff889aae4 100644 --- a/util/kubernetes_kubectl.go +++ b/util/kubernetes_kubectl.go @@ -33,6 +33,7 @@ type KubernetesKubectl struct { Arguments []string } +// NewKubernetesKubectl creates a new Kubernetes kubectl wrapper. func NewKubernetesKubectl(config *KubernetesConfig) Kubernetes { if config.KubePath == "" { log.Fatalf("kubectl path cannot be empty") @@ -85,6 +86,7 @@ func NewKubernetesKubectl(config *KubernetesConfig) Kubernetes { return &KubernetesKubectl{config.KubePath, args} } +// Get runs a kubectl get command for a named resource of a given type. func (k *KubernetesKubectl) Get(name string, resourceType string) (string, error) { // Specify output as json rather than human readable for easier machine parsing args := []string{"get", @@ -95,16 +97,19 @@ func (k *KubernetesKubectl) Get(name string, resourceType string) (string, error return k.execute(args, "") } +// Create runs a kubectl create command for a given resource. func (k *KubernetesKubectl) Create(resource string) (string, error) { args := []string{"create"} return k.execute(args, resource) } +// Delete runs a kubectl delete command for a given resource. func (k *KubernetesKubectl) Delete(resource string) (string, error) { args := []string{"delete"} return k.execute(args, resource) } +// Replace runs a kubectl replace command for a given resource. func (k *KubernetesKubectl) Replace(resource string) (string, error) { args := []string{"replace"} return k.execute(args, resource) diff --git a/util/kubernetesutil.go b/util/kubernetesutil.go index 25c14d9bc..959c6ecae 100644 --- a/util/kubernetesutil.go +++ b/util/kubernetesutil.go @@ -6,7 +6,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,6 +24,7 @@ import ( "github.com/kubernetes/deployment-manager/common" ) +// ParseKubernetesObject parses a Kubernetes API object in YAML format. func ParseKubernetesObject(object []byte) (*common.Resource, error) { o := &common.KubernetesObject{} if err := yaml.Unmarshal(object, &o); err != nil {