/ *
Copyright © 2020 - 2021 The k3d Author ( s )
Permission is hereby granted , free of charge , to any person obtaining a copy
of this software and associated documentation files ( the "Software" ) , to deal
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE .
* /
package registry
import (
"fmt"
l "github.com/rancher/k3d/v4/pkg/logger"
"github.com/rancher/k3d/v4/pkg/runtimes"
k3d "github.com/rancher/k3d/v4/pkg/types"
"github.com/rancher/k3d/v4/pkg/client"
cliutil "github.com/rancher/k3d/v4/cmd/util"
"github.com/spf13/cobra"
)
type regCreatePreProcessedFlags struct {
Port string
Clusters [ ] string
}
type regCreateFlags struct {
Image string
NoHelp bool
}
var helptext string = ` # You can now use the registry like this ( example ) :
# 1. create a new cluster that uses this registry
k3d cluster create -- registry - use % s
# 2. tag an existing local image to be pushed to the registry
docker tag nginx : latest % s / mynginx : v0 .1
# 3. push that image to the registry
docker push % s / mynginx : v0 .1
# 4. run a pod that uses this image
kubectl run mynginx -- image % s / mynginx : v0 .1
`
// NewCmdRegistryCreate returns a new cobra command
func NewCmdRegistryCreate ( ) * cobra . Command {
flags := & regCreateFlags { }
ppFlags := & regCreatePreProcessedFlags { }
// create new command
cmd := & cobra . Command {
Use : "create NAME" ,
Short : "Create a new registry" ,
Long : ` Create a new registry. ` ,
Args : cobra . MaximumNArgs ( 1 ) , // maximum one name accepted
Run : func ( cmd * cobra . Command , args [ ] string ) {
reg , clusters := parseCreateRegistryCmd ( cmd , args , flags , ppFlags )
regNode , err := client . RegistryRun ( cmd . Context ( ) , runtimes . SelectedRuntime , reg )
if err != nil {
l . Log ( ) . Fatalln ( err )
}
if err := client . RegistryConnectClusters ( cmd . Context ( ) , runtimes . SelectedRuntime , regNode , clusters ) ; err != nil {
l . Log ( ) . Errorln ( err )
}
l . Log ( ) . Infof ( "Successfully created registry '%s'" , reg . Host )
regString := fmt . Sprintf ( "%s:%s" , reg . Host , reg . ExposureOpts . Binding . HostPort )
if ! flags . NoHelp {
fmt . Println ( fmt . Sprintf ( helptext , regString , regString , regString , regString ) )
}
} ,
}
// add flags
// TODO: connecting to clusters requires non-existing config reload functionality in containerd
cmd . Flags ( ) . StringArrayVarP ( & ppFlags . Clusters , "cluster" , "c" , nil , "[NotReady] Select the cluster(s) that the registry shall connect to." )
if err := cmd . RegisterFlagCompletionFunc ( "cluster" , cliutil . ValidArgsAvailableClusters ) ; err != nil {
l . Log ( ) . Fatalln ( "Failed to register flag completion for '--cluster'" , err )
}
if err := cmd . Flags ( ) . MarkHidden ( "cluster" ) ; err != nil {
l . Log ( ) . Fatalln ( "Failed to hide --cluster flag on registry create command" )
}
cmd . Flags ( ) . StringVarP ( & flags . Image , "image" , "i" , fmt . Sprintf ( "%s:%s" , k3d . DefaultRegistryImageRepo , k3d . DefaultRegistryImageTag ) , "Specify image used for the registry" )
cmd . Flags ( ) . StringVarP ( & ppFlags . Port , "port" , "p" , "random" , "Select which port the registry should be listening on on your machine (localhost) (Format: `[HOST:]HOSTPORT`)\n - Example: `k3d registry create --port 0.0.0.0:5111`" )
cmd . Flags ( ) . BoolVar ( & flags . NoHelp , "no-help" , false , "Disable the help text (How-To use the registry)" )
// done
return cmd
}
// parseCreateRegistryCmd parses the command input into variables required to create a registry
func parseCreateRegistryCmd ( cmd * cobra . Command , args [ ] string , flags * regCreateFlags , ppFlags * regCreatePreProcessedFlags ) ( * k3d . Registry , [ ] * k3d . Cluster ) {
// --cluster
clusters := [ ] * k3d . Cluster { }
for _ , name := range ppFlags . Clusters {
clusters = append ( clusters ,
& k3d . Cluster {
Name : name ,
} ,
)
}
// --port
exposePort , err := cliutil . ParsePortExposureSpec ( ppFlags . Port , k3d . DefaultRegistryPort )
if err != nil {
l . Log ( ) . Errorln ( "Failed to parse registry port" )
l . Log ( ) . Fatalln ( err )
}
// set the name for the registry node
registryName := ""
if len ( args ) > 0 {
registryName = fmt . Sprintf ( "%s-%s" , k3d . DefaultObjectNamePrefix , args [ 0 ] )
}
return & k3d . Registry { Host : registryName , Image : flags . Image , ExposureOpts : * exposePort } , clusters
}