Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Create helm registry for ksonnet#583

Merged
bryanl merged 1 commit intoksonnet:masterfrom
bryanl:helm-registry
Jun 7, 2018
Merged

Create helm registry for ksonnet#583
bryanl merged 1 commit intoksonnet:masterfrom
bryanl:helm-registry

Conversation

@bryanl
Copy link
Member

@bryanl bryanl commented Jun 3, 2018

Creates a helm registry that can treat helm charts as ksonnet parts.

design doc

#522

This change does the following:

If you have a helm registry defined in app.yaml, It will show up in the registry listing:

NAME        OVERRIDE PROTOCOL URI
====        ======== ======== ===
helm-stable          helm     https://kubernetes-charts.storage.googleapis.com

You can run ks pkg list and see charts in your helm repository

REGISTRY    NAME                           INSTALLED
========    ====                           =========
helm-stable acs-engine-autoscaler
helm-stable aerospike
helm-stable anchore-engine
helm-stable artifactory
helm-stable artifactory-ha
helm-stable aws-cluster-autoscaler
helm-stable bitcoind
helm-stable buildkite
helm-stable burrow

You can run ks pkg install to install a package:

$ ks pkg install helm-stable/acs-engine-autoscaler
INFO Retrieved 8 files

The pkg will then be vendored for you:

vendor/helm-stable/
└── acs-engine-autoscaler
    └── helm
        └── 2.2.0
            └── acs-engine-autoscaler
                ├── Chart.yaml
                ├── README.md
                ├── templates
                │   ├── NOTES.txt
                │   ├── _helpers.tpl
                │   ├── deployment.yaml
                │   └── secrets.yaml
                └── values.yaml

5 directories, 7 files

Signed-off-by: bryanl bryanliles@gmail.com

@bryanl bryanl self-assigned this Jun 3, 2018
@bryanl bryanl requested review from shomron and underrun June 3, 2018 15:54
@coveralls
Copy link

coveralls commented Jun 3, 2018

Pull Request Test Coverage Report for Build 953

  • 239 of 279 (85.66%) changed or added relevant lines in 8 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.3%) to 69.734%

Changes Missing Coverage Covered Lines Changed/Added Lines %
pkg/cluster/apply.go 2 3 66.67%
pkg/cluster/cluster.go 0 4 0.0%
pkg/registry/manager.go 0 6 0.0%
pkg/helm/client.go 111 123 90.24%
pkg/registry/helm.go 91 108 84.26%
Totals Coverage Status
Change from base Build 950: 0.3%
Covered Lines: 9617
Relevant Lines: 13791

💛 - Coveralls

@rimusz
Copy link

rimusz commented Jun 3, 2018

👍

@rimusz
Copy link

rimusz commented Jun 3, 2018

would you mind to give comment access to the design doc, please?

Copy link
Collaborator

@underrun underrun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a couple questions... will dig in more Monday

Makefile Outdated
VERSION?=dev-$(shell date +%FT%T%z)
KS_BIN?=ks

APIMACHINERY_VER := $(shell dep status | grep k8s.io/apimachinery | awk '{print $$3}')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is api machinery back/forward compat as of 1.8? i'm all for getting rid of this line as it requires someone to have run dep ensure before running make - just checking to make sure we can do this safely.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option here if we we want to keep the flexibility without the terrible build time:
APIMACHINERY_VER := $(shell grep -B1 k8s.io/apimachinery Gopkg.lock | head -n1 | cut -d'"' -f2)

}

// MakeRegistryRefSpec returns app registry ref spec.
func (h *Helm) MakeRegistryRefSpec() *app.RegistryRefSpec {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this called MakeRegistryRefSpec instead of RegistryRefSpec?

spec *app.RegistryRefSpec
repositoryClient HelmRepositoryClient
unarchiver archive.Unarchiver
httpGet httpGet
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this not encapsulated in the repositoryClient?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I missed it. It should be in there.

spec: registryRef,
repositoryClient: rc,
unarchiver: ua,
httpGet: http.Get,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should support request timeouts - http.DefaultClient does not.

Version string `json:"version,omitempty"`
}

type httpGet func(string) (*http.Response, error)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this style preferred over a getter interface?

"github.com/pkg/errors"
)

// Helm is a Helm repository.
Copy link
Collaborator

@shomron shomron Jun 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a good helm repository spec we could link to from somewhere? The most comprehensive I found was this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The might be the best there is.

}

