Update osbuild/images to v0.41.0

Multiple blueprint fixes:

- Extend the blueprint service customizations to accept services to be
  masked.

- The `storage-path` and `container-transport` fields were removed in
  imagees 41.0 in order to simplify the way local storage containers are
  handled.
This commit is contained in:
Gianluca Zuccarelli 2024-02-28 14:57:33 +00:00 committed by Tomáš Hozza
parent 4e504f7905
commit f6b76cce31
50 changed files with 615 additions and 529 deletions

View file

@ -32,7 +32,7 @@ func (impl *ContainerResolveJobImpl) Run(job worker.Job) error {
resolver.AuthFilePath = impl.AuthFilePath
for _, s := range args.Specs {
resolver.Add(container.SourceSpec{s.Source, s.Name, nil, s.TLSVerify, nil, nil})
resolver.Add(container.SourceSpec{s.Source, s.Name, nil, s.TLSVerify, false})
}
specs, err := resolver.Finish()

8
go.mod
View file

@ -16,7 +16,7 @@ require (
github.com/Azure/go-autorest/autorest v0.11.29
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12
github.com/BurntSushi/toml v1.3.2
github.com/aws/aws-sdk-go v1.50.24
github.com/aws/aws-sdk-go v1.50.27
github.com/coreos/go-semver v0.3.1
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
github.com/deepmap/oapi-codegen v1.8.2
@ -26,7 +26,7 @@ require (
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
github.com/gophercloud/gophercloud v1.9.0
github.com/gophercloud/gophercloud v1.10.0
github.com/hashicorp/go-retryablehttp v0.7.5
github.com/jackc/pgtype v1.14.1
github.com/jackc/pgx/v4 v4.18.1
@ -36,7 +36,7 @@ require (
github.com/labstack/gommon v0.4.2
github.com/openshift-online/ocm-sdk-go v0.1.398
github.com/oracle/oci-go-sdk/v54 v54.0.0
github.com/osbuild/images v0.40.0
github.com/osbuild/images v0.41.0
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20231117174845-e969a9dc3cd1
github.com/osbuild/pulp-client v0.1.0
github.com/prometheus/client_golang v1.18.0
@ -50,7 +50,7 @@ require (
golang.org/x/oauth2 v0.17.0
golang.org/x/sync v0.6.0
golang.org/x/sys v0.17.0
google.golang.org/api v0.166.0
google.golang.org/api v0.167.0
)
require (

16
go.sum
View file

@ -76,8 +76,8 @@ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat6
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aws/aws-sdk-go v1.50.24 h1:3o2Pg7mOoVL0jv54vWtuafoZqAeEXLhm1tltWA2GcEw=
github.com/aws/aws-sdk-go v1.50.24/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.50.27 h1:96ifhrSuja+AzdP3W/T2337igqVQ2FcSIJYkk+0rCeA=
github.com/aws/aws-sdk-go v1.50.27/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@ -307,8 +307,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfF
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.12.1 h1:9F8GV9r9ztXyAi00gsMQHNoF51xPZm8uj1dpYt2ZETM=
github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc=
github.com/gophercloud/gophercloud v1.9.0 h1:zKvmHOmHuaZlnx9d2DJpEgbMxrGt/+CJ/bKOKQh9Xzo=
github.com/gophercloud/gophercloud v1.9.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gophercloud/gophercloud v1.10.0 h1:watRMsaMDlSLuLkpLeLSQ87yvcuwIajNg6A5uLcjoIU=
github.com/gophercloud/gophercloud v1.10.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
@ -503,8 +503,8 @@ github.com/openshift-online/ocm-sdk-go v0.1.398 h1:6C1mDcPxzG4jSduOaWixTTI5gSEO+
github.com/openshift-online/ocm-sdk-go v0.1.398/go.mod h1:tke8vKcE7eHKyRbkJv6qo4ljo919zhx04uyQTcgF5cQ=
github.com/oracle/oci-go-sdk/v54 v54.0.0 h1:CDLjeSejv2aDpElAJrhKpi6zvT/zhZCZuXchUUZ+LS4=
github.com/oracle/oci-go-sdk/v54 v54.0.0/go.mod h1:+t+yvcFGVp+3ZnztnyxqXfQDsMlq8U25faBLa+mqCMc=
github.com/osbuild/images v0.40.0 h1:aVlg1+0CiVY6ViuEAMjEIBXvXfTtbKGHHIgQ8N95YWE=
github.com/osbuild/images v0.40.0/go.mod h1:RyfQIjcdjGQ+wKcqLCd5KrCixO0xsDRaDYCgorPFVXk=
github.com/osbuild/images v0.41.0 h1:KYQnk00oubMr3QlUd2P9UAunZu8FQUrG8g8R3IbNqEI=
github.com/osbuild/images v0.41.0/go.mod h1:aBpF8Dc2e9MnZSwlAFGEDKHAHzHAqRqyXRWP4HV5Gyo=
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20231117174845-e969a9dc3cd1 h1:UFEJIcPa46W8gtWgOYzriRKYyy1t6SWL0BI7fPTuVvc=
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20231117174845-e969a9dc3cd1/go.mod h1:z+WA+dX6qMwc7fqY5jCzESDIlg4WR2sBQezxsoXv9Ik=
github.com/osbuild/pulp-client v0.1.0 h1:L0C4ezBJGTamN3BKdv+rKLuq/WxXJbsFwz/Hj7aEmJ8=
@ -816,8 +816,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
google.golang.org/api v0.166.0 h1:6m4NUwrZYhAaVIHZWxaKjw1L1vNAjtMwORmKRyEEo24=
google.golang.org/api v0.166.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA=
google.golang.org/api v0.167.0 h1:CKHrQD1BLRii6xdkatBDXyKzM0mkawt2QP+H3LtPmSE=
google.golang.org/api v0.167.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=

View file

@ -48,9 +48,8 @@ type Container struct {
Source string `json:"source,omitempty" toml:"source"`
Name string `json:"name,omitempty" toml:"name,omitempty"`
TLSVerify *bool `json:"tls-verify,omitempty" toml:"tls-verify,omitempty"`
ContainersTransport *string `json:"containers-transport,omitempty" toml:"containers-transport,omitempty"`
StoragePath *string `json:"source-path,omitempty" toml:"source-path,omitempty"`
TLSVerify *bool `json:"tls-verify,omitempty" toml:"tls-verify,omitempty"`
LocalStorage bool `json:"local-storage,omitempty" toml:"local-storage,omitempty"`
}
// DeepCopy returns a deep copy of the blueprint

View file

@ -109,6 +109,7 @@ type FirewallServicesCustomization struct {
type ServicesCustomization struct {
Enabled []string `json:"enabled,omitempty" toml:"enabled,omitempty"`
Disabled []string `json:"disabled,omitempty" toml:"disabled,omitempty"`
Masked []string `json:"masked,omitempty" toml:"masked,omitempty"`
}
type OpenSCAPCustomization struct {

View file

@ -228,6 +228,7 @@ func TestGetServices(t *testing.T) {
expectedServices := ServicesCustomization{
Enabled: []string{"cockpit", "osbuild-composer"},
Disabled: []string{"sshd", "ftp"},
Masked: []string{"firewalld"},
}
TestCustomizations := Customizations{
@ -238,6 +239,7 @@ func TestGetServices(t *testing.T) {
assert.ElementsMatch(t, expectedServices.Enabled, retServices.Enabled)
assert.ElementsMatch(t, expectedServices.Disabled, retServices.Disabled)
assert.ElementsMatch(t, expectedServices.Masked, retServices.Masked)
}
func TestError(t *testing.T) {

View file

@ -499,7 +499,7 @@ func TestBlueprintsCustomizationInfoToml(t *testing.T) {
],
"disabled": [
"telnet"
]
]
}
},
"services": {
@ -511,6 +511,9 @@ func TestBlueprintsCustomizationInfoToml(t *testing.T) {
"disabled": [
"postfix",
"telnetd"
],
"masked": [
"firewalld"
]
},
"user": [
@ -629,6 +632,7 @@ func TestBlueprintsCustomizationInfoToml(t *testing.T) {
Services: &blueprint.ServicesCustomization{
Enabled: []string{"sshd", "cockpit.socket", "httpd"},
Disabled: []string{"postfix", "telnetd"},
Masked: []string{"firewalld"},
},
Filesystem: []blueprint.FilesystemCustomization{
blueprint.FilesystemCustomization{

View file

@ -5,4 +5,4 @@ package aws
const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK
const SDKVersion = "1.50.24"
const SDKVersion = "1.50.27"

View file

@ -1,3 +1,13 @@
## v1.10.0 (2024-02-27)
* [GH-2893](https://github.com/gophercloud/gophercloud/pull/2893) [v1] authentication: Add WithContext functions
* [GH-2894](https://github.com/gophercloud/gophercloud/pull/2894) [v1] pager: Add WithContext functions
* [GH-2899](https://github.com/gophercloud/gophercloud/pull/2899) [v1] Authenticate with a clouds.yaml
* [GH-2917](https://github.com/gophercloud/gophercloud/pull/2917) [v1] Add ParseOption type to made clouds.Parse() more usable for optional With* funcs
* [GH-2924](https://github.com/gophercloud/gophercloud/pull/2924) [v1] build(deps): bump EmilienM/devstack-action from 0.11 to 0.14
* [GH-2933](https://github.com/gophercloud/gophercloud/pull/2933) [v1] Fix AllowReauth reauthentication
* [GH-2950](https://github.com/gophercloud/gophercloud/pull/2950) [v1] compute: Use volumeID, not attachmentID for volume attachments
## v1.9.0 (2024-02-02)
New features and improvements:

View file

@ -1,6 +1,7 @@
package openstack
import (
"context"
"fmt"
"reflect"
"strings"
@ -23,20 +24,18 @@ const (
v3 = "v3"
)
/*
NewClient prepares an unauthenticated ProviderClient instance.
Most users will probably prefer using the AuthenticatedClient function
instead.
This is useful if you wish to explicitly control the version of the identity
service that's used for authentication explicitly, for example.
A basic example of using this would be:
ao, err := openstack.AuthOptionsFromEnv()
provider, err := openstack.NewClient(ao.IdentityEndpoint)
client, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{})
*/
// NewClient prepares an unauthenticated ProviderClient instance.
// Most users will probably prefer using the AuthenticatedClient function
// instead.
//
// This is useful if you wish to explicitly control the version of the identity
// service that's used for authentication explicitly, for example.
//
// A basic example of using this would be:
//
// ao, err := openstack.AuthOptionsFromEnv()
// provider, err := openstack.NewClient(ao.IdentityEndpoint)
// client, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{})
func NewClient(endpoint string) (*gophercloud.ProviderClient, error) {
base, err := utils.BaseEndpoint(endpoint)
if err != nil {
@ -54,42 +53,45 @@ func NewClient(endpoint string) (*gophercloud.ProviderClient, error) {
return p, nil
}
/*
AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint
specified by the options, acquires a token, and returns a Provider Client
instance that's ready to operate.
If the full path to a versioned identity endpoint was specified (example:
http://example.com:5000/v3), that path will be used as the endpoint to query.
If a versionless endpoint was specified (example: http://example.com:5000/),
the endpoint will be queried to determine which versions of the identity service
are available, then chooses the most recent or most supported version.
Example:
ao, err := openstack.AuthOptionsFromEnv()
provider, err := openstack.AuthenticatedClient(ao)
client, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
})
*/
func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) {
// AuthenticatedClientWithContext logs in to an OpenStack cloud found at the identity endpoint
// specified by the options, acquires a token, and returns a Provider Client
// instance that's ready to operate.
//
// If the full path to a versioned identity endpoint was specified (example:
// http://example.com:5000/v3), that path will be used as the endpoint to query.
//
// If a versionless endpoint was specified (example: http://example.com:5000/),
// the endpoint will be queried to determine which versions of the identity service
// are available, then chooses the most recent or most supported version.
//
// Example:
//
// ao, err := openstack.AuthOptionsFromEnv()
// provider, err := openstack.AuthenticatedClientWithContext(ctx, ao)
// client, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{
// Region: os.Getenv("OS_REGION_NAME"),
// })
func AuthenticatedClientWithContext(ctx context.Context, options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) {
client, err := NewClient(options.IdentityEndpoint)
if err != nil {
return nil, err
}
err = Authenticate(client, options)
err = AuthenticateWithContext(ctx, client, options)
if err != nil {
return nil, err
}
return client, nil
}
// Authenticate or re-authenticate against the most recent identity service
// supported at the provided endpoint.
func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
// AuthenticatedClient is a compatibility wrapper around AuthenticatedClientWithContext
func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) {
return AuthenticatedClientWithContext(context.Background(), options)
}
// AuthenticateWithContext authenticates or re-authenticates against the most
// recent identity service supported at the provided endpoint.
func AuthenticateWithContext(ctx context.Context, client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
versions := []*utils.Version{
{ID: v2, Priority: 20, Suffix: "/v2.0/"},
{ID: v3, Priority: 30, Suffix: "/v3/"},
@ -102,21 +104,31 @@ func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOp
switch chosen.ID {
case v2:
return v2auth(client, endpoint, options, gophercloud.EndpointOpts{})
return v2auth(ctx, client, endpoint, options, gophercloud.EndpointOpts{})
case v3:
return v3auth(client, endpoint, &options, gophercloud.EndpointOpts{})
return v3auth(ctx, client, endpoint, &options, gophercloud.EndpointOpts{})
default:
// The switch statement must be out of date from the versions list.
return fmt.Errorf("Unrecognized identity version: %s", chosen.ID)
}
}
// AuthenticateV2 explicitly authenticates against the identity v2 endpoint.
func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
return v2auth(client, "", options, eo)
// Authenticate is a compatibility wrapper around AuthenticateWithContext.
func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
return AuthenticateWithContext(context.Background(), client, options)
}
func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
// AuthenticateV2WithContext explicitly authenticates against the identity v2 endpoint.
func AuthenticateV2WithContext(ctx context.Context, client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
return v2auth(ctx, client, "", options, eo)
}
// AuthenticateV2 is a compatibility wrapper around AuthenticateV2WithContext.
func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
return AuthenticateV2WithContext(context.Background(), client, options, eo)
}
func v2auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
v2Client, err := NewIdentityV2(client, eo)
if err != nil {
return err
@ -136,7 +148,7 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
TokenID: options.TokenID,
}
result := tokens2.Create(v2Client, v2Opts)
result := tokens2.CreateWithContext(ctx, v2Client, v2Opts)
err = client.SetTokenAndAuthResult(result)
if err != nil {
@ -159,7 +171,7 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
tao := options
tao.AllowReauth = false
client.ReauthFunc = func() error {
err := v2auth(&tac, endpoint, tao, eo)
err := v2auth(context.Background(), &tac, endpoint, tao, eo)
if err != nil {
return err
}
@ -174,12 +186,17 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
return nil
}
// AuthenticateV3 explicitly authenticates against the identity v3 service.
func AuthenticateV3(client *gophercloud.ProviderClient, options tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error {
return v3auth(client, "", options, eo)
// AuthenticateV3WithContext explicitly authenticates against the identity v3 service.
func AuthenticateV3WithContext(ctx context.Context, client *gophercloud.ProviderClient, options tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error {
return v3auth(ctx, client, "", options, eo)
}
func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error {
// AuthenticateV3 is a compatibility wrapper around AuthenticateV3WithContext
func AuthenticateV3(client *gophercloud.ProviderClient, options tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error {
return AuthenticateV3WithContext(context.Background(), client, options, eo)
}
func v3auth(ctx context.Context, client *gophercloud.ProviderClient, endpoint string, opts tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error {
// Override the generated service endpoint with the one returned by the version endpoint.
v3Client, err := NewIdentityV3(client, eo)
if err != nil {
@ -229,11 +246,11 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au
var result tokens3.CreateResult
switch opts.(type) {
case *ec2tokens.AuthOptions:
result = ec2tokens.Create(v3Client, opts)
result = ec2tokens.CreateWithContext(ctx, v3Client, opts)
case *oauth1.AuthOptions:
result = oauth1.Create(v3Client, opts)
result = oauth1.CreateWithContext(ctx, v3Client, opts)
default:
result = tokens3.Create(v3Client, opts)
result = tokens3.CreateWithContext(ctx, v3Client, opts)
}
err = client.SetTokenAndAuthResult(result)
@ -277,7 +294,7 @@ func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.Au
tao = opts
}
client.ReauthFunc = func() error {
err := v3auth(&tac, endpoint, tao, eo)
err := v3auth(context.Background(), &tac, endpoint, tao, eo)
if err != nil {
return err
}

View file

@ -1,6 +1,10 @@
package tokens
import "github.com/gophercloud/gophercloud"
import (
"context"
"github.com/gophercloud/gophercloud"
)
// PasswordCredentialsV2 represents the required options to authenticate
// with a username and password.
@ -77,17 +81,17 @@ func (opts AuthOptions) ToTokenV2CreateMap() (map[string]interface{}, error) {
return b, nil
}
// Create authenticates to the identity service and attempts to acquire a Token.
// CreateWithContext authenticates to the identity service and attempts to acquire a Token.
// Generally, rather than interact with this call directly, end users should
// call openstack.AuthenticatedClient(), which abstracts all of the gory details
// about navigating service catalogs and such.
func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) {
func CreateWithContext(ctx context.Context, client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) {
b, err := auth.ToTokenV2CreateMap()
if err != nil {
r.Err = err
return
}
resp, err := client.Post(CreateURL(client), b, &r.Body, &gophercloud.RequestOpts{
resp, err := client.PostWithContext(ctx, CreateURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 203},
OmitHeaders: []string{"X-Auth-Token"},
})
@ -95,11 +99,21 @@ func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r Creat
return
}
// Get validates and retrieves information for user's token.
func Get(client *gophercloud.ServiceClient, token string) (r GetResult) {
// Create is a compatibility wrapper around CreateWithContext
func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) {
return CreateWithContext(context.Background(), client, auth)
}
// GetWithContext validates and retrieves information for user's token.
func GetWithContext(ctx context.Context, client *gophercloud.ServiceClient, token string) (r GetResult) {
resp, err := client.Get(GetURL(client, token), &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 203},
})
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
// Get is a compatibility wrapper around GetWithContext
func Get(client *gophercloud.ServiceClient, token string) (r GetResult) {
return GetWithContext(context.Background(), client, token)
}

View file

@ -1,6 +1,7 @@
package ec2tokens
import (
"context"
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
@ -287,8 +288,8 @@ func (opts *AuthOptions) ToTokenV3CreateMap(map[string]interface{}) (map[string]
return b, nil
}
// Create authenticates and either generates a new token from EC2 credentials
func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) {
// CreateWithContext authenticates and either generates a new token from EC2 credentials
func CreateWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) {
b, err := opts.ToTokenV3CreateMap(nil)
if err != nil {
r.Err = err
@ -298,7 +299,7 @@ func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tok
// delete "token" element, since it is used in s3tokens
deleteBodyElements(b, "token")
resp, err := c.Post(ec2tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{
resp, err := c.PostWithContext(ctx, ec2tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{
MoreHeaders: map[string]string{"X-Auth-Token": ""},
OkCodes: []int{200},
})
@ -306,9 +307,15 @@ func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tok
return
}
// ValidateS3Token authenticates an S3 request using EC2 credentials. Doesn't
// generate a new token ID, but returns a tokens.CreateResult.
func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) {
// Create is a compatibility wrapper around CreateWithContext
func Create(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) {
return CreateWithContext(context.Background(), c, opts)
}
// ValidateS3TokenWithContext authenticates an S3 request using EC2
// credentials. Doesn't generate a new token ID, but returns a
// tokens.CreateResult.
func ValidateS3TokenWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) {
b, err := opts.ToTokenV3CreateMap(nil)
if err != nil {
r.Err = err
@ -318,7 +325,7 @@ func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilde
// delete unused element, since it is used in ec2tokens only
deleteBodyElements(b, "body_hash", "headers", "host", "params", "path", "verb")
resp, err := c.Post(s3tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{
resp, err := c.PostWithContext(ctx, s3tokensURL(c), b, &r.Body, &gophercloud.RequestOpts{
MoreHeaders: map[string]string{"X-Auth-Token": ""},
OkCodes: []int{200},
})
@ -326,6 +333,11 @@ func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilde
return
}
// ValidateS3Token is a compatibility wrapper around ValidateS3TokenWithContext
func ValidateS3Token(c *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) {
return ValidateS3TokenWithContext(context.Background(), c, opts)
}
// The following are small helper functions used to help build the signature.
// sumHMAC1 is a func to implement the HMAC SHA1 signature method.

View file

@ -1,6 +1,7 @@
package oauth1
import (
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
@ -133,9 +134,9 @@ func (opts AuthOptions) ToTokenV3CreateMap(map[string]interface{}) (map[string]i
return gophercloud.BuildRequestBody(req, "")
}
// Create authenticates and either generates a new OpenStack token from an
// OAuth1 token.
func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) {
// CreateWithContext authenticates and either generates a new OpenStack token
// from an OAuth1 token.
func CreateWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) {
b, err := opts.ToTokenV3CreateMap(nil)
if err != nil {
r.Err = err
@ -153,7 +154,7 @@ func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (
return
}
resp, err := client.Post(authURL(client), b, &r.Body, &gophercloud.RequestOpts{
resp, err := client.PostWithContext(ctx, authURL(client), b, &r.Body, &gophercloud.RequestOpts{
MoreHeaders: h,
OkCodes: []int{201},
})
@ -161,6 +162,11 @@ func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (
return
}
// Create is a compatibility wrapper around CreateWithContext.
func Create(client *gophercloud.ServiceClient, opts tokens.AuthOptionsBuilder) (r tokens.CreateResult) {
return CreateWithContext(context.Background(), client, opts)
}
// CreateConsumerOptsBuilder allows extensions to add additional parameters to
// the CreateConsumer request.
type CreateConsumerOptsBuilder interface {
@ -178,27 +184,37 @@ func (opts CreateConsumerOpts) ToOAuth1CreateConsumerMap() (map[string]interface
return gophercloud.BuildRequestBody(opts, "consumer")
}
// Create creates a new Consumer.
func CreateConsumer(client *gophercloud.ServiceClient, opts CreateConsumerOptsBuilder) (r CreateConsumerResult) {
// CreateConsumerWithContext creates a new Consumer.
func CreateConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts CreateConsumerOptsBuilder) (r CreateConsumerResult) {
b, err := opts.ToOAuth1CreateConsumerMap()
if err != nil {
r.Err = err
return
}
resp, err := client.Post(consumersURL(client), b, &r.Body, &gophercloud.RequestOpts{
resp, err := client.PostWithContext(ctx, consumersURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{201},
})
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
// Delete deletes a Consumer.
func DeleteConsumer(client *gophercloud.ServiceClient, id string) (r DeleteConsumerResult) {
resp, err := client.Delete(consumerURL(client, id), nil)
// CreateConsumer is a compatibility wrapper around CreateConsumerWithContext.
func CreateConsumer(client *gophercloud.ServiceClient, opts CreateConsumerOptsBuilder) (r CreateConsumerResult) {
return CreateConsumerWithContext(context.Background(), client, opts)
}
// DeleteConsumerWithContext deletes a Consumer.
func DeleteConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string) (r DeleteConsumerResult) {
resp, err := client.DeleteWithContext(ctx, consumerURL(client, id), nil)
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
// DeleteConsumer is a compatibility wrapper around DeleteConsumerWithContext.
func DeleteConsumer(client *gophercloud.ServiceClient, id string) (r DeleteConsumerResult) {
return DeleteConsumerWithContext(context.Background(), client, id)
}
// List enumerates Consumers.
func ListConsumers(client *gophercloud.ServiceClient) pagination.Pager {
return pagination.NewPager(client, consumersURL(client), func(r pagination.PageResult) pagination.Page {
@ -206,13 +222,18 @@ func ListConsumers(client *gophercloud.ServiceClient) pagination.Pager {
})
}
// GetConsumer retrieves details on a single Consumer by ID.
func GetConsumer(client *gophercloud.ServiceClient, id string) (r GetConsumerResult) {
resp, err := client.Get(consumerURL(client, id), &r.Body, nil)
// GetConsumerWithContext retrieves details on a single Consumer by ID.
func GetConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetConsumerResult) {
resp, err := client.GetWithContext(ctx, consumerURL(client, id), &r.Body, nil)
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
// GetConsumer is a compatibility wrapper around GetConsumerWithContext.
func GetConsumer(client *gophercloud.ServiceClient, id string) (r GetConsumerResult) {
return GetConsumerWithContext(context.Background(), client, id)
}
// UpdateConsumerOpts provides options used to update a consumer.
type UpdateConsumerOpts struct {
// Description is the consumer description.
@ -225,20 +246,25 @@ func (opts UpdateConsumerOpts) ToOAuth1UpdateConsumerMap() (map[string]interface
return gophercloud.BuildRequestBody(opts, "consumer")
}
// UpdateConsumer updates an existing Consumer.
func UpdateConsumer(client *gophercloud.ServiceClient, id string, opts UpdateConsumerOpts) (r UpdateConsumerResult) {
// UpdateConsumerWithContext updates an existing Consumer.
func UpdateConsumerWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string, opts UpdateConsumerOpts) (r UpdateConsumerResult) {
b, err := opts.ToOAuth1UpdateConsumerMap()
if err != nil {
r.Err = err
return
}
resp, err := client.Patch(consumerURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
resp, err := client.PatchWithContext(ctx, consumerURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
// UpdateConsumer is a compatibility wrapper around UpdateConsumerWithContext.
func UpdateConsumer(client *gophercloud.ServiceClient, id string, opts UpdateConsumerOpts) (r UpdateConsumerResult) {
return UpdateConsumerWithContext(context.Background(), client, id, opts)
}
// RequestTokenOptsBuilder allows extensions to add additional parameters to the
// RequestToken request.
type RequestTokenOptsBuilder interface {
@ -297,15 +323,15 @@ func (opts RequestTokenOpts) ToOAuth1RequestTokenHeaders(method, u string) (map[
return h, nil
}
// RequestToken requests an unauthorized OAuth1 Token.
func RequestToken(client *gophercloud.ServiceClient, opts RequestTokenOptsBuilder) (r TokenResult) {
// RequestTokenWithContext requests an unauthorized OAuth1 Token.
func RequestTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts RequestTokenOptsBuilder) (r TokenResult) {
h, err := opts.ToOAuth1RequestTokenHeaders("POST", requestTokenURL(client))
if err != nil {
r.Err = err
return
}
resp, err := client.Post(requestTokenURL(client), nil, nil, &gophercloud.RequestOpts{
resp, err := client.PostWithContext(ctx, requestTokenURL(client), nil, nil, &gophercloud.RequestOpts{
MoreHeaders: h,
OkCodes: []int{201},
KeepResponseBody: true,
@ -323,6 +349,11 @@ func RequestToken(client *gophercloud.ServiceClient, opts RequestTokenOptsBuilde
return
}
// RequestToken is a compatibility wrapper around RequestTokenWithContext.
func RequestToken(client *gophercloud.ServiceClient, opts RequestTokenOptsBuilder) (r TokenResult) {
return RequestTokenWithContext(context.Background(), client, opts)
}
// AuthorizeTokenOptsBuilder allows extensions to add additional parameters to
// the AuthorizeToken request.
type AuthorizeTokenOptsBuilder interface {
@ -351,20 +382,25 @@ func (opts AuthorizeTokenOpts) ToOAuth1AuthorizeTokenMap() (map[string]interface
return gophercloud.BuildRequestBody(opts, "")
}
// AuthorizeToken authorizes an unauthorized consumer token.
func AuthorizeToken(client *gophercloud.ServiceClient, id string, opts AuthorizeTokenOptsBuilder) (r AuthorizeTokenResult) {
// AuthorizeTokenWithContext authorizes an unauthorized consumer token.
func AuthorizeTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, id string, opts AuthorizeTokenOptsBuilder) (r AuthorizeTokenResult) {
b, err := opts.ToOAuth1AuthorizeTokenMap()
if err != nil {
r.Err = err
return
}
resp, err := client.Put(authorizeTokenURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
resp, err := client.PutWithContext(ctx, authorizeTokenURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
// AuthorizeToken is a compatibility wrapper around AuthorizeTokenWithContext.
func AuthorizeToken(client *gophercloud.ServiceClient, id string, opts AuthorizeTokenOptsBuilder) (r AuthorizeTokenResult) {
return AuthorizeTokenWithContext(context.Background(), client, id, opts)
}
// CreateAccessTokenOptsBuilder allows extensions to add additional parameters
// to the CreateAccessToken request.
type CreateAccessTokenOptsBuilder interface {
@ -425,15 +461,15 @@ func (opts CreateAccessTokenOpts) ToOAuth1CreateAccessTokenHeaders(method, u str
return headers, nil
}
// CreateAccessToken creates a new OAuth1 Access Token
func CreateAccessToken(client *gophercloud.ServiceClient, opts CreateAccessTokenOptsBuilder) (r TokenResult) {
// CreateAccessTokenWithContext creates a new OAuth1 Access Token
func CreateAccessTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, opts CreateAccessTokenOptsBuilder) (r TokenResult) {
h, err := opts.ToOAuth1CreateAccessTokenHeaders("POST", createAccessTokenURL(client))
if err != nil {
r.Err = err
return
}
resp, err := client.Post(createAccessTokenURL(client), nil, nil, &gophercloud.RequestOpts{
resp, err := client.PostWithContext(ctx, createAccessTokenURL(client), nil, nil, &gophercloud.RequestOpts{
MoreHeaders: h,
OkCodes: []int{201},
KeepResponseBody: true,
@ -451,20 +487,35 @@ func CreateAccessToken(client *gophercloud.ServiceClient, opts CreateAccessToken
return
}
// GetAccessToken retrieves details on a single OAuth1 access token by an ID.
func GetAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r GetAccessTokenResult) {
resp, err := client.Get(userAccessTokenURL(client, userID, id), &r.Body, nil)
// CreateAccessToken is a compatibility wrapper around CreateAccessTokenWithContext.
func CreateAccessToken(client *gophercloud.ServiceClient, opts CreateAccessTokenOptsBuilder) (r TokenResult) {
return CreateAccessTokenWithContext(context.Background(), client, opts)
}
// GetAccessTokenWithContext retrieves details on a single OAuth1 access token by an ID.
func GetAccessTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, userID string, id string) (r GetAccessTokenResult) {
resp, err := client.GetWithContext(ctx, userAccessTokenURL(client, userID, id), &r.Body, nil)
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
// RevokeAccessToken revokes an OAuth1 access token.
func RevokeAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r RevokeAccessTokenResult) {
resp, err := client.Delete(userAccessTokenURL(client, userID, id), nil)
// GetAccessToken is a compatibility wrapper around GetAccessTokenWithContext.
func GetAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r GetAccessTokenResult) {
return GetAccessTokenWithContext(context.Background(), client, userID, id)
}
// RevokeAccessTokenWithContext revokes an OAuth1 access token.
func RevokeAccessTokenWithContext(ctx context.Context, client *gophercloud.ServiceClient, userID string, id string) (r RevokeAccessTokenResult) {
resp, err := client.DeleteWithContext(ctx, userAccessTokenURL(client, userID, id), nil)
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
// RevokeAccessToken is a compatibility wrapper around RevokeAccessTokenWithContext.
func RevokeAccessToken(client *gophercloud.ServiceClient, userID string, id string) (r RevokeAccessTokenResult) {
return RevokeAccessTokenWithContext(context.Background(), client, userID, id)
}
// ListAccessTokens enumerates authorized access tokens.
func ListAccessTokens(client *gophercloud.ServiceClient, userID string) pagination.Pager {
url := userAccessTokensURL(client, userID)
@ -481,14 +532,19 @@ func ListAccessTokenRoles(client *gophercloud.ServiceClient, userID string, id s
})
}
// GetAccessTokenRole retrieves details on a single OAuth1 access token role by
// GetAccessTokenRoleWithContext retrieves details on a single OAuth1 access token role by
// an ID.
func GetAccessTokenRole(client *gophercloud.ServiceClient, userID string, id string, roleID string) (r GetAccessTokenRoleResult) {
resp, err := client.Get(userAccessTokenRoleURL(client, userID, id, roleID), &r.Body, nil)
func GetAccessTokenRoleWithContext(ctx context.Context, client *gophercloud.ServiceClient, userID string, id string, roleID string) (r GetAccessTokenRoleResult) {
resp, err := client.GetWithContext(ctx, userAccessTokenRoleURL(client, userID, id, roleID), &r.Body, nil)
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
// GetAccessTokenRole is a compatibility wrapper around GetAccessTokenRoleWithContext.
func GetAccessTokenRole(client *gophercloud.ServiceClient, userID string, id string, roleID string) (r GetAccessTokenRoleResult) {
return GetAccessTokenRoleWithContext(context.Background(), client, userID, id, roleID)
}
// The following are small helper functions used to help build the signature.
// buildOAuth1QueryString builds a URLEncoded parameters string specific for

View file

@ -1,6 +1,10 @@
package tokens
import "github.com/gophercloud/gophercloud"
import (
"context"
"github.com/gophercloud/gophercloud"
)
// Scope allows a created token to be limited to a specific domain or project.
type Scope struct {
@ -119,9 +123,9 @@ func subjectTokenHeaders(subjectToken string) map[string]string {
}
}
// Create authenticates and either generates a new token, or changes the Scope
// CreateWithContext authenticates and either generates a new token, or changes the Scope
// of an existing token.
func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) {
func CreateWithContext(ctx context.Context, c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) {
scope, err := opts.ToTokenV3ScopeMap()
if err != nil {
r.Err = err
@ -134,16 +138,21 @@ func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResu
return
}
resp, err := c.Post(tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{
resp, err := c.PostWithContext(ctx, tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{
OmitHeaders: []string{"X-Auth-Token"},
})
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
// Get validates and retrieves information about another token.
func Get(c *gophercloud.ServiceClient, token string) (r GetResult) {
resp, err := c.Get(tokenURL(c), &r.Body, &gophercloud.RequestOpts{
// Create is a compatibility wrapper around CreateWithContext
func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) {
return CreateWithContext(context.Background(), c, opts)
}
// GetGetWithContext validates and retrieves information about another token.
func GetWithContext(ctx context.Context, c *gophercloud.ServiceClient, token string) (r GetResult) {
resp, err := c.GetWithContext(ctx, tokenURL(c), &r.Body, &gophercloud.RequestOpts{
MoreHeaders: subjectTokenHeaders(token),
OkCodes: []int{200, 203},
})
@ -151,9 +160,14 @@ func Get(c *gophercloud.ServiceClient, token string) (r GetResult) {
return
}
// Validate determines if a specified token is valid or not.
func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
resp, err := c.Head(tokenURL(c), &gophercloud.RequestOpts{
// Get is a compatibility wrapper around GetWithContext
func Get(c *gophercloud.ServiceClient, token string) (r GetResult) {
return GetWithContext(context.Background(), c, token)
}
// ValidateWithContext determines if a specified token is valid or not.
func ValidateWithContext(ctx context.Context, c *gophercloud.ServiceClient, token string) (bool, error) {
resp, err := c.HeadWithContext(ctx, tokenURL(c), &gophercloud.RequestOpts{
MoreHeaders: subjectTokenHeaders(token),
OkCodes: []int{200, 204, 404},
})
@ -164,11 +178,21 @@ func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
return resp.StatusCode == 200 || resp.StatusCode == 204, nil
}
// Revoke immediately makes specified token invalid.
func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) {
resp, err := c.Delete(tokenURL(c), &gophercloud.RequestOpts{
// Validate is a compatibility wrapper around ValidateWithContext
func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
return ValidateWithContext(context.Background(), c, token)
}
// RevokeWithContext immediately makes specified token invalid.
func RevokeWithContext(ctx context.Context, c *gophercloud.ServiceClient, token string) (r RevokeResult) {
resp, err := c.DeleteWithContext(ctx, tokenURL(c), &gophercloud.RequestOpts{
MoreHeaders: subjectTokenHeaders(token),
})
_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
return
}
// Revoke is a compatibility wrapper around RevokeWithContext
func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) {
return RevokeWithContext(context.Background(), c, token)
}

View file

@ -1,6 +1,7 @@
package pagination
import (
"context"
"encoding/json"
"io/ioutil"
"net/http"
@ -52,11 +53,16 @@ func PageResultFromParsed(resp *http.Response, body interface{}) PageResult {
}
}
// Request performs an HTTP request and extracts the http.Response from the result.
func Request(client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) {
return client.Get(url, nil, &gophercloud.RequestOpts{
// RequestWithContext performs an HTTP request and extracts the http.Response from the result.
func RequestWithContext(ctx context.Context, client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) {
return client.GetWithContext(ctx, url, nil, &gophercloud.RequestOpts{
MoreHeaders: headers,
OkCodes: []int{200, 204, 300},
KeepResponseBody: true,
})
}
// Request is a compatibility wrapper around RequestWithContext.
func Request(client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) {
return RequestWithContext(context.Background(), client, headers, url)
}

View file

@ -1,6 +1,7 @@
package pagination
import (
"context"
"errors"
"fmt"
"net/http"
@ -69,8 +70,8 @@ func (p Pager) WithPageCreator(createPage func(r PageResult) Page) Pager {
}
}
func (p Pager) fetchNextPage(url string) (Page, error) {
resp, err := Request(p.client, p.Headers, url)
func (p Pager) fetchNextPage(ctx context.Context, url string) (Page, error) {
resp, err := RequestWithContext(ctx, p.client, p.Headers, url)
if err != nil {
return nil, err
}
@ -83,9 +84,10 @@ func (p Pager) fetchNextPage(url string) (Page, error) {
return p.createPage(remembered), nil
}
// EachPage iterates over each page returned by a Pager, yielding one at a time to a handler function.
// Return "false" from the handler to prematurely stop iterating.
func (p Pager) EachPage(handler func(Page) (bool, error)) error {
// EachPageWithContext iterates over each page returned by a Pager, yielding
// one at a time to a handler function. Return "false" from the handler to
// prematurely stop iterating.
func (p Pager) EachPageWithContext(ctx context.Context, handler func(context.Context, Page) (bool, error)) error {
if p.Err != nil {
return p.Err
}
@ -99,7 +101,7 @@ func (p Pager) EachPage(handler func(Page) (bool, error)) error {
p.firstPage = nil
} else {
var err error
currentPage, err = p.fetchNextPage(currentURL)
currentPage, err = p.fetchNextPage(ctx, currentURL)
if err != nil {
return err
}
@ -113,7 +115,7 @@ func (p Pager) EachPage(handler func(Page) (bool, error)) error {
return nil
}
ok, err := handler(currentPage)
ok, err := handler(ctx, currentPage)
if err != nil {
return err
}
@ -131,9 +133,16 @@ func (p Pager) EachPage(handler func(Page) (bool, error)) error {
}
}
// AllPages returns all the pages from a `List` operation in a single page,
// EachPage is a compatibility wrapper around EachPageWithContext.
func (p Pager) EachPage(handler func(Page) (bool, error)) error {
return p.EachPageWithContext(context.Background(), func(_ context.Context, p Page) (bool, error) {
return handler(p)
})
}
// AllPagesWithContext returns all the pages from a `List` operation in a single page,
// allowing the user to retrieve all the pages at once.
func (p Pager) AllPages() (Page, error) {
func (p Pager) AllPagesWithContext(ctx context.Context) (Page, error) {
if p.Err != nil {
return nil, p.Err
}
@ -143,7 +152,7 @@ func (p Pager) AllPages() (Page, error) {
var body reflect.Value
// Grab a first page to ascertain the page body type.
firstPage, err := p.fetchNextPage(p.initialURL)
firstPage, err := p.fetchNextPage(ctx, p.initialURL)
if err != nil {
return nil, err
}
@ -252,3 +261,8 @@ func (p Pager) AllPages() (Page, error) {
// `Extract*` methods will work.
return page.Elem().Interface().(Page), err
}
// AllPages is a compatibility wrapper around AllPagesWithContext.
func (p Pager) AllPages() (Page, error) {
return p.AllPagesWithContext(context.Background())
}

View file

@ -16,7 +16,7 @@ import (
// DefaultUserAgent is the default User-Agent string set in the request header.
const (
DefaultUserAgent = "gophercloud/v1.9.0"
DefaultUserAgent = "gophercloud/v1.10.0"
DefaultMaxBackoffRetries = 60
)

View file

@ -26,3 +26,7 @@ func VersionLessThan(a, b string) bool {
return aV.LessThan(bV)
}
func VersionGreaterThanOrEqual(a, b string) bool {
return !VersionLessThan(a, b)
}

View file

@ -1,13 +1,6 @@
// Package blueprint contains primitives for representing weldr blueprints
package blueprint
import "fmt"
const (
dockerTransport = "docker"
containersStorageTransport = "containers-storage"
)
// A Blueprint is a high-level description of an image.
type Blueprint struct {
Name string `json:"name" toml:"name"`
@ -36,12 +29,11 @@ type Group struct {
}
type Container struct {
Source string `json:"source,omitempty" toml:"source"`
Source string `json:"source" toml:"source"`
Name string `json:"name,omitempty" toml:"name,omitempty"`
TLSVerify *bool `json:"tls-verify,omitempty" toml:"tls-verify,omitempty"`
ContainersTransport *string `json:"containers-transport,omitempty" toml:"containers-transport,omitempty"`
StoragePath *string `json:"source-path,omitempty" toml:"source-path,omitempty"`
TLSVerify *bool `json:"tls-verify,omitempty" toml:"tls-verify,omitempty"`
LocalStorage bool `json:"local-storage,omitempty" toml:"local-storage,omitempty"`
}
// packages, modules, and groups all resolve to rpm packages right now. This
@ -79,31 +71,3 @@ func (p Package) ToNameVersion() string {
return p.Name + "-" + p.Version
}
func (c Container) Validate() error {
if c.StoragePath != nil {
if c.ContainersTransport == nil {
// error out here, but realistically we could also just
// set the transport instead
return fmt.Errorf("Cannot specify storage location %s without a transport", *c.StoragePath)
}
if *c.ContainersTransport != containersStorageTransport {
return fmt.Errorf(
"Incompatible transport %s for storage location %s, only containers-storage transport is supported",
*c.ContainersTransport,
*c.StoragePath,
)
}
}
if c.ContainersTransport == nil {
return nil
}
if *c.ContainersTransport != dockerTransport && *c.ContainersTransport != containersStorageTransport {
return fmt.Errorf("Unknown containers-transport: %s", *c.ContainersTransport)
}
return nil
}

View file

@ -108,6 +108,7 @@ type FirewallServicesCustomization struct {
type ServicesCustomization struct {
Enabled []string `json:"enabled,omitempty" toml:"enabled,omitempty"`
Disabled []string `json:"disabled,omitempty" toml:"disabled,omitempty"`
Masked []string `json:"masked,omitempty" toml:"masked,omitempty"`
}
type OpenSCAPCustomization struct {

View file

@ -35,9 +35,6 @@ import (
const (
DefaultUserAgent = "osbuild-composer/1.0"
DefaultPolicyPath = "/etc/containers/policy.json"
containersStorageTransport = "containers-storage"
dockerTransport = "docker"
)
// GetDefaultAuthFile returns the authentication file to use for the
@ -344,32 +341,17 @@ func (m RawManifest) Digest() (digest.Digest, error) {
return manifest.Digest(m.Data)
}
func getImageRef(target reference.Named, transport string, storagePath string) (types.ImageReference, error) {
switch transport {
case "", dockerTransport:
ref, err := docker.NewReference(target)
if err != nil {
return nil, err
}
return ref, nil
case containersStorageTransport:
var storage string
if storagePath != "" {
storage = fmt.Sprintf("[overlay@%s]", storagePath)
}
ref, err := alltransports.ParseImageName(fmt.Sprintf("%s:%s%s", transport, storage, target.Name()))
if err != nil {
return nil, err
}
return ref, nil
default:
return nil, fmt.Errorf("Unknown containers-transport: %s", transport)
func getImageRef(target reference.Named, local bool) (types.ImageReference, error) {
if local {
return alltransports.ParseImageName(fmt.Sprintf("containers-storage:%s", target))
}
return docker.NewReference(target)
}
// GetManifest fetches the raw manifest data from the server. If digest is not empty
// it will override any given tag for the Client's Target.
func (cl *Client) GetManifest(ctx context.Context, digest digest.Digest, container *SourceSpec) (r RawManifest, err error) {
func (cl *Client) GetManifest(ctx context.Context, digest digest.Digest, local bool) (r RawManifest, err error) {
target := cl.Target
if digest != "" {
@ -382,17 +364,7 @@ func (cl *Client) GetManifest(ctx context.Context, digest digest.Digest, contain
target = t
}
var transport string
if container != nil && container.ContainersTransport != nil {
transport = *container.ContainersTransport
}
var storagePath string
if container != nil && container.StoragePath != nil {
storagePath = *container.StoragePath
}
ref, err := getImageRef(target, transport, storagePath)
ref, err := getImageRef(target, local)
if err != nil {
return
}
@ -438,7 +410,7 @@ func (cl *Client) resolveManifestList(ctx context.Context, list manifestList) (r
return resolvedIds{}, err
}
raw, err := cl.GetManifest(ctx, digest, nil)
raw, err := cl.GetManifest(ctx, digest, false)
if err != nil {
return resolvedIds{}, fmt.Errorf("error getting manifest: %w", err)
}
@ -522,10 +494,9 @@ func (cl *Client) resolveRawManifest(ctx context.Context, rm RawManifest) (resol
// which is the digest of the configuration object. It uses the architecture and
// variant specified via SetArchitectureChoice or the corresponding defaults for
// the host.
func (cl *Client) Resolve(ctx context.Context, name string, container *SourceSpec) (Spec, error) {
raw, err := cl.GetManifest(ctx, "", container)
func (cl *Client) Resolve(ctx context.Context, name string, local bool) (Spec, error) {
raw, err := cl.GetManifest(ctx, "", local)
if err != nil {
return Spec{}, fmt.Errorf("error getting manifest: %w", err)
}
@ -535,13 +506,6 @@ func (cl *Client) Resolve(ctx context.Context, name string, container *SourceSpe
return Spec{}, err
}
var transport *string
var location *string
if container != nil {
transport = container.ContainersTransport
location = container.StoragePath
}
spec := NewSpec(
cl.Target,
ids.Manifest,
@ -549,8 +513,7 @@ func (cl *Client) Resolve(ctx context.Context, name string, container *SourceSpe
cl.GetTLSVerify(),
ids.ListManifest.String(),
name,
transport,
location,
local,
)
return spec, nil

View file

@ -23,12 +23,11 @@ type Resolver struct {
}
type SourceSpec struct {
Source string
Name string
Digest *string
TLSVerify *bool
ContainersTransport *string
StoragePath *string
Source string
Name string
Digest *string
TLSVerify *bool
Local bool
}
func NewResolver(arch string) *Resolver {
@ -55,7 +54,7 @@ func (r *Resolver) Add(spec SourceSpec) {
}
go func() {
spec, err := client.Resolve(r.ctx, spec.Name, &spec)
spec, err := client.Resolve(r.ctx, spec.Name, spec.Local)
if err != nil {
err = fmt.Errorf("'%s': %w", spec.Source, err)
}

View file

@ -11,31 +11,29 @@ import (
// at the Source via Digest and ImageID. The latter one
// should remain the same in the target image as well.
type Spec struct {
Source string // does not include the manifest digest
Digest string // digest of the manifest at the Source
TLSVerify *bool // controls TLS verification
ImageID string // container image identifier
LocalName string // name to use inside the image
ListDigest string // digest of the list manifest at the Source (optional)
ContainersTransport *string // the type of transport used for the container
StoragePath *string // location of the local containers-storage
Source string // does not include the manifest digest
Digest string // digest of the manifest at the Source
TLSVerify *bool // controls TLS verification
ImageID string // container image identifier
LocalName string // name to use inside the image
ListDigest string // digest of the list manifest at the Source (optional)
LocalStorage bool
}
// NewSpec creates a new Spec from the essential information.
// It also converts is the transition point from container
// specific types (digest.Digest) to generic types (string).
func NewSpec(source reference.Named, digest, imageID digest.Digest, tlsVerify *bool, listDigest string, localName string, transport *string, storagePath *string) Spec {
func NewSpec(source reference.Named, digest, imageID digest.Digest, tlsVerify *bool, listDigest string, localName string, localStorage bool) Spec {
if localName == "" {
localName = source.String()
}
return Spec{
Source: source.Name(),
Digest: digest.String(),
TLSVerify: tlsVerify,
ImageID: imageID.String(),
LocalName: localName,
ListDigest: listDigest,
ContainersTransport: transport,
StoragePath: storagePath,
Source: source.Name(),
Digest: digest.String(),
TLSVerify: tlsVerify,
ImageID: imageID.String(),
LocalName: localName,
ListDigest: listDigest,
LocalStorage: localStorage,
}
}

View file

@ -818,58 +818,56 @@ func newDistro(version int) distro.Distro {
minimalrawImgType,
)
if !common.VersionLessThan(rd.Releasever(), "38") {
// iot simplified installer was introduced in F38
x86_64.addImageTypes(
&platform.X86{
BasePlatform: platform.BasePlatform{
ImageFormat: platform.FORMAT_RAW,
FirmwarePackages: []string{
"grub2-efi-x64",
"grub2-efi-x64-cdboot",
"grub2-tools",
"grub2-tools-minimal",
"efibootmgr",
"shim-x64",
"brcmfmac-firmware",
"iwlwifi-dvm-firmware",
"iwlwifi-mvm-firmware",
"realtek-firmware",
"microcode_ctl",
},
// iot simplified installer was introduced in F38
x86_64.addImageTypes(
&platform.X86{
BasePlatform: platform.BasePlatform{
ImageFormat: platform.FORMAT_RAW,
FirmwarePackages: []string{
"grub2-efi-x64",
"grub2-efi-x64-cdboot",
"grub2-tools",
"grub2-tools-minimal",
"efibootmgr",
"shim-x64",
"brcmfmac-firmware",
"iwlwifi-dvm-firmware",
"iwlwifi-mvm-firmware",
"realtek-firmware",
"microcode_ctl",
},
BIOS: false,
UEFIVendor: "fedora",
},
iotSimplifiedInstallerImgType,
)
BIOS: false,
UEFIVendor: "fedora",
},
iotSimplifiedInstallerImgType,
)
aarch64.addImageTypes(
&platform.Aarch64{
BasePlatform: platform.BasePlatform{
FirmwarePackages: []string{
"arm-image-installer",
"bcm283x-firmware",
"grub2-efi-aa64",
"grub2-efi-aa64-cdboot",
"grub2-tools",
"grub2-tools-minimal",
"efibootmgr",
"shim-aa64",
"brcmfmac-firmware",
"iwlwifi-dvm-firmware",
"iwlwifi-mvm-firmware",
"realtek-firmware",
"uboot-images-armv8",
},
aarch64.addImageTypes(
&platform.Aarch64{
BasePlatform: platform.BasePlatform{
FirmwarePackages: []string{
"arm-image-installer",
"bcm283x-firmware",
"grub2-efi-aa64",
"grub2-efi-aa64-cdboot",
"grub2-tools",
"grub2-tools-minimal",
"efibootmgr",
"shim-aa64",
"brcmfmac-firmware",
"iwlwifi-dvm-firmware",
"iwlwifi-mvm-firmware",
"realtek-firmware",
"uboot-images-armv8",
},
UEFIVendor: "fedora",
},
iotSimplifiedInstallerImgType,
)
}
UEFIVendor: "fedora",
},
iotSimplifiedInstallerImgType,
)
if !common.VersionLessThan(rd.Releasever(), "39") {
if common.VersionGreaterThanOrEqual(rd.Releasever(), "39") {
// bootc was introduced in F39
x86_64.addImageTypes(
&platform.X86{

View file

@ -69,6 +69,7 @@ func osCustomizations(
osc.EnabledServices = imageConfig.EnabledServices
osc.DisabledServices = imageConfig.DisabledServices
osc.MaskedServices = imageConfig.MaskedServices
if imageConfig.DefaultTarget != nil {
osc.DefaultTarget = *imageConfig.DefaultTarget
}
@ -353,9 +354,8 @@ func imageInstallerImage(workload workload.Workload,
img.UnattendedKickstart = instCust.Unattended
}
// Enable anaconda-webui for Fedora > 38
distro := t.Arch().Distro()
if !common.VersionLessThan(distro.Releasever(), "38") {
if common.VersionGreaterThanOrEqual(distro.Releasever(), "39") {
img.AdditionalAnacondaModules = []string{
"org.fedoraproject.Anaconda.Modules.Security",
"org.fedoraproject.Anaconda.Modules.Timezone",
@ -369,8 +369,6 @@ func imageInstallerImage(workload workload.Workload,
// time since they might be running headless and a UI is
// unnecessary.
img.AdditionalKernelOpts = []string{"inst.text", "inst.noninteractive"}
} else {
img.AdditionalKernelOpts = []string{"inst.webui", "inst.webui.remote"}
}
}
img.AdditionalAnacondaModules = append(img.AdditionalAnacondaModules, "org.fedoraproject.Anaconda.Modules.Users")
@ -412,23 +410,23 @@ func iotCommitImage(workload workload.Workload,
img.Platform = t.platform
img.OSCustomizations = osCustomizations(t, packageSets[osPkgsKey], containers, bp.Customizations)
if !common.VersionLessThan(d.Releasever(), "38") {
// see https://github.com/ostreedev/ostree/issues/2840
img.OSCustomizations.Presets = []osbuild.Preset{
{
Name: "ignition-firstboot-complete.service",
State: osbuild.StateEnable,
},
{
Name: "coreos-ignition-write-issues.service",
State: osbuild.StateEnable,
},
{
Name: "fdo-client-linuxapp.service",
State: osbuild.StateEnable,
},
}
// see https://github.com/ostreedev/ostree/issues/2840
img.OSCustomizations.Presets = []osbuild.Preset{
{
Name: "ignition-firstboot-complete.service",
State: osbuild.StateEnable,
},
{
Name: "coreos-ignition-write-issues.service",
State: osbuild.StateEnable,
},
{
Name: "fdo-client-linuxapp.service",
State: osbuild.StateEnable,
},
}
img.Environment = t.environment
img.Workload = workload
img.OSTreeParent = parentCommit
@ -478,23 +476,23 @@ func iotContainerImage(workload workload.Workload,
d := t.arch.distro
img.Platform = t.platform
img.OSCustomizations = osCustomizations(t, packageSets[osPkgsKey], containers, bp.Customizations)
if !common.VersionLessThan(d.Releasever(), "38") {
// see https://github.com/ostreedev/ostree/issues/2840
img.OSCustomizations.Presets = []osbuild.Preset{
{
Name: "ignition-firstboot-complete.service",
State: osbuild.StateEnable,
},
{
Name: "coreos-ignition-write-issues.service",
State: osbuild.StateEnable,
},
{
Name: "fdo-client-linuxapp.service",
State: osbuild.StateEnable,
},
}
// see https://github.com/ostreedev/ostree/issues/2840
img.OSCustomizations.Presets = []osbuild.Preset{
{
Name: "ignition-firstboot-complete.service",
State: osbuild.StateEnable,
},
{
Name: "coreos-ignition-write-issues.service",
State: osbuild.StateEnable,
},
{
Name: "fdo-client-linuxapp.service",
State: osbuild.StateEnable,
},
}
img.ContainerLanguage = img.OSCustomizations.Language
img.Environment = t.environment
img.Workload = workload
@ -575,8 +573,6 @@ func iotImage(workload workload.Workload,
}
img := image.NewOSTreeDiskImageFromCommit(commit)
distro := t.Arch().Distro()
customizations := bp.Customizations
img.FIPS = customizations.GetFIPS()
img.Users = users.UsersFromBP(customizations.GetUsers())
@ -607,17 +603,15 @@ func iotImage(workload workload.Workload,
img.OSName = "fedora-iot"
img.LockRoot = true
if !common.VersionLessThan(distro.Releasever(), "38") {
img.KernelOptionsAppend = append(img.KernelOptionsAppend, "coreos.no_persist_ip")
switch img.Platform.GetImageFormat() {
case platform.FORMAT_RAW:
img.IgnitionPlatform = "metal"
if bpIgnition := customizations.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" {
img.KernelOptionsAppend = append(img.KernelOptionsAppend, "ignition.config.url="+bpIgnition.FirstBoot.ProvisioningURL)
}
case platform.FORMAT_QCOW2:
img.IgnitionPlatform = "qemu"
img.KernelOptionsAppend = append(img.KernelOptionsAppend, "coreos.no_persist_ip")
switch img.Platform.GetImageFormat() {
case platform.FORMAT_RAW:
img.IgnitionPlatform = "metal"
if bpIgnition := customizations.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" {
img.KernelOptionsAppend = append(img.KernelOptionsAppend, "ignition.config.url="+bpIgnition.FirstBoot.ProvisioningURL)
}
case platform.FORMAT_QCOW2:
img.IgnitionPlatform = "qemu"
}
if kopts := customizations.GetKernel(); kopts != nil && kopts.Append != "" {
@ -659,10 +653,8 @@ func iotSimplifiedInstallerImage(workload workload.Workload,
rawImg.KernelOptionsAppend = []string{"modprobe.blacklist=vc4"}
rawImg.Keyboard = "us"
rawImg.Locale = "C.UTF-8"
if !common.VersionLessThan(t.arch.distro.osVersion, "38") {
rawImg.SysrootReadOnly = true
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, "rw")
}
rawImg.SysrootReadOnly = true
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, "rw")
rawImg.Platform = t.platform
rawImg.Workload = workload
@ -672,12 +664,10 @@ func iotSimplifiedInstallerImage(workload workload.Workload,
rawImg.OSName = "fedora"
rawImg.LockRoot = true
if !common.VersionLessThan(t.arch.distro.osVersion, "38") {
rawImg.IgnitionPlatform = "metal"
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, "coreos.no_persist_ip")
if bpIgnition := customizations.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" {
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, "ignition.config.url="+bpIgnition.FirstBoot.ProvisioningURL)
}
rawImg.IgnitionPlatform = "metal"
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, "coreos.no_persist_ip")
if bpIgnition := customizations.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" {
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, "ignition.config.url="+bpIgnition.FirstBoot.ProvisioningURL)
}
// TODO: move generation into LiveImage

View file

@ -224,11 +224,10 @@ func (t *imageType) Manifest(bp *blueprint.Blueprint,
containerSources := make([]container.SourceSpec, len(bp.Containers))
for idx, cont := range bp.Containers {
containerSources[idx] = container.SourceSpec{
Source: cont.Source,
Name: cont.Name,
TLSVerify: cont.TLSVerify,
ContainersTransport: cont.ContainersTransport,
StoragePath: cont.StoragePath,
Source: cont.Source,
Name: cont.Name,
TLSVerify: cont.TLSVerify,
Local: cont.LocalStorage,
}
}
@ -262,14 +261,6 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp
return nil, fmt.Errorf("embedding containers is not supported for %s on %s", t.name, t.arch.distro.name)
}
if len(bp.Containers) > 0 {
for _, container := range bp.Containers {
if err := container.Validate(); err != nil {
return nil, err
}
}
}
if options.OSTree != nil {
if err := options.OSTree.Validate(); err != nil {
return nil, err

View file

@ -4,7 +4,6 @@ package fedora
import (
"fmt"
"strconv"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/arch"
@ -74,6 +73,9 @@ func vmdkCommonPackageSet(t *imageType) rpmmd.PackageSet {
func iotCommitPackageSet(t *imageType) rpmmd.PackageSet {
ps := rpmmd.PackageSet{
Include: []string{
"NetworkManager",
"NetworkManager-wifi",
"NetworkManager-wwan",
"aardvark-dns",
"atheros-firmware",
"attr",
@ -87,8 +89,8 @@ func iotCommitPackageSet(t *imageType) rpmmd.PackageSet {
"clevis-dracut",
"clevis-luks",
"clevis-pin-tpm2",
"containernetworking-plugins",
"container-selinux",
"containernetworking-plugins",
"coreutils",
"cracklib-dicts",
"criu",
@ -101,6 +103,8 @@ func iotCommitPackageSet(t *imageType) rpmmd.PackageSet {
"dracut-network",
"e2fsprogs",
"efibootmgr",
"fdo-client",
"fdo-owner-cli",
"fedora-iot-config",
"fedora-release-iot",
"firewalld",
@ -116,6 +120,7 @@ func iotCommitPackageSet(t *imageType) rpmmd.PackageSet {
"gzip",
"hostname",
"ignition",
"ignition-edge",
"ima-evm-utils",
"iproute",
"iputils",
@ -128,9 +133,6 @@ func iotCommitPackageSet(t *imageType) rpmmd.PackageSet {
"linux-firmware",
"lvm2",
"netavark",
"NetworkManager",
"NetworkManager-wifi",
"NetworkManager-wwan",
"nss-altfiles",
"openssh-clients",
"openssh-server",
@ -154,6 +156,7 @@ func iotCommitPackageSet(t *imageType) rpmmd.PackageSet {
"shadow-utils",
"skopeo",
"slirp4netns",
"ssh-key-dir",
"sssd-client",
"sudo",
"systemd",
@ -174,17 +177,6 @@ func iotCommitPackageSet(t *imageType) rpmmd.PackageSet {
},
}
if !common.VersionLessThan(t.arch.distro.osVersion, "38") {
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"fdo-client",
"fdo-owner-cli",
"ignition-edge",
"ssh-key-dir",
},
})
}
return ps
}
@ -498,13 +490,7 @@ func iotInstallerPackageSet(t *imageType) rpmmd.PackageSet {
// include anaconda packages
ps := anacondaPackageSet(t)
releasever := t.Arch().Distro().Releasever()
version, err := strconv.Atoi(releasever)
if err != nil {
panic("cannot convert releasever to int: " + err.Error())
}
if version >= 38 {
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "39") {
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"fedora-release-iot",
@ -545,8 +531,7 @@ func liveInstallerPackageSet(t *imageType) rpmmd.PackageSet {
},
}
// We want to generate a preview image when rawhide is built
if !common.VersionLessThan(t.arch.distro.osVersion, "39") {
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "39") {
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"anaconda-webui",
@ -560,14 +545,7 @@ func liveInstallerPackageSet(t *imageType) rpmmd.PackageSet {
func imageInstallerPackageSet(t *imageType) rpmmd.PackageSet {
ps := anacondaPackageSet(t)
releasever := t.Arch().Distro().Releasever()
version, err := strconv.Atoi(releasever)
if err != nil {
panic("cannot convert releasever to int: " + err.Error())
}
// We want to generate a preview image when rawhide is built
if version >= 38 {
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "39") {
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"anaconda-webui",

View file

@ -18,6 +18,7 @@ type ImageConfig struct {
Keyboard *osbuild.KeymapStageOptions
EnabledServices []string
DisabledServices []string
MaskedServices []string
DefaultTarget *string
Sysconfig []*osbuild.SysconfigStageOptions

View file

@ -63,6 +63,7 @@ func osCustomizations(
osc.EnabledServices = imageConfig.EnabledServices
osc.DisabledServices = imageConfig.DisabledServices
osc.MaskedServices = imageConfig.MaskedServices
if imageConfig.DefaultTarget != nil {
osc.DefaultTarget = *imageConfig.DefaultTarget
}

View file

@ -200,11 +200,10 @@ func (t *imageType) Manifest(bp *blueprint.Blueprint,
containerSources := make([]container.SourceSpec, len(bp.Containers))
for idx, cont := range bp.Containers {
containerSources[idx] = container.SourceSpec{
Source: cont.Source,
Name: cont.Name,
TLSVerify: cont.TLSVerify,
ContainersTransport: cont.ContainersTransport,
StoragePath: cont.StoragePath,
Source: cont.Source,
Name: cont.Name,
TLSVerify: cont.TLSVerify,
Local: cont.LocalStorage,
}
}

View file

@ -368,7 +368,7 @@ func ec2CommonPackageSet(t *imageType) rpmmd.PackageSet {
func rhelEc2CommonPackageSet(t *imageType) rpmmd.PackageSet {
ps := ec2CommonPackageSet(t)
// Include "redhat-cloud-client-configuration" on 8.7+ (COMPOSER-1804)
if !common.VersionLessThan(t.arch.distro.osVersion, "8.7") {
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "8.7") {
ps.Include = append(ps.Include, "redhat-cloud-client-configuration")
}
return ps

View file

@ -397,7 +397,7 @@ func newDistro(name string, minor int) *distribution {
)
if rd.isRHEL() {
if !common.VersionLessThan(rd.osVersion, "8.6") {
if common.VersionGreaterThanOrEqual(rd.osVersion, "8.6") {
// image types only available on 8.6 and later on RHEL
// These edge image types require FDO which aren't available on older versions
x86_64.addImageTypes(

View file

@ -71,6 +71,7 @@ func osCustomizations(
osc.EnabledServices = imageConfig.EnabledServices
osc.DisabledServices = imageConfig.DisabledServices
osc.MaskedServices = imageConfig.MaskedServices
if imageConfig.DefaultTarget != nil {
osc.DefaultTarget = *imageConfig.DefaultTarget
}

View file

@ -245,11 +245,10 @@ func (t *imageType) Manifest(bp *blueprint.Blueprint,
containerSources := make([]container.SourceSpec, len(bp.Containers))
for idx, cont := range bp.Containers {
containerSources[idx] = container.SourceSpec{
Source: cont.Source,
Name: cont.Name,
TLSVerify: cont.TLSVerify,
ContainersTransport: cont.ContainersTransport,
StoragePath: cont.StoragePath,
Source: cont.Source,
Name: cont.Name,
TLSVerify: cont.TLSVerify,
Local: cont.LocalStorage,
}
}
@ -296,14 +295,6 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp
return warnings, fmt.Errorf("embedding containers is not supported for %s on %s", t.name, t.arch.distro.name)
}
if len(bp.Containers) > 0 {
for _, container := range bp.Containers {
if err := container.Validate(); err != nil {
return nil, err
}
}
}
if options.OSTree != nil {
if err := options.OSTree.Validate(); err != nil {
return nil, err

View file

@ -356,7 +356,7 @@ func ec2CommonPackageSet(t *imageType) rpmmd.PackageSet {
func rhelEc2CommonPackageSet(t *imageType) rpmmd.PackageSet {
ps := ec2CommonPackageSet(t)
// Include "redhat-cloud-client-configuration" on 9.1+ (COMPOSER-1805)
if !common.VersionLessThan(t.arch.distro.osVersion, "9.1") {
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "9.1") {
ps.Include = append(ps.Include, "redhat-cloud-client-configuration")
}
return ps

View file

@ -589,7 +589,7 @@ func edgeCommitPackageSet(t *imageType) rpmmd.PackageSet {
ps = ps.Append(aarch64EdgeCommitPackageSet(t))
}
if !common.VersionLessThan(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
ps.Include = append(ps.Include, "ignition", "ignition-edge", "ssh-key-dir")
}

View file

@ -68,6 +68,7 @@ func osCustomizations(
osc.EnabledServices = imageConfig.EnabledServices
osc.DisabledServices = imageConfig.DisabledServices
osc.MaskedServices = imageConfig.MaskedServices
if imageConfig.DefaultTarget != nil {
osc.DefaultTarget = *imageConfig.DefaultTarget
}
@ -327,7 +328,7 @@ func edgeCommitImage(workload workload.Workload,
img.OSVersion = t.arch.distro.osVersion
img.Filename = t.Filename()
if !common.VersionLessThan(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
img.OSCustomizations.EnabledServices = append(img.OSCustomizations.EnabledServices, "ignition-firstboot-complete.service", "coreos-ignition-write-issues.service")
}
img.Environment = t.environment
@ -361,7 +362,7 @@ func edgeContainerImage(workload workload.Workload,
img.ExtraContainerPackages = packageSets[containerPkgsKey]
img.Filename = t.Filename()
if !common.VersionLessThan(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
img.OSCustomizations.EnabledServices = append(img.OSCustomizations.EnabledServices, "ignition-firstboot-complete.service", "coreos-ignition-write-issues.service")
}
@ -452,12 +453,12 @@ func edgeRawImage(workload workload.Workload,
}
img.Keyboard = "us"
img.Locale = "C.UTF-8"
if !common.VersionLessThan(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
img.SysrootReadOnly = true
img.KernelOptionsAppend = append(img.KernelOptionsAppend, "rw")
}
if !common.VersionLessThan(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
img.IgnitionPlatform = "metal"
img.KernelOptionsAppend = append(img.KernelOptionsAppend, "coreos.no_persist_ip")
if bpIgnition := customizations.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" {
@ -513,7 +514,7 @@ func edgeSimplifiedInstallerImage(workload workload.Workload,
rawImg.KernelOptionsAppend = []string{"modprobe.blacklist=vc4"}
rawImg.Keyboard = "us"
rawImg.Locale = "C.UTF-8"
if !common.VersionLessThan(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
rawImg.SysrootReadOnly = true
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, "rw")
}
@ -528,7 +529,7 @@ func edgeSimplifiedInstallerImage(workload workload.Workload,
rawImg.OSName = "redhat"
rawImg.LockRoot = true
if !common.VersionLessThan(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "9.2") || !t.arch.distro.isRHEL() {
rawImg.IgnitionPlatform = "metal"
rawImg.KernelOptionsAppend = append(rawImg.KernelOptionsAppend, "coreos.no_persist_ip")
if bpIgnition := customizations.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" {

View file

@ -250,11 +250,10 @@ func (t *imageType) Manifest(bp *blueprint.Blueprint,
containerSources := make([]container.SourceSpec, len(bp.Containers))
for idx, cont := range bp.Containers {
containerSources[idx] = container.SourceSpec{
Source: cont.Source,
Name: cont.Name,
TLSVerify: cont.TLSVerify,
ContainersTransport: cont.ContainersTransport,
StoragePath: cont.StoragePath,
Source: cont.Source,
Name: cont.Name,
TLSVerify: cont.TLSVerify,
Local: cont.LocalStorage,
}
}
@ -301,14 +300,6 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp
return warnings, fmt.Errorf("embedding containers is not supported for %s on %s", t.name, t.arch.distro.name)
}
if len(bp.Containers) > 0 {
for _, container := range bp.Containers {
if err := container.Validate(); err != nil {
return nil, err
}
}
}
if options.OSTree != nil {
if err := options.OSTree.Validate(); err != nil {
return nil, err

View file

@ -389,7 +389,7 @@ func (p *AnacondaInstallerISOTree) ostreeCommitStages() []*osbuild.Stage {
func (p *AnacondaInstallerISOTree) ostreeContainerStages() []*osbuild.Stage {
stages := make([]*osbuild.Stage, 0)
images := osbuild.NewContainersInputForSources([]container.Spec{*p.containerSpec})
image := osbuild.NewContainersInputForSingleSource(*p.containerSpec)
stages = append(stages, osbuild.NewMkdirStage(&osbuild.MkdirStageOptions{
Paths: []osbuild.MkdirStagePath{
@ -402,7 +402,7 @@ func (p *AnacondaInstallerISOTree) ostreeContainerStages() []*osbuild.Stage {
// copy the container in
stages = append(stages, osbuild.NewSkopeoStageWithOCI(
p.PayloadPath,
images,
image,
nil))
// do what we can in our kickstart stage
@ -439,13 +439,6 @@ func (p *AnacondaInstallerISOTree) ostreeContainerStages() []*osbuild.Stage {
// and what we can't do in a separate kickstart that we include
targetContainerTransport := "registry"
if p.containerSpec.ContainersTransport != nil {
targetContainerTransport = *p.containerSpec.ContainersTransport
}
// Canonicalize to registry, as that's what the bootc stack wants
if targetContainerTransport == "docker://" {
targetContainerTransport = "registry"
}
// Because osbuild core only supports a subset of options, we append to the
// base here with some more hardcoded defaults

View file

@ -1,6 +1,8 @@
package manifest
import (
"fmt"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree"
@ -225,14 +227,19 @@ func (p *BuildrootFromContainer) serialize() osbuild.Pipeline {
if len(p.containerSpecs) == 0 {
panic("serialization not started")
}
if len(p.containerSpecs) != 1 {
panic(fmt.Sprintf("BuildrootFromContainer expectes exactly one container input, got: %v", p.containerSpecs))
}
pipeline := p.Base.serialize()
pipeline.Runner = p.runner.String()
inputs := osbuild.NewContainersInputForSources(p.containerSpecs)
image := osbuild.NewContainersInputForSingleSource(p.containerSpecs[0])
options := &osbuild.ContainerDeployOptions{
Exclude: []string{"/sysroot"},
}
stage, err := osbuild.NewContainerDeployStage(inputs, options)
stage, err := osbuild.NewContainerDeployStage(image, options)
if err != nil {
panic(err)
}

View file

@ -77,6 +77,7 @@ type OSCustomizations struct {
Timezone string
EnabledServices []string
DisabledServices []string
MaskedServices []string
DefaultTarget string
// SELinux policy, when set it enables the labeling of the tree with the
@ -405,21 +406,14 @@ func (p *OS) serialize() osbuild.Pipeline {
}
if len(p.containerSpecs) > 0 {
images := osbuild.NewContainersInputForSources(p.containerSpecs)
var storagePath string
if containerStore := p.OSCustomizations.ContainersStorage; containerStore != nil {
storagePath = *containerStore
storageConf := "/etc/containers/storage.conf"
containerStoreOpts := osbuild.NewContainerStorageOptions(storageConf, storagePath)
pipeline.AddStage(osbuild.NewContainersStorageConfStage(containerStoreOpts))
}
manifests := osbuild.NewFilesInputForManifestLists(p.containerSpecs)
skopeo := osbuild.NewSkopeoStageWithContainersStorage(storagePath, images, manifests)
pipeline.AddStage(skopeo)
for _, stage := range osbuild.GenContainerStorageStages(storagePath, p.containerSpecs) {
pipeline.AddStage(stage)
}
}
pipeline.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: p.Language}))
@ -706,8 +700,10 @@ func (p *OS) serialize() osbuild.Pipeline {
enabledServices := []string{}
disabledServices := []string{}
maskedServices := []string{}
enabledServices = append(enabledServices, p.EnabledServices...)
disabledServices = append(disabledServices, p.DisabledServices...)
maskedServices = append(maskedServices, p.MaskedServices...)
if p.Environment != nil {
enabledServices = append(enabledServices, p.Environment.GetServices()...)
}
@ -716,10 +712,12 @@ func (p *OS) serialize() osbuild.Pipeline {
disabledServices = append(disabledServices, p.Workload.GetDisabledServices()...)
}
if len(enabledServices) != 0 ||
len(disabledServices) != 0 || p.DefaultTarget != "" {
len(disabledServices) != 0 ||
len(maskedServices) != 0 || p.DefaultTarget != "" {
pipeline.AddStage(osbuild.NewSystemdStage(&osbuild.SystemdStageOptions{
EnabledServices: enabledServices,
DisabledServices: disabledServices,
MaskedServices: maskedServices,
DefaultTarget: p.DefaultTarget,
}))
}

View file

@ -228,7 +228,6 @@ func (p *OSTreeDeployment) doOSTreeSpec(pipeline *osbuild.Pipeline, repoPath str
}
func (p *OSTreeDeployment) doOSTreeContainerSpec(pipeline *osbuild.Pipeline, repoPath string, kernelOpts []string) string {
cont := *p.containerSpec
ref := p.ref
var targetImgref string
@ -249,7 +248,8 @@ func (p *OSTreeDeployment) doOSTreeContainerSpec(pipeline *osbuild.Pipeline, rep
Label: "root",
},
}
images := osbuild.NewContainersInputForSources([]container.Spec{cont})
images := osbuild.NewContainersInputForSingleSource(*p.containerSpec)
pipeline.AddStage(osbuild.NewOSTreeDeployContainerStage(options, images))
return ref
}

View file

@ -0,0 +1,29 @@
package osbuild
import (
"github.com/osbuild/images/pkg/container"
)
func GenContainerStorageStages(storagePath string, containerSpecs []container.Spec) (stages []*Stage) {
if storagePath != "" {
storageConf := "/etc/containers/storage.conf"
containerStoreOpts := NewContainerStorageOptions(storageConf, storagePath)
stages = append(stages, NewContainersStorageConfStage(containerStoreOpts))
}
images := NewContainersInputForSources(containerSpecs)
localImages := NewLocalContainersInputForSources(containerSpecs)
if len(images.References) > 0 {
manifests := NewFilesInputForManifestLists(containerSpecs)
stages = append(stages, NewSkopeoStageWithContainersStorage(storagePath, images, manifests))
}
if len(localImages.References) > 0 {
stages = append(stages, NewSkopeoStageWithContainersStorage(storagePath, localImages, nil))
}
return stages
}

View file

@ -13,22 +13,50 @@ type ContainersInput struct {
References map[string]ContainersInputSourceRef `json:"references"`
}
func NewContainersInputForSources(containers []container.Spec) ContainersInput {
func (c ContainersInput) isStageInputs() {}
func newContainersInputForSources(containers []container.Spec, forLocal bool) ContainersInput {
refs := make(map[string]ContainersInputSourceRef, len(containers))
for _, c := range containers {
if forLocal != c.LocalStorage {
continue
}
ref := ContainersInputSourceRef{
Name: c.LocalName,
}
refs[c.ImageID] = ref
}
var sourceType string
if forLocal {
sourceType = "org.osbuild.containers-storage"
} else {
sourceType = "org.osbuild.containers"
}
return ContainersInput{
References: refs,
inputCommon: inputCommon{
Type: "org.osbuild.containers",
Type: sourceType,
Origin: InputOriginSource,
},
}
}
func (c ContainersInput) isStageInputs() {}
func NewContainersInputForSources(containers []container.Spec) ContainersInput {
return newContainersInputForSources(containers, false)
}
func NewLocalContainersInputForSources(containers []container.Spec) ContainersInput {
return newContainersInputForSources(containers, true)
}
// NewContainersInputForSingleSource will return a containers input for a
// single container spec. It will automatically select the right local or
// remote input.
func NewContainersInputForSingleSource(spec container.Spec) ContainersInput {
if spec.LocalStorage {
return NewLocalContainersInputForSources([]container.Spec{spec})
}
return NewContainersInputForSources([]container.Spec{spec})
}

View file

@ -0,0 +1,22 @@
package osbuild
import "fmt"
type ContainersStorageSource struct {
Items map[string]struct{} `json:"items"`
}
func (ContainersStorageSource) isSource() {}
func NewContainersStorageSource() *ContainersStorageSource {
return &ContainersStorageSource{
Items: make(map[string]struct{}),
}
}
func (source *ContainersStorageSource) AddItem(id string) {
if !skopeoDigestPattern.MatchString(id) {
panic(fmt.Errorf("item %#v has invalid image id", id))
}
source.Items[id] = struct{}{}
}

View file

@ -11,38 +11,20 @@ type SkopeoIndexSource struct {
func (SkopeoIndexSource) isSource() {}
type SkopeoIndexSourceImage struct {
Name string `json:"name"`
TLSVerify *bool `json:"tls-verify,omitempty"`
ContainersTransport *string `json:"containers-transport,omitempty"`
StorageLocation *string `json:"storage-location,omitempty"`
Name string `json:"name"`
TLSVerify *bool `json:"tls-verify,omitempty"`
}
type SkopeoIndexSourceItem struct {
Image SkopeoIndexSourceImage `json:"image"`
}
func validateTransport(transport *string) error {
if transport == nil {
return nil
}
if *transport != DockerTransport && *transport != ContainersStorageTransport {
return fmt.Errorf("invalid container transport: %s", *transport)
}
return nil
}
func (item SkopeoIndexSourceItem) validate() error {
if item.Image.Name == "" {
return fmt.Errorf("source item has empty name")
}
if err := validateTransport(item.Image.ContainersTransport); err != nil {
return err
}
return nil
}
@ -55,13 +37,11 @@ func NewSkopeoIndexSource() *SkopeoIndexSource {
// AddItem adds a source item to the source; will panic
// if any of the supplied options are invalid or missing
func (source *SkopeoIndexSource) AddItem(name, image string, tlsVerify *bool, containersTransport *string, storageLocation *string) {
func (source *SkopeoIndexSource) AddItem(name, image string, tlsVerify *bool) {
item := SkopeoIndexSourceItem{
Image: SkopeoIndexSourceImage{
Name: name,
TLSVerify: tlsVerify,
ContainersTransport: containersTransport,
StorageLocation: storageLocation,
Name: name,
TLSVerify: tlsVerify,
},
}

View file

@ -17,11 +17,9 @@ type SkopeoSource struct {
func (SkopeoSource) isSource() {}
type SkopeopSourceImage struct {
Name string `json:"name,omitempty"`
Digest string `json:"digest,omitempty"`
TLSVerify *bool `json:"tls-verify,omitempty"`
ContainersTransport *string `json:"containers-transport,omitempty"`
StorageLocation *string `json:"storage-location,omitempty"`
Name string `json:"name,omitempty"`
Digest string `json:"digest,omitempty"`
TLSVerify *bool `json:"tls-verify,omitempty"`
}
type SkopeoSourceItem struct {
@ -29,14 +27,12 @@ type SkopeoSourceItem struct {
}
// NewSkopeoSourceItem creates a new source item for name and digest
func NewSkopeoSourceItem(name, digest string, tlsVerify *bool, containersTransport *string, storageLocation *string) SkopeoSourceItem {
func NewSkopeoSourceItem(name, digest string, tlsVerify *bool) SkopeoSourceItem {
item := SkopeoSourceItem{
Image: SkopeopSourceImage{
Name: name,
Digest: digest,
TLSVerify: tlsVerify,
ContainersTransport: containersTransport,
StorageLocation: storageLocation,
Name: name,
Digest: digest,
TLSVerify: tlsVerify,
},
}
if err := item.validate(); err != nil {
@ -54,10 +50,6 @@ func (item SkopeoSourceItem) validate() error {
return fmt.Errorf("source item %#v has invalid digest", item)
}
if err := validateTransport(item.Image.ContainersTransport); err != nil {
return err
}
return nil
}
@ -70,8 +62,8 @@ func NewSkopeoSource() *SkopeoSource {
// AddItem adds a source item to the source; will panic
// if any of the supplied options are invalid or missing
func (source *SkopeoSource) AddItem(name, digest, image string, tlsVerify *bool, containersTransport *string, storageLocation *string) {
item := NewSkopeoSourceItem(name, digest, tlsVerify, containersTransport, storageLocation)
func (source *SkopeoSource) AddItem(name, digest, image string, tlsVerify *bool) {
item := NewSkopeoSourceItem(name, digest, tlsVerify)
if !skopeoDigestPattern.MatchString(image) {
panic(fmt.Errorf("item %#v has invalid image id", image))
}

View file

@ -90,16 +90,20 @@ func GenSources(packages []rpmmd.PackageSpec, ostreeCommits []ostree.CommitSpec,
sources["org.osbuild.inline"] = ils
}
// collect skopeo container sources
// collect skopeo and local container sources
if len(containers) > 0 {
skopeo := NewSkopeoSource()
skopeoIndex := NewSkopeoIndexSource()
localContainers := NewContainersStorageSource()
for _, c := range containers {
skopeo.AddItem(c.Source, c.Digest, c.ImageID, c.TLSVerify, c.ContainersTransport, c.StoragePath)
// if we have a list digest, add a skopeo-index source as well
if c.ListDigest != "" {
skopeoIndex.AddItem(c.Source, c.ListDigest, c.TLSVerify, c.ContainersTransport, c.StoragePath)
if c.LocalStorage {
localContainers.AddItem(c.ImageID)
} else {
skopeo.AddItem(c.Source, c.Digest, c.ImageID, c.TLSVerify)
// if we have a list digest, add a skopeo-index source as well
if c.ListDigest != "" {
skopeoIndex.AddItem(c.Source, c.ListDigest, c.TLSVerify)
}
}
}
if len(skopeo.Items) > 0 {
@ -108,6 +112,9 @@ func GenSources(packages []rpmmd.PackageSpec, ostreeCommits []ostree.CommitSpec,
if len(skopeoIndex.Items) > 0 {
sources["org.osbuild.skopeo-index"] = skopeoIndex
}
if len(localContainers.Items) > 0 {
sources["org.osbuild.containers-storage"] = localContainers
}
}
return sources, nil

View file

@ -5,4 +5,4 @@
package internal
// Version is the current tagged release of the library.
const Version = "0.166.0"
const Version = "0.167.0"

8
vendor/modules.txt vendored
View file

@ -193,7 +193,7 @@ github.com/acarl005/stripansi
# github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
## explicit; go 1.13
github.com/asaskevich/govalidator
# github.com/aws/aws-sdk-go v1.50.24
# github.com/aws/aws-sdk-go v1.50.27
## explicit; go 1.19
github.com/aws/aws-sdk-go/aws
github.com/aws/aws-sdk-go/aws/arn
@ -642,7 +642,7 @@ github.com/googleapis/gax-go/v2/apierror
github.com/googleapis/gax-go/v2/apierror/internal/proto
github.com/googleapis/gax-go/v2/callctx
github.com/googleapis/gax-go/v2/internal
# github.com/gophercloud/gophercloud v1.9.0
# github.com/gophercloud/gophercloud v1.10.0
## explicit; go 1.14
github.com/gophercloud/gophercloud
github.com/gophercloud/gophercloud/internal/ctxt
@ -851,7 +851,7 @@ github.com/oracle/oci-go-sdk/v54/identity
github.com/oracle/oci-go-sdk/v54/objectstorage
github.com/oracle/oci-go-sdk/v54/objectstorage/transfer
github.com/oracle/oci-go-sdk/v54/workrequests
# github.com/osbuild/images v0.40.0
# github.com/osbuild/images v0.41.0
## explicit; go 1.19
github.com/osbuild/images/internal/common
github.com/osbuild/images/internal/environment
@ -1241,7 +1241,7 @@ golang.org/x/tools/internal/pkgbits
golang.org/x/tools/internal/tokeninternal
golang.org/x/tools/internal/typeparams
golang.org/x/tools/internal/typesinternal
# google.golang.org/api v0.166.0
# google.golang.org/api v0.167.0
## explicit; go 1.19
google.golang.org/api/googleapi
google.golang.org/api/googleapi/transport