Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TOI: improve credential handling #339

Merged
merged 3 commits into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 46 additions & 13 deletions cmds/ocm/commands/toicmds/config/bootstrap/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package bootstrap

import (
"encoding/json"
"fmt"
"strings"

Expand Down Expand Up @@ -32,6 +33,7 @@ import (
utils2 "github.com/open-component-model/ocm/pkg/contexts/ocm/utils"
"github.com/open-component-model/ocm/pkg/errors"
"github.com/open-component-model/ocm/pkg/out"
"github.com/open-component-model/ocm/pkg/runtime"
"github.com/open-component-model/ocm/pkg/toi"
"github.com/open-component-model/ocm/pkg/toi/install"
utils3 "github.com/open-component-model/ocm/pkg/utils"
Expand Down Expand Up @@ -197,24 +199,55 @@ func (a *action) Out() error {
out.Outf(a.cmd.Context, "%s: %d byte(s) written\n", schemeFile, len(spec.Scheme))
}
}
if a.download("configuration template", a.cmd.ParameterFile, cv, spec.AdditionalResources[toi.AdditionalResourceConfigFile], resolver) != nil {
err = fmt.Errorf("download failed")
}

if e := a.download("credentials template", a.cmd.CredentialsFile, cv, spec.AdditionalResources[toi.AdditionalResourceCredentialsFile], resolver); e != nil {
out.Errf(a.cmd.Context, "%s", e.Error())
err = fmt.Errorf("download failed")
}
list := errors.ErrList()
list.Add(a.handle("configuration template", a.cmd.ParameterFile, cv, spec.AdditionalResources[toi.AdditionalResourceConfigFile], resolver))
list.Add(a.handle("credentials template", a.cmd.CredentialsFile, cv, spec.AdditionalResources[toi.AdditionalResourceCredentialsFile], resolver))
return list.Result()
}

return err
func (a *action) handle(kind, path string, cv ocm.ComponentVersionAccess, spec *toi.AdditionalResource, resolver ocm.ComponentVersionResolver) error {
var err error
if spec != nil {
if spec.ResourceReference != nil && len(spec.ResourceReference.Resource) != 0 {
return a.download(kind, a.cmd.ParameterFile, cv, spec.ResourceReference, resolver)
} else {
var content interface{}
if len(spec.Content) > 0 {
if err = json.Unmarshal(spec.Content, &content); err != nil {
return errors.Wrapf(err, "cannot marshal %s content", kind)
}
l := 0
out.Outf(a.cmd.Context, "writing %s...\n", kind)
switch c := content.(type) {
case string:
l = len(c)
err = vfs.WriteFile(a.cmd.FileSystem(), path, []byte(c), 0o600)
case []byte:
l = len(c)
err = vfs.WriteFile(a.cmd.FileSystem(), path, c, 0o600)
default:
data, err := runtime.DefaultYAMLEncoding.Marshal(spec.Content)
if err != nil {
data = spec.Content
}
l = len(spec.Content)
err = vfs.WriteFile(a.cmd.FileSystem(), path, data, 0o600)
}
if err != nil {
return errors.Wrapf(err, "cannot write %s to %s", kind, path)
}
out.Outf(a.cmd.Context, "%s: %d byte(s) written\n", path, l)
return nil
}
return nil
}
}
out.Outf(a.cmd.Context, "no %s configured\n", kind)
return nil
}