if hg == nil {
hg = http.Get
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for timeouts.

}, nil
}

func (hrc *helmRepositoryClient) Repository() (*HelmRepository, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's document exported methods.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method isn't exported, but it should have documentation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, and agreed 😃

}
}()

b, err := ioutil.ReadAll(resp.Body)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we feel about reading arbitrarily long bodies into memory?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not great, but this would required an onFile refactor. I noted this in #522.

defer func() {
cerr := resp.Body.Close()
if cerr != nil {
err = cerr
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the intention here? What is generally done with errors within defer blocks?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an extremely hard error to trigger. If it does happen, return it instead of the initial error since it is most likely the cause of the problem. The reason it's a deferred function is because defer resp.Body.Close() will swallow the error.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But to pull that off correctly, would error need to be a named return value?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if that's the plan it might be better to wrap any existing error rather than steam-rolling it.

}

func (hrc *helmRepositoryClient) Chart(name, version string) (*HelmRepositoryChart, error) {
repo, err := hrc.Repository()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be cached - do we want to download and parse multiple megabytes for each call?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, going to add another issue for this.

}

if version == "" {
for _, chart := range repo.Latest() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a lot of extra work - we're sorting all versions of all charts, then doing a linear search for the desired chart name. Why instead not sort just repo.Charts[name]?

return githubFactory(a, spec)
case ProtocolFilesystem:
return NewFs(a, spec)
case ProtocolHelm:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is registry add support in scope for this PR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope. Don't want to do that until we have a complete solution.

case ProtocolFilesystem:
return NewFs(a, spec)
case ProtocolHelm:
client, err := newHelmRepositoryClient("https://kubernetes-charts.storage.googleapis.com", nil)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be configurable? Or at least const? Or will that be part of the registry add work?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be, but this is dependent on registry add. So for now, it is hard coded.

}

if resp.StatusCode != http.StatusOK {
return nil, nil, errors.Errorf("unexpected HTTP status code %q when retrieving helm chart", resp.Status)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more context in this error (chart? url?) would be useful - I'm not clear on whether those are added up the stack.

}
}()

handler := func(f *archive.File) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment along the lines of "file contents are returned to the caller via onFile handler would be useful to the uninitiated.


name := path.Join(chart.Name, "helm", chart.Version, f.Name)

return onFile(name, b)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd consider a future refactor of the ResolveFile interface to allow streaming with io.Reader all the way to the consumer.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Captured this change in #596


refSpec := &app.LibraryRefSpec{
Name: partAlias,
Registry: h.Name(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conspicuously missing is GitVersion - should we discuss how we might better abstract away the version details while allowing them to be persisted in app.yaml?

Copy link
Member Author

@bryanl bryanl Jun 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no GitVersion if there is not GitRepo. This is an implementation detailed that leaked before registries were understood.

@bryanl bryanl force-pushed the helm-registry branch 3 times, most recently from e6d54ca to c205f1e Compare June 7, 2018 16:43
@bryanl
Copy link
Member Author

bryanl commented Jun 7, 2018

@ksonnet/reviewers is this ready to go? Any more changes?

Charts map[string][]RepositoryChart `json:"entries,omitempty"`
}

// FooLatest returns the latest version of charts in a Helm repository.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minus Foo

Get(string) (*http.Response, error)
}

type getter struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose renaming to httpGetter - it will be clearer to read vs. the abstract getter interface.


// Repository returns the Helm repository's content.
func (hrc *HTTPClient) Repository() (*Repository, error) {
resp, err := hrc.getter.Get(hrc.url.String())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use Fetch() from below here?

}

// Fetch fetches URLs from a repository. If uri is a path, it will use the client URL as the base.
func (hrc *HTTPClient) Fetch(uri string) (io.ReadCloser, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be exported?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because the Helm registry uses it to resolve files and it is in another package.

@shomron
Copy link
Collaborator

shomron commented Jun 7, 2018

Added a last round of comments. None need to be hard blockers.

Creates a helm registry that can treat helm charts as ksonnet parts.

[design doc](https://docs.google.com/document/d/1FcK8pDqj_9EFjNVr9e_t9WemouQpS9ix-r0AxNDB_nM/edit?usp=sharing)

Signed-off-by: bryanl bryanliles@gmail.com
@bryanl bryanl merged commit b03ceb4 into ksonnet:master Jun 7, 2018
@bryanl bryanl deleted the helm-registry branch June 7, 2018 18:29
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants