cloudapi: add support for uploading to a container registry
Worker ------ Add configuration for the default container registry. Use the default container registry if not provided as part of the image name. When using the default registry use the configured values Return the image url as part of the result. Composer Worker API ------------------- Add `ContainerTargetResultOptions` to return the image url Composer API ------------ Add UploadOptions to allow setting of the image name and tag Add UploadStatus to return the url of the uploaded image Co-Developed-By: Christian Kellner <christian@kellner.me>
This commit is contained in:
parent
14208d872b
commit
3231aabbc0
9 changed files with 277 additions and 130 deletions
|
|
@ -52,6 +52,10 @@ type authenticationConfig struct {
|
||||||
|
|
||||||
type containersConfig struct {
|
type containersConfig struct {
|
||||||
AuthFilePath string `toml:"auth_file_path"`
|
AuthFilePath string `toml:"auth_file_path"`
|
||||||
|
Domain string `toml:"domain"`
|
||||||
|
Account string `toml:"account"`
|
||||||
|
CertPath string `toml:"cert_path"`
|
||||||
|
TLSVerify bool `toml:"tls_verify"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type workerConfig struct {
|
type workerConfig struct {
|
||||||
|
|
|
||||||
|
|
@ -40,16 +40,24 @@ type S3Configuration struct {
|
||||||
SkipSSLVerification bool
|
SkipSSLVerification bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type OSBuildJobImpl struct {
|
type ContainersConfiguration struct {
|
||||||
Store string
|
|
||||||
Output string
|
|
||||||
KojiServers map[string]kojiServer
|
|
||||||
GCPCreds string
|
|
||||||
AzureCreds *azure.Credentials
|
|
||||||
AWSCreds string
|
|
||||||
AWSBucket string
|
|
||||||
S3Config S3Configuration
|
|
||||||
ContainerAuthFile string
|
ContainerAuthFile string
|
||||||
|
Domain string
|
||||||
|
Account string
|
||||||
|
CertPath string
|
||||||
|
TLSVerify *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type OSBuildJobImpl struct {
|
||||||
|
Store string
|
||||||
|
Output string
|
||||||
|
KojiServers map[string]kojiServer
|
||||||
|
GCPCreds string
|
||||||
|
AzureCreds *azure.Credentials
|
||||||
|
AWSCreds string
|
||||||
|
AWSBucket string
|
||||||
|
S3Config S3Configuration
|
||||||
|
ContainersConfig ContainersConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an *awscloud.AWS object with the credentials of the request. If they
|
// Returns an *awscloud.AWS object with the credentials of the request. If they
|
||||||
|
|
@ -199,6 +207,40 @@ func uploadToS3(a *awscloud.AWS, outputDirectory, exportPath, bucket, key, filen
|
||||||
return url, nil
|
return url, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (impl *OSBuildJobImpl) getContainerClient(destination string, targetOptions *target.ContainerTargetOptions) (*container.Client, error) {
|
||||||
|
useImpl := false
|
||||||
|
i := strings.IndexRune(destination, '/')
|
||||||
|
if i == -1 || (!strings.ContainsAny(destination[:i], ".:") && destination[:i] != "localhost") {
|
||||||
|
if impl.ContainersConfig.Domain != "" {
|
||||||
|
base := impl.ContainersConfig.Domain
|
||||||
|
if impl.ContainersConfig.Account != "" {
|
||||||
|
base = fmt.Sprintf("%s/%s", base, impl.ContainersConfig.Account)
|
||||||
|
}
|
||||||
|
destination = fmt.Sprintf("%s/%s", base, destination)
|
||||||
|
useImpl = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := container.NewClient(destination)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if useImpl {
|
||||||
|
if impl.ContainersConfig.CertPath != "" {
|
||||||
|
client.SetDockerCertPath(impl.ContainersConfig.CertPath)
|
||||||
|
}
|
||||||
|
client.SetTLSVerify(impl.ContainersConfig.TLSVerify)
|
||||||
|
} else {
|
||||||
|
if targetOptions.Username != "" || targetOptions.Password != "" {
|
||||||
|
client.SetCredentials(targetOptions.Username, targetOptions.Password)
|
||||||
|
}
|
||||||
|
client.SetTLSVerify(targetOptions.TlsVerify)
|
||||||
|
}
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (impl *OSBuildJobImpl) Run(job worker.Job) error {
|
func (impl *OSBuildJobImpl) Run(job worker.Job) error {
|
||||||
logWithId := logrus.WithField("jobId", job.Id().String())
|
logWithId := logrus.WithField("jobId", job.Id().String())
|
||||||
// Initialize variable needed for reporting back to osbuild-composer.
|
// Initialize variable needed for reporting back to osbuild-composer.
|
||||||
|
|
@ -308,9 +350,9 @@ func (impl *OSBuildJobImpl) Run(job worker.Job) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var extraEnv []string
|
var extraEnv []string
|
||||||
if impl.ContainerAuthFile != "" {
|
if impl.ContainersConfig.ContainerAuthFile != "" {
|
||||||
extraEnv = []string{
|
extraEnv = []string{
|
||||||
fmt.Sprintf("REGISTRY_AUTH_FILE=%s", impl.ContainerAuthFile),
|
fmt.Sprintf("REGISTRY_AUTH_FILE=%s", impl.ContainersConfig.ContainerAuthFile),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -775,34 +817,29 @@ func (impl *OSBuildJobImpl) Run(job worker.Job) error {
|
||||||
targetResult.Options = &target.OCITargetResultOptions{ImageID: imageID}
|
targetResult.Options = &target.OCITargetResultOptions{ImageID: imageID}
|
||||||
|
|
||||||
case *target.ContainerTargetOptions:
|
case *target.ContainerTargetOptions:
|
||||||
targetResult = target.NewContainerTargetResult()
|
targetResult = target.NewContainerTargetResult(nil)
|
||||||
destination := jobTarget.ImageName
|
destination := jobTarget.ImageName
|
||||||
|
|
||||||
logWithId.Printf("[container] ⬆ Uploading the image to %s", destination)
|
logWithId.Printf("[container] ⬆ Uploading the image to %s", destination)
|
||||||
|
|
||||||
ctx := context.Background()
|
client, err := impl.getContainerClient(destination, targetOptions)
|
||||||
client, err := container.NewClient(destination)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
targetResult.TargetError = clienterrors.WorkerClientError(clienterrors.ErrorInvalidConfig, err.Error())
|
targetResult.TargetError = clienterrors.WorkerClientError(clienterrors.ErrorInvalidConfig, err.Error())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if targetOptions.Username != "" || targetOptions.Password != "" {
|
|
||||||
client.SetCredentials(targetOptions.Username, targetOptions.Password)
|
|
||||||
}
|
|
||||||
client.SetTLSVerify(targetOptions.TlsVerify)
|
|
||||||
|
|
||||||
sourcePath := path.Join(outputDirectory, jobTarget.OsbuildArtifact.ExportName, jobTarget.OsbuildArtifact.ExportFilename)
|
sourcePath := path.Join(outputDirectory, jobTarget.OsbuildArtifact.ExportName, jobTarget.OsbuildArtifact.ExportFilename)
|
||||||
|
|
||||||
// TODO: get the container type from the metadata of the osbuild job
|
// TODO: get the container type from the metadata of the osbuild job
|
||||||
sourceRef := fmt.Sprintf("oci-archive:%s", sourcePath)
|
sourceRef := fmt.Sprintf("oci-archive:%s", sourcePath)
|
||||||
|
|
||||||
digest, err := client.UploadImage(ctx, sourceRef, "")
|
digest, err := client.UploadImage(context.Background(), sourceRef, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
targetResult.TargetError = clienterrors.WorkerClientError(clienterrors.ErrorUploadingImage, err.Error())
|
targetResult.TargetError = clienterrors.WorkerClientError(clienterrors.ErrorUploadingImage, err.Error())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
logWithId.Printf("[container] 🎉 Image uploaded (%s)!", digest.String())
|
logWithId.Printf("[container] 🎉 Image uploaded (%s)!", digest.String())
|
||||||
|
targetResult.Options = &target.ContainerTargetResultOptions{URL: client.Target.String(), Digest: digest.String()}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// TODO: we may not want to return completely here with multiple targets, because then no TargetErrors will be added to the JobError details
|
// TODO: we may not want to return completely here with multiple targets, because then no TargetErrors will be added to the JobError details
|
||||||
|
|
|
||||||
|
|
@ -378,8 +378,16 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var containersAuthFilePath string
|
var containersAuthFilePath string
|
||||||
|
var containersDomain = ""
|
||||||
|
var containersAccount = ""
|
||||||
|
var containersCertPath = ""
|
||||||
|
var containersTLSVerify = true
|
||||||
if config.Containers != nil {
|
if config.Containers != nil {
|
||||||
containersAuthFilePath = config.Containers.AuthFilePath
|
containersAuthFilePath = config.Containers.AuthFilePath
|
||||||
|
containersDomain = config.Containers.Domain
|
||||||
|
containersAccount = config.Containers.Account
|
||||||
|
containersCertPath = config.Containers.CertPath
|
||||||
|
containersTLSVerify = config.Containers.TLSVerify
|
||||||
}
|
}
|
||||||
|
|
||||||
// depsolve jobs can be done during other jobs
|
// depsolve jobs can be done during other jobs
|
||||||
|
|
@ -435,7 +443,13 @@ func main() {
|
||||||
CABundle: genericS3CABundle,
|
CABundle: genericS3CABundle,
|
||||||
SkipSSLVerification: genericS3SkipSSLVerification,
|
SkipSSLVerification: genericS3SkipSSLVerification,
|
||||||
},
|
},
|
||||||
ContainerAuthFile: containersAuthFilePath,
|
ContainersConfig: ContainersConfiguration{
|
||||||
|
ContainerAuthFile: containersAuthFilePath,
|
||||||
|
Domain: containersDomain,
|
||||||
|
Account: containersAccount,
|
||||||
|
CertPath: containersCertPath,
|
||||||
|
TLSVerify: &containersTLSVerify,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
worker.JobTypeKojiInit: &KojiInitJobImpl{
|
worker.JobTypeKojiInit: &KojiInitJobImpl{
|
||||||
KojiServers: kojiServers,
|
KojiServers: kojiServers,
|
||||||
|
|
|
||||||
|
|
@ -344,8 +344,6 @@ func (h *apiHandlers) PostCompose(ctx echo.Context) error {
|
||||||
fallthrough
|
fallthrough
|
||||||
case ImageTypesEdgeInstaller:
|
case ImageTypesEdgeInstaller:
|
||||||
fallthrough
|
fallthrough
|
||||||
case ImageTypesEdgeContainer:
|
|
||||||
fallthrough
|
|
||||||
case ImageTypesEdgeCommit:
|
case ImageTypesEdgeCommit:
|
||||||
var awsS3UploadOptions AWSS3UploadOptions
|
var awsS3UploadOptions AWSS3UploadOptions
|
||||||
jsonUploadOptions, err := json.Marshal(*ir.UploadOptions)
|
jsonUploadOptions, err := json.Marshal(*ir.UploadOptions)
|
||||||
|
|
@ -365,6 +363,22 @@ func (h *apiHandlers) PostCompose(ctx echo.Context) error {
|
||||||
t.ImageName = key
|
t.ImageName = key
|
||||||
t.OsbuildArtifact.ExportFilename = imageType.Filename()
|
t.OsbuildArtifact.ExportFilename = imageType.Filename()
|
||||||
|
|
||||||
|
irTarget = t
|
||||||
|
case ImageTypesEdgeContainer:
|
||||||
|
var containerUploadOptions ContainerUploadOptions
|
||||||
|
jsonUploadOptions, err := json.Marshal(*ir.UploadOptions)
|
||||||
|
if err != nil {
|
||||||
|
return HTTPError(ErrorJSONMarshallingError)
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(jsonUploadOptions, &containerUploadOptions)
|
||||||
|
if err != nil {
|
||||||
|
return HTTPError(ErrorJSONUnMarshallingError)
|
||||||
|
}
|
||||||
|
|
||||||
|
t := target.NewContainerTarget(&target.ContainerTargetOptions{})
|
||||||
|
t.ImageName = fmt.Sprintf("%s:%s", containerUploadOptions.Name, containerUploadOptions.Tag)
|
||||||
|
t.OsbuildArtifact.ExportFilename = imageType.Filename()
|
||||||
|
|
||||||
irTarget = t
|
irTarget = t
|
||||||
case ImageTypesGcp:
|
case ImageTypesGcp:
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
@ -544,6 +558,14 @@ func targetResultToUploadStatus(t *target.TargetResult) (*UploadStatus, error) {
|
||||||
uploadOptions = AzureUploadStatus{
|
uploadOptions = AzureUploadStatus{
|
||||||
ImageName: gcpOptions.ImageName,
|
ImageName: gcpOptions.ImageName,
|
||||||
}
|
}
|
||||||
|
case target.TargetNameContainer:
|
||||||
|
uploadType = UploadTypesContainer
|
||||||
|
containerOptions := t.Options.(*target.ContainerTargetResultOptions)
|
||||||
|
uploadOptions = ContainerUploadStatus{
|
||||||
|
Url: containerOptions.URL,
|
||||||
|
Digest: containerOptions.Digest,
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unknown upload target: %s", t.Name)
|
return nil, fmt.Errorf("unknown upload target: %s", t.Name)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,8 @@ const (
|
||||||
|
|
||||||
UploadTypesAzure UploadTypes = "azure"
|
UploadTypesAzure UploadTypes = "azure"
|
||||||
|
|
||||||
|
UploadTypesContainer UploadTypes = "container"
|
||||||
|
|
||||||
UploadTypesGcp UploadTypes = "gcp"
|
UploadTypesGcp UploadTypes = "gcp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -218,6 +220,24 @@ type ComposeStatusError struct {
|
||||||
// ComposeStatusValue defines model for ComposeStatusValue.
|
// ComposeStatusValue defines model for ComposeStatusValue.
|
||||||
type ComposeStatusValue string
|
type ComposeStatusValue string
|
||||||
|
|
||||||
|
// ContainerUploadOptions defines model for ContainerUploadOptions.
|
||||||
|
type ContainerUploadOptions struct {
|
||||||
|
// Name for the created container image
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Tag for the created container image
|
||||||
|
Tag string `json:"tag"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainerUploadStatus defines model for ContainerUploadStatus.
|
||||||
|
type ContainerUploadStatus struct {
|
||||||
|
// Digest of the manifest of the uploaded container on the registry
|
||||||
|
Digest string `json:"digest"`
|
||||||
|
|
||||||
|
// FQDN of the uploaded image
|
||||||
|
Url string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
// Customizations defines model for Customizations.
|
// Customizations defines model for Customizations.
|
||||||
type Customizations struct {
|
type Customizations struct {
|
||||||
Filesystem *[]Filesystem `json:"filesystem,omitempty"`
|
Filesystem *[]Filesystem `json:"filesystem,omitempty"`
|
||||||
|
|
@ -672,110 +692,112 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
|
||||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||||
var swaggerSpec = []string{
|
var swaggerSpec = []string{
|
||||||
|
|
||||||
"H4sIAAAAAAAC/+x8aW/jOBLoXyG8D+hpxId8OwEGu7bjJL5y2M7hjBsBLVESbYlUSMpHGvnvD6Qkn3Li",
|
"H4sIAAAAAAAC/+x8aW/jOLboXyF8H1DdiBd5dwI05tqOk3jLYjtruxDQEi3RlkiFpLykUP/9gdTiRXLi",
|
||||||
"7Pbuvn3o+TAdS2RVsVgXq4r6mdCp61GCiOCJs58JDzLoIoFY+MtC8l8DcZ1hT2BKEmeJW2ghgImBFolk",
|
"zNTMffeh+kNXLJE8C8/Gcw71I6VTx6UEEcFTZz9SLmTQQQKx4JeJ5L8G4jrDrsCUpM5St9BEABMDrVLp",
|
||||||
"Ai2g6zloa/gMOj5KnCWyiff3ZALLOa8+YstEMkGgK9+okckE123kQjlFLD35nAuGiaWmcfwWg/vad8eI",
|
"FFpBx7XRzvAFtD2UOkvlUz9/plNYznnzEFun0ikCHflGjUynuG4hB8opYu3K51wwTEw1jeP3BNjXnjNB",
|
||||||
"AWoCLJDLASYAQd0GIcBNaiIAK2o07SA9auxH9LxHLxXo6mO/Uc/dew6Fxo0iLVg/ox5iAgf4GbIUzT8j",
|
"DNApwAI5HGACENQtECy4jU24QISNph3ER439CJ+f4Uu1dP1x2GoW7l2bQuNGoebTz6iLmMA+fIZMhfOP",
|
||||||
"qhJnCeSn5oiLVDaR3EWRTHAbMvQyx8J+gbpO/XBLVrP/SmRz+UKxVK6catlc4kcyoXgQQ+4KOGQMLhVs",
|
"EKvUWQp5mSXiIpNPpfdBpFPcggy9LrGwXqGuUy/Ykmj236l8oVgqV6q1Uy1fSH1PpxQPEtCNFoeMwbVa",
|
||||||
"Aj1uU/ESLHiTJneZit7uU/WeTDD06mOGDElAuKZ4Wn+sZtPxBOlC4t3kVF9A4ccwCrp4myLo4pSmV/Ja",
|
"m0CXW1S8+gRv4+SsM+HbOFY/0ymG3jzMkCERCGhKxvV7NJtOZkgXEu42p4YCCi+BUdDBuxhBB2c0vVbU",
|
||||||
"+TRfLheLp0WjMI7j2BdZvLMYiXcF4wDx/fyv3eV4fn6C/BDjfObE684mCjkoFv6bz9Ani8MutNBKZHY0",
|
"qqfFarVcPi0bpUkSx77I4j1iJNxojQPID4u/dpeT+fkJ8EOM85idrDvbIOSgxPXfPYY+IQ470ESRyOxp",
|
||||||
"EbpI6qGwEfAVGGQANSENmgK4PhdgjIBP8KsvzYUaaOEZIoAhTn2mI2Ax6nvpEWmaQCIBmAPqYiGQAUxG",
|
"InSQ1ENhIeCpZZAB1IQsaAvgeFyACQIewW+eNBdqoIkXiACGOPWYjoDJqOdmx6Q9BRIIwBxQBwuBDDBl",
|
||||||
"XTVFrgVxkQQQMEgM6gJKEBhDjgxACYDg/r55DjAfEQsRxKBARnpE1rYgkHBFWJwIOVSHItzB7QV2wjdg",
|
"1FFTJC2IizSAgEFiUAdQgsAEcmQASgAE9/ftc4D5mJiIIAYFMrJjsrEFvoQrxJJEyKY6FMEO7hLYC96A",
|
||||||
"biOGFC0KCuA29R1DLS5aNyQGkHvJBWIK/xWdA0GBg7kA0HFAhIafjYgthMfPMhmD6jztYp1RTk2R1qmb",
|
"pYUYUrioVQC3qGcbiriQbkgMIPeSC8QU/Cu6BIICG3MBoG2DEAw/GxNLCJef5XIG1XnWwTqjnE5FVqdO",
|
||||||
"QSTl84zu4AyU25MJdevvM4zmf6pHKd3BKQcKxMXf4FukfC8S0csKybcdBkhpRL7c2ngtCrbjRW3Hxzu9",
|
"DpGMx3O6jXNQbk8u0K1/LDBa/qUeZXQbZ2woEBf/Bd9D5XuVgF4jIN/2GCClEXlya5O1yN+OV7UdH+/0",
|
||||||
"vXVHsGZ3LwbU1yHphWAuFcY4W+iPVyS8YGOfqOa5JGlz2D9BTAEVjco4p6fgOFdIFQrZfOpU04upUjaX",
|
"7tYdwZr9vRhRT4dkECxzqSAm2UJvEqHwio04Uu1zidL2sH8CmRIqG7VJQc/ASaGUKZXyxcypppczlXyh",
|
||||||
"10qoop2iXBx1AhFIxAd0SSKCQcdRFYqLiYkBsIi0RakouKVMQOcYuYlkRuAZShmYIV1QtsyYPjGgi4iA",
|
"qFVQTTtFhSTsBCKQiA/wkkj4g47DKhCXKSYGwCLUFqWi4JYyAe1j5CaUGYEXKGNghnRB2To39YgBHUQE",
|
||||||
"Dt97m7LpPCVoSqJOBSTvMKmol5FZHJdSWT1vpgoG1FKwlMultLFW0nL5U6NslD81dGuO7e/tngRuaOUn",
|
"tHnsbcaiy4ygGQk646O8x6SyXkXT8qSSyevFaaZkQC0DK4VCRptoFa1QPDWqRvVTQ7fhWHxvYxK4pZWf",
|
||||||
"luuQZdw2XMdYgh16NwDEkVCXQRNHTSUA0HFuzMTZXz8T/4chM3GW+FtmHVRlwrAhc6Mm95CJGCI6Srwn",
|
"WK5DlnHXcB1jCfbw3VogCYWmDJo4aisBgLZ9M02d/f0j9X8YmqbOUv+V2wRVuSBsyN2oyQM0RQwRHaV+",
|
||||||
"94g2tonN5vJIuvsUqpyOU9mckU/BQrGUKuRKpWKxUNA0TUskEyZlLhSJs4TvK2Z+sjAjZkE/1kvqUIv/",
|
"pmNIG7vI5gtFJN19BtVOJ5l8wShmYKlcyZQKlUq5XCppmqal0qkpZQ4UqbOU5ylmfkKYkUDQ9w1JPWry",
|
||||||
"0kUpRo597BjB752QJSQhmVikLJoKH2IiEDOhjn6+xwUzUzpREcNHlLXpBKu1xO9sSNCHrOhCgk3ExS/l",
|
"X0qUYuTEw7bh/94LWQIU0qlVxqSZ4CEmArEp1NGPn0nBzJzOVMTwEWZdOsOKluSdDRD6kBV9SPAUcfFL",
|
||||||
"h7sJ9F9nxs7i1tA/XhkS0IAC/sqFUS4YQi86dV0sYu3iHzbk9vfIPModECAcHmNjPahPoRXA3j1/qDeB",
|
"+eFsL/qvM2OPuM3qH1OGBDSggL+SMMoFQ+hVp46DRaJd/MOC3PozNI9yBwQIhifYWBfqc2j6a++fP9Qb",
|
||||||
"c8VEd3wDEwtcNx561cRGUPzRekIYK0bEMfYw/3pBTLJvd3SfC+riN7gKqD4ior49+j2ZMLBkwNgXezEl",
|
"37liotuegYkJrlsPg3pqKyj+iJ5gjYgRSYw9zL+BH5PE7Y7ucUEd/A6jgOojJJq7o3+mUwaWDJh4IhZT",
|
||||||
"s5GTqsQxKhBotibpI5RNOTgif3fytkx+Bcw/q6F7ArzFgA2Orw39rzVMfAX30+WGJKyYFkxFX2TaGkoc",
|
"MgvZmVoSo3yBZhuUPgLZloND9Pcn78rkV5b5ZzU0JsA7DNji+MbQ/1rDxKN1PyU3QCFimj8VfZFpm1WS",
|
||||||
"z46kR7JuDei4OVuMfFBn4l3mh4C2F/ixJQnANRijbF8bDCQgduSfkmnGhqGTNs1CLIg+IQ+E/VPHtRq8",
|
"eHYkPpJ1m4WOm7PDyAd1Jt5nfrDQLoEfWxJ/uRZjlMW1wUACYlv+KZlmbBk6adNMxPzoE3Jf2D91XNHg",
|
||||||
"R0CwHqkwxHfVUnxdR1yuxYTY8Zn0+B4i0lDIBa31aj1wT7Hqe8q8vTwTO4gvuUDu0SJwsZ4SIwGbJm/j",
|
"GAI+PVJhiOcoUjxdR1zSMoXY9pj0+C4i0lBIgjZ6tRkYU6wmJQJigljslAQNA8sf0L7dIngKbY7Sezz4",
|
||||||
"1O9RLiyG+NdO/B5cygjphSGPciwow3G2tLEQDILNMcCkDESUAO4hHZtYHu0I2LZuaTCwEUcjsjV7jh0H",
|
"4PA0pUxZQp0heWoBegjPjxT3wjDKlc9KDEehGQcxguYXIfinik8jCEWRDzQ5NNrh2pbiHs80A5uBLdul",
|
||||||
"UOIsVYQrD2mCAgN5nDozFJ6TBMNohlZIRkSilD7hpg+w4MgxwR/CRssAGKHqIAlnEDtw7CAQjVY+HDBK",
|
"6Vw9Dz1I6Oxip9ANmZQEpxZ5NGNrRXCMfcExehfUxd35dfLxdo9rbx5cZzHNOevgLJYLdursSH5K8OmQ",
|
||||||
"BaBsRCBZAipsJKlnYtPNGMBjVO7yd0VzhPiFI8GBiZFjRDD3loM5wBahLDo7HLXLvQjCMjYVg9gM62Hq",
|
"5ESOxpzKLrem2EZ8zQVyjjZFF5spCZZo2/VuZZ9cyoXJEP9a5smFa8m9V4ZcyrGgDCf59NZKMAi2xyjh",
|
||||||
"wzCwZCZ0bjdEy4QOR8ldZcJcrj7myNGRflAehkLAiuPBaDBeAgOZ0HfEJvFr8TcxQ3PoOEacAriYNIMp",
|
"DTEB3EU6nmK5BwTsetksGFmIozHZmb3Etg0osdfqpMWRIc9XBnI5tRcoOK8LhtECRUDGJNSXmyHAgiN7",
|
||||||
"2f1lIPIFcoLBn1JDTCHH8S8S8x4ToW8eMj7br/7m2Pdkwudh/vOo3b7ngSH7nKaVmfxVPkynBoo1BluW",
|
"Cv4QFlr7ixGqEhpwAbENJ/ZGf9VuA0apAJSNCSRrQIWFJPZMbIc7BnAZldbmT4VzCPiVI8HBFCPbCNeM",
|
||||||
"V86AGwfpmATAcSZYoVsN3wEc7ybUkqVEHL9sNTrGX0d7cdSmBKz+LFwOQMVTfrFl3XeCeExeovTySnqz",
|
"kYM5wCahLDzDHrXLg3CFdWJKELEF1tHXdZNL6hOOvj3s62K4sOK4PxpM1sBAU+jZYhv5jRZNMUNLaCfb",
|
||||||
"Wq6wHbn7mIhSQQkv9YnwKCZiW+AzM8g+PbJtTE6uUccdSy/rt59k9Ma+PkXicI4HEoAWmAsZUPcH1evz",
|
"NweTtj8lHycDkS+g4w/+FBsyFXIc/yIyPxOUd/uw+9l+DbfHSsPEgzz8Ubt9z32H+jlOkbv+VbGUTg2U",
|
||||||
"au8c9AVlMuDWHcg5qCkQ6d0MW/gjFWI4GKjGZxOlWVYpQEGl11jZeOx6lIkww6aSzgaQnt8XCDSIhUmY",
|
"aAx2IgA5A24ldBISUceFAgpcNHxv4eRwRZEsJeJ4stXohLgx3IujNsVn9WfHNn+pZMwvdqz73mESk9ew",
|
||||||
"VkmPyGCVYlGAdhKQcyzsMK1yWb+VDkEyLQnmNtZtaealr9r2RApWkKRR6ANa0qBpKp+0do1RZnJEvulB",
|
"zBFJb14rlHZPkB4molJSwisdlEsxEbsCn1tA9qmj2pqc3oBO8liXzdtPMssTT58jcTjXCAlAK8yFPNgN",
|
||||||
"VMJS0MOpka9peV0ey9Vf6BsImBGhA5BvJIYk1V/JXK4zz/uslEsM3m/kn1ZrUm51vMFcQTf5azLqhvxU",
|
"R/Xr8/rgHAwFZfLgp9uQc9BQS2T3M73Bj0wA4eCBKTkwk2ZZpaIFlV4jsvHYcSkTQaZXFT8MICNQTyDQ",
|
||||||
"tZMVK6H8jQ0FPcrQpEEfIRClpnSH+kbaotRykEpM8UB0VM4qs8pPhinfTSYmFYmu7wicCimPhgPdoRxx",
|
"IiYmQXovOyajKNWnFtpLhC+xsIL03mXzVjoEybQ0WFpYt6SZl75q1xOptfwYRIH3ccmC9lT5pI1rDDPk",
|
||||||
"IcmUg4Jc0Yj8EaYiI/EMBHM17btks25TjgiAvqAuFFiHjrPcZTLyv1CNifd1IV/UukE0XNKroGxLcpz4",
|
"Y/JN96NjloEuzow9TSvqnocN9Rf6BnxmhOAA5FsJSon1VzLomwpInJWSRP/9Vh40okm51ckWcwXd5u+U",
|
||||||
"KvFMj0gD6nYkJIrrOiUCYgLgilMsimxCNEBSngYPioIgF8QBZOhsRABIgW/SmZ39RC7EDjbev52BKgHq",
|
"USfgp6rhRayE8jc21OphpjALhgiBMEWq29Qzsialpo1UgpT7oqNyp7koTx6UHraZmPZDS88WOBNgHg4H",
|
||||||
"F4CGwRCXIgiFDAEZ4tKGrnHpEgTYWVYaXFAGQu4lwTfoYB39I/wt9/xbOsQcBgDVYN4XaQhQhyAO4XaX",
|
"uk25jDcFVYP8nOWY/BGkxEPx9AUzmvanZLNuUY4IgJ6gDhRYh7a93mcy8r5QFUz2dQFfFN0gHC7xVavs",
|
||||||
"KRXxpaDn/QN6HveoSFvhpGjOJkkqv/hVboTrj4oVkq4dFhguJjyWBwZ1ISZnP4N/JUKlnqDvY4FA8BT8",
|
"SnKS+CrxzI5JC+pWKCSK60FIDWDEKRZGNgEYIDHPggeFgZ+T5AAydDYmAGTAN+nMzn4gB2IbGz+/nYE6",
|
||||||
"4THsQrb8vo/ccQKEqsoiw5Jg96EI5+5yZK163wBl4NsOTfFa97FoYh7MCYyDFFQAyXJEIv5ua9NfKno6",
|
"AeoXgIbBEJciCIUMARni0oZuYOlyCbBHVhZcUAYC7qXBN2hjHf138Fvu+bdsADkIAOr+vC/i4IMOljgE",
|
||||||
"25OKxCrwjeTh2M1LJBPBtu2zOZFMhAzefPiFY9Kh8mboxD70sb8u96xCfQn/ZTcFDLmOiAGJSI0ZxEYq",
|
"21lnVMSXga7739B1uUtF1gwmhXO2UVJ57q9yI6A/LJpJvPZYYDiY8EQeGNSBmJz98P+VAJV6gqGHBQL+",
|
||||||
"r+WL2fynEcMGuORnqeytVM5+bZbpNhZIF/IIvUXaolJ6KRUO+/ng8REZkcHSQyqPEWQQP5tz0x/IUWrF",
|
"U/CHy7AD2frPOHDb9gGq45AMS/zdhyKYu8+Rjep9A5SBb3s4JWvdx6KJuT/HNw5SUAEk6zEJ+burTX+r",
|
||||||
"2yfbX3A2C7z9C/WOyt9tx1p75eVN1m1xZYf0H9EuHJIoFJ0bjs7vrMLfL+e3wszQihXHAdjSiANppZ1l",
|
"6OksJhWpKPAN5eHYzUulU/62xdksz28+g7cffuGYdKjMHjixD33sr6uBqFBfrv+6X4qAXEfEgERkJgxi",
|
||||||
"fillIzUSO+GfAWXB31HRNczr7MnihoRtoIJziQbOeYrZPg7/tOHmLw691c+3gJig/ho+RIaFUqvsdfhL",
|
"I1PUiuV88dOIYWu59GcllZ2UYrxHgOkWFkgXHtsjZ1WrvFZKh/28//iIzNxo7SKVT/Mz2Z/NuRmO5ChF",
|
||||||
"+WrEogeYcAEdRz2wdC/4fwTAkgq3sgjq360JM+7JyC12Ve0wvbotJvsm5wIZlMFUXUZlqRrkB+JIB8lX",
|
"8e7J9heczXxv/0rdo/LIu7FWrM1hm3U7XNlD/Xu4C4ckCoXnhqPzjFH4++U8a5ChjFhx3AI7GnEgvblH",
|
||||||
"WzNzWk7TTrVyWouNjRCbIbY9IwoBp3SC06ZCHJqhNGWWemz74616FcOxxVXIp7uGsJBLxqQOZ4jxvUR5",
|
"5pdSh1IjsR386WPm/x0W/4P8YkwWtyRsCxRcSjBwyTPM8nDwpwW3f3HoRj/ffWT8PoDgITJMlImqKMGv",
|
||||||
"/vOui5D8NaqwD2gNcc2VOJO5qi3F2H7pScOEJ1F1kL0zJ1ESE448BP6QKVBqcAx34vIP0Tl8G+QUk/i0",
|
"IP0VPsCEC2jb6oGpu/7/wwVMqXCRRVD/7kxYcFdGbolUdYM0f3LKc6OjF8igDGaaMirLNCA/EEfaSL7a",
|
||||||
"QNTOtc/46Oy7/0ZQAZ24VztcUEiTqz6woP0qmJw8eCxPJkLjv7cGDzJEYo61dUjkwQVhlReEYbkJ/BGy",
|
"mVnQCpp2qlWzWmJshNgCsd0ZYQg4pzOcnSrAgRnKUmaqx5Y32ambMpycVeXzfUNYKqQTUtgLxHisYFP8",
|
||||||
"7gxouZJWGOcMWEKnxcLYyBfGlXElByv5IirCctnIjUuaacLvSRlOQTBmkOh2ysFTBFiUmdmAx2zkZCqZ",
|
"vPsnQH8DKh0mV8MVN1xJMplRjTPB9ktPGiTeiarHxc6cRElMMPLQ8odMgVKDY7iTlH8Iz+G7S84xSU4L",
|
||||||
"wDlmpBX4vnPa2B8Rr5Tmfv3n82kHO4L2ObmTXNpjqR2SsO/e46XlgBjFZfHDzVcY4nZ5tzgXG5XEEoE8",
|
"hG2FccaHZ9/4G0EFtJNe7XFBAU1H/Yh+G6A/OX3wWJ5OBcY/RoMLGSIJx9omJPLggrDKC8Kg7An+CFh3",
|
||||||
"euBNZBw/Mn/7dg5brlE89IrAKCo6EGXGvNgwWZ80TASBwkG7lAyYsKJReteN2GbfcECOQunYt9m6QdIM",
|
"BrRCRStNCgasoNNyaWIUS5PapFaAtWIZlWG1ahQmFW06hX+mZTgFwYRBolsZG88RYGFmZms9ZiE7V8v5",
|
||||||
"GTYMukmkI0NEZAzMRUYKXmUteRIO5RnKM0eYct1G+vTF8qyN9Y4pdRBUeVbLs6Zoua+1l7eXYIqWq/KB",
|
"zjEnrcCfe6eN+IhkpZzG65CfTzvYmRbn5F5yKcZSK0Ah7t6TpeWAGCVVk4LNVxCSdnm/SJwYlSQigVx6",
|
||||||
"5PW6JKGyOJivixbL7VxUSv5Xa1w2r8Ht5S24va91mnXQbgxBrXNTb6vXIzIi7l3zunZZ1fs6rTWq5x2z",
|
"4E1oHD8yf3E7h03HKB96RWAYFR2IMhNebJmsTxp3/EDhoF1K+0yIcJTedSu2iRsOyFEgHXGbrRsky5Bh",
|
||||||
"MryaordWCRpOdzgvw8vLptOCjqi0JrlFppZrn9hNs+kvLoX3MCmjEen0rPP7cmkCB0Xv4bzoXnRbeW+K",
|
"Qb+rSToyRETOwFzkpODVNpIn16E8R3nuCFOuW0ifv5quuUXvhFIbQZVnNV1zjtZxrb28vQRztI7KB5LX",
|
||||||
"COpl9IH7+no3vV7ecfspR++e5o23+/44W7/u1s36pTV9qtzlRuTtecqaep1daHe5OWuPHegb9v0JfoCk",
|
"m5KEyuJgvilarHdzURn5X6N12b4Gt5e34Pa+0Ws3Qbf1DBq9m2ZXvR6TMXHu2teNy7o+1GmjVT/vTWvP",
|
||||||
"es7dbGXYeOXjYvU+XzbEPevm74bGo3XaO3nCt+ZDpTci7dpkoOVnD7Ubo9vnw/xpB9ZJqellb2Zepdmg",
|
"V3P03qlAw+4/L6vw8rJtd6Atap1ZYZVrFLonVnva9laXwn2YVdGY9Abm+X21MoOjsvtwXnYu+p2iO0cE",
|
||||||
"mSZqPAyzr2795rYK29q4dZX3TatQ99GUnwz6IzK/exygemfhP3dKN90nenPbns+6d+ZibGWfzisz/1lr",
|
"DXL6yHl7u5tfr++49VSgd0/L1vv9cJJvXveb0+alOX+q3RXG5P1lztp6k11od4Ul605s6BnW/Ql+gKR+",
|
||||||
"i0lGv77KLaCvLVxe9U+vWh6azm5uewtnRJavYrJ8Nhl9wOhi6c2frdndXBDSrWSsfsPPtB4GbKgVc27j",
|
"zp187bn1xifl+n2xaoh71i/ePRuP5ung5AnfTh9qgzHpNmYjrbh4aNwY/SF/Lp72YJNU2m7+ZuHW2i2a",
|
||||||
"flCu6+NyYapfXQwuzO7UIdPLzIho5n2h2oNFrXCVX0y0qRij/Kyt3z7R2xu/XXvgV/2Zpt1fDqvLW+Qv",
|
"a6PWw3P+zWne3NZhV5t0rore1Cw1PTTnJ6PhmCzvHkeo2Vt5L73KTf+J3tx2l4v+3XQ1MfNP57WF96J1",
|
||||||
"Typl/T4zbNjd8jTff2hPRqSEms/WEndvtLmTHV6e99q678yn/LR64jtTK0sH4wLPv7nPs1utfEkHi8dC",
|
"xSynX18VVtDTVg6ve6dXHRfNFze3g5U9Jus3MVu/TBl9wOhi7S5fzMXdUhDSr+XMYcvLdR5G7FkrF5zW",
|
||||||
"bgLbxcf+ybX9jNCIVEraE32wx3q27fVPJuYznXDWEM+V2/H988lwdlHpecx4rLLJ1bg1zbW8Xru6GNgL",
|
"/aja1CfV0ly/uhhdTPtzm8wvc2OiTe9L9QEsa6Wr4mqmzcUEFRdd/faJ3t543cYDvxouNO3+8rm+vkXe",
|
||||||
"flflNfsyOyJax1/kHmG3plm5ZvFW7xqtjP46oVpF19mk9uTjxSPDReyfdp+8yusgY/bfrl1uNC1Sybw+",
|
"+qRW1e9zzy2rX50Xhw/d2ZhUUPvFXOP+jba088+X54Ou7tnLOT+tn3j23MzT0aTEi+/Oy+JWq17S0eqx",
|
||||||
"t0cEV+58x/TLZf/VfszMRW4sCBZWj79O7EXXnwzvC8/jgj0VFxW7fZ95eioXcq92p9ieV3vVu2ptRMT5",
|
"VJjBbvlxeHJtvSA0JrWK9kQfrIme77rDk9n0hc44a4mX2u3k/uXkeXFRG7jMeKyz2dWkMy903EG3vhpZ",
|
||||||
"xeXzY2+muw2rfd7NtvvVyrP7MB3nW3Zn0M12nmpL+Ji1deJUo+f6VWsG3YeJUS/ORkR39RN817qp1bq1",
|
"K35X5w3rMj8mWs9bFR5hv6GZhXb5Vu8bnZz+NqNaTdfZrPHk4dUjw2Xsnfaf3NrbKDcdvl873GibpJZ7",
|
||||||
"erVauMCNBroqucy+uCr7D/yu0+3mtGFRf7bJYli5qLpKh+qX88pFfT5tjkht3ry8uKOtepXXa7VhvTpv",
|
"e+mOCa7defbUq1a9N+sxtxSFiSBYmAP+NrNWfW/2fF96mZSsubioWd373NNTtVR4s3rl7rI+qN/VG2Mi",
|
||||||
"1K+sRv2iUK3WrendevbJ9bCaKdeGnuUs+9Xn4ZU9WbbtEcmcmKW3W/NhNr7KaY3X/LRZvrmoXWuk83RS",
|
"zi8uXx4HC91pmd3zfr47rNdenIf5pNixeqN+vvfUWMPHvKUTux4+1686C+g8zIxmeTEmuqOf4LvOTaPR",
|
||||||
"u8+6/qx/8jrw+/nHDqvl3fyl7wiv3Wu02h3hFhvnI5Jll29PVTrILr3TYbPSqZ4b3Xr9ZjmpTjh9vK+U",
|
"bzTr9dIFbrXQVcVh1sVV1Xvgd71+v6A9l/UXi6yeaxd1R+lQ83JZu2gu5+0xaSzblxd3tNOs82aj8dys",
|
||||||
"h/d+/SQzJhM2QL1cp3dTN5e39XLp8bRSxDcPI+IW+ydjfnc+L9dzHeYY1W6he+7T5XO2j8UlfC607zoP",
|
"L1vNK7PVvCjV601zfreZfXL9XM9VG8+uaa+H9ZfnK2u27lpjkjuZVt5vpw+LyVVBa70V5+3qzUXjWiO9",
|
||||||
"4mTQgNkC5sP+ZX3yRsu3w8pDvnUzLWojYr0+WpXcdWbs5hpv/fKgkn9snI+zzmxSaDqzhdV8bSMrm317",
|
"p5PGfd7xFsOTt5E3LD72WKPoFC89W7jdQavT7Qmn3Dofkzy7fH+q01F+7Z4+t2u9+rnRbzZv1rP6jNPH",
|
||||||
"Gi5cNuw/t1p1c/ZmnjjX/ZK/sK5GZLLItLSl85zr4PElK11Wq8ub0/tHVn3uz/tdraFPBpV5o04W0/65",
|
"+1r1+d5rnuQmZMZGaFDoDW6a0/Vts1p5PK2V8c3DmDjl4cmE350vq81Cj9lGvV/qn3t0/ZIfYnEJX0rd",
|
||||||
"v3x1H+cPs+vak99oPlRuUH44Il18nzVb1xVulM89frEodk+eDNIld/2TKzYZ3LbP8+4jc6oGaQxsY/hQ",
|
"u96DOBm1YL6E+fPwsjl7p9Xb59pDsXMzL2tjYr49mrXCdW7iFFrvw+qoVnxsnU/y9mJWatuLldl+6yIz",
|
||||||
"mTxPvUf7fMnzmdNTdDMi9lRjHbLUJtfzKfTNDL6v3Oilp1l3Oun0ui2reH/60F62/MdH8TZ/IpPudfGx",
|
"n39/el457Hn40uk0p4v36Yl9Pax4K/NqTGarXEdb2y+FHp5cssplvb6+Ob1/ZPWX4XLY11r6bFRbtppk",
|
||||||
"d1F7bRf4M3W73RExxXhwlT0pLse9x0w1P6uN4aL3mBPl+7frif6Gpv3nBoad69NO5kpv1Zu97N1FpVTJ",
|
"NR+ee+s353H5sLhuPHmt9kPtBhWfx6SP7/PTznWNG9Vzl1+syv2TJ4P0yd3w5IrNRrfd86LzyOy6QVoj",
|
||||||
"nRtVp3FxaozINGfd4WH/rgphS2u1qm9Xs9601+p0rHZueDfEV9cPy5zIt5YXJmfQLc779ccb075FzWWn",
|
"y3h+qM1e5u6jdb7mxdzpKboZE2uusR5Za7Pr5Rx60xy+r93oladFfz7rDfods3x/+tBdd7zHR/G+fCKz",
|
||||||
"NnhujciMedfO7RiZfHBaLA/MXO266Vtvz6xefFic99vTZ6tnZx8uZ/3mHakv36Z3y1LjPvd66+HH4qm0",
|
"/nX5cXDReOuW+At1+v0xmYrJ6Cp/Ul5PBo+5enHRmMDV4LEgqvfv1zP9Hc2HLy0Me9envdyV3mm2B/m7",
|
||||||
"UfZt8+mZtanezrc7/dMMfmvdDXqOmHSrf47In7fmoDwiyrs0rs8/cj2xORNVZH7h3Il3lS4S0MFkGu+/",
|
"i1qlVjg36nbr4tQYk3nBvMPPw7s6hB2t06m/Xy0G80Gn1zO7hee7Z3x1/bAuiGJnfTHlDDrl5bD5eDO1",
|
||||||
"XSzP+zzm2BXN+7v0ln8G71P53MjXtFxJRhB/rvI4nznzAIkTniG2iVjRIF+ndUQE5Qr/38N45c9KiguG",
|
"blF73WuMXjpjsmDutX07QVM+Oi1XR9NC47rtme8vrFl+WJ0Pu/MXc2DlHy4Xw/Ydaa7f53frSuu+8Hbr",
|
||||||
"oLuBGcr/lwrBE0WfPKLe9I+gZbOCH1vMwsSKIgYQlPlV+L6OGQDkMqzgAKu6wjrnrboHRuQPD3vIwQR9",
|
"4sfyqbRR1m376YV1qd4tdnvD0xx+79yNBraY9et/jclft9NRdUyUd2ldn3/kehJzJqrI/Mq5newqHSSg",
|
||||||
"j+0k2Mt6qreJZIJ+sU2D2dwNVhDUxaPi//aKzpFAzMUEcTC3UXiYCYoOWy3QKiwKgki1KpVRiQuXdiUs",
|
"jck82X87WJ73ecKxK5z3D+kt//LfZ4qFsadphYqMIP6K8jifOXMfiB2cIXaRiHCQr7M6IoJyBf8fQbzy",
|
||||||
"7ojQ3ymh78TgusCzoPobBnHbV0qQzpBIyVcb2+lBzueUxXYbyMjyJTZE3Y9QjxARTDi27J0rNIL5KBmj",
|
"Vy3DBUPQ2YIM5f8rJf+Jwk8eUW+GR+CyXcFPLGZhYoYRA/DL/Cp838QMAHIZVnCAVV1hk/NW3QNj8oeL",
|
||||||
"XpRZkISNLbuJkIKWzxUOZ0H2Sd7ckbTc3w3KPyV85xiwRVhyl+lbNGxwcGP1ceervRoxJMsjCvNxt57e",
|
"XWRjgv5M7CSIZT3DJiH6xTYNZnHHp8Cvi4fF/70GHCQQczBBHCwtFBxm/KLDTiu+Cov8IFJRpTIqSeHS",
|
||||||
"k5/O2b1C89mUvSL2pzj2b7K8/0juVUUxj3rvGYJO0KBECboxwdgXYJ9QqUxQqRcSgJojErP+NFBwXQRJ",
|
"voQlHRGGeyX0vRhcF3jhV3+DIG73ahPSGRIZ+WprO13I+ZKyxG4DGVm+Joao8Qj1CBHBhGPT2rvKJZiH",
|
||||||
"WDmCjgNiBoKA+3xEIEMAOpyG6ruHF67GhrXpGabqvocyQorgEWG+g4IGLIZMylASzBGw4WxVP1c7ClTp",
|
"0gnqRZkJSdDYsp8IKWnFQulwFiSO8vaOZOX+bmH+KeJ7x4AdxNL7TN/BYYuDW9Qnna/ifXVkfURhPun2",
|
||||||
"V65ujACcB5VIKNQNA06+iRHxKOd47KhpLl6oKrALhW4DlzIEQg4DQS1ldKTVW8nPoRTVRvJcUfsluVp1",
|
"3c/0p3P2r3J9NiVWxP4URvxG1WdTDrQY/vyejhVTMQ+vjjAEbb+viRJ0MwUTT4A4fVIHodJKJACdjkkC",
|
||||||
"NR4tVkfO2C3bfEGoohk/js6nb85bJdSPKYgEE8OKyKHuzDA1EPH5x86OfDGxznxCDmXPN8mJS5+neX6V",
|
"27JAresgSIKCE7RtkDAQ+JvGxwQyBKDNaaD1MbgwGhuUtBeYqkY4ZbsUwmPCPBv5fVsMTSlDabBEwIKL",
|
||||||
"2g6y5LFQOIppDlU1ve26zdqEqpexlyT3umZ3fQ/ndgoZuWIxewqq1Wq1nr9+g/Ws83zezF4PGkX5rHnN",
|
"qOyuBAGoirGkboIAXPoFTCjUBRlOvokxcSnneGKraQ5eqeKxA4VuAYcyBAIuA0FNZauksYzE7lBmayvn",
|
||||||
"LtsN1h3ik273fu5fwV615fY6tPnWM3Ov5znjvPim1QaLTGkRR8R+pt3niH2eeD5QhFO+RPcZFsu+FISA",
|
"rrD9kjhGTblHS+ORM/arPV+QxSNnJPdtqhaUr+feo+z9MdUXf2JQfjnUkhzkIcLd+b63j1/M4jOPkEOp",
|
||||||
"QTUEWcC4sfrrIvIbrcdBdFdVubFg3Aqq9JjBjVVMTLofHfXDmrqgYUijeluCykNQ8uUyQnCwjkiQFwsv",
|
"+m10knL1WV6M8uhhSn6Tck9ckaOE7mhVTNwtGG1st3qZeEs41ja+7/Q4tzLIKJTL+VNQr9frzeL1O2zm",
|
||||||
"yVY9qNsI5FRNQHm9VQA6n8/TUL1WUV84l2c6zXrjut9I5dJa2hauo3YQC8Wym35NoQ8LVwyo5hEAPbyR",
|
"7Zfzdv561CrLZ+1rdtltsf4zPun375feFRzUO86gR9vvg2nh7bxgnJfftcZolauskpCIp/g9jlj+uN7h",
|
||||||
"8DpL5BJBCxuRL84S+bSWzqrMsbAVmzJhy42SMMrjksAMQYEABATNQTg6CTwqEBFYeQKdEh42PanGxRli",
|
"uCtQTkz3GBbroRQKn0ENBJnPuIn66yJ0WJ3HUXhZW/lPf1y0qnTV/pVtTKY0HpYNg2K+oEEspZpq/JKH",
|
||||||
"MOKFYk/YBaSuGgddKJgBA8kpYUfLZjtc00icJW4pF+HSEoEUIC5q1FgGjXsqw6Z8r+c5OOhYyUzCNrz1",
|
"X2vmMjSxsY6In5ALbonXXahbCBRUMUK52yjyXS6XWaheq3AzmMtzvXazdT1sZQpZLWsJx1Y7iIVi2c2w",
|
||||||
"PeQjKn6rNvxtaZOhTnC5z6MkbFPPadlfjb1pBIh3WB68BDbkgAvIBDLkNhY07ZfhD0uc+7ibJPCs4U5H",
|
"ocAHFTMGVNcKgC7eyrSdpQopv3eOyBdnqWJWy+ZVylpYik25oNdHSRhNaptuqvZvAAFBSxCMTgOXCkQE",
|
||||||
"F0gD/Nl/P/6qL6SQTJEKx3FATYA9/+/Hfk+gL2zK8FtwBPAQkwEnWAlnQEnhP0HJlNA5We1DwITif0IE",
|
"Vr5Ep4QH3VaqY3KBGAx5odgTtB+pu/Z++wtmwEByStBKs92H1zZSZ6lbykVAWsqXAsRFgxprv2NQpfaU",
|
||||||
"7glaeEgXyACqdg6orvtMqsWmrVWBSWRl//ohY0buuy5ky7XRiIyLnBdZGp75iY135cPiWikvkQja1JQ3",
|
"03ddG/utMrlZ0P+3uYh/RKkxuoeyK20yxvJvt7qUBPc0Clr+V0NvGz7gPZb7L4EFOeACMoEMuY0lTftl",
|
||||||
"Vk2VIHSygDIF0UGStBCcarVTkqI7vrFxwqNMNd5IWBEPlStHBjL27c0lEtt3ZZJbH3P4K/6i6gpwQKyg",
|
"8IPaahx2m/i+Odjp8Aa1Dz//74df94QUkjlS5wDsY+NDL/77od8T6AmLMvzunz1cxGSkCyLh9DEp/Scw",
|
||||||
"wFLNm+ojCdLGrr+REF7A2LQvm19M+OX3Fn/sGS/tVxuvVcPCngRt8+W/Zrsiw/HbbP02W0eZrcGO4Tls",
|
"mRO6JNE++Ewo/ydE4J6glYt0gQygivaA6rrHpFps21oV2oRW9u/vMurknuNAtt4YjdC4yHmhpeG5H9j4",
|
||||||
"vzJO2MHwzxgxExPM7Q0bBj40YVisLVdSBVTqBOwiAYEMUqUhwJQAOKa+iL4z4DviIyunGjB+27hPbVx4",
|
"qXxYUg/nJRJ+f5zyzKqbEwQOF1CmVrSRfx1FLad6/JSk6LZnbB0tKVMdP+oGS8BD5daRgYy4vblEYvey",
|
||||||
"Cfo9GdMmLkVg1WoffJtjFR9jAghVyVCs+w5kYW8x+EPY1LfsMH3R6t9cf0/H20eBFiLjORDvEB3zbZ3j",
|
"WHrnayZ/J9/Ujhb2kRUUmKprVH0lRNrYzUdCghtI2/Zl+5Mhv/zi7veY8dJ+tfGKOiViErTLl/8x2xUa",
|
||||||
"rGDhVyGI0/H3TTW6VH3kVpQ2jqQ8To22LnR/qEurkUeoUw8JnxGuvnUSzVPEqCNI2JhLNj+QkgaqeXw1",
|
"jt9m67fZOspsjfYMz2H7lbOD1ol/xohNMcHc2rJh4EMThsXGcqVVQKXO0A4SEMggVRoCTAmAE+qJ8EMb",
|
||||||
"WKdKsXjUNR9un4FMTJABoACbhzfK1VkwqBlAkgl/pyJw6eIHqri+KP9bHz/VxzWzDijl1nbvKeb/n7q2",
|
"ni0+snKq8+O3jfvUxgVfAfiZTuhPlyIQ9fj7H6eJ4mNMAKEqC4t1z4YsaGoGfwiLeqYVJEA6w5vrP7PJ",
|
||||||
"rR5HKN1Ga9DHOhcODFRuT8+CWy5oAXWx5YiYUj9kAAN5iBhSDzd1LfrSUXD34iPNiOj8rRifK8bqWwwH",
|
"9lGglci5NsR7SCd8XOo4K1j6VQCSdPznthpdqgZ2M8xXh1KepEY7XzT4UJeikUeo0wAJjxGuPvYTXfSU",
|
||||||
"9CLayq/oxe8Y/XeM/v9ajL5nm+LsnQK+GVPsmZj11do94xK3svWQjOq6PVQA2Rin2nL/raq/XkOctAdf",
|
"yKgjSNARTLa/EJQFqms9GqxTpVg8bNcPts9AU0yQAaAA24e34NKmX6yAJLzEmQmXy5Y/UMXNlyJ+6+On",
|
||||||
"eKEmCJnxW83+O2oWCPr/npLBlQBBxwGrWmckTWs1+zyhB0lQIiH66lN4AWXrW8DjJVCuM15Rj4sAVnD/",
|
"+rhh1gGl3NnumGL+/6lru+pxhNJt9SR9rHPBQF/lYnrmX69BK6iLHUfElPohAxjIRcTgm5vUStfCu9D+",
|
||||||
"Va+f/w/78INbqV6AzWe/tfi3Fn9Fi9G+BEnNXZUED3vIm3BIvNxvExuCU/osT9aSB+GZ+X8xtvhwOe+r",
|
"pY+PNCPE87difK4Y0cdIDuhFuJVf0YvfMfrvGP3/tRg9ZpuS7J1afDumiJmYzZ3emHFJomwzJKfafQ8V",
|
||||||
"5qU4S9QNryRTw9eDe/Sr+1LbRV/o4bTEw20cfoYSejgT3GRT2QPEUtH3EDKznIo4dkrRAlqYWB8h4AJa",
|
"RLbGqX7gf6vqb2hIknb/E0d0CgJm/Faz/xk18wX9f5+SwUiAoG2DqFoaStNGzT5P6EHil0iIHn0L0sds",
|
||||||
"6F9Eo5hIoivTKzSfwfnx/n8DAAD//6klz9IeWwAA",
|
"c/14sgbKdSYr6nERQLTuv+r1i/9hH35wK9ULsP3stxb/1uKvaDGKS5DU3KgkeNhD3gRDkuV+F9lgOaXP",
|
||||||
|
"8mQteRCcmf83xhYfkvMz6ppKskT94C40NTzdv8AfXdTaLfpCF2clHG7h4Dus0MU5/wqdyh4glgk/xJBb",
|
||||||
|
"FFTEsVeKFtDExPwIABfQRP8iGMVEEt7VjsB8ts73n/83AAD//6lVbrsfXgAA",
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSwagger returns the content of the embedded swagger specification file
|
// GetSwagger returns the content of the embedded swagger specification file
|
||||||
|
|
|
||||||
|
|
@ -511,6 +511,7 @@ components:
|
||||||
- $ref: '#/components/schemas/AWSS3UploadStatus'
|
- $ref: '#/components/schemas/AWSS3UploadStatus'
|
||||||
- $ref: '#/components/schemas/GCPUploadStatus'
|
- $ref: '#/components/schemas/GCPUploadStatus'
|
||||||
- $ref: '#/components/schemas/AzureUploadStatus'
|
- $ref: '#/components/schemas/AzureUploadStatus'
|
||||||
|
- $ref: '#/components/schemas/ContainerUploadStatus'
|
||||||
UploadStatusValue:
|
UploadStatusValue:
|
||||||
type: string
|
type: string
|
||||||
enum: ['success', 'failure', 'pending', 'running']
|
enum: ['success', 'failure', 'pending', 'running']
|
||||||
|
|
@ -521,6 +522,7 @@ components:
|
||||||
- aws.s3
|
- aws.s3
|
||||||
- gcp
|
- gcp
|
||||||
- azure
|
- azure
|
||||||
|
- container
|
||||||
AWSEC2UploadStatus:
|
AWSEC2UploadStatus:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
|
|
@ -566,7 +568,22 @@ components:
|
||||||
build_id:
|
build_id:
|
||||||
type: integer
|
type: integer
|
||||||
example: 42
|
example: 42
|
||||||
|
ContainerUploadStatus:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
required:
|
||||||
|
- url
|
||||||
|
- digest
|
||||||
|
properties:
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
example: 'quay.io/myaccount/osbuild:latest'
|
||||||
|
description: |
|
||||||
|
FQDN of the uploaded image
|
||||||
|
digest:
|
||||||
|
type: string
|
||||||
|
description: |
|
||||||
|
Digest of the manifest of the uploaded container on the registry
|
||||||
ComposeMetadata:
|
ComposeMetadata:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: '#/components/schemas/ObjectReference'
|
- $ref: '#/components/schemas/ObjectReference'
|
||||||
|
|
@ -700,6 +717,7 @@ components:
|
||||||
- $ref: '#/components/schemas/AWSS3UploadOptions'
|
- $ref: '#/components/schemas/AWSS3UploadOptions'
|
||||||
- $ref: '#/components/schemas/GCPUploadOptions'
|
- $ref: '#/components/schemas/GCPUploadOptions'
|
||||||
- $ref: '#/components/schemas/AzureUploadOptions'
|
- $ref: '#/components/schemas/AzureUploadOptions'
|
||||||
|
- $ref: '#/components/schemas/ContainerUploadOptions'
|
||||||
description: |
|
description: |
|
||||||
This should really be oneOf but AWSS3UploadOptions is a subset of
|
This should really be oneOf but AWSS3UploadOptions is a subset of
|
||||||
AWSEC2UploadOptions. This means that all AWSEC2UploadOptions objects
|
AWSEC2UploadOptions. This means that all AWSEC2UploadOptions objects
|
||||||
|
|
@ -824,6 +842,23 @@ components:
|
||||||
Name of the uploaded image. It must be unique in the given resource group.
|
Name of the uploaded image. It must be unique in the given resource group.
|
||||||
If name is omitted from the request, a random one based on a UUID is
|
If name is omitted from the request, a random one based on a UUID is
|
||||||
generated.
|
generated.
|
||||||
|
ContainerUploadOptions:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- tag
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
example: 'osbuild'
|
||||||
|
description: |
|
||||||
|
Name for the created container image
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
example: 'latest'
|
||||||
|
description: |
|
||||||
|
Tag for the created container image
|
||||||
Customizations:
|
Customizations:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,10 @@ func (cl *Client) SetCredentials(username, password string) {
|
||||||
cl.sysCtx.DockerAuthConfig.Password = password
|
cl.sysCtx.DockerAuthConfig.Password = password
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cl *Client) SetDockerCertPath(path string) {
|
||||||
|
cl.sysCtx.DockerCertPath = path
|
||||||
|
}
|
||||||
|
|
||||||
// SetSkipTLSVerify controls if TLS verification happens when
|
// SetSkipTLSVerify controls if TLS verification happens when
|
||||||
// making requests. If nil is passed it falls back to the default.
|
// making requests. If nil is passed it falls back to the default.
|
||||||
func (cl *Client) SetTLSVerify(verify *bool) {
|
func (cl *Client) SetTLSVerify(verify *bool) {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,13 @@ func NewContainerTarget(options *ContainerTargetOptions) *Target {
|
||||||
return newTarget(TargetNameContainer, options)
|
return newTarget(TargetNameContainer, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContainerTargetResult() *TargetResult {
|
type ContainerTargetResultOptions struct {
|
||||||
return newTargetResult(TargetNameContainer, nil)
|
URL string `json:"url"`
|
||||||
|
Digest string `json:"digest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ContainerTargetResultOptions) isTargetResultOptions() {}
|
||||||
|
|
||||||
|
func NewContainerTargetResult(options *ContainerTargetResultOptions) *TargetResult {
|
||||||
|
return newTargetResult(TargetNameContainer, options)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,8 @@ func UnmarshalTargetResultOptions(trName TargetName, rawOptions json.RawMessage)
|
||||||
options = new(KojiTargetResultOptions)
|
options = new(KojiTargetResultOptions)
|
||||||
case TargetNameOCI:
|
case TargetNameOCI:
|
||||||
options = new(OCITargetResultOptions)
|
options = new(OCITargetResultOptions)
|
||||||
|
case TargetNameContainer:
|
||||||
|
options = new(ContainerTargetResultOptions)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unexpected target result name: %s", trName)
|
return nil, fmt.Errorf("unexpected target result name: %s", trName)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue