diff --git a/registry/app/api/controller/metadata/get_client_setup_details.go b/registry/app/api/controller/metadata/get_client_setup_details.go index 1000345f1..5ac415c4a 100644 --- a/registry/app/api/controller/metadata/get_client_setup_details.go +++ b/registry/app/api/controller/metadata/get_client_setup_details.go @@ -113,8 +113,9 @@ func (c *APIController) GenerateClientSetupDetails( loginUsernameValue := "" loginPasswordLabel := "Password: *see step 2*" blankString := "" - // Fixme: Use ENUMS - if packageType == "HELM" { + if packageType == string(artifact.PackageTypeMAVEN) { + return c.generateMavenClientSetupDetail(ctx, image, tag, registryRef, username) + } else if packageType == string(artifact.PackageTypeHELM) { header1 := "Login to Helm" section1step1Header := "Run this Helm command in your terminal to authenticate the client." helmLoginValue := "helm registry login " @@ -126,7 +127,7 @@ func (c *APIController) GenerateClientSetupDetails( section1step1Type := artifact.ClientSetupStepTypeStatic section1step2Header := "For the Password field above, generate an identity token" section1step2Type := artifact.ClientSetupStepTypeGenerateToken - section1 := []artifact.ClientSetupStep{ + section1Steps := []artifact.ClientSetupStep{ { Header: §ion1step1Header, Commands: §ion1step1Commands, @@ -137,6 +138,12 @@ func (c *APIController) GenerateClientSetupDetails( Type: §ion1step2Type, }, } + section1 := artifact.ClientSetupSection{ + Header: &header1, + } + _ = section1.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: §ion1Steps, + }) header2 := "Push a version" section2step1Header := "Run this Helm push command in your terminal to push a chart in OCI form." + @@ -146,13 +153,19 @@ func (c *APIController) GenerateClientSetupDetails( {Label: &blankString, Value: &helmPushValue}, } section2step1Type := artifact.ClientSetupStepTypeStatic - section2 := []artifact.ClientSetupStep{ + section2Steps := []artifact.ClientSetupStep{ { Header: §ion2step1Header, Commands: §ion2step1Commands, Type: §ion2step1Type, }, } + section2 := artifact.ClientSetupSection{ + Header: &header2, + } + _ = section2.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: §ion2Steps, + }) header3 := "Pull a version" section3step1Header := "Run this Helm command in your terminal to pull a specific chart version." @@ -161,33 +174,30 @@ func (c *APIController) GenerateClientSetupDetails( {Label: &blankString, Value: &helmPullValue}, } section3step1Type := artifact.ClientSetupStepTypeStatic - section3 := []artifact.ClientSetupStep{ + section3Steps := []artifact.ClientSetupStep{ { Header: §ion3step1Header, Commands: §ion3step1Commands, Type: §ion3step1Type, }, } + section3 := artifact.ClientSetupSection{ + Header: &header3, + } + _ = section3.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: §ion3Steps, + }) clientSetupDetails := artifact.ClientSetupDetails{ MainHeader: "Helm Client Setup", SecHeader: "Follow these instructions to install/use Helm artifacts or compatible packages.", Sections: []artifact.ClientSetupSection{ - { - Header: &header1, - Steps: §ion1, - }, - { - Header: &header2, - Steps: §ion2, - }, - { - Header: &header3, - Steps: §ion3, - }, + section1, + section2, + section3, }, } - c.replacePlaceholders(ctx, clientSetupDetails, username, registryRef, image, tag) + c.replacePlaceholders(ctx, &clientSetupDetails.Sections, username, registryRef, image, tag, "", "") return &artifact.ClientSetupDetailsResponseJSONResponse{ Data: clientSetupDetails, @@ -205,7 +215,7 @@ func (c *APIController) GenerateClientSetupDetails( section1step1Type := artifact.ClientSetupStepTypeStatic section1step2Header := "For the Password field above, generate an identity token" section1step2Type := artifact.ClientSetupStepTypeGenerateToken - section1 := []artifact.ClientSetupStep{ + section1Steps := []artifact.ClientSetupStep{ { Header: §ion1step1Header, Commands: §ion1step1Commands, @@ -216,6 +226,12 @@ func (c *APIController) GenerateClientSetupDetails( Type: §ion1step2Type, }, } + section1 := artifact.ClientSetupSection{ + Header: &header1, + } + _ = section1.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: §ion1Steps, + }) header2 := "Pull an image" section2step1Header := "Run this Docker command in your terminal to pull image." dockerPullValue := "docker pull //:" @@ -223,13 +239,19 @@ func (c *APIController) GenerateClientSetupDetails( {Label: &blankString, Value: &dockerPullValue}, } section2step1Type := artifact.ClientSetupStepTypeStatic - section2 := []artifact.ClientSetupStep{ + section2Steps := []artifact.ClientSetupStep{ { Header: §ion2step1Header, Commands: §ion2step1Commands, Type: §ion2step1Type, }, } + section2 := artifact.ClientSetupSection{ + Header: &header2, + } + _ = section2.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: §ion2Steps, + }) header3 := "Retag and Push the image" section3step1Header := "Run this Docker command in your terminal to tag the image." dockerTagValue := "docker tag : //:" @@ -243,7 +265,7 @@ func (c *APIController) GenerateClientSetupDetails( {Label: &blankString, Value: &dockerPushValue}, } section3step2Type := artifact.ClientSetupStepTypeStatic - section3 := []artifact.ClientSetupStep{ + section3Steps := []artifact.ClientSetupStep{ { Header: §ion3step1Header, Commands: §ion3step1Commands, @@ -255,26 +277,344 @@ func (c *APIController) GenerateClientSetupDetails( Type: §ion3step2Type, }, } + section3 := artifact.ClientSetupSection{ + Header: &header3, + } + _ = section3.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: §ion3Steps, + }) clientSetupDetails := artifact.ClientSetupDetails{ MainHeader: "Docker Client Setup", SecHeader: "Follow these instructions to install/use Docker artifacts or compatible packages.", Sections: []artifact.ClientSetupSection{ - { - Header: &header1, - Steps: §ion1, - }, - { - Header: &header3, - Steps: §ion3, - }, - { - Header: &header2, - Steps: §ion2, - }, + section1, + section2, + section3, }, } - c.replacePlaceholders(ctx, clientSetupDetails, username, registryRef, image, tag) + c.replacePlaceholders(ctx, &clientSetupDetails.Sections, username, registryRef, image, tag, "", "") + + return &artifact.ClientSetupDetailsResponseJSONResponse{ + Data: clientSetupDetails, + Status: artifact.StatusSUCCESS, + } +} + +func (c *APIController) generateMavenClientSetupDetail( + ctx context.Context, + artifactName *artifact.ArtifactParam, + version *artifact.VersionParam, + registryRef string, + username string, +) *artifact.ClientSetupDetailsResponseJSONResponse { + staticStepType := artifact.ClientSetupStepTypeStatic + generateTokenStepType := artifact.ClientSetupStepTypeGenerateToken + + section1 := artifact.ClientSetupSection{ + Header: stringPtr("1. Generate Identity Token"), + SecHeader: stringPtr("An identity token will serve as the password for uploading and downloading artifacts."), + } + _ = section1.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: &[]artifact.ClientSetupStep{ + { + Header: stringPtr("Generate an identity token"), + Type: &generateTokenStepType, + }, + }, + }) + + mavenSection1 := artifact.ClientSetupSection{ + Header: stringPtr("2. Pull a Maven Package"), + SecHeader: stringPtr("Set default repository in your pom.xml file."), + } + _ = mavenSection1.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: &[]artifact.ClientSetupStep{ + { + Header: stringPtr("To set default registry in your pom.xml file by adding the following:"), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + //nolint:lll + Value: stringPtr("\n \n maven-dev\n /\n \n true\n always\n \n \n true\n always\n \n \n"), + }, + }, + }, + { + //nolint:lll + Header: stringPtr("Copy the following your ~/ .m2/setting.xml file for MacOs, or $USERPROFILE$\\ .m2\\settings.xml for Windows to authenticate with token to pull from your Maven registry."), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + //nolint:lll + Value: stringPtr("\n \n \n maven-dev\n \n identity-token\n \n \n"), + }, + }, + }, + { + //nolint:lll + Header: stringPtr("Add a dependency to the project's pom.xml (replace , & with your own):"), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + //nolint:lll + Value: stringPtr("\n \n \n \n"), + }, + }, + }, + { + Header: stringPtr("Install dependencies in pom.xml file"), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + Value: stringPtr("mvn install"), + }, + }, + }, + }, + }) + + mavenSection2 := artifact.ClientSetupSection{ + Header: stringPtr("3. Push a Maven Package"), + SecHeader: stringPtr("Set default repository in your pom.xml file."), + } + + _ = mavenSection2.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: &[]artifact.ClientSetupStep{ + { + Header: stringPtr("To set default registry in your pom.xml file by adding the following:"), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + //nolint:lll + Value: stringPtr("\n \n maven-dev\n /\n \n \n maven-dev\n /\n \n"), + }, + }, + }, + { + //nolint:lll + Header: stringPtr("Copy the following your ~/ .m2/setting.xml file for MacOs, or $USERPROFILE$\\ .m2\\settings.xml for Windows to authenticate with token to push to your Maven registry."), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + //nolint:lll + Value: stringPtr("\n \n \n maven-dev\n \n identity-token\n \n \n"), + }, + }, + }, + { + Header: stringPtr("Publish package to your Maven registry."), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + Value: stringPtr("mvn deploy"), + }, + }, + }, + }, + }) + + gradleSection1 := artifact.ClientSetupSection{ + Header: stringPtr("2. Pull a Gradle Package"), + SecHeader: stringPtr("Set default repository in your build.gradle file."), + } + _ = gradleSection1.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: &[]artifact.ClientSetupStep{ + { + Header: stringPtr("Set the default registry in your project’s build.gradle by adding the following:"), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + //nolint:lll + Value: stringPtr("repositories{\n maven{\n url “/”\n\n credentials {\n username “”\n password “identity-token”\n }\n }\n}"), + }, + }, + }, + { + //nolint:lll + Header: stringPtr("As this is a private registry, you’ll need to authenticate. Create or add to the ~/.gradle/gradle.properties file with the following:"), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + Value: stringPtr("repositoryUser=\nrepositoryPassword={{identity-token}}"), + }, + }, + }, + { + Header: stringPtr("Add a dependency to the project’s build.gradle"), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + Value: stringPtr("dependencies {\n implementation ‘::’\n}"), + }, + }, + }, + { + Header: stringPtr("Install dependencies in build.gradle file"), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + Value: stringPtr("gradlew build // Linux or OSX\n gradlew.bat build // Windows"), + }, + }, + }, + }, + }) + + gradleSection2 := artifact.ClientSetupSection{ + Header: stringPtr("3. Push a Gradle Package"), + SecHeader: stringPtr("Set default repository in your build.gradle file."), + } + + _ = gradleSection2.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: &[]artifact.ClientSetupStep{ + { + Header: stringPtr("Add a maven publish plugin configuration to the project’s build.gradle."), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + //nolint:lll + Value: stringPtr("publishing {\n publications {\n maven(MavenPublication) {\n groupId = ''\n artifactId = ''\n version = ''\n\n from components.java\n }\n }\n}"), + }, + }, + }, + { + Header: stringPtr("Publish package to your Maven registry."), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + Value: stringPtr("gradlew publish"), + }, + }, + }, + }, + }) + + sbtSection1 := artifact.ClientSetupSection{ + Header: stringPtr("2. Pull a Sbt/Scala Package"), + SecHeader: stringPtr("Set default repository in your build.sbt file."), + } + _ = sbtSection1.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: &[]artifact.ClientSetupStep{ + { + Header: stringPtr("Set the default registry in your project’s build.sbt by adding the following:"), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + //nolint:lll + Value: stringPtr("resolver += “Harness Registry” at “/”\ncredentials += Credentials(Path.userHome / “.sbt” / “.Credentials”)"), + }, + }, + }, + { + //nolint:lll + Header: stringPtr("As this is a private registry, you’ll need to authenticate. Create or add to the ~/.sbt/.credentials file with the following:"), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + //nolint:lll + Value: stringPtr("realm=Harness Registry\nhost=\nuser=\npassword={{identity-token}}"), + }, + }, + }, + { + Header: stringPtr("Add a dependency to the project’s build.sbt"), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + Value: stringPtr("libraryDependencies += “” % “” % “”"), + }, + }, + }, + { + Header: stringPtr("Install dependencies in build.sbt file"), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + Value: stringPtr("sbt update"), + }, + }, + }, + }, + }) + + sbtSection2 := artifact.ClientSetupSection{ + Header: stringPtr("3. Push a Sbt/Scala Package"), + SecHeader: stringPtr("Set default repository in your build.sbt file."), + } + + _ = sbtSection2.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{ + Steps: &[]artifact.ClientSetupStep{ + { + Header: stringPtr("Add publish configuration to the project’s build.sbt."), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + Value: stringPtr("publishTo := Some(\"Harness Registry\" at \"/\")"), + }, + }, + }, + { + Header: stringPtr("Publish package to your Maven registry."), + Type: &staticStepType, + Commands: &[]artifact.ClientSetupStepCommand{ + { + Value: stringPtr("sbt publish"), + }, + }, + }, + }, + }) + + section2 := artifact.ClientSetupSection{} + _ = section2.FromTabSetupStepConfig(artifact.TabSetupStepConfig{ + Tabs: &[]artifact.TabSetupStep{ + { + Header: stringPtr("Maven"), + Sections: &[]artifact.ClientSetupSection{ + mavenSection1, + mavenSection2, + }, + }, + { + Header: stringPtr("Gradle"), + Sections: &[]artifact.ClientSetupSection{ + gradleSection1, + gradleSection2, + }, + }, + { + Header: stringPtr("Sbt/Scala"), + Sections: &[]artifact.ClientSetupSection{ + sbtSection1, + sbtSection2, + }, + }, + }, + }) + + clientSetupDetails := artifact.ClientSetupDetails{ + MainHeader: "Maven Client Setup", + SecHeader: "Follow these instructions to install/use Maven artifacts or compatible packages.", + Sections: []artifact.ClientSetupSection{ + section1, + section2, + }, + } + groupID := "" + if artifactName != nil { + parts := strings.Split(string(*artifactName), ":") + if len(parts) == 2 { + groupID = parts[0] + *artifactName = artifact.ArtifactParam(parts[1]) + } + } + + rootSpace, _, _ := paths.DisectRoot(registryRef) + registryURL := c.URLProvider.RegistryURL(ctx, "maven", rootSpace) + + //nolint:lll + c.replacePlaceholders(ctx, &clientSetupDetails.Sections, username, registryRef, artifactName, version, registryURL, groupID) return &artifact.ClientSetupDetailsResponseJSONResponse{ Data: clientSetupDetails, @@ -284,29 +624,54 @@ func (c *APIController) GenerateClientSetupDetails( func (c *APIController) replacePlaceholders( ctx context.Context, - clientSetupDetails artifact.ClientSetupDetails, + clientSetupSections *[]artifact.ClientSetupSection, username string, regRef string, image *artifact.ArtifactParam, tag *artifact.VersionParam, + registryURL string, + groupID string, +) { + for i := range *clientSetupSections { + tab, err := (*clientSetupSections)[i].AsTabSetupStepConfig() + if err != nil || tab.Tabs == nil { + c.replacePlaceholdersInSection(ctx, &(*clientSetupSections)[i], username, regRef, image, tag, groupID, registryURL) + } else { + for j := range *tab.Tabs { + c.replacePlaceholders(ctx, (*tab.Tabs)[j].Sections, username, regRef, image, tag, groupID, registryURL) + } + _ = (*clientSetupSections)[i].FromTabSetupStepConfig(tab) + } + } +} + +func (c *APIController) replacePlaceholdersInSection( + ctx context.Context, + clientSetupSection *artifact.ClientSetupSection, + username string, + regRef string, + image *artifact.ArtifactParam, + tag *artifact.VersionParam, + registryURL string, + groupID string, ) { rootSpace, _, _ := paths.DisectRoot(regRef) _, registryName, _ := paths.DisectLeaf(regRef) hostname := common.TrimURLScheme(c.URLProvider.RegistryURL(ctx, rootSpace)) - for _, s := range clientSetupDetails.Sections { - if s.Steps == nil { + sec, err := clientSetupSection.AsClientSetupStepConfig() + if err != nil || sec.Steps == nil { + return + } + for _, st := range *sec.Steps { + if st.Commands == nil { continue } - for _, st := range *s.Steps { - if st.Commands == nil { - continue - } - for i := range *st.Commands { - replaceText(username, st, i, hostname, registryName, image, tag) - } + for j := range *st.Commands { + replaceText(username, st, j, hostname, registryName, image, tag, registryURL, groupID) } } + _ = clientSetupSection.FromClientSetupStepConfig(sec) } func replaceText( @@ -317,10 +682,20 @@ func replaceText( repoName string, image *artifact.ArtifactParam, tag *artifact.VersionParam, + registryURL string, + groupID string, ) { if username != "" { (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", username)) - (*st.Commands)[i].Label = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Label, "", username)) + if (*st.Commands)[i].Label != nil { + (*st.Commands)[i].Label = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Label, "", username)) + } + } + if groupID != "" { + (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", groupID)) + } + if registryURL != "" { + (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", registryURL)) } if hostname != "" { (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", hostname)) @@ -334,9 +709,11 @@ func replaceText( } if image != nil { (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", string(*image))) + (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", string(*image))) } if tag != nil { (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", string(*tag))) + (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", string(*tag))) } } diff --git a/registry/app/api/controller/metadata/utils.go b/registry/app/api/controller/metadata/utils.go index 05a13064e..e054d716d 100644 --- a/registry/app/api/controller/metadata/utils.go +++ b/registry/app/api/controller/metadata/utils.go @@ -108,6 +108,7 @@ var validUpstreamSources = []string{ string(a.UpstreamConfigSourceCustom), string(a.UpstreamConfigSourceDockerhub), string(a.UpstreamConfigSourceAwsEcr), + string(a.UpstreamConfigSourceMavenCentral), } func ValidatePackageTypes(packageTypes []string) error { @@ -163,7 +164,8 @@ func ValidateUpstream(config *a.RegistryConfig) error { return err } if !commons.IsEmpty(config.Type) && config.Type == a.RegistryTypeUPSTREAM && - *upstreamConfig.Source != a.UpstreamConfigSourceDockerhub { + *upstreamConfig.Source != a.UpstreamConfigSourceDockerhub && + *upstreamConfig.Source != a.UpstreamConfigSourceMavenCentral { if commons.IsEmpty(upstreamConfig.Url) { return errors.New("URL is required for upstream repository") } diff --git a/registry/app/api/middleware/auth.go b/registry/app/api/middleware/auth.go index 241fa7f9d..2183acc1f 100644 --- a/registry/app/api/middleware/auth.go +++ b/registry/app/api/middleware/auth.go @@ -107,7 +107,7 @@ func CheckMavenAuth() func(http.Handler) http.Handler { } func setMavenHeaders(w http.ResponseWriter) { - w.Header().Set("WWW-Authenticate", "Basic realm=\"Maven API\"") + w.Header().Set("WWW-Authenticate", "Basic realm=\"Harness Registry\"") } func getRefsFromName(name string) (spaceRef, repoRef string) { diff --git a/registry/app/api/openapi/api.yaml b/registry/app/api/openapi/api.yaml index 1b5d38441..28d139860 100644 --- a/registry/app/api/openapi/api.yaml +++ b/registry/app/api/openapi/api.yaml @@ -1535,10 +1535,46 @@ components: properties: header: type: string + secHeader: + type: string + type: + $ref: "#/components/schemas/SectionType" + discriminator: + propertyName: type + mapping: + INLINE: "#/components/schemas/ClientSetupStepConfig" + TABS: "#/components/schemas/TabSetupStepConfig" + oneOf: + - $ref: "#/components/schemas/ClientSetupStepConfig" + - $ref: "#/components/schemas/TabSetupStepConfig" + required: + - type + TabSetupStepConfig: + type: object + description: Tab Setup step config + properties: + tabs: + type: array + items: + $ref: "#/components/schemas/TabSetupStep" + ClientSetupStepConfig: + type: object + description: Client Setup Step + properties: steps: type: array items: $ref: "#/components/schemas/ClientSetupStep" + TabSetupStep: + type: object + description: Tab Setup step + properties: + header: + type: string + sections: + type: array + items: + $ref: "#/components/schemas/ClientSetupSection" ClientSetupStep: type: object description: Client Setup Step @@ -2153,6 +2189,14 @@ components: - MAVEN - GENERIC - HELM + SectionType: + type: string + description: refers to client setup section type + enum: + - INLINE + - TABS + discriminator: + propertyName: type Status: type: string description: "Indicates if the request was successful or not" diff --git a/registry/app/api/openapi/contracts/artifact/services.gen.go b/registry/app/api/openapi/contracts/artifact/services.gen.go index 11a216ca8..825cb3f2a 100644 --- a/registry/app/api/openapi/contracts/artifact/services.gen.go +++ b/registry/app/api/openapi/contracts/artifact/services.gen.go @@ -5723,94 +5723,96 @@ func (sh *strictHandler) GetAllRegistries(w http.ResponseWriter, r *http.Request // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "6st9/PXj+v8DAAD//9MnwuCj3gAA", + "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", + "Xm7jrx/X/x8AAP//M3nlRXDiAAA=", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/registry/app/api/openapi/contracts/artifact/types.gen.go b/registry/app/api/openapi/contracts/artifact/types.gen.go index 025134078..3aee27a5e 100644 --- a/registry/app/api/openapi/contracts/artifact/types.gen.go +++ b/registry/app/api/openapi/contracts/artifact/types.gen.go @@ -38,6 +38,12 @@ const ( RegistryTypeVIRTUAL RegistryType = "VIRTUAL" ) +// Defines values for SectionType. +const ( + SectionTypeINLINE SectionType = "INLINE" + SectionTypeTABS SectionType = "TABS" +) + // Defines values for Status. const ( StatusERROR Status = "ERROR" @@ -195,8 +201,12 @@ type ClientSetupDetails struct { // ClientSetupSection Client Setup Section type ClientSetupSection struct { - Header *string `json:"header,omitempty"` - Steps *[]ClientSetupStep `json:"steps,omitempty"` + Header *string `json:"header,omitempty"` + SecHeader *string `json:"secHeader,omitempty"` + + // Type refers to client setup section type + Type SectionType `json:"type"` + union json.RawMessage } // ClientSetupStep Client Setup Step @@ -214,6 +224,11 @@ type ClientSetupStepCommand struct { Value *string `json:"value,omitempty"` } +// ClientSetupStepConfig Client Setup Step +type ClientSetupStepConfig struct { + Steps *[]ClientSetupStep `json:"steps,omitempty"` +} + // ClientSetupStepType ClientSetupStepType type type ClientSetupStepType string @@ -545,9 +560,23 @@ type RegistryRequest struct { // RegistryType refers to type of registry i.e virtual or upstream type RegistryType string +// SectionType refers to client setup section type +type SectionType string + // Status Indicates if the request was successful or not type Status string +// TabSetupStep Tab Setup step +type TabSetupStep struct { + Header *string `json:"header,omitempty"` + Sections *[]ClientSetupSection `json:"sections,omitempty"` +} + +// TabSetupStepConfig Tab Setup step config +type TabSetupStepConfig struct { + Tabs *[]TabSetupStep `json:"tabs,omitempty"` +} + // Trigger refers to trigger type Trigger string @@ -1475,6 +1504,160 @@ func (t *ArtifactDetail) UnmarshalJSON(b []byte) error { return err } +// AsClientSetupStepConfig returns the union data inside the ClientSetupSection as a ClientSetupStepConfig +func (t ClientSetupSection) AsClientSetupStepConfig() (ClientSetupStepConfig, error) { + var body ClientSetupStepConfig + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromClientSetupStepConfig overwrites any union data inside the ClientSetupSection as the provided ClientSetupStepConfig +func (t *ClientSetupSection) FromClientSetupStepConfig(v ClientSetupStepConfig) error { + t.Type = "INLINE" + + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeClientSetupStepConfig performs a merge with any union data inside the ClientSetupSection, using the provided ClientSetupStepConfig +func (t *ClientSetupSection) MergeClientSetupStepConfig(v ClientSetupStepConfig) error { + t.Type = "INLINE" + + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +// AsTabSetupStepConfig returns the union data inside the ClientSetupSection as a TabSetupStepConfig +func (t ClientSetupSection) AsTabSetupStepConfig() (TabSetupStepConfig, error) { + var body TabSetupStepConfig + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromTabSetupStepConfig overwrites any union data inside the ClientSetupSection as the provided TabSetupStepConfig +func (t *ClientSetupSection) FromTabSetupStepConfig(v TabSetupStepConfig) error { + t.Type = "TABS" + + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeTabSetupStepConfig performs a merge with any union data inside the ClientSetupSection, using the provided TabSetupStepConfig +func (t *ClientSetupSection) MergeTabSetupStepConfig(v TabSetupStepConfig) error { + t.Type = "TABS" + + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + +func (t ClientSetupSection) Discriminator() (string, error) { + var discriminator struct { + Discriminator string `json:"type"` + } + err := json.Unmarshal(t.union, &discriminator) + return discriminator.Discriminator, err +} + +func (t ClientSetupSection) ValueByDiscriminator() (interface{}, error) { + discriminator, err := t.Discriminator() + if err != nil { + return nil, err + } + switch discriminator { + case "INLINE": + return t.AsClientSetupStepConfig() + case "TABS": + return t.AsTabSetupStepConfig() + default: + return nil, errors.New("unknown discriminator value: " + discriminator) + } +} + +func (t ClientSetupSection) MarshalJSON() ([]byte, error) { + b, err := t.union.MarshalJSON() + if err != nil { + return nil, err + } + object := make(map[string]json.RawMessage) + if t.union != nil { + err = json.Unmarshal(b, &object) + if err != nil { + return nil, err + } + } + + if t.Header != nil { + object["header"], err = json.Marshal(t.Header) + if err != nil { + return nil, fmt.Errorf("error marshaling 'header': %w", err) + } + } + + if t.SecHeader != nil { + object["secHeader"], err = json.Marshal(t.SecHeader) + if err != nil { + return nil, fmt.Errorf("error marshaling 'secHeader': %w", err) + } + } + + object["type"], err = json.Marshal(t.Type) + if err != nil { + return nil, fmt.Errorf("error marshaling 'type': %w", err) + } + + b, err = json.Marshal(object) + return b, err +} + +func (t *ClientSetupSection) UnmarshalJSON(b []byte) error { + err := t.union.UnmarshalJSON(b) + if err != nil { + return err + } + object := make(map[string]json.RawMessage) + err = json.Unmarshal(b, &object) + if err != nil { + return err + } + + if raw, found := object["header"]; found { + err = json.Unmarshal(raw, &t.Header) + if err != nil { + return fmt.Errorf("error reading 'header': %w", err) + } + } + + if raw, found := object["secHeader"]; found { + err = json.Unmarshal(raw, &t.SecHeader) + if err != nil { + return fmt.Errorf("error reading 'secHeader': %w", err) + } + } + + if raw, found := object["type"]; found { + err = json.Unmarshal(raw, &t.Type) + if err != nil { + return fmt.Errorf("error reading 'type': %w", err) + } + } + + return err +} + // AsVirtualConfig returns the union data inside the RegistryConfig as a VirtualConfig func (t RegistryConfig) AsVirtualConfig() (VirtualConfig, error) { var body VirtualConfig diff --git a/registry/app/pkg/maven/local.go b/registry/app/pkg/maven/local.go index 410dfd0af..6e6d0cd5c 100644 --- a/registry/app/pkg/maven/local.go +++ b/registry/app/pkg/maven/local.go @@ -157,7 +157,9 @@ func (r *LocalRegistry) PutArtifact(ctx context.Context, info pkg.MavenArtifactI func processError(err error) ( responseHeaders *commons.ResponseHeaders, body *storage.FileReader, readCloser io.ReadCloser, errs []error) { - if strings.Contains(err.Error(), sql.ErrNoRows.Error()) || strings.Contains(err.Error(), "resource not found") { + if strings.Contains(err.Error(), sql.ErrNoRows.Error()) || + strings.Contains(err.Error(), "resource not found") || + strings.Contains(err.Error(), "http status code: 404") { return responseHeaders, nil, nil, []error{commons.NotFoundError(err.Error(), err)} } return responseHeaders, nil, nil, []error{errcode.ErrCodeUnknown.WithDetail(err)} diff --git a/registry/app/pkg/maven/remote.go b/registry/app/pkg/maven/remote.go index 067ad59a4..2854d2b72 100644 --- a/registry/app/pkg/maven/remote.go +++ b/registry/app/pkg/maven/remote.go @@ -80,14 +80,13 @@ func (r *RemoteRegistry) FetchArtifact(ctx context.Context, info pkg.MavenArtifa upstreamProxy, err := r.DBStore.UpstreamProxyDao.GetByRegistryIdentifier(ctx, info.ParentID, info.RegIdentifier) if err != nil { - errs = append(errs, err) + return processError(err) } // This is start of proxy Code. responseHeaders, readCloser, err = r.proxyController.ProxyFile(ctx, info, *upstreamProxy, serveFile) if err != nil { - errs = append(errs, err) - return responseHeaders, nil, readCloser, errs + return processError(err) } return responseHeaders, nil, readCloser, errs }