@@ -77,34 +77,23 @@ func formatPrefix(prefix string) string {
7777}
7878```
7979
80- ### Use in Template Files
80+ ### Use in Template Generation
8181
8282``` go
8383package templates
8484
8585import (
8686 " fmt"
87- " path/filepath"
88- " sigs.k8s.io/kubebuilder/v4/pkg/machinery"
8987 " github.com/yourorg/yourplugin/pkg/markers"
9088)
9189
92- type RustMainFile struct {
93- machinery.TemplateMixin
94- machinery.ProjectNameMixin
95- }
96-
97- func (f *RustMainFile ) SetTemplateDefaults () error {
98- if f.Path == " " {
99- f.Path = filepath.Join (" src" , " main.rs" )
100- }
101-
102- marker , err := markers.NewRustMarker (f.Path , " imports" )
90+ func GenerateRustFile (projectName string ) (string , error ) {
91+ marker , err := markers.NewRustMarker (" src/main.rs" , " imports" )
10392 if err != nil {
104- return err
93+ return " " , err
10594 }
10695
107- f. TemplateBody = fmt.Sprintf (` // Generated by Rust Plugin
96+ content : = fmt.Sprintf (` // Generated by Rust Plugin
10897%s
10998
11099use std::error::Error;
@@ -113,9 +102,19 @@ fn main() -> Result<(), Box<dyn Error>> {
113102 println!("Hello from %s!");
114103 Ok(())
115104}
116- ` , marker.String (), f. ProjectName )
105+ ` , marker.String (), projectName )
117106
118- return nil
107+ return content, nil
108+ }
109+
110+ func GenerateCargoToml (projectName string ) string {
111+ return fmt.Sprintf (` [package]
112+ name = "%s"
113+ version = "0.1.0"
114+ edition = "2021"
115+
116+ [dependencies]
117+ ` , projectName)
119118}
120119```
121120
@@ -125,27 +124,86 @@ fn main() -> Result<(), Box<dyn Error>> {
125124package main
126125
127126import (
128- " sigs.k8s.io/kubebuilder/v4/pkg/plugin"
127+ " bufio"
128+ " encoding/json"
129+ " fmt"
130+ " io"
131+ " os"
132+ " path/filepath"
133+
129134 " sigs.k8s.io/kubebuilder/v4/pkg/plugin/external"
130- " github.com/yourorg/yourplugin/pkg/templates "
135+ " github.com/yourorg/yourplugin/pkg/markers "
131136)
132137
133138func main () {
134- p := &external.Plugin {
135- Name: " rust.kubebuilder.io" ,
136- Version: plugin.Version {Number: 1 , Stage: plugin.Alpha },
137-
138- Init: func (req external.PluginRequest ) external.PluginResponse {
139- mainFile := &templates.RustMainFile {}
140-
141- return external.PluginResponse {
142- Universe: req.Universe ,
143- Files: []machinery.File {mainFile},
144- }
145- },
139+ // External plugins communicate via JSON over STDIN/STDOUT
140+ reader := bufio.NewReader (os.Stdin )
141+ input , err := io.ReadAll (reader)
142+ if err != nil {
143+ returnError (fmt.Errorf (" error reading STDIN: % w" , err))
144+ return
146145 }
147146
148- external.Run (p)
147+ pluginRequest := &external.PluginRequest {}
148+ err = json.Unmarshal (input, pluginRequest)
149+ if err != nil {
150+ returnError (fmt.Errorf (" error unmarshaling request: % w" , err))
151+ return
152+ }
153+
154+ var response external.PluginResponse
155+
156+ switch pluginRequest.Command {
157+ case " init" :
158+ response = handleInit (pluginRequest)
159+ case " flags" :
160+ response = handleFlags (pluginRequest)
161+ case " metadata" :
162+ response = handleMetadata (pluginRequest)
163+ default :
164+ response = external.PluginResponse {
165+ Command: pluginRequest.Command ,
166+ Error: true ,
167+ ErrorMsgs: []string {fmt.Sprintf (" unknown command: %s " , pluginRequest.Command )},
168+ }
169+ }
170+
171+ output , _ := json.Marshal (response)
172+ fmt.Printf (" %s " , output)
173+ }
174+
175+ func handleInit (req *external .PluginRequest ) external .PluginResponse {
176+ // Create Rust file with custom markers
177+ marker , _ := markers.NewRustMarker (" src/main.rs" , " imports" )
178+
179+ fileContent := fmt.Sprintf (` // Generated by Rust Plugin
180+ %s
181+
182+ use std::error::Error;
183+
184+ fn main() -> Result<(), Box<dyn Error>> {
185+ println!("Hello from Rust!");
186+ Ok(())
187+ }
188+ ` , marker.String ())
189+
190+ // External plugins use "universe" to represent file changes
191+ universe := make (map [string ]string )
192+ universe[" src/main.rs" ] = fileContent
193+
194+ return external.PluginResponse {
195+ Command: " init" ,
196+ Universe: universe,
197+ }
198+ }
199+
200+ func returnError (err error ) {
201+ response := external.PluginResponse {
202+ Error: true ,
203+ ErrorMsgs: []string {err.Error ()},
204+ }
205+ output , _ := json.Marshal (response)
206+ fmt.Printf (" %s " , output)
149207}
150208```
151209
@@ -157,14 +215,4 @@ To support other file extensions, modify the marker implementation by changing:
157215- The file extension check (e.g., ` .java ` , ` .py ` , ` .tpl ` )
158216- The marker prefix (e.g., ` +java:scaffold: ` , ` +python:scaffold: ` )
159217
160- ## Key Considerations
161-
162- 1 . ** Unique Prefixes** : Choose a unique prefix for your plugin to avoid conflicts (e.g., ` +rust:scaffold: ` , ` +java:scaffold: ` )
163-
164- 2 . ** Comment Syntax** : Different languages have different comment syntax. Ensure you map the correct comment style for each file extension
165-
166- 3 . ** Error Handling** : Validate file extensions and return clear error messages for unsupported files
167-
168- 4 . ** Testing** : Test your marker implementation with various scenarios to ensure reliability
169-
170218For more information on creating external plugins, see [ External Plugins] ( external-plugins.md ) .
0 commit comments