func (a *action) download(kind, path string, cv ocm.ComponentVersionAccess, spec *metav1.ResourceReference, resolver ocm.ComponentVersionResolver) error {

if spec == nil {
out.Outf(a.cmd.Context, "no %s configured\n", kind)
return nil
}
res, _, err := utils2.MatchResourceReference(cv, toi.TypeYAML, *spec, resolver)
if err != nil {
return errors.Wrapf(err, "%s resource", kind)
Expand Down
122 changes: 122 additions & 0 deletions cmds/ocm/commands/toicmds/config/bootstrap/cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// SPDX-FileCopyrightText: 2022 SAP SE or an SAP affiliate company and Open Component Model contributors.
//
// SPDX-License-Identifier: Apache-2.0

package bootstrap_test

import (
"bytes"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
. "github.com/open-component-model/ocm/cmds/ocm/testhelper"
. "github.com/open-component-model/ocm/pkg/testutils"

"github.com/mandelsoft/vfs/pkg/vfs"

"github.com/open-component-model/ocm/cmds/ocm/commands/toicmds/config/bootstrap"
"github.com/open-component-model/ocm/pkg/common/accessio"
v1 "github.com/open-component-model/ocm/pkg/contexts/ocm/compdesc/meta/v1"
"github.com/open-component-model/ocm/pkg/mime"
"github.com/open-component-model/ocm/pkg/toi"
)

const ARCH = "/tmp/ctf"
const VERSION = "v1"
const COMP1 = "test.de/a"
const COMP2 = "test.de/b"
const PROVIDER = "mandelsoft"

var _ = Describe("Test Environment", func() {
var env *TestEnv

respkg := `
description: with config example by resource
additionalResources:
` + toi.AdditionalResourceConfigFile + `:
content:
param: value
`
cntpkg := `
description: with example by content
additionalResources:
` + toi.AdditionalResourceCredentialsFile + `:
content: |
credentials: none
` + toi.AdditionalResourceConfigFile + `:
content:
param: value
`

BeforeEach(func() {
env = NewTestEnv()
env.OCMCommonTransport(ARCH, accessio.FormatDirectory, func() {
env.Component(COMP1, func() {
env.Version(VERSION, func() {
env.Provider(PROVIDER)
env.Resource("package", VERSION, toi.TypeTOIPackage, v1.LocalRelation, func() {
env.BlobStringData(toi.PackageSpecificationMimeType, respkg)
})
env.Resource("example", VERSION, toi.TypeTOIPackage, v1.LocalRelation, func() {
env.BlobStringData(mime.MIME_YAML, "param: value")
})
})
})
env.Component(COMP2, func() {
env.Version(VERSION, func() {
env.Provider(PROVIDER)
env.Resource("package", VERSION, toi.TypeTOIPackage, v1.LocalRelation, func() {
env.BlobStringData(toi.PackageSpecificationMimeType, cntpkg)
})
})
})
})
})

AfterEach(func() {
env.Cleanup()
})

It("config by resource", func() {
buf := bytes.NewBuffer(nil)
Expect(env.CatchOutput(buf).Execute("bootstrap", "config", ARCH+"//"+COMP1)).To(Succeed())
Expect(buf.String()).To(StringEqualTrimmedWithContext(
`
Warning: repository is no OCI registry, consider importing it or use upload repository with option ' -X ociuploadrepo=...
found package resource "package" in test.de/a:v1

Package Description:
with config example by resource

writing configuration template...
TOIParameters: 17 byte(s) written
no credentials template configured
`))
data := Must(vfs.ReadFile(env.FileSystem(), bootstrap.DEFAULT_PARAMETER_FILE))
Expect(string(data)).To(Equal(`param: value
`))
})
It("config by content", func() {
buf := bytes.NewBuffer(nil)
Expect(env.CatchOutput(buf).Execute("bootstrap", "config", ARCH+"//"+COMP2)).To(Succeed())
Expect(buf.String()).To(StringEqualTrimmedWithContext(
`
Warning: repository is no OCI registry, consider importing it or use upload repository with option ' -X ociuploadrepo=...
found package resource "package" in test.de/b:v1

Package Description:
with example by content

writing configuration template...
TOIParameters: 17 byte(s) written
writing credentials template...
TOICredentials: 18 byte(s) written
`))
data := Must(vfs.ReadFile(env.FileSystem(), bootstrap.DEFAULT_PARAMETER_FILE))
Expect(string(data)).To(Equal(`param: value
`))
data = Must(vfs.ReadFile(env.FileSystem(), bootstrap.DEFAULT_CREDENTIALS_FILE))
Expect(string(data)).To(Equal(`credentials: none
`))
})
})
17 changes: 17 additions & 0 deletions cmds/ocm/commands/toicmds/config/bootstrap/suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-FileCopyrightText: 2022 SAP SE or an SAP affiliate company and Open Component Model contributors.
//
// SPDX-License-Identifier: Apache-2.0

package bootstrap_test

import (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestConfig(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "TOI bootstrap config")
}
33 changes: 27 additions & 6 deletions cmds/ocm/topics/toi/bootstrapping/topic.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ contained in the component version, which contains the package resource.

It is a plain yaml resource with the media types media type <code>` + mime.MIME_YAML + `</code>,
<code>` + mime.MIME_YAML_ALT + `</code> or

<code>` + toi.PackageSpecificationMimeType + `</code>) containing
information required to control the instantiation of an executor.

Expand Down Expand Up @@ -151,9 +152,10 @@ It has the following format:
requites the specification of a credentials file providing the information
how to satisfy those credential requests.

- **<code>additionalResources</code>** (optional) *map[string]ResourceReference*
- **<code>additionalResources</code>** (optional) *map[string]AdditionalResource)*

A set of additional resources specified by OCM resource references.
A set of additional resources specified by an OCM resource reference or
direct data as byte, string or yaml.
The key describes the meaning of the resource. The following keys have
a special meaning:

