← back to jspanos__n8n-resource-operator

Function bodies 53 total

All specs Real LLM only Function bodies
v1alpha1.N8nInstance.GetSecretKey method · go · L161-L166 (6 LOC)
api/v1alpha1/n8ninstance_types.go
func (i *N8nInstance) GetSecretKey() string {
	if i.Spec.Credentials.SecretKey != "" {
		return i.Spec.Credentials.SecretKey
	}
	return "api-key"
}
v1alpha1.CredentialsRef.DeepCopy method · go · L34-L41 (8 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *CredentialsRef) DeepCopy() *CredentialsRef {
	if in == nil {
		return nil
	}
	out := new(CredentialsRef)
	in.DeepCopyInto(out)
	return out
}
v1alpha1.N8nInstance.DeepCopyInto method · go · L44-L50 (7 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nInstance) DeepCopyInto(out *N8nInstance) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
	in.Spec.DeepCopyInto(&out.Spec)
	in.Status.DeepCopyInto(&out.Status)
}
v1alpha1.N8nInstance.DeepCopy method · go · L53-L60 (8 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nInstance) DeepCopy() *N8nInstance {
	if in == nil {
		return nil
	}
	out := new(N8nInstance)
	in.DeepCopyInto(out)
	return out
}
v1alpha1.N8nInstance.DeepCopyObject method · go · L63-L68 (6 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nInstance) DeepCopyObject() runtime.Object {
	if c := in.DeepCopy(); c != nil {
		return c
	}
	return nil
}
v1alpha1.N8nInstanceList.DeepCopyInto method · go · L71-L82 (12 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nInstanceList) DeepCopyInto(out *N8nInstanceList) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ListMeta.DeepCopyInto(&out.ListMeta)
	if in.Items != nil {
		in, out := &in.Items, &out.Items
		*out = make([]N8nInstance, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
}
v1alpha1.N8nInstanceList.DeepCopy method · go · L85-L92 (8 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nInstanceList) DeepCopy() *N8nInstanceList {
	if in == nil {
		return nil
	}
	out := new(N8nInstanceList)
	in.DeepCopyInto(out)
	return out
}
Open data scored by Repobility · https://repobility.com
v1alpha1.N8nInstanceList.DeepCopyObject method · go · L95-L100 (6 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nInstanceList) DeepCopyObject() runtime.Object {
	if c := in.DeepCopy(); c != nil {
		return c
	}
	return nil
}
v1alpha1.N8nInstanceSpec.DeepCopyInto method · go · L103-L111 (9 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nInstanceSpec) DeepCopyInto(out *N8nInstanceSpec) {
	*out = *in
	if in.ServiceRef != nil {
		in, out := &in.ServiceRef, &out.ServiceRef
		*out = new(ServiceRef)
		**out = **in
	}
	out.Credentials = in.Credentials
}
v1alpha1.N8nInstanceSpec.DeepCopy method · go · L114-L121 (8 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nInstanceSpec) DeepCopy() *N8nInstanceSpec {
	if in == nil {
		return nil
	}
	out := new(N8nInstanceSpec)
	in.DeepCopyInto(out)
	return out
}
v1alpha1.N8nInstanceStatus.DeepCopyInto method · go · L124-L137 (14 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nInstanceStatus) DeepCopyInto(out *N8nInstanceStatus) {
	*out = *in
	if in.LastHealthCheck != nil {
		in, out := &in.LastHealthCheck, &out.LastHealthCheck
		*out = (*in).DeepCopy()
	}
	if in.Conditions != nil {
		in, out := &in.Conditions, &out.Conditions
		*out = make([]v1.Condition, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
}
v1alpha1.N8nInstanceStatus.DeepCopy method · go · L140-L147 (8 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nInstanceStatus) DeepCopy() *N8nInstanceStatus {
	if in == nil {
		return nil
	}
	out := new(N8nInstanceStatus)
	in.DeepCopyInto(out)
	return out
}
v1alpha1.N8nWorkflow.DeepCopyInto method · go · L150-L156 (7 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nWorkflow) DeepCopyInto(out *N8nWorkflow) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
	in.Spec.DeepCopyInto(&out.Spec)
	in.Status.DeepCopyInto(&out.Status)
}
v1alpha1.N8nWorkflow.DeepCopy method · go · L159-L166 (8 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nWorkflow) DeepCopy() *N8nWorkflow {
	if in == nil {
		return nil
	}
	out := new(N8nWorkflow)
	in.DeepCopyInto(out)
	return out
}
v1alpha1.N8nWorkflow.DeepCopyObject method · go · L169-L174 (6 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nWorkflow) DeepCopyObject() runtime.Object {
	if c := in.DeepCopy(); c != nil {
		return c
	}
	return nil
}
Repobility — the code-quality scanner for AI-generated software · https://repobility.com
v1alpha1.N8nWorkflowList.DeepCopyInto method · go · L177-L188 (12 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nWorkflowList) DeepCopyInto(out *N8nWorkflowList) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ListMeta.DeepCopyInto(&out.ListMeta)
	if in.Items != nil {
		in, out := &in.Items, &out.Items
		*out = make([]N8nWorkflow, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
}
v1alpha1.N8nWorkflowList.DeepCopy method · go · L191-L198 (8 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nWorkflowList) DeepCopy() *N8nWorkflowList {
	if in == nil {
		return nil
	}
	out := new(N8nWorkflowList)
	in.DeepCopyInto(out)
	return out
}
v1alpha1.N8nWorkflowList.DeepCopyObject method · go · L201-L206 (6 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nWorkflowList) DeepCopyObject() runtime.Object {
	if c := in.DeepCopy(); c != nil {
		return c
	}
	return nil
}
v1alpha1.N8nWorkflowSpec.DeepCopy method · go · L215-L222 (8 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nWorkflowSpec) DeepCopy() *N8nWorkflowSpec {
	if in == nil {
		return nil
	}
	out := new(N8nWorkflowSpec)
	in.DeepCopyInto(out)
	return out
}
v1alpha1.N8nWorkflowStatus.DeepCopyInto method · go · L225-L238 (14 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nWorkflowStatus) DeepCopyInto(out *N8nWorkflowStatus) {
	*out = *in
	if in.LastSyncTime != nil {
		in, out := &in.LastSyncTime, &out.LastSyncTime
		*out = (*in).DeepCopy()
	}
	if in.Conditions != nil {
		in, out := &in.Conditions, &out.Conditions
		*out = make([]v1.Condition, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
}
v1alpha1.N8nWorkflowStatus.DeepCopy method · go · L241-L248 (8 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *N8nWorkflowStatus) DeepCopy() *N8nWorkflowStatus {
	if in == nil {
		return nil
	}
	out := new(N8nWorkflowStatus)
	in.DeepCopyInto(out)
	return out
}
v1alpha1.ServiceRef.DeepCopy method · go · L256-L263 (8 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *ServiceRef) DeepCopy() *ServiceRef {
	if in == nil {
		return nil
	}
	out := new(ServiceRef)
	in.DeepCopyInto(out)
	return out
}
v1alpha1.WorkflowSpec.DeepCopyInto method · go · L266-L295 (30 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *WorkflowSpec) DeepCopyInto(out *WorkflowSpec) {
	*out = *in
	if in.Nodes != nil {
		in, out := &in.Nodes, &out.Nodes
		*out = make([]runtime.RawExtension, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	if in.Connections != nil {
		in, out := &in.Connections, &out.Connections
		*out = new(runtime.RawExtension)
		(*in).DeepCopyInto(*out)
	}
	if in.Settings != nil {
		in, out := &in.Settings, &out.Settings
		*out = new(runtime.RawExtension)
		(*in).DeepCopyInto(*out)
	}
	if in.StaticData != nil {
		in, out := &in.StaticData, &out.StaticData
		*out = new(runtime.RawExtension)
		(*in).DeepCopyInto(*out)
	}
	if in.PinData != nil {
		in, out := &in.PinData, &out.PinData
		*out = new(runtime.RawExtension)
		(*in).DeepCopyInto(*out)
	}
}
Repobility · severity-and-effort ranking · https://repobility.com
v1alpha1.WorkflowSpec.DeepCopy method · go · L298-L305 (8 LOC)
api/v1alpha1/zz_generated.deepcopy.go
func (in *WorkflowSpec) DeepCopy() *WorkflowSpec {
	if in == nil {
		return nil
	}
	out := new(WorkflowSpec)
	in.DeepCopyInto(out)
	return out
}
main.init function · go · L48-L53 (6 LOC)
cmd/main.go
func init() {
	utilruntime.Must(clientgoscheme.AddToScheme(scheme))

	utilruntime.Must(n8nv1alpha1.AddToScheme(scheme))
	// +kubebuilder:scaffold:scheme
}
main.main function · go · L56-L229 (174 LOC)
cmd/main.go
func main() {
	var metricsAddr string
	var metricsCertPath, metricsCertName, metricsCertKey string
	var webhookCertPath, webhookCertName, webhookCertKey string
	var enableLeaderElection bool
	var probeAddr string
	var secureMetrics bool
	var enableHTTP2 bool
	var operatorNamespace string
	var tlsOpts []func(*tls.Config)
	flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
		"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
	flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
	flag.BoolVar(&enableLeaderElection, "leader-elect", false,
		"Enable leader election for controller manager. "+
			"Enabling this will ensure there is only one active controller manager.")
	flag.StringVar(&operatorNamespace, "operator-namespace", "",
		"The namespace where N8nInstance resources and secrets are stored. "+
			"Defaults to POD_NAMESPACE environment variab
controller.N8nInstanceReconciler.Reconcile method · go · L61-L136 (76 LOC)
internal/controller/n8ninstance_controller.go
func (r *N8nInstanceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	log := logf.FromContext(ctx)
	log.V(1).Info("Reconciling N8nInstance")

	// Fetch the N8nInstance
	instance := &n8nv1alpha1.N8nInstance{}
	if err := r.Get(ctx, req.NamespacedName, instance); err != nil {
		if errors.IsNotFound(err) {
			log.Info("N8nInstance resource not found, ignoring")
			return ctrl.Result{}, nil
		}
		log.Error(err, "Failed to get N8nInstance")
		return ctrl.Result{}, err
	}

	// Validate configuration
	if err := r.validateInstance(instance); err != nil {
		log.Error(err, "Invalid N8nInstance configuration")
		r.setCondition(instance, n8nv1alpha1.InstanceConditionTypeReady, metav1.ConditionFalse,
			n8nv1alpha1.InstanceReasonInvalidConfig, err.Error())
		instance.Status.Ready = false
		if statusErr := r.Status().Update(ctx, instance); statusErr != nil {
			log.Error(statusErr, "Failed to update status")
		}
		return ctrl.Result{RequeueAfter: instanceErrorRequeu
controller.N8nInstanceReconciler.validateInstance method · go · L139-L168 (30 LOC)
internal/controller/n8ninstance_controller.go
func (r *N8nInstanceReconciler) validateInstance(instance *n8nv1alpha1.N8nInstance) error {
	// Either URL or ServiceRef must be specified
	hasURL := instance.Spec.URL != ""
	hasServiceRef := instance.Spec.ServiceRef != nil

	if !hasURL && !hasServiceRef {
		return fmt.Errorf("either url or serviceRef must be specified")
	}

	if hasURL && hasServiceRef {
		return fmt.Errorf("only one of url or serviceRef can be specified, not both")
	}

	// Validate ServiceRef if specified
	if hasServiceRef {
		if instance.Spec.ServiceRef.Name == "" {
			return fmt.Errorf("serviceRef.name is required")
		}
		if instance.Spec.ServiceRef.Namespace == "" {
			return fmt.Errorf("serviceRef.namespace is required")
		}
	}

	// Credentials must be specified
	if instance.Spec.Credentials.SecretName == "" {
		return fmt.Errorf("credentials.secretName is required")
	}

	return nil
}
controller.N8nInstanceReconciler.getAPIKey method · go · L171-L189 (19 LOC)
internal/controller/n8ninstance_controller.go
func (r *N8nInstanceReconciler) getAPIKey(ctx context.Context, instance *n8nv1alpha1.N8nInstance) (string, error) {
	secret := &corev1.Secret{}
	secretKey := types.NamespacedName{
		Name:      instance.Spec.Credentials.SecretName,
		Namespace: instance.Namespace, // Secret must be in same namespace as N8nInstance
	}

	if err := r.Get(ctx, secretKey, secret); err != nil {
		return "", fmt.Errorf("failed to get secret %s/%s: %w", secretKey.Namespace, secretKey.Name, err)
	}

	key := instance.GetSecretKey()
	apiKeyBytes, ok := secret.Data[key]
	if !ok {
		return "", fmt.Errorf("secret %s/%s does not contain key %s", secretKey.Namespace, secretKey.Name, key)
	}

	return string(apiKeyBytes), nil
}
controller.N8nInstanceReconciler.setCondition method · go · L192-L202 (11 LOC)
internal/controller/n8ninstance_controller.go
func (r *N8nInstanceReconciler) setCondition(instance *n8nv1alpha1.N8nInstance, conditionType string, status metav1.ConditionStatus, reason, message string) {
	condition := metav1.Condition{
		Type:               conditionType,
		Status:             status,
		ObservedGeneration: instance.Generation,
		LastTransitionTime: metav1.Now(),
		Reason:             reason,
		Message:            message,
	}
	meta.SetStatusCondition(&instance.Status.Conditions, condition)
}
controller.N8nInstanceReconciler.SetupWithManager method · go · L205-L210 (6 LOC)
internal/controller/n8ninstance_controller.go
func (r *N8nInstanceReconciler) SetupWithManager(mgr ctrl.Manager) error {
	return ctrl.NewControllerManagedBy(mgr).
		For(&n8nv1alpha1.N8nInstance{}).
		Named("n8ninstance").
		Complete(r)
}
Repobility (the analyzer behind this table) · https://repobility.com
controller.N8nWorkflowReconciler.Reconcile method · go · L77-L121 (45 LOC)
internal/controller/n8nworkflow_controller.go
func (r *N8nWorkflowReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	log := logf.FromContext(ctx)
	log.V(1).Info("Reconciling N8nWorkflow")

	// Fetch the N8nWorkflow instance
	workflow := &n8nv1alpha1.N8nWorkflow{}
	if err := r.Get(ctx, req.NamespacedName, workflow); err != nil {
		if errors.IsNotFound(err) {
			log.Info("N8nWorkflow resource not found, ignoring")
			return ctrl.Result{}, nil
		}
		log.Error(err, "Failed to get N8nWorkflow")
		return ctrl.Result{}, err
	}

	// Get n8n API client
	n8nClient, err := r.getN8nClient(ctx, workflow)
	if err != nil {
		log.Error(err, "Failed to create n8n client")
		r.setCondition(workflow, n8nv1alpha1.ConditionTypeReady, metav1.ConditionFalse,
			n8nv1alpha1.ReasonAPIError, fmt.Sprintf("Failed to create n8n client: %v", err))
		if statusErr := r.Status().Update(ctx, workflow); statusErr != nil {
			log.Error(statusErr, "Failed to update status")
		}
		return ctrl.Result{RequeueAfter: errorRequeueInterval}
controller.N8nWorkflowReconciler.getN8nClient method · go · L124-L171 (48 LOC)
internal/controller/n8nworkflow_controller.go
func (r *N8nWorkflowReconciler) getN8nClient(ctx context.Context, workflow *n8nv1alpha1.N8nWorkflow) (*n8n.Client, error) {
	// instanceRef is required
	if workflow.Spec.InstanceRef == "" {
		return nil, fmt.Errorf("instanceRef is required")
	}

	// Look up the N8nInstance in the operator namespace
	instance := &n8nv1alpha1.N8nInstance{}
	instanceKey := types.NamespacedName{
		Name:      workflow.Spec.InstanceRef,
		Namespace: r.OperatorNamespace,
	}
	if err := r.Get(ctx, instanceKey, instance); err != nil {
		if errors.IsNotFound(err) {
			return nil, fmt.Errorf("N8nInstance %q not found in namespace %q", workflow.Spec.InstanceRef, r.OperatorNamespace)
		}
		return nil, fmt.Errorf("failed to get N8nInstance %q: %w", workflow.Spec.InstanceRef, err)
	}

	// Check if instance is ready
	if !instance.Status.Ready {
		return nil, fmt.Errorf("N8nInstance %q is not ready", workflow.Spec.InstanceRef)
	}

	// Get the resolved URL
	baseURL := instance.GetResolvedURL()
	if baseURL == "" {
		retur
controller.N8nWorkflowReconciler.handleDeletion method · go · L381-L418 (38 LOC)
internal/controller/n8nworkflow_controller.go
func (r *N8nWorkflowReconciler) handleDeletion(ctx context.Context, workflow *n8nv1alpha1.N8nWorkflow, n8nClient *n8n.Client) (ctrl.Result, error) {
	log := logf.FromContext(ctx)

	if !controllerutil.ContainsFinalizer(workflow, finalizerName) {
		return ctrl.Result{}, nil
	}

	log.Info("Handling deletion of N8nWorkflow")

	// Delete the workflow from n8n if it exists
	if workflow.Status.WorkflowID != "" {
		log.Info("Deleting workflow from n8n", "id", workflow.Status.WorkflowID)
		err := n8nClient.DeleteWorkflow(ctx, workflow.Status.WorkflowID)
		if err != nil {
			// Check if the workflow was already deleted (not found is acceptable)
			if strings.Contains(err.Error(), "Not Found") || strings.Contains(err.Error(), "not found") {
				log.Info("Workflow already deleted from n8n", "id", workflow.Status.WorkflowID)
			} else {
				// Log as warning but continue with finalizer removal
				log.Info("Failed to delete workflow from n8n (continuing with cleanup)", "error", err)
				r.Recorder.
controller.N8nWorkflowReconciler.convertToN8nWorkflow method · go · L421-L476 (56 LOC)
internal/controller/n8nworkflow_controller.go
func (r *N8nWorkflowReconciler) convertToN8nWorkflow(workflow *n8nv1alpha1.N8nWorkflow) (*n8n.Workflow, error) {
	n8nWorkflow := &n8n.Workflow{
		Name:   workflow.Spec.Workflow.Name,
		Active: workflow.Spec.Active,
	}

	// Convert nodes
	if len(workflow.Spec.Workflow.Nodes) > 0 {
		n8nWorkflow.Nodes = make([]map[string]any, len(workflow.Spec.Workflow.Nodes))
		for i, node := range workflow.Spec.Workflow.Nodes {
			var nodeMap map[string]any
			if err := json.Unmarshal(node.Raw, &nodeMap); err != nil {
				return nil, fmt.Errorf("failed to unmarshal node %d: %w", i, err)
			}
			n8nWorkflow.Nodes[i] = nodeMap
		}
	}

	// Convert connections
	if workflow.Spec.Workflow.Connections != nil && workflow.Spec.Workflow.Connections.Raw != nil {
		var connections map[string]any
		if err := json.Unmarshal(workflow.Spec.Workflow.Connections.Raw, &connections); err != nil {
			return nil, fmt.Errorf("failed to unmarshal connections: %w", err)
		}
		n8nWorkflow.Connections = connections
	}

	// Conve
controller.N8nWorkflowReconciler.calculateSpecHash method · go · L480-L498 (19 LOC)
internal/controller/n8nworkflow_controller.go
func (r *N8nWorkflowReconciler) calculateSpecHash(workflow *n8nv1alpha1.N8nWorkflow) string {
	// Create a struct with just the fields we care about for comparison
	specData := struct {
		Active   bool                             `json:"active"`
		Workflow n8nv1alpha1.WorkflowSpec         `json:"workflow"`
	}{
		Active:   workflow.Spec.Active,
		Workflow: workflow.Spec.Workflow,
	}

	data, err := json.Marshal(specData)
	if err != nil {
		// If marshaling fails, return empty string to force update
		return ""
	}

	hash := sha256.Sum256(data)
	return hex.EncodeToString(hash[:])
}
controller.N8nWorkflowReconciler.extractWebhookURL method · go · L501-L524 (24 LOC)
internal/controller/n8nworkflow_controller.go
func (r *N8nWorkflowReconciler) extractWebhookURL(workflow *n8n.Workflow) string {
	if workflow == nil || len(workflow.Nodes) == 0 {
		return ""
	}

	for _, node := range workflow.Nodes {
		nodeType, ok := node["type"].(string)
		if !ok {
			continue
		}
		if nodeType == "n8n-nodes-base.webhook" {
			params, ok := node["parameters"].(map[string]any)
			if !ok {
				continue
			}
			path, ok := params["path"].(string)
			if ok {
				return "/webhook/" + path
			}
		}
	}

	return ""
}
controller.N8nWorkflowReconciler.setCondition method · go · L527-L537 (11 LOC)
internal/controller/n8nworkflow_controller.go
func (r *N8nWorkflowReconciler) setCondition(workflow *n8nv1alpha1.N8nWorkflow, conditionType string, status metav1.ConditionStatus, reason, message string) {
	condition := metav1.Condition{
		Type:               conditionType,
		Status:             status,
		ObservedGeneration: workflow.Generation,
		LastTransitionTime: metav1.Now(),
		Reason:             reason,
		Message:            message,
	}
	meta.SetStatusCondition(&workflow.Status.Conditions, condition)
}
controller.N8nWorkflowReconciler.SetupWithManager method · go · L540-L545 (6 LOC)
internal/controller/n8nworkflow_controller.go
func (r *N8nWorkflowReconciler) SetupWithManager(mgr ctrl.Manager) error {
	return ctrl.NewControllerManagedBy(mgr).
		For(&n8nv1alpha1.N8nWorkflow{}).
		Named("n8nworkflow").
		Complete(r)
}
Open data scored by Repobility · https://repobility.com
n8n.NewClient function · go · L37-L45 (9 LOC)
internal/n8n/client.go
func NewClient(baseURL, apiKey string) *Client {
	return &Client{
		baseURL: baseURL,
		apiKey:  apiKey,
		httpClient: &http.Client{
			Timeout: 30 * time.Second,
		},
	}
}
n8n.ErrorResponse.Error method · go · L85-L90 (6 LOC)
internal/n8n/client.go
func (e *ErrorResponse) Error() string {
	if e.Code != "" {
		return fmt.Sprintf("%s: %s", e.Code, e.Message)
	}
	return e.Message
}
n8n.Client.doRequest method · go · L93-L132 (40 LOC)
internal/n8n/client.go
func (c *Client) doRequest(ctx context.Context, method, path string, body any) ([]byte, error) {
	var reqBody io.Reader
	if body != nil {
		jsonBody, err := json.Marshal(body)
		if err != nil {
			return nil, fmt.Errorf("failed to marshal request body: %w", err)
		}
		reqBody = bytes.NewReader(jsonBody)
	}

	req, err := http.NewRequestWithContext(ctx, method, c.baseURL+path, reqBody)
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %w", err)
	}

	req.Header.Set("X-N8N-API-KEY", c.apiKey)
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Accept", "application/json")

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("request failed: %w", err)
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response body: %w", err)
	}

	if resp.StatusCode >= 400 {
		var errResp ErrorResponse
		if err := json.Unmarshal(respBody, &errResp); err != nil {
			return 
n8n.Client.ListWorkflows method · go · L135-L164 (30 LOC)
internal/n8n/client.go
func (c *Client) ListWorkflows(ctx context.Context) ([]Workflow, error) {
	var allWorkflows []Workflow
	cursor := ""

	for {
		path := "/api/v1/workflows"
		if cursor != "" {
			path += "?cursor=" + cursor
		}

		respBody, err := c.doRequest(ctx, http.MethodGet, path, nil)
		if err != nil {
			return nil, fmt.Errorf("failed to list workflows: %w", err)
		}

		var listResp WorkflowListResponse
		if err := json.Unmarshal(respBody, &listResp); err != nil {
			return nil, fmt.Errorf("failed to unmarshal workflows: %w", err)
		}

		allWorkflows = append(allWorkflows, listResp.Data...)

		if listResp.NextCursor == "" {
			break
		}
		cursor = listResp.NextCursor
	}

	return allWorkflows, nil
}
n8n.Client.GetWorkflow method · go · L167-L179 (13 LOC)
internal/n8n/client.go
func (c *Client) GetWorkflow(ctx context.Context, id string) (*Workflow, error) {
	respBody, err := c.doRequest(ctx, http.MethodGet, "/api/v1/workflows/"+id, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get workflow %s: %w", id, err)
	}

	var workflow Workflow
	if err := json.Unmarshal(respBody, &workflow); err != nil {
		return nil, fmt.Errorf("failed to unmarshal workflow: %w", err)
	}

	return &workflow, nil
}
n8n.Client.GetWorkflowByName method · go · L182-L195 (14 LOC)
internal/n8n/client.go
func (c *Client) GetWorkflowByName(ctx context.Context, name string) (*Workflow, error) {
	workflows, err := c.ListWorkflows(ctx)
	if err != nil {
		return nil, err
	}

	for _, w := range workflows {
		if w.Name == name {
			return &w, nil
		}
	}

	return nil, nil // Not found
}
n8n.Client.CreateWorkflow method · go · L198-L220 (23 LOC)
internal/n8n/client.go
func (c *Client) CreateWorkflow(ctx context.Context, workflow *Workflow) (*Workflow, error) {
	// Use WorkflowCreateRequest to exclude the 'active' field (read-only in n8n API)
	createReq := &WorkflowCreateRequest{
		Name:        workflow.Name,
		Nodes:       workflow.Nodes,
		Connections: workflow.Connections,
		Settings:    workflow.Settings,
		StaticData:  workflow.StaticData,
		PinData:     workflow.PinData,
	}

	respBody, err := c.doRequest(ctx, http.MethodPost, "/api/v1/workflows", createReq)
	if err != nil {
		return nil, fmt.Errorf("failed to create workflow: %w", err)
	}

	var created Workflow
	if err := json.Unmarshal(respBody, &created); err != nil {
		return nil, fmt.Errorf("failed to unmarshal created workflow: %w", err)
	}

	return &created, nil
}
n8n.Client.UpdateWorkflow method · go · L223-L245 (23 LOC)
internal/n8n/client.go
func (c *Client) UpdateWorkflow(ctx context.Context, id string, workflow *Workflow) (*Workflow, error) {
	// Use WorkflowCreateRequest to exclude the 'active' field (read-only in n8n API)
	updateReq := &WorkflowCreateRequest{
		Name:        workflow.Name,
		Nodes:       workflow.Nodes,
		Connections: workflow.Connections,
		Settings:    workflow.Settings,
		StaticData:  workflow.StaticData,
		PinData:     workflow.PinData,
	}

	respBody, err := c.doRequest(ctx, http.MethodPut, "/api/v1/workflows/"+id, updateReq)
	if err != nil {
		return nil, fmt.Errorf("failed to update workflow %s: %w", id, err)
	}

	var updated Workflow
	if err := json.Unmarshal(respBody, &updated); err != nil {
		return nil, fmt.Errorf("failed to unmarshal updated workflow: %w", err)
	}

	return &updated, nil
}
Repobility — the code-quality scanner for AI-generated software · https://repobility.com
n8n.Client.DeleteWorkflow method · go · L248-L254 (7 LOC)
internal/n8n/client.go
func (c *Client) DeleteWorkflow(ctx context.Context, id string) error {
	_, err := c.doRequest(ctx, http.MethodDelete, "/api/v1/workflows/"+id, nil)
	if err != nil {
		return fmt.Errorf("failed to delete workflow %s: %w", id, err)
	}
	return nil
}
n8n.Client.ActivateWorkflow method · go · L257-L269 (13 LOC)
internal/n8n/client.go
func (c *Client) ActivateWorkflow(ctx context.Context, id string) (*Workflow, error) {
	respBody, err := c.doRequest(ctx, http.MethodPost, "/api/v1/workflows/"+id+"/activate", nil)
	if err != nil {
		return nil, fmt.Errorf("failed to activate workflow %s: %w", id, err)
	}

	var workflow Workflow
	if err := json.Unmarshal(respBody, &workflow); err != nil {
		return nil, fmt.Errorf("failed to unmarshal activated workflow: %w", err)
	}

	return &workflow, nil
}
n8n.Client.DeactivateWorkflow method · go · L272-L284 (13 LOC)
internal/n8n/client.go
func (c *Client) DeactivateWorkflow(ctx context.Context, id string) (*Workflow, error) {
	respBody, err := c.doRequest(ctx, http.MethodPost, "/api/v1/workflows/"+id+"/deactivate", nil)
	if err != nil {
		return nil, fmt.Errorf("failed to deactivate workflow %s: %w", id, err)
	}

	var workflow Workflow
	if err := json.Unmarshal(respBody, &workflow); err != nil {
		return nil, fmt.Errorf("failed to unmarshal deactivated workflow: %w", err)
	}

	return &workflow, nil
}
page 1 / 2next ›