Expand Down Expand Up @@ -236,6 +238,17 @@ that contains the resource reference. It uses the following fields:

This is the identity of the resource in the selected component version.

#### *AdditionalResource*

This field has either the fields of a *ResourceReference* to refer to the
content of an OCM resource or the field:

- **<code>content</code>** *string|[]byte|YAML*

Either a resource reference or the field <code>content</code> must be given.
The content field may contain a string or an inline YAML document.
For larger content the resource reference form should be preferred.

#### *Identity*

An identity specification is a <code>map[string]string</code>. It describes
Expand All @@ -253,7 +266,7 @@ to provide specifc values expected by the executor.
This is done by a _spiff_ template. Here special functions
are provided to access specific content:

- <code>hasCredentials(string) bool</code>
- <code>hasCredentials(string[,string]) bool</code>

This function can be used to check whether dedicated credentials
are effectively provided for the actual installation.
Expand All @@ -262,9 +275,18 @@ are provided to access specific content:
request section optionally mapped to the name used for the executor
(field <code>credentialMapping</code>).

- <code>getCredentials(string) map[string]string</code>
If the second argument is given, it checks for the named property
in the credential set.

This functions provides the property set of the provided credentials.
- <code>getCredentials(string[,string]) map[string]string | string</code>

This functions provides the property set of the provided credentials.

If the second argument is given, it returns the named property in the
selected credential set.

If the property name is an asterisks (<code>*</code>) a single property
is expected, whose value is returned.

#### User Config vs Executor Config

Expand Down Expand Up @@ -301,7 +323,6 @@ definitions.


### The <code>` + toi.TypeTOIExecutor + `</code> Resource

Instead of directly describing an image resource in the package file, it is
possible to refer to a resource of type ` + toi.TypeTOIExecutor + `. This
is a yaml file with the media type <code>` + mime.MIME_YAML + `</code>,
Expand Down
33 changes: 27 additions & 6 deletions docs/reference/ocm_bootstrap_configuration_toi-bootstrapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ contained in the component version, which contains the package resource.

It is a plain yaml resource with the media types media type <code>application/x-yaml</code>,
<code>text/yaml</code> or

<code>application/vnd.toi.ocm.software.package.v1+yaml</code>) containing
information required to control the instantiation of an executor.

Expand Down Expand Up @@ -90,9 +91,10 @@ It has the following format:
requites the specification of a credentials file providing the information
how to satisfy those credential requests.

- **<code>additionalResources</code>** (optional) *map[string]ResourceReference*
- **<code>additionalResources</code>** (optional) *map[string]AdditionalResource)*

A set of additional resources specified by OCM resource references.
A set of additional resources specified by an OCM resource reference or
direct data as byte, string or yaml.
The key describes the meaning of the resource. The following keys have
a special meaning:

Expand Down Expand Up @@ -175,6 +177,17 @@ that contains the resource reference. It uses the following fields:

This is the identity of the resource in the selected component version.

#### *AdditionalResource*

This field has either the fields of a *ResourceReference* to refer to the
content of an OCM resource or the field:

- **<code>content</code>** *string|[]byte|YAML*

Either a resource reference or the field <code>content</code> must be given.
The content field may contain a string or an inline YAML document.
For larger content the resource reference form should be preferred.

#### *Identity*

An identity specification is a <code>map[string]string</code>. It describes
Expand All @@ -192,7 +205,7 @@ to provide specifc values expected by the executor.
This is done by a _spiff_ template. Here special functions
are provided to access specific content:

- <code>hasCredentials(string) bool</code>
- <code>hasCredentials(string[,string]) bool</code>

This function can be used to check whether dedicated credentials
are effectively provided for the actual installation.
Expand All @@ -201,9 +214,18 @@ are provided to access specific content:
request section optionally mapped to the name used for the executor
(field <code>credentialMapping</code>).

- <code>getCredentials(string) map[string]string</code>
If the second argument is given, it checks for the named property
in the credential set.

This functions provides the property set of the provided credentials.
- <code>getCredentials(string[,string]) map[string]string | string</code>

This functions provides the property set of the provided credentials.

If the second argument is given, it returns the named property in the
selected credential set.

If the property name is an asterisks (<code>*</code>) a single property
is expected, whose value is returned.

#### User Config vs Executor Config

Expand Down Expand Up @@ -240,7 +262,6 @@ definitions.


### The <code>toiExecutor</code> Resource

Instead of directly describing an image resource in the package file, it is
possible to refer to a resource of type toiExecutor. This
is a yaml file with the media type <code>application/x-yaml</code>,
Expand Down
Loading